mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
Merge pull request #292 from TomHarte/Help
Introduces command-line help and reduces code duplicity in those options.
This commit is contained in:
commit
723c113186
76
Configurable/StandardOptions.cpp
Normal file
76
Configurable/StandardOptions.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// StandardOptions.cpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 20/11/2017.
|
||||||
|
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "StandardOptions.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Appends a Boolean selection of @c selection for option @c name to @c selection_set.
|
||||||
|
*/
|
||||||
|
void append_bool(Configurable::SelectionSet &selection_set, const std::string &name, bool selection) {
|
||||||
|
selection_set[name] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(selection));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Enquires for a Boolean selection for option @c name from @c selections_by_option, storing it to @c result if found.
|
||||||
|
*/
|
||||||
|
bool get_bool(const Configurable::SelectionSet &selections_by_option, const std::string &name, bool &result) {
|
||||||
|
auto quickload = Configurable::selection<Configurable::BooleanSelection>(selections_by_option, "quickload");
|
||||||
|
if(!quickload) return false;
|
||||||
|
result = quickload->value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Standard option list builder
|
||||||
|
std::vector<std::unique_ptr<Configurable::Option>> Configurable::standard_options(Configurable::StandardOptions mask) {
|
||||||
|
std::vector<std::unique_ptr<Configurable::Option>> options;
|
||||||
|
if(mask & QuickLoadTape) options.emplace_back(new Configurable::BooleanOption("Load Tapes Quickly", "quickload"));
|
||||||
|
if(mask & DisplayRGBComposite) options.emplace_back(new Configurable::ListOption("Display", "display", {"composite", "rgb"}));
|
||||||
|
if(mask & AutomaticTapeMotorControl) options.emplace_back(new Configurable::BooleanOption("Automatic Tape Motor Control", "autotapemotor"));
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Selection appenders
|
||||||
|
void Configurable::append_quick_load_tape_selection(Configurable::SelectionSet &selection_set, bool selection) {
|
||||||
|
append_bool(selection_set, "quickload", selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Configurable::append_automatic_tape_motor_control_selection(SelectionSet &selection_set, bool selection) {
|
||||||
|
append_bool(selection_set, "autotapemotor", selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Configurable::append_display_selection(Configurable::SelectionSet &selection_set, Display selection) {
|
||||||
|
selection_set["display"] = std::unique_ptr<Configurable::Selection>(new Configurable::ListSelection((selection == Display::RGB) ? "rgb" : "composite"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Selection parsers
|
||||||
|
bool Configurable::get_quick_load_tape(const Configurable::SelectionSet &selections_by_option, bool &result) {
|
||||||
|
return get_bool(selections_by_option, "quickload", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Configurable::get_automatic_tape_motor_control_selection(const SelectionSet &selections_by_option, bool &result) {
|
||||||
|
return get_bool(selections_by_option, "autotapemotor", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Configurable::get_display(const Configurable::SelectionSet &selections_by_option, Configurable::Display &result) {
|
||||||
|
auto display = Configurable::selection<Configurable::ListSelection>(selections_by_option, "display");
|
||||||
|
if(display) {
|
||||||
|
if(display->value == "rgb") {
|
||||||
|
result = Configurable::Display::RGB;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(display->value == "composite") {
|
||||||
|
result = Configurable::Display::Composite;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
76
Configurable/StandardOptions.hpp
Normal file
76
Configurable/StandardOptions.hpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// StandardOptions.hpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 20/11/2017.
|
||||||
|
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef StandardOptions_hpp
|
||||||
|
#define StandardOptions_hpp
|
||||||
|
|
||||||
|
#include "Configurable.hpp"
|
||||||
|
|
||||||
|
namespace Configurable {
|
||||||
|
|
||||||
|
enum StandardOptions {
|
||||||
|
DisplayRGBComposite = (1 << 0),
|
||||||
|
QuickLoadTape = (1 << 1),
|
||||||
|
AutomaticTapeMotorControl = (1 << 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Display {
|
||||||
|
RGB,
|
||||||
|
Composite
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@returns An option list comprised of the standard names for all the options indicated by @c mask.
|
||||||
|
*/
|
||||||
|
std::vector<std::unique_ptr<Option>> standard_options(StandardOptions mask);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Appends to @c selection_set a selection of @c selection for QuickLoadTape.
|
||||||
|
*/
|
||||||
|
void append_quick_load_tape_selection(SelectionSet &selection_set, bool selection);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Appends to @c selection_set a selection of @c selection for AutomaticTapeMotorControl.
|
||||||
|
*/
|
||||||
|
void append_automatic_tape_motor_control_selection(SelectionSet &selection_set, bool selection);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Appends to @c selection_set a selection of @c selection for DisplayRGBComposite.
|
||||||
|
*/
|
||||||
|
void append_display_selection(SelectionSet &selection_set, Display selection);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Attempts to discern a QuickLoadTape selection from @c selections_by_option.
|
||||||
|
|
||||||
|
@param selections_by_option The user selections.
|
||||||
|
@param result The location to which the selection will be stored if found.
|
||||||
|
@returns @c true if a selection is found; @c false otherwise.
|
||||||
|
*/
|
||||||
|
bool get_quick_load_tape(const SelectionSet &selections_by_option, bool &result);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Attempts to discern an AutomaticTapeMotorControl selection from @c selections_by_option.
|
||||||
|
|
||||||
|
@param selections_by_option The user selections.
|
||||||
|
@param result The location to which the selection will be stored if found.
|
||||||
|
@returns @c true if a selection is found; @c false otherwise.
|
||||||
|
*/
|
||||||
|
bool get_automatic_tape_motor_control_selection(const SelectionSet &selections_by_option, bool &result);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Attempts to discern a display RGB/composite selection from @c selections_by_option.
|
||||||
|
|
||||||
|
@param selections_by_option The user selections.
|
||||||
|
@param result The location to which the selection will be stored if found.
|
||||||
|
@returns @c true if a selection is found; @c false otherwise.
|
||||||
|
*/
|
||||||
|
bool get_display(const SelectionSet &selections_by_option, Display &result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* StandardOptions_hpp */
|
@ -24,11 +24,17 @@
|
|||||||
#include "../../../Storage/Tape/Tape.hpp"
|
#include "../../../Storage/Tape/Tape.hpp"
|
||||||
#include "../../../Storage/Disk/Disk.hpp"
|
#include "../../../Storage/Disk/Disk.hpp"
|
||||||
|
|
||||||
|
#include "../../../Configurable/StandardOptions.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Commodore {
|
namespace Commodore {
|
||||||
namespace Vic20 {
|
namespace Vic20 {
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<Configurable::Option>> get_options() {
|
||||||
|
return Configurable::standard_options(Configurable::QuickLoadTape);
|
||||||
|
}
|
||||||
|
|
||||||
enum JoystickInput {
|
enum JoystickInput {
|
||||||
Up = 0x04,
|
Up = 0x04,
|
||||||
Down = 0x08,
|
Down = 0x08,
|
||||||
@ -638,25 +644,25 @@ class ConcreteMachine:
|
|||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> options;
|
return Commodore::Vic20::get_options();
|
||||||
options.emplace_back(new Configurable::BooleanOption("Load Tapes Quickly", "quickload"));
|
|
||||||
return options;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_selections(const Configurable::SelectionSet &selections_by_option) override {
|
void set_selections(const Configurable::SelectionSet &selections_by_option) override {
|
||||||
auto quickload = Configurable::selection<Configurable::BooleanSelection>(selections_by_option, "quickload");
|
bool quickload;
|
||||||
if(quickload) set_use_fast_tape_hack(quickload->value);
|
if(Configurable::get_quick_load_tape(selections_by_option, quickload)) {
|
||||||
|
set_use_fast_tape_hack(quickload);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Configurable::SelectionSet get_accurate_selections() override {
|
Configurable::SelectionSet get_accurate_selections() override {
|
||||||
Configurable::SelectionSet selection_set;
|
Configurable::SelectionSet selection_set;
|
||||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(false));
|
Configurable::append_quick_load_tape_selection(selection_set, false);
|
||||||
return selection_set;
|
return selection_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
Configurable::SelectionSet get_user_friendly_selections() override {
|
Configurable::SelectionSet get_user_friendly_selections() override {
|
||||||
Configurable::SelectionSet selection_set;
|
Configurable::SelectionSet selection_set;
|
||||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(true));
|
Configurable::append_quick_load_tape_selection(selection_set, true);
|
||||||
return selection_set;
|
return selection_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,9 @@ enum Region {
|
|||||||
Swedish
|
Swedish
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @returns The options available for a Vic-20.
|
||||||
|
std::vector<std::unique_ptr<Configurable::Option>> get_options();
|
||||||
|
|
||||||
class Machine:
|
class Machine:
|
||||||
public CRTMachine::Machine,
|
public CRTMachine::Machine,
|
||||||
public ConfigurationTarget::Machine,
|
public ConfigurationTarget::Machine,
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "Electron.hpp"
|
#include "Electron.hpp"
|
||||||
|
|
||||||
|
#include "../../Configurable/StandardOptions.hpp"
|
||||||
#include "../../Processors/6502/6502.hpp"
|
#include "../../Processors/6502/6502.hpp"
|
||||||
#include "../../Storage/Tape/Tape.hpp"
|
#include "../../Storage/Tape/Tape.hpp"
|
||||||
#include "../../ClockReceiver/ClockReceiver.hpp"
|
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||||
@ -24,6 +25,12 @@
|
|||||||
|
|
||||||
namespace Electron {
|
namespace Electron {
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<Configurable::Option>> get_options() {
|
||||||
|
return Configurable::standard_options(
|
||||||
|
static_cast<Configurable::StandardOptions>(Configurable::DisplayRGBComposite | Configurable::QuickLoadTape)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
class ConcreteMachine:
|
class ConcreteMachine:
|
||||||
public Machine,
|
public Machine,
|
||||||
public CPU::MOS6502::BusHandler,
|
public CPU::MOS6502::BusHandler,
|
||||||
@ -418,31 +425,32 @@ class ConcreteMachine:
|
|||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> options;
|
return Electron::get_options();
|
||||||
options.emplace_back(new Configurable::BooleanOption("Load Tapes Quickly", "quickload"));
|
|
||||||
options.emplace_back(new Configurable::ListOption("Display", "display", {"composite", "rgb"}));
|
|
||||||
return options;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_selections(const Configurable::SelectionSet &selections_by_option) override {
|
void set_selections(const Configurable::SelectionSet &selections_by_option) override {
|
||||||
auto quickload = Configurable::selection<Configurable::BooleanSelection>(selections_by_option, "quickload");
|
bool quickload;
|
||||||
if(quickload) set_use_fast_tape_hack(quickload->value);
|
if(Configurable::get_quick_load_tape(selections_by_option, quickload)) {
|
||||||
|
set_use_fast_tape_hack(quickload);
|
||||||
|
}
|
||||||
|
|
||||||
auto display = Configurable::selection<Configurable::ListSelection>(selections_by_option, "display");
|
Configurable::Display display;
|
||||||
if(display) get_crt()->set_output_device((display->value == "rgb") ? Outputs::CRT::OutputDevice::Monitor : Outputs::CRT::OutputDevice::Television);
|
if(Configurable::get_display(selections_by_option, display)) {
|
||||||
|
get_crt()->set_output_device((display == Configurable::Display::RGB) ? Outputs::CRT::OutputDevice::Monitor : Outputs::CRT::OutputDevice::Television);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Configurable::SelectionSet get_accurate_selections() override {
|
Configurable::SelectionSet get_accurate_selections() override {
|
||||||
Configurable::SelectionSet selection_set;
|
Configurable::SelectionSet selection_set;
|
||||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(false));
|
Configurable::append_quick_load_tape_selection(selection_set, false);
|
||||||
selection_set["display"] = std::unique_ptr<Configurable::Selection>(new Configurable::ListSelection("composite"));
|
Configurable::append_display_selection(selection_set, Configurable::Display::Composite);
|
||||||
return selection_set;
|
return selection_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
Configurable::SelectionSet get_user_friendly_selections() override {
|
Configurable::SelectionSet get_user_friendly_selections() override {
|
||||||
Configurable::SelectionSet selection_set;
|
Configurable::SelectionSet selection_set;
|
||||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(true));
|
Configurable::append_quick_load_tape_selection(selection_set, true);
|
||||||
selection_set["display"] = std::unique_ptr<Configurable::Selection>(new Configurable::ListSelection("rgb"));
|
Configurable::append_display_selection(selection_set, Configurable::Display::RGB);
|
||||||
return selection_set;
|
return selection_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,9 @@ enum ROMSlot: uint8_t {
|
|||||||
ROMSlotADFS1, ROMSlotADFS2
|
ROMSlotADFS1, ROMSlotADFS2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @returns The options available for an Electron.
|
||||||
|
std::vector<std::unique_ptr<Configurable::Option>> get_options();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@abstract Represents an Acorn Electron.
|
@abstract Represents an Acorn Electron.
|
||||||
|
|
||||||
|
@ -23,11 +23,18 @@
|
|||||||
#include "../../Storage/Tape/Parsers/Oric.hpp"
|
#include "../../Storage/Tape/Parsers/Oric.hpp"
|
||||||
|
|
||||||
#include "../../ClockReceiver/ForceInline.hpp"
|
#include "../../ClockReceiver/ForceInline.hpp"
|
||||||
|
#include "../../Configurable/StandardOptions.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Oric {
|
namespace Oric {
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<Configurable::Option>> get_options() {
|
||||||
|
return Configurable::standard_options(
|
||||||
|
static_cast<Configurable::StandardOptions>(Configurable::DisplayRGBComposite | Configurable::QuickLoadTape)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Models the Oric's keyboard: eight key rows, containing a bitfield of keys set.
|
Models the Oric's keyboard: eight key rows, containing a bitfield of keys set.
|
||||||
|
|
||||||
@ -429,31 +436,32 @@ class ConcreteMachine:
|
|||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> options;
|
return Oric::get_options();
|
||||||
options.emplace_back(new Configurable::BooleanOption("Load Tapes Quickly", "quickload"));
|
|
||||||
options.emplace_back(new Configurable::ListOption("Display", "display", {"composite", "rgb"}));
|
|
||||||
return options;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_selections(const Configurable::SelectionSet &selections_by_option) override {
|
void set_selections(const Configurable::SelectionSet &selections_by_option) override {
|
||||||
auto quickload = Configurable::selection<Configurable::BooleanSelection>(selections_by_option, "quickload");
|
bool quickload;
|
||||||
if(quickload) set_use_fast_tape_hack(quickload->value);
|
if(Configurable::get_quick_load_tape(selections_by_option, quickload)) {
|
||||||
|
set_use_fast_tape_hack(quickload);
|
||||||
|
}
|
||||||
|
|
||||||
auto display = Configurable::selection<Configurable::ListSelection>(selections_by_option, "display");
|
Configurable::Display display;
|
||||||
if(display) get_crt()->set_output_device((display->value == "rgb") ? Outputs::CRT::OutputDevice::Monitor : Outputs::CRT::OutputDevice::Television);
|
if(Configurable::get_display(selections_by_option, display)) {
|
||||||
|
get_crt()->set_output_device((display == Configurable::Display::RGB) ? Outputs::CRT::OutputDevice::Monitor : Outputs::CRT::OutputDevice::Television);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Configurable::SelectionSet get_accurate_selections() override {
|
Configurable::SelectionSet get_accurate_selections() override {
|
||||||
Configurable::SelectionSet selection_set;
|
Configurable::SelectionSet selection_set;
|
||||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(false));
|
Configurable::append_quick_load_tape_selection(selection_set, false);
|
||||||
selection_set["display"] = std::unique_ptr<Configurable::Selection>(new Configurable::ListSelection("composite"));
|
Configurable::append_display_selection(selection_set, Configurable::Display::Composite);
|
||||||
return selection_set;
|
return selection_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
Configurable::SelectionSet get_user_friendly_selections() override {
|
Configurable::SelectionSet get_user_friendly_selections() override {
|
||||||
Configurable::SelectionSet selection_set;
|
Configurable::SelectionSet selection_set;
|
||||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(true));
|
Configurable::append_quick_load_tape_selection(selection_set, true);
|
||||||
selection_set["display"] = std::unique_ptr<Configurable::Selection>(new Configurable::ListSelection("rgb"));
|
Configurable::append_display_selection(selection_set, Configurable::Display::RGB);
|
||||||
return selection_set;
|
return selection_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@ enum ROM {
|
|||||||
BASIC10 = 0, BASIC11, Microdisc, Colour
|
BASIC10 = 0, BASIC11, Microdisc, Colour
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @returns The options available for an Oric.
|
||||||
|
std::vector<std::unique_ptr<Configurable::Option>> get_options();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Models an Oric 1/Atmos with or without a Microdisc.
|
Models an Oric 1/Atmos with or without a Microdisc.
|
||||||
*/
|
*/
|
||||||
|
@ -63,8 +63,8 @@ template<typename T> class TypedDynamicMachine: public ::Machine::DynamicMachine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Machine::NameForTarget(const StaticAnalyser::Target &target) {
|
std::string Machine::ShortNameForTargetMachine(const StaticAnalyser::Target::Machine machine) {
|
||||||
switch(target.machine) {
|
switch(machine) {
|
||||||
case StaticAnalyser::Target::AmstradCPC: return "AmstradCPC";
|
case StaticAnalyser::Target::AmstradCPC: return "AmstradCPC";
|
||||||
case StaticAnalyser::Target::Atari2600: return "Atari2600";
|
case StaticAnalyser::Target::Atari2600: return "Atari2600";
|
||||||
case StaticAnalyser::Target::Electron: return "Electron";
|
case StaticAnalyser::Target::Electron: return "Electron";
|
||||||
@ -75,3 +75,27 @@ std::string Machine::NameForTarget(const StaticAnalyser::Target &target) {
|
|||||||
default: return "";
|
default: return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Machine::LongNameForTargetMachine(StaticAnalyser::Target::Machine machine) {
|
||||||
|
switch(machine) {
|
||||||
|
case StaticAnalyser::Target::AmstradCPC: return "Amstrad CPC";
|
||||||
|
case StaticAnalyser::Target::Atari2600: return "Atari 2600";
|
||||||
|
case StaticAnalyser::Target::Electron: return "Acorn Electron";
|
||||||
|
case StaticAnalyser::Target::Oric: return "Oric";
|
||||||
|
case StaticAnalyser::Target::Vic20: return "Vic 20";
|
||||||
|
case StaticAnalyser::Target::ZX8081: return "ZX80/81";
|
||||||
|
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, std::vector<std::unique_ptr<Configurable::Option>>> Machine::AllOptionsByMachineName() {
|
||||||
|
std::map<std::string, std::vector<std::unique_ptr<Configurable::Option>>> options;
|
||||||
|
|
||||||
|
options.emplace(std::make_pair(LongNameForTargetMachine(StaticAnalyser::Target::Electron), Electron::get_options()));
|
||||||
|
options.emplace(std::make_pair(LongNameForTargetMachine(StaticAnalyser::Target::Oric), Oric::get_options()));
|
||||||
|
options.emplace(std::make_pair(LongNameForTargetMachine(StaticAnalyser::Target::Vic20), Commodore::Vic20::get_options()));
|
||||||
|
options.emplace(std::make_pair(LongNameForTargetMachine(StaticAnalyser::Target::ZX8081), ZX8081::get_options()));
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "../JoystickMachine.hpp"
|
#include "../JoystickMachine.hpp"
|
||||||
#include "../KeyboardMachine.hpp"
|
#include "../KeyboardMachine.hpp"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace Machine {
|
namespace Machine {
|
||||||
@ -45,7 +46,19 @@ DynamicMachine *MachineForTarget(const StaticAnalyser::Target &target);
|
|||||||
which is guaranteed not to have any spaces or other potentially
|
which is guaranteed not to have any spaces or other potentially
|
||||||
filesystem-bothering contents.
|
filesystem-bothering contents.
|
||||||
*/
|
*/
|
||||||
std::string NameForTarget(const StaticAnalyser::Target &target);
|
std::string ShortNameForTargetMachine(const StaticAnalyser::Target::Machine target);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns a long string name for the machine identified by the target,
|
||||||
|
usable for presentation to a human.
|
||||||
|
*/
|
||||||
|
std::string LongNameForTargetMachine(const StaticAnalyser::Target::Machine target);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns a map from 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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "../../Storage/Tape/Parsers/ZX8081.hpp"
|
#include "../../Storage/Tape/Parsers/ZX8081.hpp"
|
||||||
|
|
||||||
#include "../../ClockReceiver/ForceInline.hpp"
|
#include "../../ClockReceiver/ForceInline.hpp"
|
||||||
|
#include "../../Configurable/StandardOptions.hpp"
|
||||||
|
|
||||||
#include "../Utility/MemoryFuzzer.hpp"
|
#include "../Utility/MemoryFuzzer.hpp"
|
||||||
#include "../Utility/Typer.hpp"
|
#include "../Utility/Typer.hpp"
|
||||||
@ -29,6 +30,12 @@ namespace {
|
|||||||
|
|
||||||
namespace ZX8081 {
|
namespace ZX8081 {
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<Configurable::Option>> get_options() {
|
||||||
|
return Configurable::standard_options(
|
||||||
|
static_cast<Configurable::StandardOptions>(Configurable::AutomaticTapeMotorControl | Configurable::QuickLoadTape)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
template<bool is_zx81> class ConcreteMachine:
|
template<bool is_zx81> class ConcreteMachine:
|
||||||
public Utility::TypeRecipient,
|
public Utility::TypeRecipient,
|
||||||
public CPU::Z80::BusHandler,
|
public CPU::Z80::BusHandler,
|
||||||
@ -345,31 +352,32 @@ template<bool is_zx81> class ConcreteMachine:
|
|||||||
|
|
||||||
// MARK: - Configuration options.
|
// MARK: - Configuration options.
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> options;
|
return ZX8081::get_options();
|
||||||
options.emplace_back(new Configurable::BooleanOption("Load Tapes Quickly", "quickload"));
|
|
||||||
options.emplace_back(new Configurable::BooleanOption("Automatic Tape Motor Control", "autotapemotor"));
|
|
||||||
return options;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_selections(const Configurable::SelectionSet &selections_by_option) override {
|
void set_selections(const Configurable::SelectionSet &selections_by_option) override {
|
||||||
auto quickload = Configurable::selection<Configurable::BooleanSelection>(selections_by_option, "quickload");
|
bool quickload;
|
||||||
if(quickload) set_use_fast_tape_hack(quickload->value);
|
if(Configurable::get_quick_load_tape(selections_by_option, quickload)) {
|
||||||
|
set_use_fast_tape_hack(quickload);
|
||||||
|
}
|
||||||
|
|
||||||
auto autotapemotor = Configurable::selection<Configurable::BooleanSelection>(selections_by_option, "autotapemotor");
|
bool autotapemotor;
|
||||||
if(autotapemotor) set_use_automatic_tape_motor_control(autotapemotor->value);
|
if(Configurable::get_automatic_tape_motor_control_selection(selections_by_option, autotapemotor)) {
|
||||||
|
set_use_automatic_tape_motor_control(autotapemotor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Configurable::SelectionSet get_accurate_selections() override {
|
Configurable::SelectionSet get_accurate_selections() override {
|
||||||
Configurable::SelectionSet selection_set;
|
Configurable::SelectionSet selection_set;
|
||||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(false));
|
Configurable::append_quick_load_tape_selection(selection_set, false);
|
||||||
selection_set["autotapemotor"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(false));
|
Configurable::append_automatic_tape_motor_control_selection(selection_set, false);
|
||||||
return selection_set;
|
return selection_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
Configurable::SelectionSet get_user_friendly_selections() override {
|
Configurable::SelectionSet get_user_friendly_selections() override {
|
||||||
Configurable::SelectionSet selection_set;
|
Configurable::SelectionSet selection_set;
|
||||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(true));
|
Configurable::append_quick_load_tape_selection(selection_set, true);
|
||||||
selection_set["autotapemotor"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(true));
|
Configurable::append_automatic_tape_motor_control_selection(selection_set, true);
|
||||||
return selection_set;
|
return selection_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@ enum ROMType: uint8_t {
|
|||||||
ZX80 = 0, ZX81
|
ZX80 = 0, ZX81
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @returns The options available for a ZX80 or ZX81.
|
||||||
|
std::vector<std::unique_ptr<Configurable::Option>> get_options();
|
||||||
|
|
||||||
class Machine:
|
class Machine:
|
||||||
public CRTMachine::Machine,
|
public CRTMachine::Machine,
|
||||||
public ConfigurationTarget::Machine,
|
public ConfigurationTarget::Machine,
|
||||||
|
@ -578,6 +578,8 @@
|
|||||||
4BFCA1291ECBE7A700AC40C1 /* zexall.com in Resources */ = {isa = PBXBuildFile; fileRef = 4BFCA1281ECBE7A700AC40C1 /* zexall.com */; };
|
4BFCA1291ECBE7A700AC40C1 /* zexall.com in Resources */ = {isa = PBXBuildFile; fileRef = 4BFCA1281ECBE7A700AC40C1 /* zexall.com */; };
|
||||||
4BFCA12B1ECBE7C400AC40C1 /* ZexallTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA12A1ECBE7C400AC40C1 /* ZexallTests.swift */; };
|
4BFCA12B1ECBE7C400AC40C1 /* ZexallTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA12A1ECBE7C400AC40C1 /* ZexallTests.swift */; };
|
||||||
4BFDD78C1F7F2DB4008579B9 /* ImplicitSectors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFDD78B1F7F2DB4008579B9 /* ImplicitSectors.cpp */; };
|
4BFDD78C1F7F2DB4008579B9 /* ImplicitSectors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFDD78B1F7F2DB4008579B9 /* ImplicitSectors.cpp */; };
|
||||||
|
4BFE7B871FC39BF100160B38 /* StandardOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFE7B851FC39BF100160B38 /* StandardOptions.cpp */; };
|
||||||
|
4BFE7B881FC39D8900160B38 /* StandardOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFE7B851FC39BF100160B38 /* StandardOptions.cpp */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -1268,6 +1270,8 @@
|
|||||||
4BFCA12A1ECBE7C400AC40C1 /* ZexallTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZexallTests.swift; sourceTree = "<group>"; };
|
4BFCA12A1ECBE7C400AC40C1 /* ZexallTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZexallTests.swift; sourceTree = "<group>"; };
|
||||||
4BFDD78A1F7F2DB4008579B9 /* ImplicitSectors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ImplicitSectors.hpp; sourceTree = "<group>"; };
|
4BFDD78A1F7F2DB4008579B9 /* ImplicitSectors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ImplicitSectors.hpp; sourceTree = "<group>"; };
|
||||||
4BFDD78B1F7F2DB4008579B9 /* ImplicitSectors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImplicitSectors.cpp; sourceTree = "<group>"; };
|
4BFDD78B1F7F2DB4008579B9 /* ImplicitSectors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImplicitSectors.cpp; sourceTree = "<group>"; };
|
||||||
|
4BFE7B851FC39BF100160B38 /* StandardOptions.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StandardOptions.cpp; sourceTree = "<group>"; };
|
||||||
|
4BFE7B861FC39BF100160B38 /* StandardOptions.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = StandardOptions.hpp; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -1518,6 +1522,8 @@
|
|||||||
children = (
|
children = (
|
||||||
4B31B88F1FBFBCD800C140D5 /* Configurable.hpp */,
|
4B31B88F1FBFBCD800C140D5 /* Configurable.hpp */,
|
||||||
4B0783591FC11D10001D12BB /* Configurable.cpp */,
|
4B0783591FC11D10001D12BB /* Configurable.cpp */,
|
||||||
|
4BFE7B851FC39BF100160B38 /* StandardOptions.cpp */,
|
||||||
|
4BFE7B861FC39BF100160B38 /* StandardOptions.hpp */,
|
||||||
);
|
);
|
||||||
name = Configurable;
|
name = Configurable;
|
||||||
path = ../../Configurable;
|
path = ../../Configurable;
|
||||||
@ -3187,6 +3193,7 @@
|
|||||||
4B055A991FAE85CB0060FFFF /* DiskController.cpp in Sources */,
|
4B055A991FAE85CB0060FFFF /* DiskController.cpp in Sources */,
|
||||||
4B055ACC1FAE9B030060FFFF /* Electron.cpp in Sources */,
|
4B055ACC1FAE9B030060FFFF /* Electron.cpp in Sources */,
|
||||||
4B055AB11FAE86070060FFFF /* Tape.cpp in Sources */,
|
4B055AB11FAE86070060FFFF /* Tape.cpp in Sources */,
|
||||||
|
4BFE7B881FC39D8900160B38 /* StandardOptions.cpp in Sources */,
|
||||||
4B055AA91FAE85EF0060FFFF /* CommodoreGCR.cpp in Sources */,
|
4B055AA91FAE85EF0060FFFF /* CommodoreGCR.cpp in Sources */,
|
||||||
4B055A7F1FAE852F0060FFFF /* StaticAnalyser.cpp in Sources */,
|
4B055A7F1FAE852F0060FFFF /* StaticAnalyser.cpp in Sources */,
|
||||||
4B055ADB1FAE9B460060FFFF /* 6560.cpp in Sources */,
|
4B055ADB1FAE9B460060FFFF /* 6560.cpp in Sources */,
|
||||||
@ -3357,6 +3364,7 @@
|
|||||||
4B5073071DDD3B9400C48FBD /* ArrayBuilder.cpp in Sources */,
|
4B5073071DDD3B9400C48FBD /* ArrayBuilder.cpp in Sources */,
|
||||||
4BEE0A6F1D72496600532C7B /* Cartridge.cpp in Sources */,
|
4BEE0A6F1D72496600532C7B /* Cartridge.cpp in Sources */,
|
||||||
4B8805FB1DCFF807003085B1 /* Oric.cpp in Sources */,
|
4B8805FB1DCFF807003085B1 /* Oric.cpp in Sources */,
|
||||||
|
4BFE7B871FC39BF100160B38 /* StandardOptions.cpp in Sources */,
|
||||||
4B5FADC01DE3BF2B00AEC565 /* Microdisc.cpp in Sources */,
|
4B5FADC01DE3BF2B00AEC565 /* Microdisc.cpp in Sources */,
|
||||||
4B54C0C81F8D91E50050900F /* Keyboard.cpp in Sources */,
|
4B54C0C81F8D91E50050900F /* Keyboard.cpp in Sources */,
|
||||||
4BEE0A701D72496600532C7B /* PRG.cpp in Sources */,
|
4BEE0A701D72496600532C7B /* PRG.cpp in Sources */,
|
||||||
|
@ -115,8 +115,6 @@ bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ParsedArguments {
|
struct ParsedArguments {
|
||||||
std::string file_name;
|
std::string file_name;
|
||||||
Configurable::SelectionSet selections;
|
Configurable::SelectionSet selections;
|
||||||
@ -158,15 +156,70 @@ ParsedArguments parse_arguments(int argc, char *argv[]) {
|
|||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string final_path_component(const std::string &path) {
|
||||||
|
// An empty path has no final component.
|
||||||
|
if(path.empty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the last slash...
|
||||||
|
auto final_slash = path.find_last_of("/\\");
|
||||||
|
|
||||||
|
// If no slash was found at all, return the whole path.
|
||||||
|
if(final_slash == std::string::npos) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a slash was found in the final position, remove it and recurse.
|
||||||
|
if(final_slash == path.size() - 1) {
|
||||||
|
return final_path_component(path.substr(0, path.size() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise return everything from just after the slash to the end of the path.
|
||||||
|
return path.substr(final_slash+1, path.size() - final_slash - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
SDL_Window *window = nullptr;
|
SDL_Window *window = nullptr;
|
||||||
|
|
||||||
// Attempt to parse arguments.
|
// Attempt to parse arguments.
|
||||||
ParsedArguments arguments = parse_arguments(argc, argv);
|
ParsedArguments arguments = parse_arguments(argc, argv);
|
||||||
|
|
||||||
|
// Print a help message if requested.
|
||||||
|
if(arguments.selections.find("help") != arguments.selections.end() || arguments.selections.find("h") != arguments.selections.end()) {
|
||||||
|
std::cout << "Usage: " << final_path_component(argv[0]) << " [file] [OPTIONS]" << std::endl;
|
||||||
|
std::cout << "Required machine type and configuration is determined from the file. Machines with further options:" << std::endl << std::endl;
|
||||||
|
|
||||||
|
auto all_options = Machine::AllOptionsByMachineName();
|
||||||
|
for(auto &machine_options: all_options) {
|
||||||
|
std::cout << machine_options.first << ":" << std::endl;
|
||||||
|
for(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(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;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Perform a sanity check on arguments.
|
// Perform a sanity check on arguments.
|
||||||
if(arguments.file_name.empty()) {
|
if(arguments.file_name.empty()) {
|
||||||
std::cerr << "Usage: " << argv[0] << " [file]" << std::endl;
|
std::cerr << "Usage: " << final_path_component(argv[0]) << " [file] [OPTIONS]" << std::endl;
|
||||||
|
std::cerr << "Use --help to learn more about available options." << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +259,7 @@ int main(int argc, char *argv[]) {
|
|||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||||
SDL_GL_SetSwapInterval(1);
|
SDL_GL_SetSwapInterval(1);
|
||||||
|
|
||||||
window = SDL_CreateWindow( "Clock Signal",
|
window = SDL_CreateWindow( final_path_component(arguments.file_name).c_str(),
|
||||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||||
400, 300,
|
400, 300,
|
||||||
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
||||||
|
@ -66,7 +66,7 @@ struct Media {
|
|||||||
and instructions on how to launch the software attached, plus a measure of confidence in this target's correctness.
|
and instructions on how to launch the software attached, plus a measure of confidence in this target's correctness.
|
||||||
*/
|
*/
|
||||||
struct Target {
|
struct Target {
|
||||||
enum {
|
enum Machine {
|
||||||
AmstradCPC,
|
AmstradCPC,
|
||||||
Atari2600,
|
Atari2600,
|
||||||
Electron,
|
Electron,
|
||||||
|
Loading…
Reference in New Issue
Block a user