forked from Popn_Tools/popnhax
cleanup, expose options
This commit is contained in:
parent
5f2a9d7bc0
commit
46ec71b83b
6
dist/popnhax/popnhax.xml
vendored
6
dist/popnhax/popnhax.xml
vendored
@ -5,6 +5,8 @@
|
|||||||
<patch_db __type="bool">0</patch_db>
|
<patch_db __type="bool">0</patch_db>
|
||||||
<!-- Force unlock music, charts, characters, and deco parts when applicable -->
|
<!-- Force unlock music, charts, characters, and deco parts when applicable -->
|
||||||
<force_unlocks __type="bool">0</force_unlocks>
|
<force_unlocks __type="bool">0</force_unlocks>
|
||||||
|
<!-- Put customs into their own category (0: no, 1: simple category with all customs, 2: subcategories by folder name) -->
|
||||||
|
<custom_categ __type="u8">0</custom_categ>
|
||||||
|
|
||||||
<!-- Classic patches -->
|
<!-- Classic patches -->
|
||||||
<!-- Prevent crash on boot when using a different default audio source (aka HDMI audio patch) -->
|
<!-- Prevent crash on boot when using a different default audio source (aka HDMI audio patch) -->
|
||||||
@ -132,6 +134,10 @@
|
|||||||
<disable_expansions __type="bool">0</disable_expansions>
|
<disable_expansions __type="bool">0</disable_expansions>
|
||||||
<!-- Copy the new table information over top the old tables (automatically enables disable_expansions) -->
|
<!-- Copy the new table information over top the old tables (automatically enables disable_expansions) -->
|
||||||
<disable_redirection __type="bool">0</disable_redirection>
|
<disable_redirection __type="bool">0</disable_redirection>
|
||||||
|
<!-- minimum songid for a song to be seen as "custom" (inclusive) -->
|
||||||
|
<custom_categ_min_songid __type="u16">4000</custom_categ_min_songid>
|
||||||
|
<!-- maximum songid for a song to be seen as "custom" (0 = no limit) -->
|
||||||
|
<custom_categ_max_songid __type="u16">0</custom_categ_max_songid>
|
||||||
|
|
||||||
<!-- Translation -->
|
<!-- Translation -->
|
||||||
<!-- Disable .dict string replacements and .ips patches -->
|
<!-- Disable .dict string replacements and .ips patches -->
|
||||||
|
@ -14,6 +14,9 @@ struct popnhax_config {
|
|||||||
bool quick_retire;
|
bool quick_retire;
|
||||||
bool back_to_song_select;
|
bool back_to_song_select;
|
||||||
bool score_challenge;
|
bool score_challenge;
|
||||||
|
uint8_t custom_categ;
|
||||||
|
uint16_t custom_categ_min_songid;
|
||||||
|
uint16_t custom_categ_max_songid;
|
||||||
bool force_hd_timing;
|
bool force_hd_timing;
|
||||||
uint8_t force_hd_resolution;
|
uint8_t force_hd_resolution;
|
||||||
bool force_unlocks;
|
bool force_unlocks;
|
||||||
|
@ -19,9 +19,8 @@
|
|||||||
#include "minhook/hde32.h"
|
#include "minhook/hde32.h"
|
||||||
#include "minhook/include/MinHook.h"
|
#include "minhook/include/MinHook.h"
|
||||||
|
|
||||||
uint8_t g_subcateg_count = 3;
|
uint32_t g_min_id = 4000;
|
||||||
uint32_t **subcategs;
|
uint32_t g_max_id = 0;
|
||||||
char **subcateg_names;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *name;
|
char *name;
|
||||||
@ -30,7 +29,7 @@ typedef struct {
|
|||||||
} subcategory_s;
|
} subcategory_s;
|
||||||
|
|
||||||
subcategory_s* subcategories;
|
subcategory_s* subcategories;
|
||||||
uint32_t subcateg_count = 0;
|
uint32_t g_subcateg_count = 0;
|
||||||
|
|
||||||
struct property *load_prop_file(const char *filename);
|
struct property *load_prop_file(const char *filename);
|
||||||
|
|
||||||
@ -46,17 +45,19 @@ static bool subcateg_has_songid(uint32_t songid, subcategory_s* subcateg)
|
|||||||
|
|
||||||
static void add_song_to_subcateg(uint32_t songid, subcategory_s* subcateg)
|
static void add_song_to_subcateg(uint32_t songid, subcategory_s* subcateg)
|
||||||
{
|
{
|
||||||
if ( songid >= 3000 && !subcateg_has_songid(songid, subcateg) )
|
if ( songid >= g_min_id
|
||||||
|
&& (g_max_id == 0 || songid <= g_max_id)
|
||||||
|
&& !subcateg_has_songid(songid, subcateg) )
|
||||||
{
|
{
|
||||||
subcateg->songlist = (uint32_t *) realloc(subcateg->songlist, sizeof(uint32_t)*(++subcateg->size));
|
subcateg->songlist = (uint32_t *) realloc(subcateg->songlist, sizeof(uint32_t)*(++subcateg->size));
|
||||||
subcateg->songlist[subcateg->size-1] = songid;
|
subcateg->songlist[subcateg->size-1] = songid;
|
||||||
LOG("%s : %d (subcateg size %d)\n", subcateg->name, songid, subcateg->size);
|
subcateg->songlist[subcateg->size-1] |= 0x00060000; // game wants this otherwise only easy difficulty will appear
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static subcategory_s* get_subcateg(char *title)
|
static subcategory_s* get_subcateg(char *title)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < subcateg_count; i++)
|
for (uint32_t i = 0; i < g_subcateg_count; i++)
|
||||||
{
|
{
|
||||||
if (strcmp(title, subcategories[i].name) == 0)
|
if (strcmp(title, subcategories[i].name) == 0)
|
||||||
return &(subcategories[i]);
|
return &(subcategories[i]);
|
||||||
@ -118,7 +119,7 @@ void hook_event_categ_generation()
|
|||||||
__asm("mov ebx, [esp+0x2C]\n");
|
__asm("mov ebx, [esp+0x2C]\n");
|
||||||
__asm("mov _tmp_str_addr, ebx\n");
|
__asm("mov _tmp_str_addr, ebx\n");
|
||||||
|
|
||||||
for (uint32_t i = 0; i < subcateg_count; i++)
|
for (uint32_t i = 0; i < g_subcateg_count; i++)
|
||||||
{
|
{
|
||||||
if ( (uint32_t)subcategories[i].name == tmp_str_addr )
|
if ( (uint32_t)subcategories[i].name == tmp_str_addr )
|
||||||
{
|
{
|
||||||
@ -156,7 +157,7 @@ void (*reimpl_func_3)();
|
|||||||
void (*reimpl_func_4)();
|
void (*reimpl_func_4)();
|
||||||
|
|
||||||
//this is a reimplementation of the event category generation function, modded to use popnhax internal subcategories
|
//this is a reimplementation of the event category generation function, modded to use popnhax internal subcategories
|
||||||
void categ_inject_songlist_reimpl()
|
void categ_inject_songlist_subcategs()
|
||||||
{
|
{
|
||||||
__asm("add esp, 0xC"); // cancel a sub esp 0xC that is added by this code for no reason
|
__asm("add esp, 0xC"); // cancel a sub esp 0xC that is added by this code for no reason
|
||||||
__asm("push 0xFFFFFFFF\n");
|
__asm("push 0xFFFFFFFF\n");
|
||||||
@ -261,7 +262,7 @@ void categ_inject_songlist_reimpl()
|
|||||||
__asm("inc ebx\n");
|
__asm("inc ebx\n");
|
||||||
__asm("mov dword ptr ss:[esp+0x34], ebx\n");
|
__asm("mov dword ptr ss:[esp+0x34], ebx\n");
|
||||||
|
|
||||||
__asm("cmp ebx, [_subcateg_count]\n");
|
__asm("cmp ebx, [_g_subcateg_count]\n");
|
||||||
__asm("jb subcateg_loop\n");
|
__asm("jb subcateg_loop\n");
|
||||||
|
|
||||||
__asm("mov ecx, dword ptr ss:[esp+0x24]\n");
|
__asm("mov ecx, dword ptr ss:[esp+0x24]\n");
|
||||||
@ -276,7 +277,7 @@ void categ_inject_songlist_reimpl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//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 )
|
||||||
void categ_inject_songlist_impl()
|
void categ_inject_songlist_simple()
|
||||||
{
|
{
|
||||||
__asm("push edx\n");
|
__asm("push edx\n");
|
||||||
songlist_struct.array_start = (uint32_t)&songlist;
|
songlist_struct.array_start = (uint32_t)&songlist;
|
||||||
@ -289,21 +290,23 @@ void categ_inject_songlist_impl()
|
|||||||
__asm("pop ecx\n");
|
__asm("pop ecx\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mask_applied = false;
|
|
||||||
|
|
||||||
void (*real_categ_reinit_songlist)();
|
void (*real_categ_reinit_songlist)();
|
||||||
void hook_categ_reinit_songlist()
|
void hook_categ_reinit_songlist()
|
||||||
{
|
{
|
||||||
songlist_count = 0;
|
songlist_count = 0;
|
||||||
mask_applied = false;
|
|
||||||
real_categ_reinit_songlist();
|
real_categ_reinit_songlist();
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*real_categ_build_songlist)();
|
void (*real_categ_build_songlist)();
|
||||||
void hook_categ_build_songlist()
|
void hook_categ_build_songlist()
|
||||||
{
|
{
|
||||||
__asm("cmp eax, 0xFA0\n");
|
__asm("cmp eax, _g_min_id\n");
|
||||||
__asm("jb categ_skip_add\n");
|
__asm("jb categ_skip_add\n");
|
||||||
|
__asm("cmp dword ptr _g_max_id, 0\n");
|
||||||
|
__asm("je add_my_song\n");
|
||||||
|
__asm("cmp eax, _g_max_id\n");
|
||||||
|
__asm("ja categ_skip_add\n");
|
||||||
|
__asm("add_my_song:\n");
|
||||||
__asm("push eax\n");
|
__asm("push eax\n");
|
||||||
__asm("push ebx\n");
|
__asm("push ebx\n");
|
||||||
__asm("mov eax, [_songlist_count]\n");
|
__asm("mov eax, [_songlist_count]\n");
|
||||||
@ -326,7 +329,7 @@ void apply_mask_to_all()
|
|||||||
__asm("mov _songid_mask, eax");
|
__asm("mov _songid_mask, eax");
|
||||||
__asm("pop eax");
|
__asm("pop eax");
|
||||||
songid_mask &= 0xFFFF0000;
|
songid_mask &= 0xFFFF0000;
|
||||||
for (uint32_t i = 0; i < subcateg_count; i++)
|
for (uint32_t i = 0; i < g_subcateg_count; i++)
|
||||||
{
|
{
|
||||||
for (uint32_t j = 0; j < subcategories[i].size; j++)
|
for (uint32_t j = 0; j < subcategories[i].size; j++)
|
||||||
{
|
{
|
||||||
@ -335,60 +338,6 @@ void apply_mask_to_all()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//cherche dans toutes mes categ où est la song que je veux
|
|
||||||
//et renvoie un pointeur dessus dans eax
|
|
||||||
uint32_t *return_value;
|
|
||||||
void put_song_addr_in_eax()
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < subcateg_count; i++)
|
|
||||||
{
|
|
||||||
for (uint32_t j = 0; j < subcategories[i].size; j++)
|
|
||||||
{
|
|
||||||
if (subcategories[i].songlist[j] == (songid_mask&0xFFFF))
|
|
||||||
{
|
|
||||||
return_value = &(subcategories[i].songlist[j]);
|
|
||||||
__asm("mov eax, [_return_value]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void hook_subcateg_adjust_songlist()
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
__asm("cmp eax, 0xFA0\n");
|
|
||||||
__asm("jb skip_mask\n");
|
|
||||||
|
|
||||||
__asm("push eax");
|
|
||||||
__asm("push ebx");
|
|
||||||
__asm("push ecx");
|
|
||||||
__asm("push edx");
|
|
||||||
|
|
||||||
__asm("push eax");
|
|
||||||
__asm("mov eax, [ebx]");
|
|
||||||
__asm("mov _songid_mask, eax");
|
|
||||||
__asm("pop eax");
|
|
||||||
//songid_mask contient le uint32_t complet
|
|
||||||
put_song_addr_in_eax();
|
|
||||||
__asm("mov ebx, _songid_mask");
|
|
||||||
__asm("mov [eax], ebx");
|
|
||||||
|
|
||||||
__asm("pop edx");
|
|
||||||
__asm("pop ecx");
|
|
||||||
__asm("pop ebx");
|
|
||||||
__asm("pop eax");
|
|
||||||
#else
|
|
||||||
__asm("cmp byte ptr [_mask_applied], 0\n");
|
|
||||||
__asm("jne skip_mask\n");
|
|
||||||
apply_mask_to_all();
|
|
||||||
mask_applied = true;
|
|
||||||
#endif
|
|
||||||
__asm("skip_mask:\n");
|
|
||||||
real_categ_build_songlist();
|
|
||||||
}
|
|
||||||
|
|
||||||
void (*real_categ_printf_call)();
|
void (*real_categ_printf_call)();
|
||||||
void (*real_categ_title_printf)();
|
void (*real_categ_title_printf)();
|
||||||
void hook_categ_title_printf()
|
void hook_categ_title_printf()
|
||||||
@ -402,7 +351,6 @@ void hook_categ_title_printf()
|
|||||||
real_categ_title_printf();
|
real_categ_title_printf();
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*categ_listing_event)();
|
|
||||||
void (*real_categ_listing)();
|
void (*real_categ_listing)();
|
||||||
void hook_categ_listing()
|
void hook_categ_listing()
|
||||||
{
|
{
|
||||||
@ -417,7 +365,7 @@ void hook_categ_listing()
|
|||||||
real_categ_listing();
|
real_categ_listing();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool patch_custom_categ_simple(const char *game_dll_fn) {
|
static bool patch_custom_categ(const char *game_dll_fn) {
|
||||||
|
|
||||||
DWORD dllSize = 0;
|
DWORD dllSize = 0;
|
||||||
char *data = getDllData(game_dll_fn, &dllSize);
|
char *data = getDllData(game_dll_fn, &dllSize);
|
||||||
@ -437,6 +385,7 @@ static bool patch_custom_categ_simple(const char *game_dll_fn) {
|
|||||||
(void **)&real_categ_title_printf);
|
(void **)&real_categ_title_printf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// patch category handling jumptable to add our processing
|
||||||
{
|
{
|
||||||
int64_t pattern_offset = search(data, dllSize, "\x83\xF8\x10\x77\x75\xFF\x24\x85", 8, 0);
|
int64_t pattern_offset = search(data, dllSize, "\x83\xF8\x10\x77\x75\xFF\x24\x85", 8, 0);
|
||||||
if (pattern_offset == -1) {
|
if (pattern_offset == -1) {
|
||||||
@ -445,12 +394,17 @@ static bool patch_custom_categ_simple(const char *game_dll_fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t patch_addr = (int64_t)data + pattern_offset + 0x05 + 0x75;
|
uint64_t patch_addr = (int64_t)data + pattern_offset + 0x05 + 0x75;
|
||||||
|
|
||||||
|
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_categ_listing,
|
||||||
|
(void **)&real_categ_listing);
|
||||||
|
|
||||||
|
if (g_subcategmode)
|
||||||
|
{
|
||||||
uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x05 + 69);
|
uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x05 + 69);
|
||||||
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;
|
||||||
categ_listing_event = (void (*)())(function_addr);
|
|
||||||
|
|
||||||
/* retrieve useful values from this function */
|
/* retrieve values from this function, needed for my reimplementation */
|
||||||
reimpl_value_1 = *((uint32_t*)(function_addr +0x03));
|
reimpl_value_1 = *((uint32_t*)(function_addr +0x03));
|
||||||
reimpl_value_2 = *((uint32_t*)(function_addr +0x16));
|
reimpl_value_2 = *((uint32_t*)(function_addr +0x16));
|
||||||
reimpl_func_1 = (void (*)())( *((uint32_t*)(function_addr +0x49)) + (uint32_t)(function_addr +0x04 +0x49) );
|
reimpl_func_1 = (void (*)())( *((uint32_t*)(function_addr +0x49)) + (uint32_t)(function_addr +0x04 +0x49) );
|
||||||
@ -458,19 +412,19 @@ static bool patch_custom_categ_simple(const char *game_dll_fn) {
|
|||||||
reimpl_func_3 = (void (*)())( *((uint32_t*)(function_addr +0xBC)) + (uint32_t)(function_addr +0x04 +0xBC) );
|
reimpl_func_3 = (void (*)())( *((uint32_t*)(function_addr +0xBC)) + (uint32_t)(function_addr +0x04 +0xBC) );
|
||||||
reimpl_func_4 = (void (*)())( *((uint32_t*)(function_addr +0xD1)) + (uint32_t)(function_addr +0x04 +0xD1) );
|
reimpl_func_4 = (void (*)())( *((uint32_t*)(function_addr +0xD1)) + (uint32_t)(function_addr +0x04 +0xD1) );
|
||||||
|
|
||||||
//get_subcateg_size = (void (*)())( *((uint32_t*)(function_addr +0x37)) + (uint32_t)(function_addr +0x04 +0x37) );
|
|
||||||
//get_subcateg_name = (void (*)())( *((uint32_t*)(function_addr +0x63)) + (uint32_t)(function_addr +0x04 +0x63) );
|
|
||||||
|
|
||||||
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_categ_listing,
|
|
||||||
(void **)&real_categ_listing);
|
|
||||||
|
|
||||||
uint64_t patch_addr_2 = (int64_t)reimpl_func_2_generate_event_category + 80;
|
uint64_t patch_addr_2 = (int64_t)reimpl_func_2_generate_event_category + 80;
|
||||||
//need to inject correct memory zone after generation as well
|
//need to inject correct memory zone after generation as well
|
||||||
MH_CreateHook((LPVOID)patch_addr_2, (LPVOID)hook_event_categ_generation,
|
MH_CreateHook((LPVOID)patch_addr_2, (LPVOID)hook_event_categ_generation,
|
||||||
(void **)&real_event_categ_generation);
|
(void **)&real_event_categ_generation);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//add new category processing in jump table
|
//add new category processing in jump table
|
||||||
|
if (g_subcategmode)
|
||||||
|
{
|
||||||
|
categ_inject_songlist = &categ_inject_songlist_subcategs;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
int64_t pattern_offset = search(data, dllSize, "\x8B\x4D\x10\x8B\x5D\x0C\x8B\xF1", 8, 0);
|
int64_t pattern_offset = search(data, dllSize, "\x8B\x4D\x10\x8B\x5D\x0C\x8B\xF1", 8, 0);
|
||||||
if (pattern_offset == -1) {
|
if (pattern_offset == -1) {
|
||||||
@ -478,29 +432,15 @@ static bool patch_custom_categ_simple(const char *game_dll_fn) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//I need to call this subfunction from my hook
|
||||||
add_song_in_list = (void (*)())(data + pattern_offset - 0x12);
|
add_song_in_list = (void (*)())(data + pattern_offset - 0x12);
|
||||||
|
|
||||||
if (g_subcategmode)
|
categ_inject_songlist = &categ_inject_songlist_simple;
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate songlist with all songs whose ID is above the threshold
|
||||||
|
if (!g_subcategmode)
|
||||||
{
|
{
|
||||||
categ_inject_songlist = &categ_inject_songlist_reimpl;
|
|
||||||
//categ_inject_songlist = categ_listing_event;
|
|
||||||
/*
|
|
||||||
//create a copy of event categ handling function then mod it
|
|
||||||
categ_inject_songlist = (void(*)())malloc(256);
|
|
||||||
DWORD old_prot;
|
|
||||||
VirtualProtect((LPVOID)categ_inject_songlist, 256, PAGE_EXECUTE_READWRITE, &old_prot);
|
|
||||||
memcpy((LPVOID)categ_inject_songlist, (uint64_t*)categ_listing_event, 256);
|
|
||||||
VirtualProtect((LPVOID)categ_inject_songlist, 256, old_prot, &old_prot);
|
|
||||||
|
|
||||||
uint32_t call_offset = (uint32_t*)categ_inject_songlist - (uint32_t*)categ_listing_event;
|
|
||||||
LOG("popnhax: call offset is %x\n",call_offset);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
else
|
|
||||||
categ_inject_songlist = &categ_inject_songlist_impl;
|
|
||||||
}
|
|
||||||
|
|
||||||
//create new song list
|
|
||||||
{
|
{
|
||||||
int64_t pattern_offset = search(data, dllSize, "\x00\x8B\x56\x04\x0F\xB7\x02\xE8", 8, 0);
|
int64_t pattern_offset = search(data, dllSize, "\x00\x8B\x56\x04\x0F\xB7\x02\xE8", 8, 0);
|
||||||
if (pattern_offset == -1) {
|
if (pattern_offset == -1) {
|
||||||
@ -510,19 +450,11 @@ static bool patch_custom_categ_simple(const char *game_dll_fn) {
|
|||||||
|
|
||||||
uint64_t patch_addr = (int64_t)data + pattern_offset + 0x07;
|
uint64_t patch_addr = (int64_t)data + pattern_offset + 0x07;
|
||||||
|
|
||||||
if (g_subcategmode)
|
|
||||||
{
|
|
||||||
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_subcateg_adjust_songlist,
|
|
||||||
(void **)&real_categ_build_songlist);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_categ_build_songlist,
|
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_categ_build_songlist,
|
||||||
(void **)&real_categ_build_songlist);
|
(void **)&real_categ_build_songlist);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//create new song list
|
//force rearm songlist creation so that it keeps working
|
||||||
{
|
{
|
||||||
int64_t pattern_offset = search(data, dllSize, "\x33\xC9\xB8\x12\x00\x00\x00\xBA", 8, 0);
|
int64_t pattern_offset = search(data, dllSize, "\x33\xC9\xB8\x12\x00\x00\x00\xBA", 8, 0);
|
||||||
if (pattern_offset == -1) {
|
if (pattern_offset == -1) {
|
||||||
@ -535,21 +467,22 @@ static bool patch_custom_categ_simple(const char *game_dll_fn) {
|
|||||||
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_categ_reinit_songlist,
|
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_categ_reinit_songlist,
|
||||||
(void **)&real_categ_reinit_songlist);
|
(void **)&real_categ_reinit_songlist);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//bump category count from 16 to 17
|
||||||
//bump category number from 16 to 17
|
|
||||||
if (!find_and_patch_hex(game_dll_fn, "\x83\xFE\x11\x0F\x82\x59\xFE\xFF\xFF", 9, 2, "\x12", 1))
|
if (!find_and_patch_hex(game_dll_fn, "\x83\xFE\x11\x0F\x82\x59\xFE\xFF\xFF", 9, 2, "\x12", 1))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//patch getCategName for a 17th entry
|
//patch getCategName for a 17th entry
|
||||||
|
{
|
||||||
//make array one cell larger
|
//make array one cell larger
|
||||||
if (!find_and_patch_hex(game_dll_fn, "\x83\xEC\x44\x98\xC7\x04\x24", 7, 2, "\x48", 1))
|
if (!find_and_patch_hex(game_dll_fn, "\x83\xEC\x44\x98\xC7\x04\x24", 7, 2, "\x48", 1))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
//add the new name
|
||||||
uint32_t categname_str_addr = (uint32_t)g_categname;
|
uint32_t categname_str_addr = (uint32_t)g_categname;
|
||||||
char categname_patch_string[] = "\xC7\x44\x24\x44\x20\x00\x28\x10\x8B\x04\x84\x83\xC4\x48\xC3";
|
char categname_patch_string[] = "\xC7\x44\x24\x44\x20\x00\x28\x10\x8B\x04\x84\x83\xC4\x48\xC3";
|
||||||
memcpy(categname_patch_string+4, &categname_str_addr, 4);
|
memcpy(categname_patch_string+4, &categname_str_addr, 4);
|
||||||
@ -557,13 +490,15 @@ static bool patch_custom_categ_simple(const char *game_dll_fn) {
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//patch getIconName for a 17th entry
|
//patch getIconName for a 17th entry
|
||||||
|
{
|
||||||
if (!find_and_patch_hex(game_dll_fn, "\x83\xEC\x44\x98\xC7\x04\x24", 7, 2, "\x48", 1)) //2nd occurrence since first one just got patched
|
if (!find_and_patch_hex(game_dll_fn, "\x83\xEC\x44\x98\xC7\x04\x24", 7, 2, "\x48", 1)) //2nd occurrence since first one just got patched
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
//add the new icon name
|
||||||
uint32_t categicon_str_addr = (uint32_t)g_categicon;
|
uint32_t categicon_str_addr = (uint32_t)g_categicon;
|
||||||
char categicon_patch_string[] = "\xC7\x44\x24\x44\xDC\x00\x28\x10\x8B\x04\x84\x83\xC4\x48\xC3";
|
char categicon_patch_string[] = "\xC7\x44\x24\x44\xDC\x00\x28\x10\x8B\x04\x84\x83\xC4\x48\xC3";
|
||||||
memcpy(categicon_patch_string+4, &categicon_str_addr, 4);
|
memcpy(categicon_patch_string+4, &categicon_str_addr, 4);
|
||||||
@ -571,8 +506,13 @@ static bool patch_custom_categ_simple(const char *game_dll_fn) {
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG("popnhax: custom category injected\n");
|
LOG("popnhax: custom %s injected (for songids ", g_subcategmode? "subcategories":"category");
|
||||||
|
if (g_max_id)
|
||||||
|
LOG("between %d and %d (inclusive))\n", g_min_id, g_max_id);
|
||||||
|
else
|
||||||
|
LOG("above %d (inclusive))\n", g_min_id);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -592,8 +532,8 @@ static void parse_musicdb(const char *input_filename) {
|
|||||||
subcategory_s *subcateg = get_subcateg(title);
|
subcategory_s *subcateg = get_subcateg(title);
|
||||||
if ( subcateg == NULL )
|
if ( subcateg == NULL )
|
||||||
{
|
{
|
||||||
subcategories = (subcategory_s*)realloc(subcategories, sizeof(subcategory_s)*(++subcateg_count));
|
subcategories = (subcategory_s*)realloc(subcategories, sizeof(subcategory_s)*(++g_subcateg_count));
|
||||||
subcateg = &(subcategories[subcateg_count-1]);
|
subcateg = &(subcategories[g_subcateg_count-1]);
|
||||||
subcateg->name = strdup(title);
|
subcateg->name = strdup(title);
|
||||||
subcateg->songlist = NULL;
|
subcateg->songlist = NULL;
|
||||||
subcateg->size = 0;
|
subcateg->size = 0;
|
||||||
@ -615,6 +555,7 @@ static void parse_musicdb(const char *input_filename) {
|
|||||||
|
|
||||||
static void load_databases() {
|
static void load_databases() {
|
||||||
SearchFile s;
|
SearchFile s;
|
||||||
|
g_subcateg_count = 0;
|
||||||
printf("musicdb search...\n");
|
printf("musicdb search...\n");
|
||||||
s.search("data_mods", "xml", true);
|
s.search("data_mods", "xml", true);
|
||||||
auto result = s.getResult();
|
auto result = s.getResult();
|
||||||
@ -628,29 +569,23 @@ static void load_databases() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool patch_custom_categs(const char *dllFilename, uint8_t mode)
|
bool patch_custom_categs(const char *dllFilename, uint8_t mode, uint16_t min, uint16_t max)
|
||||||
{
|
{
|
||||||
if (mode == 1)
|
g_min_id = min;
|
||||||
{
|
g_max_id = max;
|
||||||
g_subcategmode = true;
|
|
||||||
subcateg_count = 0;
|
|
||||||
load_databases();
|
|
||||||
return patch_custom_categ_simple(dllFilename);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == 2)
|
if (mode == 2)
|
||||||
{
|
{
|
||||||
g_subcategmode = true;
|
g_subcategmode = true;
|
||||||
subcateg_count = 0;
|
|
||||||
load_databases();
|
load_databases();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return patch_custom_categ(dllFilename);
|
||||||
|
/*
|
||||||
LOG("Subcateg list :\n");
|
LOG("Subcateg list :\n");
|
||||||
for (uint32_t i = 0; i < subcateg_count; i++)
|
for (uint32_t i = 0; i < g_subcateg_count; i++)
|
||||||
{
|
{
|
||||||
if (subcategories[i].size != 0)
|
if (subcategories[i].size != 0)
|
||||||
LOG(" %s (%d songs)", subcategories[i].name, subcategories[i].size);
|
LOG(" %s (%d songs)", subcategories[i].name, subcategories[i].size);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
LOG("HELLO OK :\n");
|
|
||||||
return true;
|
|
||||||
}
|
}
|
@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
bool patch_custom_categs(const char *dllFilename, uint8_t mode);
|
bool patch_custom_categs(const char *dllFilename, uint8_t mode, uint16_t min, uint16_t max);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -185,6 +185,12 @@ PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_U16, struct popnhax_config, hispeed_default
|
|||||||
"/popnhax/hispeed_default_bpm")
|
"/popnhax/hispeed_default_bpm")
|
||||||
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_S8, struct popnhax_config, base_offset,
|
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_S8, struct popnhax_config, base_offset,
|
||||||
"/popnhax/base_offset")
|
"/popnhax/base_offset")
|
||||||
|
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_U8, struct popnhax_config, custom_categ,
|
||||||
|
"/popnhax/custom_categ")
|
||||||
|
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_U16, struct popnhax_config, custom_categ_min_songid,
|
||||||
|
"/popnhax/custom_categ_min_songid")
|
||||||
|
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_U16, struct popnhax_config, custom_categ_max_songid,
|
||||||
|
"/popnhax/custom_categ_max_songid")
|
||||||
PSMAP_END
|
PSMAP_END
|
||||||
|
|
||||||
enum BufferIndexes {
|
enum BufferIndexes {
|
||||||
@ -5580,7 +5586,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
|||||||
/* must be called after force_datecode */
|
/* must be called after force_datecode */
|
||||||
patch_db_power_points();
|
patch_db_power_points();
|
||||||
patch_db_fix_cursor();
|
patch_db_fix_cursor();
|
||||||
patch_custom_categs(g_game_dll_fn, 1);
|
if (config.custom_categ)
|
||||||
|
patch_custom_categs(g_game_dll_fn, config.custom_categ, config.custom_categ_min_songid, config.custom_categ_max_songid);
|
||||||
patch_database(config.force_unlocks);
|
patch_database(config.force_unlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user