forked from Popn_Tools/popnhax
Compare commits
3 Commits
46ec71b83b
...
de69af2d66
Author | SHA1 | Date | |
---|---|---|---|
de69af2d66 | |||
4f22fd29be | |||
2543d2632f |
2
dist/popnhax/popnhax.xml
vendored
2
dist/popnhax/popnhax.xml
vendored
@ -134,7 +134,7 @@
|
|||||||
<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) -->
|
<!-- minimum songid for a song to be seen as "custom" -->
|
||||||
<custom_categ_min_songid __type="u16">4000</custom_categ_min_songid>
|
<custom_categ_min_songid __type="u16">4000</custom_categ_min_songid>
|
||||||
<!-- maximum songid for a song to be seen as "custom" (0 = no limit) -->
|
<!-- maximum songid for a song to be seen as "custom" (0 = no limit) -->
|
||||||
<custom_categ_max_songid __type="u16">0</custom_categ_max_songid>
|
<custom_categ_max_songid __type="u16">0</custom_categ_max_songid>
|
||||||
|
@ -19,9 +19,37 @@
|
|||||||
#include "minhook/hde32.h"
|
#include "minhook/hde32.h"
|
||||||
#include "minhook/include/MinHook.h"
|
#include "minhook/include/MinHook.h"
|
||||||
|
|
||||||
|
bool g_subcategmode = false;
|
||||||
uint32_t g_min_id = 4000;
|
uint32_t g_min_id = 4000;
|
||||||
uint32_t g_max_id = 0;
|
uint32_t g_max_id = 0;
|
||||||
|
|
||||||
|
const char *g_categname = "Custom Tracks";
|
||||||
|
const char *g_categicon = "cate_13";
|
||||||
|
const char *g_categformat = "[ol:4][olc:d92f0d]%s";
|
||||||
|
|
||||||
|
char *g_string_addr;
|
||||||
|
uint8_t idx = 0;
|
||||||
|
uint32_t tmp_size = 0;
|
||||||
|
uint32_t tmp_categ_ptr = 0;
|
||||||
|
uint32_t tmp_songlist_ptr = 0;
|
||||||
|
|
||||||
|
#define SIMPLE_CATEG_ALLOC 1
|
||||||
|
|
||||||
|
#if SIMPLE_CATEG_ALLOC == 1
|
||||||
|
uint32_t *songlist;
|
||||||
|
#else
|
||||||
|
uint32_t songlist[4096] = {0};
|
||||||
|
#endif
|
||||||
|
uint32_t songlist_addr = (uint32_t)&songlist;
|
||||||
|
uint32_t songlist_count = 0;
|
||||||
|
|
||||||
|
struct songlist_struct_s {
|
||||||
|
uint32_t dummy[3];
|
||||||
|
uint32_t array_start;
|
||||||
|
uint32_t array_end;
|
||||||
|
} songlist_struct;
|
||||||
|
uint32_t songlist_struct_addr = (uint32_t)&songlist_struct;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *name;
|
char *name;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
@ -30,6 +58,8 @@ typedef struct {
|
|||||||
|
|
||||||
subcategory_s* subcategories;
|
subcategory_s* subcategories;
|
||||||
uint32_t g_subcateg_count = 0;
|
uint32_t g_subcateg_count = 0;
|
||||||
|
//subcategories[0] is the "ALL SONGS" virtual subcategory,
|
||||||
|
//actual subcategories then go from subcategories[1] to subcategories[g_subcateg_count]
|
||||||
|
|
||||||
struct property *load_prop_file(const char *filename);
|
struct property *load_prop_file(const char *filename);
|
||||||
|
|
||||||
@ -52,6 +82,10 @@ static void add_song_to_subcateg(uint32_t songid, subcategory_s* 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;
|
||||||
subcateg->songlist[subcateg->size-1] |= 0x00060000; // game wants this otherwise only easy difficulty will appear
|
subcateg->songlist[subcateg->size-1] |= 0x00060000; // game wants this otherwise only easy difficulty will appear
|
||||||
|
|
||||||
|
// Also add it to the "ALL SONGS" subcategory
|
||||||
|
subcategories[0].songlist = (uint32_t *) realloc(subcategories[0].songlist, sizeof(uint32_t)*(++subcategories[0].size));
|
||||||
|
subcategories[0].songlist[subcategories[0].size-1] = subcateg->songlist[subcateg->size-1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,34 +93,13 @@ static subcategory_s* get_subcateg(char *title)
|
|||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < g_subcateg_count; i++)
|
for (uint32_t i = 0; i < g_subcateg_count; i++)
|
||||||
{
|
{
|
||||||
if (strcmp(title, subcategories[i].name) == 0)
|
//iterating over actual subcategories, excluding "ALL SONGS"
|
||||||
return &(subcategories[i]);
|
if (strcmp(title, subcategories[i+1].name) == 0)
|
||||||
|
return &(subcategories[i+1]);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool g_subcategmode = false;
|
|
||||||
const char *g_categname = "Custom Tracks";
|
|
||||||
const char *g_categicon = "cate_13";
|
|
||||||
const char *g_categformat = "[ol:4][olc:d92f0d]%s";
|
|
||||||
|
|
||||||
char *g_string_addr;
|
|
||||||
uint8_t idx = 0;
|
|
||||||
uint32_t tmp_size = 0;
|
|
||||||
uint32_t tmp_categ_ptr = 0;
|
|
||||||
uint32_t tmp_songlist_ptr = 0;
|
|
||||||
|
|
||||||
uint32_t songlist[4096] = {0};
|
|
||||||
uint32_t songlist_addr = (uint32_t)&songlist;
|
|
||||||
uint32_t songlist_count = 0;
|
|
||||||
|
|
||||||
struct songlist_struct_s {
|
|
||||||
uint32_t dummy[3];
|
|
||||||
uint32_t array_start;
|
|
||||||
uint32_t array_end;
|
|
||||||
} songlist_struct;
|
|
||||||
uint32_t songlist_struct_addr = (uint32_t)&songlist_struct;
|
|
||||||
|
|
||||||
void (*add_song_in_list)();
|
void (*add_song_in_list)();
|
||||||
void (*categ_inject_songlist)();
|
void (*categ_inject_songlist)();
|
||||||
|
|
||||||
@ -110,16 +123,16 @@ uint32_t tmp_str_addr;
|
|||||||
void (*real_event_categ_generation)();
|
void (*real_event_categ_generation)();
|
||||||
void hook_event_categ_generation()
|
void hook_event_categ_generation()
|
||||||
{
|
{
|
||||||
//chaine dans [esp+0x1C], on check si l'adresse correspond à l'une de nos subcateg
|
//[esp+0x1C] contains the subcategory name string pointer, I compare it with my subcategories string pointers..
|
||||||
//si c'est pas le cas on s'en va sans rien faire
|
// no match found -> we're actually processing the EVENT category, leave
|
||||||
//si c'est le cas alors on met les coord de début et fin dans la struct_songlist et on envoie l'adresse de struct sur eax
|
// match found -> I need to fix eax with a pointer to my songlist before the subcall to the subcategory generating function
|
||||||
__asm("mov _new_song_list, eax"); //save original intended value
|
__asm("mov _new_song_list, eax"); //save original intended value
|
||||||
__asm("push ecx");
|
__asm("push ecx");
|
||||||
__asm("push edx");
|
__asm("push edx");
|
||||||
__asm("mov ebx, [esp+0x2C]\n");
|
__asm("mov ebx, [esp+0x30]\n"); // +0x30 due to a couple implicit "push" added by the compiler
|
||||||
__asm("mov _tmp_str_addr, ebx\n");
|
__asm("mov _tmp_str_addr, ebx\n");
|
||||||
|
|
||||||
for (uint32_t i = 0; i < g_subcateg_count; i++)
|
for (uint32_t i = 0; i < g_subcateg_count+1; i++)
|
||||||
{
|
{
|
||||||
if ( (uint32_t)subcategories[i].name == tmp_str_addr )
|
if ( (uint32_t)subcategories[i].name == tmp_str_addr )
|
||||||
{
|
{
|
||||||
@ -148,7 +161,7 @@ void get_subcateg_name_impl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t reimpl_value_1;
|
uint32_t reimpl_value_1;
|
||||||
uint32_t reimpl_value_2; //commun aux deux fonctions
|
uint32_t reimpl_value_2;
|
||||||
void (*get_subcateg_size)() = &get_subcateg_size_impl;
|
void (*get_subcateg_size)() = &get_subcateg_size_impl;
|
||||||
void (*get_subcateg_name)() = &get_subcateg_name_impl;
|
void (*get_subcateg_name)() = &get_subcateg_name_impl;
|
||||||
void (*reimpl_func_1)();
|
void (*reimpl_func_1)();
|
||||||
@ -262,7 +275,12 @@ void categ_inject_songlist_subcategs()
|
|||||||
__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, [_g_subcateg_count]\n");
|
//effectively __asm("cmp ebx, [_g_subcateg_count+1]\n"); (to take "ALL SONGS" into account)
|
||||||
|
__asm("push edx\n");
|
||||||
|
__asm("mov edx, [_g_subcateg_count]\n");
|
||||||
|
__asm("inc edx\n");
|
||||||
|
__asm("cmp ebx, edx\n");
|
||||||
|
__asm("pop edx\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");
|
||||||
@ -279,10 +297,12 @@ void categ_inject_songlist_subcategs()
|
|||||||
//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_simple()
|
void categ_inject_songlist_simple()
|
||||||
{
|
{
|
||||||
|
__asm("push ecx\n");
|
||||||
__asm("push edx\n");
|
__asm("push edx\n");
|
||||||
songlist_struct.array_start = (uint32_t)&songlist;
|
songlist_struct.array_start = (uint32_t)songlist;
|
||||||
songlist_struct.array_end = (uint32_t)&(songlist[songlist_count]);
|
songlist_struct.array_end = (uint32_t)&(songlist[songlist_count]);
|
||||||
__asm("pop edx\n");
|
__asm("pop edx\n");
|
||||||
|
__asm("pop ecx\n");
|
||||||
__asm("push ecx\n");
|
__asm("push ecx\n");
|
||||||
__asm("push _songlist_struct_addr\n");
|
__asm("push _songlist_struct_addr\n");
|
||||||
__asm("lea eax, dword ptr [ecx+0x24]\n");
|
__asm("lea eax, dword ptr [ecx+0x24]\n");
|
||||||
@ -306,9 +326,20 @@ void hook_categ_build_songlist()
|
|||||||
__asm("je add_my_song\n");
|
__asm("je add_my_song\n");
|
||||||
__asm("cmp eax, _g_max_id\n");
|
__asm("cmp eax, _g_max_id\n");
|
||||||
__asm("ja categ_skip_add\n");
|
__asm("ja categ_skip_add\n");
|
||||||
|
|
||||||
__asm("add_my_song:\n");
|
__asm("add_my_song:\n");
|
||||||
__asm("push eax\n");
|
__asm("push eax\n");
|
||||||
__asm("push ebx\n");
|
__asm("push ebx\n");
|
||||||
|
#if SIMPLE_CATEG_ALLOC == 1
|
||||||
|
__asm("push ecx\n");
|
||||||
|
__asm("push edx\n");
|
||||||
|
__asm("sub esp, 0x08\n");
|
||||||
|
songlist = (uint32_t*)realloc((void*)songlist, sizeof(uint32_t)*(songlist_count+4)); //TODO: only realloc when growing
|
||||||
|
songlist_addr = (uint32_t)songlist;
|
||||||
|
__asm("add esp, 0x08\n");
|
||||||
|
__asm("pop edx\n");
|
||||||
|
__asm("pop ecx\n");
|
||||||
|
#endif
|
||||||
__asm("mov eax, [_songlist_count]\n");
|
__asm("mov eax, [_songlist_count]\n");
|
||||||
__asm("sal eax, 2\n");
|
__asm("sal eax, 2\n");
|
||||||
__asm("add eax, _songlist_addr\n");
|
__asm("add eax, _songlist_addr\n");
|
||||||
@ -321,23 +352,6 @@ void hook_categ_build_songlist()
|
|||||||
real_categ_build_songlist();
|
real_categ_build_songlist();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t songid_mask = 0;
|
|
||||||
void apply_mask_to_all()
|
|
||||||
{
|
|
||||||
__asm("push eax");
|
|
||||||
__asm("mov eax, [ebx]");
|
|
||||||
__asm("mov _songid_mask, eax");
|
|
||||||
__asm("pop eax");
|
|
||||||
songid_mask &= 0xFFFF0000;
|
|
||||||
for (uint32_t i = 0; i < g_subcateg_count; i++)
|
|
||||||
{
|
|
||||||
for (uint32_t j = 0; j < subcategories[i].size; j++)
|
|
||||||
{
|
|
||||||
subcategories[i].songlist[j] |= songid_mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
||||||
@ -532,8 +546,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)*(++g_subcateg_count));
|
subcategories = (subcategory_s*)realloc(subcategories, sizeof(subcategory_s)*((++g_subcateg_count)+1));
|
||||||
subcateg = &(subcategories[g_subcateg_count-1]);
|
subcateg = &(subcategories[g_subcateg_count]);
|
||||||
subcateg->name = strdup(title);
|
subcateg->name = strdup(title);
|
||||||
subcateg->songlist = NULL;
|
subcateg->songlist = NULL;
|
||||||
subcateg->size = 0;
|
subcateg->size = 0;
|
||||||
@ -556,6 +570,11 @@ static void parse_musicdb(const char *input_filename) {
|
|||||||
static void load_databases() {
|
static void load_databases() {
|
||||||
SearchFile s;
|
SearchFile s;
|
||||||
g_subcateg_count = 0;
|
g_subcateg_count = 0;
|
||||||
|
subcategories = (subcategory_s*)realloc(subcategories, sizeof(subcategory_s)*(1));
|
||||||
|
subcategories[0].name = strdup("ALL SONGS");
|
||||||
|
subcategories[0].songlist = NULL;
|
||||||
|
subcategories[0].size = 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();
|
||||||
@ -567,12 +586,22 @@ static void load_databases() {
|
|||||||
printf("(musicdb) Loading %s...\n", result[i].c_str());
|
printf("(musicdb) Loading %s...\n", result[i].c_str());
|
||||||
parse_musicdb(result[i].c_str());
|
parse_musicdb(result[i].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < g_subcateg_count+1; i++)
|
||||||
|
{
|
||||||
|
if (subcategories[i].size != 0)
|
||||||
|
LOG(" %s (%d songs)", subcategories[i].name, subcategories[i].size);
|
||||||
|
}
|
||||||
|
LOG("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool patch_custom_categs(const char *dllFilename, uint8_t mode, uint16_t min, uint16_t max)
|
bool patch_custom_categs(const char *dllFilename, uint8_t mode, uint16_t min, uint16_t max)
|
||||||
{
|
{
|
||||||
g_min_id = min;
|
g_min_id = min;
|
||||||
g_max_id = max;
|
g_max_id = max;
|
||||||
|
#if SIMPLE_CATEG_ALLOC == 1
|
||||||
|
songlist = (uint32_t*)calloc(1,5);
|
||||||
|
#endif
|
||||||
if (mode == 2)
|
if (mode == 2)
|
||||||
{
|
{
|
||||||
g_subcategmode = true;
|
g_subcategmode = true;
|
||||||
@ -580,12 +609,4 @@ bool patch_custom_categs(const char *dllFilename, uint8_t mode, uint16_t min, ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
return patch_custom_categ(dllFilename);
|
return patch_custom_categ(dllFilename);
|
||||||
/*
|
|
||||||
LOG("Subcateg list :\n");
|
|
||||||
for (uint32_t i = 0; i < g_subcateg_count; i++)
|
|
||||||
{
|
|
||||||
if (subcategories[i].size != 0)
|
|
||||||
LOG(" %s (%d songs)", subcategories[i].name, subcategories[i].size);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user