forked from Popn_Tools/popnhax
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
9b4b2dfee6 |
@ -21,8 +21,6 @@ $(zipdir)/:
|
||||
$(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 $@ $^
|
||||
|
BIN
dist/popnhax/D3d9.dll
vendored
BIN
dist/popnhax/D3d9.dll
vendored
Binary file not shown.
BIN
dist/popnhax/ifs_hook.dll
vendored
BIN
dist/popnhax/ifs_hook.dll
vendored
Binary file not shown.
152
dist/popnhax/popnhax.xml
vendored
152
dist/popnhax/popnhax.xml
vendored
@ -1,148 +1,34 @@
|
||||
<?xml version='1.0' encoding='shift-jis'?>
|
||||
<popnhax>
|
||||
<!-- Databases -->
|
||||
<!-- Enable database modifications (omnimix, custom tracks) -->
|
||||
<patch_db __type="bool">0</patch_db>
|
||||
<!-- Force unlock music, charts, characters, and deco parts when applicable -->
|
||||
<force_unlocks __type="bool">0</force_unlocks>
|
||||
|
||||
<!-- Classic patches -->
|
||||
<!-- Prevent crash on boot when using a different default audio source (aka HDMI audio patch) -->
|
||||
<audio_source_fix __type="bool">0</audio_source_fix>
|
||||
<!-- Hidden+ setting (press 0 for advanced options) is now an offset adjust (negative means you have to hit earlier) -->
|
||||
<hidden_is_offset __type="bool">0</hidden_is_offset>
|
||||
<!-- Premium free (unlimited stages per credit) -->
|
||||
<pfree __type="bool">0</pfree>
|
||||
<!-- Press numpad 9 to exit song, or on result screen to exit session (great for pfree!) -->
|
||||
<quick_retire __type="bool">0</quick_retire>
|
||||
<!-- HD timing for pcb_type=0 (0: no, 1: force HD timing offset (for SD cab with CRT), 2: also set resolution to 768p but center text (for SD cab with LCD mod)) -->
|
||||
<hd_on_sd __type="u8">0</hd_on_sd>
|
||||
<!-- Force unlock music, charts, characters, and deco parts -->
|
||||
<force_unlocks __type="bool">1</force_unlocks>
|
||||
<!-- Prevent Windows volume from being reset on boot -->
|
||||
<unset_volume __type="bool">0</unset_volume>
|
||||
<!-- Force booting directly into event mode -->
|
||||
<event_mode __type="bool">0</event_mode>
|
||||
<event_mode __type="bool">1</event_mode>
|
||||
<!-- Remove the timer completely without event mode -->
|
||||
<remove_timer __type="bool">0</remove_timer>
|
||||
<!-- or Freeze the timer at 10 seconds after counting down -->
|
||||
<freeze_timer __type="bool">0</freeze_timer>
|
||||
<!-- Force skip menu and long note tutorials without a card -->
|
||||
<skip_tutorials __type="bool">0</skip_tutorials>
|
||||
|
||||
<!-- Stage management -->
|
||||
<!-- Premium free (unlimited stages per credit) -->
|
||||
<pfree __type="bool">0</pfree>
|
||||
<!-- Press numpad 9 in song to retire instantly, or on result screen to leave game session (thank you for playing) -->
|
||||
<!-- 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>
|
||||
|
||||
<!-- Visual offset -->
|
||||
<!-- Hidden+ setting (press 0 for advanced options) is now a visual offset adjust (negative means you have to hit earlier) -->
|
||||
<hidden_is_offset __type="bool">0</hidden_is_offset>
|
||||
<!-- Display offset adjust value on score result screen (requires hidden_is_offset, won't be sent over network) -->
|
||||
<show_offset __type="bool">0</show_offset>
|
||||
|
||||
<!-- Option patches -->
|
||||
<!-- Auto set hi-speed to match previously set BPM (0: off, 1: target higher bpm on soflan, 2: target lower bpm on soflan, 3: target longest bpm on soflan) -->
|
||||
<hispeed_auto __type="u8">0</hispeed_auto>
|
||||
<!-- Default target BPM, 0 to disable (requires hispeed_auto) -->
|
||||
<!-- Note: target is still updated when manually changing hi-speed (except soflan and "?" charts) -->
|
||||
<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% ) -->
|
||||
<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>
|
||||
<!-- Guide SE defaults to OFF (useful for Battle mode) -->
|
||||
<guidese_off __type="bool">0</guidese_off>
|
||||
<!-- All net Ojama default to OFF (useful for Local mode) -->
|
||||
<netvs_off __type="bool">0</netvs_off>
|
||||
|
||||
<!-- Result screen display patches -->
|
||||
<!-- Details on result screen by default (no need to press yellow button) -->
|
||||
<show_details __type="bool">0</show_details>
|
||||
<!-- Fast/Slow counter on result screen even on judge+ off/lost/panic -->
|
||||
<show_fast_slow __type="bool">0</show_fast_slow>
|
||||
|
||||
<!-- Input polling -->
|
||||
<!-- 1000Hz polling rate (no more shifting timing windows/magic bpm, consistent scoring independently of framerate) -->
|
||||
<enhanced_polling __type="bool">0</enhanced_polling>
|
||||
<!-- button release debounce time in ms (for enhanced_polling only) -->
|
||||
<debounce __type="u8">5</debounce>
|
||||
<!-- 1000Hz polling stats (display onscreen info to check performance on your system) -->
|
||||
<enhanced_polling_stats __type="bool">0</enhanced_polling_stats>
|
||||
|
||||
<!-- LCD mod on CRT cabs -->
|
||||
<!-- HD timing for pcb_type=0 -->
|
||||
<force_hd_timing __type="bool">0</force_hd_timing>
|
||||
<!-- HD resolution for pcb_type=0 (0: no, 1: keep texts as on HD cab (smaller LCD mod), 2: center texts (32" LCD mod) ) -->
|
||||
<force_hd_resolution __type="u8">0</force_hd_resolution>
|
||||
|
||||
<!-- ====================
|
||||
END OF USER SETTINGS
|
||||
==================== -->
|
||||
|
||||
<!-- EXPERIMENTAL PATCHES -->
|
||||
<!-- Enable practice mode menu, (r-ran, constant chart speed, slow motion, etc...) -->
|
||||
<!-- 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>
|
||||
|
||||
|
||||
<!-- ========================================================================================
|
||||
DEBUG OPTIONS FOLLOW (GENERALLY SHOULD NOT BE CHANGED UNLESS YOU KNOW WHAT YOU'RE DOING)
|
||||
======================================================================================== -->
|
||||
|
||||
<!-- Datecode and Multiboot -->
|
||||
<!-- Force a different datecode than the one found in ea3-config (yyyymmdd00) -->
|
||||
<force_datecode __type="str"></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 __type="bool">0</disable_multiboot>
|
||||
|
||||
<!-- Timing and lanes -->
|
||||
<!-- 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
|
||||
THREAD_PRIORITY_NORMAL 0
|
||||
THREAD_PRIORITY_ABOVE_NORMAL 1
|
||||
THREAD_PRIORITY_HIGHEST 2
|
||||
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) -->
|
||||
<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>
|
||||
<skip_tutorials __type="bool">1</skip_tutorials>
|
||||
<!-- Settings for database hooking patches follow: -->
|
||||
<!-- Enable database modifications -->
|
||||
<patch_db __type="bool">1</patch_db>
|
||||
<!-- Force the newly created buffers to be the same size as the original buffers -->
|
||||
<disable_expansions __type="bool">0</disable_expansions>
|
||||
<!-- Copy the new table information over top the old tables (automatically enables disable_expansions) -->
|
||||
<disable_redirection __type="bool">0</disable_redirection>
|
||||
|
||||
<!-- Translation -->
|
||||
<!-- Disable .dict string replacements and .ips patches -->
|
||||
<disable_translation __type="bool">0</disable_translation>
|
||||
<!-- Dump applied translations and dll runtime data to help debug translation -->
|
||||
<translation_debug __type="bool">0</translation_debug>
|
||||
|
||||
<!-- HARD Gauge alteration modes -->
|
||||
<!-- Turn hard gauge into survival gauge (1: former COURSE gauge (-3.42%), 2: NORMAL gauge decrease rate (-4.99%), 3: IIDX HARD gauge decrease rate (-9%), 4: HARD gauge decrease rate (-19.94%)) -->
|
||||
<survival_gauge __type="u8">0</survival_gauge>
|
||||
<!-- Survival gauge has IIDX-like decrease rate adjustment (decrease amount halved when gauge is at 30% or less) -->
|
||||
<survival_iidx __type="bool">0</survival_iidx>
|
||||
<!-- Set survival gauge increase rate to spicy (+01/+01 instead of +02/+01) -->
|
||||
<survival_spicy __type="bool">0</survival_spicy>
|
||||
|
||||
<!-- Autoload latest patch file (highest datecode) from data_mods folder -->
|
||||
<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>
|
||||
</popnhax>
|
||||
|
@ -13,5 +13,4 @@ libs_popnhax := \
|
||||
srcpp_popnhax := \
|
||||
dllmain.cc \
|
||||
loader.cc \
|
||||
SearchFile.cc \
|
||||
translation.cc
|
||||
SearchFile.cc
|
||||
|
@ -4,53 +4,22 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
struct popnhax_config {
|
||||
bool practice_mode;
|
||||
bool hidden_is_offset;
|
||||
bool iidx_hard_gauge;
|
||||
bool show_offset;
|
||||
bool show_fast_slow;
|
||||
bool show_details;
|
||||
bool pfree;
|
||||
bool quick_retire;
|
||||
bool back_to_song_select;
|
||||
bool score_challenge;
|
||||
bool force_hd_timing;
|
||||
uint8_t force_hd_resolution;
|
||||
uint8_t hd_on_sd;
|
||||
bool force_unlocks;
|
||||
bool audio_source_fix;
|
||||
bool unset_volume;
|
||||
bool event_mode;
|
||||
bool remove_timer;
|
||||
bool freeze_timer;
|
||||
bool skip_tutorials;
|
||||
bool force_full_opt;
|
||||
bool netvs_off;
|
||||
bool guidese_off;
|
||||
|
||||
bool patch_db;
|
||||
bool disable_expansions;
|
||||
bool disable_redirection;
|
||||
bool disable_multiboot;
|
||||
bool patch_xml_auto;
|
||||
char patch_xml_filename[MAX_PATH];
|
||||
char force_datecode[11];
|
||||
bool network_datecode;
|
||||
int8_t audio_offset;
|
||||
bool disable_keysounds;
|
||||
int8_t keysound_offset;
|
||||
int8_t beam_brightness;
|
||||
bool fps_uncap;
|
||||
bool disable_translation;
|
||||
bool translation_debug;
|
||||
bool enhanced_polling;
|
||||
uint8_t debounce;
|
||||
bool enhanced_polling_stats;
|
||||
int8_t enhanced_polling_priority;
|
||||
uint8_t hispeed_auto;
|
||||
uint16_t hispeed_default_bpm;
|
||||
uint8_t survival_gauge;
|
||||
bool survival_iidx;
|
||||
bool survival_spicy;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
4795
popnhax/dllmain.cc
4795
popnhax/dllmain.cc
File diff suppressed because it is too large
Load Diff
@ -683,16 +683,16 @@ void parse_charadb(const char *input_filename, const char *target) {
|
||||
property_node_refer(config_xml, property_search(config_xml, NULL, "/database"), "before@",
|
||||
PROPERTY_TYPE_ATTR, beforeTarget, 64);
|
||||
|
||||
if (strlen(beforeTarget) > 0 && strcmp(target, beforeTarget) >= 0) {
|
||||
printf("Currently loading %s, found database that is only valid before %s, skipping %s...\n", target, beforeTarget, input_filename);
|
||||
if (strlen(beforeTarget) > 0 && atoi(target) >= atoi(beforeTarget)) {
|
||||
printf("Currently loading %s, found database that is only valid before %s, skipping %s...\n", beforeTarget, target, input_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
char afterTarget[64] = {};
|
||||
property_node_refer(config_xml, property_search(config_xml, NULL, "/database"), "after@",
|
||||
PROPERTY_TYPE_ATTR, afterTarget, 64);
|
||||
if (strlen(afterTarget) > 0 && strcmp(target, afterTarget) < 0) {
|
||||
printf("Currently loading %s, found database that is only valid after %s, skipping %s...\n", target, afterTarget, input_filename);
|
||||
if (strlen(afterTarget) > 0 && atoi(target) < atoi(afterTarget)) {
|
||||
printf("Currently loading %s, found database that is only valid after %s, skipping %s...\n", beforeTarget, target, input_filename);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -831,16 +831,16 @@ void parse_musicdb(const char *input_filename, const char *target) {
|
||||
property_node_refer(config_xml, property_search(config_xml, NULL, "/database"), "before@",
|
||||
PROPERTY_TYPE_ATTR, beforeTarget, 64);
|
||||
|
||||
if (strlen(beforeTarget) > 0 && strcmp(target, beforeTarget) >= 0) {
|
||||
printf("Currently loading %s, found database that is only valid before %s, skipping %s...\n", target, beforeTarget, input_filename);
|
||||
if (strlen(beforeTarget) > 0 && atoi(target) >= atoi(beforeTarget)) {
|
||||
printf("Currently loading %s, found database that is only valid before %s, skipping %s...\n", beforeTarget, target, input_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
char afterTarget[64] = {};
|
||||
property_node_refer(config_xml, property_search(config_xml, NULL, "/database"), "after@",
|
||||
PROPERTY_TYPE_ATTR, afterTarget, 64);
|
||||
if (strlen(afterTarget) > 0 && strcmp(target, afterTarget) < 0) {
|
||||
printf("Currently loading %s, found database that is only valid after %s, skipping %s...\n", target, afterTarget, input_filename);
|
||||
if (strlen(afterTarget) > 0 && atoi(target) < atoi(afterTarget)) {
|
||||
printf("Currently loading %s, found database that is only valid after %s, skipping %s...\n", beforeTarget, target, input_filename);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1002,16 +1002,12 @@ void load_databases(const char *target_datecode) {
|
||||
// Character databases must be loaded before music databases because the music databases could reference modified/new characters
|
||||
for(uint16_t i=0;i<result.size();i++)
|
||||
{
|
||||
if ( strstr(result[i].c_str(), "charadb") == NULL )
|
||||
continue;
|
||||
printf("(charadb) Loading %s...\n", result[i].c_str());
|
||||
parse_charadb(result[i].c_str(), target_datecode);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -1,445 +0,0 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "util/search.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/patch.h"
|
||||
|
||||
#include "tableinfo.h"
|
||||
#include "loader.h"
|
||||
|
||||
#define MAX_REPLACE_SIZE 16384
|
||||
|
||||
FILE *g_dict_applied_fp;
|
||||
bool patch_sjis(const char *dllFilename, const char *find, uint8_t find_size, int64_t *offset, char *replace, uint8_t replace_size, bool dump_dict) {
|
||||
static DWORD dllSize = 0;
|
||||
static char *data = getDllData(dllFilename, &dllSize);
|
||||
static uint8_t first_offset = 0;
|
||||
|
||||
int64_t offset_orig = *offset;
|
||||
uint64_t patch_addr;
|
||||
bool valid_sjis = false;
|
||||
do {
|
||||
*offset = search(data, dllSize-*offset, find, find_size, *offset);
|
||||
if (*offset == -1) {
|
||||
*offset = offset_orig;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !first_offset )
|
||||
{
|
||||
if (dump_dict)
|
||||
{
|
||||
LOG("popnhax: dump_dict: dump applied patches in dict_applied.txt\n");
|
||||
g_dict_applied_fp = fopen("dict_applied.txt","wb");
|
||||
}
|
||||
first_offset = 1;
|
||||
}
|
||||
|
||||
patch_addr = (int64_t)data + *offset;
|
||||
|
||||
/* filter out partial matches (check that there isn't a valid sjis char before our match) */
|
||||
uint8_t byte1 = *(uint8_t*)(patch_addr-2);
|
||||
uint8_t byte2 = *(uint8_t*)(patch_addr-1);
|
||||
bool valid_first = ((0x81 <= byte1) && (byte1 <= 0x9F)) || ((0xE0 <= byte1) && (byte1 <= 0xFC));
|
||||
bool valid_secnd = ((0x40 <= byte2) && (byte2 <= 0x9E)) || ((0x9F <= byte2) && (byte2 <= 0xFC));
|
||||
valid_sjis = valid_first && valid_secnd;
|
||||
|
||||
if (valid_sjis)
|
||||
{
|
||||
printf("Partial match at offset 0x%x, retry...\n",(uint32_t)*offset);
|
||||
*offset += find_size;
|
||||
}
|
||||
} 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
|
||||
{
|
||||
free_size++;
|
||||
}
|
||||
while ( *(uint8_t *)(patch_addr+free_size) == 0 );
|
||||
|
||||
if ((free_size-1) < replace_size)
|
||||
{
|
||||
LOG("WARNING: translation %s is too big, truncating to ",(char *)replace);
|
||||
replace_size = free_size-1;
|
||||
replace[replace_size-1] = '\0';
|
||||
LOG("%s\n",(char *)replace);
|
||||
}
|
||||
|
||||
patch_memory(patch_addr, (char *)replace, replace_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#define BYTE3_TO_UINT(bp) \
|
||||
(((unsigned int)(bp)[0] << 16) & 0x00FF0000) | \
|
||||
(((unsigned int)(bp)[1] << 8) & 0x0000FF00) | \
|
||||
((unsigned int)(bp)[2] & 0x000000FF)
|
||||
|
||||
#define BYTE2_TO_UINT(bp) \
|
||||
(((unsigned int)(bp)[0] << 8) & 0xFF00) | \
|
||||
((unsigned int) (bp)[1] & 0x00FF)
|
||||
|
||||
#define IPS_EOF 0x464F45
|
||||
|
||||
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;\
|
||||
}\
|
||||
} while (0)
|
||||
DWORD dllSize = 0;
|
||||
char *data = getDllData(dllFilename, &dllSize);
|
||||
|
||||
char dict_filepath[64];
|
||||
sprintf(dict_filepath, "%s%s%s", "data_mods\\", foldername, "\\popn22.ips");
|
||||
FILE *ips_fp = fopen(dict_filepath, "rb");
|
||||
|
||||
if (ips_fp == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
/* 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 trans_base = 0; /* eclale patch adds new section header which I'm relocating */
|
||||
uint32_t trans_base_offset = 0;
|
||||
uint32_t trans_rebase = 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;
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
static bool patch_translation_dict(const char *dllFilename, const char *foldername, bool dump_dict)
|
||||
{
|
||||
char original[128];
|
||||
char translation[128];
|
||||
uint8_t buffer;
|
||||
int64_t curr_offset = 0;
|
||||
uint8_t word_count = 0;
|
||||
uint8_t orig_size = 0;
|
||||
|
||||
char dict_filepath[64];
|
||||
sprintf(dict_filepath, "%s%s%s", "data_mods\\", foldername, "\\popn22.dict");
|
||||
FILE *dict_fp = fopen(dict_filepath, "rb");
|
||||
|
||||
if (dict_fp == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG("popnhax: translation: popn22.dict file found\n");
|
||||
|
||||
#define STATE_WAITING 0
|
||||
#define STATE_ORIGINAL 1
|
||||
#define STATE_TRANSLATION 2
|
||||
uint16_t err_count = 0;
|
||||
uint8_t state = STATE_WAITING;
|
||||
uint8_t arr_idx = 0;
|
||||
while (fread(&buffer, 1, 1, dict_fp) == 1)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case STATE_WAITING:
|
||||
if (buffer == ';')
|
||||
{
|
||||
state = STATE_ORIGINAL;
|
||||
arr_idx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("Unexpected char %c\n", buffer);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case STATE_ORIGINAL:
|
||||
if (buffer == ';')
|
||||
{
|
||||
original[arr_idx++] = '\0';
|
||||
state = STATE_TRANSLATION;
|
||||
orig_size = arr_idx;
|
||||
arr_idx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
original[arr_idx++] = buffer;
|
||||
}
|
||||
break;
|
||||
case STATE_TRANSLATION:
|
||||
if (buffer == ';')
|
||||
{
|
||||
/* end of word, let's patch! */
|
||||
translation[arr_idx-1] = '\0'; /* strip last \n */
|
||||
while ( arr_idx < orig_size )
|
||||
{
|
||||
translation[arr_idx++] = '\0'; /* fill with null when translation is shorter */
|
||||
}
|
||||
printf("%d: %s -> %s\n",++word_count,(char *)original,(char *)translation);
|
||||
|
||||
/* patch all occurrences */
|
||||
/*curr_offset = 0;
|
||||
uint8_t count = 0;
|
||||
while (patch_sjis(dllFilename, original, orig_size, &curr_offset, translation, arr_idx-1, dump_dict))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
LOG("%d occurrences found\n",count);
|
||||
*/
|
||||
if (!patch_sjis(dllFilename, original, orig_size, &curr_offset, translation, arr_idx-1, dump_dict))
|
||||
{
|
||||
printf("Warning: string %s (%s) not found in order, trying again.\n", (char *)original, (char *)translation);
|
||||
curr_offset = 0;
|
||||
if (!patch_sjis(dllFilename, original, orig_size, &curr_offset, translation, arr_idx-1, dump_dict))
|
||||
{
|
||||
LOG("Warning: string %s not found, skipping.\n", (char *)original);
|
||||
err_count++;
|
||||
}
|
||||
}
|
||||
|
||||
state = STATE_ORIGINAL;
|
||||
arr_idx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
translation[arr_idx++] = buffer;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOG("popnhax: translation: patched %u strings", word_count - err_count);
|
||||
if (err_count)
|
||||
LOG(" (%u skipped strings)", err_count);
|
||||
LOG("\n");
|
||||
|
||||
if (dump_dict)
|
||||
fclose(g_dict_applied_fp);
|
||||
return true;
|
||||
#undef STATE_WAITING
|
||||
#undef STATE_ORIGINAL
|
||||
#undef STATE_TRANSLATION
|
||||
}
|
||||
|
||||
bool patch_translate(const char *dllFilename, const char *folder, bool debug)
|
||||
{
|
||||
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;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#ifndef __TRANSLATION_H__
|
||||
#define __TRANSLATION_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
bool patch_translate(const char *dllFilename, const char *folder, bool debug);
|
||||
|
||||
#endif
|
@ -2,6 +2,5 @@ libs += util
|
||||
|
||||
srcpp_util := \
|
||||
fuzzy_search.cc \
|
||||
search.cc \
|
||||
cmdline.cc \
|
||||
patch.cc \
|
||||
|
@ -7,7 +7,7 @@ int find_block_core(char *haystack, size_t haystack_size, fuzzy_search_task *nee
|
||||
size_t orig_offset, int dir) {
|
||||
size_t offset = orig_offset;
|
||||
haystack_size += orig_offset;
|
||||
while (offset + 1 < haystack_size) {
|
||||
while (offset + 1 < orig_offset + haystack_size) {
|
||||
size_t offset_temp = offset;
|
||||
int found = 1;
|
||||
|
||||
|
19
util/log.h
19
util/log.h
@ -1,19 +0,0 @@
|
||||
#ifndef __LOG_H__
|
||||
#define __LOG_H__
|
||||
|
||||
#include <cstdio>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern FILE *g_log_fp;
|
||||
|
||||
#define LOG(...) do { \
|
||||
if (g_log_fp != NULL) { \
|
||||
fprintf(g_log_fp, __VA_ARGS__); \
|
||||
fflush(g_log_fp);\
|
||||
}\
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
115
util/patch.cc
115
util/patch.cc
@ -3,7 +3,6 @@
|
||||
#include <psapi.h>
|
||||
// clang-format on
|
||||
|
||||
#include "util/search.h"
|
||||
#include "patch.h"
|
||||
|
||||
void patch_memory(uint64_t patch_addr, char *data, size_t len) {
|
||||
@ -26,117 +25,3 @@ char *getDllData(const char *dllFilename, DWORD *dllSize) {
|
||||
*dllSize = module_info.SizeOfImage;
|
||||
return (char *)module_info.lpBaseOfDll;
|
||||
}
|
||||
|
||||
|
||||
bool rva_to_offset(const char *dllFilename, uint32_t rva, uint32_t *offset)
|
||||
{
|
||||
uintptr_t baseAddr = (uintptr_t)GetModuleHandle(dllFilename);
|
||||
IMAGE_DOS_HEADER * pDosHdr = (IMAGE_DOS_HEADER *) baseAddr;
|
||||
IMAGE_NT_HEADERS * pNtHdr = (IMAGE_NT_HEADERS *) (baseAddr + pDosHdr->e_lfanew);
|
||||
|
||||
int i;
|
||||
WORD wSections;
|
||||
PIMAGE_SECTION_HEADER pSectionHdr;
|
||||
pSectionHdr = IMAGE_FIRST_SECTION(pNtHdr);
|
||||
wSections = pNtHdr -> FileHeader.NumberOfSections;
|
||||
for (i = 0; i < wSections; i++)
|
||||
{
|
||||
if (pSectionHdr -> VirtualAddress <= rva)
|
||||
if ((pSectionHdr -> VirtualAddress + pSectionHdr -> Misc.VirtualSize) > rva)
|
||||
{
|
||||
rva -= pSectionHdr -> VirtualAddress;
|
||||
rva += pSectionHdr -> PointerToRawData;
|
||||
*offset = rva;
|
||||
return true;
|
||||
}
|
||||
pSectionHdr++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool offset_to_rva(const char *dllFilename, uint32_t offset, uint32_t *rva)
|
||||
{
|
||||
uintptr_t baseAddr = (uintptr_t)GetModuleHandle(dllFilename);
|
||||
IMAGE_DOS_HEADER * pDosHdr = (IMAGE_DOS_HEADER *) baseAddr;
|
||||
IMAGE_NT_HEADERS * pNtHdr = (IMAGE_NT_HEADERS *) (baseAddr + pDosHdr->e_lfanew);
|
||||
|
||||
int i;
|
||||
WORD wSections;
|
||||
PIMAGE_SECTION_HEADER pSectionHdr;
|
||||
|
||||
pSectionHdr = IMAGE_FIRST_SECTION(pNtHdr);
|
||||
wSections = pNtHdr -> FileHeader.NumberOfSections;
|
||||
|
||||
for (i = 0; i < wSections; i++) {
|
||||
if (pSectionHdr -> PointerToRawData <= offset)
|
||||
if ((pSectionHdr -> PointerToRawData + pSectionHdr -> SizeOfRawData) > offset) {
|
||||
offset -= pSectionHdr -> PointerToRawData;
|
||||
offset += pSectionHdr -> VirtualAddress;
|
||||
|
||||
*rva = offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
pSectionHdr++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void find_and_patch_string(const char *dllFilename, const char *input_string, const char *new_string) {
|
||||
DWORD dllSize = 0;
|
||||
char *data = getDllData(dllFilename, &dllSize);
|
||||
|
||||
while (1) {
|
||||
int64_t pattern_offset = search(data, dllSize, input_string, strlen(input_string), 0);
|
||||
if (pattern_offset == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint64_t patch_addr = (int64_t)data + pattern_offset;
|
||||
char *new_string_buff = (char*)calloc(strlen(new_string) + 1, sizeof(char));
|
||||
memcpy(new_string_buff, new_string, strlen(new_string));
|
||||
patch_memory(patch_addr, new_string_buff, strlen(new_string) + 1);
|
||||
free(new_string_buff);
|
||||
}
|
||||
}
|
||||
|
||||
bool find_and_patch_hex(const char *dllFilename, const char *find, uint8_t find_size, int64_t shift, const char *replace, uint8_t replace_size) {
|
||||
DWORD dllSize = 0;
|
||||
char *data = getDllData(dllFilename, &dllSize);
|
||||
|
||||
int64_t pattern_offset = search(data, dllSize, find, find_size, 0);
|
||||
if (pattern_offset == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if DEBUG == 1
|
||||
LOG("BEFORE PATCH :\n");
|
||||
uint8_t *offset = (uint8_t *) ((int64_t)data + pattern_offset + shift - 5);
|
||||
for (int i=0; i<32; i++)
|
||||
{
|
||||
LOG("%02x ", *offset);
|
||||
offset++;
|
||||
if (i == 15)
|
||||
LOG("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t patch_addr = (int64_t)data + pattern_offset + shift;
|
||||
patch_memory(patch_addr, (char *)replace, replace_size);
|
||||
|
||||
#if DEBUG == 1
|
||||
LOG("\nAFTER PATCH :\n");
|
||||
offset = (uint8_t *) ((int64_t)data + pattern_offset + shift - 5);
|
||||
for (int i=0; i<32; i++)
|
||||
{
|
||||
LOG("%02x ", *offset);
|
||||
offset++;
|
||||
if (i == 15)
|
||||
LOG("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
||||
}
|
@ -7,14 +7,7 @@
|
||||
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
void patch_memory(uint64_t patch_addr, char *data, size_t len);
|
||||
char *getDllData(const char *dllFilename, DWORD *dllSize);
|
||||
|
||||
bool rva_to_offset(const char *dllFilename, uint32_t rva, uint32_t *offset);
|
||||
bool offset_to_rva(const char *dllFilename, uint32_t offset, uint32_t *rva);
|
||||
|
||||
void patch_memory(uint64_t patch_addr, char *data, size_t len);
|
||||
|
||||
bool find_and_patch_hex(const char *dllFilename, const char *find, uint8_t find_size, int64_t shift, const char *replace, uint8_t replace_size);
|
||||
void find_and_patch_string(const char *dllFilename, const char *input_string, const char *new_string);
|
||||
|
||||
#endif
|
@ -1,75 +0,0 @@
|
||||
#include <memory.h>
|
||||
#include <stdint.h>
|
||||
#include <cstdio>
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#define NO_OF_CHARS 256
|
||||
|
||||
// A utility function to get maximum of two integers
|
||||
static int max(int a, int b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
// The preprocessing function for Boyer Moore's bad character heuristic
|
||||
static void badCharHeuristic(const unsigned char *str, int size, int* badchar) {
|
||||
int i;
|
||||
|
||||
// Initialize all occurrences as -1
|
||||
for (i = 0; i < NO_OF_CHARS; i++)
|
||||
badchar[i] = -1;
|
||||
|
||||
// Fill the actual value of last occurrence of a character
|
||||
for (i = 0; i < size; i++)
|
||||
badchar[(int) str[i]] = i;
|
||||
}
|
||||
|
||||
#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 badchar[NO_OF_CHARS];
|
||||
|
||||
badCharHeuristic(needle, needle_size, badchar);
|
||||
|
||||
int64_t s = 0; // s is shift of the pattern with respect to text
|
||||
while (s <= (haystack_size - needle_size)) {
|
||||
int j = needle_size - 1;
|
||||
if (debug == 2)
|
||||
{
|
||||
LOG("--------------------------------\n");
|
||||
LOG("txt...");
|
||||
for (size_t i = 0; i < needle_size; i++)
|
||||
{
|
||||
LOG("%02x ", haystack[orig_offset+s+i]);
|
||||
}
|
||||
LOG("\n");
|
||||
LOG("pat...");
|
||||
for (size_t i = 0; i < needle_size; i++)
|
||||
{
|
||||
LOG("%02x ", needle[i]);
|
||||
}
|
||||
LOG("\n");
|
||||
}
|
||||
while (j >= 0 && needle[j] == haystack[orig_offset + s + j])
|
||||
j--;
|
||||
|
||||
if (j < 0) {
|
||||
if (debug)
|
||||
LOG("found string at offset %llx!\n", orig_offset +s);
|
||||
return orig_offset + s;
|
||||
}
|
||||
else
|
||||
{
|
||||
s += max(1, j - badchar[(int)haystack[orig_offset + s + j]]);
|
||||
if (debug)
|
||||
LOG("mismatch at pos %d, new offset %llx\n\n", j, orig_offset+s);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
return res;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
#ifndef __SEARCH_H__
|
||||
#define __SEARCH_H__
|
||||
|
||||
int search(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset);
|
||||
|
||||
#endif
|
@ -84,20 +84,17 @@ struct property *load_prop_file(const char *filename) {
|
||||
return config_data;
|
||||
}
|
||||
|
||||
bool _load_config(const char *filename, void *dest, const struct property_psmap *psmap) {
|
||||
void _load_config(const char *filename, void *dest, const struct property_psmap *psmap) {
|
||||
struct property *config_xml = load_prop_file(filename);
|
||||
|
||||
if (!config_xml) {
|
||||
printf("Couldn't load xml file: %s\n", filename);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(property_psmap_import(config_xml, nullptr, dest, psmap))) {
|
||||
printf("Couldn't parse psmap\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user