mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-15 05:31:30 +00:00
Roll formatting and const
tweaks into Inputs.
This commit is contained in:
parent
9d87296316
commit
7248470950
@ -115,6 +115,6 @@ void MultiConfigurable::set_options(const std::unique_ptr<Reflection::Struct> &s
|
||||
options->apply();
|
||||
}
|
||||
|
||||
std::unique_ptr<Reflection::Struct> MultiConfigurable::get_options() {
|
||||
std::unique_ptr<Reflection::Struct> MultiConfigurable::get_options() const {
|
||||
return std::make_unique<MultiStruct>(devices_);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
|
||||
// Below is the standard Configurable::Device interface; see there for documentation.
|
||||
void set_options(const std::unique_ptr<Reflection::Struct> &) final;
|
||||
std::unique_ptr<Reflection::Struct> get_options() final;
|
||||
std::unique_ptr<Reflection::Struct> get_options() const final;
|
||||
|
||||
private:
|
||||
std::vector<Configurable::Device *> devices_;
|
||||
|
@ -65,126 +65,126 @@ template <> struct TaskQueueStorage<void> {
|
||||
called once per action.
|
||||
*/
|
||||
template <bool perform_automatically, bool start_immediately = true, typename Performer = void> class AsyncTaskQueue: public TaskQueueStorage<Performer> {
|
||||
public:
|
||||
template <typename... Args> AsyncTaskQueue(Args&&... args) :
|
||||
TaskQueueStorage<Performer>(std::forward<Args>(args)...) {
|
||||
if constexpr (start_immediately) {
|
||||
start();
|
||||
}
|
||||
public:
|
||||
template <typename... Args> AsyncTaskQueue(Args&&... args) :
|
||||
TaskQueueStorage<Performer>(std::forward<Args>(args)...) {
|
||||
if constexpr (start_immediately) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
/// Enqueus @c post_action to be performed asynchronously at some point
|
||||
/// in the future. If @c perform_automatically is @c true then the action
|
||||
/// will be performed as soon as possible. Otherwise it will sit unsheculed until
|
||||
/// a call to @c perform().
|
||||
///
|
||||
/// Actions may be elided.
|
||||
///
|
||||
/// If this TaskQueue has a @c Performer then the action will be performed
|
||||
/// on the same thread as the performer, after the performer has been updated
|
||||
/// to 'now'.
|
||||
void enqueue(const std::function<void(void)> &post_action) {
|
||||
std::lock_guard guard(condition_mutex_);
|
||||
actions_.push_back(post_action);
|
||||
/// Enqueus @c post_action to be performed asynchronously at some point
|
||||
/// in the future. If @c perform_automatically is @c true then the action
|
||||
/// will be performed as soon as possible. Otherwise it will sit unsheculed until
|
||||
/// a call to @c perform().
|
||||
///
|
||||
/// Actions may be elided.
|
||||
///
|
||||
/// If this TaskQueue has a @c Performer then the action will be performed
|
||||
/// on the same thread as the performer, after the performer has been updated
|
||||
/// to 'now'.
|
||||
void enqueue(const std::function<void(void)> &post_action) {
|
||||
std::lock_guard guard(condition_mutex_);
|
||||
actions_.push_back(post_action);
|
||||
|
||||
if constexpr (perform_automatically) {
|
||||
condition_.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
/// Causes any enqueued actions that are not yet scheduled to be scheduled.
|
||||
void perform() {
|
||||
if(actions_.empty()) {
|
||||
return;
|
||||
}
|
||||
if constexpr (perform_automatically) {
|
||||
condition_.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
/// Permanently stops this task queue, blocking until that has happened.
|
||||
/// All pending actions will be performed first.
|
||||
///
|
||||
/// The queue cannot be restarted; this is a destructive action.
|
||||
void stop() {
|
||||
if(thread_.joinable()) {
|
||||
should_quit_ = true;
|
||||
enqueue([] {});
|
||||
if constexpr (!perform_automatically) {
|
||||
perform();
|
||||
}
|
||||
thread_.join();
|
||||
}
|
||||
/// Causes any enqueued actions that are not yet scheduled to be scheduled.
|
||||
void perform() {
|
||||
if(actions_.empty()) {
|
||||
return;
|
||||
}
|
||||
condition_.notify_all();
|
||||
}
|
||||
|
||||
/// Starts the queue if it has never been started before.
|
||||
///
|
||||
/// This is not guaranteed safely to restart a stopped queue.
|
||||
void start() {
|
||||
thread_ = std::thread{
|
||||
[this] {
|
||||
ActionVector actions;
|
||||
|
||||
// Continue until told to quit.
|
||||
while(!should_quit_) {
|
||||
// Wait for new actions to be signalled, and grab them.
|
||||
std::unique_lock lock(condition_mutex_);
|
||||
while(actions_.empty() && !should_quit_) {
|
||||
condition_.wait(lock);
|
||||
}
|
||||
std::swap(actions, actions_);
|
||||
lock.unlock();
|
||||
|
||||
// Update to now (which is possibly a no-op).
|
||||
TaskQueueStorage<Performer>::update();
|
||||
|
||||
// Perform the actions and destroy them.
|
||||
for(const auto &action: actions) {
|
||||
action();
|
||||
}
|
||||
actions.clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Schedules any remaining unscheduled work, then blocks synchronously
|
||||
/// until all scheduled work has been performed.
|
||||
void flush() {
|
||||
std::mutex flush_mutex;
|
||||
std::condition_variable flush_condition;
|
||||
bool has_run = false;
|
||||
std::unique_lock lock(flush_mutex);
|
||||
|
||||
enqueue([&flush_mutex, &flush_condition, &has_run] () {
|
||||
std::unique_lock inner_lock(flush_mutex);
|
||||
has_run = true;
|
||||
flush_condition.notify_all();
|
||||
});
|
||||
|
||||
/// Permanently stops this task queue, blocking until that has happened.
|
||||
/// All pending actions will be performed first.
|
||||
///
|
||||
/// The queue cannot be restarted; this is a destructive action.
|
||||
void stop() {
|
||||
if(thread_.joinable()) {
|
||||
should_quit_ = true;
|
||||
enqueue([] {});
|
||||
if constexpr (!perform_automatically) {
|
||||
perform();
|
||||
}
|
||||
thread_.join();
|
||||
}
|
||||
}
|
||||
|
||||
flush_condition.wait(lock, [&has_run] { return has_run; });
|
||||
/// Starts the queue if it has never been started before.
|
||||
///
|
||||
/// This is not guaranteed safely to restart a stopped queue.
|
||||
void start() {
|
||||
thread_ = std::thread{
|
||||
[this] {
|
||||
ActionVector actions;
|
||||
|
||||
// Continue until told to quit.
|
||||
while(!should_quit_) {
|
||||
// Wait for new actions to be signalled, and grab them.
|
||||
std::unique_lock lock(condition_mutex_);
|
||||
while(actions_.empty() && !should_quit_) {
|
||||
condition_.wait(lock);
|
||||
}
|
||||
std::swap(actions, actions_);
|
||||
lock.unlock();
|
||||
|
||||
// Update to now (which is possibly a no-op).
|
||||
TaskQueueStorage<Performer>::update();
|
||||
|
||||
// Perform the actions and destroy them.
|
||||
for(const auto &action: actions) {
|
||||
action();
|
||||
}
|
||||
actions.clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Schedules any remaining unscheduled work, then blocks synchronously
|
||||
/// until all scheduled work has been performed.
|
||||
void flush() {
|
||||
std::mutex flush_mutex;
|
||||
std::condition_variable flush_condition;
|
||||
bool has_run = false;
|
||||
std::unique_lock lock(flush_mutex);
|
||||
|
||||
enqueue([&flush_mutex, &flush_condition, &has_run] () {
|
||||
std::unique_lock inner_lock(flush_mutex);
|
||||
has_run = true;
|
||||
flush_condition.notify_all();
|
||||
});
|
||||
|
||||
if constexpr (!perform_automatically) {
|
||||
perform();
|
||||
}
|
||||
|
||||
~AsyncTaskQueue() {
|
||||
stop();
|
||||
}
|
||||
flush_condition.wait(lock, [&has_run] { return has_run; });
|
||||
}
|
||||
|
||||
private:
|
||||
// The list of actions waiting be performed. These will be elided,
|
||||
// increasing their latency, if the emulation thread falls behind.
|
||||
using ActionVector = std::vector<std::function<void(void)>>;
|
||||
ActionVector actions_;
|
||||
~AsyncTaskQueue() {
|
||||
stop();
|
||||
}
|
||||
|
||||
// Necessary synchronisation parts.
|
||||
std::atomic<bool> should_quit_ = false;
|
||||
std::mutex condition_mutex_;
|
||||
std::condition_variable condition_;
|
||||
private:
|
||||
// The list of actions waiting be performed. These will be elided,
|
||||
// increasing their latency, if the emulation thread falls behind.
|
||||
using ActionVector = std::vector<std::function<void(void)>>;
|
||||
ActionVector actions_;
|
||||
|
||||
// Ensure the thread isn't constructed until after the mutex
|
||||
// and condition variable.
|
||||
std::thread thread_;
|
||||
// Necessary synchronisation parts.
|
||||
std::atomic<bool> should_quit_ = false;
|
||||
std::mutex condition_mutex_;
|
||||
std::condition_variable condition_;
|
||||
|
||||
// Ensure the thread isn't constructed until after the mutex
|
||||
// and condition variable.
|
||||
std::thread thread_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ struct Device {
|
||||
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;
|
||||
virtual std::unique_ptr<Reflection::Struct> get_options() const = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -26,37 +26,37 @@ ReflectableEnum(Display,
|
||||
//===
|
||||
|
||||
template <typename Owner> class DisplayOption {
|
||||
public:
|
||||
Configurable::Display output;
|
||||
DisplayOption(Configurable::Display output) : output(output) {}
|
||||
public:
|
||||
Configurable::Display output;
|
||||
DisplayOption(Configurable::Display output) : output(output) {}
|
||||
|
||||
protected:
|
||||
void declare_display_option() {
|
||||
static_cast<Owner *>(this)->declare(&output, "output");
|
||||
AnnounceEnumNS(Configurable, Display);
|
||||
}
|
||||
protected:
|
||||
void declare_display_option() {
|
||||
static_cast<Owner *>(this)->declare(&output, "output");
|
||||
AnnounceEnumNS(Configurable, Display);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Owner> class QuickloadOption {
|
||||
public:
|
||||
bool quickload;
|
||||
QuickloadOption(bool quickload) : quickload(quickload) {}
|
||||
public:
|
||||
bool quickload;
|
||||
QuickloadOption(bool quickload) : quickload(quickload) {}
|
||||
|
||||
protected:
|
||||
void declare_quickload_option() {
|
||||
static_cast<Owner *>(this)->declare(&quickload, "quickload");
|
||||
}
|
||||
protected:
|
||||
void declare_quickload_option() {
|
||||
static_cast<Owner *>(this)->declare(&quickload, "quickload");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Owner> class QuickbootOption {
|
||||
public:
|
||||
bool quickboot;
|
||||
QuickbootOption(bool quickboot) : quickboot(quickboot) {}
|
||||
public:
|
||||
bool quickboot;
|
||||
QuickbootOption(bool quickboot) : quickboot(quickboot) {}
|
||||
|
||||
protected:
|
||||
void declare_quickboot_option() {
|
||||
static_cast<Owner *>(this)->declare(&quickboot, "quickboot");
|
||||
}
|
||||
protected:
|
||||
void declare_quickboot_option() {
|
||||
static_cast<Owner *>(this)->declare(&quickboot, "quickboot");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -18,137 +18,137 @@ namespace Inputs {
|
||||
machine to toggle states, while an interested party either observes or polls.
|
||||
*/
|
||||
class Joystick {
|
||||
public:
|
||||
virtual ~Joystick() = default;
|
||||
public:
|
||||
virtual ~Joystick() = default;
|
||||
|
||||
/*!
|
||||
Defines a single input, any individually-measured thing — a fire button or
|
||||
other digital control, an analogue axis, or a button with a symbol on it.
|
||||
*/
|
||||
struct Input {
|
||||
/// Defines the broad type of the input.
|
||||
enum Type {
|
||||
// Half-axis inputs.
|
||||
Up, Down, Left, Right,
|
||||
// Full-axis inputs.
|
||||
Horizontal, Vertical,
|
||||
// Fire buttons.
|
||||
Fire,
|
||||
// Other labelled keys.
|
||||
Key,
|
||||
/*!
|
||||
Defines a single input, any individually-measured thing — a fire button or
|
||||
other digital control, an analogue axis, or a button with a symbol on it.
|
||||
*/
|
||||
struct Input {
|
||||
/// Defines the broad type of the input.
|
||||
enum Type {
|
||||
// Half-axis inputs.
|
||||
Up, Down, Left, Right,
|
||||
// Full-axis inputs.
|
||||
Horizontal, Vertical,
|
||||
// Fire buttons.
|
||||
Fire,
|
||||
// Other labelled keys.
|
||||
Key,
|
||||
|
||||
// The maximum value this enum can contain.
|
||||
Max = Key
|
||||
};
|
||||
const Type type;
|
||||
|
||||
bool is_digital_axis() const {
|
||||
return type < Type::Horizontal;
|
||||
}
|
||||
bool is_analogue_axis() const {
|
||||
return type >= Type::Horizontal && type < Type::Fire;
|
||||
}
|
||||
bool is_axis() const {
|
||||
return type < Type::Fire;
|
||||
}
|
||||
bool is_button() const {
|
||||
return type >= Type::Fire;
|
||||
}
|
||||
|
||||
enum Precision {
|
||||
Analogue, Digital
|
||||
};
|
||||
Precision precision() const {
|
||||
return is_analogue_axis() ? Precision::Analogue : Precision::Digital;
|
||||
}
|
||||
|
||||
/*!
|
||||
Holds extra information pertaining to the input.
|
||||
|
||||
@c Type::Key inputs declare the symbol printed on them.
|
||||
|
||||
All other types of input have an associated index, indicating whether they
|
||||
are the zeroth, first, second, third, etc of those things. E.g. a joystick
|
||||
may have two fire buttons, which will be buttons 0 and 1.
|
||||
*/
|
||||
union Info {
|
||||
struct {
|
||||
size_t index;
|
||||
} control;
|
||||
struct {
|
||||
wchar_t symbol;
|
||||
} key;
|
||||
};
|
||||
Info info;
|
||||
// TODO: Find a way to make the above safely const; may mean not using a union.
|
||||
|
||||
Input(Type type, size_t index = 0) :
|
||||
type(type) {
|
||||
info.control.index = index;
|
||||
}
|
||||
Input(wchar_t symbol) : type(Key) {
|
||||
info.key.symbol = symbol;
|
||||
}
|
||||
|
||||
bool operator == (const Input &rhs) {
|
||||
if(rhs.type != type) return false;
|
||||
if(rhs.type == Key) {
|
||||
return rhs.info.key.symbol == info.key.symbol;
|
||||
} else {
|
||||
return rhs.info.control.index == info.control.index;
|
||||
}
|
||||
}
|
||||
// The maximum value this enum can contain.
|
||||
Max = Key
|
||||
};
|
||||
const Type type;
|
||||
|
||||
/// @returns The list of all inputs defined on this joystick.
|
||||
virtual const std::vector<Input> &get_inputs() = 0;
|
||||
bool is_digital_axis() const {
|
||||
return type < Type::Horizontal;
|
||||
}
|
||||
bool is_analogue_axis() const {
|
||||
return type >= Type::Horizontal && type < Type::Fire;
|
||||
}
|
||||
bool is_axis() const {
|
||||
return type < Type::Fire;
|
||||
}
|
||||
bool is_button() const {
|
||||
return type >= Type::Fire;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the digital value of @c input. This may have direct effect or
|
||||
influence an analogue value; e.g. if the caller declares that ::Left is
|
||||
active but this joystick has only an analogue horizontal axis, this will
|
||||
cause a change to that analogue value.
|
||||
*/
|
||||
virtual void set_input(const Input &input, bool is_active) = 0;
|
||||
|
||||
/*!
|
||||
Sets the analogue value of @c input. If the input is actually digital,
|
||||
or if there is a digital input with a corresponding meaning (e.g. ::Left
|
||||
versus the horizontal axis), this may cause a digital input to be set.
|
||||
|
||||
@c value should be in the range [0.0, 1.0].
|
||||
*/
|
||||
virtual void set_input(const Input &input, float value) = 0;
|
||||
|
||||
/*!
|
||||
Sets all inputs to their resting state.
|
||||
*/
|
||||
virtual void reset_all_inputs() {
|
||||
for(const auto &input: get_inputs()) {
|
||||
if(input.precision() == Input::Precision::Digital)
|
||||
set_input(input, false);
|
||||
else
|
||||
set_input(input, 0.5f);
|
||||
}
|
||||
enum Precision {
|
||||
Analogue, Digital
|
||||
};
|
||||
Precision precision() const {
|
||||
return is_analogue_axis() ? Precision::Analogue : Precision::Digital;
|
||||
}
|
||||
|
||||
/*!
|
||||
Gets the number of input fire buttons.
|
||||
Holds extra information pertaining to the input.
|
||||
|
||||
This is cached by default, but it's virtual so overridable.
|
||||
@c Type::Key inputs declare the symbol printed on them.
|
||||
|
||||
All other types of input have an associated index, indicating whether they
|
||||
are the zeroth, first, second, third, etc of those things. E.g. a joystick
|
||||
may have two fire buttons, which will be buttons 0 and 1.
|
||||
*/
|
||||
virtual int get_number_of_fire_buttons() {
|
||||
if(number_of_buttons_ >= 0) return number_of_buttons_;
|
||||
union Info {
|
||||
struct {
|
||||
size_t index;
|
||||
} control;
|
||||
struct {
|
||||
wchar_t symbol;
|
||||
} key;
|
||||
};
|
||||
Info info;
|
||||
// TODO: Find a way to make the above safely const; may mean not using a union.
|
||||
|
||||
number_of_buttons_ = 0;
|
||||
for(const auto &input: get_inputs()) {
|
||||
if(input.type == Input::Type::Fire) ++number_of_buttons_;
|
||||
}
|
||||
return number_of_buttons_;
|
||||
Input(const Type type, const size_t index = 0) :
|
||||
type(type) {
|
||||
info.control.index = index;
|
||||
}
|
||||
Input(const wchar_t symbol) : type(Key) {
|
||||
info.key.symbol = symbol;
|
||||
}
|
||||
|
||||
private:
|
||||
int number_of_buttons_ = -1;
|
||||
bool operator == (const Input &rhs) {
|
||||
if(rhs.type != type) return false;
|
||||
if(rhs.type == Key) {
|
||||
return rhs.info.key.symbol == info.key.symbol;
|
||||
} else {
|
||||
return rhs.info.control.index == info.control.index;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// @returns The list of all inputs defined on this joystick.
|
||||
virtual const std::vector<Input> &get_inputs() = 0;
|
||||
|
||||
/*!
|
||||
Sets the digital value of @c input. This may have direct effect or
|
||||
influence an analogue value; e.g. if the caller declares that ::Left is
|
||||
active but this joystick has only an analogue horizontal axis, this will
|
||||
cause a change to that analogue value.
|
||||
*/
|
||||
virtual void set_input(const Input &input, bool is_active) = 0;
|
||||
|
||||
/*!
|
||||
Sets the analogue value of @c input. If the input is actually digital,
|
||||
or if there is a digital input with a corresponding meaning (e.g. ::Left
|
||||
versus the horizontal axis), this may cause a digital input to be set.
|
||||
|
||||
@c value should be in the range [0.0, 1.0].
|
||||
*/
|
||||
virtual void set_input(const Input &input, float value) = 0;
|
||||
|
||||
/*!
|
||||
Sets all inputs to their resting state.
|
||||
*/
|
||||
virtual void reset_all_inputs() {
|
||||
for(const auto &input: get_inputs()) {
|
||||
if(input.precision() == Input::Precision::Digital)
|
||||
set_input(input, false);
|
||||
else
|
||||
set_input(input, 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Gets the number of input fire buttons.
|
||||
|
||||
This is cached by default, but it's virtual so overridable.
|
||||
*/
|
||||
virtual int get_number_of_fire_buttons() {
|
||||
if(number_of_buttons_ >= 0) return number_of_buttons_;
|
||||
|
||||
number_of_buttons_ = 0;
|
||||
for(const auto &input: get_inputs()) {
|
||||
if(input.type == Input::Type::Fire) ++number_of_buttons_;
|
||||
}
|
||||
return number_of_buttons_;
|
||||
}
|
||||
|
||||
private:
|
||||
int number_of_buttons_ = -1;
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -157,79 +157,79 @@ class Joystick {
|
||||
promised analogue <-> digital mapping of Joystick.
|
||||
*/
|
||||
class ConcreteJoystick: public Joystick {
|
||||
public:
|
||||
ConcreteJoystick(const std::vector<Input> &inputs) : inputs_(inputs) {
|
||||
// Size and populate stick_types_, which is used for digital <-> analogue conversion.
|
||||
for(const auto &input: inputs_) {
|
||||
const bool is_digital_axis = input.is_digital_axis();
|
||||
const bool is_analogue_axis = input.is_analogue_axis();
|
||||
if(is_digital_axis || is_analogue_axis) {
|
||||
const size_t required_size = size_t(input.info.control.index+1);
|
||||
if(stick_types_.size() < required_size) {
|
||||
stick_types_.resize(required_size);
|
||||
}
|
||||
stick_types_[size_t(input.info.control.index)] = is_digital_axis ? StickType::Digital : StickType::Analogue;
|
||||
public:
|
||||
ConcreteJoystick(const std::vector<Input> &inputs) : inputs_(inputs) {
|
||||
// Size and populate stick_types_, which is used for digital <-> analogue conversion.
|
||||
for(const auto &input: inputs_) {
|
||||
const bool is_digital_axis = input.is_digital_axis();
|
||||
const bool is_analogue_axis = input.is_analogue_axis();
|
||||
if(is_digital_axis || is_analogue_axis) {
|
||||
const size_t required_size = size_t(input.info.control.index+1);
|
||||
if(stick_types_.size() < required_size) {
|
||||
stick_types_.resize(required_size);
|
||||
}
|
||||
stick_types_[size_t(input.info.control.index)] = is_digital_axis ? StickType::Digital : StickType::Analogue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<Input> &get_inputs() final {
|
||||
return inputs_;
|
||||
const std::vector<Input> &get_inputs() final {
|
||||
return inputs_;
|
||||
}
|
||||
|
||||
void set_input(const Input &input, const bool is_active) final {
|
||||
// If this is a digital setting to a digital property, just pass it along.
|
||||
if(input.is_button() || stick_types_[input.info.control.index] == StickType::Digital) {
|
||||
did_set_input(input, is_active);
|
||||
return;
|
||||
}
|
||||
|
||||
void set_input(const Input &input, bool is_active) final {
|
||||
// If this is a digital setting to a digital property, just pass it along.
|
||||
if(input.is_button() || stick_types_[input.info.control.index] == StickType::Digital) {
|
||||
did_set_input(input, is_active);
|
||||
return;
|
||||
}
|
||||
// Otherwise this is logically to an analogue axis; for now just use some
|
||||
// convenient hard-coded values. TODO: make these a function of time.
|
||||
using Type = Joystick::Input::Type;
|
||||
switch(input.type) {
|
||||
default: did_set_input(input, is_active ? 1.0f : 0.0f); break;
|
||||
case Type::Left: did_set_input(Input(Type::Horizontal, input.info.control.index), is_active ? 0.1f : 0.5f); break;
|
||||
case Type::Right: did_set_input(Input(Type::Horizontal, input.info.control.index), is_active ? 0.9f : 0.5f); break;
|
||||
case Type::Up: did_set_input(Input(Type::Vertical, input.info.control.index), is_active ? 0.1f : 0.5f); break;
|
||||
case Type::Down: did_set_input(Input(Type::Vertical, input.info.control.index), is_active ? 0.9f : 0.5f); break;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise this is logically to an analogue axis; for now just use some
|
||||
// convenient hard-coded values. TODO: make these a function of time.
|
||||
using Type = Joystick::Input::Type;
|
||||
switch(input.type) {
|
||||
default: did_set_input(input, is_active ? 1.0f : 0.0f); break;
|
||||
case Type::Left: did_set_input(Input(Type::Horizontal, input.info.control.index), is_active ? 0.1f : 0.5f); break;
|
||||
case Type::Right: did_set_input(Input(Type::Horizontal, input.info.control.index), is_active ? 0.9f : 0.5f); break;
|
||||
case Type::Up: did_set_input(Input(Type::Vertical, input.info.control.index), is_active ? 0.1f : 0.5f); break;
|
||||
case Type::Down: did_set_input(Input(Type::Vertical, input.info.control.index), is_active ? 0.9f : 0.5f); break;
|
||||
}
|
||||
void set_input(const Input &input, const float value) final {
|
||||
// If this is an analogue setting to an analogue property, just pass it along.
|
||||
if(!input.is_button() && stick_types_[input.info.control.index] == StickType::Analogue) {
|
||||
did_set_input(input, value);
|
||||
return;
|
||||
}
|
||||
|
||||
void set_input(const Input &input, float value) final {
|
||||
// If this is an analogue setting to an analogue property, just pass it along.
|
||||
if(!input.is_button() && stick_types_[input.info.control.index] == StickType::Analogue) {
|
||||
did_set_input(input, value);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise apply a threshold test to convert to digital, with remapping from axes to digital inputs.
|
||||
using Type = Joystick::Input::Type;
|
||||
switch(input.type) {
|
||||
default: did_set_input(input, value > 0.5f); break;
|
||||
case Type::Horizontal:
|
||||
did_set_input(Input(Type::Left, input.info.control.index), value <= 0.25f);
|
||||
did_set_input(Input(Type::Right, input.info.control.index), value >= 0.75f);
|
||||
break;
|
||||
case Type::Vertical:
|
||||
did_set_input(Input(Type::Up, input.info.control.index), value <= 0.25f);
|
||||
did_set_input(Input(Type::Down, input.info.control.index), value >= 0.75f);
|
||||
break;
|
||||
}
|
||||
// Otherwise apply a threshold test to convert to digital, with remapping from axes to digital inputs.
|
||||
using Type = Joystick::Input::Type;
|
||||
switch(input.type) {
|
||||
default: did_set_input(input, value > 0.5f); break;
|
||||
case Type::Horizontal:
|
||||
did_set_input(Input(Type::Left, input.info.control.index), value <= 0.25f);
|
||||
did_set_input(Input(Type::Right, input.info.control.index), value >= 0.75f);
|
||||
break;
|
||||
case Type::Vertical:
|
||||
did_set_input(Input(Type::Up, input.info.control.index), value <= 0.25f);
|
||||
did_set_input(Input(Type::Down, input.info.control.index), value >= 0.75f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void did_set_input([[maybe_unused]] const Input &input, [[maybe_unused]] float value) {}
|
||||
virtual void did_set_input([[maybe_unused]] const Input &input, [[maybe_unused]] bool value) {}
|
||||
protected:
|
||||
virtual void did_set_input([[maybe_unused]] const Input &input, [[maybe_unused]] float value) {}
|
||||
virtual void did_set_input([[maybe_unused]] const Input &input, [[maybe_unused]] bool value) {}
|
||||
|
||||
private:
|
||||
const std::vector<Input> inputs_;
|
||||
private:
|
||||
const std::vector<Input> inputs_;
|
||||
|
||||
enum class StickType {
|
||||
Digital,
|
||||
Analogue
|
||||
};
|
||||
std::vector<StickType> stick_types_;
|
||||
enum class StickType {
|
||||
Digital,
|
||||
Analogue
|
||||
};
|
||||
std::vector<StickType> stick_types_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ Keyboard::Keyboard(const std::set<Key> &essential_modifiers) : essential_modifie
|
||||
Keyboard::Keyboard(const std::set<Key> &observed_keys, const std::set<Key> &essential_modifiers) :
|
||||
observed_keys_(observed_keys), essential_modifiers_(essential_modifiers), is_exclusive_(false) {}
|
||||
|
||||
bool Keyboard::set_key_pressed(Key key, char, bool is_pressed, bool) {
|
||||
bool Keyboard::set_key_pressed(const Key key, const char, const bool is_pressed, bool) {
|
||||
const size_t key_offset = size_t(key);
|
||||
if(key_offset >= key_states_.size()) {
|
||||
key_states_.resize(key_offset+1, false);
|
||||
@ -41,7 +41,7 @@ void Keyboard::reset_all_keys() {
|
||||
if(delegate_) delegate_->reset_all_keys(this);
|
||||
}
|
||||
|
||||
void Keyboard::set_delegate(Delegate *delegate) {
|
||||
void Keyboard::set_delegate(Delegate *const delegate) {
|
||||
delegate_ = delegate;
|
||||
}
|
||||
|
||||
|
@ -19,73 +19,73 @@ namespace Inputs {
|
||||
machine to toggle states, while an interested party either observes or polls.
|
||||
*/
|
||||
class Keyboard {
|
||||
public:
|
||||
enum class Key {
|
||||
Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PrintScreen, ScrollLock, Pause,
|
||||
BackTick, k1, k2, k3, k4, k5, k6, k7, k8, k9, k0, Hyphen, Equals, Backspace,
|
||||
Tab, Q, W, E, R, T, Y, U, I, O, P, OpenSquareBracket, CloseSquareBracket, Backslash,
|
||||
CapsLock, A, S, D, F, G, H, J, K, L, Semicolon, Quote, Hash, Enter,
|
||||
LeftShift, Z, X, C, V, B, N, M, Comma, FullStop, ForwardSlash, RightShift,
|
||||
LeftControl, LeftOption, LeftMeta, Space, RightMeta, RightOption, RightControl,
|
||||
Left, Right, Up, Down,
|
||||
Insert, Home, PageUp, Delete, End, PageDown,
|
||||
NumLock, KeypadSlash, KeypadAsterisk, KeypadDelete,
|
||||
Keypad7, Keypad8, Keypad9, KeypadPlus,
|
||||
Keypad4, Keypad5, Keypad6, KeypadMinus,
|
||||
Keypad1, Keypad2, Keypad3, KeypadEnter,
|
||||
Keypad0, KeypadDecimalPoint, KeypadEquals,
|
||||
Help,
|
||||
public:
|
||||
enum class Key {
|
||||
Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PrintScreen, ScrollLock, Pause,
|
||||
BackTick, k1, k2, k3, k4, k5, k6, k7, k8, k9, k0, Hyphen, Equals, Backspace,
|
||||
Tab, Q, W, E, R, T, Y, U, I, O, P, OpenSquareBracket, CloseSquareBracket, Backslash,
|
||||
CapsLock, A, S, D, F, G, H, J, K, L, Semicolon, Quote, Hash, Enter,
|
||||
LeftShift, Z, X, C, V, B, N, M, Comma, FullStop, ForwardSlash, RightShift,
|
||||
LeftControl, LeftOption, LeftMeta, Space, RightMeta, RightOption, RightControl,
|
||||
Left, Right, Up, Down,
|
||||
Insert, Home, PageUp, Delete, End, PageDown,
|
||||
NumLock, KeypadSlash, KeypadAsterisk, KeypadDelete,
|
||||
Keypad7, Keypad8, Keypad9, KeypadPlus,
|
||||
Keypad4, Keypad5, Keypad6, KeypadMinus,
|
||||
Keypad1, Keypad2, Keypad3, KeypadEnter,
|
||||
Keypad0, KeypadDecimalPoint, KeypadEquals,
|
||||
Help,
|
||||
|
||||
Max = Help
|
||||
};
|
||||
Max = Help
|
||||
};
|
||||
|
||||
/// Constructs a Keyboard that declares itself to observe all keys.
|
||||
Keyboard(const std::set<Key> &essential_modifiers = {});
|
||||
/// Constructs a Keyboard that declares itself to observe all keys.
|
||||
Keyboard(const std::set<Key> &essential_modifiers = {});
|
||||
|
||||
/// Constructs a Keyboard that declares itself to observe only members of @c observed_keys.
|
||||
Keyboard(const std::set<Key> &observed_keys, const std::set<Key> &essential_modifiers);
|
||||
/// Constructs a Keyboard that declares itself to observe only members of @c observed_keys.
|
||||
Keyboard(const std::set<Key> &observed_keys, const std::set<Key> &essential_modifiers);
|
||||
|
||||
virtual ~Keyboard() = default;
|
||||
virtual ~Keyboard() = default;
|
||||
|
||||
// Host interface.
|
||||
// Host interface.
|
||||
|
||||
/// @returns @c true if the key press affects the machine; @c false otherwise.
|
||||
virtual bool set_key_pressed(Key key, char value, bool is_pressed, bool is_repeat);
|
||||
virtual void reset_all_keys();
|
||||
/// @returns @c true if the key press affects the machine; @c false otherwise.
|
||||
virtual bool set_key_pressed(Key key, char value, bool is_pressed, bool is_repeat);
|
||||
virtual void reset_all_keys();
|
||||
|
||||
/// @returns a set of all Keys that this keyboard responds to.
|
||||
virtual const std::set<Key> &observed_keys() const;
|
||||
/// @returns a set of all Keys that this keyboard responds to.
|
||||
virtual const std::set<Key> &observed_keys() const;
|
||||
|
||||
/// @returns the list of modifiers that this keyboard considers 'essential' (i.e. both mapped and highly used).
|
||||
virtual const std::set<Inputs::Keyboard::Key> &get_essential_modifiers() const;
|
||||
/// @returns the list of modifiers that this keyboard considers 'essential' (i.e. both mapped and highly used).
|
||||
virtual const std::set<Inputs::Keyboard::Key> &get_essential_modifiers() const;
|
||||
|
||||
/*!
|
||||
@returns @c true if this keyboard, on its original machine, looked
|
||||
like a complete keyboard — i.e. if a user would expect this keyboard
|
||||
to be the only thing a real keyboard maps to.
|
||||
/*!
|
||||
@returns @c true if this keyboard, on its original machine, looked
|
||||
like a complete keyboard — i.e. if a user would expect this keyboard
|
||||
to be the only thing a real keyboard maps to.
|
||||
|
||||
So this would be true of something like the Amstrad CPC, which has a full
|
||||
keyboard, but it would be false of something like the Sega Master System
|
||||
which has some buttons that you'd expect an emulator to map to its host
|
||||
keyboard but which does not offer a full keyboard.
|
||||
*/
|
||||
virtual bool is_exclusive() const;
|
||||
So this would be true of something like the Amstrad CPC, which has a full
|
||||
keyboard, but it would be false of something like the Sega Master System
|
||||
which has some buttons that you'd expect an emulator to map to its host
|
||||
keyboard but which does not offer a full keyboard.
|
||||
*/
|
||||
virtual bool is_exclusive() const;
|
||||
|
||||
// Delegate interface.
|
||||
struct Delegate {
|
||||
virtual bool keyboard_did_change_key(Keyboard *keyboard, Key key, bool is_pressed) = 0;
|
||||
virtual void reset_all_keys(Keyboard *keyboard) = 0;
|
||||
};
|
||||
void set_delegate(Delegate *delegate);
|
||||
bool get_key_state(Key key) const;
|
||||
// Delegate interface.
|
||||
struct Delegate {
|
||||
virtual bool keyboard_did_change_key(Keyboard *keyboard, Key key, bool is_pressed) = 0;
|
||||
virtual void reset_all_keys(Keyboard *keyboard) = 0;
|
||||
};
|
||||
void set_delegate(Delegate *);
|
||||
bool get_key_state(Key) const;
|
||||
|
||||
private:
|
||||
std::set<Key> observed_keys_;
|
||||
const std::set<Key> essential_modifiers_;
|
||||
const bool is_exclusive_ = true;
|
||||
private:
|
||||
std::set<Key> observed_keys_;
|
||||
const std::set<Key> essential_modifiers_;
|
||||
const bool is_exclusive_ = true;
|
||||
|
||||
std::vector<bool> key_states_;
|
||||
Delegate *delegate_ = nullptr;
|
||||
std::vector<bool> key_states_;
|
||||
Delegate *delegate_ = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -19,12 +19,12 @@ class Mouse {
|
||||
/*!
|
||||
Indicates a movement of the mouse.
|
||||
*/
|
||||
virtual void move([[maybe_unused]] int x, [[maybe_unused]] int y) {}
|
||||
virtual void move([[maybe_unused]] const int x, [[maybe_unused]] const int y) {}
|
||||
|
||||
/*!
|
||||
@returns the number of buttons on this mouse.
|
||||
*/
|
||||
virtual int get_number_of_buttons() {
|
||||
virtual int get_number_of_buttons() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ class Mouse {
|
||||
The intention is that @c index be semantic, not positional:
|
||||
0 for the primary button, 1 for the secondary, 2 for the tertiary, etc.
|
||||
*/
|
||||
virtual void set_button_pressed([[maybe_unused]] int index, [[maybe_unused]] bool is_pressed) {}
|
||||
virtual void set_button_pressed([[maybe_unused]] const int index, [[maybe_unused]] const bool is_pressed) {}
|
||||
|
||||
/*!
|
||||
Releases all depressed buttons.
|
||||
|
@ -26,95 +26,95 @@ namespace Inputs {
|
||||
channels below. This is intended to be fixed.
|
||||
*/
|
||||
class QuadratureMouse: public Mouse {
|
||||
public:
|
||||
QuadratureMouse(int number_of_buttons) :
|
||||
number_of_buttons_(number_of_buttons) {}
|
||||
public:
|
||||
QuadratureMouse(const int number_of_buttons) :
|
||||
number_of_buttons_(number_of_buttons) {}
|
||||
|
||||
/*
|
||||
Inputs, to satisfy the Mouse interface.
|
||||
*/
|
||||
void move(int x, int y) final {
|
||||
// Accumulate all provided motion.
|
||||
axes_[0] += x;
|
||||
axes_[1] += y;
|
||||
}
|
||||
/*
|
||||
Inputs, to satisfy the Mouse interface.
|
||||
*/
|
||||
void move(const int x, const int y) final {
|
||||
// Accumulate all provided motion.
|
||||
axes_[0] += x;
|
||||
axes_[1] += y;
|
||||
}
|
||||
|
||||
int get_number_of_buttons() final {
|
||||
return number_of_buttons_;
|
||||
}
|
||||
int get_number_of_buttons() const final {
|
||||
return number_of_buttons_;
|
||||
}
|
||||
|
||||
void set_button_pressed(int index, bool is_pressed) final {
|
||||
if(is_pressed)
|
||||
button_flags_ |= (1 << index);
|
||||
else
|
||||
button_flags_ &= ~(1 << index);
|
||||
}
|
||||
void set_button_pressed(const int index, const bool is_pressed) final {
|
||||
if(is_pressed)
|
||||
button_flags_ |= (1 << index);
|
||||
else
|
||||
button_flags_ &= ~(1 << index);
|
||||
}
|
||||
|
||||
void reset_all_buttons() final {
|
||||
button_flags_ = 0;
|
||||
}
|
||||
void reset_all_buttons() final {
|
||||
button_flags_ = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Outputs.
|
||||
*/
|
||||
/*
|
||||
Outputs.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Applies a single step from the current accumulated mouse movement, which
|
||||
might involve the mouse moving right, or left, or not at all.
|
||||
*/
|
||||
void prepare_step() {
|
||||
for(int axis = 0; axis < 2; ++axis) {
|
||||
// Do nothing if there's no motion to communicate.
|
||||
const int axis_value = axes_[axis];
|
||||
if(!axis_value) continue;
|
||||
/*!
|
||||
Applies a single step from the current accumulated mouse movement, which
|
||||
might involve the mouse moving right, or left, or not at all.
|
||||
*/
|
||||
void prepare_step() {
|
||||
for(int axis = 0; axis < 2; ++axis) {
|
||||
// Do nothing if there's no motion to communicate.
|
||||
const int axis_value = axes_[axis];
|
||||
if(!axis_value) continue;
|
||||
|
||||
// Toggle the primary channel and set the secondary for
|
||||
// negative motion. At present the y axis signals the
|
||||
// secondary channel the opposite way around from the
|
||||
// primary.
|
||||
primaries_[axis] ^= 1;
|
||||
secondaries_[axis] = primaries_[axis] ^ axis;
|
||||
if(axis_value > 0) {
|
||||
-- axes_[axis];
|
||||
secondaries_[axis] ^= 1; // Switch to positive motion.
|
||||
} else {
|
||||
++ axes_[axis];
|
||||
}
|
||||
// Toggle the primary channel and set the secondary for
|
||||
// negative motion. At present the y axis signals the
|
||||
// secondary channel the opposite way around from the
|
||||
// primary.
|
||||
primaries_[axis] ^= 1;
|
||||
secondaries_[axis] = primaries_[axis] ^ axis;
|
||||
if(axis_value > 0) {
|
||||
-- axes_[axis];
|
||||
secondaries_[axis] ^= 1; // Switch to positive motion.
|
||||
} else {
|
||||
++ axes_[axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@returns the two quadrature channels — bit 0 is the 'primary' channel
|
||||
(i.e. the one that can be monitored to observe velocity) and
|
||||
bit 1 is the 'secondary' (i.e. that which can be queried to
|
||||
observe direction).
|
||||
*/
|
||||
int get_channel(int axis) {
|
||||
return primaries_[axis] | (secondaries_[axis] << 1);
|
||||
}
|
||||
/*!
|
||||
@returns the two quadrature channels — bit 0 is the 'primary' channel
|
||||
(i.e. the one that can be monitored to observe velocity) and
|
||||
bit 1 is the 'secondary' (i.e. that which can be queried to
|
||||
observe direction).
|
||||
*/
|
||||
int get_channel(int axis) const {
|
||||
return primaries_[axis] | (secondaries_[axis] << 1);
|
||||
}
|
||||
|
||||
/*!
|
||||
@returns a bit mask of the currently pressed buttons.
|
||||
*/
|
||||
int get_button_mask() {
|
||||
return button_flags_;
|
||||
}
|
||||
/*!
|
||||
@returns a bit mask of the currently pressed buttons.
|
||||
*/
|
||||
int get_button_mask() const {
|
||||
return button_flags_;
|
||||
}
|
||||
|
||||
/*!
|
||||
@returns @c true if any mouse motion is waiting to be communicated;
|
||||
@c false otherwise.
|
||||
*/
|
||||
bool has_steps() {
|
||||
return axes_[0] || axes_[1];
|
||||
}
|
||||
/*!
|
||||
@returns @c true if any mouse motion is waiting to be communicated;
|
||||
@c false otherwise.
|
||||
*/
|
||||
bool has_steps() const {
|
||||
return axes_[0] || axes_[1];
|
||||
}
|
||||
|
||||
private:
|
||||
const int number_of_buttons_ = 0;
|
||||
std::atomic<int> button_flags_{0};
|
||||
std::atomic<int> axes_[2]{0, 0};
|
||||
private:
|
||||
const int number_of_buttons_ = 0;
|
||||
std::atomic<int> button_flags_{0};
|
||||
std::atomic<int> axes_[2]{0, 0};
|
||||
|
||||
int primaries_[2] = {0, 0};
|
||||
int secondaries_[2] = {0, 0};
|
||||
int primaries_[2] = {0, 0};
|
||||
int secondaries_[2] = {0, 0};
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -507,7 +507,7 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||
std::unique_ptr<Reflection::Struct> get_options() const final {
|
||||
auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);
|
||||
options->quickload = accelerate_loading_;
|
||||
return options;
|
||||
|
@ -314,7 +314,7 @@ private:
|
||||
keyboard_.mouse_y_ += y;
|
||||
}
|
||||
|
||||
int get_number_of_buttons() override {
|
||||
int get_number_of_buttons() const override {
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
@ -589,7 +589,7 @@ template <bool has_scsi_bus> class ConcreteMachine:
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||
std::unique_ptr<Reflection::Struct> get_options() const final {
|
||||
auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);
|
||||
options->output = get_video_signal_configurable();
|
||||
options->quickload = allow_fast_tape_hack_;
|
||||
|
@ -14,7 +14,7 @@ using namespace Amiga;
|
||||
|
||||
// MARK: - Mouse.
|
||||
|
||||
int Mouse::get_number_of_buttons() {
|
||||
int Mouse::get_number_of_buttons() const {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ class Mouse: public Inputs::Mouse, public MouseJoystickInput {
|
||||
uint8_t get_cia_button() const final;
|
||||
|
||||
private:
|
||||
int get_number_of_buttons() final;
|
||||
int get_number_of_buttons() const final;
|
||||
void set_button_pressed(int, bool) final;
|
||||
void reset_all_buttons() final;
|
||||
void move(int, int) final;
|
||||
|
@ -1187,7 +1187,7 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||
std::unique_ptr<Reflection::Struct> get_options() const final {
|
||||
auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);
|
||||
options->output = get_video_signal_configurable();
|
||||
options->quickload = allow_fast_tape_hack_;
|
||||
|
@ -58,7 +58,7 @@ void Mouse::move(int x, int y) {
|
||||
post_service_request();
|
||||
}
|
||||
|
||||
int Mouse::get_number_of_buttons() {
|
||||
int Mouse::get_number_of_buttons() const {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ class Mouse: public ReactiveDevice, public Inputs::Mouse {
|
||||
void perform_command(const Command &command) override;
|
||||
|
||||
void move(int x, int y) override;
|
||||
int get_number_of_buttons() override;
|
||||
int get_number_of_buttons() const override;
|
||||
void set_button_pressed(int index, bool is_pressed) override;
|
||||
void reset_all_buttons() override;
|
||||
|
||||
|
@ -1043,7 +1043,7 @@ template <Analyser::Static::AppleII::Target::Model model, bool has_mockingboard>
|
||||
}
|
||||
|
||||
// MARK:: Configuration options.
|
||||
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||
std::unique_ptr<Reflection::Struct> get_options() const final {
|
||||
auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);
|
||||
options->output = get_video_signal_configurable();
|
||||
options->use_square_pixels = video_.get_use_square_pixels();
|
||||
|
@ -55,11 +55,10 @@ void VideoBase::set_use_square_pixels(bool use_square_pixels) {
|
||||
crt_.set_aspect_ratio(4.0f / 3.0f);
|
||||
}
|
||||
}
|
||||
bool VideoBase::get_use_square_pixels() {
|
||||
bool VideoBase::get_use_square_pixels() const {
|
||||
return use_square_pixels_;
|
||||
}
|
||||
|
||||
|
||||
void VideoBase::set_scan_target(Outputs::Display::ScanTarget *scan_target) {
|
||||
crt_.set_scan_target(scan_target);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ class VideoBase: public VideoSwitches<Cycles> {
|
||||
/// Sets whether the current CRT should be recalibrated away from normative NTSC
|
||||
/// to produce square pixels in 40-column text mode.
|
||||
void set_use_square_pixels(bool);
|
||||
bool get_use_square_pixels();
|
||||
bool get_use_square_pixels() const;
|
||||
|
||||
protected:
|
||||
Outputs::CRT::CRT crt_;
|
||||
|
@ -502,7 +502,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||
std::unique_ptr<Reflection::Struct> get_options() const final {
|
||||
auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);
|
||||
options->quickboot = quickboot_;
|
||||
return options;
|
||||
|
@ -692,7 +692,7 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||
std::unique_ptr<Reflection::Struct> get_options() const final {
|
||||
auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);
|
||||
options->output = get_video_signal_configurable();
|
||||
return options;
|
||||
|
@ -427,7 +427,7 @@ void IntelligentKeyboard::move(int x, int y) {
|
||||
mouse_movement_[1] += y;
|
||||
}
|
||||
|
||||
int IntelligentKeyboard::get_number_of_buttons() {
|
||||
int IntelligentKeyboard::get_number_of_buttons() const {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ class IntelligentKeyboard:
|
||||
|
||||
// Inputs::Mouse.
|
||||
void move(int x, int y) final;
|
||||
int get_number_of_buttons() final;
|
||||
int get_number_of_buttons() const final;
|
||||
void set_button_pressed(int index, bool is_pressed) final;
|
||||
void reset_all_buttons() final;
|
||||
|
||||
|
@ -357,7 +357,7 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||
std::unique_ptr<Reflection::Struct> get_options() const final {
|
||||
auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);
|
||||
options->output = get_video_signal_configurable();
|
||||
return options;
|
||||
|
@ -678,7 +678,7 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||
std::unique_ptr<Reflection::Struct> get_options() const final {
|
||||
auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);
|
||||
options->output = get_video_signal_configurable();
|
||||
options->quickload = allow_fast_tape_hack_;
|
||||
|
@ -734,7 +734,7 @@ template <bool has_disk_controller, bool is_6mhz> class ConcreteMachine:
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||