writecodeblocks noop clean
Feature/pc writecodeblocks noop clean
This commit is contained in:
@@ -251,6 +251,9 @@ ClientFunctionIndex::ClientFunctionIndex(const std::string& root_dir, bool raise
|
|||||||
add_directory(item_path);
|
add_directory(item_path);
|
||||||
} else if (item_path.ends_with(".s") && std::filesystem::is_regular_file(item_path)) {
|
} else if (item_path.ends_with(".s") && std::filesystem::is_regular_file(item_path)) {
|
||||||
client_functions_log.debug_f("Adding {} from {}", item_name, item_path);
|
client_functions_log.debug_f("Adding {} from {}", item_name, item_path);
|
||||||
|
if (item_name.find("Dragon") != std::string::npos) {
|
||||||
|
client_functions_log.warning_f("Dragon source load debug: adding {} from {}", item_name, item_path);
|
||||||
|
}
|
||||||
if (!source_files.emplace(item_name, phosg::load_file(item_path)).second) {
|
if (!source_files.emplace(item_name, phosg::load_file(item_path)).second) {
|
||||||
throw std::runtime_error(std::format("Duplicate source filename: {}", item_name));
|
throw std::runtime_error(std::format("Duplicate source filename: {}", item_name));
|
||||||
}
|
}
|
||||||
@@ -285,6 +288,20 @@ ClientFunctionIndex::ClientFunctionIndex(const std::string& root_dir, bool raise
|
|||||||
throw std::runtime_error(std::format("({} preprocessing) {}", source_filename, e.what()));
|
throw std::runtime_error(std::format("({} preprocessing) {}", source_filename, e.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (source_filename.find("Dragon") != std::string::npos) {
|
||||||
|
client_functions_log.warning_f(
|
||||||
|
"Dragon preprocess debug: source={} produced {} version chunk(s)",
|
||||||
|
source_filename,
|
||||||
|
preprocessed.size());
|
||||||
|
for (const auto& [debug_sv, debug_source] : preprocessed) {
|
||||||
|
client_functions_log.warning_f(
|
||||||
|
"Dragon preprocess debug: source={} sv={} chunk_size={}",
|
||||||
|
source_filename,
|
||||||
|
str_for_specific_version(debug_sv),
|
||||||
|
debug_source.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& [specific_version, source] : preprocessed) {
|
for (const auto& [specific_version, source] : preprocessed) {
|
||||||
std::shared_ptr<Function> fn = std::make_shared<Function>();
|
std::shared_ptr<Function> fn = std::make_shared<Function>();
|
||||||
fn->short_name = source_filename.substr(0, source_filename.size() - 2);
|
fn->short_name = source_filename.substr(0, source_filename.size() - 2);
|
||||||
@@ -444,6 +461,37 @@ ClientFunctionIndex::ClientFunctionIndex(const std::string& root_dir, bool raise
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const char* probe_name : {"DragonVisualFix", "PsoPeepsDragonVisualFixPC", "RaresInQuests"}) {
|
||||||
|
for (uint32_t probe_sv : {0x324F4A57u, SPECIFIC_VERSION_X86_INDETERMINATE}) {
|
||||||
|
std::string key = cache_key(probe_name, probe_sv);
|
||||||
|
auto all_it = this->all_functions.find(key);
|
||||||
|
auto map_it = this->functions_by_specific_version.find(probe_sv);
|
||||||
|
bool in_version_map = false;
|
||||||
|
if (map_it != this->functions_by_specific_version.end()) {
|
||||||
|
in_version_map = map_it->second.count(key);
|
||||||
|
}
|
||||||
|
client_functions_log.warning_f(
|
||||||
|
"Client function probe: name={} sv={} key={} all_functions={} version_map={} map_size={}",
|
||||||
|
probe_name,
|
||||||
|
str_for_specific_version(probe_sv),
|
||||||
|
key,
|
||||||
|
all_it != this->all_functions.end(),
|
||||||
|
in_version_map,
|
||||||
|
map_it == this->functions_by_specific_version.end() ? 0 : map_it->second.size());
|
||||||
|
if (all_it != this->all_functions.end()) {
|
||||||
|
const auto& fn = all_it->second;
|
||||||
|
client_functions_log.warning_f(
|
||||||
|
"Client function probe detail: short={} long={} visibility={} specific_version={} arch={} menu_item_id={:08X}",
|
||||||
|
fn->short_name,
|
||||||
|
fn->long_name,
|
||||||
|
phosg::name_for_enum(fn->visibility),
|
||||||
|
str_for_specific_version(fn->specific_version),
|
||||||
|
name_for_architecture(fn->arch),
|
||||||
|
static_cast<uint32_t>(fn->menu_item_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const Menu> ClientFunctionIndex::patch_switches_menu(
|
std::shared_ptr<const Menu> ClientFunctionIndex::patch_switches_menu(
|
||||||
@@ -455,15 +503,44 @@ std::shared_ptr<const Menu> ClientFunctionIndex::patch_switches_menu(
|
|||||||
|
|
||||||
auto map_it = this->functions_by_specific_version.find(specific_version);
|
auto map_it = this->functions_by_specific_version.find(specific_version);
|
||||||
if (map_it != this->functions_by_specific_version.end()) {
|
if (map_it != this->functions_by_specific_version.end()) {
|
||||||
|
client_functions_log.warning_f(
|
||||||
|
"Patch menu debug: building menu for specific_version={} with {} function entries",
|
||||||
|
str_for_specific_version(specific_version),
|
||||||
|
map_it->second.size());
|
||||||
|
|
||||||
for (auto [name, fn] : map_it->second) {
|
for (auto [name, fn] : map_it->second) {
|
||||||
if (fn->appears_in_patches_menu() && !server_auto_patches_enabled.count(fn->short_name)) {
|
bool appears = fn->appears_in_patches_menu();
|
||||||
|
bool server_auto = server_auto_patches_enabled.count(fn->short_name);
|
||||||
|
bool client_enabled = client_auto_patches_enabled.count(fn->short_name);
|
||||||
|
bool dragon_debug =
|
||||||
|
(fn->short_name.find("Dragon") != std::string::npos) ||
|
||||||
|
(fn->long_name.find("Dragon") != std::string::npos);
|
||||||
|
|
||||||
|
if (dragon_debug || appears) {
|
||||||
|
client_functions_log.warning_f(
|
||||||
|
"Patch menu debug: key={} short={} long={} visibility={} appears={} server_auto={} client_enabled={} menu_item_id={:08X}",
|
||||||
|
name,
|
||||||
|
fn->short_name,
|
||||||
|
fn->long_name,
|
||||||
|
phosg::name_for_enum(fn->visibility),
|
||||||
|
appears,
|
||||||
|
server_auto,
|
||||||
|
client_enabled,
|
||||||
|
static_cast<uint32_t>(fn->menu_item_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appears && !server_auto) {
|
||||||
std::string item_text;
|
std::string item_text;
|
||||||
item_text.push_back(client_auto_patches_enabled.count(fn->short_name) ? '*' : '-');
|
item_text.push_back(client_enabled ? '*' : '-');
|
||||||
item_text += fn->long_name.empty() ? fn->short_name : fn->long_name;
|
item_text += fn->long_name.empty() ? fn->short_name : fn->long_name;
|
||||||
ret->items.emplace_back(
|
ret->items.emplace_back(
|
||||||
fn->menu_item_id, item_text, fn->description, MenuItem::Flag::REQUIRES_SEND_FUNCTION_CALL_RUNS_CODE);
|
fn->menu_item_id, item_text, fn->description, MenuItem::Flag::REQUIRES_SEND_FUNCTION_CALL_RUNS_CODE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
client_functions_log.warning_f(
|
||||||
|
"Patch menu debug: no functions for specific_version={}",
|
||||||
|
str_for_specific_version(specific_version));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
.meta visibility="all"
|
||||||
|
.meta name="Dragon fix"
|
||||||
|
.meta description="Skips the bad Dragon\nBML selector path."
|
||||||
|
|
||||||
|
entry_ptr:
|
||||||
|
reloc0:
|
||||||
|
.offsetof start
|
||||||
|
start:
|
||||||
|
.include WriteCodeBlocks
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.versions 2OJW
|
||||||
|
|
||||||
|
.data 0x00420326
|
||||||
|
.data 2
|
||||||
|
.data 0x14EB
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.all_versions
|
||||||
|
|
||||||
|
.data 0x00000000
|
||||||
|
.data 0x00000000
|
||||||
@@ -118,7 +118,109 @@ first_patch_header:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
.versions 2OJW 2OJZ 50YJ 59NJ 59NL
|
.versions 2OJW
|
||||||
|
|
||||||
|
start:
|
||||||
|
push ebx
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
sub esp, 8 # [esp] = oldProtect, [esp + 4] = tempProtect
|
||||||
|
jmp get_patch_data_ptr
|
||||||
|
get_patch_data_ptr_ret:
|
||||||
|
pop ebx # ebx = patch header
|
||||||
|
|
||||||
|
# Resolve kernel32!VirtualProtect using pso.exe's 2OJW IAT:
|
||||||
|
# GetModuleHandleA = 0x0064D114
|
||||||
|
# GetProcAddress = 0x0064D128
|
||||||
|
#
|
||||||
|
# Build "KERNEL32.dll\0" on stack.
|
||||||
|
sub esp, 16
|
||||||
|
mov dword [esp], 0x4E52454B # "KERN"
|
||||||
|
mov dword [esp + 4], 0x32334C45 # "EL32"
|
||||||
|
mov dword [esp + 8], 0x6C6C642E # ".dll"
|
||||||
|
mov dword [esp + 12], 0
|
||||||
|
push esp
|
||||||
|
call [0x0064D114] # GetModuleHandleA
|
||||||
|
add esp, 16
|
||||||
|
test eax, eax
|
||||||
|
jz fail
|
||||||
|
|
||||||
|
mov esi, eax # esi = kernel32 module handle
|
||||||
|
|
||||||
|
# Build "VirtualProtect\0" on stack.
|
||||||
|
sub esp, 16
|
||||||
|
mov dword [esp], 0x74726956 # "Virt"
|
||||||
|
mov dword [esp + 4], 0x506C6175 # "ualP"
|
||||||
|
mov dword [esp + 8], 0x65746F72 # "rote"
|
||||||
|
mov dword [esp + 12], 0x00007463 # "ct\0\0"
|
||||||
|
push esp
|
||||||
|
push esi
|
||||||
|
call [0x0064D128] # GetProcAddress
|
||||||
|
add esp, 16
|
||||||
|
test eax, eax
|
||||||
|
jz fail
|
||||||
|
|
||||||
|
mov edi, eax # edi = VirtualProtect
|
||||||
|
|
||||||
|
apply_next_patch:
|
||||||
|
cmp dword [ebx + 4], 0
|
||||||
|
jne copy_code_and_apply_again
|
||||||
|
|
||||||
|
add esp, 8
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebx
|
||||||
|
mov eax, 1
|
||||||
|
ret
|
||||||
|
|
||||||
|
copy_code_and_apply_again:
|
||||||
|
# VirtualProtect(dest, size, PAGE_EXECUTE_READWRITE, &oldProtect)
|
||||||
|
lea eax, [esp]
|
||||||
|
push eax
|
||||||
|
push 0x40
|
||||||
|
push dword [ebx + 4]
|
||||||
|
push dword [ebx]
|
||||||
|
call edi
|
||||||
|
test eax, eax
|
||||||
|
jz fail
|
||||||
|
|
||||||
|
xor ecx, ecx # ecx = offset
|
||||||
|
mov edx, [ebx] # edx = dest addr
|
||||||
|
copy_next_byte:
|
||||||
|
mov al, [ebx + ecx + 8] # copy one byte to dest
|
||||||
|
mov [edx + ecx], al
|
||||||
|
inc ecx # offset++
|
||||||
|
cmp [ebx + 4], ecx # check if all bytes have been copied
|
||||||
|
jne copy_next_byte
|
||||||
|
|
||||||
|
# VirtualProtect(dest, size, oldProtect, &tempProtect)
|
||||||
|
mov esi, [ebx + 4] # esi = size; VirtualProtect preserves esi
|
||||||
|
mov edx, [esp] # edx = oldProtect
|
||||||
|
lea eax, [esp + 4]
|
||||||
|
push eax
|
||||||
|
push edx
|
||||||
|
push esi
|
||||||
|
push dword [ebx]
|
||||||
|
call edi
|
||||||
|
|
||||||
|
lea ebx, [ebx + esi + 8] # advance to next block
|
||||||
|
jmp apply_next_patch
|
||||||
|
|
||||||
|
fail:
|
||||||
|
add esp, 8
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebx
|
||||||
|
xor eax, eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
get_patch_data_ptr:
|
||||||
|
call get_patch_data_ptr_ret
|
||||||
|
first_patch_header:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.versions 2OJZ 50YJ 59NJ 59NL
|
||||||
|
|
||||||
start:
|
start:
|
||||||
push ebx
|
push ebx
|
||||||
|
|||||||
Reference in New Issue
Block a user