From 8efc9f1b3e0c4500ba71d87df20a47a1a678dd59 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Mon, 28 Nov 2022 21:38:58 -0800 Subject: [PATCH] support uncompressed ep3 card definition lists --- src/CommandFormats.hh | 5 ++-- src/Episode3/DataIndex.cc | 27 +++++++++++++----- src/ProxyCommands.cc | 2 +- .../{cardupdate.mnr => card-definitions.mnr} | Bin system/ep3/{cardtext.mnr => card-text.mnr} | Bin 5 files changed, 24 insertions(+), 10 deletions(-) rename system/ep3/{cardupdate.mnr => card-definitions.mnr} (100%) rename system/ep3/{cardtext.mnr => card-text.mnr} (100%) diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index 006a2ac5..3ff465d4 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -1834,8 +1834,9 @@ struct S_RankUpdate_GC_Ep3_B7 { // B8 (S->C): Update card definitions (Episode 3) // Contents is a single little-endian le_uint32_t specifying the size of the // (PRS-compressed) data, followed immediately by the data. The maximum size of -// the compressed data is 0x9000 bytes, and the maximum size of the decompressed -// data is 0x36EC0 bytes. +// the compressed data is 0x9000 bytes, although the receive buffer size limit +// applies first in practice, which limits this to 0x7BF8 bytes. The maximum +// size of the decompressed data is 0x36EC0 bytes. // Note: PSO BB accepts this command as well, but ignores it. // B8 (C->S): Confirm updated card definitions (Episode 3) diff --git a/src/Episode3/DataIndex.cc b/src/Episode3/DataIndex.cc index 3cae382a..35cc9032 100644 --- a/src/Episode3/DataIndex.cc +++ b/src/Episode3/DataIndex.cc @@ -1161,7 +1161,7 @@ DataIndex::DataIndex(const string& directory, bool debug) unordered_map card_text; if (this->debug) { try { - string data = prs_decompress(load_file(directory + "/cardtext.mnr")); + string data = prs_decompress(load_file(directory + "/card-text.mnr")); StringReader r(data); while (!r.eof()) { @@ -1245,16 +1245,29 @@ DataIndex::DataIndex(const string& directory, bool debug) } try { - this->compressed_card_definitions = load_file(directory + "/cardupdate.mnr"); - string data = prs_decompress(this->compressed_card_definitions); + string decompressed_data; + if (isfile(directory + "/card-definitions.mnrd")) { + decompressed_data = load_file(directory + "/card-definitions.mnrd"); + this->compressed_card_definitions = prs_compress(decompressed_data); + } else { + this->compressed_card_definitions = load_file(directory + "/card-definitions.mnr"); + decompressed_data = prs_decompress(this->compressed_card_definitions); + } + if (this->compressed_card_definitions.size() > 0x7BF8) { + throw runtime_error("compressed card list data is too long"); + } + if (decompressed_data.size() > 0x36EC0) { + throw runtime_error("decompressed card list data is too long"); + } + // There's a footer after the card definitions, but we ignore it - if (data.size() % sizeof(CardDefinition) != sizeof(CardDefinitionsFooter)) { + if (decompressed_data.size() % sizeof(CardDefinition) != sizeof(CardDefinitionsFooter)) { throw runtime_error(string_printf( "decompressed card update file size %zX is not aligned with card definition size %zX (%zX extra bytes)", - data.size(), sizeof(CardDefinition), data.size() % sizeof(CardDefinition))); + decompressed_data.size(), sizeof(CardDefinition), decompressed_data.size() % sizeof(CardDefinition))); } - const auto* def = reinterpret_cast(data.data()); - size_t max_cards = data.size() / sizeof(CardDefinition); + const auto* def = reinterpret_cast(decompressed_data.data()); + size_t max_cards = decompressed_data.size() / sizeof(CardDefinition); for (size_t x = 0; x < max_cards; x++) { // The last card entry has the build date and some other metadata (and // isn't a real card, obviously), so skip it. Seems like the card ID is diff --git a/src/ProxyCommands.cc b/src/ProxyCommands.cc index 892875d8..df844517 100644 --- a/src/ProxyCommands.cc +++ b/src/ProxyCommands.cc @@ -1053,7 +1053,7 @@ static HandlerResult S_G_B8(shared_ptr, return HandlerResult::Type::FORWARD; } - string output_filename = string_printf("cardupdate.%" PRIu64 ".mnr", now()); + string output_filename = string_printf("card-definitions.%" PRIu64 ".mnr", now()); save_file(output_filename, r.read(size)); session.log.info("Wrote %zu bytes to %s", size, output_filename.c_str()); } diff --git a/system/ep3/cardupdate.mnr b/system/ep3/card-definitions.mnr similarity index 100% rename from system/ep3/cardupdate.mnr rename to system/ep3/card-definitions.mnr diff --git a/system/ep3/cardtext.mnr b/system/ep3/card-text.mnr similarity index 100% rename from system/ep3/cardtext.mnr rename to system/ep3/card-text.mnr