forked from Popn_Tools/popnhax
Compare commits
10 Commits
3fef3f58bf
...
543edc3fbf
Author | SHA1 | Date | |
---|---|---|---|
543edc3fbf | |||
2a67d07700 | |||
8795e55f02 | |||
f569e9dd4b | |||
4c5751a694 | |||
15b1bf20a7 | |||
4d618e5d1c | |||
607c2842b6 | |||
dd109549b0 | |||
edea20b403 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*:Zone.Identifier
|
22
Module.mk
22
Module.mk
@ -14,17 +14,15 @@ include popnhax/Module.mk
|
|||||||
#
|
#
|
||||||
|
|
||||||
zipdir := $(BUILDDIR)/zip
|
zipdir := $(BUILDDIR)/zip
|
||||||
|
popnhax_version := $(shell grep "define PROGRAM_VERSION" popnhax/dllmain.cc | cut -d'"' -f2)
|
||||||
|
|
||||||
$(zipdir)/:
|
$(BUILDDIR)/popnhax_v$(popnhax_version).zip: \
|
||||||
mkdir -p $@
|
build/bin/avs2_1508-32/popnhax.dll
|
||||||
|
@echo ... $@
|
||||||
|
@mkdir -p $(zipdir)
|
||||||
|
@cp -a -p build/bin/avs2_1508-32/popnhax.dll $(zipdir)
|
||||||
|
@cp -r -a -p dist/popnhax/* $(zipdir)
|
||||||
|
@cd $(zipdir) \
|
||||||
|
&& zip -r ../popnhax_v$(popnhax_version).zip ./*
|
||||||
|
|
||||||
$(BUILDDIR)/popnhax.zip: \
|
all: $(BUILDDIR)/popnhax_v$(popnhax_version).zip
|
||||||
build/bin/avs2_1508-32/popnhax.dll \
|
|
||||||
dist/popnhax/popnhax.xml \
|
|
||||||
dist/popnhax/D3d9.dll \
|
|
||||||
dist/popnhax/ifs_hook.dll \
|
|
||||||
| $(zipdir)/
|
|
||||||
echo ... $@
|
|
||||||
zip -j $@ $^
|
|
||||||
|
|
||||||
all: $(BUILDDIR)/popnhax.zip
|
|
||||||
|
26
README.md
26
README.md
@ -2,10 +2,32 @@
|
|||||||
|
|
||||||
# popnhax
|
# popnhax
|
||||||
|
|
||||||
Arcade game patcher.
|
Patcher for pop'n music arcade game.
|
||||||
|
|
||||||
|
Featuring pfree, instant retire, visual and audio offset adjust, 1000Hz input polling for true ms-based timing, unlimited favorites, auto hi-speed selection, iidx-like hard gauge and more..
|
||||||
|
|
||||||
Based on [bemanihax](https://github.com/windyfairy/bemanihax) whose an updated version was included with omnimix v1
|
Based on [bemanihax](https://github.com/windyfairy/bemanihax) whose an updated version was included with omnimix v1
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
Refer to [popnhax.xml](https://github.com/CrazyRedMachine/popnhax/blob/main/dist/popnhax/popnhax.xml) for complete list and explanations
|
||||||
|
|
||||||
|
More info could be found in [Release Notes](https://github.com/CrazyRedMachine/popnhax/releases) or in the [popnhax_tools](https://github.com/CrazyRedMachine/popnhax_tools) repository.
|
||||||
|
|
||||||
|
### Run Instructions
|
||||||
|
|
||||||
|
- Extract all files directly in the `contents` folder of your install.
|
||||||
|
|
||||||
|
(**Note**: if you're running your dlls from `modules` subfolder, please rather copy them back into `contents` folder).
|
||||||
|
|
||||||
|
- Edit `popnhax.xml` with a text editor and set your desired options.
|
||||||
|
|
||||||
|
- Add `popnhax.dll` as an inject dll to your gamestart command or option menu.
|
||||||
|
|
||||||
|
eg. modify your gamestart.bat to add `-k popnhax.dll` or `-K popnhax.dll` depending on the launcher you use.
|
||||||
|
|
||||||
|
Some launchers also feature an option menu (accessible by pressing F4 ingame), in which case you can locate the "Inject Hook" setting in option tab. Enter `popnhax.dll` there.
|
||||||
|
|
||||||
### Build Instructions
|
### Build Instructions
|
||||||
|
|
||||||
Should be working out of the box with MSYS2/MinGW32. Just run `make`.
|
Using WSL is the recommended method. Just run `make`.
|
||||||
|
BIN
dist/popnhax/data_mods/_popnhax_assets/tex/system24/ms_ifs/cate_cc.png
vendored
Normal file
BIN
dist/popnhax/data_mods/_popnhax_assets/tex/system24/ms_ifs/cate_cc.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
dist/popnhax/data_mods/_popnhax_assets/tex/system25/ms_ifs/cate_cc.png
vendored
Normal file
BIN
dist/popnhax/data_mods/_popnhax_assets/tex/system25/ms_ifs/cate_cc.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
dist/popnhax/data_mods/_popnhax_assets/tex/system26/ms_ifs/cate_cc.png
vendored
Normal file
BIN
dist/popnhax/data_mods/_popnhax_assets/tex/system26/ms_ifs/cate_cc.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
dist/popnhax/data_mods/_popnhax_assets/tex/system27/ms_ifs/cate_cc.png
vendored
Normal file
BIN
dist/popnhax/data_mods/_popnhax_assets/tex/system27/ms_ifs/cate_cc.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
26
dist/popnhax/popnhax.xml
vendored
26
dist/popnhax/popnhax.xml
vendored
@ -15,7 +15,7 @@
|
|||||||
<!-- Other categories -->
|
<!-- Other categories -->
|
||||||
<!-- 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>
|
||||||
<!-- Handle favorites through data_mods/<friendID>.fav files (Note: allows UNLIMITED favorites) -->
|
<!-- Handle favorites through data_mods/<game>.<friendID>.fav files (Note: allows UNLIMITED favorites as well as favorites without an account/server) -->
|
||||||
<local_favorites __type="bool">0</local_favorites>
|
<local_favorites __type="bool">0</local_favorites>
|
||||||
|
|
||||||
<!-- Classic patches -->
|
<!-- Classic patches -->
|
||||||
@ -57,7 +57,7 @@
|
|||||||
<hispeed_default_bpm __type="u16">0</hispeed_default_bpm>
|
<hispeed_default_bpm __type="u16">0</hispeed_default_bpm>
|
||||||
|
|
||||||
<!-- IIDX-like hard gauge (start with full gauge, instant fail if gauge drops to 0) -->
|
<!-- IIDX-like hard gauge (start with full gauge, instant fail if gauge drops to 0) -->
|
||||||
<!-- Gauge details: increment: +0.1% for each cool/great/good (like spicy gauge), decrement: -9% for each bad, or -4.5% if gauge <=30% ) -->
|
<!-- Gauge details: increment: +0.1% for each cool/great/good (like spicy gauge), decrement: -9% for each bad, or -4.5% if gauge <=30% (like IIDX) -->
|
||||||
<iidx_hard_gauge __type="bool">0</iidx_hard_gauge>
|
<iidx_hard_gauge __type="bool">0</iidx_hard_gauge>
|
||||||
<!-- Force full options by default (useful when no numpad is available) -->
|
<!-- Force full options by default (useful when no numpad is available) -->
|
||||||
<force_full_opt __type="bool">0</force_full_opt>
|
<force_full_opt __type="bool">0</force_full_opt>
|
||||||
@ -104,11 +104,11 @@
|
|||||||
======================================================================================== -->
|
======================================================================================== -->
|
||||||
|
|
||||||
<!-- Datecode and Multiboot -->
|
<!-- Datecode and Multiboot -->
|
||||||
<!-- Force a different datecode than the one found in ea3-config (yyyymmdd00) -->
|
<!-- Force a different datecode than the one found in ea3-config (yyyymmdd00), or use "auto" to let music limit decide for you if patch_db is on -->
|
||||||
<force_datecode __type="str"></force_datecode>
|
<force_datecode __type="str">auto</force_datecode>
|
||||||
<!-- Also apply force_datecode to network packets -->
|
<!-- Also apply force_datecode to network packets -->
|
||||||
<network_datecode __type="bool">1</network_datecode>
|
<network_datecode __type="bool">1</network_datecode>
|
||||||
<!-- Disable multiboot auto conf tuning (which takes place when using popn22_yyyymmddrr.dll format and an xml without force_datecode option) -->
|
<!-- Disable multiboot auto conf tuning (which takes place when using popn22_yyyymmddrr.dll format and an xml without another datecode in force_datecode) -->
|
||||||
<disable_multiboot __type="bool">0</disable_multiboot>
|
<disable_multiboot __type="bool">0</disable_multiboot>
|
||||||
|
|
||||||
<!-- Timing and lanes -->
|
<!-- Timing and lanes -->
|
||||||
@ -132,13 +132,13 @@
|
|||||||
<enhanced_polling_priority __type="s8">1</enhanced_polling_priority>
|
<enhanced_polling_priority __type="s8">1</enhanced_polling_priority>
|
||||||
|
|
||||||
<!-- Song db patches -->
|
<!-- Song db patches -->
|
||||||
<!-- Auto select patch file from data_mods folder (will detect datecode from ea3-config or force_datecode option) -->
|
<!-- Auto select patch file from data_mods folder based on music limit, or datecode otherwise (will detect datecode from ea3-config or force_datecode option) -->
|
||||||
<patch_xml_auto __type="bool">1</patch_xml_auto>
|
<patch_xml_auto __type="bool">1</patch_xml_auto>
|
||||||
<!-- Manually set XML file containing patches (requires patch_xml_auto to be disabled) -->
|
<!-- Manually set XML file containing patches (requires patch_xml_auto to be disabled) -->
|
||||||
<patch_xml_filename __type="str"></patch_xml_filename>
|
<patch_xml_filename __type="str"></patch_xml_filename>
|
||||||
<!-- Force the newly created buffers to be the same size as the original buffers -->
|
<!-- Force the newly created buffers to be the same size as the original buffers (not recommended) -->
|
||||||
<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) (not recommended) -->
|
||||||
<disable_redirection __type="bool">0</disable_redirection>
|
<disable_redirection __type="bool">0</disable_redirection>
|
||||||
<!-- Do not perform music limit checks for patch_xml_auto (not recommended) -->
|
<!-- Do not perform music limit checks for patch_xml_auto (not recommended) -->
|
||||||
<ignore_music_limit __type="bool">0</ignore_music_limit>
|
<ignore_music_limit __type="bool">0</ignore_music_limit>
|
||||||
@ -146,14 +146,16 @@
|
|||||||
<!-- Custom category options -->
|
<!-- Custom category options -->
|
||||||
<!-- minimum songid for a song to be seen as "custom" -->
|
<!-- 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, not recommended since "random" category will use fake song ids in the 65400+ range) -->
|
||||||
<custom_categ_max_songid __type="u16">0</custom_categ_max_songid>
|
<custom_categ_max_songid __type="u16">65400</custom_categ_max_songid>
|
||||||
<!-- Category title for customs -->
|
<!-- Category title for customs -->
|
||||||
<custom_category_title __type="str">Customs</custom_category_title>
|
<custom_category_title __type="str">Customs</custom_category_title>
|
||||||
<!-- Format used for category title (see -->
|
<!-- Format used for category title (in BM2DXFontScript format, refer to BM2DXFontScript.md in popnhax_tools repo) -->
|
||||||
<custom_category_format __type="str">[ol:4][olc:d92f0d]%s</custom_category_format>
|
<custom_category_format __type="str">[ol:4][olc:d92f0d]%s</custom_category_format>
|
||||||
<!-- Format used for custom song titles on song select (Note: colors not working for kaimei and unilab, but rotation does, e.g.: * [rz:3]%s[/rz] ) -->
|
<!-- Format used for custom song titles on song select (Note: colors not working for kaimei and above, but rotation does, e.g. "* [rz:3]%s[/rz]" ) -->
|
||||||
<custom_track_title_format __type="str"></custom_track_title_format>
|
<custom_track_title_format __type="str"></custom_track_title_format>
|
||||||
|
<!-- Optional secondary format used for older games only (Full colors supported, e.g. "[ol:4][olc:d92f0d]%s") -->
|
||||||
|
<custom_track_title_format2 __type="str"></custom_track_title_format2>
|
||||||
|
|
||||||
<!-- Translation -->
|
<!-- Translation -->
|
||||||
<!-- Disable .dict string replacements and .ips patches -->
|
<!-- Disable .dict string replacements and .ips patches -->
|
||||||
|
@ -63,6 +63,7 @@ struct popnhax_config {
|
|||||||
char custom_category_title[16];
|
char custom_category_title[16];
|
||||||
char custom_category_format[64];
|
char custom_category_format[64];
|
||||||
char custom_track_title_format[64];
|
char custom_track_title_format[64];
|
||||||
|
char custom_track_title_format2[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -55,6 +55,11 @@ uint32_t favorites_count = 0;
|
|||||||
songlist_t favorites_struct;
|
songlist_t favorites_struct;
|
||||||
uint32_t favorites_struct_addr = (uint32_t)&favorites_struct;
|
uint32_t favorites_struct_addr = (uint32_t)&favorites_struct;
|
||||||
|
|
||||||
|
bool is_a_custom(uint32_t songid)
|
||||||
|
{
|
||||||
|
return (songid >= g_min_id && (g_max_id==0 || g_max_id >= songid));
|
||||||
|
}
|
||||||
|
|
||||||
void add_song_to_favorites()
|
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));
|
||||||
@ -250,7 +255,7 @@ static bool subcateg_has_songid(uint32_t songid, subcategory_s* subcateg)
|
|||||||
{
|
{
|
||||||
for ( uint32_t i = 0; i < subcateg->size; i++ )
|
for ( uint32_t i = 0; i < subcateg->size; i++ )
|
||||||
{
|
{
|
||||||
if ( subcateg->songlist[i] == songid )
|
if ( (subcateg->songlist[i] & 0x0000FFFF) == songid )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -258,8 +263,7 @@ 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 >= g_min_id
|
if ( is_a_custom(songid)
|
||||||
&& (g_max_id == 0 || songid <= g_max_id)
|
|
||||||
&& !subcateg_has_songid(songid, subcateg) )
|
&& !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));
|
||||||
@ -267,12 +271,15 @@ static void add_song_to_subcateg(uint32_t songid, subcategory_s* subcateg)
|
|||||||
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
|
// Also add it to the "ALL SONGS" subcategory
|
||||||
|
if ( !subcateg_has_songid(songid, &subcategories[0]) )
|
||||||
|
{
|
||||||
subcategories[0].songlist = (uint32_t *) realloc(subcategories[0].songlist, sizeof(uint32_t)*(++subcategories[0].size));
|
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];
|
subcategories[0].songlist[subcategories[0].size-1] = subcateg->songlist[subcateg->size-1];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static subcategory_s* get_subcateg(char *title)
|
static subcategory_s* get_subcateg(const char *title)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < g_subcateg_count; i++)
|
for (uint32_t i = 0; i < g_subcateg_count; i++)
|
||||||
{
|
{
|
||||||
@ -502,12 +509,15 @@ void hook_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, _g_min_id\n");
|
__asm("push edx\n");
|
||||||
__asm("jb categ_skip_add\n");
|
__asm("push ecx\n");
|
||||||
__asm("cmp dword ptr _g_max_id, 0\n");
|
__asm("push eax\n");
|
||||||
__asm("je add_my_song\n");
|
__asm("call %P0" : : "i"(is_a_custom));
|
||||||
__asm("cmp eax, _g_max_id\n");
|
__asm("test eax, eax\n");
|
||||||
__asm("ja categ_skip_add\n");
|
__asm("pop eax\n");
|
||||||
|
__asm("pop ecx\n");
|
||||||
|
__asm("pop edx\n");
|
||||||
|
__asm("jz categ_skip_add\n");
|
||||||
|
|
||||||
__asm("add_my_song:\n");
|
__asm("add_my_song:\n");
|
||||||
__asm("push eax\n");
|
__asm("push eax\n");
|
||||||
@ -567,12 +577,16 @@ void hook_song_printf()
|
|||||||
__asm("push eax\n");
|
__asm("push eax\n");
|
||||||
__asm("push ebx\n");
|
__asm("push ebx\n");
|
||||||
__asm("mov eax, [esp+0x50]\n");
|
__asm("mov eax, [esp+0x50]\n");
|
||||||
__asm("cmp eax, _g_min_id\n");
|
|
||||||
__asm("jb print_regular_song\n");
|
__asm("push ecx\n");
|
||||||
__asm("cmp dword ptr _g_max_id, 0\n");
|
__asm("push edx\n");
|
||||||
__asm("je print_custom_song\n");
|
__asm("push eax\n");
|
||||||
__asm("cmp eax, _g_max_id\n");
|
__asm("call %P0" : : "i"(is_a_custom));
|
||||||
__asm("ja print_regular_song\n");
|
__asm("test eax, eax\n");
|
||||||
|
__asm("pop eax\n");
|
||||||
|
__asm("pop edx\n");
|
||||||
|
__asm("pop ecx\n");
|
||||||
|
__asm("jz print_regular_song\n");
|
||||||
|
|
||||||
__asm("print_custom_song:\n");
|
__asm("print_custom_song:\n");
|
||||||
|
|
||||||
@ -592,12 +606,16 @@ void hook_artist_printf()
|
|||||||
__asm("push eax\n");
|
__asm("push eax\n");
|
||||||
__asm("push ebx\n");
|
__asm("push ebx\n");
|
||||||
__asm("mov eax, [esp+0x50]\n");
|
__asm("mov eax, [esp+0x50]\n");
|
||||||
__asm("cmp eax, _g_min_id\n");
|
|
||||||
__asm("jb print_regular_artist\n");
|
__asm("push ecx\n");
|
||||||
__asm("cmp dword ptr _g_max_id, 0\n");
|
__asm("push edx\n");
|
||||||
__asm("je print_custom_artist\n");
|
__asm("push eax\n");
|
||||||
__asm("cmp eax, _g_max_id\n");
|
__asm("call %P0" : : "i"(is_a_custom));
|
||||||
__asm("ja print_regular_artist\n");
|
__asm("test eax, eax\n");
|
||||||
|
__asm("pop eax\n");
|
||||||
|
__asm("pop edx\n");
|
||||||
|
__asm("pop ecx\n");
|
||||||
|
__asm("jz print_regular_artist\n");
|
||||||
|
|
||||||
__asm("print_custom_artist:\n");
|
__asm("print_custom_artist:\n");
|
||||||
|
|
||||||
@ -695,7 +713,7 @@ static bool patch_favorite_categ(const char *game_dll_fn) {
|
|||||||
|
|
||||||
//hook result screen to replace 3 functions
|
//hook result screen to replace 3 functions
|
||||||
{
|
{
|
||||||
int64_t first_loc = search(data, dllSize, "\xBF\x07\x00\x00\x00\xC6\x85\x61\xD3", 9, 0);
|
int64_t first_loc = search(data, dllSize, "\xBF\x07\x00\x00\x00\xC6\x85", 7, 0);
|
||||||
if (first_loc == -1) {
|
if (first_loc == -1) {
|
||||||
LOG("popnhax: local_favorites: cannot find result screen function\n");
|
LOG("popnhax: local_favorites: cannot find result screen function\n");
|
||||||
return false;
|
return false;
|
||||||
@ -905,6 +923,12 @@ static char *get_folder_name(const char* path) {
|
|||||||
return categ_name;
|
return categ_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool is_excluded_folder(const char *input_filename)
|
||||||
|
{
|
||||||
|
return (input_filename[strlen("data_mods/")] == '_');
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_musicdb(const char *input_filename) {
|
static void parse_musicdb(const char *input_filename) {
|
||||||
char *title = get_folder_name(input_filename);
|
char *title = get_folder_name(input_filename);
|
||||||
|
|
||||||
@ -930,6 +954,7 @@ static void parse_musicdb(const char *input_filename) {
|
|||||||
add_song_to_subcateg(songid, subcateg);
|
add_song_to_subcateg(songid, subcateg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_databases() {
|
static void load_databases() {
|
||||||
@ -945,8 +970,10 @@ static void load_databases() {
|
|||||||
|
|
||||||
for(uint16_t i=0;i<result.size();i++)
|
for(uint16_t i=0;i<result.size();i++)
|
||||||
{
|
{
|
||||||
if ( strstr(result[i].c_str(), "musicdb") == NULL )
|
if ( (strstr(result[i].c_str(), "musicdb") == NULL)
|
||||||
|
|| is_excluded_folder(result[i].c_str()) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
parse_musicdb(result[i].c_str());
|
parse_musicdb(result[i].c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -965,12 +992,18 @@ void hook_after_getlevel()
|
|||||||
{
|
{
|
||||||
__asm("push ebx\n");
|
__asm("push ebx\n");
|
||||||
__asm("mov ebx, dword ptr [esp+0x04]\n");
|
__asm("mov ebx, dword ptr [esp+0x04]\n");
|
||||||
__asm("cmp ebx, _g_min_id\n");
|
|
||||||
__asm("jb real_level\n");
|
__asm("push eax\n");
|
||||||
__asm("cmp dword ptr _g_max_id, 0\n");
|
__asm("push ecx\n");
|
||||||
__asm("je force_level_0\n");
|
__asm("push edx\n");
|
||||||
__asm("cmp ebx, _g_max_id\n");
|
__asm("push ebx\n");
|
||||||
__asm("ja real_level\n");
|
__asm("call %P0" : : "i"(is_a_custom));
|
||||||
|
__asm("test eax, eax\n");
|
||||||
|
__asm("pop ebx\n");
|
||||||
|
__asm("pop edx\n");
|
||||||
|
__asm("pop ecx\n");
|
||||||
|
__asm("pop eax\n");
|
||||||
|
__asm("jz real_level\n");
|
||||||
|
|
||||||
__asm("force_level_0:\n");
|
__asm("force_level_0:\n");
|
||||||
__asm("mov eax, 0x00\n");
|
__asm("mov eax, 0x00\n");
|
||||||
@ -1006,7 +1039,7 @@ bool patch_exclude(const char *game_dll_fn)
|
|||||||
bool patch_custom_categs(const char *dllFilename, struct popnhax_config *config)
|
bool patch_custom_categs(const char *dllFilename, struct popnhax_config *config)
|
||||||
{
|
{
|
||||||
g_min_id = config->custom_categ_min_songid;
|
g_min_id = config->custom_categ_min_songid;
|
||||||
g_max_id = config->custom_categ_max_songid;
|
//g_max_id = config->custom_categ_max_songid; //handled during injection already
|
||||||
uint8_t mode = config->custom_categ;
|
uint8_t mode = config->custom_categ;
|
||||||
|
|
||||||
char icon_path[64];
|
char icon_path[64];
|
||||||
@ -1046,11 +1079,13 @@ bool patch_custom_categs(const char *dllFilename, struct popnhax_config *config)
|
|||||||
print_databases();
|
print_databases();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( config->custom_track_title_format[0] != '\0' )
|
if ( config->game_version < 26 && config->custom_track_title_format2[0] != '\0' )
|
||||||
{
|
g_customformat = config->custom_track_title_format2;
|
||||||
|
else if ( config->custom_track_title_format[0] != '\0' )
|
||||||
g_customformat = config->custom_track_title_format;
|
g_customformat = config->custom_track_title_format;
|
||||||
|
|
||||||
|
if ( g_customformat != NULL )
|
||||||
patch_custom_track_format(dllFilename);
|
patch_custom_track_format(dllFilename);
|
||||||
}
|
|
||||||
|
|
||||||
if (config->custom_exclude_from_version)
|
if (config->custom_exclude_from_version)
|
||||||
LOG("popnhax: Customs excluded from version folders\n"); //musichax_core_init took care of it
|
LOG("popnhax: Customs excluded from version folders\n"); //musichax_core_init took care of it
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "popnhax/config.h"
|
#include "popnhax/config.h"
|
||||||
|
|
||||||
|
extern uint32_t g_max_id;
|
||||||
|
|
||||||
|
bool is_excluded_folder(const char *input_filename);
|
||||||
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, uint8_t version);
|
bool patch_local_favorites(const char *dllFilename, uint8_t version);
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
#include "SearchFile.h"
|
#include "SearchFile.h"
|
||||||
|
|
||||||
#define PROGRAM_VERSION "1.11.beta2"
|
#define PROGRAM_VERSION "1.12.dev"
|
||||||
|
|
||||||
const char *g_game_dll_fn = NULL;
|
const char *g_game_dll_fn = NULL;
|
||||||
const char *g_config_fn = NULL;
|
const char *g_config_fn = NULL;
|
||||||
@ -201,6 +201,8 @@ PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_STR, struct popnhax_config, custom_category
|
|||||||
"/popnhax/custom_category_format")
|
"/popnhax/custom_category_format")
|
||||||
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_STR, struct popnhax_config, custom_track_title_format,
|
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_STR, struct popnhax_config, custom_track_title_format,
|
||||||
"/popnhax/custom_track_title_format")
|
"/popnhax/custom_track_title_format")
|
||||||
|
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_STR, struct popnhax_config, custom_track_title_format2,
|
||||||
|
"/popnhax/custom_track_title_format2")
|
||||||
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, local_favorites,
|
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, local_favorites,
|
||||||
"/popnhax/local_favorites")
|
"/popnhax/local_favorites")
|
||||||
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, ignore_music_limit,
|
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, ignore_music_limit,
|
||||||
@ -1411,10 +1413,57 @@ static bool patch_purelong()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_music_limit(uint32_t* limit) {
|
|
||||||
|
void (*real_normal0)();
|
||||||
|
void hook_normal0()
|
||||||
|
{
|
||||||
|
// getChartDifficulty returns 0xFFFFFFFF when there's no chart,
|
||||||
|
// but the game assumes there's always a normal chart so there's no check in this case
|
||||||
|
// and it returns 0... let's fix this
|
||||||
|
__asm("cmp ebx, 1\n"); //chart id
|
||||||
|
__asm("jne process_normal0\n");
|
||||||
|
__asm("cmp eax, 0\n"); //difficulty
|
||||||
|
__asm("jne process_normal0\n");
|
||||||
|
__asm("or eax, 0xFFFFFFFF\n");
|
||||||
|
__asm("process_normal0:\n");
|
||||||
|
real_normal0();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool patch_normal0()
|
||||||
|
{
|
||||||
DWORD dllSize = 0;
|
DWORD dllSize = 0;
|
||||||
char *data = getDllData(g_game_dll_fn, &dllSize);
|
char *data = getDllData(g_game_dll_fn, &dllSize);
|
||||||
|
|
||||||
|
{
|
||||||
|
int64_t pattern_offset = search(data, dllSize, "\x83\xC4\x08\x8B\xF8\x89\x7C\x24\x3C", 9, 0);
|
||||||
|
if (pattern_offset == -1) {
|
||||||
|
LOG("popnhax: Couldn't find song list display function\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t patch_addr = (int64_t)data + pattern_offset;
|
||||||
|
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_normal0,
|
||||||
|
(void **)&real_normal0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool get_music_limit(uint32_t* limit) {
|
||||||
|
// avoid doing the search multiple times
|
||||||
|
static uint32_t music_limit = 0;
|
||||||
|
if ( music_limit != 0 )
|
||||||
|
{
|
||||||
|
*limit = music_limit;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD dllSize = 0;
|
||||||
|
char *data = getDllData(g_game_dll_fn, &dllSize);
|
||||||
|
PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)((int64_t)data + ((PIMAGE_DOS_HEADER)data)->e_lfanew);
|
||||||
|
DWORD_PTR reloc_delta = (DWORD_PTR)((int64_t)data - headers->OptionalHeader.ImageBase);
|
||||||
|
|
||||||
{
|
{
|
||||||
int64_t string_loc = search(data, dllSize, "Illegal music no %d", 19, 0);
|
int64_t string_loc = search(data, dllSize, "Illegal music no %d", 19, 0);
|
||||||
if (string_loc == -1) {
|
if (string_loc == -1) {
|
||||||
@ -1422,16 +1471,18 @@ static bool get_music_limit(uint32_t* limit) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string_loc += reloc_delta; //reloc delta just in case
|
||||||
string_loc += 0x10000000; //entrypoint
|
string_loc += 0x10000000; //entrypoint
|
||||||
char *as_hex = (char *) &string_loc;
|
char *as_hex = (char *) &string_loc;
|
||||||
|
|
||||||
int64_t pattern_offset = search(data, dllSize, as_hex, 4, 0);
|
int64_t pattern_offset = search(data, dllSize, as_hex, 4, 0);
|
||||||
if (pattern_offset == -1) {
|
if (pattern_offset == -1) {
|
||||||
LOG("popnhax: patch_db: could not retrieve music limit test function\n");
|
LOG("popnhax: could not retrieve music limit test function\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t patch_addr = (int64_t)data + pattern_offset - 0x1F;
|
uint64_t patch_addr = (int64_t)data + pattern_offset - 0x1F;
|
||||||
*limit = *(uint32_t*)patch_addr;
|
*limit = *(uint32_t*)patch_addr;
|
||||||
|
music_limit = *limit;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1664,6 +1715,8 @@ static bool patch_database() {
|
|||||||
|
|
||||||
patch_purelong();
|
patch_purelong();
|
||||||
|
|
||||||
|
patch_normal0();
|
||||||
|
|
||||||
{
|
{
|
||||||
int64_t pattern_offset = search(data, dllSize, "\x8D\x44\x24\x10\x88\x4C\x24\x10\x88\x5C\x24\x11\x8D\x50\x01", 15, 0);
|
int64_t pattern_offset = search(data, dllSize, "\x8D\x44\x24\x10\x88\x4C\x24\x10\x88\x5C\x24\x11\x8D\x50\x01", 15, 0);
|
||||||
if (pattern_offset != -1) {
|
if (pattern_offset != -1) {
|
||||||
@ -3147,7 +3200,7 @@ static unsigned int __stdcall enhanced_polling_stats_proc(void *ctx)
|
|||||||
if (config.enhanced_polling_priority)
|
if (config.enhanced_polling_priority)
|
||||||
{
|
{
|
||||||
SetThreadPriority(GetCurrentThread(), config.enhanced_polling_priority);
|
SetThreadPriority(GetCurrentThread(), config.enhanced_polling_priority);
|
||||||
fprintf(stderr, "[Enhanced polling] Thread priority set to %d\n", GetThreadPriority(GetCurrentThread()));
|
LOG("[Enhanced polling] Thread priority set to %d\n", GetThreadPriority(GetCurrentThread()));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
@ -3236,7 +3289,7 @@ static unsigned int __stdcall enhanced_polling_proc(void *ctx)
|
|||||||
if (config.enhanced_polling_priority)
|
if (config.enhanced_polling_priority)
|
||||||
{
|
{
|
||||||
SetThreadPriority(GetCurrentThread(), config.enhanced_polling_priority);
|
SetThreadPriority(GetCurrentThread(), config.enhanced_polling_priority);
|
||||||
fprintf(stderr, "[Enhanced polling] Thread priority set to %d\n", GetThreadPriority(GetCurrentThread()));
|
LOG("[Enhanced polling] Thread priority set to %d\n", GetThreadPriority(GetCurrentThread()));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t curr_poll_time = 0;
|
uint32_t curr_poll_time = 0;
|
||||||
@ -5430,6 +5483,116 @@ uint8_t get_version()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool get_music_limit_from_file(const char *filepath, uint32_t *limit){
|
||||||
|
HANDLE hFile;
|
||||||
|
HANDLE hMap;
|
||||||
|
LPVOID lpBasePtr;
|
||||||
|
LARGE_INTEGER liFileSize;
|
||||||
|
|
||||||
|
hFile = CreateFile(filepath,
|
||||||
|
GENERIC_READ, // dwDesiredAccess
|
||||||
|
0, // dwShareMode
|
||||||
|
NULL, // lpSecurityAttributes
|
||||||
|
OPEN_EXISTING, // dwCreationDisposition
|
||||||
|
FILE_ATTRIBUTE_NORMAL, // dwFlagsAndAttributes
|
||||||
|
0); // hTemplateFile
|
||||||
|
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||||||
|
//file not existing is actually a good thing
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetFileSizeEx(hFile, &liFileSize)) {
|
||||||
|
LOG("popnhax: auto_diag: GetFileSize failed with error %ld\n", GetLastError());
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (liFileSize.QuadPart == 0) {
|
||||||
|
LOG("popnhax: auto_diag: popn22.dll file is empty?!\n");
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hMap = CreateFileMapping(
|
||||||
|
hFile,
|
||||||
|
NULL, // Mapping attributes
|
||||||
|
PAGE_READONLY, // Protection flags
|
||||||
|
0, // MaximumSizeHigh
|
||||||
|
0, // MaximumSizeLow
|
||||||
|
NULL); // Name
|
||||||
|
if (hMap == 0) {
|
||||||
|
LOG("popnhax: auto_diag: CreateFileMapping failed with error %ld\n", GetLastError());
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lpBasePtr = MapViewOfFile(
|
||||||
|
hMap,
|
||||||
|
FILE_MAP_READ, // dwDesiredAccess
|
||||||
|
0, // dwFileOffsetHigh
|
||||||
|
0, // dwFileOffsetLow
|
||||||
|
0); // dwNumberOfBytesToMap
|
||||||
|
if (lpBasePtr == NULL) {
|
||||||
|
LOG("popnhax: auto_diag: MapViewOfFile failed with error %ld\n", GetLastError());
|
||||||
|
CloseHandle(hMap);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *data = (char *)lpBasePtr;
|
||||||
|
int32_t delta = 0;
|
||||||
|
|
||||||
|
//first retrieve .rdata virtual and raw addresses to compute delta
|
||||||
|
{
|
||||||
|
int64_t string_loc = search(data, liFileSize.QuadPart, ".rdata", 6, 0);
|
||||||
|
if (string_loc == -1) {
|
||||||
|
LOG("popnhax: auto_diag: could not retrieve .rdata section header\n");
|
||||||
|
UnmapViewOfFile(lpBasePtr);
|
||||||
|
CloseHandle(hMap);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint32_t virtual_address = *(uint32_t *)(data + string_loc + 0x0C);
|
||||||
|
uint32_t raw_address = *(uint32_t *)(data + string_loc + 0x14);
|
||||||
|
delta = virtual_address - raw_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
//now attempt to find music limit from the dll
|
||||||
|
{
|
||||||
|
int64_t string_loc = search(data, liFileSize.QuadPart, "Illegal music no %d", 19, 0);
|
||||||
|
if (string_loc == -1) {
|
||||||
|
LOG("popnhax: auto_diag: could not retrieve music limit error string\n");
|
||||||
|
UnmapViewOfFile(lpBasePtr);
|
||||||
|
CloseHandle(hMap);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_loc += delta; //convert to virtual address
|
||||||
|
string_loc += 0x10000000; //entrypoint
|
||||||
|
|
||||||
|
char *as_hex = (char *) &string_loc;
|
||||||
|
int64_t pattern_offset = search(data, liFileSize.QuadPart, as_hex, 4, 0);
|
||||||
|
if (pattern_offset == -1) {
|
||||||
|
LOG("popnhax: auto_diag: could not retrieve music limit test function\n");
|
||||||
|
UnmapViewOfFile(lpBasePtr);
|
||||||
|
CloseHandle(hMap);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t patch_addr = (int64_t)data + pattern_offset - 0x1F;
|
||||||
|
*limit = *(uint32_t*)patch_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnmapViewOfFile(lpBasePtr);
|
||||||
|
CloseHandle(hMap);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
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: {
|
||||||
@ -5489,6 +5652,30 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
|||||||
if (g_game_dll_fn == NULL)
|
if (g_game_dll_fn == NULL)
|
||||||
g_game_dll_fn = strdup("popn22.dll");
|
g_game_dll_fn = strdup("popn22.dll");
|
||||||
|
|
||||||
|
if ( strcmp(g_game_dll_fn, "popn22.dll") == 0 )
|
||||||
|
{
|
||||||
|
//ensure you're not running popn22.dll from the modules subfolder
|
||||||
|
char filename[MAX_PATH];
|
||||||
|
if ( GetModuleFileName(GetModuleHandle(g_game_dll_fn), filename, MAX_PATH+1) != 0 )
|
||||||
|
{
|
||||||
|
if ( strstr(filename, "\\modules\\popn22.dll") != NULL )
|
||||||
|
{
|
||||||
|
LOG("WARNING: running popn22.dll from \"modules\" subfolder is not recommended with popnhax. Please copy dlls back to contents folder\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG("WARNING: auto_diag: Cannot retrieve module path (%ld)\n", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
//ensure there isn't a more recent version in modules subfolder
|
||||||
|
uint32_t modules_limit, current_limit;
|
||||||
|
if ( get_music_limit(¤t_limit)
|
||||||
|
&& get_music_limit_from_file("modules\\popn22.dll", &modules_limit)
|
||||||
|
&& (modules_limit > current_limit) )
|
||||||
|
{
|
||||||
|
LOG("ERROR: a newer version of popn22.dll seems to be present in modules subfolder (%d vs %d songs). Please copy dlls back to contents folder\n", modules_limit, current_limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (g_config_fn == NULL)
|
if (g_config_fn == NULL)
|
||||||
{
|
{
|
||||||
/* if there's an xml named like the custom game dll, it takes priority */
|
/* if there's an xml named like the custom game dll, it takes priority */
|
||||||
@ -5573,10 +5760,10 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
|||||||
char translation_path[64] = "";
|
char translation_path[64] = "";
|
||||||
|
|
||||||
/* parse */
|
/* parse */
|
||||||
if (config.force_datecode[0] != '\0')
|
if ( g_datecode_override != NULL )
|
||||||
{
|
{
|
||||||
|
|
||||||
sprintf(translation_folder, "_%s%s", config.force_datecode, "_tr");
|
sprintf(translation_folder, "_%s%s", g_datecode_override, "_tr");
|
||||||
sprintf(translation_path, "%s%s", "data_mods\\", translation_folder);
|
sprintf(translation_path, "%s%s", "data_mods\\", translation_folder);
|
||||||
if (access(translation_path, F_OK) != 0)
|
if (access(translation_path, F_OK) != 0)
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "util/patch.h"
|
#include "util/patch.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
#include "xmlhelper.h"
|
#include "xmlhelper.h"
|
||||||
|
#include "custom_categs.h"
|
||||||
|
|
||||||
#include "tableinfo.h"
|
#include "tableinfo.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
@ -855,6 +856,10 @@ void parse_musicdb(const char *input_filename, const char *target, struct popnha
|
|||||||
sizeof(idxStr));
|
sizeof(idxStr));
|
||||||
uint32_t idx = atoi(idxStr);
|
uint32_t idx = atoi(idxStr);
|
||||||
|
|
||||||
|
if (idx > g_max_id)
|
||||||
|
{
|
||||||
|
g_max_id = idx;
|
||||||
|
}
|
||||||
// Get an existing music entry in memory
|
// Get an existing music entry in memory
|
||||||
// If it exists, return the existing entry
|
// If it exists, return the existing entry
|
||||||
// If it doesn't exist, create a new entry in memory
|
// If it doesn't exist, create a new entry in memory
|
||||||
@ -917,10 +922,11 @@ void parse_musicdb(const char *input_filename, const char *target, struct popnha
|
|||||||
}
|
}
|
||||||
|
|
||||||
//force loading background for unilab
|
//force loading background for unilab
|
||||||
m->mask |= 0x100;
|
//m->mask |= 0x100;
|
||||||
|
|
||||||
if ( config->custom_categ
|
if ( config->custom_categ
|
||||||
&& config->custom_exclude_from_version
|
&& config->custom_exclude_from_version
|
||||||
|
&& !is_excluded_folder(input_filename)
|
||||||
&& idx >= config->custom_categ_min_songid
|
&& idx >= config->custom_categ_min_songid
|
||||||
&& (config->custom_categ_max_songid == 0 || idx <= config->custom_categ_max_songid) )
|
&& (config->custom_categ_max_songid == 0 || idx <= config->custom_categ_max_songid) )
|
||||||
{
|
{
|
||||||
|
@ -73,3 +73,8 @@ int search(char *haystack, size_t haystack_size, const char *needle, size_t need
|
|||||||
int res = _search((unsigned char*) haystack, haystack_size, (const unsigned char *)needle, needle_size, orig_offset, 0);
|
int res = _search((unsigned char*) haystack, haystack_size, (const unsigned char *)needle, needle_size, orig_offset, 0);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int search_debug(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset) {
|
||||||
|
int res = _search((unsigned char*) haystack, haystack_size, (const unsigned char *)needle, needle_size, orig_offset, 2);
|
||||||
|
return res;
|
||||||
|
}
|
@ -2,5 +2,6 @@
|
|||||||
#define __SEARCH_H__
|
#define __SEARCH_H__
|
||||||
|
|
||||||
int search(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset);
|
int search(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset);
|
||||||
|
int search_debug(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user