add item pickup patch
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include <phosg/Filesystem.hh>
|
||||
#include <phosg/Strings.hh>
|
||||
#include <resource_file/ExecutableFormats/DOLFile.hh>
|
||||
#include <resource_file/ExecutableFormats/PEFile.hh>
|
||||
#include <resource_file/ExecutableFormats/XBEFile.hh>
|
||||
|
||||
using namespace std;
|
||||
@@ -112,9 +113,13 @@ public:
|
||||
this->directory.pop_back();
|
||||
}
|
||||
for (const auto& filename : phosg::list_directory(this->directory)) {
|
||||
if (filename.size() < 4) {
|
||||
continue;
|
||||
}
|
||||
string name = filename.substr(0, filename.size() - 4);
|
||||
string path = directory + "/" + filename;
|
||||
|
||||
if (phosg::ends_with(filename, ".dol")) {
|
||||
string name = filename.substr(0, filename.size() - 4);
|
||||
string path = directory + "/" + filename;
|
||||
ResourceDASM::DOLFile dol(path.c_str());
|
||||
auto mem = make_shared<ResourceDASM::MemoryContext>();
|
||||
dol.load_into(mem);
|
||||
@@ -122,16 +127,18 @@ public:
|
||||
this->enable_ppc = true;
|
||||
this->log.info("Loaded %s", name.c_str());
|
||||
} else if (phosg::ends_with(filename, ".xbe")) {
|
||||
string name = filename.substr(0, filename.size() - 4);
|
||||
string path = directory + "/" + filename;
|
||||
ResourceDASM::XBEFile xbe(path.c_str());
|
||||
auto mem = make_shared<ResourceDASM::MemoryContext>();
|
||||
xbe.load_into(mem);
|
||||
this->mems.emplace(name, mem);
|
||||
this->log.info("Loaded %s", name.c_str());
|
||||
} else if (phosg::ends_with(filename, ".exe")) {
|
||||
ResourceDASM::PEFile pe(path.c_str());
|
||||
auto mem = make_shared<ResourceDASM::MemoryContext>();
|
||||
pe.load_into(mem);
|
||||
this->mems.emplace(name, mem);
|
||||
this->log.info("Loaded %s", name.c_str());
|
||||
} else if (phosg::ends_with(filename, ".bin")) {
|
||||
string name = filename.substr(0, filename.size() - 4);
|
||||
string path = directory + "/" + filename;
|
||||
string data = phosg::load_file(path);
|
||||
auto mem = make_shared<ResourceDASM::MemoryContext>();
|
||||
mem->allocate_at(0x8C010000, data.size());
|
||||
|
||||
@@ -891,6 +891,98 @@ static void proxy_command_patch(shared_ptr<ProxyServer::LinkedSession> ses, cons
|
||||
}
|
||||
}
|
||||
|
||||
static bool console_address_in_range(Version version, uint32_t addr) {
|
||||
if (is_dc(version)) {
|
||||
return ((addr > 0x8C000000) && (addr <= 0x8CFFFFFC));
|
||||
} else if (is_gc(version)) {
|
||||
return ((addr > 0x80000000) && (addr <= 0x817FFFFC));
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void server_command_readmem(shared_ptr<Client> c, const std::string& args) {
|
||||
check_debug_enabled(c);
|
||||
|
||||
uint32_t addr = stoul(args, nullptr, 16);
|
||||
if (!console_address_in_range(c->version(), addr)) {
|
||||
send_text_message(c, "$C4Address out of\nrange");
|
||||
return;
|
||||
}
|
||||
|
||||
prepare_client_for_patches(c, [wc = weak_ptr<Client>(c), addr]() {
|
||||
auto c = wc.lock();
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
auto s = c->require_server_state();
|
||||
const char* function_name = is_dc(c->version())
|
||||
? "ReadMemoryWordDC"
|
||||
: is_gc(c->version())
|
||||
? "ReadMemoryWordGC"
|
||||
: "ReadMemoryWordX86";
|
||||
auto fn = s->function_code_index->name_to_function.at(function_name);
|
||||
send_function_call(c, fn, {{"address", addr}});
|
||||
c->function_call_response_queue.emplace_back([wc = weak_ptr<Client>(c), addr](uint32_t ret, uint32_t) {
|
||||
auto c = wc.lock();
|
||||
if (c) {
|
||||
string data_str;
|
||||
if (is_big_endian(c->version())) {
|
||||
be_uint32_t v = ret;
|
||||
data_str = phosg::format_data_string(&v, sizeof(v));
|
||||
} else {
|
||||
le_uint32_t v = ret;
|
||||
data_str = phosg::format_data_string(&v, sizeof(v));
|
||||
}
|
||||
send_text_message_printf(c, "Bytes at %08" PRIX32 ":\n$C6%s", addr, data_str.c_str());
|
||||
}
|
||||
});
|
||||
} catch (const out_of_range&) {
|
||||
send_text_message(c, "Invalid patch name");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void server_command_writemem(shared_ptr<Client> c, const std::string& args) {
|
||||
check_debug_enabled(c);
|
||||
|
||||
auto tokens = phosg::split(args, ' ');
|
||||
if (tokens.size() < 2) {
|
||||
send_text_message(c, "Incorrect arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t addr = stoul(tokens[0], nullptr, 16);
|
||||
if (!console_address_in_range(c->version(), addr)) {
|
||||
send_text_message(c, "$C4Address out of\nrange");
|
||||
return;
|
||||
}
|
||||
|
||||
tokens.erase(tokens.begin());
|
||||
std::string data = phosg::parse_data_string(phosg::join(tokens, " "));
|
||||
|
||||
prepare_client_for_patches(c, [wc = weak_ptr<Client>(c), addr, data]() {
|
||||
auto c = wc.lock();
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
auto s = c->require_server_state();
|
||||
const char* function_name = is_dc(c->version())
|
||||
? "WriteMemoryDC"
|
||||
: is_gc(c->version())
|
||||
? "WriteMemoryGC"
|
||||
: "WriteMemoryX86";
|
||||
auto fn = s->function_code_index->name_to_function.at(function_name);
|
||||
send_function_call(c, fn, {{"dest_addr", addr}, {"size", data.size()}}, data.data(), data.size());
|
||||
c->function_call_response_queue.emplace_back(empty_function_call_response_handler);
|
||||
} catch (const out_of_range&) {
|
||||
send_text_message(c, "Invalid patch name");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void server_command_persist(shared_ptr<Client> c, const std::string&) {
|
||||
auto l = c->require_lobby();
|
||||
if (l->check_flag(Lobby::Flag::DEFAULT)) {
|
||||
@@ -2703,6 +2795,7 @@ static const unordered_map<string, ChatCommandDefinition> chat_commands({
|
||||
{"$qsyncall", {server_command_qsyncall, proxy_command_qsyncall}},
|
||||
{"$quest", {server_command_quest, nullptr}},
|
||||
{"$rand", {server_command_rand, proxy_command_rand}},
|
||||
{"$readmem", {server_command_readmem, nullptr}},
|
||||
{"$save", {server_command_save, nullptr}},
|
||||
{"$savechar", {server_command_savechar, nullptr}},
|
||||
{"$saverec", {server_command_saverec, nullptr}},
|
||||
@@ -2728,6 +2821,7 @@ static const unordered_map<string, ChatCommandDefinition> chat_commands({
|
||||
{"$warpall", {server_command_warpall, proxy_command_warpall}},
|
||||
{"$what", {server_command_what, nullptr}},
|
||||
{"$where", {server_command_where, nullptr}},
|
||||
{"$writemem", {server_command_writemem, nullptr}},
|
||||
});
|
||||
|
||||
struct SplitCommand {
|
||||
|
||||
@@ -67,7 +67,7 @@ string CompiledFunctionCode::generate_client_command_t(
|
||||
if (offset > modified_code.size() - 4) {
|
||||
throw runtime_error("label out of range");
|
||||
}
|
||||
*reinterpret_cast<be_uint32_t*>(modified_code.data() + offset) = it.second;
|
||||
*reinterpret_cast<U32T<FooterT::IsBE>*>(modified_code.data() + offset) = it.second;
|
||||
}
|
||||
w.write(modified_code);
|
||||
} else {
|
||||
|
||||
@@ -2745,7 +2745,7 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
// base address for loading the file.
|
||||
send_function_call(
|
||||
c,
|
||||
s->function_code_index->name_to_function.at("ReadMemoryWord"),
|
||||
s->function_code_index->name_to_function.at("ReadMemoryWordGC"),
|
||||
{{"address", 0x80000034}}); // ArenaHigh from GC globals
|
||||
}
|
||||
break;
|
||||
@@ -2927,7 +2927,7 @@ static void send_dol_file_chunk(shared_ptr<Client> c, uint32_t start_addr) {
|
||||
string data_to_send = c->loading_dol_file->data.substr(offset, bytes_to_send);
|
||||
|
||||
auto s = c->require_server_state();
|
||||
auto fn = s->function_code_index->name_to_function.at("WriteMemory");
|
||||
auto fn = s->function_code_index->name_to_function.at("WriteMemoryGC");
|
||||
unordered_map<string, uint32_t> label_writes(
|
||||
{{"dest_addr", start_addr}, {"size", bytes_to_send}});
|
||||
send_function_call(c, fn, label_writes, data_to_send.data(), data_to_send.size());
|
||||
@@ -2946,10 +2946,10 @@ static void on_B3(shared_ptr<Client> c, uint16_t, uint32_t flag, string& data) {
|
||||
c->function_call_response_queue.pop_front();
|
||||
} else if (c->loading_dol_file.get()) {
|
||||
auto called_fn = s->function_code_index->index_to_function.at(flag);
|
||||
if (called_fn->short_name == "ReadMemoryWord") {
|
||||
if (called_fn->short_name == "ReadMemoryWordGC") {
|
||||
c->dol_base_addr = (cmd.return_value - c->loading_dol_file->data.size()) & (~3);
|
||||
send_dol_file_chunk(c, c->dol_base_addr);
|
||||
} else if (called_fn->short_name == "WriteMemory") {
|
||||
} else if (called_fn->short_name == "WriteMemoryGC") {
|
||||
if (cmd.return_value >= c->dol_base_addr + c->loading_dol_file->data.size()) {
|
||||
auto fn = s->function_code_index->name_to_function.at("RunDOL");
|
||||
unordered_map<string, uint32_t> label_writes({{"dol_base_ptr", c->dol_base_addr}});
|
||||
|
||||
@@ -135,9 +135,9 @@ WordSelectSet::WordSelectSet(const string& data, Version version, const vector<s
|
||||
this->parse_non_windows_t<true, 0x63F, 0x693>(decrypt_and_decompress_pr2_data<true>(data), use_sjis);
|
||||
break;
|
||||
case Version::GC_EP3_NTE:
|
||||
case Version::GC_V3:
|
||||
this->parse_non_windows_t<true, 0x67C, 0x68C>(decrypt_and_decompress_pr2_data<true>(data), use_sjis);
|
||||
break;
|
||||
case Version::GC_V3:
|
||||
case Version::GC_EP3:
|
||||
this->parse_non_windows_t<true, 0x804, 0x68C>(decrypt_and_decompress_pr2_data<true>(data), use_sjis);
|
||||
break;
|
||||
@@ -159,11 +159,13 @@ const string& WordSelectSet::string_for_token(uint16_t token_id) const {
|
||||
void WordSelectSet::print(FILE* stream) const {
|
||||
fprintf(stream, "strings:\n");
|
||||
for (size_t z = 0; z < this->strings.size(); z++) {
|
||||
fprintf(stream, " [%04zX] \"%s\"\n", z, this->strings[z].c_str());
|
||||
auto escaped = phosg::escape_controls_utf8(this->strings[z]);
|
||||
fprintf(stream, " [%04zX] \"%s\"\n", z, escaped.c_str());
|
||||
}
|
||||
fprintf(stream, "token_id_to_string_id:\n");
|
||||
for (size_t z = 0; z < this->token_id_to_string_id.size(); z++) {
|
||||
fprintf(stream, " [%04zX] %04zX \"%s\"\n", z, this->token_id_to_string_id[z], this->string_for_token(z).c_str());
|
||||
auto escaped = phosg::escape_controls_utf8(this->string_for_token(z));
|
||||
fprintf(stream, " [%04zX] %04zX \"%s\"\n", z, this->token_id_to_string_id[z], escaped.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user