From ccd82591aa0526fd8323fe440f27176d38ede1bd Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 4 Jun 2021 21:53:56 -0400 Subject: [PATCH] Reinstates SDL error message; adds expansion of `~`. --- Machines/Utility/ROMCatalogue.cpp | 38 ++++++++++ Machines/Utility/ROMCatalogue.hpp | 14 ++++ .../xcschemes/Clock Signal Kiosk.xcscheme | 12 +++- OSBindings/SDL/main.cpp | 69 +++++++++++++++---- 4 files changed, 117 insertions(+), 16 deletions(-) diff --git a/Machines/Utility/ROMCatalogue.cpp b/Machines/Utility/ROMCatalogue.cpp index dd42e06b0..e04c58042 100644 --- a/Machines/Utility/ROMCatalogue.cpp +++ b/Machines/Utility/ROMCatalogue.cpp @@ -96,6 +96,44 @@ bool Request::Node::validate(Map &map) const { return (type == Type::Any && has_any) || (type == Type::All && has_all); } +void Request::visit( + const std::function &enter_list, + const std::function &exit_list, + const std::function &add_item +) const { + node.visit(enter_list, exit_list, add_item); +} + +void Request::Node::visit( + const std::function &enter_list, + const std::function &exit_list, + const std::function &add_item +) const { + switch(type) { + case Type::One: + enter_list(ListType::Single); + add_item(ROM::Request::ListType::Any, Description(name), is_optional, 0); + exit_list(); + break; + + case Type::Any: + case Type::All: { + const ListType list_type = type == Type::Any ? ListType::Any : ListType::All; + enter_list(list_type); + for(size_t index = 0; index < children.size(); index++) { + auto &child = children[index]; + + if(child.type == Type::One) { + add_item(list_type, Description(child.name), child.is_optional, children.size() - 1 - index); + } else { + child.visit(enter_list, exit_list, add_item); + } + } + exit_list(); + } break; + } +} + std::optional Description::from_crc(uint32_t crc32) { for(int name = 1; name <= SpectrumPlus3; name++) { const Description candidate = Description(ROM::Name(name)); diff --git a/Machines/Utility/ROMCatalogue.hpp b/Machines/Utility/ROMCatalogue.hpp index 96b4eefd1..01fc921d2 100644 --- a/Machines/Utility/ROMCatalogue.hpp +++ b/Machines/Utility/ROMCatalogue.hpp @@ -163,6 +163,15 @@ struct Request { std::vector all_descriptions() const; + enum class ListType { + Any, All, Single + }; + void visit( + const std::function &enter_list, + const std::function &exit_list, + const std::function &add_item + ) const; + private: struct Node { enum class Type { @@ -178,6 +187,11 @@ struct Request { void add_descriptions(std::vector &) const; bool validate(Map &) const; + void visit( + const std::function &enter_list, + const std::function &exit_list, + const std::function &add_item + ) const; }; Node node; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme index 7c5c8f004..e270b2f2b 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme @@ -56,6 +56,14 @@ argument = "/Users/thomasharte/Downloads/test-dsk-for-rw-and-50-60-hz/TEST-RW-60Hz.DSK" isEnabled = "NO"> + + + + @@ -106,7 +114,7 @@ + isEnabled = "NO"> diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index 735dfab6d..aafe6be07 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -707,11 +707,20 @@ int main(int argc, char *argv[]) { const auto rompath = arguments.selections.find("rompath"); if(rompath != arguments.selections.end()) { - if(rompath->second.back() != '/') { - paths.push_back(rompath->second + "/"); - } else { - paths.push_back(rompath->second); + std::string path = rompath->second; + + // Ensure the path ends in a slash. + if(path.back() != '/') { + path += '/'; } + + // If ~ is present, expand it to %HOME%. + const size_t tilde_position = path.find("~"); + if(tilde_position != std::string::npos) { + path.replace(tilde_position, 1, getenv("HOME")); + } + + paths.push_back(path); } ROM::Map results; @@ -764,11 +773,33 @@ int main(int argc, char *argv[]) { if(!machine) { switch(error) { default: break; - case ::Machine::Error::MissingROM: -/* std::cerr << "Could not find system ROMs; please install to /usr/local/share/CLK/ or /usr/share/CLK/, or provide a --rompath." << std::endl; - std::cerr << "One or more of the following was needed but not found:" << std::endl; - for(const auto &rom: requested_roms) { - std::cerr << rom.machine_name << '/' << rom.file_name << " ("; + case ::Machine::Error::MissingROM: { + std::cerr << "Could not find system ROMs; please install to /usr/local/share/CLK/ or /usr/share/CLK/, or provide a --rompath, e.g. --rompath=~/ROMs." << std::endl; + std::cerr << "Needed "; + + int indentation_level = 0; + const auto indent = [&indentation_level] { + if(indentation_level) { + std::cerr << std::endl; + for(int c = 0; c < indentation_level; c++) std::cerr << '\t'; + std::cerr << "* "; + } + }; + + requested_roms.visit([&indentation_level, indent] (ROM::Request::ListType type) { + indent(); + switch(type) { + default: + case ROM::Request::ListType::All: std::cerr << "all of:"; break; + case ROM::Request::ListType::Any: std::cerr << "any of:"; break; + } + ++indentation_level; + }, [&indentation_level] { + --indentation_level; + }, [&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()) { std::cerr << rom.descriptive_name << "; "; } @@ -779,17 +810,27 @@ int main(int argc, char *argv[]) { is_first = false; std::cerr << std::hex << std::setfill('0') << std::setw(8) << crc32; } - std::cerr << ")" << std::endl; - } - std::cerr << std::endl << "Tried specifically: "; + std::cerr << ")"; + + if(remaining) { + std::cerr << ";"; + if(remaining == 1) { + std::cerr << ((type == ROM::Request::ListType::All) ? " and" : " or"); + } + } else { + std::cerr << "."; + } + }); + + std::cerr << std::endl << std::endl << "Searched unsuccessfully: "; bool is_first = true; for(const auto &path: checked_paths) { if(!is_first) std::cerr << "; "; std::cerr << path; is_first = false; } - std::cerr << std::endl;*/ - break; + std::cerr << std::endl; + } break; } return EXIT_FAILURE;