write assemble-all-patches action

This commit is contained in:
Martin Michelsen
2024-01-09 21:32:31 -08:00
parent 9e0dfc7749
commit 68be13dd62
5 changed files with 104 additions and 40 deletions
+1
View File
@@ -223,6 +223,7 @@ FunctionCodeIndex::FunctionCodeIndex(const string& directory) {
}
}
code->specific_version = specific_version;
code->source_path = path;
code->short_name = short_name;
this->name_to_function.emplace(name, code);
if (is_patch) {
+1
View File
@@ -27,6 +27,7 @@ struct CompiledFunctionCode {
std::vector<uint16_t> relocation_deltas;
std::unordered_map<std::string, uint32_t> label_offsets;
uint32_t entrypoint_offset_offset;
std::string source_path; // Path to source file from newserv root
std::string short_name; // Based on filename
std::string long_name; // From .meta name directive
std::string description; // From .meta description directive
+44
View File
@@ -31,6 +31,7 @@
#include "Loggers.hh"
#include "NetworkAddresses.hh"
#include "PSOGCObjectGraph.hh"
#include "PSOProtocol.hh"
#include "ProxyServer.hh"
#include "Quest.hh"
#include "QuestScript.hh"
@@ -1092,6 +1093,49 @@ Action a_assemble_quest_script(
write_output_data(args, result.data(), result.size(), compress ? "bin" : "bind");
});
Action a_assemble_all_patches(
"assemble-all-patches", "\
assemble-all-patches\n\
Assemble all patches in the system/ppc directory, and produce two compiled\n\
.bin files for each patch (one unencrypted, for most PSO versions, and one\n\
encrypted, for PSO JP v1.04, JP Ep3, and Ep3 Trial Edition). The output\n\
files are written to the system/ppc directory.\n",
+[](Arguments&) {
ServerState s;
s.load_objects_and_upstream_dependents("functions");
auto process_code = +[](shared_ptr<const CompiledFunctionCode> code,
uint32_t checksum_addr,
uint32_t checksum_size,
uint32_t override_start_addr) -> void {
for (uint8_t encrypted = 0; encrypted < 2; encrypted++) {
StringWriter w;
string data = prepare_send_function_call_data(code, {}, "", checksum_addr, checksum_size, override_start_addr, encrypted);
w.put(PSOCommandHeaderDCV3{.command = 0xB2, .flag = code->index, .size = data.size() + 4});
w.write(data);
string out_path = code->source_path + (encrypted ? ".enc.bin" : ".std.bin");
save_file(out_path, w.str());
fprintf(stderr, "... %s\n", out_path.c_str());
}
};
for (const auto& it : s.function_code_index->name_and_specific_version_to_patch_function) {
process_code(it.second, 0, 0, 0);
}
try {
process_code(s.function_code_index->name_to_function.at("VersionDetect"), 0, 0, 0);
} catch (const out_of_range&) {
}
try {
process_code(s.function_code_index->name_to_function.at("CacheClearFix-Phase1"), 0x80000000, 8, 0x7F2734EC);
} catch (const out_of_range&) {
}
try {
process_code(s.function_code_index->name_to_function.at("CacheClearFix-Phase2"), 0, 0, 0);
} catch (const out_of_range&) {
}
});
void a_extract_archive_fn(Arguments& args) {
string output_prefix = args.get<string>(2, false);
if (output_prefix == "-") {
+48 -38
View File
@@ -402,48 +402,19 @@ void prepare_client_for_patches(shared_ptr<Client> c, function<void()> on_comple
}
}
void send_function_call(
shared_ptr<Client> c,
shared_ptr<CompiledFunctionCode> code,
string prepare_send_function_call_data(
shared_ptr<const CompiledFunctionCode> code,
const unordered_map<string, uint32_t>& label_writes,
const string& suffix,
uint32_t checksum_addr,
uint32_t checksum_size,
uint32_t override_relocations_offset) {
return send_function_call(
c->channel,
c->config,
code,
label_writes,
suffix,
checksum_addr,
checksum_size,
override_relocations_offset);
}
void send_function_call(
Channel& ch,
const Client::Config& client_config,
shared_ptr<CompiledFunctionCode> code,
const unordered_map<string, uint32_t>& label_writes,
const string& suffix,
uint32_t checksum_addr,
uint32_t checksum_size,
uint32_t override_relocations_offset) {
if (client_config.check_flag(Client::Flag::NO_SEND_FUNCTION_CALL)) {
throw logic_error("client does not support function calls");
}
if (code.get() && client_config.check_flag(Client::Flag::SEND_FUNCTION_CALL_CHECKSUM_ONLY)) {
throw logic_error("client only supports checksums in send_function_call");
}
uint32_t override_relocations_offset,
bool use_encrypted_format) {
string data;
uint32_t index = 0;
if (code.get()) {
data = code->generate_client_command(label_writes, suffix, override_relocations_offset);
index = code->index;
if (client_config.check_flag(Client::Flag::ENCRYPTED_SEND_FUNCTION_CALL)) {
if (use_encrypted_format) {
uint32_t key = random_object<uint32_t>();
// This format was probably never used on any little-endian system, but we
@@ -473,13 +444,52 @@ void send_function_call(
}
}
S_ExecuteCode_B2 header = {data.size(), checksum_addr, checksum_size};
StringWriter w;
w.put(header);
w.put(S_ExecuteCode_B2{data.size(), checksum_addr, checksum_size});
w.write(data);
return std::move(w.str());
}
ch.send(0xB2, index, w.str());
void send_function_call(
shared_ptr<Client> c,
shared_ptr<const CompiledFunctionCode> code,
const unordered_map<string, uint32_t>& label_writes,
const string& suffix,
uint32_t checksum_addr,
uint32_t checksum_size,
uint32_t override_relocations_offset) {
return send_function_call(
c->channel,
c->config,
code,
label_writes,
suffix,
checksum_addr,
checksum_size,
override_relocations_offset);
}
void send_function_call(
Channel& ch,
const Client::Config& client_config,
shared_ptr<const CompiledFunctionCode> code,
const unordered_map<string, uint32_t>& label_writes,
const string& suffix,
uint32_t checksum_addr,
uint32_t checksum_size,
uint32_t override_relocations_offset) {
if (client_config.check_flag(Client::Flag::NO_SEND_FUNCTION_CALL)) {
throw logic_error("client does not support function calls");
}
if (code.get() && client_config.check_flag(Client::Flag::SEND_FUNCTION_CALL_CHECKSUM_ONLY)) {
throw logic_error("client only supports checksums in send_function_call");
}
string data = prepare_send_function_call_data(
code, label_writes, suffix, checksum_addr, checksum_size, override_relocations_offset,
client_config.check_flag(Client::Flag::ENCRYPTED_SEND_FUNCTION_CALL));
ch.send(0xB2, code ? code->index : 0x00, data);
}
void send_reconnect(shared_ptr<Client> c, uint32_t address, uint16_t port) {
+10 -2
View File
@@ -134,10 +134,18 @@ void empty_function_call_response_handler(uint32_t, uint32_t);
void send_quest_buffer_overflow(std::shared_ptr<Client> c);
void prepare_client_for_patches(std::shared_ptr<Client> c, std::function<void()> on_complete);
std::string prepare_send_function_call_data(
std::shared_ptr<const CompiledFunctionCode> code,
const std::unordered_map<std::string, uint32_t>& label_writes,
const std::string& suffix,
uint32_t checksum_addr,
uint32_t checksum_size,
uint32_t override_relocations_offset,
bool use_encrypted_format);
void send_function_call(
Channel& ch,
const Client::Config& client_config,
std::shared_ptr<CompiledFunctionCode> code,
std::shared_ptr<const CompiledFunctionCode> code,
const std::unordered_map<std::string, uint32_t>& label_writes = {},
const std::string& suffix = "",
uint32_t checksum_addr = 0,
@@ -145,7 +153,7 @@ void send_function_call(
uint32_t override_relocations_offset = 0);
void send_function_call(
std::shared_ptr<Client> c,
std::shared_ptr<CompiledFunctionCode> code,
std::shared_ptr<const CompiledFunctionCode> code,
const std::unordered_map<std::string, uint32_t>& label_writes = {},
const std::string& suffix = "",
uint32_t checksum_addr = 0,