mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Starts a switch to reflectable-style runtime options.
The Amstrad CPC and ZX80/81 have made the jump so far, subject to caveats. The macOS build is unlikely currently to work properly.
This commit is contained in:
parent
1d40aa687e
commit
394ee61c78
@ -22,7 +22,7 @@ MultiConfigurable::MultiConfigurable(const std::vector<std::unique_ptr<::Machine
|
|||||||
void MultiConfigurable::set_options(const std::unique_ptr<Reflection::Struct> &options) {
|
void MultiConfigurable::set_options(const std::unique_ptr<Reflection::Struct> &options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Reflection::Struct> MultiConfigurable::get_options(OptionsType type) {
|
std::unique_ptr<Reflection::Struct> MultiConfigurable::get_options() {
|
||||||
// TODO: this'll need to mash options together, maybe? Or just take the front?
|
// TODO: this'll need to mash options together, maybe? Or just take the front?
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ class MultiConfigurable: public Configurable::Device {
|
|||||||
|
|
||||||
// Below is the standard Configurable::Device interface; see there for documentation.
|
// Below is the standard Configurable::Device interface; see there for documentation.
|
||||||
void set_options(const std::unique_ptr<Reflection::Struct> &options) final;
|
void set_options(const std::unique_ptr<Reflection::Struct> &options) final;
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final;
|
std::unique_ptr<Reflection::Struct> get_options() final;
|
||||||
// std::vector<std::unique_ptr<Configurable::Option>> get_options() final;
|
// std::vector<std::unique_ptr<Configurable::Option>> get_options() final;
|
||||||
// void set_selections(const Configurable::SelectionSet &selection_by_option) final;
|
// void set_selections(const Configurable::SelectionSet &selection_by_option) final;
|
||||||
// Configurable::SelectionSet get_accurate_selections() final;
|
// Configurable::SelectionSet get_accurate_selections() final;
|
||||||
|
@ -87,6 +87,7 @@ template <class BusHandler> class MOS6560 {
|
|||||||
void set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); }
|
void set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); }
|
||||||
Outputs::Display::ScanStatus get_scaled_scan_status() const { return crt_.get_scaled_scan_status() / 4.0f; }
|
Outputs::Display::ScanStatus get_scaled_scan_status() const { return crt_.get_scaled_scan_status() / 4.0f; }
|
||||||
void set_display_type(Outputs::Display::DisplayType display_type) { crt_.set_display_type(display_type); }
|
void set_display_type(Outputs::Display::DisplayType display_type) { crt_.set_display_type(display_type); }
|
||||||
|
Outputs::Display::DisplayType get_display_type() { return crt_.get_display_type(); }
|
||||||
Outputs::Speaker::Speaker *get_speaker() { return &speaker_; }
|
Outputs::Speaker::Speaker *get_speaker() { return &speaker_; }
|
||||||
|
|
||||||
void set_high_frequency_cutoff(float cutoff) {
|
void set_high_frequency_cutoff(float cutoff) {
|
||||||
|
@ -17,27 +17,28 @@ namespace Configurable {
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
A Configurable::Device provides a reflective struct listing the available runtime options for this machine.
|
A Configurable::Device provides a reflective struct listing the available runtime options for this machine.
|
||||||
It can provide it populated with 'accurate' options, 'user-friendly' options or just whatever the user
|
You can ordinarily either get or set a machine's current options, or else construct a new instance of
|
||||||
currently has selected.
|
its options with one of the OptionsTypes defined below.
|
||||||
|
*/
|
||||||
|
struct Device {
|
||||||
|
/// Sets the current options. The caller must ensure that the object passed in is either an instance of the machine's
|
||||||
|
/// Options struct, or else was previously returned by get_options.
|
||||||
|
virtual void set_options(const std::unique_ptr<Reflection::Struct> &options) = 0;
|
||||||
|
|
||||||
|
/// @returns An options object
|
||||||
|
virtual std::unique_ptr<Reflection::Struct> get_options() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
'Accurate' options should correspond to the way that this device was usually used during its lifespan.
|
'Accurate' options should correspond to the way that this device was usually used during its lifespan.
|
||||||
E.g. a ColecoVision might accurately be given composite output.
|
E.g. a ColecoVision might accurately be given composite output.
|
||||||
|
|
||||||
'User-friendly' options should be more like those that a user today might most expect from an emulator.
|
'User-friendly' options should be more like those that a user today might most expect from an emulator.
|
||||||
E.g. the ColecoVision might bump itself up to S-Video output.
|
E.g. the ColecoVision might bump itself up to S-Video output.
|
||||||
*/
|
*/
|
||||||
struct Device {
|
enum class OptionsType {
|
||||||
/// Sets the current options.
|
Accurate,
|
||||||
virtual void set_options(const std::unique_ptr<Reflection::Struct> &options) = 0;
|
UserFriendly
|
||||||
|
|
||||||
enum class OptionsType {
|
|
||||||
Current,
|
|
||||||
Accurate,
|
|
||||||
UserFriendly
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @returns Options of type @c type.
|
|
||||||
virtual std::unique_ptr<Reflection::Struct> get_options(OptionsType type) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,16 +40,6 @@
|
|||||||
|
|
||||||
namespace AmstradCPC {
|
namespace AmstradCPC {
|
||||||
|
|
||||||
//std::vector<std::unique_ptr<Configurable::Option>> get_options() {
|
|
||||||
// return Configurable::standard_options(
|
|
||||||
// Configurable::StandardOptions(Configurable::DisplayRGB | Configurable::DisplayCompositeColour)
|
|
||||||
// );
|
|
||||||
//}
|
|
||||||
|
|
||||||
std::unique_ptr<Reflection::Struct> get_options() {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Models the CPC's interrupt timer. Inputs are vsync, hsync, interrupt acknowledge and reset, and its output
|
Models the CPC's interrupt timer. Inputs are vsync, hsync, interrupt acknowledge and reset, and its output
|
||||||
is simply yes or no on whether an interupt is currently requested. Internally it uses a counter with a period
|
is simply yes or no on whether an interupt is currently requested. Internally it uses a counter with a period
|
||||||
@ -358,6 +348,11 @@ class CRTCBusHandler {
|
|||||||
crt_.set_display_type(display_type);
|
crt_.set_display_type(display_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the type of display.
|
||||||
|
Outputs::Display::DisplayType get_display_type() {
|
||||||
|
return crt_.get_display_type();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Sets the next video mode. Per the documentation, mode changes take effect only at the end of line,
|
Sets the next video mode. Per the documentation, mode changes take effect only at the end of line,
|
||||||
not immediately. So next means "as of the end of this line".
|
not immediately. So next means "as of the end of this line".
|
||||||
@ -1049,6 +1044,11 @@ template <bool has_fdc> class ConcreteMachine:
|
|||||||
crtc_bus_handler_.set_display_type(display_type);
|
crtc_bus_handler_.set_display_type(display_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A CRTMachine function; gets the output display type.
|
||||||
|
Outputs::Display::DisplayType get_display_type() {
|
||||||
|
return crtc_bus_handler_.get_display_type();
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns the speaker in use.
|
/// @returns the speaker in use.
|
||||||
Outputs::Speaker::Speaker *get_speaker() final {
|
Outputs::Speaker::Speaker *get_speaker() final {
|
||||||
return ay_.get_speaker();
|
return ay_.get_speaker();
|
||||||
@ -1118,34 +1118,16 @@ template <bool has_fdc> class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final {
|
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||||
return nullptr;
|
auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);
|
||||||
|
options->output = get_video_signal_configurable();
|
||||||
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_options(const std::unique_ptr<Reflection::Struct> &options) {
|
void set_options(const std::unique_ptr<Reflection::Struct> &str) {
|
||||||
|
const auto options = dynamic_cast<Options *>(str.get());
|
||||||
|
set_video_signal_configurable(options->output);
|
||||||
}
|
}
|
||||||
// std::vector<std::unique_ptr<Configurable::Option>> get_options() final {
|
|
||||||
// return AmstradCPC::get_options();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void set_selections(const Configurable::SelectionSet &selections_by_option) final {
|
|
||||||
// Configurable::Display display;
|
|
||||||
// if(Configurable::get_display(selections_by_option, display)) {
|
|
||||||
// set_video_signal_configurable(display);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Configurable::SelectionSet get_accurate_selections() final {
|
|
||||||
// Configurable::SelectionSet selection_set;
|
|
||||||
// Configurable::append_display_selection(selection_set, Configurable::Display::RGB);
|
|
||||||
// return selection_set;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Configurable::SelectionSet get_user_friendly_selections() final {
|
|
||||||
// Configurable::SelectionSet selection_set;
|
|
||||||
// Configurable::append_display_selection(selection_set, Configurable::Display::RGB);
|
|
||||||
// return selection_set;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// MARK: - Joysticks
|
// MARK: - Joysticks
|
||||||
const std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() final {
|
const std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() final {
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
#ifndef AmstradCPC_hpp
|
#ifndef AmstradCPC_hpp
|
||||||
#define AmstradCPC_hpp
|
#define AmstradCPC_hpp
|
||||||
|
|
||||||
#include "../../Reflection/Struct.h"
|
#include "../../Configurable/Configurable.hpp"
|
||||||
|
#include "../../Configurable/StandardOptions.hpp"
|
||||||
#include "../../Analyser/Static/StaticAnalyser.hpp"
|
#include "../../Analyser/Static/StaticAnalyser.hpp"
|
||||||
#include "../ROMMachine.hpp"
|
#include "../ROMMachine.hpp"
|
||||||
|
|
||||||
@ -17,9 +18,6 @@
|
|||||||
|
|
||||||
namespace AmstradCPC {
|
namespace AmstradCPC {
|
||||||
|
|
||||||
/// @returns The options available for an Amstrad CPC.
|
|
||||||
std::unique_ptr<Reflection::Struct> get_options();
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Models an Amstrad CPC.
|
Models an Amstrad CPC.
|
||||||
*/
|
*/
|
||||||
@ -29,6 +27,22 @@ class Machine {
|
|||||||
|
|
||||||
/// Creates and returns an Amstrad CPC.
|
/// Creates and returns an Amstrad CPC.
|
||||||
static Machine *AmstradCPC(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher);
|
static Machine *AmstradCPC(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher);
|
||||||
|
|
||||||
|
/// Defines the runtime options available for a ZX80/81.
|
||||||
|
class Options: public Reflection::StructImpl<Options> {
|
||||||
|
public:
|
||||||
|
Configurable::Display output = Configurable::Display::RGB;
|
||||||
|
|
||||||
|
Options(Configurable::OptionsType type) {
|
||||||
|
// Declare fields if necessary.
|
||||||
|
if(needs_declare()) {
|
||||||
|
DeclareField(output);
|
||||||
|
AnnounceEnumNS(Configurable, Display);
|
||||||
|
// TODO: some way to set limited enum support for a struct?
|
||||||
|
// In this case, to support only RGB and CompositeColour.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -869,7 +869,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK:: Configuration options.
|
// MARK:: Configuration options.
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final {
|
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,7 +527,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final {
|
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,7 +682,7 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final {
|
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,10 +181,28 @@ class Machine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Forwards the video signal to the target returned by get_crt().
|
Maps back from Outputs::Display::VideoSignal to Configurable::Display,
|
||||||
|
calling @c get_display_type for the input.
|
||||||
|
*/
|
||||||
|
Configurable::Display get_video_signal_configurable() {
|
||||||
|
switch(get_display_type()) {
|
||||||
|
default:
|
||||||
|
case Outputs::Display::DisplayType::RGB: return Configurable::Display::RGB;
|
||||||
|
case Outputs::Display::DisplayType::SVideo: return Configurable::Display::SVideo;
|
||||||
|
case Outputs::Display::DisplayType::CompositeColour: return Configurable::Display::CompositeColour;
|
||||||
|
case Outputs::Display::DisplayType::CompositeMonochrome: return Configurable::Display::CompositeMonochrome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the display type.
|
||||||
*/
|
*/
|
||||||
virtual void set_display_type(Outputs::Display::DisplayType display_type) {}
|
virtual void set_display_type(Outputs::Display::DisplayType display_type) {}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Gets the display type.
|
||||||
|
*/
|
||||||
|
virtual Outputs::Display::DisplayType get_display_type() { return Outputs::Display::DisplayType::RGB; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double clock_rate_ = 1.0;
|
double clock_rate_ = 1.0;
|
||||||
|
@ -373,7 +373,7 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final {
|
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,7 +682,7 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final {
|
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,7 +454,7 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final {
|
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -653,7 +653,7 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final {
|
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +378,7 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final {
|
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,7 +627,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final {
|
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +176,6 @@ std::vector<std::string> Machine::AllMachines(bool meaningful_without_media_only
|
|||||||
std::map<std::string, std::unique_ptr<Reflection::Struct>> Machine::AllOptionsByMachineName() {
|
std::map<std::string, std::unique_ptr<Reflection::Struct>> Machine::AllOptionsByMachineName() {
|
||||||
std::map<std::string, std::unique_ptr<Reflection::Struct>> options;
|
std::map<std::string, std::unique_ptr<Reflection::Struct>> options;
|
||||||
|
|
||||||
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::AmstradCPC), AmstradCPC::get_options()));
|
|
||||||
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::AppleII), Apple::II::get_options()));
|
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::AppleII), Apple::II::get_options()));
|
||||||
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::AtariST), Atari::ST::get_options()));
|
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::AtariST), Atari::ST::get_options()));
|
||||||
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::ColecoVision), Coleco::Vision::get_options()));
|
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::ColecoVision), Coleco::Vision::get_options()));
|
||||||
@ -186,7 +185,14 @@ std::map<std::string, std::unique_ptr<Reflection::Struct>> Machine::AllOptionsBy
|
|||||||
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::MSX), MSX::get_options()));
|
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::MSX), MSX::get_options()));
|
||||||
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Oric), Oric::get_options()));
|
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Oric), Oric::get_options()));
|
||||||
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Vic20), Commodore::Vic20::get_options()));
|
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Vic20), Commodore::Vic20::get_options()));
|
||||||
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::ZX8081), ZX8081::get_options()));
|
|
||||||
|
#define Emplace(machine, class) \
|
||||||
|
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::machine), std::make_unique<class::Options>(Configurable::OptionsType::UserFriendly)));
|
||||||
|
|
||||||
|
Emplace(AmstradCPC, AmstradCPC::Machine);
|
||||||
|
Emplace(ZX8081, ZX8081::Machine);
|
||||||
|
|
||||||
|
#undef Emplace
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
@ -50,22 +50,6 @@ enum ROMType: uint8_t {
|
|||||||
ZX80 = 0, ZX81
|
ZX80 = 0, ZX81
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Options: public Reflection::StructImpl<Options> {
|
|
||||||
bool automatic_tape_motor_control = true;
|
|
||||||
bool quickload = true;
|
|
||||||
|
|
||||||
Options() {
|
|
||||||
if(needs_declare()) {
|
|
||||||
DeclareField(automatic_tape_motor_control);
|
|
||||||
DeclareField(quickload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::unique_ptr<Reflection::Struct> get_options() {
|
|
||||||
return std::make_unique<Options>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool is_zx81> class ConcreteMachine:
|
template<bool is_zx81> class ConcreteMachine:
|
||||||
public CRTMachine::Machine,
|
public CRTMachine::Machine,
|
||||||
public MediaTarget::Machine,
|
public MediaTarget::Machine,
|
||||||
@ -422,31 +406,18 @@ template<bool is_zx81> class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::unique_ptr<Reflection::Struct> get_options(OptionsType type) final {
|
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||||
auto options = std::make_unique<Options>();
|
auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly); // OptionsType is arbitrary, but not optional.
|
||||||
switch(type) {
|
options->automatic_tape_motor_control = use_automatic_tape_motor_control_;
|
||||||
case OptionsType::Current:
|
options->quickload = allow_fast_tape_hack_;
|
||||||
options->automatic_tape_motor_control = use_automatic_tape_motor_control_;
|
|
||||||
options->quickload = allow_fast_tape_hack_;
|
|
||||||
break;
|
|
||||||
case OptionsType::Accurate:
|
|
||||||
case OptionsType::UserFriendly:
|
|
||||||
options->automatic_tape_motor_control =
|
|
||||||
options->quickload = type == OptionsType::UserFriendly;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_options(const std::unique_ptr<Reflection::Struct> &options) {
|
void set_options(const std::unique_ptr<Reflection::Struct> &str) {
|
||||||
if(Reflection::get<bool>(*options, "quickload", allow_fast_tape_hack_)) {
|
const auto options = dynamic_cast<Options *>(str.get());
|
||||||
set_use_fast_tape();
|
set_use_automatic_tape_motor_control(options->automatic_tape_motor_control);
|
||||||
}
|
allow_fast_tape_hack_ = options->quickload;
|
||||||
|
set_use_fast_tape();
|
||||||
bool autotapemotor;
|
|
||||||
if(Reflection::get<bool>(*options, "automatic_tape_motor_control", autotapemotor)) {
|
|
||||||
set_use_automatic_tape_motor_control(autotapemotor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#ifndef ZX8081_hpp
|
#ifndef ZX8081_hpp
|
||||||
#define ZX8081_hpp
|
#define ZX8081_hpp
|
||||||
|
|
||||||
#include "../../Reflection/Struct.h"
|
#include "../../Configurable/Configurable.hpp"
|
||||||
#include "../../Analyser/Static/StaticAnalyser.hpp"
|
#include "../../Analyser/Static/StaticAnalyser.hpp"
|
||||||
#include "../ROMMachine.hpp"
|
#include "../ROMMachine.hpp"
|
||||||
|
|
||||||
@ -17,9 +17,7 @@
|
|||||||
|
|
||||||
namespace ZX8081 {
|
namespace ZX8081 {
|
||||||
|
|
||||||
/// @returns The options available for a ZX80 or ZX81.
|
/// The ZX80/81 machine.
|
||||||
std::unique_ptr<Reflection::Struct> get_options();
|
|
||||||
|
|
||||||
class Machine {
|
class Machine {
|
||||||
public:
|
public:
|
||||||
virtual ~Machine();
|
virtual ~Machine();
|
||||||
@ -28,6 +26,24 @@ class Machine {
|
|||||||
|
|
||||||
virtual void set_tape_is_playing(bool is_playing) = 0;
|
virtual void set_tape_is_playing(bool is_playing) = 0;
|
||||||
virtual bool get_tape_is_playing() = 0;
|
virtual bool get_tape_is_playing() = 0;
|
||||||
|
|
||||||
|
/// Defines the runtime options available for a ZX80/81.
|
||||||
|
class Options: public Reflection::StructImpl<Options> {
|
||||||
|
public:
|
||||||
|
bool automatic_tape_motor_control;
|
||||||
|
bool quickload;
|
||||||
|
|
||||||
|
Options(Configurable::OptionsType type):
|
||||||
|
automatic_tape_motor_control(type == Configurable::OptionsType::UserFriendly),
|
||||||
|
quickload(automatic_tape_motor_control) {
|
||||||
|
|
||||||
|
// Declare fields if necessary.
|
||||||
|
if(needs_declare()) {
|
||||||
|
DeclareField(automatic_tape_motor_control);
|
||||||
|
DeclareField(quickload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@
|
|||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
<CommandLineArgument
|
<CommandLineArgument
|
||||||
argument = "--help"
|
argument = "--help"
|
||||||
isEnabled = "NO">
|
isEnabled = "YES">
|
||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
</CommandLineArguments>
|
</CommandLineArguments>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
|
@ -497,39 +497,42 @@ int main(int argc, char *argv[]) {
|
|||||||
std::cout << "Further machine options:" << std::endl;
|
std::cout << "Further machine options:" << std::endl;
|
||||||
std::cout << "(* means: a selection will be made automatically based on the file selected, if any)" << std::endl << std::endl;
|
std::cout << "(* means: a selection will be made automatically based on the file selected, if any)" << std::endl << std::endl;
|
||||||
|
|
||||||
// const auto all_options = Machine::AllOptionsByMachineName();
|
|
||||||
// for(const auto &machine_options: all_options) {
|
|
||||||
// std::cout << machine_options.first << ":" << std::endl;
|
|
||||||
// for(const auto &option: machine_options.second) {
|
|
||||||
// std::cout << '\t' << "--" << option->short_name;
|
|
||||||
//
|
|
||||||
// Configurable::ListOption *list_option = dynamic_cast<Configurable::ListOption *>(option.get());
|
|
||||||
// if(list_option) {
|
|
||||||
// std::cout << "={";
|
|
||||||
// bool is_first = true;
|
|
||||||
// for(const auto &option: list_option->options) {
|
|
||||||
// if(!is_first) std::cout << '|';
|
|
||||||
// is_first = false;
|
|
||||||
// std::cout << option;
|
|
||||||
// }
|
|
||||||
// std::cout << "}";
|
|
||||||
// }
|
|
||||||
// std::cout << std::endl;
|
|
||||||
// }
|
|
||||||
// std::cout << std::endl;
|
|
||||||
// }
|
|
||||||
|
|
||||||
const auto targets = Machine::TargetsByMachineName(false);
|
const auto targets = Machine::TargetsByMachineName(false);
|
||||||
for(const auto &target: targets) {
|
const auto runtime_options = Machine::AllOptionsByMachineName();
|
||||||
const auto reflectable = dynamic_cast<Reflection::Struct *>(target.second.get());
|
const auto machine_names = Machine::AllMachines(false, true);
|
||||||
if(!reflectable) continue;
|
for(const auto &machine: machine_names) {
|
||||||
const auto all_keys = reflectable->all_keys();
|
const auto target = targets.find(machine);
|
||||||
if(all_keys.empty()) continue;
|
const auto options = runtime_options.find(machine);
|
||||||
|
|
||||||
std::cout << target.first << ":" << std::endl;
|
const auto target_reflectable = dynamic_cast<Reflection::Struct *>(target != targets.end() ? target->second.get() : nullptr);
|
||||||
for(const auto &option: reflectable->all_keys()) {
|
const auto options_reflectable = dynamic_cast<Reflection::Struct *>(options != runtime_options.end() ? options->second.get() : nullptr);
|
||||||
|
|
||||||
|
// Don't print a section for this machine if it has no construction and no runtime options objects.
|
||||||
|
if(!target_reflectable && !options_reflectable) continue;
|
||||||
|
|
||||||
|
const auto target_keys = target_reflectable ? target_reflectable->all_keys() : std::vector<std::string>();
|
||||||
|
const auto options_keys = options_reflectable ? options_reflectable->all_keys() : std::vector<std::string>();
|
||||||
|
|
||||||
|
// Don't print a section for this machine if it doesn't actually have any options.
|
||||||
|
if(target_keys.empty() && options_keys.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << machine << ":" << std::endl;
|
||||||
|
|
||||||
|
// Join the two lists of properties.
|
||||||
|
std::vector<std::string> all_options = options_keys;
|
||||||
|
all_options.insert(all_options.end(), target_keys.begin(), target_keys.end());
|
||||||
|
|
||||||
|
for(const auto &option: all_options) {
|
||||||
std::cout << '\t' << "--" << option;
|
std::cout << '\t' << "--" << option;
|
||||||
const auto type = reflectable->type_of(option);
|
|
||||||
|
bool is_construction_option = true;
|
||||||
|
auto type = target_reflectable->type_of(option);
|
||||||
|
if(!type) {
|
||||||
|
is_construction_option = false;
|
||||||
|
type = options_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()) {
|
||||||
@ -544,7 +547,9 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: if not a registered enum... then assume it was a Boolean?
|
// TODO: if not a registered enum... then assume it was a Boolean?
|
||||||
std::cout << "\t*" << std::endl;
|
|
||||||
|
if(is_construction_option) std::cout << "\t*";
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
@ -93,6 +93,10 @@ void CRT::set_display_type(Outputs::Display::DisplayType display_type) {
|
|||||||
scan_target_->set_modals(scan_target_modals_);
|
scan_target_->set_modals(scan_target_modals_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Outputs::Display::DisplayType CRT::get_display_type() {
|
||||||
|
return scan_target_modals_.display_type;
|
||||||
|
}
|
||||||
|
|
||||||
void CRT::set_phase_linked_luminance_offset(float offset) {
|
void CRT::set_phase_linked_luminance_offset(float offset) {
|
||||||
scan_target_modals_.input_data_tweaks.phase_linked_luminance_offset = offset;
|
scan_target_modals_.input_data_tweaks.phase_linked_luminance_offset = offset;
|
||||||
scan_target_->set_modals(scan_target_modals_);
|
scan_target_->set_modals(scan_target_modals_);
|
||||||
|
@ -298,6 +298,9 @@ class CRT {
|
|||||||
/*! Sets the display type that will be nominated to the scan target. */
|
/*! Sets the display type that will be nominated to the scan target. */
|
||||||
void set_display_type(Outputs::Display::DisplayType);
|
void set_display_type(Outputs::Display::DisplayType);
|
||||||
|
|
||||||
|
/*! Gets the last display type provided to set_display_type. */
|
||||||
|
Outputs::Display::DisplayType get_display_type();
|
||||||
|
|
||||||
/*! Sets the offset to apply to phase when using the PhaseLinkedLuminance8 input data type. */
|
/*! Sets the offset to apply to phase when using the PhaseLinkedLuminance8 input data type. */
|
||||||
void set_phase_linked_luminance_offset(float);
|
void set_phase_linked_luminance_offset(float);
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ namespace Reflection {
|
|||||||
#define EnumDeclaration(Name) #Name, __declaration##Name
|
#define EnumDeclaration(Name) #Name, __declaration##Name
|
||||||
|
|
||||||
#define AnnounceEnum(Name) ::Reflection::Enum::declare<Name>(EnumDeclaration(Name))
|
#define AnnounceEnum(Name) ::Reflection::Enum::declare<Name>(EnumDeclaration(Name))
|
||||||
|
#define AnnounceEnumNS(Namespace, Name) ::Reflection::Enum::declare<Namespace::Name>(#Name, Namespace::__declaration##Name)
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
This provides a very slight version of enum reflection; you can introspect only:
|
This provides a very slight version of enum reflection; you can introspect only:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user