From fc3d3c76f81b6b348b01f5335cf83a3328a39bcb Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 15 Mar 2020 12:54:55 -0400 Subject: [PATCH] Edges further towards providing enough information for dynamic user-provided machine creation. --- Machines/Utility/MachineForTarget.cpp | 20 +++++---- Machines/Utility/MachineForTarget.hpp | 17 +++++++- OSBindings/SDL/main.cpp | 63 ++++++++++++++------------- 3 files changed, 60 insertions(+), 40 deletions(-) diff --git a/Machines/Utility/MachineForTarget.cpp b/Machines/Utility/MachineForTarget.cpp index 73db40743..638cfbf85 100644 --- a/Machines/Utility/MachineForTarget.cpp +++ b/Machines/Utility/MachineForTarget.cpp @@ -26,19 +26,19 @@ #include "../../Analyser/Static/Acorn/Target.hpp" #include "../../Analyser/Static/AmstradCPC/Target.hpp" #include "../../Analyser/Static/AppleII/Target.hpp" +#include "../../Analyser/Static/Atari2600/Target.hpp" #include "../../Analyser/Static/AtariST/Target.hpp" #include "../../Analyser/Static/Commodore/Target.hpp" #include "../../Analyser/Static/Macintosh/Target.hpp" #include "../../Analyser/Static/MSX/Target.hpp" #include "../../Analyser/Static/Oric/Target.hpp" +#include "../../Analyser/Static/Sega/Target.hpp" #include "../../Analyser/Static/ZX8081/Target.hpp" #include "../../Analyser/Dynamic/MultiMachine/MultiMachine.hpp" #include "TypedDynamicMachine.hpp" -namespace { - -::Machine::DynamicMachine *MachineForTarget(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher, Machine::Error &error) { +Machine::DynamicMachine *Machine::MachineForTarget(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher, Machine::Error &error) { error = Machine::Error::None; Machine::DynamicMachine *machine = nullptr; @@ -78,9 +78,7 @@ namespace { return machine; } -} - -::Machine::DynamicMachine *::Machine::MachineForTargets(const Analyser::Static::TargetList &targets, const ROMMachine::ROMFetcher &rom_fetcher, Error &error) { +Machine::DynamicMachine *Machine::MachineForTargets(const Analyser::Static::TargetList &targets, const ROMMachine::ROMFetcher &rom_fetcher, Error &error) { // Zero targets implies no machine. if(targets.empty()) { error = Error::NoTargets; @@ -193,8 +191,8 @@ std::map>> Machin return options; } -std::map> Machine::ConstructionOptionsByMachineName() { - std::map> options; +std::map> Machine::TargetsByMachineName(bool meaningful_without_media_only) { + std::map> options; #define AddMapped(Name, TargetNamespace) \ options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Name), new Analyser::Static::TargetNamespace::Target)); @@ -210,6 +208,12 @@ std::map> Machine::Construction AddMapped(Vic20, Commodore); Add(ZX8081); + if(!meaningful_without_media_only) { + Add(Atari2600); + options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::ColecoVision), new Analyser::Static::Target(Analyser::Machine::ColecoVision))); + AddMapped(MasterSystem, Sega); + } + #undef Add #undef AddTwo diff --git a/Machines/Utility/MachineForTarget.hpp b/Machines/Utility/MachineForTarget.hpp index 15fd27bf9..e5891b5b4 100644 --- a/Machines/Utility/MachineForTarget.hpp +++ b/Machines/Utility/MachineForTarget.hpp @@ -19,6 +19,8 @@ #include #include +/*! +*/ namespace Machine { enum class Error { @@ -36,6 +38,12 @@ enum class Error { */ DynamicMachine *MachineForTargets(const Analyser::Static::TargetList &targets, const ::ROMMachine::ROMFetcher &rom_fetcher, Error &error); +/*! + Allocates an instance of DynamicMaachine holding the machine described + by @c target. It is the caller's responsibility to delete the class when finished. +*/ +DynamicMachine *MachineForTarget(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher, Machine::Error &error); + /*! Returns a short string name for the machine identified by the target, which is guaranteed not to have any spaces or other potentially @@ -55,12 +63,17 @@ std::string LongNameForTargetMachine(const Analyser::Machine target); std::vector AllMachines(bool meaningful_without_media_only, bool long_names); /*! - Returns a map from machine name to the list of options that machine + Returns a map from long machine name to the list of options that machine exposes, for all machines. */ std::map>> AllOptionsByMachineName(); -std::map> ConstructionOptionsByMachineName(); +/*! + Returns a map from long machine name to appropriate instances of Target for the machine. + + NB: Usually the instances of Target can be dynamic_casted to Reflection::Struct in order to determine available properties. +*/ +std::map> TargetsByMachineName(bool meaningful_without_media_only); } diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index f7eaa114a..927ca35be 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -13,10 +13,11 @@ #include #include #include +#include #include #include #include -#include +#include #include @@ -363,7 +364,7 @@ bool KeyboardKeyForSDLScancode(SDL_Scancode scancode, Inputs::Keyboard::Key &key struct ParsedArguments { std::string file_name; - Configurable::SelectionSet selections; + std::map> selections; }; /*! Parses an argc/argv pair to discern program arguments. */ @@ -388,11 +389,11 @@ ParsedArguments parse_arguments(int argc, char *argv[]) { std::size_t split_index = argument.find("="); if(split_index == std::string::npos) { - arguments.selections[argument] = std::make_unique(true); + arguments.selections[argument] = true; } else { std::string name = argument.substr(0, split_index); std::string value = argument.substr(split_index+1, std::string::npos); - arguments.selections[name] = std::make_unique(value); + arguments.selections[name] = value; } } else { arguments.file_name = arg; @@ -506,12 +507,14 @@ int main(int argc, char *argv[]) { std::cout << std::endl; } - const auto construction_options = Machine::ConstructionOptionsByMachineName(); - for(const auto &options: construction_options) { - std::cout << options.first << ":" << std::endl; - for(const auto &option: options.second->all_keys()) { + const auto targets = Machine::TargetsByMachineName(false); + for(const auto &target: targets) { + const auto reflectable = dynamic_cast(target.second.get()); + + std::cout << target.first << ":" << std::endl; + for(const auto &option: reflectable->all_keys()) { std::cout << '\t' << "--" << option; - const auto type = options.second->type_of(option); + const auto type = reflectable->type_of(option); // Is this a registered enum? If so, list options. if(!Reflection::Enum::name(*type).empty()) { @@ -565,14 +568,14 @@ int main(int argc, char *argv[]) { "/usr/local/share/CLK/", "/usr/share/CLK/" }; - if(arguments.selections.find("rompath") != arguments.selections.end()) { - const std::string user_path = arguments.selections["rompath"]->list_selection()->value; - if(user_path.back() != '/') { - paths.push_back(user_path + "/"); - } else { - paths.push_back(user_path); - } - } +// if(arguments.selections.find("rompath") != arguments.selections.end()) { +// const std::string user_path = arguments.selections["rompath"]->list_selection()->value; +// if(user_path.back() != '/') { +// paths.push_back(user_path + "/"); +// } else { +// paths.push_back(user_path); +// } +// } std::vector>> results; for(const auto &rom: roms) { @@ -630,17 +633,17 @@ int main(int argc, char *argv[]) { // Apply the speed multiplier, if one was requested. if(arguments.selections.find("speed") != arguments.selections.end()) { - const char *speed_string = arguments.selections["speed"]->list_selection()->value.c_str(); - char *end; - double speed = strtod(speed_string, &end); - - if(size_t(end - speed_string) != strlen(speed_string)) { - std::cerr << "Unable to parse speed: " << speed_string << std::endl; - } else if(speed <= 0.0) { - std::cerr << "Cannot run at speed " << speed_string << "; speeds must be positive." << std::endl; - } else { - machine_runner.set_speed_multiplier(speed); - } +// const char *speed_string = arguments.selections["speed"]->list_selection()->value.c_str(); +// char *end; +// double speed = strtod(speed_string, &end); +// +// if(size_t(end - speed_string) != strlen(speed_string)) { +// std::cerr << "Unable to parse speed: " << speed_string << std::endl; +// } else if(speed <= 0.0) { +// std::cerr << "Cannot run at speed " << speed_string << "; speeds must be positive." << std::endl; +// } else { +// machine_runner.set_speed_multiplier(speed); +// } } // Check whether a 'logical' keyboard has been requested. @@ -718,7 +721,7 @@ int main(int argc, char *argv[]) { int window_width, window_height; SDL_GetWindowSize(window, &window_width, &window_height); - Configurable::Device *const configurable_device = machine->configurable_device(); +/* Configurable::Device *const configurable_device = machine->configurable_device(); if(configurable_device) { // Establish user-friendly options by default. configurable_device->set_selections(configurable_device->get_user_friendly_selections()); @@ -741,7 +744,7 @@ int main(int argc, char *argv[]) { // Apply the user's actual selections to final the defaults. configurable_device->set_selections(arguments.selections); - } + }*/ // If this is a joystick machine, check for and open attached joysticks. /*!