forked from Popn_Tools/popnhax
Compare commits
53 Commits
Author | SHA1 | Date | |
---|---|---|---|
60f1b172ef | |||
f5efc561c0 | |||
d23931f7f7 | |||
03104c4ae9 | |||
65f9c02f65 | |||
a00cbd6daa | |||
3a57387e6a | |||
d483cd61d7 | |||
cce17f9483 | |||
bed5eed9b6 | |||
87de9ed78a | |||
f1a78c8469 | |||
94377ea218 | |||
3c20bef186 | |||
6a21121e8b | |||
fc4a817824 | |||
899b311281 | |||
989350e051 | |||
6f2a340359 | |||
2b7ba52f1a | |||
c39bce4e1f | |||
eb56b39d1b | |||
aa7505206c | |||
27d6453bd3 | |||
ae12d608cd | |||
8795e55f02 | |||
f569e9dd4b | |||
4c5751a694 | |||
15b1bf20a7 | |||
4d618e5d1c | |||
607c2842b6 | |||
dd109549b0 | |||
edea20b403 | |||
3fef3f58bf | |||
6dfed35c5f | |||
15122be9b7 | |||
151c90352d | |||
0e1f365ac2 | |||
e9bdbaa9f7 | |||
814edb296f | |||
52048c2133 | |||
3083c62c67 | |||
11801e6340 | |||
f2802c5bd7 | |||
a4a4e53da1 | |||
fd529834b5 | |||
0cb685ef4b | |||
dc987c46ac | |||
4706d117a1 | |||
2535fba8d6 | |||
ccf3a4c8f8 | |||
c3e8eb5f13 | |||
783dafbe97 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*:Zone.Identifier
|
8
Makefile
8
Makefile
@ -232,8 +232,8 @@ $$(dll_$1_$2_$3) $$(implib_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) \
|
||||
$(ccache) $$(toolchain_$1)gcc -shared $$(srcdir_$3)/$3.def \
|
||||
-o $$(dll_$1_$2_$3) -Wl,--out-implib,$$(implib_$1_$2_$3) \
|
||||
$$^ $$(ldflags_$3) $(optflags_$1)
|
||||
strip -s $$(dll_$1_$2_$3)
|
||||
ranlib $$(implib_$1_$2_$3)
|
||||
$$(toolchain_$1)strip -s $$(dll_$1_$2_$3)
|
||||
$$(toolchain_$1)ranlib $$(implib_$1_$2_$3)
|
||||
|
||||
endef
|
||||
|
||||
@ -248,7 +248,7 @@ exe_$1_$2_$3 := $$(bindir_$1_$2)/$3.exe
|
||||
$$(exe_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) $$(absdpl_$1_$2_$3) \
|
||||
| $$(bindir_$1_$2)
|
||||
$(ccache) $$(toolchain_$1)gcc -o $$@ $$^ $$(ldflags_$3) $(optflags_$1)
|
||||
strip -s $$@
|
||||
$$(toolchain_$1)strip -s $$@
|
||||
|
||||
endef
|
||||
|
||||
@ -259,7 +259,7 @@ define t_import
|
||||
impdef_$1_$2_$3 ?= imports/import_$1_$2_$3.def
|
||||
|
||||
$$(bindir_$1_$2)/lib$3.a: $$(impdef_$1_$2_$3) | $$(bindir_$1_$2)
|
||||
dlltool -l $$@ -d $$<
|
||||
$$(toolchain_$1)dlltool -l $$@ -d $$<
|
||||
|
||||
endef
|
||||
|
||||
|
22
Module.mk
22
Module.mk
@ -14,17 +14,15 @@ include popnhax/Module.mk
|
||||
#
|
||||
|
||||
zipdir := $(BUILDDIR)/zip
|
||||
popnhax_version := $(shell grep "define PROGRAM_VERSION" popnhax/dllmain.cc | cut -d'"' -f2)
|
||||
|
||||
$(zipdir)/:
|
||||
mkdir -p $@
|
||||
$(BUILDDIR)/popnhax_v$(popnhax_version).zip: \
|
||||
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: \
|
||||
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
|
||||
all: $(BUILDDIR)/popnhax_v$(popnhax_version).zip
|
||||
|
26
README.md
26
README.md
@ -2,10 +2,32 @@
|
||||
|
||||
# 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
|
||||
|
||||
### 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
|
||||
|
||||
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/gmcmh.ifs
vendored
Normal file
BIN
dist/popnhax/data_mods/_popnhax_assets/tex/gmcmh.ifs
vendored
Normal file
Binary file not shown.
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 |
67
dist/popnhax/popnhax.xml
vendored
67
dist/popnhax/popnhax.xml
vendored
@ -5,6 +5,22 @@
|
||||
<patch_db __type="bool">0</patch_db>
|
||||
<!-- Force unlock music, charts, characters, and deco parts when applicable -->
|
||||
<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">2</custom_categ>
|
||||
<!-- Prevent customs from showing up in version folders -->
|
||||
<custom_exclude_from_version __type="bool">1</custom_exclude_from_version>
|
||||
<!-- Prevent customs from showing up in level folders -->
|
||||
<custom_exclude_from_level __type="bool">0</custom_exclude_from_level>
|
||||
|
||||
<!-- Other categories -->
|
||||
<!-- Bring back score challenge in the game for servers supporting it (only for kaimei onwards) -->
|
||||
<score_challenge __type="bool">0</score_challenge>
|
||||
<!-- 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>
|
||||
|
||||
<!-- Framerate -->
|
||||
<!-- Fix animation speed at higher framerate for a smoother experience (lower visual latency) -->
|
||||
<high_framerate __type="bool">0</high_framerate>
|
||||
|
||||
<!-- Classic patches -->
|
||||
<!-- Prevent crash on boot when using a different default audio source (aka HDMI audio patch) -->
|
||||
@ -27,10 +43,6 @@
|
||||
<!-- quick_retire with pfree also enables quick retry: press numpad 8 during song or on result screen to retry (keep holding to skip option select) -->
|
||||
<quick_retire __type="bool">0</quick_retire>
|
||||
|
||||
<!-- Network features -->
|
||||
<!-- Bring back score challenge in the game for servers supporting it (only for kaimei onwards) -->
|
||||
<score_challenge __type="bool">0</score_challenge>
|
||||
|
||||
<!-- Audio offset -->
|
||||
<!-- Offset the audio by x ms (negative plays audio earlier). This will disable keysounds -->
|
||||
<audio_offset __type="s8">0</audio_offset>
|
||||
@ -49,7 +61,7 @@
|
||||
<hispeed_default_bpm __type="u16">0</hispeed_default_bpm>
|
||||
|
||||
<!-- 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>
|
||||
<!-- Force full options by default (useful when no numpad is available) -->
|
||||
<force_full_opt __type="bool">0</force_full_opt>
|
||||
@ -87,7 +99,6 @@
|
||||
<!-- PLEASE USE OFFLINE ONLY -->
|
||||
<practice_mode __type="bool">0</practice_mode>
|
||||
<!-- Press 9 on option select screen to go back to song selection (requires quick_retire) -->
|
||||
<!-- Note: causes issues with sounds on song select -->
|
||||
<back_to_song_select __type="bool">0</back_to_song_select>
|
||||
|
||||
|
||||
@ -96,22 +107,22 @@
|
||||
======================================================================================== -->
|
||||
|
||||
<!-- Datecode and Multiboot -->
|
||||
<!-- Force a different datecode than the one found in ea3-config (yyyymmdd00) -->
|
||||
<force_datecode __type="str"></force_datecode>
|
||||
<!-- 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">auto</force_datecode>
|
||||
<!-- Also apply force_datecode to network packets -->
|
||||
<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>
|
||||
|
||||
<!-- Timing and lanes -->
|
||||
<!-- Base visual offset (value will be added to the base SD (-60) and base HD (-76) values) -->
|
||||
<base_offset __type="s8">0</base_offset>
|
||||
<!-- Automatically play keysounds during songs -->
|
||||
<disable_keysounds __type="bool">0</disable_keysounds>
|
||||
<!-- Offset the keysounds by x ms (negative is earlier). With disable_keysounds, becomes an audio offset -->
|
||||
<keysound_offset __type="s8">0</keysound_offset>
|
||||
<!-- Adjust pop-kun and beam brightness (won't affect long popkuns) -->
|
||||
<beam_brightness __type="s8">0</beam_brightness>
|
||||
<!-- Disable the builtin frame limiter (faster/smoother animations at 120fps+) -->
|
||||
<fps_uncap __type="bool">0</fps_uncap>
|
||||
<!-- 1000Hz polling thread priority (for enhanced_polling only, might cause crashes on some systems if set too high)
|
||||
values THREAD_PRIORITY_LOWEST -2
|
||||
THREAD_PRIORITY_BELOW_NORMAL -1
|
||||
@ -121,15 +132,41 @@
|
||||
THREAD_PRIORITY_TIME_CRITICAL 15 -->
|
||||
<enhanced_polling_priority __type="s8">1</enhanced_polling_priority>
|
||||
|
||||
<!-- Song db patches -->
|
||||
<!-- Auto select patch file from data_mods folder (will detect datecode from ea3-config or force_datecode option) -->
|
||||
<!-- Framerate -->
|
||||
<!-- Reference fps value for high_framerate animation speed (0: use monitor refreshrate and disable frame limiter) -->
|
||||
<high_framerate_fps __type="u16">0</high_framerate_fps>
|
||||
<!-- Tune the builtin frame limiter the closest to high_framerate_fps -->
|
||||
<high_framerate_limiter __type="bool">1</high_framerate_limiter>
|
||||
<!-- Disable the builtin frame limiter -->
|
||||
<fps_uncap __type="bool">0</fps_uncap>
|
||||
|
||||
<!-- Song db patches (requires patch_db) -->
|
||||
<!-- 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>
|
||||
<!-- Manually set XML file containing patches (requires patch_xml_auto to be disabled) -->
|
||||
<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>
|
||||
<!-- 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>
|
||||
<!-- Do not perform music limit checks for patch_xml_auto (not recommended) -->
|
||||
<ignore_music_limit __type="bool">0</ignore_music_limit>
|
||||
|
||||
<!-- Custom category options (requires patch_db) -->
|
||||
<!-- Also exclude omnimix (song id < 3000) tracks from version/level (requires custom_exclude_from_level or custom_exclude_from_version) -->
|
||||
<exclude_omni __type="bool">0</exclude_omni>
|
||||
<!-- Any new chart added to an existing song moves the song to the customs folder -->
|
||||
<partial_entries __type="bool">0</partial_entries>
|
||||
<!-- Minimum songid for a song to be seen as "custom" (e.g. use 4000 for real customs only) -->
|
||||
<custom_categ_min_songid __type="u16">0</custom_categ_min_songid>
|
||||
<!-- Category title for customs -->
|
||||
<custom_category_title __type="str">Customs</custom_category_title>
|
||||
<!-- 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>
|
||||
<!-- 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>
|
||||
<!-- 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 -->
|
||||
<!-- Disable .dict string replacements and .ips patches -->
|
||||
|
@ -14,4 +14,5 @@ srcpp_popnhax := \
|
||||
dllmain.cc \
|
||||
loader.cc \
|
||||
SearchFile.cc \
|
||||
translation.cc
|
||||
translation.cc \
|
||||
custom_categs.cc
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
struct popnhax_config {
|
||||
uint8_t game_version;
|
||||
bool practice_mode;
|
||||
bool hidden_is_offset;
|
||||
bool iidx_hard_gauge;
|
||||
@ -14,6 +15,10 @@ struct popnhax_config {
|
||||
bool quick_retire;
|
||||
bool back_to_song_select;
|
||||
bool score_challenge;
|
||||
uint8_t custom_categ;
|
||||
uint16_t custom_categ_min_songid;
|
||||
bool custom_exclude_from_version;
|
||||
bool custom_exclude_from_level;
|
||||
bool force_hd_timing;
|
||||
uint8_t force_hd_resolution;
|
||||
bool force_unlocks;
|
||||
@ -26,12 +31,14 @@ struct popnhax_config {
|
||||
bool force_full_opt;
|
||||
bool netvs_off;
|
||||
bool guidese_off;
|
||||
bool local_favorites;
|
||||
|
||||
bool patch_db;
|
||||
bool disable_expansions;
|
||||
bool disable_redirection;
|
||||
bool disable_multiboot;
|
||||
bool patch_xml_auto;
|
||||
bool ignore_music_limit;
|
||||
char patch_xml_filename[MAX_PATH];
|
||||
char force_datecode[11];
|
||||
bool network_datecode;
|
||||
@ -51,6 +58,16 @@ struct popnhax_config {
|
||||
uint8_t survival_gauge;
|
||||
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];
|
||||
char custom_track_title_format2[64];
|
||||
bool exclude_omni;
|
||||
bool partial_entries;
|
||||
bool high_framerate;
|
||||
bool high_framerate_limiter;
|
||||
uint16_t high_framerate_fps;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
1115
popnhax/custom_categs.cc
Normal file
1115
popnhax/custom_categs.cc
Normal file
File diff suppressed because it is too large
Load Diff
24
popnhax/custom_categs.h
Normal file
24
popnhax/custom_categs.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __CUSTOM_CATEGS_H__
|
||||
#define __CUSTOM_CATEGS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "popnhax/config.h"
|
||||
#include "util/bst.h"
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
uint32_t size;
|
||||
uint32_t *songlist; //really is a (songlist_t *) pointer
|
||||
} subcategory_s;
|
||||
|
||||
extern uint32_t g_max_id;
|
||||
extern bst_t *g_customs_bst;
|
||||
|
||||
void init_subcategories();
|
||||
void add_song_to_subcateg(uint32_t songid, subcategory_s* subcateg);
|
||||
subcategory_s* get_subcateg(const char *title);
|
||||
|
||||
bool patch_custom_categs(const char *dllFilename, struct popnhax_config *config);
|
||||
bool patch_local_favorites(const char *dllFilename, uint8_t version);
|
||||
|
||||
#endif
|
4530
popnhax/dllmain.cc
4530
popnhax/dllmain.cc
File diff suppressed because it is too large
Load Diff
@ -4,8 +4,11 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include "imports/avs.h"
|
||||
#include "util/bst.h"
|
||||
#include "util/patch.h"
|
||||
#include "util/log.h"
|
||||
#include "xmlhelper.h"
|
||||
#include "custom_categs.h"
|
||||
|
||||
#include "tableinfo.h"
|
||||
#include "loader.h"
|
||||
@ -66,7 +69,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<uint32_t, int8_t> chart_type_overrides;
|
||||
|
||||
@ -818,12 +821,76 @@ void parse_charadb(const char *input_filename, const char *target) {
|
||||
free(config_xml);
|
||||
}
|
||||
|
||||
void parse_musicdb(const char *input_filename, const char *target) {
|
||||
static char *get_subcateg_title(const char* path) {
|
||||
char *categ_name = NULL;
|
||||
char filename[64];
|
||||
|
||||
//try to open "folderpath/_name.txt"
|
||||
size_t len = (size_t)(strchr(path+10, '\\')-(path));
|
||||
strncpy(filename, path, len);
|
||||
sprintf(filename+len, "\\_name.txt");
|
||||
|
||||
FILE *file = fopen(filename, "r");
|
||||
if ( file != NULL ) {
|
||||
//if it has a custom title, use it
|
||||
char line[64];
|
||||
if (fgets(line, sizeof(line), file)) {
|
||||
//handle UTF-8 BOM since that could be common
|
||||
categ_name = (memcmp(line, "\xEF\xBB\xBF", 3) == 0) ? strdup(line+3) : strdup(line);
|
||||
LOG("%s sets subcategory name to %s\n", filename, categ_name);
|
||||
}
|
||||
fclose(file);
|
||||
} else { // or just keep folder name by itself (cut "data_mods")
|
||||
len = (size_t)(strchr(path+10, '\\')-(path+10));
|
||||
categ_name = (char*) malloc(len+1);
|
||||
strncpy(categ_name, path+10, len);
|
||||
categ_name[len] = '\0';
|
||||
}
|
||||
|
||||
return categ_name;
|
||||
}
|
||||
|
||||
#define F_OK 0
|
||||
static bool is_excluded_folder(const char *path)
|
||||
{
|
||||
char filename[64];
|
||||
|
||||
//try to open "folderpath/_exclude"
|
||||
size_t len = (size_t)(strchr(path+10, '\\')-(path));
|
||||
strncpy(filename, path, len);
|
||||
sprintf(filename+len, "\\_exclude");
|
||||
if (access(filename, F_OK) == 0)
|
||||
{
|
||||
LOG("%s causes folder to be excluded from customs (contents will be treated as regular songs)\n", filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( path[strlen("data_mods/")] == '_' )
|
||||
{
|
||||
filename[strchr(path+10, '\\')-path] = '\0';
|
||||
LOG("%s starting with _ causes folder to be excluded from customs (contents will be treated as regular songs)\n", filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool excluded = (config->custom_categ && is_excluded_folder(input_filename));
|
||||
|
||||
char *subcateg_title = NULL;
|
||||
subcategory_s *subcateg = NULL;
|
||||
if (config->custom_categ == 2 && !excluded)
|
||||
{
|
||||
subcateg_title = get_subcateg_title(input_filename);
|
||||
subcateg = get_subcateg(subcateg_title); //will return a new one if not found
|
||||
}
|
||||
|
||||
property *config_xml = load_prop_file(input_filename);
|
||||
|
||||
if (target && strlen(target) > 0) {
|
||||
@ -859,7 +926,22 @@ void parse_musicdb(const char *input_filename, const char *target) {
|
||||
// If it doesn't exist, create a new entry in memory
|
||||
// Update the data in-place and make all parameters optional
|
||||
music_entry *m = get_music(idx);
|
||||
bool is_fresh = m == NULL;
|
||||
bool is_fresh = m == NULL; // ie. not part of internal songdb
|
||||
bool is_gone = ( m != NULL && strcmp((const char*) m->title_ptr, "\x81\x5D") == 0); // removed entries all have this title (SJIS "-")
|
||||
|
||||
// Update customs/omni songid list
|
||||
if ( is_fresh || is_gone || config->partial_entries )
|
||||
{
|
||||
if ( idx >= config->custom_categ_min_songid && !excluded && bst_search(g_customs_bst, idx) == NULL )
|
||||
{
|
||||
g_customs_bst = bst_insert(g_customs_bst, idx);
|
||||
//LOG("%d inserted into customs bst\n", idx);
|
||||
if (config->custom_categ == 2)
|
||||
{
|
||||
add_song_to_subcateg(idx, subcateg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_fresh) {
|
||||
// Default music entry
|
||||
@ -915,6 +997,16 @@ void parse_musicdb(const char *input_filename, const char *target) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( config->custom_categ
|
||||
&& config->custom_exclude_from_version
|
||||
&& !excluded
|
||||
&& idx >= config->custom_categ_min_songid
|
||||
&& ( is_fresh || config->exclude_omni ) )
|
||||
{
|
||||
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)) {
|
||||
@ -990,9 +1082,14 @@ void parse_musicdb(const char *input_filename, const char *target) {
|
||||
}
|
||||
|
||||
free(config_xml);
|
||||
|
||||
if (config->custom_categ == 2 && !excluded)
|
||||
{
|
||||
free(subcateg_title);
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
@ -1008,16 +1105,19 @@ void load_databases(const char *target_datecode) {
|
||||
parse_charadb(result[i].c_str(), target_datecode);
|
||||
}
|
||||
|
||||
if (config->custom_categ == 2)
|
||||
init_subcategories();
|
||||
|
||||
for(uint16_t i=0;i<result.size();i++)
|
||||
{
|
||||
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 +1136,10 @@ 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 +1285,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++) {
|
||||
|
@ -2,10 +2,11 @@
|
||||
#define __LOADER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#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,
|
||||
|
@ -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;
|
||||
}
|
@ -2,6 +2,7 @@ libs += util
|
||||
|
||||
srcpp_util := \
|
||||
fuzzy_search.cc \
|
||||
bst.cc \
|
||||
search.cc \
|
||||
cmdline.cc \
|
||||
patch.cc \
|
||||
|
34
util/bst.cc
Normal file
34
util/bst.cc
Normal file
@ -0,0 +1,34 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bst.h"
|
||||
|
||||
bst_t* bst_search(bst_t *root, uint32_t val)
|
||||
{
|
||||
if( root == NULL || root->data == val )
|
||||
return root;
|
||||
else if( val > (root->data) )
|
||||
return bst_search(root->right, val);
|
||||
else
|
||||
return bst_search(root->left,val);
|
||||
}
|
||||
|
||||
bst_t* bst_insert(bst_t *root, uint32_t val)
|
||||
{
|
||||
if ( root == NULL )
|
||||
{
|
||||
bst_t *p;
|
||||
p = (bst_t *)malloc(sizeof(bst_t));
|
||||
p->data = val;
|
||||
p->left = NULL;
|
||||
p->right = NULL;
|
||||
return p;
|
||||
}
|
||||
else if ( val > root->data )
|
||||
root->right = bst_insert(root->right, val);
|
||||
else
|
||||
root->left = bst_insert(root->left, val);
|
||||
|
||||
return root;
|
||||
}
|
14
util/bst.h
Normal file
14
util/bst.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __BST_H__
|
||||
#define __BST_H__
|
||||
|
||||
typedef struct bst_s
|
||||
{
|
||||
uint32_t data;
|
||||
struct bst_s *right;
|
||||
struct bst_s *left;
|
||||
} bst_t;
|
||||
|
||||
bst_t* bst_search(bst_t *root, uint32_t val);
|
||||
bst_t* bst_insert(bst_t *root, uint32_t val);
|
||||
|
||||
#endif
|
@ -26,7 +26,7 @@ static void badCharHeuristic(const unsigned char *str, int size, int* badchar) {
|
||||
|
||||
#define DEBUG_SEARCH 0
|
||||
|
||||
int _search(unsigned char *haystack, size_t haystack_size, const unsigned char *needle, size_t needle_size, int orig_offset, int debug) {
|
||||
int _search(unsigned char *haystack, size_t haystack_size, const unsigned char *needle, size_t needle_size, int orig_offset, bool wildcards, int debug) {
|
||||
int badchar[NO_OF_CHARS];
|
||||
|
||||
badCharHeuristic(needle, needle_size, badchar);
|
||||
@ -46,12 +46,21 @@ int _search(unsigned char *haystack, size_t haystack_size, const unsigned char *
|
||||
LOG("pat...");
|
||||
for (size_t i = 0; i < needle_size; i++)
|
||||
{
|
||||
LOG("%02x ", needle[i]);
|
||||
if (wildcards && needle[i] == '?')
|
||||
LOG("** ");
|
||||
else
|
||||
LOG("%02x ", needle[i]);
|
||||
}
|
||||
LOG("\n");
|
||||
}
|
||||
while (j >= 0 && needle[j] == haystack[orig_offset + s + j])
|
||||
j--;
|
||||
if ( wildcards )
|
||||
{
|
||||
while (j >= 0 && ( needle[j] == '?' || needle[j] == haystack[orig_offset + s + j]) )
|
||||
j--;
|
||||
} else {
|
||||
while (j >= 0 && ( needle[j] == haystack[orig_offset + s + j]) )
|
||||
j--;
|
||||
}
|
||||
|
||||
if (j < 0) {
|
||||
if (debug)
|
||||
@ -70,6 +79,21 @@ int _search(unsigned char *haystack, size_t haystack_size, const unsigned char *
|
||||
}
|
||||
|
||||
int search(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, 0);
|
||||
int res = _search((unsigned char*) haystack, haystack_size, (const unsigned char *)needle, needle_size, orig_offset, false, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
int wildcard_search(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, true, 0);
|
||||
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, false, 2);
|
||||
return res;
|
||||
}
|
||||
|
||||
int wildcard_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, true, 2);
|
||||
return res;
|
||||
}
|
@ -2,5 +2,8 @@
|
||||
#define __SEARCH_H__
|
||||
|
||||
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);
|
||||
int wildcard_search(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset);
|
||||
int wildcard_search_debug(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user