diff --git a/dist/popnhax/popnhax.xml b/dist/popnhax/popnhax.xml
index 8f21a63..fda72de 100644
--- a/dist/popnhax/popnhax.xml
+++ b/dist/popnhax/popnhax.xml
@@ -7,6 +7,16 @@
0
0
+
+ 0
+
+ 0
+
+
+
+ 0
+
+ 0
@@ -29,10 +39,6 @@
0
-
-
- 0
-
0
@@ -134,10 +140,18 @@
0
0
+
+
4000
0
+
+ Customs
+
+ [ol:4][olc:d92f0d]%s
+
+
diff --git a/popnhax/config.h b/popnhax/config.h
index 5397ef7..b5aad2c 100644
--- a/popnhax/config.h
+++ b/popnhax/config.h
@@ -17,6 +17,8 @@ struct popnhax_config {
uint8_t custom_categ;
uint16_t custom_categ_min_songid;
uint16_t custom_categ_max_songid;
+ bool custom_exclude_from_version;
+ bool custom_exclude_from_level;
bool force_hd_timing;
uint8_t force_hd_resolution;
bool force_unlocks;
@@ -29,6 +31,7 @@ struct popnhax_config {
bool force_full_opt;
bool netvs_off;
bool guidese_off;
+ bool local_favorites;
bool patch_db;
bool disable_expansions;
@@ -55,6 +58,9 @@ struct popnhax_config {
bool survival_iidx;
bool survival_spicy;
int8_t base_offset;
+ char custom_category_title[16];
+ char custom_category_format[64];
+ char custom_track_title_format[64];
};
#endif
diff --git a/popnhax/custom_categs.cc b/popnhax/custom_categs.cc
index 00eb695..181040d 100644
--- a/popnhax/custom_categs.cc
+++ b/popnhax/custom_categs.cc
@@ -35,10 +35,10 @@ bool g_subcategmode = false;
uint32_t g_min_id = 4000;
uint32_t g_max_id = 0;
-const char *g_categname = "Customs";
+char *g_categname;
const char *g_categicon = "cate_cc";
-const char *g_categformat = "[ol:4][olc:d92f0d]%s";
-const char *g_customformat = " [rz:3][c:d92f0d]%s[/rz][/c]";
+char *g_categformat;
+char *g_customformat;
char *g_string_addr;
uint8_t idx = 0;
@@ -85,12 +85,7 @@ void prepare_favorite_list(){
if ( file == NULL )
{
- file = fopen("data_mods\\default.fav", "rb");
-
- if (file == NULL)
- {
- return;
- }
+ return;
}
char line[32];
@@ -121,12 +116,7 @@ void commit_favorites()
if ( file == NULL )
{
- file = fopen("data_mods\\default.fav", "w");
-
- if (file == NULL)
- {
- return;
- }
+ return;
}
for (uint32_t i = 0; i < favorites_count; i++)
@@ -213,6 +203,10 @@ void categ_inject_favorites()
__asm("cmp ecx, 0\n");
__asm("jne skip_fake_login\n");
__asm("mov dword ptr [edx], 0xFF000001\n");
+ __asm("sub edx, 0x19D\n"); //back to popn friendid offset
+ __asm("mov dword ptr [edx], 0x61666564\n"); // "defa"
+ __asm("add edx, 0x04\n");
+ __asm("mov dword ptr [edx], 0x00746C75\n"); // "ult"
__asm("skip_fake_login:\n");
//retrieve songlist according to friend id
@@ -627,7 +621,7 @@ void hook_artist_printf()
real_artist_printf();
}
-static bool patch_custom_highlight(const char *game_dll_fn) {
+static bool patch_custom_track_format(const char *game_dll_fn) {
DWORD dllSize = 0;
char *data = getDllData(game_dll_fn, &dllSize);
@@ -635,7 +629,7 @@ static bool patch_custom_highlight(const char *game_dll_fn) {
{
int64_t pattern_offset = search(data, dllSize, "\x83\xC4\x08\x8B\x44\x24\x50\x50\x68", 9, 0);
if (pattern_offset == -1) {
- LOG("popnhax: custom_highlight: cannot find song/genre print function\n");
+ LOG("popnhax: custom_track_format: cannot find song/genre print function\n");
return false;
}
@@ -649,7 +643,7 @@ static bool patch_custom_highlight(const char *game_dll_fn) {
{
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) {
- LOG("popnhax: custom_highlight: cannot find artist print function\n");
+ LOG("popnhax: custom_track_format: cannot find artist print function\n");
return false;
}
@@ -659,6 +653,7 @@ static bool patch_custom_highlight(const char *game_dll_fn) {
(void **)&real_artist_printf);
}
+ LOG("popnhax: custom_track_format: custom format injected\n");
return true;
}
@@ -670,7 +665,7 @@ static bool patch_favorite_categ(const char *game_dll_fn) {
if (add_song_in_list == NULL) {
int64_t pattern_offset = search(data, dllSize, "\x8B\x4D\x10\x8B\x5D\x0C\x8B\xF1", 8, 0);
if (pattern_offset == -1) {
- LOG("popnhax: custom_favorites: cannot find add_song_in_list function\n");
+ LOG("popnhax: local_favorites: cannot find add_song_in_list function\n");
return false;
}
@@ -682,7 +677,7 @@ static bool patch_favorite_categ(const char *game_dll_fn) {
{
int64_t pattern_offset = search(data, dllSize, "\x83\xF8\x10\x77\x75\xFF\x24\x85", 8, 0);
if (pattern_offset == -1) {
- LOG("popnhax: custom_favorites: cannot find category jump table\n");
+ LOG("popnhax: local_favorites: cannot find category jump table\n");
return false;
}
@@ -698,7 +693,7 @@ static bool patch_favorite_categ(const char *game_dll_fn) {
//this is the same function used in score challenge patch, checking if we're logged in... but now we just directly retrieve the address
int64_t pattern_offset = search(data, dllSize, "\x8B\x01\x8B\x50\x14\xFF\xE2\xC3\xCC\xCC\xCC\xCC", 12, 0);
if (pattern_offset == -1) {
- LOG("popnhax: custom_favorites: cannot find check if logged function\n");
+ LOG("popnhax: local_favorites: cannot find check if logged function\n");
return false;
}
@@ -707,35 +702,50 @@ static bool patch_favorite_categ(const char *game_dll_fn) {
//hook result screen to replace 3 functions
{
- int64_t pattern_offset = search(data, dllSize, "\xBF\x07\x00\x00\x00\xC6\x85\x61\xD3", 9, 0);
- if (pattern_offset == -1) {
- LOG("popnhax: custom_favorites: cannot find result screen function\n");
+ int64_t first_loc = search(data, dllSize, "\xBF\x07\x00\x00\x00\xC6\x85\x61\xD3", 9, 0);
+ if (first_loc == -1) {
+ LOG("popnhax: local_favorites: cannot find result screen function\n");
return false;
}
//song is in favorite
- uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x5F);
- uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01));
- uint64_t function_addr = function_call_addr+5+function_offset;
- MH_CreateHook((LPVOID)function_addr, (LPVOID)hook_song_is_in_favorite,
+ int64_t second_loc = search(data, 1000, "\x8B\xC8\xE8", 3, first_loc);
+ if (second_loc == -1) {
+ LOG("popnhax: local_favorites: cannot retrieve is song in favorites call\n");
+ return false;
+ }
+ uint64_t function_call_addr = (int64_t)(data + second_loc + 0x02);
+ uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01));
+ uint64_t function_addr = function_call_addr+5+function_offset;
+ MH_CreateHook((LPVOID)function_addr, (LPVOID)hook_song_is_in_favorite,
(void **)&real_song_is_in_favorite);
-//add to favorites
- uint64_t function2_call_addr = (int64_t)(data + pattern_offset + 0xBA);
- uint32_t function2_offset = *((uint32_t*)(function2_call_addr +0x01));
- uint64_t function2_addr = function2_call_addr+5+function2_offset;
- MH_CreateHook((LPVOID)function2_addr, (LPVOID)hook_add_to_favorite,
- (void **)&real_add_to_favorite);
-
//remove from favorites
- uint64_t function3_call_addr = (int64_t)(data + pattern_offset + 0x89);
- uint32_t function3_offset = *((uint32_t*)(function3_call_addr +0x01));
- uint64_t function3_addr = function3_call_addr+5+function3_offset;
- MH_CreateHook((LPVOID)function3_addr, (LPVOID)hook_remove_from_favorite,
+ int64_t third_loc = search(data, 1000, "\x6A\x01\x6A\x00\x68", 5, second_loc);
+ if (third_loc == -1) {
+ LOG("popnhax: local_favorites: cannot retrieve remove from favorites call\n");
+ return false;
+ }
+ uint64_t function2_call_addr = (int64_t)(data + third_loc - 0x05);
+ uint32_t function2_offset = *((uint32_t*)(function2_call_addr +0x01));
+ uint64_t function2_addr = function2_call_addr+5+function2_offset;
+ MH_CreateHook((LPVOID)function2_addr, (LPVOID)hook_remove_from_favorite,
(void **)&real_remove_from_favorite);
+//add to favorites
+ int64_t fourth_loc = search(data, 1000, "\x6A\x01\x6A\x00\x68", 5, third_loc+2);
+ if (fourth_loc == -1) {
+ LOG("popnhax: local_favorites: cannot retrieve add to favorites call\n");
+ return false;
+ }
+ uint64_t function3_call_addr = (int64_t)(data + fourth_loc - 0x05);
+ uint32_t function3_offset = *((uint32_t*)(function3_call_addr +0x01));
+ uint64_t function3_addr = function3_call_addr+5+function3_offset;
+ MH_CreateHook((LPVOID)function3_addr, (LPVOID)hook_add_to_favorite,
+ (void **)&real_add_to_favorite);
+
}
- LOG("popnhax: custom_favorites: favorite category handling replaced\n");
+ LOG("popnhax: local_favorites: favorite category handling replaced\n");
return true;
}
@@ -986,10 +996,97 @@ bool load_favorites(){
return true;
}
-bool patch_custom_categs(const char *dllFilename, uint8_t mode, uint16_t min, uint16_t max)
+void (*real_getversion)();
+void hook_getversion()
{
- g_min_id = min;
- g_max_id = max;
+ __asm("cmp eax, _g_min_id\n");
+ __asm("jb real_version\n");
+ __asm("cmp dword ptr _g_max_id, 0\n");
+ __asm("je force_version_0\n");
+ __asm("cmp eax, _g_max_id\n");
+ __asm("ja real_version\n");
+
+ __asm("force_version_0:\n");
+ __asm("mov eax, 0x00\n");
+ __asm("ret\n");
+
+ __asm("real_version:\n");
+ real_getversion();
+}
+
+void (*real_getcsversion)();
+void hook_getcsversion()
+{
+ __asm("cmp eax, _g_min_id\n");
+ __asm("jb real_csversion\n");
+ __asm("cmp dword ptr _g_max_id, 0\n");
+ __asm("je force_csversion_0\n");
+ __asm("cmp eax, _g_max_id\n");
+ __asm("ja real_csversion\n");
+
+ __asm("force_csversion_0:\n");
+ __asm("mov eax, 0x00\n");
+ __asm("ret\n");
+
+ __asm("real_csversion:\n");
+ real_getcsversion();
+}
+
+bool patch_exclude(const char *game_dll_fn)
+{
+
+ DWORD dllSize = 0;
+ char *data = getDllData(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: exclude_customs: cannot find songlist processing table\n");
+ return false;
+ }
+
+ uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x07);
+ uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01));
+ uint64_t function_addr = function_call_addr+5+function_offset;
+
+ MH_CreateHook((LPVOID)function_addr, (LPVOID)hook_getversion,
+ (void **)&real_getversion);
+ }
+ /*
+ //exclude from CS version category too
+ {
+ int64_t pattern_offset = search(data, dllSize, "\xB8\x13\x05\x00\x00\x66\x3B\xF0", 8, 0);
+ if (pattern_offset == -1) {
+ LOG("popnhax: exclude_customs: cannot find getCSVersion calling function\n");
+ return false;
+ }
+
+ uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x0C);
+ uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01));
+ uint64_t function_addr = function_call_addr+5+function_offset;
+
+ MH_CreateHook((LPVOID)function_addr, (LPVOID)hook_getcsversion,
+ (void **)&real_getcsversion);
+ }*/
+
+ LOG("popnhax: exclude_customs: Custom songs excluded from version listings\n");
+ return true;
+}
+
+bool patch_custom_categs(const char *dllFilename, struct popnhax_config *config)
+{
+LOG("config is %p\n", (void*)config);
+ g_min_id = config->custom_categ_min_songid;
+ g_max_id = config->custom_categ_max_songid;
+ uint8_t mode = config->custom_categ;
+
+ g_categname = config->custom_category_title;
+ g_categformat = config->custom_category_format;
+
+LOG("custom songid range is [%d;%d]\n", g_min_id, g_max_id);
+LOG("category name is %s\n", g_categname);
+LOG("category format is %s\n", g_categformat);
+
#if SIMPLE_CATEG_ALLOC == 1
songlist = (uint32_t*)calloc(1,5);
#endif
@@ -999,10 +1096,18 @@ bool patch_custom_categs(const char *dllFilename, uint8_t mode, uint16_t min, ui
load_databases();
}
- patch_custom_highlight(dllFilename);
-
-load_favorites();
-patch_favorite_categ(dllFilename);
+ if ( config->custom_track_title_format[0] != '\0' )
+ {
+ g_customformat = config->custom_track_title_format;
+LOG("custom title format is %s\n", g_customformat);
+ patch_custom_track_format(dllFilename);
+ }
return patch_custom_categ(dllFilename);
+}
+
+bool patch_local_favorites(const char *dllFilename)
+{
+ //load_favorites();
+ return patch_favorite_categ(dllFilename);
}
\ No newline at end of file
diff --git a/popnhax/custom_categs.h b/popnhax/custom_categs.h
index 15d48d3..c27929b 100644
--- a/popnhax/custom_categs.h
+++ b/popnhax/custom_categs.h
@@ -2,7 +2,9 @@
#define __CUSTOM_CATEGS_H__
#include
+#include "popnhax/config.h"
-bool patch_custom_categs(const char *dllFilename, uint8_t mode, uint16_t min, uint16_t max);
+bool patch_custom_categs(const char *dllFilename, struct popnhax_config *config);
+bool patch_local_favorites(const char *dllFilename);
#endif
diff --git a/popnhax/dllmain.cc b/popnhax/dllmain.cc
index 9b67792..eca8228 100644
--- a/popnhax/dllmain.cc
+++ b/popnhax/dllmain.cc
@@ -191,6 +191,18 @@ PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_U16, struct popnhax_config, custom_categ_mi
"/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_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, custom_exclude_from_version,
+ "/popnhax/custom_exclude_from_version")
+PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, custom_exclude_from_level,
+ "/popnhax/custom_exclude_from_level")
+PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_STR, struct popnhax_config, custom_category_title,
+ "/popnhax/custom_category_title")
+PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_STR, struct popnhax_config, custom_category_format,
+ "/popnhax/custom_category_format")
+PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_STR, struct popnhax_config, custom_track_title_format,
+ "/popnhax/custom_track_title_format")
+PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, local_favorites,
+ "/popnhax/local_favorites")
PSMAP_END
enum BufferIndexes {
@@ -1441,7 +1453,7 @@ static bool patch_datecode(char *datecode) {
return true;
}
-static bool patch_database(uint8_t force_unlocks) {
+static bool patch_database() {
DWORD dllSize = 0;
char *data = getDllData(g_game_dll_fn, &dllSize);
@@ -1519,10 +1531,7 @@ static bool patch_database(uint8_t force_unlocks) {
config.disable_expansions = true;
}
- musichax_core_init(
- force_unlocks,
- !config.disable_expansions,
- !config.disable_redirection,
+ musichax_core_init(&config,
target,
data,
@@ -1554,6 +1563,9 @@ static bool patch_database(uint8_t force_unlocks) {
);
limit_table[STYLE_TABLE_IDX] = new_limit_table[STYLE_TABLE_IDX];
+ if (config.custom_exclude_from_version)
+ LOG("popnhax: custom_exclude_from_version: customs excluded from version folders\n"); //musichax_core_init took care of it
+
if (config.disable_redirection) {
LOG("Redirection-related code is disabled, buffer address, buffer size and related patches will not be applied");
printf("Redirection-related code is disabled, buffer address, buffer size and related patches will not be applied");
@@ -5589,8 +5601,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
patch_db_power_points();
patch_db_fix_cursor();
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_custom_categs(g_game_dll_fn, &config);
+ patch_database();
}
if (config.force_unlocks) {
@@ -5603,6 +5615,9 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
force_unlock_deco_parts();
}
+ if (config.local_favorites)
+ patch_local_favorites(g_game_dll_fn);
+
if (config.force_full_opt)
option_full();
diff --git a/popnhax/loader.cc b/popnhax/loader.cc
index aecde91..cf9cd50 100644
--- a/popnhax/loader.cc
+++ b/popnhax/loader.cc
@@ -5,6 +5,7 @@
#include "imports/avs.h"
#include "util/patch.h"
+#include "util/log.h"
#include "xmlhelper.h"
#include "tableinfo.h"
@@ -66,7 +67,7 @@ uint32_t add_chart(uint32_t cur_idx, uint8_t *folder, uint8_t *filename, int32_t
uint32_t file_type, uint16_t used_keys, bool override_idx);
void parse_charadb(const char *input_filename, const char *target);
-void parse_musicdb(const char *input_filename, const char *target);
+void parse_musicdb(const char *input_filename, const char *target, struct popnhax_config *config);
std::map chart_type_overrides;
@@ -818,7 +819,7 @@ void parse_charadb(const char *input_filename, const char *target) {
free(config_xml);
}
-void parse_musicdb(const char *input_filename, const char *target) {
+void parse_musicdb(const char *input_filename, const char *target, struct popnhax_config *config) {
if (!file_exists(input_filename)) {
printf("Couldn't find %s, skipping...\n", input_filename);
return;
@@ -915,6 +916,18 @@ void parse_musicdb(const char *input_filename, const char *target) {
}
}
+ //force loading background for unilab
+ m->mask |= 0x100;
+
+ if ( config->custom_categ
+ && config->custom_exclude_from_version
+ && idx >= config->custom_categ_min_songid
+ && (config->custom_categ_max_songid == 0 || idx <= config->custom_categ_max_songid) )
+ {
+ m->cs_version = 0;
+ m->folder = 0;
+ }
+
if ((prop_chart = property_search(config_xml, prop, "charts/chart"))) {
for (; prop_chart != NULL; prop_chart = property_node_traversal(
prop_chart, TRAVERSE_NEXT_SEARCH_RESULT)) {
@@ -992,7 +1005,7 @@ void parse_musicdb(const char *input_filename, const char *target) {
free(config_xml);
}
-void load_databases(const char *target_datecode) {
+void load_databases(const char *target_datecode, struct popnhax_config *config) {
SearchFile s;
printf("XML db files search...\n");
@@ -1013,11 +1026,11 @@ void load_databases(const char *target_datecode) {
if ( strstr(result[i].c_str(), "musicdb") == NULL )
continue;
printf("(musicdb) Loading %s...\n", result[i].c_str());
- parse_musicdb(result[i].c_str(), target_datecode);
+ parse_musicdb(result[i].c_str(), target_datecode, config);
}
}
-void musichax_core_init(bool force_unlocks, bool is_expansion_allowed, bool is_redirection_allowed,
+void musichax_core_init(struct popnhax_config *config,
char *target_datecode,
char *base_data,
@@ -1036,6 +1049,11 @@ void musichax_core_init(bool force_unlocks, bool is_expansion_allowed, bool is_r
uint64_t chara_size, uint64_t *new_chara_size, char *orig_chara_data,
uint8_t **new_chara_table) {
+
+ bool force_unlocks = config->force_unlocks;
+ bool is_expansion_allowed = !config->disable_expansions;
+ bool is_redirection_allowed = !config->disable_redirection;
+
if (style_size > fontstyle_table_size) {
fontstyle_table_size = style_size;
}
@@ -1181,7 +1199,7 @@ void musichax_core_init(bool force_unlocks, bool is_expansion_allowed, bool is_r
cur->chara_x, cur->chara_y, cur->unk1, cur->display_bpm, cur->hold_flags, true);
}
- load_databases((const char *)target_datecode);
+ load_databases((const char *)target_datecode, config);
// Add some filler charts to fix some bugs (hack)
for (int i = 0; i < 10; i++) {
diff --git a/popnhax/loader.h b/popnhax/loader.h
index 4d91185..161a83c 100644
--- a/popnhax/loader.h
+++ b/popnhax/loader.h
@@ -2,10 +2,11 @@
#define __LOADER_H__
#include
+#include "popnhax/config.h"
int8_t get_chart_type_override(uint8_t *, uint32_t, uint32_t);
-void musichax_core_init(bool force_unlocks, bool is_expansion_allowed, bool is_redirection_allowed,
+void musichax_core_init(struct popnhax_config *config,
char *target_datecode, char *base_data, uint64_t music_size,
uint64_t *new_music_size, char *orig_music_data, uint8_t **new_music_table,
uint64_t chart_size, uint64_t *new_chart_size, char *orig_chart_data,
diff --git a/popnhax/translation.cc b/popnhax/translation.cc
index dff5f1f..31e40e2 100644
--- a/popnhax/translation.cc
+++ b/popnhax/translation.cc
@@ -56,10 +56,10 @@ bool patch_sjis(const char *dllFilename, const char *find, uint8_t find_size, in
} while (valid_sjis);
if (dump_dict)
- {
+ {
//fprintf(g_dict_applied_fp,"0x%x;%s;%s\n",rva_to_offset(dllFilename, (uint32_t)*offset),(char*)find,(char*)replace);
fprintf(g_dict_applied_fp,";%s;%s\n",(char*)find,(char*)replace);
- }
+ }
/* safety check replace is not too big */
uint8_t free_size = find_size-1;
do
@@ -83,41 +83,41 @@ bool patch_sjis(const char *dllFilename, const char *find, uint8_t find_size, in
#define RELOC_HIGHLOW 0x3
static void perform_reloc(char *data, int32_t delta, uint32_t ext_base, uint32_t ext_delta)
-{
- PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)((int64_t)data + ((PIMAGE_DOS_HEADER)data)->e_lfanew);
- PIMAGE_DATA_DIRECTORY datadir = &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
- PIMAGE_BASE_RELOCATION reloc = (PIMAGE_BASE_RELOCATION)(data + datadir->VirtualAddress);
+{
+ PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)((int64_t)data + ((PIMAGE_DOS_HEADER)data)->e_lfanew);
+ PIMAGE_DATA_DIRECTORY datadir = &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ PIMAGE_BASE_RELOCATION reloc = (PIMAGE_BASE_RELOCATION)(data + datadir->VirtualAddress);
- while(reloc->VirtualAddress != 0)
- {
- if (reloc->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION))
- {
- DWORD relocDescNb = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
- LPWORD relocDescList = (LPWORD)((LPBYTE)reloc + sizeof(IMAGE_BASE_RELOCATION));
+ while(reloc->VirtualAddress != 0)
+ {
+ if (reloc->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION))
+ {
+ DWORD relocDescNb = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
+ LPWORD relocDescList = (LPWORD)((LPBYTE)reloc + sizeof(IMAGE_BASE_RELOCATION));
- for (DWORD i = 0; i < relocDescNb; i++)
- {
- if ( ((relocDescList[i])>>12) == RELOC_HIGHLOW )
- {
- DWORD_PTR *p = (DWORD_PTR *)( data + (reloc->VirtualAddress + ((relocDescList[i])&0x0FFF)) );
- /* Change the offset to adapt to injected module base address */
-
- DWORD old_prot;
- VirtualProtect((LPVOID)p, 4, PAGE_EXECUTE_READWRITE, &old_prot);
- *p += delta;
- if ( ext_base > 0 && *p >= ((int64_t)data+ext_base) )
- {
- //fprintf(stderr,"reloc rva %lx to ext ", *p);
- *p += ext_delta;
- //fprintf(stderr," %lx\n", *p);
- }
- VirtualProtect((LPVOID)p, 4, old_prot, &old_prot);
- }
- }
- }
- /* Set reloc pointer to the next relocation block */
- reloc = (PIMAGE_BASE_RELOCATION)((LPBYTE)reloc + reloc->SizeOfBlock);
- }
+ for (DWORD i = 0; i < relocDescNb; i++)
+ {
+ if ( ((relocDescList[i])>>12) == RELOC_HIGHLOW )
+ {
+ DWORD_PTR *p = (DWORD_PTR *)( data + (reloc->VirtualAddress + ((relocDescList[i])&0x0FFF)) );
+ /* Change the offset to adapt to injected module base address */
+
+ DWORD old_prot;
+ VirtualProtect((LPVOID)p, 4, PAGE_EXECUTE_READWRITE, &old_prot);
+ *p += delta;
+ if ( ext_base > 0 && *p >= ((int64_t)data+ext_base) )
+ {
+ //fprintf(stderr,"reloc rva %lx to ext ", *p);
+ *p += ext_delta;
+ //fprintf(stderr," %lx\n", *p);
+ }
+ VirtualProtect((LPVOID)p, 4, old_prot, &old_prot);
+ }
+ }
+ }
+ /* Set reloc pointer to the next relocation block */
+ reloc = (PIMAGE_BASE_RELOCATION)((LPBYTE)reloc + reloc->SizeOfBlock);
+ }
}
#define BYTE3_TO_UINT(bp) \
@@ -134,191 +134,191 @@ static void perform_reloc(char *data, int32_t delta, uint32_t ext_base, uint32_t
static bool patch_translation_ips(const char *dllFilename, const char *foldername, bool dump_dll)
{
#define IPS_READ(_ips_read_dest, _ips_read_size, _ips_read_name) do {\
- if ( fread(_ips_read_dest, 1, _ips_read_size, ips_fp) != _ips_read_size )\
- {\
- LOG("CANNOT READ %s\n", _ips_read_name);\
- return false;\
- }\
+ if ( fread(_ips_read_dest, 1, _ips_read_size, ips_fp) != _ips_read_size )\
+ {\
+ LOG("CANNOT READ %s\n", _ips_read_name);\
+ return false;\
+ }\
} while (0)
- DWORD dllSize = 0;
+ DWORD dllSize = 0;
char *data = getDllData(dllFilename, &dllSize);
- char dict_filepath[64];
+ char dict_filepath[64];
sprintf(dict_filepath, "%s%s%s", "data_mods\\", foldername, "\\popn22.ips");
- FILE *ips_fp = fopen(dict_filepath, "rb");
+ FILE *ips_fp = fopen(dict_filepath, "rb");
if (ips_fp == NULL)
- {
+ {
return false;
- }
+ }
- LOG("popnhax: translation: popn22.ips found\n");
+ LOG("popnhax: translation: popn22.ips found\n");
- /* check .ips header */
- uint8_t buffer[8];
- if (fread(&buffer, 1, 5, ips_fp) != 5)
- return false;
-
- if (memcmp(buffer, "PATCH", 5) != 0)
- {
- LOG("popnhax: translation: invalid .ips header\n");
- return false;
- }
+ /* check .ips header */
+ uint8_t buffer[8];
+ if (fread(&buffer, 1, 5, ips_fp) != 5)
+ return false;
- if (dump_dll)
- {
- LOG("popnhax: translation debug: dump dll before patch\n");
- FILE* dllrtp = fopen("dllruntime.dll", "wb");
- fwrite(data, 1, dllSize, dllrtp);
- fclose(dllrtp);
- LOG("popnhax: translation debug: dllruntime.dll generated\n");
- }
+ if (memcmp(buffer, "PATCH", 5) != 0)
+ {
+ LOG("popnhax: translation: invalid .ips header\n");
+ return false;
+ }
- /* undo all relocation so you can apply ips patch with correct values, we'll reapply them later */
- 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);
- perform_reloc(data, -1*reloc_delta, 0, 0);
+ if (dump_dll)
+ {
+ LOG("popnhax: translation debug: dump dll before patch\n");
+ FILE* dllrtp = fopen("dllruntime.dll", "wb");
+ fwrite(data, 1, dllSize, dllrtp);
+ fclose(dllrtp);
+ LOG("popnhax: translation debug: dllruntime.dll generated\n");
+ }
- uint32_t trans_base = 0; /* eclale patch adds new section header which I'm relocating */
- uint32_t trans_base_offset = 0;
- uint32_t trans_rebase = 0;
+ /* undo all relocation so you can apply ips patch with correct values, we'll reapply them later */
+ 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);
+ perform_reloc(data, -1*reloc_delta, 0, 0);
- uint32_t offset = 0;
- uint16_t size = 0;
- uint16_t count = 0;
- uint8_t replace[MAX_REPLACE_SIZE] = {0};
-
- while ( fread(&offset, 1, 3, ips_fp) == 3 && offset != IPS_EOF )
- {
- bool skip = false;
-
- /* need to convert offset to rva before applying patch since the dll is already in memory */
- uint8_t *bp = (uint8_t *)&offset;
- offset = BYTE3_TO_UINT(bp);
- uint32_t rva;
+ uint32_t trans_base = 0; /* eclale patch adds new section header which I'm relocating */
+ uint32_t trans_base_offset = 0;
+ uint32_t trans_rebase = 0;
- if (offset < 0x400)
- {
- rva = offset;
- }
- else if ( !offset_to_rva(dllFilename, offset, &rva) )
- {
- LOG("Invalid offset %x conversion. Skip this patch\n", offset);
- skip = true;
- /* still need to go through the loop to increase read pointer accordingly */
- }
-
- IPS_READ(&size, 2, "SIZE");
- bp = (uint8_t *)&size;
- size = BYTE2_TO_UINT(bp);
- ++count;
-
- //LOG("%03d: offset %x converted to %x\nsize %d\n", count, offset, rva,size);
- if ( size == 0 )
- {
- uint8_t value;
-
- IPS_READ(&size, 2, "RLE SIZE");
- bp = (uint8_t *)&size;
- size = BYTE2_TO_UINT(bp);
+ uint32_t offset = 0;
+ uint16_t size = 0;
+ uint16_t count = 0;
+ uint8_t replace[MAX_REPLACE_SIZE] = {0};
- IPS_READ(&value, 1, "RLE VALUE");
-
- //LOG("RLE PATCH! size %d value %d\n", size, value);
- //fprintf(stderr, "rle value %d (%d bytes)\n",value, size);
- if ( size > MAX_REPLACE_SIZE )
- {
- LOG("RLE replacement too big.\n");
- return false;
- }
- memset(replace, value, size);
- }
- else
- {
- if ( size > MAX_REPLACE_SIZE )
- {
-
- uint16_t remaining = size;
- uint32_t chunk_rva = rva;
-
- do {
- /* patch in multiple chunks */
- LOG("multipart patch: rva %x, %d remaining\n", chunk_rva, remaining);
- IPS_READ(&replace, MAX_REPLACE_SIZE, "DATA");
-
- if ( !skip )
- patch_memory((int64_t)data+chunk_rva, (char *)replace, MAX_REPLACE_SIZE);
-
- remaining -= MAX_REPLACE_SIZE;
- chunk_rva += MAX_REPLACE_SIZE;
-
- } while (remaining > MAX_REPLACE_SIZE);
-
- size = remaining;
- rva = chunk_rva;
-
- }
-
- IPS_READ(&replace, size, "DATA");
- }
-
- /* eclale woes */
- if ( trans_base == 0 && rva < 0x400 )
- {
- if (memcmp(replace, ".trans", 6) == 0)
- {
- trans_base = *(uint32_t*)(replace+0x0C);
- trans_base_offset = *(uint32_t*)(replace+0x14);
- //LOG("found .trans section at offset %x rva %x\n", trans_base_offset, trans_base);
- }
- }
+ while ( fread(&offset, 1, 3, ips_fp) == 3 && offset != IPS_EOF )
+ {
+ bool skip = false;
- if ( trans_base_offset != 0 && offset >= trans_base_offset )
- {
- /* patching into new section */
- if ( trans_rebase == 0 )
- {
- HANDLE hProc = GetCurrentProcess();
- LPVOID myAlloc = VirtualAllocEx(hProc, NULL, 16384, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- if (myAlloc == NULL)
- {
- LOG("Failed to allocate memory in target process. Error: 0x%lX\n", GetLastError());
- exit(0);
- }
- trans_rebase = (uint32_t)myAlloc - (uint32_t)data;
- //LOG( "virtualalloc worked; address %x (%p)\n", trans_rebase, myAlloc);
+ /* need to convert offset to rva before applying patch since the dll is already in memory */
+ uint8_t *bp = (uint8_t *)&offset;
+ offset = BYTE3_TO_UINT(bp);
+ uint32_t rva;
- /* seems useless */
- //memcpy(replace, &trans_rebase, 4);
- //patch_memory((int64_t)data+0x02d4, (char *)replace, 4);
- //LOG( "patched .trans section address to %02x %02x %02x %02x\n", replace[0], replace[1], replace[2], replace[3]);
- }
- rva = (offset - trans_base_offset) + trans_rebase;
- //LOG( "off %x - base %x + rebase %x = %x\n\n", offset, trans_base_offset, trans_rebase, rva);
- //LOG( "offset %x relocated to rva %x.", offset, rva);
- }
-
- if ( !skip )
- {
- patch_memory((int64_t)data+rva, (char *)replace, size);
- }
- }
+ if (offset < 0x400)
+ {
+ rva = offset;
+ }
+ else if ( !offset_to_rva(dllFilename, offset, &rva) )
+ {
+ LOG("Invalid offset %x conversion. Skip this patch\n", offset);
+ skip = true;
+ /* still need to go through the loop to increase read pointer accordingly */
+ }
- /* redo all relocation now the dll is patched */
- perform_reloc(data, reloc_delta, trans_base, trans_rebase-trans_base);
+ IPS_READ(&size, 2, "SIZE");
+ bp = (uint8_t *)&size;
+ size = BYTE2_TO_UINT(bp);
+ ++count;
- LOG("popnhax: translation: IPS patch applied.\n");
-
- if (dump_dll)
- {
- LOG("popnhax: translation debug: dump dll after patch\n");
- FILE* dllrtp = fopen("dllruntime_patched.dll", "wb");
- fwrite(data, 1, dllSize, dllrtp);
- fclose(dllrtp);
- }
+ //LOG("%03d: offset %x converted to %x\nsize %d\n", count, offset, rva,size);
+ if ( size == 0 )
+ {
+ uint8_t value;
- fclose(ips_fp);
- return true;
+ IPS_READ(&size, 2, "RLE SIZE");
+ bp = (uint8_t *)&size;
+ size = BYTE2_TO_UINT(bp);
+
+ IPS_READ(&value, 1, "RLE VALUE");
+
+ //LOG("RLE PATCH! size %d value %d\n", size, value);
+ //fprintf(stderr, "rle value %d (%d bytes)\n",value, size);
+ if ( size > MAX_REPLACE_SIZE )
+ {
+ LOG("RLE replacement too big.\n");
+ return false;
+ }
+ memset(replace, value, size);
+ }
+ else
+ {
+ if ( size > MAX_REPLACE_SIZE )
+ {
+
+ uint16_t remaining = size;
+ uint32_t chunk_rva = rva;
+
+ do {
+ /* patch in multiple chunks */
+ LOG("multipart patch: rva %x, %d remaining\n", chunk_rva, remaining);
+ IPS_READ(&replace, MAX_REPLACE_SIZE, "DATA");
+
+ if ( !skip )
+ patch_memory((int64_t)data+chunk_rva, (char *)replace, MAX_REPLACE_SIZE);
+
+ remaining -= MAX_REPLACE_SIZE;
+ chunk_rva += MAX_REPLACE_SIZE;
+
+ } while (remaining > MAX_REPLACE_SIZE);
+
+ size = remaining;
+ rva = chunk_rva;
+
+ }
+
+ IPS_READ(&replace, size, "DATA");
+ }
+
+ /* eclale woes */
+ if ( trans_base == 0 && rva < 0x400 )
+ {
+ if (memcmp(replace, ".trans", 6) == 0)
+ {
+ trans_base = *(uint32_t*)(replace+0x0C);
+ trans_base_offset = *(uint32_t*)(replace+0x14);
+ //LOG("found .trans section at offset %x rva %x\n", trans_base_offset, trans_base);
+ }
+ }
+
+ if ( trans_base_offset != 0 && offset >= trans_base_offset )
+ {
+ /* patching into new section */
+ if ( trans_rebase == 0 )
+ {
+ HANDLE hProc = GetCurrentProcess();
+ LPVOID myAlloc = VirtualAllocEx(hProc, NULL, 16384, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ if (myAlloc == NULL)
+ {
+ LOG("Failed to allocate memory in target process. Error: 0x%lX\n", GetLastError());
+ exit(0);
+ }
+ trans_rebase = (uint32_t)myAlloc - (uint32_t)data;
+ //LOG( "virtualalloc worked; address %x (%p)\n", trans_rebase, myAlloc);
+
+ /* seems useless */
+ //memcpy(replace, &trans_rebase, 4);
+ //patch_memory((int64_t)data+0x02d4, (char *)replace, 4);
+ //LOG( "patched .trans section address to %02x %02x %02x %02x\n", replace[0], replace[1], replace[2], replace[3]);
+ }
+ rva = (offset - trans_base_offset) + trans_rebase;
+ //LOG( "off %x - base %x + rebase %x = %x\n\n", offset, trans_base_offset, trans_rebase, rva);
+ //LOG( "offset %x relocated to rva %x.", offset, rva);
+ }
+
+ if ( !skip )
+ {
+ patch_memory((int64_t)data+rva, (char *)replace, size);
+ }
+ }
+
+ /* redo all relocation now the dll is patched */
+ perform_reloc(data, reloc_delta, trans_base, trans_rebase-trans_base);
+
+ LOG("popnhax: translation: IPS patch applied.\n");
+
+ if (dump_dll)
+ {
+ LOG("popnhax: translation debug: dump dll after patch\n");
+ FILE* dllrtp = fopen("dllruntime_patched.dll", "wb");
+ fwrite(data, 1, dllSize, dllrtp);
+ fclose(dllrtp);
+ }
+
+ fclose(ips_fp);
+ return true;
#undef IPS_READ
}
@@ -331,16 +331,16 @@ static bool patch_translation_dict(const char *dllFilename, const char *folderna
uint8_t word_count = 0;
uint8_t orig_size = 0;
- char dict_filepath[64];
+ char dict_filepath[64];
sprintf(dict_filepath, "%s%s%s", "data_mods\\", foldername, "\\popn22.dict");
- FILE *dict_fp = fopen(dict_filepath, "rb");
-
+ FILE *dict_fp = fopen(dict_filepath, "rb");
+
if (dict_fp == NULL)
- {
- return false;
- }
-
- LOG("popnhax: translation: popn22.dict file found\n");
+ {
+ return false;
+ }
+
+ LOG("popnhax: translation: popn22.dict file found\n");
#define STATE_WAITING 0
#define STATE_ORIGINAL 1
@@ -435,11 +435,11 @@ static bool patch_translation_dict(const char *dllFilename, const char *folderna
bool patch_translate(const char *dllFilename, const char *folder, bool debug)
{
- bool ips_done = false;
- bool dict_done = false;
+ bool ips_done = false;
+ bool dict_done = false;
- ips_done = patch_translation_ips(dllFilename, folder, debug);
- dict_done = patch_translation_dict(dllFilename, folder, debug);
-
- return ips_done || dict_done;
+ ips_done = patch_translation_ips(dllFilename, folder, debug);
+ dict_done = patch_translation_dict(dllFilename, folder, debug);
+
+ return ips_done || dict_done;
}
\ No newline at end of file