diff --git a/Machines/Enterprise/Enterprise.cpp b/Machines/Enterprise/Enterprise.cpp index e1cc9b86c..97dc6ba38 100644 --- a/Machines/Enterprise/Enterprise.cpp +++ b/Machines/Enterprise/Enterprise.cpp @@ -64,6 +64,7 @@ namespace Enterprise { template class ConcreteMachine: public Activity::Source, + public Configurable::Device, public CPU::Z80::BusHandler, public Machine, public MachineTypes::AudioProducer, @@ -591,6 +592,14 @@ template class ConcreteMachine: return nick_.last_valid()->get_scaled_scan_status(); } + void set_display_type(Outputs::Display::DisplayType display_type) final { + nick_.last_valid()->set_display_type(display_type); + } + + Outputs::Display::DisplayType get_display_type() const final { + return nick_.last_valid()->get_display_type(); + } + // MARK: - AudioProducer Outputs::Speaker::Speaker *get_speaker() final { @@ -692,6 +701,18 @@ template class ConcreteMachine: exdos_.set_activity_observer(observer); } } + + // MARK: - Configuration options. + std::unique_ptr get_options() final { + auto options = std::make_unique(Configurable::OptionsType::UserFriendly); + options->output = get_video_signal_configurable(); + return options; + } + + void set_options(const std::unique_ptr &str) final { + const auto options = dynamic_cast(str.get()); + set_video_signal_configurable(options->output); + } }; } diff --git a/Machines/Enterprise/Enterprise.hpp b/Machines/Enterprise/Enterprise.hpp index 3a42a70f5..4970a66f1 100644 --- a/Machines/Enterprise/Enterprise.hpp +++ b/Machines/Enterprise/Enterprise.hpp @@ -10,16 +10,36 @@ #define Enterprise_hpp #include "../../Analyser/Static/StaticAnalyser.hpp" +#include "../../Configurable/Configurable.hpp" +#include "../../Configurable/StandardOptions.hpp" #include "../ROMMachine.hpp" namespace Enterprise { +/*! + @abstract Represents an Elan Enterprise. + + @discussion An instance of Enterprise::Machine represents the current state of an + Elan Enterprise. +*/ class Machine { public: virtual ~Machine(); static Machine *Enterprise(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher); + /// Defines the runtime options available for an Enterprise. + class Options: public Reflection::StructImpl, public Configurable::DisplayOption { + friend Configurable::DisplayOption; + public: + Options(Configurable::OptionsType type) : + Configurable::DisplayOption(type == Configurable::OptionsType::UserFriendly ? Configurable::Display::RGB : Configurable::Display::CompositeColour) { + if(needs_declare()) { + declare_display_option(); + limit_enum(&output, Configurable::Display::RGB, Configurable::Display::CompositeColour, Configurable::Display::CompositeMonochrome, -1); + } + } + }; }; }; diff --git a/Machines/Enterprise/Nick.cpp b/Machines/Enterprise/Nick.cpp index 02628ead0..cb07a345a 100644 --- a/Machines/Enterprise/Nick.cpp +++ b/Machines/Enterprise/Nick.cpp @@ -51,7 +51,7 @@ Nick::Nick(const uint8_t *ram) : ram_(ram) { // Just use RGB for now. - crt_.set_display_type(Outputs::Display::DisplayType::RGB); + set_display_type(Outputs::Display::DisplayType::RGB); // Crop to the centre 90% of the display. crt_.set_visible_area(Outputs::Display::Rect(0.05f, 0.05f, 0.9f, 0.9f)); @@ -287,7 +287,7 @@ void Nick::run_for(Cycles duration) { // the start of window 6 to the end of window 10. // // The first 8 palette entries also need to be fetched here. - while(window < 10 && window < end_window) { + while(window < first_pixel_window_ && window < end_window) { if(window == 6) { set_output_type(OutputType::ColourBurst); } @@ -303,8 +303,8 @@ void Nick::run_for(Cycles duration) { add_window(1); } - if(window >= 10) { - if(window == 10) { + if(window >= first_pixel_window_) { + if(window == first_pixel_window_) { set_output_type(is_sync_or_pixels_ ? OutputType::Pixels : OutputType::Border); } @@ -484,6 +484,15 @@ Outputs::Display::ScanStatus Nick::get_scaled_scan_status() const { return crt_.get_scaled_scan_status(); } +void Nick::set_display_type(Outputs::Display::DisplayType display_type) { + first_pixel_window_ = display_type == Outputs::Display::DisplayType::RGB ? 8 : 10; + crt_.set_display_type(display_type); +} + +Outputs::Display::DisplayType Nick::get_display_type() const { + return crt_.get_display_type(); +} + // MARK: - Specific pixel outputters. #define output1bpp(x) \ diff --git a/Machines/Enterprise/Nick.hpp b/Machines/Enterprise/Nick.hpp index b9ce44439..d19760859 100644 --- a/Machines/Enterprise/Nick.hpp +++ b/Machines/Enterprise/Nick.hpp @@ -28,6 +28,7 @@ class Nick { void set_scan_target(Outputs::Display::ScanTarget *scan_target); Outputs::Display::ScanStatus get_scaled_scan_status() const; + /// @returns The amount of time until the next potential change in interrupt output. Cycles get_next_sequence_point() const; /*! @@ -38,6 +39,12 @@ class Nick { return interrupt_line_; } + /// Sets the type of output. + void set_display_type(Outputs::Display::DisplayType); + + /// Gets the type of output. + Outputs::Display::DisplayType get_display_type() const; + private: Outputs::CRT::CRT crt_; const uint8_t *const ram_; @@ -96,6 +103,10 @@ class Nick { // Current palette. uint16_t palette_[16]{}; + // The first column with pixels on it; will be either 8 or 10 depending + // on whether the colour burst is meaningful to the current display type. + int first_pixel_window_ = 10; + // Specific outputters. template void output_pixel(uint16_t *target, int columns) const; template void output_character(uint16_t *target, int columns) const; diff --git a/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm b/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm index 805fff5d1..e50217f91 100644 --- a/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm +++ b/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm @@ -316,6 +316,7 @@ static Analyser::Static::ZX8081::Target::MemoryModel ZX8081MemoryModelFromSize(K case Analyser::Machine::AtariST: return @"CompositeOptions"; case Analyser::Machine::ColecoVision: return @"CompositeOptions"; case Analyser::Machine::Electron: return @"QuickLoadCompositeOptions"; + case Analyser::Machine::Enterprise: return @"CompositeOptions"; case Analyser::Machine::Macintosh: return @"MacintoshOptions"; case Analyser::Machine::MasterSystem: return @"CompositeOptions"; case Analyser::Machine::MSX: return @"QuickLoadCompositeOptions";