Compare commits

..

23 Commits

Author SHA1 Message Date
d17bd63f3a fix local favorite end of credit crash with guest 2024-06-06 09:55:31 +02:00
03104c4ae9 result screen retire/retry sound ok 2024-06-06 00:33:57 +02:00
65f9c02f65 backtosongselect sound ok 2024-06-06 00:19:59 +02:00
a00cbd6daa indent 2024-06-05 20:44:27 +02:00
3a57387e6a wip backtosongselect fix 2024-06-05 20:43:39 +02:00
d483cd61d7 wip sound when pfree leave 2024-06-05 00:39:18 +02:00
cce17f9483 auto hispeed reset to default bpm between credits 2024-06-04 21:59:52 +02:00
bed5eed9b6 high_framerate_limiter 2024-06-03 21:05:29 +02:00
87de9ed78a high framerate fps 2024-06-03 21:05:29 +02:00
f1a78c8469 high framerate patch 2024-06-03 21:05:29 +02:00
94377ea218 exclude custom folder with _ or _exclude file 2024-06-03 21:05:29 +02:00
3c20bef186 rename subcateg via _name.txt 2024-06-03 21:05:29 +02:00
6a21121e8b remove max_song_id, add partial_entries and exclude_omni 2024-06-03 21:05:29 +02:00
fc4a817824 move subcateg creation to loader.cc 2024-06-03 21:05:29 +02:00
899b311281 add BST for customs 2024-06-03 21:05:29 +02:00
989350e051 wip better custom detection 2024-06-03 21:05:29 +02:00
6f2a340359 wip exclude customs by prepending _ 2024-06-03 21:05:29 +02:00
2b7ba52f1a fix enhanced polling judgement correction 2024-06-03 21:05:29 +02:00
c39bce4e1f fix auto hispeed soflan retry quirks 2024-06-03 21:05:29 +02:00
eb56b39d1b fix auto hispeed random x1.0 bug 2024-06-03 21:05:29 +02:00
aa7505206c enhance custom popkuns handling for record mode 2024-06-03 21:05:29 +02:00
27d6453bd3 r2nk226: popkun change 2024-06-03 21:05:29 +02:00
ae12d608cd r2nk226: record mode, practice mode enhanced 2024-06-03 21:05:04 +02:00
4 changed files with 311 additions and 77 deletions

View File

@ -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>

View File

@ -680,6 +680,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 ebx\n");
__asm("push ecx\n");
__asm("lea ebx, [eax+0x1A5]\n"); //login status offset
__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("mov dword ptr [ebx], 0x00000000\n");
__asm("skip_remove_login:\n");
__asm("pop ecx\n");
__asm("pop ebx\n");
real_remove_fake_login();
}
static bool patch_favorite_categ(const char *game_dll_fn) {
DWORD dllSize = 0;
@ -722,6 +747,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
{

View File

@ -388,6 +388,7 @@ uint32_t g_hispeed = 0; // multiplier
uint32_t g_soflan_retry_hispeed = 0; //hispeed value that is temporary kept for quick retry on soflan songs
uint32_t g_hispeed_addr = 0;
uint32_t g_target_bpm = 0;
uint32_t g_default_bpm = 0; //used to rearm between credits
uint16_t *g_base_bpm_ptr = 0; //will point to g_low_bpm or g_hi_bpm according to mode
uint16_t g_low_bpm = 0;
uint16_t g_hi_bpm = 0;
@ -488,6 +489,16 @@ void compute_longest_bpm(){
g_longest_bpm = longest_bpm;
}
void (*real_rearm_hispeed)();
void hook_rearm_hispeed()
{
__asm("push eax\n");
__asm("mov eax, %0\n"::"m"(g_default_bpm):);
__asm("mov %0, eax\n":"=m"(g_target_bpm): :);
__asm("pop eax\n");
real_rearm_hispeed();
}
void (*real_set_hispeed)();
void hook_set_hispeed()
{
@ -678,7 +689,7 @@ void retry_soflan_reset()
real_leave_options();
}
bool patch_hispeed_auto(uint8_t mode, uint16_t default_bpm)
bool patch_hispeed_auto(uint8_t mode)
{
DWORD dllSize = 0;
char *data = getDllData(g_game_dll_fn, &dllSize);
@ -689,7 +700,22 @@ bool patch_hispeed_auto(uint8_t mode, uint16_t default_bpm)
else if (mode == 3)
g_base_bpm_ptr = &g_longest_bpm;
g_target_bpm = default_bpm;
g_target_bpm = g_default_bpm;
/* reset target to default bpm at the end of a credit */
{
int64_t pattern_offset = search(data, dllSize, "\x8B\x10\x8B\xC8\x8B\x42\x28\xFF\xE0\xCC", 10, 0);
if (pattern_offset == -1) {
LOG("WARNING: popnhax: auto hi-speed: cannot find playerdata clean function\n");
return false;
} else {
uint64_t patch_addr = (int64_t)data + pattern_offset;
MH_CreateHook((LPVOID)(patch_addr), (LPVOID)hook_rearm_hispeed,
(void **)&real_rearm_hispeed);
}
}
/* retrieve hi-speed address */
{
int64_t pattern_offset = search(data, dllSize, "\x66\x89\x0C\x07\x0F\xB6\x45\x04", 8, 0);
@ -903,6 +929,9 @@ void quickexit_option_screen_cleanup()
}
}
uint32_t loadnew2dx_func;
uint32_t playgeneralsound_func;
char *g_system2dx_filepath;
uint32_t g_addr_icca;
void (*real_option_screen)();
void quickexit_option_screen()
@ -952,6 +981,8 @@ reload:
real_option_screen();
}
uint8_t g_srambypass = 0;
void (*real_option_screen_later)();
void backtosongselect_option_screen()
{
@ -969,11 +1000,60 @@ void backtosongselect_option_screen()
g_return_to_song_select = true;
g_return_to_song_select_num9 = true;
/* reload correct .2dx file to get correct generalSounds */
__asm("push eax\n");
__asm("push ecx\n");
__asm("push edx\n");
__asm("push %0\n"::"m"(g_system2dx_filepath));
__asm("call %0\n"::"D"(loadnew2dx_func));
__asm("add esp, 4\n");
/* play exit sound */
__asm("push 0\n");
__asm("push 0x19\n");
__asm("call %0\n"::"D"(playgeneralsound_func));
__asm("add esp, 8\n");
/* set srambypass flag */
__asm("mov %0, 1\n":"=m"(g_srambypass):);
__asm("pop edx\n");
__asm("pop ecx\n");
__asm("pop eax\n");
__asm("exit_back_select:\n");
real_option_screen_later();
}
void (*real_backtosongselect_herewego1)();
void backtosongselect_herewego1()
{
__asm("cmp %0, 1\n"::"m"(g_srambypass));
__asm("jne skip_disable_herewego1\n");
__asm("mov %0, 0\n":"=m"(g_srambypass):);
__asm("xor eax, eax\n");
__asm("skip_disable_herewego1:\n");
real_backtosongselect_herewego1();
}
void (*real_backtosongselect_herewego2)();
void backtosongselect_herewego2()
{
__asm("cmp %0, 1\n"::"m"(g_srambypass));
__asm("jne skip_disable_herewego2\n");
__asm("mov %0, 0\n":"=m"(g_srambypass):);
__asm("xor eax, eax\n");
__asm("skip_disable_herewego2:\n");
real_backtosongselect_herewego2();
}
void (*real_backtosongselect_herewego3)();
void backtosongselect_herewego3()
{
__asm("cmp %0, 1\n"::"m"(g_srambypass));
__asm("jne skip_disable_herewego3\n");
__asm("mov %0, 0\n":"=m"(g_srambypass):);
__asm("xor eax, eax\n");
__asm("skip_disable_herewego3:\n");
real_backtosongselect_herewego3();
}
void (*real_backtosongselect_option_screen_auto_leave)();
void backtosongselect_option_screen_auto_leave()
{
@ -1003,6 +1083,24 @@ void backtosongselect_option_yellow()
g_return_to_song_select = true;
g_return_to_song_select_num9 = true;
/* reload correct .2dx file to get correct generalSounds */
__asm("push eax\n");
__asm("push ecx\n");
__asm("push edx\n");
__asm("push %0\n"::"m"(g_system2dx_filepath));
__asm("call %0\n"::"D"(loadnew2dx_func));
__asm("add esp, 4\n");
/* play exit sound */
__asm("push 0\n");
__asm("push 0x19\n");
__asm("call %0\n"::"D"(playgeneralsound_func));
__asm("add esp, 8\n");
/* set srambypass flag */
__asm("mov %0, 1\n":"=m"(g_srambypass):);
__asm("pop edx\n");
__asm("pop ecx\n");
__asm("pop eax\n");
__asm("exit_back_select_yellow:\n");
real_option_screen_yellow();
}
@ -1099,9 +1197,9 @@ void save_recSPflags() {
recbinArray_writing[1].button = (uint8_t)~recbinArray_writing[0].button;
recbinArray_writing[1].flag = (uint8_t)~recbinArray_writing[0].flag;
uint16_t *button_no = *(uint16_t **)button_addr;
uint16_t *button_no = *(uint16_t **)button_addr;
uint8_t bt00 = *button_no;
uint32_t bt14 = 0;
uint32_t bt14 = 0;
uint32_t bt58 = 0;
uint32_t i = 0;
do
@ -1121,8 +1219,8 @@ void save_recSPflags() {
printf("bt00(%02x) bt14(%08X) bt58(%08X)\n", bt00, bt14, bt58);
recbinArray_writing[1].pad[0] = bt00;
recbinArray_writing[1].timing = bt14;
recbinArray_writing[1].recid = bt58;
recbinArray_writing[1].timing = bt14;
recbinArray_writing[1].recid = bt58;
/* .rec file format
random,timing,gauge,guide_se,speed,(00),(00),bt_0-bt_8
*/
@ -1309,6 +1407,19 @@ void quickexit_result_loop()
}
g_return_to_options = true; //transition screen hook will catch it
/* play sound fx (retry song) */
__asm("push eax\n");
__asm("push ecx\n");
__asm("push edx\n");
__asm("mov eax, 0x1F\n"); //"exit menu" sound fx
__asm("push 0\n");
__asm("call %0\n"::"D"(playsramsound_func));
__asm("add esp, 4\n");
__asm("pop edx\n");
__asm("pop ecx\n");
__asm("pop eax\n");
__asm("jmp call_real_result\n");
__asm("quit_session:\n");
@ -1320,6 +1431,18 @@ void quickexit_result_loop()
__asm("mov ebx, %0\n": :"b"(g_transition_addr));
__asm("mov dword ptr[ebx], 0xFFFFFFFC\n"); //quit session
/* play sound fx (end session) */
__asm("push eax\n");
__asm("push ecx\n");
__asm("push edx\n");
__asm("mov eax, 0x09\n"); //"bring menu" sound fx
__asm("push 0\n");
__asm("call %0\n"::"D"(playsramsound_func));
__asm("add esp, 4\n");
__asm("pop edx\n");
__asm("pop ecx\n");
__asm("pop eax\n");
/* ----------- r2nk226 ----------- */
disp = false; // 8.9 message off
speed = 5;
@ -3297,6 +3420,59 @@ static bool patch_quick_retire(bool pfree)
if (config.back_to_song_select)
{
char filepath[64];
if (sprintf(filepath, "/data/sd/system/system%d/system%d.2dx", config.game_version, config.game_version) <= 0){
LOG("popnhax: back to song select: cannot build systemxx.2dx filepath string.\n");
return false;
}
g_system2dx_filepath = strdup(filepath);
if (g_system2dx_filepath == NULL){
LOG("popnhax: back to song select: cannot allocate systemxx.2dx filepath string.\n");
return false;
}
{
// loadnew2dx func
int64_t pattern_offset = search(data, dllSize,
"\x53\x55\x8B\x6C\x24\x0C\x56\x57\x8B\xCD", 10, 0);
if (pattern_offset == -1) {
LOG("popnhax: loadnew2dx_addr was not found.\n");
return false;
}
loadnew2dx_func = (uint32_t)((int64_t)data + pattern_offset);
}
{
// playgeneralsound func
int64_t pattern_offset = search(data, dllSize,
"\x33\xC0\x5B\xC3\xCC\xCC\xCC\xCC\xCC\x55\x8B\xEC\x83\xE4\xF8", 15, 0);
if (pattern_offset == -1) {
LOG("popnhax: playgeneralsound_addr was not found.\n");
return false;
}
playgeneralsound_func = (uint32_t)((int64_t)data + pattern_offset + 9);
}
/* prevent "here we go" sound from playing when going back to song select (3 occurrences) */
{
LPVOID hook[3] = { (LPVOID)backtosongselect_herewego1, (LPVOID)backtosongselect_herewego2, (LPVOID)backtosongselect_herewego3 };
void** real[3] = { (void**)&real_backtosongselect_herewego1, (void**)&real_backtosongselect_herewego2, (void**)&real_backtosongselect_herewego3 };
int64_t pattern_offset = 0;
int i = 0;
do {
pattern_offset = search(data, dllSize-pattern_offset-10, "\x6A\x00\xB8\x17\x00\x00\x00\xE8", 8, pattern_offset+10);
if (pattern_offset == -1) {
LOG("popnhax: cannot find \"here we go\" sound play (occurrence %d).\n",i+1);
} else {
uint64_t patch_addr = (int64_t)data + pattern_offset + 7;
MH_CreateHook((LPVOID)patch_addr, hook[i],real[i]);
i++;
}
} while (i < 3 && pattern_offset != -1);
}
/* go back to song select with numpad 9 on song option screen (before pressing yellow) */
{
int64_t pattern_offset = search(data, dllSize, "\x0A\x00\x00\x83\x78\x34\x00\x75\x3D\xB8", 10, 0); //unilab
@ -4933,11 +5109,11 @@ void rec_id_check() {
__asm("mov byte ptr [esi+0x60], cl\n"); // save long_judge
__asm("id_match_end:\n");
__asm("cmp cl, 0\n");
__asm("cmp cl, 0\n");
__asm("setne al\n");
__asm("rec_id_nomatch:\n");
__asm("pop ebp\n");
__asm("rec_id_nomatch:\n");
__asm("pop ebp\n");
__asm("pop ecx\n");
}
@ -5704,8 +5880,8 @@ void chart_rewrite() {
double mul = 0;
double mul_2dx =0;
uint32_t i, size;
struct CHART* chart_temp;
uint32_t i, size;
struct CHART* chart_temp;
size = sizeof(struct CHART) * chart_rows_count;
chart_temp = (struct CHART*)malloc(size);
@ -5722,7 +5898,7 @@ void chart_rewrite() {
mul = (double)(100/((double)new_speed));
mul_2dx = (double)(((double)new_speed)/100);
for (i = 0; i < chart_rows_count; i++) {
for (i = 0; i < chart_rows_count; i++) {
chart_temp[i].timestamp = (uint32_t)((double)chart_temp[i].timestamp*mul);
if (chart_temp[i].duration > 0) {
chart_temp[i].duration = (uint32_t)((double)chart_temp[i].duration*mul);
@ -5746,11 +5922,11 @@ void chart_rewrite() {
LOG("popnhax: chart_temp_addr is 0x%p\n", chart_temp);
#endif
free(chart_temp);
free(chart_temp);
chart_speed_end:
use_sp_flag = true;
LOG("popnhax: chart speed change done.\n");
LOG("popnhax: chart speed change done.\n");
#if DEBUG == 1
LOG("popnhax: chart mul is %f\n", mul);
@ -7919,7 +8095,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
if (config.hispeed_auto)
{
patch_hispeed_auto(config.hispeed_auto, config.hispeed_default_bpm);
g_default_bpm = config.hispeed_default_bpm;
patch_hispeed_auto(config.hispeed_auto);
}
#if DEBUG == 1

View File

@ -850,9 +850,29 @@ static char *get_subcateg_title(const char* path) {
return categ_name;
}
static bool is_excluded_folder(const char *input_filename)
#define F_OK 0
static bool is_excluded_folder(const char *path)
{
return (input_filename[strlen("data_mods/")] == '_');
char filename[64];
//try to open "folderpath/_exclude"
size_t len = (size_t)(strchr(path+10, '\\')-(path));
strncpy(filename, path, len);
sprintf(filename+len, "\\_exclude");
if (access(filename, F_OK) == 0)
{
LOG("%s causes folder to be excluded from customs (contents will be treated as regular songs)\n", filename);
return true;
}
if ( path[strlen("data_mods/")] == '_' )
{
filename[strchr(path+10, '\\')-path] = '\0';
LOG("%s starting with _ causes folder to be excluded from customs (contents will be treated as regular songs)\n", filename);
return true;
}
return false;
}
void parse_musicdb(const char *input_filename, const char *target, struct popnhax_config *config) {
@ -861,9 +881,11 @@ void parse_musicdb(const char *input_filename, const char *target, struct popnha
return;
}
bool excluded = (config->custom_categ && is_excluded_folder(input_filename));
char *subcateg_title = NULL;
subcategory_s *subcateg = NULL;
if (config->custom_categ == 2)
if (config->custom_categ == 2 && !excluded)
{
subcateg_title = get_subcateg_title(input_filename);
subcateg = get_subcateg(subcateg_title); //will return a new one if not found
@ -910,7 +932,7 @@ void parse_musicdb(const char *input_filename, const char *target, struct popnha
// Update customs/omni songid list
if ( is_fresh || is_gone || config->partial_entries )
{
if ( idx >= config->custom_categ_min_songid && bst_search(g_customs_bst, idx) == NULL )
if ( idx >= config->custom_categ_min_songid && !excluded && bst_search(g_customs_bst, idx) == NULL )
{
g_customs_bst = bst_insert(g_customs_bst, idx);
//LOG("%d inserted into customs bst\n", idx);
@ -918,8 +940,6 @@ void parse_musicdb(const char *input_filename, const char *target, struct popnha
{
add_song_to_subcateg(idx, subcateg);
}
} else {
//LOG("%d already present in customs bst\n", idx);
}
}
@ -979,7 +999,7 @@ void parse_musicdb(const char *input_filename, const char *target, struct popnha
if ( config->custom_categ
&& config->custom_exclude_from_version
&& !is_excluded_folder(input_filename)
&& !excluded
&& idx >= config->custom_categ_min_songid
&& ( is_fresh || config->exclude_omni ) )
{
@ -1063,7 +1083,7 @@ void parse_musicdb(const char *input_filename, const char *target, struct popnha
free(config_xml);
if (config->custom_categ == 2)
if (config->custom_categ == 2 && !excluded)
{
free(subcateg_title);
}