mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-23 03:32:32 +00:00
Merge pull request #281 from TomHarte/MachineOptions
Introduces reflective machine options and a command-line parser for them.
This commit is contained in:
commit
8dcac6561e
77
Configurable/Configurable.hpp
Normal file
77
Configurable/Configurable.hpp
Normal file
@ -0,0 +1,77 @@
|
||||
//
|
||||
// Configurable.h
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 17/11/2017.
|
||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Configurable_h
|
||||
#define Configurable_h
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Configurable {
|
||||
|
||||
/*!
|
||||
The Option class hierarchy provides a way for components, machines, etc, to provide a named
|
||||
list of typed options to which they can respond.
|
||||
*/
|
||||
struct Option {
|
||||
std::string long_name;
|
||||
std::string short_name;
|
||||
virtual ~Option() {}
|
||||
|
||||
Option(const std::string &long_name, const std::string &short_name) : long_name(long_name), short_name(short_name) {}
|
||||
};
|
||||
|
||||
struct BooleanOption: public Option {
|
||||
BooleanOption(const std::string &long_name, const std::string &short_name) : Option(long_name, short_name) {}
|
||||
};
|
||||
|
||||
struct ListOption: public Option {
|
||||
std::vector<std::string> options;
|
||||
ListOption(const std::string &long_name, const std::string &short_name, const std::vector<std::string> &options) : Option(long_name, short_name), options(options) {}
|
||||
};
|
||||
|
||||
/*!
|
||||
Selections are responses to Options.
|
||||
*/
|
||||
struct Selection {
|
||||
virtual ~Selection() {}
|
||||
};
|
||||
|
||||
struct BooleanSelection: public Selection {
|
||||
bool value;
|
||||
BooleanSelection(bool value) : value(value) {}
|
||||
};
|
||||
|
||||
struct ListSelection: public Selection {
|
||||
std::string value;
|
||||
ListSelection(const std::string value) : value(value) {}
|
||||
};
|
||||
|
||||
using SelectionSet = std::map<std::string, std::unique_ptr<Selection>>;
|
||||
|
||||
/*!
|
||||
A Configuratble provides the options that it responds to and allows selections to be set.
|
||||
*/
|
||||
struct Device {
|
||||
virtual std::vector<std::unique_ptr<Option>> get_options() = 0;
|
||||
virtual void set_selections(const SelectionSet &selection_by_option) = 0;
|
||||
virtual SelectionSet get_accurate_selections() = 0;
|
||||
virtual SelectionSet get_user_friendly_selections() = 0;
|
||||
};
|
||||
|
||||
template <typename T> T *selection(const Configurable::SelectionSet &selections_by_option, const std::string &name) {
|
||||
auto selection = selections_by_option.find(name);
|
||||
if(selection == selections_by_option.end()) return nullptr;
|
||||
return dynamic_cast<T *>(selection->second.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* Configurable_h */
|
@ -636,6 +636,30 @@ class ConcreteMachine:
|
||||
return keyboard_mapper_;
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
||||
std::vector<std::unique_ptr<Configurable::Option>> options;
|
||||
options.emplace_back(new Configurable::BooleanOption("Load Tapes Quickly", "quickload"));
|
||||
return options;
|
||||
}
|
||||
|
||||
void set_selections(const Configurable::SelectionSet &selections_by_option) override {
|
||||
auto quickload = Configurable::selection<Configurable::BooleanSelection>(selections_by_option, "quickload");
|
||||
if(quickload) set_use_fast_tape_hack(quickload->value);
|
||||
}
|
||||
|
||||
Configurable::SelectionSet get_accurate_selections() override {
|
||||
Configurable::SelectionSet selection_set;
|
||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(false));
|
||||
return selection_set;
|
||||
}
|
||||
|
||||
Configurable::SelectionSet get_user_friendly_selections() override {
|
||||
Configurable::SelectionSet selection_set;
|
||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(true));
|
||||
return selection_set;
|
||||
}
|
||||
|
||||
private:
|
||||
CPU::MOS6502::Processor<ConcreteMachine, false> m6502_;
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#ifndef Vic20_hpp
|
||||
#define Vic20_hpp
|
||||
|
||||
#include "../../../Configurable/Configurable.hpp"
|
||||
#include "../../ConfigurationTarget.hpp"
|
||||
#include "../../CRTMachine.hpp"
|
||||
#include "../../KeyboardMachine.hpp"
|
||||
@ -44,7 +45,8 @@ class Machine:
|
||||
public CRTMachine::Machine,
|
||||
public ConfigurationTarget::Machine,
|
||||
public KeyboardMachine::Machine,
|
||||
public JoystickMachine::Machine {
|
||||
public JoystickMachine::Machine,
|
||||
public Configurable::Device {
|
||||
public:
|
||||
virtual ~Machine();
|
||||
|
||||
|
@ -10,6 +10,9 @@
|
||||
#define ConfigurationTarget_hpp
|
||||
|
||||
#include "../StaticAnalyser/StaticAnalyser.hpp"
|
||||
#include "../Configurable/Configurable.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ConfigurationTarget {
|
||||
|
||||
|
@ -416,7 +416,38 @@ class ConcreteMachine:
|
||||
return keyboard_mapper_;
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
||||
std::vector<std::unique_ptr<Configurable::Option>> 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 {
|
||||
auto quickload = Configurable::selection<Configurable::BooleanSelection>(selections_by_option, "quickload");
|
||||
if(quickload) set_use_fast_tape_hack(quickload->value);
|
||||
|
||||
auto display = Configurable::selection<Configurable::ListSelection>(selections_by_option, "display");
|
||||
if(display) get_crt()->set_output_device((display->value == "rgb") ? Outputs::CRT::OutputDevice::Monitor : Outputs::CRT::OutputDevice::Television);
|
||||
}
|
||||
|
||||
Configurable::SelectionSet get_accurate_selections() override {
|
||||
Configurable::SelectionSet selection_set;
|
||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(false));
|
||||
selection_set["display"] = std::unique_ptr<Configurable::Selection>(new Configurable::ListSelection("composite"));
|
||||
return selection_set;
|
||||
}
|
||||
|
||||
Configurable::SelectionSet get_user_friendly_selections() override {
|
||||
Configurable::SelectionSet selection_set;
|
||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(true));
|
||||
selection_set["display"] = std::unique_ptr<Configurable::Selection>(new Configurable::ListSelection("rgb"));
|
||||
return selection_set;
|
||||
}
|
||||
|
||||
private:
|
||||
// MARK: - Work deferral updates.
|
||||
inline void update_display() {
|
||||
if(cycles_since_display_update_ > 0) {
|
||||
video_output_->run_for(cycles_since_display_update_.flush());
|
||||
|
@ -9,6 +9,7 @@
|
||||
#ifndef Electron_hpp
|
||||
#define Electron_hpp
|
||||
|
||||
#include "../../Configurable/Configurable.hpp"
|
||||
#include "../ConfigurationTarget.hpp"
|
||||
#include "../CRTMachine.hpp"
|
||||
#include "../KeyboardMachine.hpp"
|
||||
@ -41,7 +42,8 @@ enum ROMSlot: uint8_t {
|
||||
class Machine:
|
||||
public CRTMachine::Machine,
|
||||
public ConfigurationTarget::Machine,
|
||||
public KeyboardMachine::Machine {
|
||||
public KeyboardMachine::Machine,
|
||||
public Configurable::Device {
|
||||
public:
|
||||
virtual ~Machine();
|
||||
|
||||
|
@ -42,7 +42,7 @@ uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
|
||||
BIND(LeftShift, KeyShift); BIND(RightShift, KeyShift);
|
||||
|
||||
BIND(Hyphen, KeyMinus);
|
||||
BIND(Delete, KeyDelete);
|
||||
BIND(Delete, KeyDelete); BIND(BackSpace, KeyDelete);
|
||||
BIND(Enter, KeyReturn); BIND(KeyPadEnter, KeyReturn);
|
||||
|
||||
BIND(KeyPad0, Key0); BIND(KeyPad1, Key1); BIND(KeyPad2, Key2); BIND(KeyPad3, Key3); BIND(KeyPad4, Key4);
|
||||
|
@ -427,6 +427,36 @@ class ConcreteMachine:
|
||||
return keyboard_mapper_;
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
||||
std::vector<std::unique_ptr<Configurable::Option>> 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 {
|
||||
auto quickload = Configurable::selection<Configurable::BooleanSelection>(selections_by_option, "quickload");
|
||||
if(quickload) set_use_fast_tape_hack(quickload->value);
|
||||
|
||||
auto display = Configurable::selection<Configurable::ListSelection>(selections_by_option, "display");
|
||||
if(display) get_crt()->set_output_device((display->value == "rgb") ? Outputs::CRT::OutputDevice::Monitor : Outputs::CRT::OutputDevice::Television);
|
||||
}
|
||||
|
||||
Configurable::SelectionSet get_accurate_selections() override {
|
||||
Configurable::SelectionSet selection_set;
|
||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(false));
|
||||
selection_set["display"] = std::unique_ptr<Configurable::Selection>(new Configurable::ListSelection("composite"));
|
||||
return selection_set;
|
||||
}
|
||||
|
||||
Configurable::SelectionSet get_user_friendly_selections() override {
|
||||
Configurable::SelectionSet selection_set;
|
||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(true));
|
||||
selection_set["display"] = std::unique_ptr<Configurable::Selection>(new Configurable::ListSelection("rgb"));
|
||||
return selection_set;
|
||||
}
|
||||
|
||||
private:
|
||||
CPU::MOS6502::Processor<ConcreteMachine, false> m6502_;
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#ifndef Oric_hpp
|
||||
#define Oric_hpp
|
||||
|
||||
#include "../../Configurable/Configurable.hpp"
|
||||
#include "../ConfigurationTarget.hpp"
|
||||
#include "../CRTMachine.hpp"
|
||||
#include "../KeyboardMachine.hpp"
|
||||
@ -28,7 +29,8 @@ enum ROM {
|
||||
class Machine:
|
||||
public CRTMachine::Machine,
|
||||
public ConfigurationTarget::Machine,
|
||||
public KeyboardMachine::Machine {
|
||||
public KeyboardMachine::Machine,
|
||||
public Configurable::Device {
|
||||
public:
|
||||
virtual ~Machine();
|
||||
|
||||
|
@ -21,23 +21,30 @@ template<typename T> class TypedDynamicMachine: public ::Machine::DynamicMachine
|
||||
public:
|
||||
TypedDynamicMachine(T *machine) : machine_(machine) {}
|
||||
|
||||
ConfigurationTarget::Machine *configuration_target() {
|
||||
return dynamic_cast<ConfigurationTarget::Machine *>(machine_.get());
|
||||
ConfigurationTarget::Machine *configuration_target() override {
|
||||
return get<ConfigurationTarget::Machine>();
|
||||
}
|
||||
|
||||
CRTMachine::Machine *crt_machine() {
|
||||
return dynamic_cast<CRTMachine::Machine *>(machine_.get());
|
||||
CRTMachine::Machine *crt_machine() override {
|
||||
return get<CRTMachine::Machine>();
|
||||
}
|
||||
|
||||
JoystickMachine::Machine *joystick_machine() {
|
||||
return dynamic_cast<JoystickMachine::Machine *>(machine_.get());
|
||||
JoystickMachine::Machine *joystick_machine() override {
|
||||
return get<JoystickMachine::Machine>();
|
||||
}
|
||||
|
||||
KeyboardMachine::Machine *keyboard_machine() {
|
||||
return dynamic_cast<KeyboardMachine::Machine *>(machine_.get());
|
||||
KeyboardMachine::Machine *keyboard_machine() override {
|
||||
return get<KeyboardMachine::Machine>();
|
||||
}
|
||||
|
||||
Configurable::Device *configurable_device() override {
|
||||
return get<Configurable::Device>();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Class> Class *get() {
|
||||
return dynamic_cast<Class *>(machine_.get());
|
||||
}
|
||||
std::unique_ptr<T> machine_;
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "../../StaticAnalyser/StaticAnalyser.hpp"
|
||||
|
||||
#include "../../Configurable/Configurable.hpp"
|
||||
#include "../ConfigurationTarget.hpp"
|
||||
#include "../CRTMachine.hpp"
|
||||
#include "../JoystickMachine.hpp"
|
||||
@ -29,6 +30,7 @@ struct DynamicMachine {
|
||||
virtual CRTMachine::Machine *crt_machine() = 0;
|
||||
virtual JoystickMachine::Machine *joystick_machine() = 0;
|
||||
virtual KeyboardMachine::Machine *keyboard_machine() = 0;
|
||||
virtual Configurable::Device *configurable_device() = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -308,8 +308,7 @@ template<bool is_zx81> class ConcreteMachine:
|
||||
return true;
|
||||
}
|
||||
|
||||
// MARK: - Keyboard
|
||||
|
||||
// MARK: - Keyboard
|
||||
void set_key_state(uint16_t key, bool isPressed) override final {
|
||||
if(isPressed)
|
||||
key_states_[key >> 8] &= static_cast<uint8_t>(~key);
|
||||
@ -321,8 +320,7 @@ template<bool is_zx81> class ConcreteMachine:
|
||||
memset(key_states_, 0xff, 8);
|
||||
}
|
||||
|
||||
// MARK: - Tape control
|
||||
|
||||
// MARK: - Tape control
|
||||
void set_use_fast_tape_hack(bool activate) override final {
|
||||
use_fast_tape_hack_ = activate;
|
||||
}
|
||||
@ -337,8 +335,7 @@ template<bool is_zx81> class ConcreteMachine:
|
||||
tape_player_.set_motor_control(is_playing);
|
||||
}
|
||||
|
||||
// MARK: - Typer timing
|
||||
|
||||
// MARK: - Typer timing
|
||||
HalfCycles get_typer_delay() override final { return Cycles(7000000); }
|
||||
HalfCycles get_typer_frequency() override final { return Cycles(390000); }
|
||||
|
||||
@ -346,6 +343,36 @@ template<bool is_zx81> class ConcreteMachine:
|
||||
return keyboard_mapper_;
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
||||
std::vector<std::unique_ptr<Configurable::Option>> 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 {
|
||||
auto quickload = Configurable::selection<Configurable::BooleanSelection>(selections_by_option, "quickload");
|
||||
if(quickload) set_use_fast_tape_hack(quickload->value);
|
||||
|
||||
auto autotapemotor = Configurable::selection<Configurable::BooleanSelection>(selections_by_option, "autotapemotor");
|
||||
if(autotapemotor) set_use_automatic_tape_motor_control(autotapemotor->value);
|
||||
}
|
||||
|
||||
Configurable::SelectionSet get_accurate_selections() override {
|
||||
Configurable::SelectionSet selection_set;
|
||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(false));
|
||||
selection_set["autotapemotor"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(false));
|
||||
return selection_set;
|
||||
}
|
||||
|
||||
Configurable::SelectionSet get_user_friendly_selections() override {
|
||||
Configurable::SelectionSet selection_set;
|
||||
selection_set["quickload"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(true));
|
||||
selection_set["autotapemotor"] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(true));
|
||||
return selection_set;
|
||||
}
|
||||
|
||||
private:
|
||||
CPU::Z80::Processor<ConcreteMachine, false, is_zx81> z80_;
|
||||
|
||||
@ -383,8 +410,7 @@ template<bool is_zx81> class ConcreteMachine:
|
||||
bool use_automatic_tape_motor_control_;
|
||||
HalfCycles tape_advance_delay_ = 0;
|
||||
|
||||
// MARK: - Video
|
||||
|
||||
// MARK: - Video
|
||||
inline void set_vsync(bool sync) {
|
||||
vsync_ = sync;
|
||||
update_sync();
|
||||
|
@ -9,6 +9,7 @@
|
||||
#ifndef ZX8081_hpp
|
||||
#define ZX8081_hpp
|
||||
|
||||
#include "../../Configurable/Configurable.hpp"
|
||||
#include "../ConfigurationTarget.hpp"
|
||||
#include "../CRTMachine.hpp"
|
||||
#include "../KeyboardMachine.hpp"
|
||||
@ -25,7 +26,8 @@ enum ROMType: uint8_t {
|
||||
class Machine:
|
||||
public CRTMachine::Machine,
|
||||
public ConfigurationTarget::Machine,
|
||||
public KeyboardMachine::Machine {
|
||||
public KeyboardMachine::Machine,
|
||||
public Configurable::Device {
|
||||
public:
|
||||
static Machine *ZX8081(const StaticAnalyser::Target &target_hint);
|
||||
virtual ~Machine();
|
||||
|
@ -680,6 +680,7 @@
|
||||
4B30512C1D989E2200B4FED8 /* Drive.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Drive.hpp; sourceTree = "<group>"; };
|
||||
4B30512E1D98ACC600B4FED8 /* Plus3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Plus3.cpp; path = Electron/Plus3.cpp; sourceTree = "<group>"; };
|
||||
4B30512F1D98ACC600B4FED8 /* Plus3.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Plus3.hpp; path = Electron/Plus3.hpp; sourceTree = "<group>"; };
|
||||
4B31B88F1FBFBCD800C140D5 /* Configurable.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Configurable.hpp; sourceTree = "<group>"; };
|
||||
4B322DF31F5A26BF004EB04C /* 6502Implementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = 6502Implementation.hpp; sourceTree = "<group>"; };
|
||||
4B322DF41F5A2714004EB04C /* 6502Storage.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = 6502Storage.hpp; sourceTree = "<group>"; };
|
||||
4B322DFD1F5A2981004EB04C /* Z80AllRAM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Z80AllRAM.cpp; sourceTree = "<group>"; };
|
||||
@ -1509,6 +1510,15 @@
|
||||
name = Electron;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B31B88E1FBFBCD800C140D5 /* Configurable */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B31B88F1FBFBCD800C140D5 /* Configurable.hpp */,
|
||||
);
|
||||
name = Configurable;
|
||||
path = ../../Configurable;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B322DFC1F5A2981004EB04C /* AllRAM */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -2259,6 +2269,7 @@
|
||||
4BF660691F281573002CB053 /* ClockReceiver */,
|
||||
4BC9DF4A1D04691600F44158 /* Components */,
|
||||
4B3940E81DA83C8700427841 /* Concurrency */,
|
||||
4B31B88E1FBFBCD800C140D5 /* Configurable */,
|
||||
4B055A761FAE78210060FFFF /* Frameworks */,
|
||||
4B86E2581F8C628F006FAA45 /* Inputs */,
|
||||
4BB73EDC1B587CA500552FC2 /* Machines */,
|
||||
|
@ -6,9 +6,9 @@
|
||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <cstdio>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
@ -117,19 +117,63 @@ bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key)
|
||||
|
||||
}
|
||||
|
||||
struct ParsedArguments {
|
||||
std::string file_name;
|
||||
Configurable::SelectionSet selections;
|
||||
};
|
||||
|
||||
/*! Parses an argc/argv pair to discern program arguments. */
|
||||
ParsedArguments parse_arguments(int argc, char *argv[]) {
|
||||
ParsedArguments arguments;
|
||||
|
||||
for(int index = 1; index < argc; ++index) {
|
||||
char *arg = argv[index];
|
||||
|
||||
// Accepted format is:
|
||||
//
|
||||
// --flag sets a Boolean option to true.
|
||||
// --flag=value sets the value for a list option.
|
||||
// name sets the file name to load.
|
||||
|
||||
// Anything starting with a dash always makes a selection; otherwise it's a file name.
|
||||
if(arg[0] == '-') {
|
||||
while(*arg == '-') arg++;
|
||||
|
||||
// Check for an equals sign, to discern a Boolean selection from a list selection.
|
||||
std::string argument = arg;
|
||||
std::size_t split_index = argument.find("=");
|
||||
|
||||
if(split_index == std::string::npos) {
|
||||
arguments.selections[argument] = std::unique_ptr<Configurable::Selection>(new Configurable::BooleanSelection(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::unique_ptr<Configurable::Selection>(new Configurable::ListSelection(value));
|
||||
}
|
||||
} else {
|
||||
arguments.file_name = arg;
|
||||
}
|
||||
}
|
||||
|
||||
return arguments;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
SDL_Window *window = nullptr;
|
||||
|
||||
// Attempt to parse arguments.
|
||||
ParsedArguments arguments = parse_arguments(argc, argv);
|
||||
|
||||
// Perform a sanity check on arguments.
|
||||
if(argc < 2) {
|
||||
if(arguments.file_name.empty()) {
|
||||
std::cerr << "Usage: " << argv[0] << " [file]" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Determine the machine for the supplied file.
|
||||
std::list<StaticAnalyser::Target> targets = StaticAnalyser::GetTargets(argv[1]);
|
||||
std::list<StaticAnalyser::Target> targets = StaticAnalyser::GetTargets(arguments.file_name.c_str());
|
||||
if(targets.empty()) {
|
||||
std::cerr << "Cannot open " << argv[1] << std::endl;
|
||||
std::cerr << "Cannot open " << arguments.file_name << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -178,7 +222,6 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
GLint target_framebuffer = 0;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &target_framebuffer);
|
||||
std::cout << "Target framebuffer has ID " << target_framebuffer << std::endl;
|
||||
|
||||
// For vanilla SDL purposes, assume system ROMs can be found in one of:
|
||||
//
|
||||
@ -250,7 +293,13 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
int window_width, window_height;
|
||||
SDL_GetWindowSize(window, &window_width, &window_height);
|
||||
std::cout << "Window size is " << window_width << ", " << window_height << std::endl;
|
||||
|
||||
// Establish user-friendly options by default.
|
||||
Configurable::Device *configurable_device = machine->configurable_device();
|
||||
if(configurable_device) {
|
||||
configurable_device->set_selections(configurable_device->get_user_friendly_selections());
|
||||
configurable_device->set_selections(arguments.selections);
|
||||
}
|
||||
|
||||
// Run the main event loop until the OS tells us to quit.
|
||||
bool should_quit = false;
|
||||
@ -268,8 +317,6 @@ int main(int argc, char *argv[]) {
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &target_framebuffer);
|
||||
machine->crt_machine()->get_crt()->set_target_framebuffer(target_framebuffer);
|
||||
SDL_GetWindowSize(window, &window_width, &window_height);
|
||||
|
||||
std::cout << "Resized; framebuffer is " << target_framebuffer << ", and window size is " << window_width << ", " << window_height << std::endl;
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
|
Loading…
Reference in New Issue
Block a user