add ability to disassemble DC NTE quests
This commit is contained in:
+3
-2
@@ -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
@@ -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));
|
||||||
|
|||||||
Reference in New Issue
Block a user