Compare commits

...

3 Commits

3 changed files with 190 additions and 32 deletions

View File

@ -33,18 +33,22 @@
<!-- Bring back score challenge in the game for servers supporting it (only for kaimei onwards) --> <!-- Bring back score challenge in the game for servers supporting it (only for kaimei onwards) -->
<score_challenge __type="bool">0</score_challenge> <score_challenge __type="bool">0</score_challenge>
<!-- Audio offset -->
<!-- Offset the audio by x ms (negative plays audio earlier). This will disable keysounds -->
<audio_offset __type="s8">0</audio_offset>
<!-- Visual offset --> <!-- Visual offset -->
<!-- Hidden+ setting (press 0 for advanced options) is now a visual offset adjust (negative means you have to hit earlier) --> <!-- Hidden+ setting (press 0 for advanced options) is now a visual offset adjust (negative means you have to hit earlier) -->
<hidden_is_offset __type="bool">0</hidden_is_offset> <hidden_is_offset __type="bool">0</hidden_is_offset>
<!-- Display offset adjust value on score result screen (requires hidden_is_offset, won't be sent over network) --> <!-- Display offset adjust value on score result screen (requires hidden_is_offset, won't be sent over network) -->
<show_offset __type="bool">0</show_offset> <show_offset __type="bool">0</show_offset>
<!-- Result screen display patches -->
<!-- Display details on result screen by default (no need to press yellow button) -->
<show_details __type="bool">0</show_details>
<!-- Display fast/slow counter on result screen even on judge+ off/lost/panic --> <!-- Display fast/slow counter on result screen even on judge+ off/lost/panic -->
<show_fast_slow __type="bool">0</show_fast_slow> <show_fast_slow __type="bool">0</show_fast_slow>
<!-- Audio offset -->
<!-- Offset the audio by x ms (negative plays audio earlier). This will disable keysounds -->
<audio_offset __type="s8">0</audio_offset>
<!-- Input polling --> <!-- Input polling -->
<!-- 1000Hz polling rate (no more shifting timing windows/magic bpm, consistent scoring independently of framerate) --> <!-- 1000Hz polling rate (no more shifting timing windows/magic bpm, consistent scoring independently of framerate) -->
<enhanced_polling __type="bool">0</enhanced_polling> <enhanced_polling __type="bool">0</enhanced_polling>

View File

@ -8,6 +8,7 @@ struct popnhax_config {
bool hidden_is_offset; bool hidden_is_offset;
bool show_offset; bool show_offset;
bool show_fast_slow; bool show_fast_slow;
bool show_details;
bool pfree; bool pfree;
bool quick_retire; bool quick_retire;
bool back_to_song_select; bool back_to_song_select;

View File

@ -92,6 +92,8 @@ PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, hidden_is_offs
"/popnhax/hidden_is_offset") "/popnhax/hidden_is_offset")
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, show_fast_slow, PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, show_fast_slow,
"/popnhax/show_fast_slow") "/popnhax/show_fast_slow")
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, show_details,
"/popnhax/show_details")
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, show_offset, PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, show_offset,
"/popnhax/show_offset") "/popnhax/show_offset")
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, pfree, PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, pfree,
@ -270,8 +272,10 @@ uint32_t g_transition_addr = 0;
uint32_t g_stage_addr = 0; uint32_t g_stage_addr = 0;
uint32_t g_score_addr = 0; uint32_t g_score_addr = 0;
bool g_pfree_mode = false; bool g_pfree_mode = false;
bool g_end_session = false;
bool g_return_to_options = false; bool g_return_to_options = false;
bool g_return_to_song_select = false; bool g_return_to_song_select = false;
bool g_return_to_song_select_num9 = false;
void (*real_screen_transition)(); void (*real_screen_transition)();
void quickexit_screen_transition() void quickexit_screen_transition()
{ {
@ -287,6 +291,7 @@ void quickexit_screen_transition()
g_return_to_song_select = false; g_return_to_song_select = false;
//flag is set back to false in hook_stage_increment otherwise //flag is set back to false in hook_stage_increment otherwise
} }
g_end_session = false;
real_screen_transition(); real_screen_transition();
} }
@ -377,12 +382,24 @@ void backtosongselect_option_screen()
__asm("cmp bl, 8\n"); __asm("cmp bl, 8\n");
__asm("jne exit_back_select\n"); __asm("jne exit_back_select\n");
g_return_to_song_select = true; g_return_to_song_select = true;
g_return_to_song_select_num9 = true;
__asm("exit_back_select:\n"); __asm("exit_back_select:\n");
real_option_screen_later(); real_option_screen_later();
} }
void (*real_backtosongselect_option_screen_auto_leave)();
void backtosongselect_option_screen_auto_leave()
{
if ( g_return_to_song_select_num9 )
{
g_return_to_song_select_num9 = false;
__asm("mov al, 1\n");
}
real_backtosongselect_option_screen_auto_leave();
}
void (*real_option_screen_yellow)(); void (*real_option_screen_yellow)();
void backtosongselect_option_yellow() void backtosongselect_option_yellow()
{ {
@ -399,11 +416,25 @@ void backtosongselect_option_yellow()
__asm("jne exit_back_select_yellow\n"); __asm("jne exit_back_select_yellow\n");
g_return_to_song_select = true; g_return_to_song_select = true;
g_return_to_song_select_num9 = true;
__asm("exit_back_select_yellow:\n"); __asm("exit_back_select_yellow:\n");
real_option_screen_yellow(); real_option_screen_yellow();
} }
uint32_t g_option_yellow_leave_addr = 0;
void (*real_backtosongselect_option_screen_yellow_auto_leave)();
void backtosongselect_option_screen_yellow_auto_leave()
{
if ( g_return_to_song_select_num9 )
{
g_return_to_song_select_num9 = false;
__asm("push %0\n": :"m"(g_option_yellow_leave_addr));
__asm("ret\n");
}
real_backtosongselect_option_screen_yellow_auto_leave();
}
static bool r_ran; static bool r_ran;
static bool regul_flg; static bool regul_flg;
//static bool dj_auto; //static bool dj_auto;
@ -436,7 +467,7 @@ numpad values:
4 | 4 5 6 4 | 4 5 6
2 | 1 2 3 2 | 1 2 3
1 | 0 00 1 | 0 00
e.g. numpad 9 = 8<<16 = 00 08 00 00 e.g. numpad 9 = 8<<16 = 00 08 00 00
numpad 2 = 2<<28 = 20 00 00 00 numpad 2 = 2<<28 = 20 00 00 00
*/ */
@ -519,6 +550,7 @@ void quickexit_result_loop()
__asm("jmp call_real_result\n"); __asm("jmp call_real_result\n");
__asm("quit_session:\n"); __asm("quit_session:\n");
g_end_session = true;
g_return_to_options = false; g_return_to_options = false;
/* set value 5 in g_stage_addr and -4 in g_transition_addr (to get fade to black transition) */ /* set value 5 in g_stage_addr and -4 in g_transition_addr (to get fade to black transition) */
__asm("mov ebx, %0\n": :"b"(g_stage_addr)); __asm("mov ebx, %0\n": :"b"(g_stage_addr));
@ -534,6 +566,17 @@ void quickexit_result_loop()
real_result_loop(); real_result_loop();
} }
void (*real_result_button_loop)();
void quickexit_result_button_loop()
{
if ( g_end_session || g_return_to_options )
{
//g_return_to_options is reset in quickexit_option_screen_cleanup(), g_end_session is reset in quickexit_screen_transition()
__asm("mov al, 1\n");
}
real_result_button_loop();
}
uint32_t g_timing_addr = 0; uint32_t g_timing_addr = 0;
bool g_timing_require_update = false; bool g_timing_require_update = false;
@ -1711,6 +1754,62 @@ static bool force_show_fast_slow() {
return true; return true;
} }
void (*real_show_detail_result)();
void hook_show_detail_result()
{
static uint32_t last_call = 0;
__asm("push eax\n");
__asm("push edx\n");
uint32_t curr_time = timeGetTime(); //will clobber eax
if ( curr_time - last_call > 10000 ) //will clobber edx
{
last_call = curr_time;
__asm("pop edx\n");
__asm("pop eax\n");
//force press yellow button
__asm("mov al, 1\n");
}
else
{
last_call = curr_time;
__asm("pop edx\n");
__asm("pop eax\n");
}
real_show_detail_result();
}
static bool force_show_details_result() {
DWORD dllSize = 0;
char *data = getDllData(g_game_dll_fn, &dllSize);
int64_t first_loc = search(data, dllSize, "\x8B\x45\x48\x8B\x58\x0C\x6A\x09\x68\x80\x00\x00\x00", 13, 0);
if (first_loc == -1) {
LOG("popnhax: show details: cannot find result screen button check (1)\n");
return false;
}
//+0x26
{
int64_t pattern_offset = search(data, 0x50, "\x84\xC0", 2, first_loc);
if (pattern_offset == -1) {
LOG("popnhax: show details: cannot find result screen button check (2)\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset;
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_show_detail_result,
(void **)&real_show_detail_result);
}
LOG("popnhax: force show details on result screen\n");
return true;
}
static bool patch_pfree() { static bool patch_pfree() {
DWORD dllSize = 0; DWORD dllSize = 0;
char *data = getDllData(g_game_dll_fn, &dllSize); char *data = getDllData(g_game_dll_fn, &dllSize);
@ -1901,6 +2000,21 @@ static bool patch_quick_retire(bool pfree)
(void **)&real_result_loop); (void **)&real_result_loop);
} }
/* no need to press red button when numpad 8 or 9 is pressed on result screen */
{
int64_t pattern_offset = search(data, dllSize, "\x84\xC0\x75\x0F\x8B\x8D\x1C\x0A\x00\x00\xE8", 11, 0);
if (pattern_offset == -1) {
LOG("popnhax: cannot retrieve result screen button check\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset + 0x1D;
MH_CreateHook((LPVOID)patch_addr, (LPVOID)quickexit_result_button_loop,
(void **)&real_result_button_loop);
}
LOG("popnhax: quick retire enabled\n"); LOG("popnhax: quick retire enabled\n");
/* retrieve songstart function pointer for quick retry */ /* retrieve songstart function pointer for quick retry */
@ -1970,7 +2084,7 @@ static bool patch_quick_retire(bool pfree)
int64_t pattern_offset = search(data, dllSize, "\x8B\x85\x0C\x0A\x00\x00\x83\x78\x34\x00\x75", 11, 0); int64_t pattern_offset = search(data, dllSize, "\x8B\x85\x0C\x0A\x00\x00\x83\x78\x34\x00\x75", 11, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
LOG("popnhax: quick retry: cannot retrieve option screen loop function\n"); LOG("popnhax: back to song select: cannot retrieve option screen loop function\n");
return false; return false;
} }
@ -1978,6 +2092,19 @@ static bool patch_quick_retire(bool pfree)
MH_CreateHook((LPVOID)patch_addr, (LPVOID)backtosongselect_option_screen, MH_CreateHook((LPVOID)patch_addr, (LPVOID)backtosongselect_option_screen,
(void **)&real_option_screen_later); (void **)&real_option_screen_later);
} }
/* automatically leave option screen after numpad 9 press */
{
int64_t pattern_offset = search(data, dllSize, "\x84\xC0\x75\x63\x8B\x85\x10\x0A\x00\x00\x83\xC0\x04\xBF\x0C\x00\x00\x00", 18, 0);
if (pattern_offset == -1) {
LOG("popnhax: back to song select: cannot retrieve option screen loop function\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset;
MH_CreateHook((LPVOID)patch_addr, (LPVOID)backtosongselect_option_screen_auto_leave,
(void **)&real_backtosongselect_option_screen_auto_leave);
}
/* go back to song select with numpad 9 on song option screen (after pressing yellow) */ /* go back to song select with numpad 9 on song option screen (after pressing yellow) */
{ {
@ -1992,7 +2119,29 @@ static bool patch_quick_retire(bool pfree)
MH_CreateHook((LPVOID)patch_addr, (LPVOID)backtosongselect_option_yellow, MH_CreateHook((LPVOID)patch_addr, (LPVOID)backtosongselect_option_yellow,
(void **)&real_option_screen_yellow); (void **)&real_option_screen_yellow);
} }
LOG("popnhax: quick retry: return to song select enabled\n"); /* automatically leave after numpad 9 press */
{
int64_t pattern_offset = search(data, dllSize, "\x8B\x55\x00\x8B\x82\x9C\x00\x00\x00\x6A\x01\x8B\xCD\xFF\xD0\x80\xBD", 17, 0);
if (pattern_offset == -1) {
LOG("popnhax: back to song select: cannot retrieve option screen yellow leave addr\n");
return false;
}
g_option_yellow_leave_addr = (int32_t)data + pattern_offset - 0x05;
pattern_offset = search(data, dllSize, "\x84\xC0\x0F\x84\xF1\x00\x00\x00\x8B\xC5", 10, 0);
if (pattern_offset == -1) {
LOG("popnhax: back to song select: cannot retrieve option screen yellow button check function\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset;
MH_CreateHook((LPVOID)patch_addr, (LPVOID)backtosongselect_option_screen_yellow_auto_leave,
(void **)&real_backtosongselect_option_screen_yellow_auto_leave);
}
LOG("popnhax: quick retire: return to song select enabled\n");
} }
if (pfree) if (pfree)
@ -2075,7 +2224,7 @@ static unsigned int __stdcall enhanced_polling_stats_proc(void *ctx)
while (g_enhanced_poll_ready) while (g_enhanced_poll_ready)
{ {
uint32_t pad_bits; uint32_t pad_bits;
/* ensure at least 1ms has elapsed between polls /* ensure at least 1ms has elapsed between polls
* (beware of SD cab hardware compatibility) * (beware of SD cab hardware compatibility)
*/ */
curr_poll_time = timeGetTime(); curr_poll_time = timeGetTime();
@ -2093,7 +2242,7 @@ static unsigned int __stdcall enhanced_polling_stats_proc(void *ctx)
usbPadRead(&pad_bits); usbPadRead(&pad_bits);
g_last_button_state = pad_bits; g_last_button_state = pad_bits;
unsigned int buttonState = (g_last_button_state >> 8) & 0x1FF; unsigned int buttonState = (g_last_button_state >> 8) & 0x1FF;
for (int i = 0; i < 9; i++) for (int i = 0; i < 9; i++)
{ {
@ -2112,7 +2261,7 @@ static unsigned int __stdcall enhanced_polling_stats_proc(void *ctx)
{ {
button_debounce[i]--; button_debounce[i]--;
} }
if (button_debounce[i] == 0) if (button_debounce[i] == 0)
{ {
g_button_state[i] = -1; g_button_state[i] = -1;
@ -2161,7 +2310,7 @@ static unsigned int __stdcall enhanced_polling_proc(void *ctx)
while (g_enhanced_poll_ready) while (g_enhanced_poll_ready)
{ {
uint32_t pad_bits; uint32_t pad_bits;
/* ensure at least 1ms has elapsed between polls /* ensure at least 1ms has elapsed between polls
* (beware of SD cab hardware compatibility) * (beware of SD cab hardware compatibility)
*/ */
curr_poll_time = timeGetTime(); curr_poll_time = timeGetTime();
@ -2174,7 +2323,7 @@ static unsigned int __stdcall enhanced_polling_proc(void *ctx)
usbPadRead(&pad_bits); usbPadRead(&pad_bits);
g_last_button_state = pad_bits; g_last_button_state = pad_bits;
unsigned int buttonState = (g_last_button_state >> 8) & 0x1FF; unsigned int buttonState = (g_last_button_state >> 8) & 0x1FF;
for (int i = 0; i < 9; i++) for (int i = 0; i < 9; i++)
{ {
@ -2193,7 +2342,7 @@ static unsigned int __stdcall enhanced_polling_proc(void *ctx)
{ {
button_debounce[i]--; button_debounce[i]--;
} }
if (button_debounce[i] == 0) if (button_debounce[i] == 0)
{ {
g_button_state[i] = -1; g_button_state[i] = -1;
@ -2338,7 +2487,7 @@ static bool patch_enhanced_polling(uint8_t debounce, bool stats)
void (*real_chart_load)(); void (*real_chart_load)();
void patch_chart_load_old() { void patch_chart_load_old() {
/* This is mostly the same patch as the new version, except : /* This is mostly the same patch as the new version, except :
* - eax and ecx have a different interpretation * - eax and ecx have a different interpretation
* - a chart chunk is only 2 dwords * - a chart chunk is only 2 dwords
*/ */
__asm("cmp word ptr [edi+eax*8+4], 0x245\n"); __asm("cmp word ptr [edi+eax*8+4], 0x245\n");
@ -2347,7 +2496,7 @@ void patch_chart_load_old() {
/* keysound event has been found, we need to convert timestamp */ /* keysound event has been found, we need to convert timestamp */
__asm("mov word ptr [edi+eax*8+4], 0x745\n"); // we'll undo it if we cannot apply it __asm("mov word ptr [edi+eax*8+4], 0x745\n"); // we'll undo it if we cannot apply it
__asm("push eax\n"); // we'll convert to store chunk pointer (keysound timestamp at beginning) __asm("push eax\n"); // we'll convert to store chunk pointer (keysound timestamp at beginning)
__asm("push ebx\n"); // we'll store a copy of our chunk pointer there __asm("push ebx\n"); // we'll store a copy of our chunk pointer there
__asm("push edx\n"); // we'll store the button info there __asm("push edx\n"); // we'll store the button info there
__asm("push esi\n"); // we'll store chart growth for part2 subroutine there __asm("push esi\n"); // we'll store chart growth for part2 subroutine there
__asm("push ecx\n"); // we'll convert to store remaining chunks __asm("push ecx\n"); // we'll convert to store remaining chunks
@ -2364,7 +2513,7 @@ void patch_chart_load_old() {
__asm("mov dl, byte ptr [eax+7]\n"); __asm("mov dl, byte ptr [eax+7]\n");
__asm("shr edx, 4\n"); //dl now contains button value ( 00-08 ) __asm("shr edx, 4\n"); //dl now contains button value ( 00-08 )
__asm("mov ebx, eax\n"); //save chunk pointer into ebx for our rep movsd when a match is found __asm("mov ebx, eax\n"); //save chunk pointer into ebx for our rep movsd when a match is found
__asm("old_next_chart_chunk:\n"); __asm("old_next_chart_chunk:\n");
__asm("add eax, 0x8\n"); // +0x08 in old chart format __asm("add eax, 0x8\n"); // +0x08 in old chart format
__asm("sub ecx, 1\n"); __asm("sub ecx, 1\n");
@ -2373,7 +2522,7 @@ void patch_chart_load_old() {
/* check where the keysound is used */ /* check where the keysound is used */
__asm("cmp word ptr [eax+4], 0x245\n"); __asm("cmp word ptr [eax+4], 0x245\n");
__asm("jne old_check_first_note_event\n"); //still need to check 0x145.. __asm("jne old_check_first_note_event\n"); //still need to check 0x145..
__asm("push ecx\n"); __asm("push ecx\n");
__asm("xor cx, cx\n"); __asm("xor cx, cx\n");
__asm("mov cl, byte ptr [eax+7]\n"); __asm("mov cl, byte ptr [eax+7]\n");
@ -2389,7 +2538,7 @@ void patch_chart_load_old() {
__asm("pop eax\n"); __asm("pop eax\n");
__asm("mov word ptr [edi+eax*8+4], 0x0\n"); // disable operation, cannot be converted to a 0x745, and should not apply __asm("mov word ptr [edi+eax*8+4], 0x0\n"); // disable operation, cannot be converted to a 0x745, and should not apply
__asm("jmp old_patch_chart_load_end\n"); __asm("jmp old_patch_chart_load_end\n");
__asm("old_check_first_note_event:\n"); __asm("old_check_first_note_event:\n");
__asm("cmp word ptr [eax+4], 0x145\n"); __asm("cmp word ptr [eax+4], 0x145\n");
__asm("jne old_next_chart_chunk\n"); __asm("jne old_next_chart_chunk\n");
@ -2398,7 +2547,7 @@ void patch_chart_load_old() {
__asm("jne old_next_chart_chunk\n"); __asm("jne old_next_chart_chunk\n");
/* found MATCHING note event */ /* found MATCHING note event */
__asm("mov edx, dword ptr [ebx+4]\n"); //save operation (we need to shift the whole block first) __asm("mov edx, dword ptr [ebx+4]\n"); //save operation (we need to shift the whole block first)
/* move the whole block just before the note event to preserve timestamp ordering */ /* move the whole block just before the note event to preserve timestamp ordering */
__asm("push ecx\n"); __asm("push ecx\n");
__asm("push esi\n"); __asm("push esi\n");
@ -2417,7 +2566,7 @@ void patch_chart_load_old() {
/* write the 0x745 event just before our matching 0x145 which eax points to */ /* write the 0x745 event just before our matching 0x145 which eax points to */
__asm("mov dword ptr [eax-0x08+0x04], edx\n"); // operation __asm("mov dword ptr [eax-0x08+0x04], edx\n"); // operation
__asm("mov edx, dword ptr [eax]\n"); __asm("mov edx, dword ptr [eax]\n");
__asm("mov dword ptr [eax-0x08], edx\n"); // timestamp __asm("mov dword ptr [eax-0x08], edx\n"); // timestamp
/* PART2: Look for other instances of same button key events (0x0145) before the keysound is detached */ /* PART2: Look for other instances of same button key events (0x0145) before the keysound is detached */
@ -2431,10 +2580,10 @@ void patch_chart_load_old() {
__asm("add eax, 0x8\n"); __asm("add eax, 0x8\n");
__asm("sub ecx, 1\n"); __asm("sub ecx, 1\n");
__asm("jz old_end_of_same_note_search\n"); //end of chart reached __asm("jz old_end_of_same_note_search\n"); //end of chart reached
__asm("cmp word ptr [eax+4], 0x245\n"); __asm("cmp word ptr [eax+4], 0x245\n");
__asm("jne old_check_if_note_event\n"); //still need to check 0x145.. __asm("jne old_check_if_note_event\n"); //still need to check 0x145..
__asm("push ecx\n"); __asm("push ecx\n");
__asm("xor cx, cx\n"); __asm("xor cx, cx\n");
__asm("mov cl, byte ptr [eax+7]\n"); __asm("mov cl, byte ptr [eax+7]\n");
@ -2484,7 +2633,7 @@ void patch_chart_load_old() {
__asm("old_end_of_same_note_search:\n"); __asm("old_end_of_same_note_search:\n");
/* restore before next timestamp */ /* restore before next timestamp */
__asm("pop ecx\n"); __asm("pop ecx\n");
__asm("add ecx, esi\n"); // take chart growth into account __asm("add ecx, esi\n"); // take chart growth into account
__asm("pop esi\n"); __asm("pop esi\n");
__asm("pop edx\n"); __asm("pop edx\n");
__asm("pop ebx\n"); __asm("pop ebx\n");
@ -2494,7 +2643,7 @@ void patch_chart_load_old() {
__asm("sub eax, 1\n"); __asm("sub eax, 1\n");
__asm("sub dword ptr [edi+eax*8], 0x64\n"); __asm("sub dword ptr [edi+eax*8], 0x64\n");
__asm("jmp old_patch_chart_load_end\n"); __asm("jmp old_patch_chart_load_end\n");
__asm("old_end_of_chart:\n"); __asm("old_end_of_chart:\n");
__asm("pop ecx\n"); __asm("pop ecx\n");
__asm("pop esi\n"); __asm("pop esi\n");
@ -2513,7 +2662,7 @@ void patch_chart_load() {
/* keysound event has been found, we need to convert timestamp */ /* keysound event has been found, we need to convert timestamp */
__asm("mov word ptr [eax+4], 0x745\n"); // we'll undo it if we cannot apply it __asm("mov word ptr [eax+4], 0x745\n"); // we'll undo it if we cannot apply it
__asm("push eax\n"); // chunk pointer (keysound timestamp at beginning) __asm("push eax\n"); // chunk pointer (keysound timestamp at beginning)
__asm("push ebx\n"); // we'll store a copy of our chunk pointer there __asm("push ebx\n"); // we'll store a copy of our chunk pointer there
__asm("push edx\n"); // we'll store the button info there __asm("push edx\n"); // we'll store the button info there
__asm("push esi\n"); // we'll store chart growth for part2 subroutine there __asm("push esi\n"); // we'll store chart growth for part2 subroutine there
__asm("push ecx\n"); // remaining chunks __asm("push ecx\n"); // remaining chunks
@ -2523,7 +2672,7 @@ void patch_chart_load() {
__asm("mov dl, byte ptr [eax+7]\n"); __asm("mov dl, byte ptr [eax+7]\n");
__asm("shr edx, 4\n"); //dl now contains button value ( 00-08 ) __asm("shr edx, 4\n"); //dl now contains button value ( 00-08 )
__asm("mov ebx, eax\n"); //save chunk pointer into ebx for our rep movsd when a match is found __asm("mov ebx, eax\n"); //save chunk pointer into ebx for our rep movsd when a match is found
__asm("next_chart_chunk:\n"); __asm("next_chart_chunk:\n");
__asm("add eax, 0xC\n"); __asm("add eax, 0xC\n");
__asm("sub ecx, 1\n"); __asm("sub ecx, 1\n");
@ -2532,7 +2681,7 @@ void patch_chart_load() {
/* check where the keysound is used */ /* check where the keysound is used */
__asm("cmp word ptr [eax+4], 0x245\n"); __asm("cmp word ptr [eax+4], 0x245\n");
__asm("jne check_first_note_event\n"); //still need to check 0x145.. __asm("jne check_first_note_event\n"); //still need to check 0x145..
__asm("push ecx\n"); __asm("push ecx\n");
__asm("xor cx, cx\n"); __asm("xor cx, cx\n");
__asm("mov cl, byte ptr [eax+7]\n"); __asm("mov cl, byte ptr [eax+7]\n");
@ -2557,7 +2706,7 @@ void patch_chart_load() {
__asm("jne next_chart_chunk\n"); __asm("jne next_chart_chunk\n");
/* found MATCHING note event */ /* found MATCHING note event */
__asm("mov edx, dword ptr [ebx+4]\n"); //save operation (we need to shift the whole block first) __asm("mov edx, dword ptr [ebx+4]\n"); //save operation (we need to shift the whole block first)
/* move the whole block just before the note event to preserve timestamp ordering */ /* move the whole block just before the note event to preserve timestamp ordering */
__asm("push ecx\n"); __asm("push ecx\n");
__asm("push esi\n"); __asm("push esi\n");
@ -2576,7 +2725,7 @@ void patch_chart_load() {
/* write the 0x745 event just before our matching 0x145 which eax points to */ /* write the 0x745 event just before our matching 0x145 which eax points to */
__asm("mov dword ptr [eax-0x0C+0x04], edx\n"); // operation __asm("mov dword ptr [eax-0x0C+0x04], edx\n"); // operation
__asm("mov edx, dword ptr [eax]\n"); __asm("mov edx, dword ptr [eax]\n");
__asm("mov dword ptr [eax-0x0C], edx\n"); // timestamp __asm("mov dword ptr [eax-0x0C], edx\n"); // timestamp
__asm("mov dword ptr [eax-0x0C+0x08], 0x0\n"); // cleanup possible longnote duration leftover __asm("mov dword ptr [eax-0x0C+0x08], 0x0\n"); // cleanup possible longnote duration leftover
@ -2591,10 +2740,10 @@ void patch_chart_load() {
__asm("add eax, 0xC\n"); __asm("add eax, 0xC\n");
__asm("sub ecx, 1\n"); __asm("sub ecx, 1\n");
__asm("jz end_of_same_note_search\n"); //end of chart reached __asm("jz end_of_same_note_search\n"); //end of chart reached
__asm("cmp word ptr [eax+4], 0x245\n"); __asm("cmp word ptr [eax+4], 0x245\n");
__asm("jne check_if_note_event\n"); //still need to check 0x145.. __asm("jne check_if_note_event\n"); //still need to check 0x145..
__asm("push ecx\n"); __asm("push ecx\n");
__asm("xor cx, cx\n"); __asm("xor cx, cx\n");
__asm("mov cl, byte ptr [eax+7]\n"); __asm("mov cl, byte ptr [eax+7]\n");
@ -2645,7 +2794,7 @@ void patch_chart_load() {
__asm("end_of_same_note_search:\n"); __asm("end_of_same_note_search:\n");
/* restore before next timestamp */ /* restore before next timestamp */
__asm("pop ecx\n"); __asm("pop ecx\n");
__asm("add ecx, esi\n"); // take chart growth into account __asm("add ecx, esi\n"); // take chart growth into account
__asm("pop esi\n"); __asm("pop esi\n");
__asm("pop edx\n"); __asm("pop edx\n");
__asm("pop ebx\n"); __asm("pop ebx\n");
@ -4029,6 +4178,10 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
force_show_fast_slow(); force_show_fast_slow();
} }
if (config.show_details){
force_show_details_result();
}
if (config.audio_offset){ if (config.audio_offset){
if (config.keysound_offset) if (config.keysound_offset)
{ {