mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-09 05:25:01 +00:00
Edges further towards providing enough information for dynamic user-provided machine creation.
This commit is contained in:
@@ -26,19 +26,19 @@
|
|||||||
#include "../../Analyser/Static/Acorn/Target.hpp"
|
#include "../../Analyser/Static/Acorn/Target.hpp"
|
||||||
#include "../../Analyser/Static/AmstradCPC/Target.hpp"
|
#include "../../Analyser/Static/AmstradCPC/Target.hpp"
|
||||||
#include "../../Analyser/Static/AppleII/Target.hpp"
|
#include "../../Analyser/Static/AppleII/Target.hpp"
|
||||||
|
#include "../../Analyser/Static/Atari2600/Target.hpp"
|
||||||
#include "../../Analyser/Static/AtariST/Target.hpp"
|
#include "../../Analyser/Static/AtariST/Target.hpp"
|
||||||
#include "../../Analyser/Static/Commodore/Target.hpp"
|
#include "../../Analyser/Static/Commodore/Target.hpp"
|
||||||
#include "../../Analyser/Static/Macintosh/Target.hpp"
|
#include "../../Analyser/Static/Macintosh/Target.hpp"
|
||||||
#include "../../Analyser/Static/MSX/Target.hpp"
|
#include "../../Analyser/Static/MSX/Target.hpp"
|
||||||
#include "../../Analyser/Static/Oric/Target.hpp"
|
#include "../../Analyser/Static/Oric/Target.hpp"
|
||||||
|
#include "../../Analyser/Static/Sega/Target.hpp"
|
||||||
#include "../../Analyser/Static/ZX8081/Target.hpp"
|
#include "../../Analyser/Static/ZX8081/Target.hpp"
|
||||||
|
|
||||||
#include "../../Analyser/Dynamic/MultiMachine/MultiMachine.hpp"
|
#include "../../Analyser/Dynamic/MultiMachine/MultiMachine.hpp"
|
||||||
#include "TypedDynamicMachine.hpp"
|
#include "TypedDynamicMachine.hpp"
|
||||||
|
|
||||||
namespace {
|
Machine::DynamicMachine *Machine::MachineForTarget(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher, Machine::Error &error) {
|
||||||
|
|
||||||
::Machine::DynamicMachine *MachineForTarget(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher, Machine::Error &error) {
|
|
||||||
error = Machine::Error::None;
|
error = Machine::Error::None;
|
||||||
|
|
||||||
Machine::DynamicMachine *machine = nullptr;
|
Machine::DynamicMachine *machine = nullptr;
|
||||||
@@ -78,9 +78,7 @@ namespace {
|
|||||||
return machine;
|
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.
|
// Zero targets implies no machine.
|
||||||
if(targets.empty()) {
|
if(targets.empty()) {
|
||||||
error = Error::NoTargets;
|
error = Error::NoTargets;
|
||||||
@@ -193,8 +191,8 @@ std::map<std::string, std::vector<std::unique_ptr<Configurable::Option>>> Machin
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, std::unique_ptr<Reflection::Struct>> Machine::ConstructionOptionsByMachineName() {
|
std::map<std::string, std::unique_ptr<Analyser::Static::Target>> Machine::TargetsByMachineName(bool meaningful_without_media_only) {
|
||||||
std::map<std::string, std::unique_ptr<Reflection::Struct>> options;
|
std::map<std::string, std::unique_ptr<Analyser::Static::Target>> options;
|
||||||
|
|
||||||
#define AddMapped(Name, TargetNamespace) \
|
#define AddMapped(Name, TargetNamespace) \
|
||||||
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Name), new Analyser::Static::TargetNamespace::Target));
|
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);
|
AddMapped(Vic20, Commodore);
|
||||||
Add(ZX8081);
|
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 Add
|
||||||
#undef AddTwo
|
#undef AddTwo
|
||||||
|
|
||||||
|
@@ -19,6 +19,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*/
|
||||||
namespace Machine {
|
namespace Machine {
|
||||||
|
|
||||||
enum class Error {
|
enum class Error {
|
||||||
@@ -36,6 +38,12 @@ enum class Error {
|
|||||||
*/
|
*/
|
||||||
DynamicMachine *MachineForTargets(const Analyser::Static::TargetList &targets, const ::ROMMachine::ROMFetcher &rom_fetcher, Error &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,
|
Returns a short string name for the machine identified by the target,
|
||||||
which is guaranteed not to have any spaces or other potentially
|
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);
|
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.
|
exposes, for all machines.
|
||||||
*/
|
*/
|
||||||
std::map<std::string, std::vector<std::unique_ptr<Configurable::Option>>> AllOptionsByMachineName();
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,10 +13,11 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <variant>
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
@@ -363,7 +364,7 @@ bool KeyboardKeyForSDLScancode(SDL_Scancode scancode, Inputs::Keyboard::Key &key
|
|||||||
|
|
||||||
struct ParsedArguments {
|
struct ParsedArguments {
|
||||||
std::string file_name;
|
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. */
|
/*! 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("=");
|
std::size_t split_index = argument.find("=");
|
||||||
|
|
||||||
if(split_index == std::string::npos) {
|
if(split_index == std::string::npos) {
|
||||||
arguments.selections[argument] = std::make_unique<Configurable::BooleanSelection>(true);
|
arguments.selections[argument] = true;
|
||||||
} else {
|
} else {
|
||||||
std::string name = argument.substr(0, split_index);
|
std::string name = argument.substr(0, split_index);
|
||||||
std::string value = argument.substr(split_index+1, std::string::npos);
|
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 {
|
} else {
|
||||||
arguments.file_name = arg;
|
arguments.file_name = arg;
|
||||||
@@ -506,12 +507,14 @@ int main(int argc, char *argv[]) {
|
|||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto construction_options = Machine::ConstructionOptionsByMachineName();
|
const auto targets = Machine::TargetsByMachineName(false);
|
||||||
for(const auto &options: construction_options) {
|
for(const auto &target: targets) {
|
||||||
std::cout << options.first << ":" << std::endl;
|
const auto reflectable = dynamic_cast<Reflection::Struct *>(target.second.get());
|
||||||
for(const auto &option: options.second->all_keys()) {
|
|
||||||
|
std::cout << target.first << ":" << std::endl;
|
||||||
|
for(const auto &option: reflectable->all_keys()) {
|
||||||
std::cout << '\t' << "--" << option;
|
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.
|
// Is this a registered enum? If so, list options.
|
||||||
if(!Reflection::Enum::name(*type).empty()) {
|
if(!Reflection::Enum::name(*type).empty()) {
|
||||||
@@ -565,14 +568,14 @@ int main(int argc, char *argv[]) {
|
|||||||
"/usr/local/share/CLK/",
|
"/usr/local/share/CLK/",
|
||||||
"/usr/share/CLK/"
|
"/usr/share/CLK/"
|
||||||
};
|
};
|
||||||
if(arguments.selections.find("rompath") != arguments.selections.end()) {
|
// if(arguments.selections.find("rompath") != arguments.selections.end()) {
|
||||||
const std::string user_path = arguments.selections["rompath"]->list_selection()->value;
|
// const std::string user_path = arguments.selections["rompath"]->list_selection()->value;
|
||||||
if(user_path.back() != '/') {
|
// if(user_path.back() != '/') {
|
||||||
paths.push_back(user_path + "/");
|
// paths.push_back(user_path + "/");
|
||||||
} else {
|
// } else {
|
||||||
paths.push_back(user_path);
|
// paths.push_back(user_path);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
std::vector<std::unique_ptr<std::vector<uint8_t>>> results;
|
std::vector<std::unique_ptr<std::vector<uint8_t>>> results;
|
||||||
for(const auto &rom: roms) {
|
for(const auto &rom: roms) {
|
||||||
@@ -630,17 +633,17 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
// Apply the speed multiplier, if one was requested.
|
// Apply the speed multiplier, if one was requested.
|
||||||
if(arguments.selections.find("speed") != arguments.selections.end()) {
|
if(arguments.selections.find("speed") != arguments.selections.end()) {
|
||||||
const char *speed_string = arguments.selections["speed"]->list_selection()->value.c_str();
|
// const char *speed_string = arguments.selections["speed"]->list_selection()->value.c_str();
|
||||||
char *end;
|
// char *end;
|
||||||
double speed = strtod(speed_string, &end);
|
// double speed = strtod(speed_string, &end);
|
||||||
|
//
|
||||||
if(size_t(end - speed_string) != strlen(speed_string)) {
|
// if(size_t(end - speed_string) != strlen(speed_string)) {
|
||||||
std::cerr << "Unable to parse speed: " << speed_string << std::endl;
|
// std::cerr << "Unable to parse speed: " << speed_string << std::endl;
|
||||||
} else if(speed <= 0.0) {
|
// } else if(speed <= 0.0) {
|
||||||
std::cerr << "Cannot run at speed " << speed_string << "; speeds must be positive." << std::endl;
|
// std::cerr << "Cannot run at speed " << speed_string << "; speeds must be positive." << std::endl;
|
||||||
} else {
|
// } else {
|
||||||
machine_runner.set_speed_multiplier(speed);
|
// machine_runner.set_speed_multiplier(speed);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether a 'logical' keyboard has been requested.
|
// Check whether a 'logical' keyboard has been requested.
|
||||||
@@ -718,7 +721,7 @@ int main(int argc, char *argv[]) {
|
|||||||
int window_width, window_height;
|
int window_width, window_height;
|
||||||
SDL_GetWindowSize(window, &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) {
|
if(configurable_device) {
|
||||||
// Establish user-friendly options by default.
|
// Establish user-friendly options by default.
|
||||||
configurable_device->set_selections(configurable_device->get_user_friendly_selections());
|
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.
|
// Apply the user's actual selections to final the defaults.
|
||||||
configurable_device->set_selections(arguments.selections);
|
configurable_device->set_selections(arguments.selections);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// If this is a joystick machine, check for and open attached joysticks.
|
// If this is a joystick machine, check for and open attached joysticks.
|
||||||
/*!
|
/*!
|
||||||
|
Reference in New Issue
Block a user