From 9ca1b79409b2eb983b106320e37d2bc8f454d1ee Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Sat, 22 Jun 2024 15:22:32 -0700 Subject: [PATCH] add .include directives in quest assembler --- src/Main.cc | 8 +++++- src/Quest.cc | 3 ++- src/QuestScript.cc | 31 ++++++++++++++++++++++- src/QuestScript.hh | 2 +- system/quests/retrieval/q058-gc-e.bin.txt | 5 ++++ 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/Main.cc b/src/Main.cc index 99edf215..21de25f9 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -1237,7 +1237,13 @@ Action a_assemble_quest_script( uncompressed .bind file instead.\n", +[](Arguments& args) { string text = read_input_data(args); - string result = assemble_quest_script(text); + + const string& input_filename = args.get(1, false); + string include_dir = (!input_filename.empty() && (input_filename != "-")) + ? dirname(input_filename) + : "."; + + string result = assemble_quest_script(text, include_dir); bool compress = !args.get("decompressed"); if (compress) { result = prs_compress_optimal(result); diff --git a/src/Quest.cc b/src/Quest.cc index 24bb232f..c2262339 100644 --- a/src/Quest.cc +++ b/src/Quest.cc @@ -543,7 +543,8 @@ QuestIndex::QuestIndex( file_data = decode_dlq_data(load_file(file_path)); filename.resize(filename.size() - 4); } else if (ends_with(filename, ".txt")) { - file_data = assemble_quest_script(load_file(file_path)); + string include_dir = dirname(file_path); + file_data = assemble_quest_script(load_file(file_path), include_dir); filename.resize(filename.size() - 4); if (ends_with(filename, ".bin")) { filename.push_back('d'); diff --git a/src/QuestScript.cc b/src/QuestScript.cc index 5474e6e9..35d40b8a 100644 --- a/src/QuestScript.cc +++ b/src/QuestScript.cc @@ -12,6 +12,12 @@ #include #include +#ifdef HAVE_RESOURCE_FILE +#include +#include +#include +#endif + #include "BattleParamsIndex.hh" #include "CommandFormats.hh" #include "Compression.hh" @@ -1964,7 +1970,7 @@ struct RegisterAssigner { array, 0x100> numbered_regs; }; -std::string assemble_quest_script(const std::string& text) { +std::string assemble_quest_script(const std::string& text, const std::string& include_directory) { auto lines = split(text, '\n'); // Strip comments and whitespace @@ -2196,6 +2202,29 @@ std::string assemble_quest_script(const std::string& text) { } else if (starts_with(line, ".zero ")) { size_t size = stoull(line.substr(6), nullptr, 0); code_w.extend_by(size, 0x00); + } else if (starts_with(line, ".include_bin ")) { + string filename = line.substr(13); + strip_whitespace(filename); + code_w.write(load_file(include_directory + "/" + filename)); + } else if (starts_with(line, ".include_native ")) { +#ifdef HAVE_RESOURCE_FILE + string filename = line.substr(16); + strip_whitespace(filename); + string native_text = load_file(include_directory + "/" + filename); + string code; + if (is_ppc(quest_version)) { + code = std::move(PPC32Emulator::assemble(native_text).code); + } else if (is_x86(quest_version)) { + code = std::move(X86Emulator::assemble(native_text).code); + } else if (is_sh4(quest_version)) { + code = std::move(SH4Emulator::assemble(native_text).code); + } else { + throw runtime_error("unknown architecture"); + } + code_w.write(code); +#else + throw runtime_error("native code cannot be compiled; rebuild newserv with libresource_file"); +#endif } continue; } diff --git a/src/QuestScript.hh b/src/QuestScript.hh index b03efa9b..c08140a0 100644 --- a/src/QuestScript.hh +++ b/src/QuestScript.hh @@ -83,6 +83,6 @@ struct PSOQuestHeaderBB { Episode episode_for_quest_episode_number(uint8_t episode_number); std::string disassemble_quest_script(const void* data, size_t size, Version version, uint8_t override_language = 0xFF, bool reassembly_mode = false); -std::string assemble_quest_script(const std::string& text); +std::string assemble_quest_script(const std::string& text, const std::string& include_directory); Episode find_quest_episode_from_script(const void* data, size_t size, Version version); diff --git a/system/quests/retrieval/q058-gc-e.bin.txt b/system/quests/retrieval/q058-gc-e.bin.txt index 67807098..8d6baf55 100644 --- a/system/quests/retrieval/q058-gc-e.bin.txt +++ b/system/quests/retrieval/q058-gc-e.bin.txt @@ -96,6 +96,11 @@ // can be included in the quest script using the .data directive, like this: // hello_symbol_chat: // .data 28000000 FFFF 0D00 FFFF FFFF 05 18 1D 00 05 28 1D 01 36 20 2A 00 3C 00 32 00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00 02 FF 00 00 02 FF 00 00 02 FF 00 00 02 FF 00 00 02 +// You can also include binary data from another file in the same directory +// (the contents of the file are "pasted" into the assembled script, as if you +// had pasted in the hex along with a .data directive): +// movement_data: +// .include_bin movement_data.bin // There is also a directive for including a large number of zero bytes: // lots_of_zeroes: // .zero 0x400 // 1024 bytes of zeroes