add JSON rare table conversion

This commit is contained in:
Martin Michelsen
2023-10-16 19:37:29 -07:00
parent 04d92d93e5
commit 0bb9718da3
2 changed files with 40 additions and 16 deletions
+21 -8
View File
@@ -252,8 +252,9 @@ The actions are:\n\
system/blueburst/rare-table.json for an example of this format). If --json\n\ system/blueburst/rare-table.json for an example of this format). If --json\n\
is not given, the input is parsed as a REL rare item set.\n\ is not given, the input is parsed as a REL rare item set.\n\
convert-itemrt-rel-to-json [INPUT-FILENAME [OUTPUT-FILENAME]]\n\ convert-itemrt-rel-to-json [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
Convert a REL rare table to a JSON rare item set. The resulting JSON has\n\ convert-itemrt-gsl-to-json [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
the same structure as system/blueburst/rare-table.json.\n\ Convert a REL or GSL rare table to a JSON rare item set. The resulting JSON\n\
has the same structure as system/blueburst/rare-table.json.\n\
generate-dc-serial-number [--domain=DOMAIN] [--subdomain=SUBDOMAIN]\n\ generate-dc-serial-number [--domain=DOMAIN] [--subdomain=SUBDOMAIN]\n\
Generate a PSO DC serial number. DOMAIN should be 0 for DCv1 or 1 for DCv2;\n\ Generate a PSO DC serial number. DOMAIN should be 0 for DCv1 or 1 for DCv2;\n\
SUBDOMAIN should be 0 for Japanese, 1 for USA, or 2 for Europe.\n\ SUBDOMAIN should be 0 for Japanese, 1 for USA, or 2 for Europe.\n\
@@ -315,6 +316,7 @@ enum class Behavior {
ENCODE_TEXT_ARCHIVE, ENCODE_TEXT_ARCHIVE,
FORMAT_RARE_ITEM_SET, FORMAT_RARE_ITEM_SET,
CONVERT_ITEMRT_REL_TO_JSON, CONVERT_ITEMRT_REL_TO_JSON,
CONVERT_ITEMRT_GSL_TO_JSON,
SHOW_EP3_MAPS, SHOW_EP3_MAPS,
SHOW_EP3_CARDS, SHOW_EP3_CARDS,
GENERATE_EP3_CARDS_HTML, GENERATE_EP3_CARDS_HTML,
@@ -362,6 +364,7 @@ static bool behavior_takes_input_filename(Behavior b) {
(b == Behavior::DECODE_SJIS) || (b == Behavior::DECODE_SJIS) ||
(b == Behavior::FORMAT_RARE_ITEM_SET) || (b == Behavior::FORMAT_RARE_ITEM_SET) ||
(b == Behavior::CONVERT_ITEMRT_REL_TO_JSON) || (b == Behavior::CONVERT_ITEMRT_REL_TO_JSON) ||
(b == Behavior::CONVERT_ITEMRT_GSL_TO_JSON) ||
(b == Behavior::EXTRACT_GSL) || (b == Behavior::EXTRACT_GSL) ||
(b == Behavior::EXTRACT_BML) || (b == Behavior::EXTRACT_BML) ||
(b == Behavior::DECODE_TEXT_ARCHIVE) || (b == Behavior::DECODE_TEXT_ARCHIVE) ||
@@ -399,6 +402,7 @@ static bool behavior_takes_output_filename(Behavior b) {
(b == Behavior::ENCODE_QST) || (b == Behavior::ENCODE_QST) ||
(b == Behavior::DISASSEMBLE_QUEST_SCRIPT) || (b == Behavior::DISASSEMBLE_QUEST_SCRIPT) ||
(b == Behavior::CONVERT_ITEMRT_REL_TO_JSON) || (b == Behavior::CONVERT_ITEMRT_REL_TO_JSON) ||
(b == Behavior::CONVERT_ITEMRT_GSL_TO_JSON) ||
(b == Behavior::DECODE_SJIS) || (b == Behavior::DECODE_SJIS) ||
(b == Behavior::EXTRACT_GSL) || (b == Behavior::EXTRACT_GSL) ||
(b == Behavior::EXTRACT_BML) || (b == Behavior::EXTRACT_BML) ||
@@ -613,6 +617,8 @@ int main(int argc, char** argv) {
behavior = Behavior::FORMAT_RARE_ITEM_SET; behavior = Behavior::FORMAT_RARE_ITEM_SET;
} else if (!strcmp(argv[x], "convert-itemrt-rel-to-json")) { } else if (!strcmp(argv[x], "convert-itemrt-rel-to-json")) {
behavior = Behavior::CONVERT_ITEMRT_REL_TO_JSON; behavior = Behavior::CONVERT_ITEMRT_REL_TO_JSON;
} else if (!strcmp(argv[x], "convert-itemrt-gsl-to-json")) {
behavior = Behavior::CONVERT_ITEMRT_GSL_TO_JSON;
} else if (!strcmp(argv[x], "show-ep3-maps")) { } else if (!strcmp(argv[x], "show-ep3-maps")) {
behavior = Behavior::SHOW_EP3_MAPS; behavior = Behavior::SHOW_EP3_MAPS;
} else if (!strcmp(argv[x], "show-ep3-cards")) { } else if (!strcmp(argv[x], "show-ep3-cards")) {
@@ -718,7 +724,7 @@ int main(int argc, char** argv) {
filename += ".json"; filename += ".json";
} else if (behavior == Behavior::DISASSEMBLE_QUEST_SCRIPT) { } else if (behavior == Behavior::DISASSEMBLE_QUEST_SCRIPT) {
filename += ".txt"; filename += ".txt";
} else if (behavior == Behavior::CONVERT_ITEMRT_REL_TO_JSON) { } else if ((behavior == Behavior::CONVERT_ITEMRT_REL_TO_JSON) || (behavior == Behavior::CONVERT_ITEMRT_GSL_TO_JSON)) {
filename += ".json"; filename += ".json";
} else { } else {
filename += ".dec"; filename += ".dec";
@@ -727,7 +733,8 @@ int main(int argc, char** argv) {
} else if (isatty(fileno(stdout)) && } else if (isatty(fileno(stdout)) &&
(behavior != Behavior::DISASSEMBLE_QUEST_SCRIPT) && (behavior != Behavior::DISASSEMBLE_QUEST_SCRIPT) &&
(behavior != Behavior::CONVERT_ITEMRT_REL_TO_JSON)) { (behavior != Behavior::CONVERT_ITEMRT_REL_TO_JSON) &&
(behavior != Behavior::CONVERT_ITEMRT_GSL_TO_JSON)) {
// If stdout is a terminal and the data is not known to be text, use // If stdout is a terminal and the data is not known to be text, use
// print_data to write the result // print_data to write the result
print_data(stdout, data, size); print_data(stdout, data, size);
@@ -1562,9 +1569,15 @@ int main(int argc, char** argv) {
break; break;
} }
case Behavior::CONVERT_ITEMRT_REL_TO_JSON: { case Behavior::CONVERT_ITEMRT_REL_TO_JSON:
case Behavior::CONVERT_ITEMRT_GSL_TO_JSON: {
shared_ptr<string> data(new string(read_input_data())); shared_ptr<string> data(new string(read_input_data()));
RELRareItemSet rs(data); unique_ptr<RareItemSet> rs;
if (behavior == Behavior::CONVERT_ITEMRT_GSL_TO_JSON) {
rs.reset(new GSLRareItemSet(data, big_endian));
} else {
rs.reset(new RELRareItemSet(data));
}
// Compute the mapping of {rt_index: EnemyType} for each episode // Compute the mapping of {rt_index: EnemyType} for each episode
const auto& generate_table = +[](Episode episode) -> vector<vector<EnemyType>> { const auto& generate_table = +[](Episode episode) -> vector<vector<EnemyType>> {
@@ -1606,7 +1619,7 @@ int main(int argc, char** argv) {
continue; continue;
} }
for (const auto& spec : rs.get_enemy_specs(GameMode::NORMAL, episode, difficulty, section_id, rt_index)) { for (const auto& spec : rs->get_enemy_specs(GameMode::NORMAL, episode, difficulty, section_id, rt_index)) {
uint32_t primary_identifier = (spec.item_code[0] << 16) | (spec.item_code[1] << 8) | spec.item_code[2]; uint32_t primary_identifier = (spec.item_code[0] << 16) | (spec.item_code[1] << 8) | spec.item_code[2];
if (primary_identifier == 0) { if (primary_identifier == 0) {
continue; continue;
@@ -1625,7 +1638,7 @@ int main(int argc, char** argv) {
for (size_t area = 0; area < 0x12; area++) { for (size_t area = 0; area < 0x12; area++) {
auto area_list = JSON::list(); auto area_list = JSON::list();
for (const auto& spec : rs.get_box_specs(GameMode::NORMAL, episode, difficulty, section_id, area)) { for (const auto& spec : rs->get_box_specs(GameMode::NORMAL, episode, difficulty, section_id, area)) {
uint32_t primary_identifier = (spec.item_code[0] << 16) | (spec.item_code[1] << 8) | spec.item_code[2]; uint32_t primary_identifier = (spec.item_code[0] << 16) | (spec.item_code[1] << 8) | spec.item_code[2];
if (primary_identifier == 0) { if (primary_identifier == 0) {
continue; continue;
+19 -8
View File
@@ -101,13 +101,16 @@ GSLRareItemSet::GSLRareItemSet(shared_ptr<const string> data, bool is_big_endian
((episode == Episode::EP2) ? "l" : ""), ((episode == Episode::EP2) ? "l" : ""),
tolower(abbreviation_for_difficulty(difficulty)), // One of "nhvu" tolower(abbreviation_for_difficulty(difficulty)), // One of "nhvu"
section_id); section_id);
auto entry = this->gsl.get(filename); try {
if (entry.second < sizeof(Table)) { auto entry = this->gsl.get(filename);
throw runtime_error(string_printf("table %s is too small", filename.c_str())); if (entry.second < sizeof(Table)) {
throw runtime_error(string_printf("table %s is too small", filename.c_str()));
}
this->tables.emplace(
this->key_for_params(mode, episode, difficulty, section_id),
reinterpret_cast<const Table*>(entry.first));
} catch (const out_of_range&) {
} }
this->tables.emplace(
this->key_for_params(mode, episode, difficulty, section_id),
reinterpret_cast<const Table*>(entry.first));
} }
} }
} }
@@ -116,12 +119,20 @@ GSLRareItemSet::GSLRareItemSet(shared_ptr<const string> data, bool is_big_endian
std::vector<RareItemSet::ExpandedDrop> GSLRareItemSet::get_enemy_specs( std::vector<RareItemSet::ExpandedDrop> GSLRareItemSet::get_enemy_specs(
GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const { GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const {
return this->tables.at(this->key_for_params(mode, episode, difficulty, secid))->get_enemy_specs(rt_index); try {
return this->tables.at(this->key_for_params(mode, episode, difficulty, secid))->get_enemy_specs(rt_index);
} catch (const out_of_range&) {
return {};
}
} }
std::vector<RareItemSet::ExpandedDrop> GSLRareItemSet::get_box_specs( std::vector<RareItemSet::ExpandedDrop> GSLRareItemSet::get_box_specs(
GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const { GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const {
return this->tables.at(this->key_for_params(mode, episode, difficulty, secid))->get_box_specs(area); try {
return this->tables.at(this->key_for_params(mode, episode, difficulty, secid))->get_box_specs(area);
} catch (const out_of_range&) {
return {};
}
} }
RELRareItemSet::RELRareItemSet(shared_ptr<const string> data) : data(data) { RELRareItemSet::RELRareItemSet(shared_ptr<const string> data) : data(data) {