fix quickretire without pfree

This commit is contained in:
CrazyRedMachine 2023-02-19 15:08:38 +01:00
parent fe6fd21802
commit 9bb1f8b363

View File

@ -33,27 +33,27 @@ DWORD patch_timeGetTime()
{ {
static DWORD last_real = 0; static DWORD last_real = 0;
static DWORD cumul_offset = 0; static DWORD cumul_offset = 0;
if (last_real == 0) if (last_real == 0)
{ {
last_real = real_timeGetTime()*g_multiplier; last_real = real_timeGetTime()*g_multiplier;
return last_real; return last_real;
} }
DWORD real = real_timeGetTime()*g_multiplier; DWORD real = real_timeGetTime()*g_multiplier;
DWORD elapsed = real-last_real; DWORD elapsed = real-last_real;
if (elapsed > 16) cumul_offset+= elapsed; if (elapsed > 16) cumul_offset+= elapsed;
last_real = real; last_real = real;
return real - cumul_offset; return real - cumul_offset;
} }
bool patch_get_time() bool patch_get_time()
{ {
HMODULE hinstLib = GetModuleHandleA("winmm.dll"); HMODULE hinstLib = GetModuleHandleA("winmm.dll");
MH_CreateHook((LPVOID)GetProcAddress(hinstLib, "timeGetTime"), (LPVOID)patch_timeGetTime, MH_CreateHook((LPVOID)GetProcAddress(hinstLib, "timeGetTime"), (LPVOID)patch_timeGetTime,
(void **)&real_timeGetTime); (void **)&real_timeGetTime);
return true; return true;
} }
@ -67,7 +67,7 @@ static void memdump(uint8_t* addr, uint8_t len)
if ((i+1)%16 == 0) if ((i+1)%16 == 0)
printf("\n"); printf("\n");
} }
} }
#endif #endif
@ -182,7 +182,7 @@ void quickexit_result_loop()
__asm("shr ebx, 16\n"); __asm("shr ebx, 16\n");
__asm("cmp bl, 8\n"); __asm("cmp bl, 8\n");
__asm("jne call_real_result\n"); __asm("jne call_real_result\n");
/* set value 5 in g_stage_addr and -4 in g_transition_addr */ /* set value 5 in g_stage_addr and -4 in g_transition_addr */
__asm("mov ebx, %0\n": :"b"(g_stage_addr)); __asm("mov ebx, %0\n": :"b"(g_stage_addr));
__asm("mov dword ptr[ebx], 5\n"); __asm("mov dword ptr[ebx], 5\n");
@ -216,28 +216,28 @@ void hidden_is_offset_commit_options()
/* check if hidden active */ /* check if hidden active */
__asm("xor eax, eax\n"); __asm("xor eax, eax\n");
__asm("mov eax, [esi]\n"); __asm("mov eax, [esi]\n");
__asm("shr eax, 0x18\n"); __asm("shr eax, 0x18\n");
__asm("cmp eax, 1\n"); __asm("cmp eax, 1\n");
__asm("jne call_real_commit\n"); __asm("jne call_real_commit\n");
/* disable hidden ingame */ /* disable hidden ingame */
__asm("and ecx, 0x00FFFFFF\n"); // -kaimei __asm("and ecx, 0x00FFFFFF\n"); // -kaimei
__asm("and edx, 0x00FFFFFF\n"); // unilab __asm("and edx, 0x00FFFFFF\n"); // unilab
/* flag timing for update */ /* flag timing for update */
g_timing_require_update = true; g_timing_require_update = true;
/* write into timing offset */ /* write into timing offset */
__asm("movsx eax, word ptr [esi+4]\n"); __asm("movsx eax, word ptr [esi+4]\n");
__asm("neg eax\n"); __asm("neg eax\n");
/* leave room for rewriting (done in patch_hidden_is_offset()) */ /* leave room for rewriting (done in patch_hidden_is_offset()) */
__asm("nop\n"); __asm("nop\n");
__asm("nop\n"); __asm("nop\n");
__asm("nop\n"); __asm("nop\n");
__asm("nop\n"); __asm("nop\n");
__asm("nop\n"); __asm("nop\n");
/* quit */ /* quit */
__asm("call_real_commit:\n"); __asm("call_real_commit:\n");
__asm("pop eax\n"); __asm("pop eax\n");
@ -245,6 +245,16 @@ void hidden_is_offset_commit_options()
} }
void (*real_stage_update)(); void (*real_stage_update)();
void hook_stage_update_pfree()
{
//__asm("push ebx\n"); //handled by :"=b"
__asm("mov ebx, dword ptr [esi+0x14]\n");
__asm("lea ebx, [ebx+0xC]\n");
__asm("mov %0, ebx\n":"=b"(g_transition_addr): :);
//__asm("pop ebx\n");
//__asm("ret\n");
}
void hook_stage_update() void hook_stage_update()
{ {
//__asm("push ebx\n"); //handled by :"=b" //__asm("push ebx\n"); //handled by :"=b"
@ -252,7 +262,8 @@ void hook_stage_update()
__asm("lea ebx, [ebx+0xC]\n"); __asm("lea ebx, [ebx+0xC]\n");
__asm("mov %0, ebx\n":"=b"(g_transition_addr): :); __asm("mov %0, ebx\n":"=b"(g_transition_addr): :);
//__asm("pop ebx\n"); //__asm("pop ebx\n");
//__asm("ret\n"); //__asm("ret\n");
real_stage_update();
} }
void (*real_check_music_idx)(); void (*real_check_music_idx)();
@ -351,7 +362,7 @@ bool patch_hex(const char *find, uint8_t find_size, int64_t shift, const char *r
printf("\n"); printf("\n");
} }
#endif #endif
uint64_t patch_addr = (int64_t)data + pattern_offset + shift; uint64_t patch_addr = (int64_t)data + pattern_offset + shift;
patch_memory(patch_addr, (char *)replace, replace_size); patch_memory(patch_addr, (char *)replace, replace_size);
@ -546,10 +557,10 @@ static bool patch_purelong()
printf("popnhax: Couldn't find score increment function\n"); printf("popnhax: Couldn't find score increment function\n");
return false; return false;
} }
uint64_t patch_addr = (int64_t)data + pattern_offset + 24; uint64_t patch_addr = (int64_t)data + pattern_offset + 24;
uint8_t *patch_str = (uint8_t *) patch_addr; uint8_t *patch_str = (uint8_t *) patch_addr;
DWORD old_prot; DWORD old_prot;
VirtualProtect((LPVOID)patch_str, 20, PAGE_EXECUTE_READWRITE, &old_prot); VirtualProtect((LPVOID)patch_str, 20, PAGE_EXECUTE_READWRITE, &old_prot);
for (int i=12; i>=0; i--) for (int i=12; i>=0; i--)
@ -571,7 +582,7 @@ static bool patch_database(bool force_unlocks) {
/* replace idiv by div in score increment computation to avoid score overflow with pure long */ /* replace idiv by div in score increment computation to avoid score overflow with pure long */
patch_purelong(); patch_purelong();
{ {
fuzzy_search_task task; fuzzy_search_task task;
@ -593,7 +604,7 @@ static bool patch_database(bool force_unlocks) {
char *target; char *target;
if (config.patch_xml_auto) { if (config.patch_xml_auto) {
const char *filename = NULL; const char *filename = NULL;
SearchFile s; SearchFile s;
uint8_t *datecode = NULL; uint8_t *datecode = NULL;
bool found = false; bool found = false;
@ -627,7 +638,7 @@ static bool patch_database(bool force_unlocks) {
if (!found) { if (!found) {
printf("popnhax: (patch_xml_auto) matching datecode not found, defaulting to latest patch file.\n"); printf("popnhax: (patch_xml_auto) matching datecode not found, defaulting to latest patch file.\n");
} }
printf("popnhax: (patch_xml_auto) using %s\n",filename); printf("popnhax: (patch_xml_auto) using %s\n",filename);
target = parse_patchdb(filename, data); target = parse_patchdb(filename, data);
@ -636,7 +647,7 @@ static bool patch_database(bool force_unlocks) {
target = parse_patchdb(config.patch_xml_filename, data); target = parse_patchdb(config.patch_xml_filename, data);
} }
if (config.disable_redirection) { if (config.disable_redirection) {
config.disable_expansions = true; config.disable_expansions = true;
} }
@ -1262,13 +1273,13 @@ static bool patch_unlocks_offline() {
static bool get_addr_icca(uint32_t *res) static bool get_addr_icca(uint32_t *res)
{ {
static uint32_t addr = 0; static uint32_t addr = 0;
if (addr != 0) if (addr != 0)
{ {
*res = addr; *res = addr;
return true; return true;
} }
DWORD dllSize = 0; DWORD dllSize = 0;
char *data = getDllData("popn22.dll", &dllSize); char *data = getDllData("popn22.dll", &dllSize);
@ -1293,13 +1304,13 @@ static bool get_addr_icca(uint32_t *res)
static bool get_addr_timing_offset(uint32_t *res) static bool get_addr_timing_offset(uint32_t *res)
{ {
static uint32_t addr = 0; static uint32_t addr = 0;
if (addr != 0) if (addr != 0)
{ {
*res = addr; *res = addr;
return true; return true;
} }
DWORD dllSize = 0; DWORD dllSize = 0;
char *data = getDllData("popn22.dll", &dllSize); char *data = getDllData("popn22.dll", &dllSize);
@ -1315,7 +1326,7 @@ static bool get_addr_timing_offset(uint32_t *res)
uint32_t offset_delta = *(uint32_t *) ((int64_t)data + pattern_offset + 6); uint32_t offset_delta = *(uint32_t *) ((int64_t)data + pattern_offset + 6);
addr = *(uint32_t *) (((int64_t)data + pattern_offset + 10) + offset_delta + 1); addr = *(uint32_t *) (((int64_t)data + pattern_offset + 10) + offset_delta + 1);
#if DEBUG == 1 #if DEBUG == 1
printf("OFFSET MEMORYZONE %x\n", addr); printf("OFFSET MEMORYZONE %x\n", addr);
#endif #endif
*res = addr; *res = addr;
@ -1332,30 +1343,30 @@ static bool patch_hidden_is_offset()
printf("popnhax: hidden is offset: cannot find timing offset address\n"); printf("popnhax: hidden is offset: cannot find timing offset address\n");
return false; return false;
} }
/* patch option commit to store hidden value directly as offset */ /* patch option commit to store hidden value directly as offset */
{ {
/* add correct address to hook function */ /* add correct address to hook function */
char eax_to_offset[6] = "\xA3\x00\x00\x00\x00"; char eax_to_offset[6] = "\xA3\x00\x00\x00\x00";
uint32_t *cast_code = (uint32_t*) &eax_to_offset[1]; uint32_t *cast_code = (uint32_t*) &eax_to_offset[1];
*cast_code = timing_addr; *cast_code = timing_addr;
int64_t hiddencommitoptionaddr = (int64_t)&hidden_is_offset_commit_options; int64_t hiddencommitoptionaddr = (int64_t)&hidden_is_offset_commit_options;
uint8_t *patch_str = (uint8_t*) hiddencommitoptionaddr; uint8_t *patch_str = (uint8_t*) hiddencommitoptionaddr;
uint8_t placeholder_offset = 0; uint8_t placeholder_offset = 0;
while (patch_str[placeholder_offset] != 0x90 && patch_str[placeholder_offset+1] != 0x90) while (patch_str[placeholder_offset] != 0x90 && patch_str[placeholder_offset+1] != 0x90)
placeholder_offset++; placeholder_offset++;
patch_memory(hiddencommitoptionaddr+placeholder_offset+1, eax_to_offset, 5); patch_memory(hiddencommitoptionaddr+placeholder_offset+1, eax_to_offset, 5);
/* find option commit function (unilab) */ /* find option commit function (unilab) */
fuzzy_search_task task; fuzzy_search_task task;
FUZZY_START(task, 1) FUZZY_START(task, 1)
FUZZY_CODE(task, 0, "\x03\xC7\x8D\x44\x01\x2A\x89\x10", 8) FUZZY_CODE(task, 0, "\x03\xC7\x8D\x44\x01\x2A\x89\x10", 8)
uint8_t shift = 6; uint8_t shift = 6;
int64_t pattern_offset = find_block(data, dllSize, &task, 0); int64_t pattern_offset = find_block(data, dllSize, &task, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
/* wasn't found, look for older function */ /* wasn't found, look for older function */
@ -1365,7 +1376,7 @@ static bool patch_hidden_is_offset()
FUZZY_CODE(fallbacktask, 0, "\x0F\xB6\xC3\x03\xCF\x8D", 6) FUZZY_CODE(fallbacktask, 0, "\x0F\xB6\xC3\x03\xCF\x8D", 6)
pattern_offset = find_block(data, dllSize, &fallbacktask, 0); pattern_offset = find_block(data, dllSize, &fallbacktask, 0);
shift = 14; shift = 14;
if (pattern_offset == -1) { if (pattern_offset == -1) {
printf("popnhax: hidden is offset: cannot find address\n"); printf("popnhax: hidden is offset: cannot find address\n");
return false; return false;
@ -1374,38 +1385,38 @@ static bool patch_hidden_is_offset()
printf("popnhax: hidden is offset: appears to be kaimei or less\n"); printf("popnhax: hidden is offset: appears to be kaimei or less\n");
#endif #endif
} }
uint64_t patch_addr = (int64_t)data + pattern_offset + shift; uint64_t patch_addr = (int64_t)data + pattern_offset + shift;
MH_CreateHook((LPVOID)(patch_addr), (LPVOID)hidden_is_offset_commit_options, MH_CreateHook((LPVOID)(patch_addr), (LPVOID)hidden_is_offset_commit_options,
(void **)&real_commit_options); (void **)&real_commit_options);
} }
/* turn "set offset" into an elaborate "sometimes add to offset" to use our hidden+ value as adjust */ /* turn "set offset" into an elaborate "sometimes add to offset" to use our hidden+ value as adjust */
{ {
char set_offset_fun[6] = "\xA3\x00\x00\x00\x00"; char set_offset_fun[6] = "\xA3\x00\x00\x00\x00";
uint32_t *cast_code = (uint32_t*) &set_offset_fun[1]; uint32_t *cast_code = (uint32_t*) &set_offset_fun[1];
*cast_code = timing_addr; *cast_code = timing_addr;
fuzzy_search_task task; fuzzy_search_task task;
FUZZY_START(task, 1) FUZZY_START(task, 1)
FUZZY_CODE(task, 0, set_offset_fun, 5) FUZZY_CODE(task, 0, set_offset_fun, 5)
int64_t pattern_offset = find_block(data, dllSize, &task, 0); int64_t pattern_offset = find_block(data, dllSize, &task, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
printf("popnhax: hidden is offset: cannot find offset update function\n"); printf("popnhax: hidden is offset: cannot find offset update function\n");
return false; return false;
} }
int64_t modded_set_timing_func_addr = (int64_t)&modded_set_timing_func; int64_t modded_set_timing_func_addr = (int64_t)&modded_set_timing_func;
patch_memory(modded_set_timing_func_addr+11, (char*)&timing_addr, 4); patch_memory(modded_set_timing_func_addr+11, (char*)&timing_addr, 4);
uint64_t patch_addr = (int64_t)data + pattern_offset; uint64_t patch_addr = (int64_t)data + pattern_offset;
MH_CreateHook((LPVOID)(patch_addr), (LPVOID)modded_set_timing_func, MH_CreateHook((LPVOID)(patch_addr), (LPVOID)modded_set_timing_func,
(void **)&real_set_timing_func); (void **)&real_set_timing_func);
} }
printf("popnhax: hidden is offset: hidden is now an offset adjust\n"); printf("popnhax: hidden is offset: hidden is now an offset adjust\n");
return true; return true;
} }
@ -1425,14 +1436,14 @@ static bool patch_pfree() {
printf("couldn't find stop stage counter\n"); printf("couldn't find stop stage counter\n");
return false; return false;
} }
uint64_t patch_addr = (int64_t)data + pattern_offset - 0x05; uint64_t patch_addr = (int64_t)data + pattern_offset - 0x05;
g_stage_addr = *(uint32_t*)(patch_addr+1); g_stage_addr = *(uint32_t*)(patch_addr+1);
/* hook to retrieve address for exit to thank you for playing screen */ /* hook to retrieve address for exit to thank you for playing screen */
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_stage_update, MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_stage_update_pfree,
(void **)&real_stage_update); (void **)&real_stage_update);
} }
/* retrieve memory zone parameters to prepare for cleanup */ /* retrieve memory zone parameters to prepare for cleanup */
@ -1553,25 +1564,51 @@ pfree_apply:
return true; return true;
} }
static bool patch_quick_retire() static bool patch_quick_retire(bool pfree)
{ {
DWORD dllSize = 0; DWORD dllSize = 0;
char *data = getDllData("popn22.dll", &dllSize); char *data = getDllData("popn22.dll", &dllSize);
/* hook numpad for instant quit song */ if ( !pfree )
{
/* hook the stage counter function to retrieve stage and transition addr for quick exit session
* (when pfree is active it's taking care of hooking that function differently to prevent stage from incrementing)
*/
{
fuzzy_search_task task;
FUZZY_START(task, 1)
FUZZY_CODE(task, 0, "\x83\xF8\x04\x77\x3E", 5)
int64_t pattern_offset = find_block(data, dllSize, &task, 0);
if (pattern_offset == -1) {
printf("couldn't find stop stage counter\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset - 0x05;
g_stage_addr = *(uint32_t*)(patch_addr+1);
/* hook to retrieve address for exit to thank you for playing screen */
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_stage_update,
(void **)&real_stage_update);
}
}
/* hook numpad for instant quit song */
{ {
fuzzy_search_task task; fuzzy_search_task task;
FUZZY_START(task, 1) FUZZY_START(task, 1)
FUZZY_CODE(task, 0, "\x55\x8B\xEC\x83\xE4\xF8\x83\xEC\x08\x0F\xBF\x05", 12) FUZZY_CODE(task, 0, "\x55\x8B\xEC\x83\xE4\xF8\x83\xEC\x08\x0F\xBF\x05", 12)
int64_t pattern_offset = find_block(data, dllSize, &task, 0); int64_t pattern_offset = find_block(data, dllSize, &task, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
printf("popnhax: cannot retrieve song loop\n"); printf("popnhax: cannot retrieve song loop\n");
return false; return false;
} }
uint32_t addr_icca; uint32_t addr_icca;
if (!get_addr_icca(&addr_icca)) if (!get_addr_icca(&addr_icca))
{ {
@ -1581,26 +1618,26 @@ static bool patch_quick_retire()
int64_t quickexitaddr = (int64_t)&quickexit_game_loop; int64_t quickexitaddr = (int64_t)&quickexit_game_loop;
patch_memory(quickexitaddr+3, (char *)&addr_icca, 4); patch_memory(quickexitaddr+3, (char *)&addr_icca, 4);
uint64_t patch_addr = (int64_t)data + pattern_offset; uint64_t patch_addr = (int64_t)data + pattern_offset;
MH_CreateHook((LPVOID)patch_addr, (LPVOID)quickexit_game_loop, MH_CreateHook((LPVOID)patch_addr, (LPVOID)quickexit_game_loop,
(void **)&real_game_loop); (void **)&real_game_loop);
} }
/* hook numpad in result screen to quit pfree */ /* hook numpad in result screen to quit pfree */
{ {
fuzzy_search_task task; fuzzy_search_task task;
FUZZY_START(task, 1) FUZZY_START(task, 1)
FUZZY_CODE(task, 0, "\xF8\x53\x55\x56\x57\x8B\xE9\x8B\x75\x00\x8B\x85", 12) FUZZY_CODE(task, 0, "\xF8\x53\x55\x56\x57\x8B\xE9\x8B\x75\x00\x8B\x85", 12)
int64_t pattern_offset = find_block(data, dllSize, &task, 0); int64_t pattern_offset = find_block(data, dllSize, &task, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
printf("popnhax: cannot retrieve result screen loop\n"); printf("popnhax: cannot retrieve result screen loop\n");
return false; return false;
} }
uint32_t addr_icca; uint32_t addr_icca;
if (!get_addr_icca(&addr_icca)) if (!get_addr_icca(&addr_icca))
{ {
@ -1610,12 +1647,12 @@ static bool patch_quick_retire()
int64_t quickexitaddr = (int64_t)&quickexit_result_loop; int64_t quickexitaddr = (int64_t)&quickexit_result_loop;
patch_memory(quickexitaddr+3, (char *)&addr_icca, 4); patch_memory(quickexitaddr+3, (char *)&addr_icca, 4);
uint64_t patch_addr = (int64_t)data + pattern_offset - 0x05; uint64_t patch_addr = (int64_t)data + pattern_offset - 0x05;
MH_CreateHook((LPVOID)patch_addr, (LPVOID)quickexit_result_loop, MH_CreateHook((LPVOID)patch_addr, (LPVOID)quickexit_result_loop,
(void **)&real_result_loop); (void **)&real_result_loop);
} }
printf("popnhax: quick retire enabled\n"); printf("popnhax: quick retire enabled\n");
return true; return true;
} }
@ -1623,7 +1660,7 @@ static bool patch_quick_retire()
static bool patch_base_offset(int32_t value) { static bool patch_base_offset(int32_t value) {
char *as_hex = (char *) &value; char *as_hex = (char *) &value;
bool res = true; bool res = true;
/* call get_addr_timing_offset() so that it can still work after timing value is overwritten */ /* call get_addr_timing_offset() so that it can still work after timing value is overwritten */
uint32_t original_timing; uint32_t original_timing;
get_addr_timing_offset(&original_timing); get_addr_timing_offset(&original_timing);
@ -1633,13 +1670,13 @@ static bool patch_base_offset(int32_t value) {
printf("popnhax: base offset: cannot patch base SD timing\n"); printf("popnhax: base offset: cannot patch base SD timing\n");
res = false; res = false;
} }
if (!patch_hex("\xB8\xB4\xFF\xFF\xFF", 5, 1, as_hex, 4)) if (!patch_hex("\xB8\xB4\xFF\xFF\xFF", 5, 1, as_hex, 4))
{ {
printf("popnhax: base offset: cannot patch base HD timing\n"); printf("popnhax: base offset: cannot patch base HD timing\n");
res = false; res = false;
} }
return res; return res;
} }
@ -1655,7 +1692,7 @@ static bool patch_hd_on_sd(uint8_t mode) {
printf("popnhax: HD on SD: cannot set HD offset\n"); printf("popnhax: HD on SD: cannot set HD offset\n");
return false; return false;
} }
/* set window to 1360*768 */ /* set window to 1360*768 */
if ( mode == 2 ) if ( mode == 2 )
{ {
@ -1698,17 +1735,17 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
} }
if (config.quick_retire) { if (config.quick_retire) {
patch_quick_retire(); patch_quick_retire(config.pfree);
} }
if (config.hd_on_sd) { if (config.hd_on_sd) {
patch_hd_on_sd(config.hd_on_sd); patch_hd_on_sd(config.hd_on_sd);
} }
if (config.hidden_is_offset){ if (config.hidden_is_offset){
patch_hidden_is_offset(); patch_hidden_is_offset();
} }
if (config.event_mode) { if (config.event_mode) {
patch_event_mode(); patch_event_mode();
} }
@ -1743,7 +1780,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
#if DEBUG == 1 #if DEBUG == 1
patch_get_time(); patch_get_time();
#endif #endif
MH_EnableHook(MH_ALL_HOOKS); MH_EnableHook(MH_ALL_HOOKS);
break; break;