1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-24 17:32:55 +00:00

Edges further towards providing enough information for dynamic user-provided machine creation.

This commit is contained in:
Thomas Harte 2020-03-15 12:54:55 -04:00
parent 880bed04f5
commit fc3d3c76f8
3 changed files with 60 additions and 40 deletions

View File

@ -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<std::string, std::vector<std::unique_ptr<Configurable::Option>>> Machin
return options;
}
std::map<std::string, std::unique_ptr<Reflection::Struct>> Machine::ConstructionOptionsByMachineName() {
std::map<std::string, std::unique_ptr<Reflection::Struct>> options;
std::map<std::string, std::unique_ptr<Analyser::Static::Target>> Machine::TargetsByMachineName(bool meaningful_without_media_only) {
std::map<std::string, std::unique_ptr<Analyser::Static::Target>> 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<std::string, std::unique_ptr<Reflection::Struct>> 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

View File

@ -19,6 +19,8 @@
#include <string>
#include <vector>
/*!
*/
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<std::string> 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<std::string, std::vector<std::unique_ptr<Configurable::Option>>> AllOptionsByMachineName();
std::map<std::string, std::unique_ptr<Reflection::Struct>> 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<std::string, std::unique_ptr<Analyser::Static::Target>> TargetsByMachineName(bool meaningful_without_media_only);
}

View File

@ -13,10 +13,11 @@
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <memory>
#include <sys/stat.h>
#include <unistd.h>
#include <map>
#include <variant>
#include <SDL2/SDL.h>
@ -363,7 +364,7 @@ bool KeyboardKeyForSDLScancode(SDL_Scancode scancode, Inputs::Keyboard::Key &key
struct ParsedArguments {
std::string file_name;
Configurable::SelectionSet selections;
std::map<std::string, std::variant<std::string, bool>> 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<Configurable::BooleanSelection>(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<Configurable::ListSelection>(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<Reflection::Struct *>(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<std::unique_ptr<std::vector<uint8_t>>> 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.
/*!