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

score challenge

This commit is contained in:
CrazyRedMachine 2023-05-29 16:12:04 +02:00
parent 299c6566fe
commit 7a9795dd31
3 changed files with 204 additions and 16 deletions

View File

@ -10,6 +10,9 @@
<!-- quick_retire with pfree also enables quick retry: hold numpad 7 to retry -->
<quick_retire __type="bool">0</quick_retire>
<!-- Bring back score challenge in the game for servers supporting it (only for kaimei onwards) -->
<score_challenge __type="bool">0</score_challenge>
<!-- HD timing for pcb_type=0 -->
<force_hd_timing __type="bool">0</force_hd_timing>
<!-- HD resolution for pcb_type=0 (0: no, 1: keep texts as on HD cab (smaller LCD mod), 2: center texts (32" LCD mod) ) -->

View File

@ -8,6 +8,7 @@ struct popnhax_config {
bool hidden_is_offset;
bool pfree;
bool quick_retire;
bool score_challenge;
bool force_hd_timing;
uint8_t force_hd_resolution;
bool force_unlocks;

View File

@ -88,6 +88,8 @@ PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, pfree,
"/popnhax/pfree")
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, quick_retire,
"/popnhax/quick_retire")
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, score_challenge,
"/popnhax/score_challenge")
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, force_hd_timing,
"/popnhax/force_hd_timing")
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_U8, struct popnhax_config, force_hd_resolution,
@ -2156,6 +2158,184 @@ static bool patch_beam_brightness(uint8_t value) {
return res;
}
uint16_t *g_course_id_ptr;
uint16_t *g_course_song_id_ptr;
void (*real_parse_ranking_info)();
void score_challenge_retrieve_addr()
{
/* only set pointer if g_course_id_ptr is not set yet,
* to avoid overwriting with past challenge data which
* is sent afterwards
*/
__asm("mov ebx, %0\n": :"b"(g_course_id_ptr));
__asm("test ebx, ebx\n");
__asm("jne parse_ranking_info\n");
__asm("lea %0, [esi]\n":"=S"(g_course_id_ptr): :);
__asm("lea %0, [esi+0x8D4]\n":"=S"(g_course_song_id_ptr): :);
__asm("parse_ranking_info:\n");
real_parse_ranking_info();
}
void (*score_challenge_prep_songdata)();
void (*score_challenge_song_inject)();
void (*score_challenge_test_if_logged1)();
void (*score_challenge_test_if_normal_mode)();
void (*real_make_score_challenge_category)();
void make_score_challenge_category()
{
__asm("push ecx\n");
__asm("push ebx\n");
__asm("push edi\n");
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 */
__asm("test al, al\n");
__asm("je leave_score_challenge\n");
score_challenge_test_if_normal_mode();
__asm("test al, al\n");
__asm("jne leave_score_challenge\n");
__asm("mov cx, %0\n": :"r"(*g_course_song_id_ptr));
__asm("mov dl,6\n");
__asm("lea eax,[esp+0x8]\n");
score_challenge_prep_songdata();
__asm("lea edi,[esi+0x24]\n");
__asm("mov ebx,eax\n");
score_challenge_song_inject();
__asm("mov byte ptr ds:[esi+0xA4],1\n");
}
__asm("leave_score_challenge:\n");
__asm("pop edi\n");
__asm("pop ebx\n");
__asm("pop ecx\n");
}
/* all code handling score challenge is still in the game but the
* function responsible for building and adding the score challenge
* category to song selection has been stubbed. let's rewrite it
*/
static bool patch_score_challenge()
{
DWORD dllSize = 0;
char *data = getDllData(g_game_dll_fn, &dllSize);
/* Part1: retrieve course id and song id, useful and will simplify a little */
{
fuzzy_search_task task;
FUZZY_START(task, 1)
FUZZY_CODE(task, 0, "\x81\xC6\xCC\x08\x00\x00\xC7\x44\x24", 9)
int64_t pattern_offset = find_block(data, dllSize, &task, 0);
if (pattern_offset == -1) {
printf("popnhax: score challenge: cannot find course/song address\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset;
MH_CreateHook((LPVOID)(patch_addr), (LPVOID)score_challenge_retrieve_addr,
(void **)&real_parse_ranking_info);
}
/* Part2: retrieve subfunctions which used to be called by the now stubbed function */
{
fuzzy_search_task task;
FUZZY_START(task, 1)
FUZZY_CODE(task, 0, "\x66\x89\x08\x88\x50\x02", 6)
int64_t pattern_offset = find_block(data, dllSize, &task, 0);
if (pattern_offset == -1) {
printf("popnhax: score challenge: cannot find song data prep function\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset;
score_challenge_prep_songdata = (void(*)())patch_addr;
}
{
fuzzy_search_task task;
FUZZY_START(task, 1)
FUZZY_CODE(task, 0, "\x8B\x4F\x0C\x83\xEC\x10\x56\x85\xC9\x75\x04\x33\xC0\xEB\x08\x8B\x47\x14\x2B\xC1\xC1\xF8\x02\x8B\x77\x10\x8B\xD6\x2B\xD1\xC1\xFA\x02\x3B\xD0\x73\x2B", 37)
int64_t pattern_offset = find_block(data, dllSize-0x60000, &task, 0x60000);
if (pattern_offset == -1) {
printf("popnhax: score challenge: cannot find category song inject function\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset;
score_challenge_song_inject = (void(*)())patch_addr;
}
{
fuzzy_search_task task;
FUZZY_START(task, 1)
FUZZY_CODE(task, 0, "\x8B\x01\x8B\x50\x14\xFF\xE2\xC3\xCC\xCC\xCC\xCC", 12)
int64_t pattern_offset = find_block(data, dllSize, &task, 0);
if (pattern_offset == -1) {
printf("popnhax: score challenge: cannot find check if logged function\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset + 0x24;
score_challenge_test_if_logged1 = (void(*)())patch_addr;
}
{
fuzzy_search_task task;
FUZZY_START(task, 1)
FUZZY_CODE(task, 0, "\xF7\xD8\x1B\xC0\x40\xC3\xE8", 7)
int64_t pattern_offset = find_block(data, dllSize, &task, 0);
if (pattern_offset == -1) {
printf("popnhax: score challenge: cannot find check if logged function\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset + 0x6;
score_challenge_test_if_normal_mode = (void(*)())patch_addr;
}
/* Part3: "unstub" the score challenge category creation */
{
fuzzy_search_task task;
FUZZY_START(task, 1)
FUZZY_CODE(task, 0, "\x83\xF8\x10\x77\x75\xFF\x24\x85", 8)
int64_t pattern_offset = find_block(data, dllSize, &task, 0);
if (pattern_offset == -1) {
printf("popnhax: score challenge: cannot find category building loop\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset + 0x66;
uint32_t function_offset = *((uint32_t*)(patch_addr+0x01));
uint64_t function_addr = patch_addr+5+function_offset;
MH_CreateHook((LPVOID)(function_addr), (LPVOID)make_score_challenge_category,
(void **)&real_make_score_challenge_category);
}
printf("popnhax: score challenge reactivated (requires server support)\n");
return true;
}
static bool patch_base_offset(int32_t value) {
char *as_hex = (char *) &value;
bool res = true;
@ -3075,6 +3255,10 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
patch_quick_retire(config.pfree);
}
if (config.score_challenge) {
patch_score_challenge();
}
if (config.force_hd_timing) {
patch_hd_timing();
}