diff --git a/src/Main.cc b/src/Main.cc index 2ad4fec9..86ecc09b 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -1028,7 +1028,9 @@ Action a_disassemble_quest_script( Disassemble the input quest script (.bin file) into a text representation\n\ of the commands and metadata it contains. Specify the quest\'s game version\n\ with one of the --dc-nte, --dc-v1, --dc-v2, --pc, --gc-nte, --gc, --gc-ep3,\n\ - --xb, or --bb options.\n", + --xb, or --bb options. If you intend to edit and reassemble the script, use\n\ + the --reassembly option to add explicit label numbers and remove offsets\n\ + and data in code sections.\n", +[](Arguments& args) { string data = read_input_data(args); auto version = get_cli_version(args); @@ -1036,7 +1038,8 @@ Action a_disassemble_quest_script( data = prs_decompress(data); } uint8_t language = args.get("japanese") ? 0 : 1; - string result = disassemble_quest_script(data.data(), data.size(), version, language); + bool reassembly_mode = args.get("reassembly"); + string result = disassemble_quest_script(data.data(), data.size(), version, language, reassembly_mode); write_output_data(args, result.data(), result.size(), "txt"); }); Action a_disassemble_quest_map( diff --git a/src/QuestScript.cc b/src/QuestScript.cc index a2aa9445..e266878c 100644 --- a/src/QuestScript.cc +++ b/src/QuestScript.cc @@ -34,6 +34,11 @@ ToT as_type(const FromT& v) { return ret; } +static const char* name_for_header_episode_number(uint8_t episode) { + static const array names = {"Episode1", "Episode2", "Episode4"}; + return names.at(episode); +} + static TextEncoding encoding_for_language(uint8_t language) { return (language ? TextEncoding::ISO8859 : TextEncoding::SJIS); } @@ -892,7 +897,7 @@ opcodes_by_name_for_version(Version v) { return index; } -std::string disassemble_quest_script(const void* data, size_t size, Version version, uint8_t language) { +std::string disassemble_quest_script(const void* data, size_t size, Version version, uint8_t language, bool reassembly_mode) { StringReader r(data, size); deque lines; lines.emplace_back(string_printf(".version %s", name_for_enum(version))); @@ -954,7 +959,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers } lines.emplace_back(string_printf(".quest_num %hhu", header.quest_number)); lines.emplace_back(string_printf(".language %hhu", header.language)); - lines.emplace_back(string_printf(".episode %hhu", header.episode)); + lines.emplace_back(string_printf(".episode %s", name_for_header_episode_number(header.episode))); lines.emplace_back(".name " + escape_string(header.name.decode(language))); lines.emplace_back(".short_desc " + escape_string(header.short_description.decode(language))); lines.emplace_back(".long_desc " + escape_string(header.long_description.decode(language))); @@ -966,7 +971,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers code_offset = header.code_offset; function_table_offset = header.function_table_offset; lines.emplace_back(string_printf(".quest_num %hu", header.quest_number.load())); - lines.emplace_back(string_printf(".episode %hhu", header.episode)); + lines.emplace_back(string_printf(".episode %s", name_for_header_episode_number(header.episode))); lines.emplace_back(string_printf(".max_players %hhu", header.episode)); if (header.joinable) { lines.emplace_back(".joinable"); @@ -1009,7 +1014,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers while (!function_table_r.eof()) { try { uint32_t function_id = function_table.size(); - string name = string_printf("label%04" PRIX32, function_id); + string name = (function_id == 0) ? "start" : string_printf("label%04" PRIX32, function_id); uint32_t offset = function_table_r.get_u32l(); auto l = make_shared