add ability to disassemble DC NTE quests

This commit is contained in:
Martin Michelsen
2023-11-25 11:53:40 -08:00
parent fe6e957c92
commit 897cca83cf
2 changed files with 74 additions and 21 deletions
+3 -2
View File
@@ -146,7 +146,7 @@ void write_output_data(Arguments& args, const void* data, size_t size, const cha
// If the output is to a specified file, write it there // If the output is to a specified file, write it there
save_file(output_filename, data, size); save_file(output_filename, data, size);
} else if (output_filename.empty() && !input_filename.empty() && (input_filename != "-")) { } else if (output_filename.empty() && (output_filename != "-") && !input_filename.empty() && (input_filename != "-")) {
// If no output filename is given and an input filename is given, write to // If no output filename is given and an input filename is given, write to
// <input_filename>.<extension> // <input_filename>.<extension>
if (!extension) { if (!extension) {
@@ -1033,7 +1033,8 @@ Action a_disassemble_quest_script(
if (!args.get<bool>("decompressed")) { if (!args.get<bool>("decompressed")) {
data = prs_decompress(data); data = prs_decompress(data);
} }
string result = disassemble_quest_script(data.data(), data.size(), version, 1); uint8_t language = args.get<bool>("japanese") ? 0 : 1;
string result = disassemble_quest_script(data.data(), data.size(), version, language);
write_output_data(args, result.data(), result.size(), "txt"); write_output_data(args, result.data(), result.size(), "txt");
}); });
Action a_disassemble_quest_map( Action a_disassemble_quest_map(
+71 -19
View File
@@ -34,6 +34,54 @@ ToT as_type(const FromT& v) {
return ret; return ret;
} }
static TextEncoding encoding_for_language(uint8_t language) {
return (language ? TextEncoding::ISO8859 : TextEncoding::SJIS);
}
static string escape_string(const string& data, TextEncoding encoding = TextEncoding::UTF8) {
string decoded;
switch (encoding) {
case TextEncoding::UTF8:
decoded = data;
break;
case TextEncoding::UTF16:
decoded = tt_utf16_to_utf8(data);
break;
case TextEncoding::SJIS:
decoded = tt_sjis_to_utf8(data);
break;
case TextEncoding::ISO8859:
decoded = tt_8859_to_utf8(data);
break;
case TextEncoding::ASCII:
decoded = tt_ascii_to_utf8(data);
break;
default:
return format_data_string(data);
}
string ret = "\"";
for (char ch : decoded) {
if (ch == '\n') {
ret += "\\n";
} else if (ch == '\r') {
ret += "\\r";
} else if (ch == '\t') {
ret += "\\t";
} else if (ch >= 0x00 && ch < 0x20) {
ret += string_printf("\\x%02hhX", ch);
} else if (ch == '\'') {
ret += "\\\'";
} else if (ch == '\"') {
ret += "\\\"";
} else {
ret += ch;
}
}
ret += "\"";
return ret;
}
static string format_and_indent_data(const void* data, size_t size, uint64_t start_address) { static string format_and_indent_data(const void* data, size_t size, uint64_t start_address) {
struct iovec iov; struct iovec iov;
iov.iov_base = const_cast<void*>(data); iov.iov_base = const_cast<void*>(data);
@@ -809,7 +857,8 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
const auto& header = r.get<PSOQuestHeaderDCNTE>(); const auto& header = r.get<PSOQuestHeaderDCNTE>();
code_offset = header.code_offset; code_offset = header.code_offset;
function_table_offset = header.function_table_offset; function_table_offset = header.function_table_offset;
lines.emplace_back(".name " + JSON(header.name.decode(0)).serialize()); language = 0;
lines.emplace_back(".name " + escape_string(header.name.decode(0)));
break; break;
} }
case Version::DC_V1_12_2000_PROTOTYPE: case Version::DC_V1_12_2000_PROTOTYPE:
@@ -818,11 +867,12 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
const auto& header = r.get<PSOQuestHeaderDC>(); const auto& header = r.get<PSOQuestHeaderDC>();
code_offset = header.code_offset; code_offset = header.code_offset;
function_table_offset = header.function_table_offset; function_table_offset = header.function_table_offset;
language = header.language;
lines.emplace_back(string_printf(".quest_num %hu", header.quest_number.load())); lines.emplace_back(string_printf(".quest_num %hu", header.quest_number.load()));
lines.emplace_back(string_printf(".language %hhu", header.language)); lines.emplace_back(string_printf(".language %hhu", header.language));
lines.emplace_back(".name " + JSON(header.name.decode(language)).serialize()); lines.emplace_back(".name " + escape_string(header.name.decode(language)));
lines.emplace_back(".short_desc " + JSON(header.short_description.decode(language)).serialize()); lines.emplace_back(".short_desc " + escape_string(header.short_description.decode(language)));
lines.emplace_back(".long_desc " + JSON(header.long_description.decode(language)).serialize()); lines.emplace_back(".long_desc " + escape_string(header.long_description.decode(language)));
break; break;
} }
case Version::PC_V2: { case Version::PC_V2: {
@@ -830,11 +880,12 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
const auto& header = r.get<PSOQuestHeaderPC>(); const auto& header = r.get<PSOQuestHeaderPC>();
code_offset = header.code_offset; code_offset = header.code_offset;
function_table_offset = header.function_table_offset; function_table_offset = header.function_table_offset;
language = header.language;
lines.emplace_back(string_printf(".quest_num %hu", header.quest_number.load())); lines.emplace_back(string_printf(".quest_num %hu", header.quest_number.load()));
lines.emplace_back(string_printf(".language %hhu", header.language)); lines.emplace_back(string_printf(".language %hhu", header.language));
lines.emplace_back(".name " + JSON(header.name.decode(language)).serialize()); lines.emplace_back(".name " + escape_string(header.name.decode(language)));
lines.emplace_back(".short_desc " + JSON(header.short_description.decode(language)).serialize()); lines.emplace_back(".short_desc " + escape_string(header.short_description.decode(language)));
lines.emplace_back(".long_desc " + JSON(header.long_description.decode(language)).serialize()); lines.emplace_back(".long_desc " + escape_string(header.long_description.decode(language)));
break; break;
} }
case Version::GC_NTE: case Version::GC_NTE:
@@ -845,12 +896,13 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
const auto& header = r.get<PSOQuestHeaderGC>(); const auto& header = r.get<PSOQuestHeaderGC>();
code_offset = header.code_offset; code_offset = header.code_offset;
function_table_offset = header.function_table_offset; function_table_offset = header.function_table_offset;
language = header.language;
lines.emplace_back(string_printf(".quest_num %hhu", header.quest_number)); 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(".language %hhu", header.language));
lines.emplace_back(string_printf(".episode %hhu", header.episode)); lines.emplace_back(string_printf(".episode %hhu", header.episode));
lines.emplace_back(".name " + JSON(header.name.decode(language)).serialize()); lines.emplace_back(".name " + escape_string(header.name.decode(language)));
lines.emplace_back(".short_desc " + JSON(header.short_description.decode(language)).serialize()); lines.emplace_back(".short_desc " + escape_string(header.short_description.decode(language)));
lines.emplace_back(".long_desc " + JSON(header.long_description.decode(language)).serialize()); lines.emplace_back(".long_desc " + escape_string(header.long_description.decode(language)));
break; break;
} }
case Version::BB_V4: { case Version::BB_V4: {
@@ -864,9 +916,9 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
if (header.joinable_in_progress) { if (header.joinable_in_progress) {
lines.emplace_back(".joinable_in_progress"); lines.emplace_back(".joinable_in_progress");
} }
lines.emplace_back(".name " + JSON(header.name.decode(language)).serialize()); lines.emplace_back(".name " + escape_string(header.name.decode(language)));
lines.emplace_back(".short_desc " + JSON(header.short_description.decode(language)).serialize()); lines.emplace_back(".short_desc " + escape_string(header.short_description.decode(language)));
lines.emplace_back(".long_desc " + JSON(header.long_description.decode(language)).serialize()); lines.emplace_back(".long_desc " + escape_string(header.long_description.decode(language)));
break; break;
} }
default: default:
@@ -1115,13 +1167,13 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
if (def->flags & F_PASS) { if (def->flags & F_PASS) {
arg_stack_values.emplace_back(tt_utf16_to_utf8(w.str())); arg_stack_values.emplace_back(tt_utf16_to_utf8(w.str()));
} }
dasm_arg = JSON(w.str()).serialize(); dasm_arg = escape_string(w.str(), TextEncoding::UTF16);
} else { } else {
string s = cmd_r.get_cstr(); string s = cmd_r.get_cstr();
if (def->flags & F_PASS) { if (def->flags & F_PASS) {
arg_stack_values.emplace_back(s); arg_stack_values.emplace_back(language ? tt_8859_to_utf8(s) : tt_sjis_to_utf8(s));
} }
dasm_arg = JSON(s).serialize(); dasm_arg = escape_string(s, encoding_for_language(language));
} }
break; break;
default: default:
@@ -1227,7 +1279,7 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
break; break;
case Arg::Type::CSTRING: case Arg::Type::CSTRING:
if (arg_value.type == ArgStackValue::Type::CSTRING) { if (arg_value.type == ArgStackValue::Type::CSTRING) {
dasm_arg = format_data_string(arg_value.as_string); dasm_arg = escape_string(arg_value.as_string);
} else { } else {
dasm_arg = "/* invalid-type */"; dasm_arg = "/* invalid-type */";
} }
@@ -1331,12 +1383,12 @@ std::string disassemble_quest_script(const void* data, size_t size, Version vers
} }
str_data = tt_utf16_to_utf8(str_data); str_data = tt_utf16_to_utf8(str_data);
} }
string formatted = format_data_string(str_data); string formatted = escape_string(str_data, use_wstrs ? TextEncoding::UTF16 : encoding_for_language(language));
lines.emplace_back(string_printf(" %04" PRIX32 " %s", l->offset, formatted.c_str())); lines.emplace_back(string_printf(" %04" PRIX32 " %s", l->offset, formatted.c_str()));
} }
print_as_struct.template operator()<Arg::DataType::PLAYER_VISUAL_CONFIG, PlayerVisualConfig>([&](const PlayerVisualConfig& visual) -> void { print_as_struct.template operator()<Arg::DataType::PLAYER_VISUAL_CONFIG, PlayerVisualConfig>([&](const PlayerVisualConfig& visual) -> void {
lines.emplace_back(" // As PlayerVisualConfig"); lines.emplace_back(" // As PlayerVisualConfig");
string name = format_data_string(visual.name.decode(language)); string name = escape_string(visual.name.decode(language));
lines.emplace_back(string_printf(" %04zX name %s", l->offset + offsetof(PlayerVisualConfig, name), name.c_str())); lines.emplace_back(string_printf(" %04zX name %s", l->offset + offsetof(PlayerVisualConfig, name), name.c_str()));
lines.emplace_back(string_printf(" %04zX name_color %08" PRIX32, l->offset + offsetof(PlayerVisualConfig, name_color), visual.name_color.load())); lines.emplace_back(string_printf(" %04zX name_color %08" PRIX32, l->offset + offsetof(PlayerVisualConfig, name_color), visual.name_color.load()));
string a2_str = format_data_string(visual.unknown_a2.data(), sizeof(visual.unknown_a2)); string a2_str = format_data_string(visual.unknown_a2.data(), sizeof(visual.unknown_a2));