different favorite files per game version

This commit is contained in:
CrazyRedMachine 2024-04-29 22:31:32 +02:00
parent f0daa9e761
commit 0b88b1253d
4 changed files with 133 additions and 129 deletions

View File

@ -4,6 +4,7 @@
#include <stdbool.h> #include <stdbool.h>
struct popnhax_config { struct popnhax_config {
uint8_t game_version;
bool practice_mode; bool practice_mode;
bool hidden_is_offset; bool hidden_is_offset;
bool iidx_hard_gauge; bool iidx_hard_gauge;

View File

@ -19,6 +19,7 @@
#include "minhook/hde32.h" #include "minhook/hde32.h"
#include "minhook/include/MinHook.h" #include "minhook/include/MinHook.h"
uint8_t g_game_version;
uint32_t g_playerdata_ptr_addr; //pointer to the playerdata memory zone (offset 0x08 is popn friend ID as ascii (12 char long), offset 0x1A5 is "is logged in" flag) uint32_t g_playerdata_ptr_addr; //pointer to the playerdata memory zone (offset 0x08 is popn friend ID as ascii (12 char long), offset 0x1A5 is "is logged in" flag)
char *g_current_friendid; char *g_current_friendid;
uint32_t g_current_songid; uint32_t g_current_songid;
@ -56,37 +57,37 @@ void add_song_to_favorites()
{ {
favorites = (uint32_t *) realloc(favorites, sizeof(uint32_t)*(favorites_count+5)); favorites = (uint32_t *) realloc(favorites, sizeof(uint32_t)*(favorites_count+5));
favorites[favorites_count++] = g_current_songid | 0x00060000; // game wants this otherwise only easy difficulty will appear favorites[favorites_count++] = g_current_songid | 0x00060000; // game wants this otherwise only easy difficulty will appear
return; return;
} }
void remove_song_from_favorites() void remove_song_from_favorites()
{ {
for (uint32_t i = 0; i < favorites_count; i++) for (uint32_t i = 0; i < favorites_count; i++)
{ {
if ( g_current_songid == (favorites[i] & 0x0000FFFF) ) if ( g_current_songid == (favorites[i] & 0x0000FFFF) )
{ {
for (uint32_t j = i+1; j < favorites_count; j++) for (uint32_t j = i+1; j < favorites_count; j++)
{ {
favorites[j-1] = favorites[j]; favorites[j-1] = favorites[j];
} }
favorites_count--; favorites_count--;
return; return;
} }
} }
return; return;
} }
void prepare_favorite_list(){ void prepare_favorite_list(){
char fav_filepath[64]; char fav_filepath[64];
sprintf(fav_filepath, "data_mods\\%s.fav", g_current_friendid); sprintf(fav_filepath, "data_mods\\%d.%s.fav", g_game_version, g_current_friendid);
FILE *file = fopen(fav_filepath, "rb"); FILE *file = fopen(fav_filepath, "rb");
favorites_count = 0; favorites_count = 0;
if ( file == NULL ) if ( file == NULL )
{ {
return; return;
} }
char line[32]; char line[32];
@ -94,97 +95,97 @@ void prepare_favorite_list(){
/* note that fgets don't strip the terminating \n, checking its /* note that fgets don't strip the terminating \n, checking its
presence would allow to handle lines longer that sizeof(line) */ presence would allow to handle lines longer that sizeof(line) */
int songid = strtol(line, NULL, 10); int songid = strtol(line, NULL, 10);
if ( songid != 0 ) if ( songid != 0 )
{ {
g_current_songid = songid; g_current_songid = songid;
add_song_to_favorites(); add_song_to_favorites();
} }
} }
fclose(file); fclose(file);
//printf("added %d songs from %s to favorites\n",favorites_count,fav_filepath); //printf("added %d songs from %s to favorites\n",favorites_count,fav_filepath);
return; return;
} }
void commit_favorites() void commit_favorites()
{ {
if ( favorites_count == 0 ) if ( favorites_count == 0 )
return; return;
char fav_filepath[64]; char fav_filepath[64];
sprintf(fav_filepath, "data_mods\\%s.fav", g_current_friendid); sprintf(fav_filepath, "data_mods\\%d.%s.fav", g_game_version, g_current_friendid);
FILE *file = fopen(fav_filepath, "w"); FILE *file = fopen(fav_filepath, "w");
if ( file == NULL ) if ( file == NULL )
{ {
return; return;
} }
for (uint32_t i = 0; i < favorites_count; i++) for (uint32_t i = 0; i < favorites_count; i++)
{ {
fprintf(file, "%d\n", (favorites[i] & 0x0000FFFF)); fprintf(file, "%d\n", (favorites[i] & 0x0000FFFF));
} }
fclose(file); fclose(file);
return; return;
} }
void (*real_song_is_in_favorite)(); void (*real_song_is_in_favorite)();
void hook_song_is_in_favorite() void hook_song_is_in_favorite()
{ {
__asm("push ecx\n"); __asm("push ecx\n");
__asm("push edx\n"); __asm("push edx\n");
//dx contains songid //dx contains songid
__asm("mov _g_current_songid, dx\n"); __asm("mov _g_current_songid, dx\n");
for (uint32_t i = 0; i < favorites_count; i++) for (uint32_t i = 0; i < favorites_count; i++)
{ {
if ( g_current_songid == (favorites[i] & 0x0000FFFF) ) if ( g_current_songid == (favorites[i] & 0x0000FFFF) )
{ {
__asm("pop edx\n"); __asm("pop edx\n");
__asm("pop ecx\n"); __asm("pop ecx\n");
__asm("pop ebx\n"); __asm("pop ebx\n");
__asm("mov eax, 0x01\n"); __asm("mov eax, 0x01\n");
__asm("ret\n"); __asm("ret\n");
} }
} }
__asm("pop edx\n"); __asm("pop edx\n");
__asm("pop ecx\n"); __asm("pop ecx\n");
__asm("pop ebx\n"); __asm("pop ebx\n");
__asm("mov eax, 0x00\n"); __asm("mov eax, 0x00\n");
__asm("ret\n"); __asm("ret\n");
} }
void (*real_add_to_favorite)(); void (*real_add_to_favorite)();
void hook_add_to_favorite() void hook_add_to_favorite()
{ {
__asm("push ecx\n"); __asm("push ecx\n");
//dx contains songid //dx contains songid
__asm("mov _g_current_songid, dx\n"); __asm("mov _g_current_songid, dx\n");
add_song_to_favorites(); add_song_to_favorites();
commit_favorites(); commit_favorites();
__asm("mov eax, [_favorites_count]\n"); __asm("mov eax, [_favorites_count]\n");
__asm("mov edx, _g_current_songid\n"); __asm("mov edx, _g_current_songid\n");
__asm("pop ecx\n"); __asm("pop ecx\n");
real_add_to_favorite(); real_add_to_favorite();
} }
void (*real_remove_from_favorite)(); void (*real_remove_from_favorite)();
void hook_remove_from_favorite() void hook_remove_from_favorite()
{ {
//code pushes edi, esi and ebx as well //code pushes edi, esi and ebx as well
__asm("push ecx\n"); __asm("push ecx\n");
__asm("push edx\n"); __asm("push edx\n");
//dx contains songid //dx contains songid
__asm("mov _g_current_songid, cx\n"); __asm("mov _g_current_songid, cx\n");
remove_song_from_favorites(); remove_song_from_favorites();
commit_favorites(); commit_favorites();
__asm("pop edx\n"); __asm("pop edx\n");
__asm("pop ecx\n"); __asm("pop ecx\n");
real_remove_from_favorite(); real_remove_from_favorite();
} }
//this replaces the category handling function ( add_song_in_list is a subroutine called by the game ) //this replaces the category handling function ( add_song_in_list is a subroutine called by the game )
@ -585,7 +586,7 @@ void hook_song_printf()
__asm("ja print_regular_song\n"); __asm("ja print_regular_song\n");
__asm("print_custom_song:\n"); __asm("print_custom_song:\n");
__asm("lea eax, [esp+0x08]\n"); __asm("lea eax, [esp+0x08]\n");
__asm("mov ebx, _g_customformat\n"); __asm("mov ebx, _g_customformat\n");
__asm("mov [eax], ebx\n"); __asm("mov [eax], ebx\n");
@ -610,7 +611,7 @@ void hook_artist_printf()
__asm("ja print_regular_artist\n"); __asm("ja print_regular_artist\n");
__asm("print_custom_artist:\n"); __asm("print_custom_artist:\n");
__asm("lea eax, [esp+0x08]\n"); __asm("lea eax, [esp+0x08]\n");
__asm("mov ebx, _g_customformat\n"); __asm("mov ebx, _g_customformat\n");
__asm("mov [eax], ebx\n"); __asm("mov [eax], ebx\n");
@ -639,7 +640,7 @@ static bool patch_custom_track_format(const char *game_dll_fn) {
(void **)&real_song_printf); (void **)&real_song_printf);
} }
//hook format string for artist //hook format string for artist
{ {
int64_t pattern_offset = search(data, dllSize, "\x83\xC4\x08\x33\xFF\x8B\x43\x0C\x8B\x70\x04\x83\xC0\x04", 14, 0); int64_t pattern_offset = search(data, dllSize, "\x83\xC4\x08\x33\xFF\x8B\x43\x0C\x8B\x70\x04\x83\xC0\x04", 14, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
@ -684,8 +685,8 @@ static bool patch_favorite_categ(const char *game_dll_fn) {
uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x05 + 0x5A); uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x05 + 0x5A);
uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01)); uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01));
uint64_t function_addr = function_call_addr+5+function_offset; uint64_t function_addr = function_call_addr+5+function_offset;
MH_CreateHook((LPVOID)function_addr, (LPVOID)categ_inject_favorites, MH_CreateHook((LPVOID)function_addr, (LPVOID)categ_inject_favorites,
(void **)&real_categ_favorite); (void **)&real_categ_favorite);
} }
//categ_inject_favorites will need to force "logged in" status (for result screen) //categ_inject_favorites will need to force "logged in" status (for result screen)
@ -964,37 +965,6 @@ static void load_databases() {
} }
LOG("\n"); LOG("\n");
} }
/*
bool load_favorites(){
favorites_count = subcategories[0].size;
favorites = subcategories[0].songlist;
return true;
}*/
bool load_favorites(){
FILE *file = fopen("data_mods\\default.fav", "rb");
if (file == NULL)
{
return false;
}
char line[32];
while (fgets(line, sizeof(line), file)) {
/* note that fgets don't strip the terminating \n, checking its
presence would allow to handle lines longer that sizeof(line) */
int songid = strtol(line, NULL, 10);
if ( songid != 0 )
{
favorites = (uint32_t *) realloc(favorites, sizeof(uint32_t)*(favorites_count+5));
favorites[favorites_count++] = songid | 0x00060000; // game wants this otherwise only easy difficulty will appear
}
}
fclose(file);
LOG("added %d songs to favorites\n",favorites_count);
return true;
}
void (*real_getversion)(); void (*real_getversion)();
void hook_getversion() void hook_getversion()
@ -1048,13 +1018,13 @@ bool patch_exclude(const char *game_dll_fn)
uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x07); uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x07);
uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01)); uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01));
uint64_t function_addr = function_call_addr+5+function_offset; uint64_t function_addr = function_call_addr+5+function_offset;
MH_CreateHook((LPVOID)function_addr, (LPVOID)hook_getversion, MH_CreateHook((LPVOID)function_addr, (LPVOID)hook_getversion,
(void **)&real_getversion); (void **)&real_getversion);
} }
/* /*
//exclude from CS version category too //exclude from CS version category too
{ {
int64_t pattern_offset = search(data, dllSize, "\xB8\x13\x05\x00\x00\x66\x3B\xF0", 8, 0); int64_t pattern_offset = search(data, dllSize, "\xB8\x13\x05\x00\x00\x66\x3B\xF0", 8, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
LOG("popnhax: exclude_customs: cannot find getCSVersion calling function\n"); LOG("popnhax: exclude_customs: cannot find getCSVersion calling function\n");
@ -1064,13 +1034,13 @@ bool patch_exclude(const char *game_dll_fn)
uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x0C); uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x0C);
uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01)); uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01));
uint64_t function_addr = function_call_addr+5+function_offset; uint64_t function_addr = function_call_addr+5+function_offset;
MH_CreateHook((LPVOID)function_addr, (LPVOID)hook_getcsversion, MH_CreateHook((LPVOID)function_addr, (LPVOID)hook_getcsversion,
(void **)&real_getcsversion); (void **)&real_getcsversion);
}*/ }*/
LOG("popnhax: exclude_customs: Custom songs excluded from version listings\n"); LOG("popnhax: exclude_customs: Custom songs excluded from version listings\n");
return true; return true;
} }
bool patch_custom_categs(const char *dllFilename, struct popnhax_config *config) bool patch_custom_categs(const char *dllFilename, struct popnhax_config *config)
@ -1106,8 +1076,8 @@ LOG("custom title format is %s\n", g_customformat);
return patch_custom_categ(dllFilename); return patch_custom_categ(dllFilename);
} }
bool patch_local_favorites(const char *dllFilename) bool patch_local_favorites(const char *dllFilename, uint8_t version)
{ {
//load_favorites(); g_game_version = version;
return patch_favorite_categ(dllFilename); return patch_favorite_categ(dllFilename);
} }

View File

@ -5,6 +5,6 @@
#include "popnhax/config.h" #include "popnhax/config.h"
bool patch_custom_categs(const char *dllFilename, struct popnhax_config *config); bool patch_custom_categs(const char *dllFilename, struct popnhax_config *config);
bool patch_local_favorites(const char *dllFilename); bool patch_local_favorites(const char *dllFilename, uint8_t version);
#endif #endif

View File

@ -5303,6 +5303,22 @@ static bool option_net_ojama_off(){
return true; return true;
} }
uint8_t get_version()
{
DWORD dllSize = 0;
char *data = getDllData(g_game_dll_fn, &dllSize);
{
int64_t pattern_offset = search(data, dllSize, "\x00\x8B\x56\x04\x0F\xB7\x02\xE8", 8, 0);
if (pattern_offset == -1) {
LOG("popnhax: get_version: cannot retrieve game version (eclale or less?)\n");
return 0;
}
uint8_t version = *(uint8_t*)(data + pattern_offset + 14);
return version;
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) { switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH: { case DLL_PROCESS_ATTACH: {
@ -5374,7 +5390,9 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
free(tmp_name); free(tmp_name);
} }
LOG("popnhax: game dll: %s\n",g_game_dll_fn); uint8_t game_version = get_version();
LOG("popnhax: game dll: %s (popn%d)\n",g_game_dll_fn, game_version);
LOG("popnhax: config file: %s\n",g_config_fn); LOG("popnhax: config file: %s\n",g_config_fn);
if (!_load_config(g_config_fn, &config, config_psmap)) if (!_load_config(g_config_fn, &config, config_psmap))
@ -5383,12 +5401,15 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
return FALSE; return FALSE;
} }
config.game_version = game_version;
if (force_trans_debug) if (force_trans_debug)
config.translation_debug = true; config.translation_debug = true;
if (force_no_omni) if (force_no_omni)
config.patch_db = false; config.patch_db = false;
if (!config.disable_multiboot) if (!config.disable_multiboot)
{ {
/* automatically force datecode based on dll name when applicable (e.g. popn22_2022061300.dll and no force_datecode) */ /* automatically force datecode based on dll name when applicable (e.g. popn22_2022061300.dll and no force_datecode) */
@ -5398,21 +5419,26 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
LOG("popnhax: multiboot autotune activated (custom game dll, force_datecode off)\n"); LOG("popnhax: multiboot autotune activated (custom game dll, force_datecode off)\n");
memcpy(config.force_datecode, g_game_dll_fn+7, 10); memcpy(config.force_datecode, g_game_dll_fn+7, 10);
LOG("popnhax: multiboot: auto set datecode to %s\n", config.force_datecode); LOG("popnhax: multiboot: auto set datecode to %s\n", config.force_datecode);
if (config.score_challenge && ( strcmp(config.force_datecode,"2020092800") <= 0 ) ) if (config.score_challenge && ( config.game_version < 26 || strcmp(config.force_datecode,"2020092800") <= 0 ) )
{ {
LOG("popnhax: multiboot: auto disable score challenge patch (already ingame)\n"); LOG("popnhax: multiboot: auto disable score challenge patch (already ingame)\n");
config.score_challenge = false; config.score_challenge = false;
} }
if (config.patch_db && ( strcmp(config.force_datecode,"2016121400") < 0 ) ) if (config.patch_db && ( config.game_version == 0 || strcmp(config.force_datecode,"2016121400") < 0 ) )
{ {
LOG("popnhax: multiboot: auto disable omnimix patch (not compatible)\n"); LOG("popnhax: multiboot: auto disable omnimix patch (not compatible)\n");
config.patch_db = false; config.patch_db = false;
} }
if (config.guidese_off && ( strcmp(config.force_datecode,"2016121400") < 0 ) ) if (config.guidese_off && ( config.game_version == 0 || strcmp(config.force_datecode,"2016121400") < 0 ) )
{ {
LOG("popnhax: multiboot: auto disable Guide SE patch (not compatible)\n"); LOG("popnhax: multiboot: auto disable Guide SE patch (not compatible)\n");
config.guidese_off = false; config.guidese_off = false;
} }
if (config.local_favorites && ( config.game_version == 0 || strcmp(config.force_datecode,"2016121400") < 0 ) )
{
LOG("popnhax: multiboot: auto disable local favorites patch (not compatible)\n");
config.local_favorites = false;
}
} }
} }
@ -5616,7 +5642,14 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
} }
if (config.local_favorites) if (config.local_favorites)
patch_local_favorites(g_game_dll_fn); {
if ( config.game_version == 0 )
{
LOG("popnhax: local_favorites: patch is not compatible with your game version.\n");
} else {
patch_local_favorites(g_game_dll_fn, config.game_version);
}
}
if (config.force_full_opt) if (config.force_full_opt)
option_full(); option_full();