diff --git a/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.cpp b/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.cpp
index 3556719b1..f0dc5c2ed 100644
--- a/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.cpp
+++ b/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.cpp
@@ -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_);
 }
diff --git a/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.hpp b/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.hpp
index 07da52d3d..47b10cf17 100644
--- a/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.hpp
+++ b/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.hpp
@@ -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_;
diff --git a/Concurrency/AsyncTaskQueue.hpp b/Concurrency/AsyncTaskQueue.hpp
index 594438446..6e1b82b50 100644
--- a/Concurrency/AsyncTaskQueue.hpp
+++ b/Concurrency/AsyncTaskQueue.hpp
@@ -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_;
 };
 
 }
diff --git a/Configurable/Configurable.hpp b/Configurable/Configurable.hpp
index de543931b..0144d34c3 100644
--- a/Configurable/Configurable.hpp
+++ b/Configurable/Configurable.hpp
@@ -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;
 };
 
 /*!
diff --git a/Configurable/StandardOptions.hpp b/Configurable/StandardOptions.hpp
index 0cc911644..c57513718 100644
--- a/Configurable/StandardOptions.hpp
+++ b/Configurable/StandardOptions.hpp
@@ -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");
+	}
 };
 
 }
diff --git a/Inputs/Joystick.hpp b/Inputs/Joystick.hpp
index 064baf092..31150b7b7 100644
--- a/Inputs/Joystick.hpp
+++ b/Inputs/Joystick.hpp
@@ -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_;
 };
 
 }
diff --git a/Inputs/Keyboard.cpp b/Inputs/Keyboard.cpp
index 7abdb87e5..8825baba9 100644
--- a/Inputs/Keyboard.cpp
+++ b/Inputs/Keyboard.cpp
@@ -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;
 }
 
diff --git a/Inputs/Keyboard.hpp b/Inputs/Keyboard.hpp
index ad00c1b05..230d710f0 100644
--- a/Inputs/Keyboard.hpp
+++ b/Inputs/Keyboard.hpp
@@ -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;
 };
 
 }
diff --git a/Inputs/Mouse.hpp b/Inputs/Mouse.hpp
index 9772abfd3..6bad55950 100644
--- a/Inputs/Mouse.hpp
+++ b/Inputs/Mouse.hpp
@@ -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.
diff --git a/Inputs/QuadratureMouse/QuadratureMouse.hpp b/Inputs/QuadratureMouse/QuadratureMouse.hpp
index 78d52420d..ce2edf883 100644
--- a/Inputs/QuadratureMouse/QuadratureMouse.hpp
+++ b/Inputs/QuadratureMouse/QuadratureMouse.hpp
@@ -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};
 };
 
 }
diff --git a/Machines/Acorn/Archimedes/Archimedes.cpp b/Machines/Acorn/Archimedes/Archimedes.cpp
index e87b203dd..5a29ae891 100644
--- a/Machines/Acorn/Archimedes/Archimedes.cpp
+++ b/Machines/Acorn/Archimedes/Archimedes.cpp
@@ -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;
diff --git a/Machines/Acorn/Archimedes/Keyboard.hpp b/Machines/Acorn/Archimedes/Keyboard.hpp
index 617c87a65..81a356117 100644
--- a/Machines/Acorn/Archimedes/Keyboard.hpp
+++ b/Machines/Acorn/Archimedes/Keyboard.hpp
@@ -314,7 +314,7 @@ private:
 			keyboard_.mouse_y_ += y;
 		}
 
-		int get_number_of_buttons() override {
+		int get_number_of_buttons() const override {
 			return 3;
 		}
 
diff --git a/Machines/Acorn/Electron/Electron.cpp b/Machines/Acorn/Electron/Electron.cpp
index ab19216bf..eb1b7de4e 100644
--- a/Machines/Acorn/Electron/Electron.cpp
+++ b/Machines/Acorn/Electron/Electron.cpp
@@ -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_;
diff --git a/Machines/Amiga/MouseJoystick.cpp b/Machines/Amiga/MouseJoystick.cpp
index 7659fc7a7..c1a24aafd 100644
--- a/Machines/Amiga/MouseJoystick.cpp
+++ b/Machines/Amiga/MouseJoystick.cpp
@@ -14,7 +14,7 @@ using namespace Amiga;
 
 // MARK: - Mouse.
 
-int Mouse::get_number_of_buttons() {
+int Mouse::get_number_of_buttons() const {
 	return 2;
 }
 
diff --git a/Machines/Amiga/MouseJoystick.hpp b/Machines/Amiga/MouseJoystick.hpp
index 3289c3764..fa667c505 100644
--- a/Machines/Amiga/MouseJoystick.hpp
+++ b/Machines/Amiga/MouseJoystick.hpp
@@ -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;
diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp
index 85fba8015..17328b5d8 100644
--- a/Machines/AmstradCPC/AmstradCPC.cpp
+++ b/Machines/AmstradCPC/AmstradCPC.cpp
@@ -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_;
diff --git a/Machines/Apple/ADB/Mouse.cpp b/Machines/Apple/ADB/Mouse.cpp
index a2f9657fb..d7f431308 100644
--- a/Machines/Apple/ADB/Mouse.cpp
+++ b/Machines/Apple/ADB/Mouse.cpp
@@ -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;
 }
 
diff --git a/Machines/Apple/ADB/Mouse.hpp b/Machines/Apple/ADB/Mouse.hpp
index 2835552d5..b7e776b80 100644
--- a/Machines/Apple/ADB/Mouse.hpp
+++ b/Machines/Apple/ADB/Mouse.hpp
@@ -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;
 
diff --git a/Machines/Apple/AppleII/AppleII.cpp b/Machines/Apple/AppleII/AppleII.cpp
index f8fc8305f..94642f8e1 100644
--- a/Machines/Apple/AppleII/AppleII.cpp
+++ b/Machines/Apple/AppleII/AppleII.cpp
@@ -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();
diff --git a/Machines/Apple/AppleII/Video.cpp b/Machines/Apple/AppleII/Video.cpp
index 6ed67553c..93f0ba45c 100644
--- a/Machines/Apple/AppleII/Video.cpp
+++ b/Machines/Apple/AppleII/Video.cpp
@@ -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);
 }
diff --git a/Machines/Apple/AppleII/Video.hpp b/Machines/Apple/AppleII/Video.hpp
index fe6ce1504..f0a8e9055 100644
--- a/Machines/Apple/AppleII/Video.hpp
+++ b/Machines/Apple/AppleII/Video.hpp
@@ -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_;
diff --git a/Machines/Apple/Macintosh/Macintosh.cpp b/Machines/Apple/Macintosh/Macintosh.cpp
index cf1f65981..e7c271408 100644
--- a/Machines/Apple/Macintosh/Macintosh.cpp
+++ b/Machines/Apple/Macintosh/Macintosh.cpp
@@ -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;
diff --git a/Machines/Atari/ST/AtariST.cpp b/Machines/Atari/ST/AtariST.cpp
index 7c39e28bc..c853acec6 100644
--- a/Machines/Atari/ST/AtariST.cpp
+++ b/Machines/Atari/ST/AtariST.cpp
@@ -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;
diff --git a/Machines/Atari/ST/IntelligentKeyboard.cpp b/Machines/Atari/ST/IntelligentKeyboard.cpp
index 1888bc550..5f4e6607c 100644
--- a/Machines/Atari/ST/IntelligentKeyboard.cpp
+++ b/Machines/Atari/ST/IntelligentKeyboard.cpp
@@ -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;
 }
 
diff --git a/Machines/Atari/ST/IntelligentKeyboard.hpp b/Machines/Atari/ST/IntelligentKeyboard.hpp
index 440590229..54f9306ee 100644
--- a/Machines/Atari/ST/IntelligentKeyboard.hpp
+++ b/Machines/Atari/ST/IntelligentKeyboard.hpp
@@ -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;
 
diff --git a/Machines/ColecoVision/ColecoVision.cpp b/Machines/ColecoVision/ColecoVision.cpp
index 730624697..e45515a62 100644
--- a/Machines/ColecoVision/ColecoVision.cpp
+++ b/Machines/ColecoVision/ColecoVision.cpp
@@ -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;
diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp
index 181eb8cc9..54ea08660 100644
--- a/Machines/Commodore/Vic-20/Vic20.cpp
+++ b/Machines/Commodore/Vic-20/Vic20.cpp
@@ -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_;
diff --git a/Machines/Enterprise/Enterprise.cpp b/Machines/Enterprise/Enterprise.cpp
index 485889796..325559d30 100644
--- a/Machines/Enterprise/Enterprise.cpp
+++ b/Machines/Enterprise/Enterprise.cpp
@@ -734,7 +734,7 @@ template <bool has_disk_controller, bool is_6mhz> 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;
diff --git a/Machines/MSX/MSX.cpp b/Machines/MSX/MSX.cpp
index 66dae2aa4..8a668d8c0 100644
--- a/Machines/MSX/MSX.cpp
+++ b/Machines/MSX/MSX.cpp
@@ -812,7 +812,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_;
diff --git a/Machines/MasterSystem/MasterSystem.cpp b/Machines/MasterSystem/MasterSystem.cpp
index 40ffef60c..c8eccfbf0 100644
--- a/Machines/MasterSystem/MasterSystem.cpp
+++ b/Machines/MasterSystem/MasterSystem.cpp
@@ -421,7 +421,7 @@ template <Analyser::Static::Sega::Target::Model model> 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;
diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp
index f10a4e884..eab424a5d 100644
--- a/Machines/Oric/Oric.cpp
+++ b/Machines/Oric/Oric.cpp
@@ -677,7 +677,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
 		}
 
 		// 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 = use_fast_tape_hack_;
diff --git a/Machines/PCCompatible/PCCompatible.cpp b/Machines/PCCompatible/PCCompatible.cpp
index c0f17eb3f..f1b629e70 100644
--- a/Machines/PCCompatible/PCCompatible.cpp
+++ b/Machines/PCCompatible/PCCompatible.cpp
@@ -1118,7 +1118,7 @@ class ConcreteMachine:
 		}
 
 		// MARK: - Configuration options.
-		std::unique_ptr<Reflection::Struct> get_options() override {
+		std::unique_ptr<Reflection::Struct> get_options() const override {
 			auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);
 			options->output = get_video_signal_configurable();
 			return options;
diff --git a/Machines/Sinclair/ZX8081/ZX8081.cpp b/Machines/Sinclair/ZX8081/ZX8081.cpp
index 1186c20b7..45a823c76 100644
--- a/Machines/Sinclair/ZX8081/ZX8081.cpp
+++ b/Machines/Sinclair/ZX8081/ZX8081.cpp
@@ -383,7 +383,7 @@ template<bool is_zx81> 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);	// OptionsType is arbitrary, but not optional.
 			options->automatic_tape_motor_control = use_automatic_tape_motor_control_;
 			options->quickload = allow_fast_tape_hack_;
diff --git a/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp b/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp
index fae483b58..a94b715f0 100644
--- a/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp
+++ b/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp
@@ -721,7 +721,7 @@ template<Model model> class ConcreteMachine:
 
 		// MARK: - Configuration options.
 
-		std::unique_ptr<Reflection::Struct> get_options() override {
+		std::unique_ptr<Reflection::Struct> get_options() const override {
 			auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);	// OptionsType is arbitrary, but not optional.
 			options->automatic_tape_motor_control = use_automatic_tape_motor_control_;
 			options->quickload = allow_fast_tape_hack_;