diff --git a/Machines/Utility/ROMCatalogue.cpp b/Machines/Utility/ROMCatalogue.cpp index 45b6bb9ae..e2059544d 100644 --- a/Machines/Utility/ROMCatalogue.cpp +++ b/Machines/Utility/ROMCatalogue.cpp @@ -10,6 +10,8 @@ #include #include +#include +#include using namespace ROM; @@ -198,6 +200,73 @@ std::optional Description::from_crc(uint32_t crc32) { return std::nullopt; } +std::string Description::description(int flags) const { + std::stringstream output; + + // Print the file name(s) and the descriptive name. + if(flags & DescriptionFlag::Filename) { + flags &= ~DescriptionFlag::Filename; + + output << machine_name << '/'; + if(file_names.size() == 1) { + output << file_names[0]; + } else { + output << "{"; + bool is_first = true; + for(const auto &file_name: file_names) { + if(!is_first) output << " or "; + output << file_name; + is_first = false; + } + output << "}"; + } + output << " (" << descriptive_name; + if(!flags) { + output << ")"; + return output.str(); + } + output << "; "; + } else { + output << descriptive_name; + if(!flags) { + return output.str(); + } + output << " ("; + } + + // Print the size. + if(flags & DescriptionFlag::Size) { + flags &= ~DescriptionFlag::Size; + output << size << " bytes"; + + if(!flags) { + output << ")"; + return output.str(); + } + output << "; "; + } + + // Print the CRC(s). + if(flags & DescriptionFlag::CRC) { + flags &= ~DescriptionFlag::CRC; + + output << ((crc32s.size() > 1) ? "usual crc32s: " : "usual crc32: "); + bool is_first = true; + for(const auto crc32: crc32s) { + if(!is_first) output << ", "; + is_first = false; + output << std::hex << std::setfill('0') << std::setw(8) << crc32; + } + + if(!flags) { + output << ")"; + return output.str(); + } + } + + return output.str(); +} + Description::Description(Name name) { switch(name) { default: assert(false); break; diff --git a/Machines/Utility/ROMCatalogue.hpp b/Machines/Utility/ROMCatalogue.hpp index 86bc5d9df..02ffc4987 100644 --- a/Machines/Utility/ROMCatalogue.hpp +++ b/Machines/Utility/ROMCatalogue.hpp @@ -141,9 +141,19 @@ struct Description { /// Constructs the @c Description that correlates to @c name. Description(Name name); - /// Constructs the @c Description that correlates to @c crc32. + /// Constructs the @c Description that correlates to @c crc32, if any. static std::optional from_crc(uint32_t crc32); + enum DescriptionFlag { + Size = 1 << 0, + CRC = 1 << 1, + Filename = 1 << 2, + }; + + /// Provides a single-line of text describing this ROM, including the usual base text + /// plus all the fields provided as @c flags . + std::string description(int flags) const; + private: template Description( Name name, std::string machine_name, std::string descriptive_name, FileNameT file_names, size_t size, CRC32T crc32s = uint32_t(0) @@ -157,13 +167,18 @@ struct Description { } }; +/// @returns a vector of all possible instances of ROM::Description — i.e. descriptions of every ROM +/// currently known to the ROM catalogue. std::vector all_descriptions(); struct Request { Request(Name name, bool optional = false); Request() {} + /// Forms the request that would be satisfied by @c this plus the right-hand side. Request operator &&(const Request &); + + /// Forms the request that would be satisfied by either @c this or the right-hand side. Request operator ||(const Request &); /// Inspects the ROMMap to ensure that it satisfies this @c Request. @@ -172,8 +187,16 @@ struct Request { /// All ROMs in the map will be resized to their idiomatic sizes. bool validate(Map &) const; + /// Returns a flattened array of all @c ROM::Descriptions that relate to anything + /// anywhere in this ROM request. std::vector all_descriptions() const; + /// @returns @c true if this request is empty, i.e. would be satisfied with no ROMs; @c false otherwise. + bool empty(); + + /// @returns what remains of this ROM request given that everything in @c map has been found. + Request subtract(const ROM::Map &map) const; + enum class ListType { Any, All, Single }; @@ -183,9 +206,6 @@ struct Request { const std::function &add_item ) const; - Request subtract(const ROM::Map &map) const; - bool empty(); - private: struct Node { enum class Type { diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm index 81b8f18ee..fc1573573 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm @@ -113,6 +113,7 @@ struct ActivityObserver: public Activity::Observer { ROM::Request missing_roms; _machine.reset(Machine::MachineForTargets(_analyser.targets, CSROMFetcher(&missing_roms), error)); if(!_machine) { + // TODO. [missingROMs appendFormat:@"Who told you?"]; /* for(const auto &missing_rom : missing_roms) { CSMissingROM *rom = [[CSMissingROM alloc] init]; diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index 5b73c5b5d..49402eed7 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -798,25 +798,9 @@ int main(int argc, char *argv[]) { }, [&indentation_level, indent] (ROM::Request::ListType type, const ROM::Description &rom, bool is_optional, size_t remaining) { indent(); if(is_optional) std::cerr << "optionally, "; - std::cerr << rom.machine_name << '/' << rom.file_names[0]; - if(!rom.descriptive_name.empty() || !rom.crc32s.empty()) { - std::cerr << " ("; - if(!rom.descriptive_name.empty()) { - std::cerr << rom.descriptive_name; - if(!rom.crc32s.empty()) std::cerr << "; "; - } - if(!rom.crc32s.empty()) { - std::cerr << ((rom.crc32s.size() > 1) ? "usual crc32s: " : "usual crc32: "); - bool is_first = true; - for(const auto crc32: rom.crc32s) { - if(!is_first) std::cerr << ", "; - is_first = false; - std::cerr << std::hex << std::setfill('0') << std::setw(8) << crc32; - } - } - std::cerr << ")"; - } + using DescriptionFlag = ROM::Description::DescriptionFlag; + std::cerr << rom.description(DescriptionFlag::Filename | DescriptionFlag::CRC); if(remaining) { std::cerr << ";";