From 274867579bf612560f43661cda46eeccff848ab3 Mon Sep 17 00:00:00 2001
From: Thomas Harte <thomas.harte@gmail.com>
Date: Sun, 22 Dec 2019 00:22:17 -0500
Subject: [PATCH] Deploys `constexpr` as a stricter `const`.

---
 Components/6850/6850.hpp                      |  2 +-
 Components/68901/MFP68901.cpp                 |  2 +-
 Components/68901/MFP68901.hpp                 |  2 +-
 Components/8272/i8272.cpp                     |  2 +-
 Components/9918/9918.cpp                      | 18 +++++------
 Components/AY38910/AY38910.cpp                |  4 +--
 Components/DiskII/DiskII.hpp                  |  2 +-
 Components/DiskII/IWM.cpp                     | 18 +++++------
 Machines/AmstradCPC/AmstradCPC.cpp            |  2 +-
 Machines/Apple/AppleII/AppleII.cpp            |  4 +--
 Machines/Apple/AppleII/Video.hpp              |  8 ++---
 Machines/Apple/Macintosh/Keyboard.hpp         |  2 +-
 Machines/Apple/Macintosh/Macintosh.cpp        |  2 +-
 Machines/Apple/Macintosh/Video.hpp            | 10 +++---
 Machines/Atari/2600/TIA.cpp                   |  8 ++---
 Machines/Atari/2600/TIASound.hpp              |  2 +-
 Machines/Atari/ST/AtariST.cpp                 |  2 +-
 Machines/Atari/ST/Video.cpp                   |  4 +--
 Machines/ColecoVision/ColecoVision.cpp        |  2 +-
 Machines/Electron/SoundGenerator.hpp          |  2 +-
 Machines/Electron/Video.cpp                   | 32 +++++++++----------
 Machines/MasterSystem/MasterSystem.cpp        |  2 +-
 OSBindings/SDL/main.cpp                       |  4 +--
 Outputs/CRT/CRT.cpp                           | 16 +++++-----
 Processors/68000/68000.hpp                    | 22 ++++++-------
 .../68000/Implementation/68000Storage.hpp     |  4 +--
 Storage/Disk/DiskImage/Formats/AcornADF.cpp   |  4 +--
 Storage/Disk/DiskImage/Formats/AppleDSK.cpp   |  4 +--
 Storage/Disk/DiskImage/Formats/MSXDSK.cpp     |  6 ++--
 Storage/Disk/DiskImage/Formats/SSD.cpp        |  4 +--
 Storage/Disk/DiskImage/Formats/ST.cpp         |  4 +--
 Storage/Disk/Drive.cpp                        |  4 +--
 Storage/MassStorage/SCSI/SCSI.hpp             |  2 +-
 Storage/Tape/Formats/TapePRG.cpp              | 16 +++++-----
 Storage/Tape/Parsers/Acorn.cpp                |  2 +-
 Storage/Tape/Parsers/MSX.cpp                  |  8 ++---
 Storage/Tape/Parsers/ZX8081.cpp               |  6 ++--
 37 files changed, 119 insertions(+), 119 deletions(-)

diff --git a/Components/6850/6850.hpp b/Components/6850/6850.hpp
index 6f3734cd6..0e9c91152 100644
--- a/Components/6850/6850.hpp
+++ b/Components/6850/6850.hpp
@@ -100,7 +100,7 @@ class ACIA: public ClockingHint::Source, private Serial::Line::ReadDelegate {
 		} parity_ = Parity::None;
 		int data_bits_ = 7, stop_bits_ = 2;
 
-		static const int NoValueMask = 0x100;
+		static constexpr int NoValueMask = 0x100;
 		int next_transmission_ = NoValueMask;
 		int received_data_ = NoValueMask;
 
diff --git a/Components/68901/MFP68901.cpp b/Components/68901/MFP68901.cpp
index 95c2a1992..d22b59792 100644
--- a/Components/68901/MFP68901.cpp
+++ b/Components/68901/MFP68901.cpp
@@ -110,7 +110,7 @@ void MFP68901::write(int address, uint8_t value) {
 		return;
 	}
 
-	const int timer_prescales[] = {
+	constexpr int timer_prescales[] = {
 		1, 4, 10, 16, 50, 64, 100, 200
 	};
 
diff --git a/Components/68901/MFP68901.hpp b/Components/68901/MFP68901.hpp
index 974e195e7..25cc88cc4 100644
--- a/Components/68901/MFP68901.hpp
+++ b/Components/68901/MFP68901.hpp
@@ -61,7 +61,7 @@ class MFP68901: public ClockingHint::Source {
 		/// @returns @c true if the interrupt output is currently active; @c false otherwise.s
 		bool get_interrupt_line();
 
-		static const int NoAcknowledgement = 0x100;
+		static constexpr int NoAcknowledgement = 0x100;
 
 		/// Communicates an interrupt acknowledge cycle.
 		///
diff --git a/Components/8272/i8272.cpp b/Components/8272/i8272.cpp
index 10598525c..df5d54622 100644
--- a/Components/8272/i8272.cpp
+++ b/Components/8272/i8272.cpp
@@ -292,7 +292,7 @@ void i8272::posit_event(int event_type) {
 			WAIT_FOR_EVENT(Event8272::CommandByte)
 			SetBusy();
 
-			static const std::size_t required_lengths[32] = {
+			static constexpr std::size_t required_lengths[32] = {
 				0,	0,	9,	3,	2,	9,	9,	2,
 				1,	9,	2,	0,	9,	6,	0,	3,
 				0,	9,	0,	0,	0,	0,	0,	0,
diff --git a/Components/9918/9918.cpp b/Components/9918/9918.cpp
index f5df4eecb..3556b18c3 100644
--- a/Components/9918/9918.cpp
+++ b/Components/9918/9918.cpp
@@ -17,16 +17,16 @@ using namespace TI::TMS;
 
 namespace {
 
-const uint8_t StatusInterrupt = 0x80;
-const uint8_t StatusSpriteOverflow = 0x40;
+constexpr uint8_t StatusInterrupt = 0x80;
+constexpr uint8_t StatusSpriteOverflow = 0x40;
 
-const int StatusSpriteCollisionShift = 5;
-const uint8_t StatusSpriteCollision = 0x20;
+constexpr int StatusSpriteCollisionShift = 5;
+constexpr uint8_t StatusSpriteCollision = 0x20;
 
 // 342 internal cycles are 228/227.5ths of a line, so 341.25 cycles should be a whole
 // line. Therefore multiply everything by four, but set line length to 1365 rather than 342*4 = 1368.
-const unsigned int CRTCyclesPerLine = 1365;
-const unsigned int CRTCyclesDivider = 4;
+constexpr unsigned int CRTCyclesPerLine = 1365;
+constexpr unsigned int CRTCyclesDivider = 4;
 
 struct ReverseTable {
 	std::uint8_t map[256];
@@ -624,7 +624,7 @@ void TMS9918::set_register(int address, uint8_t value) {
 
 uint8_t TMS9918::get_current_line() {
 	// Determine the row to return.
-	static const int row_change_position = 63;	// This is the proper Master System value; substitute if any other VDPs turn out to have this functionality.
+	constexpr int row_change_position = 63;	// This is the proper Master System value; substitute if any other VDPs turn out to have this functionality.
 	int source_row =
 		(write_pointer_.column < row_change_position)
 			? (write_pointer_.row + mode_timing_.total_lines - 1)%mode_timing_.total_lines
@@ -829,8 +829,8 @@ void Base::draw_tms_character(int start, int end) {
 		int sprite_collision = 0;
 		memset(&sprite_buffer[start], 0, size_t(end - start)*sizeof(sprite_buffer[0]));
 
-		static const uint32_t sprite_colour_selection_masks[2] = {0x00000000, 0xffffffff};
-		static const int colour_masks[16] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+		constexpr uint32_t sprite_colour_selection_masks[2] = {0x00000000, 0xffffffff};
+		constexpr int colour_masks[16] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
 
 		// Draw all sprites into the sprite buffer.
 		const int shifter_target = sprites_16x16_ ? 32 : 16;
diff --git a/Components/AY38910/AY38910.cpp b/Components/AY38910/AY38910.cpp
index 30e5ddc46..5ed753bf5 100644
--- a/Components/AY38910/AY38910.cpp
+++ b/Components/AY38910/AY38910.cpp
@@ -72,8 +72,8 @@ AY38910::AY38910(Personality personality, Concurrency::DeferringAsyncTaskQueue &
 
 void AY38910::set_sample_volume_range(std::int16_t range) {
 	// set up volume lookup table
-	const float max_volume = static_cast<float>(range) / 3.0f;	// As there are three channels.
-	const float root_two = sqrtf(2.0f);
+	const float max_volume = float(range) / 3.0f;	// As there are three channels.
+	constexpr float root_two = 1.414213562373095f;
 	for(int v = 0; v < 32; v++) {
 		volumes_[v] = int(max_volume / powf(root_two, float(v ^ 0x1f) / 2.0f));
 	}
diff --git a/Components/DiskII/DiskII.hpp b/Components/DiskII/DiskII.hpp
index 13b44e4e9..edc1d0789 100644
--- a/Components/DiskII/DiskII.hpp
+++ b/Components/DiskII/DiskII.hpp
@@ -48,7 +48,7 @@ class DiskII final:
 			The value returned by @c read_address if accessing that address
 			didn't cause the disk II to place anything onto the bus.
 		*/
-		const int DidNotLoad = -1;
+		static constexpr int DidNotLoad = -1;
 
 		/// Advances the controller by @c cycles.
 		void run_for(const Cycles cycles);
diff --git a/Components/DiskII/IWM.cpp b/Components/DiskII/IWM.cpp
index b8b2d20e0..3a21a8fab 100644
--- a/Components/DiskII/IWM.cpp
+++ b/Components/DiskII/IWM.cpp
@@ -13,15 +13,15 @@
 using namespace Apple;
 
 namespace  {
-	const int CA0		= 1 << 0;
-	const int CA1		= 1 << 1;
-	const int CA2		= 1 << 2;
-	const int LSTRB		= 1 << 3;
-	const int ENABLE	= 1 << 4;
-	const int DRIVESEL	= 1 << 5;	/* This means drive select, like on the original Disk II. */
-	const int Q6		= 1 << 6;
-	const int Q7		= 1 << 7;
-	const int SEL		= 1 << 8;	/* This is an additional input, not available on a Disk II, with a confusingly-similar name to SELECT but a distinct purpose. */
+	constexpr int CA0		= 1 << 0;
+	constexpr int CA1		= 1 << 1;
+	constexpr int CA2		= 1 << 2;
+	constexpr int LSTRB		= 1 << 3;
+	constexpr int ENABLE	= 1 << 4;
+	constexpr int DRIVESEL	= 1 << 5;	/* This means drive select, like on the original Disk II. */
+	constexpr int Q6		= 1 << 6;
+	constexpr int Q7		= 1 << 7;
+	constexpr int SEL		= 1 << 8;	/* This is an additional input, not available on a Disk II, with a confusingly-similar name to SELECT but a distinct purpose. */
 }
 
 IWM::IWM(int clock_rate) :
diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp
index 3b707348e..870efb114 100644
--- a/Machines/AmstradCPC/AmstradCPC.cpp
+++ b/Machines/AmstradCPC/AmstradCPC.cpp
@@ -509,7 +509,7 @@ class CRTCBusHandler {
 
 		uint8_t mapped_palette_value(uint8_t colour) {
 #define COL(r, g, b) (r << 4) | (g << 2) | b
-			static const uint8_t mapping[32] = {
+			constexpr uint8_t mapping[32] = {
 				COL(1, 1, 1),	COL(1, 1, 1),	COL(0, 2, 1),	COL(2, 2, 1),
 				COL(0, 0, 1),	COL(2, 0, 1),	COL(0, 1, 1),	COL(2, 1, 1),
 				COL(2, 0, 1),	COL(2, 2, 1),	COL(2, 2, 0),	COL(2, 2, 2),
diff --git a/Machines/Apple/AppleII/AppleII.cpp b/Machines/Apple/AppleII/AppleII.cpp
index f561059ca..5c635935a 100644
--- a/Machines/Apple/AppleII/AppleII.cpp
+++ b/Machines/Apple/AppleII/AppleII.cpp
@@ -79,7 +79,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
 		void update_video() {
 			video_.run_for(cycles_since_video_update_.flush<Cycles>());
 		}
-		static const int audio_divider = 8;
+		static constexpr int audio_divider = 8;
 		void update_audio() {
 			speaker_.run_for(audio_queue_, cycles_since_audio_update_.divide(Cycles(audio_divider)));
 		}
@@ -329,7 +329,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
 			audio_toggle_(audio_queue_),
 			speaker_(audio_toggle_) {
 			// The system's master clock rate.
-			const float master_clock = 14318180.0;
+			constexpr float master_clock = 14318180.0;
 
 			// This is where things get slightly convoluted: establish the machine as having a clock rate
 			// equal to the number of cycles of work the 6502 will actually achieve. Which is less than
diff --git a/Machines/Apple/AppleII/Video.hpp b/Machines/Apple/AppleII/Video.hpp
index 4a1356de8..ac7e4ab70 100644
--- a/Machines/Apple/AppleII/Video.hpp
+++ b/Machines/Apple/AppleII/Video.hpp
@@ -203,7 +203,7 @@ class VideoBase {
 		std::array<uint8_t, 40> auxiliary_stream_;
 
 		bool is_iie_ = false;
-		static const int flash_length = 8406;
+		static constexpr int flash_length = 8406;
 
 		// Describes the current text mode mapping from in-memory character index
 		// to output character.
@@ -339,9 +339,9 @@ template <class BusHandler, bool is_iie> class Video: public VideoBase {
 
 				A frame is oriented around 65 cycles across, 262 lines down.
 			*/
-			static const int first_sync_line = 220;		// A complete guess. Information needed.
-			static const int first_sync_column = 49;	// Also a guess.
-			static const int sync_length = 4;			// One of the two likely candidates.
+			constexpr int first_sync_line = 220;		// A complete guess. Information needed.
+			constexpr int first_sync_column = 49;	// Also a guess.
+			constexpr int sync_length = 4;			// One of the two likely candidates.
 
 			int int_cycles = int(cycles.as_integral());
 			while(int_cycles) {
diff --git a/Machines/Apple/Macintosh/Keyboard.hpp b/Machines/Apple/Macintosh/Keyboard.hpp
index 65c043268..2caf4bbd0 100644
--- a/Machines/Apple/Macintosh/Keyboard.hpp
+++ b/Machines/Apple/Macintosh/Keyboard.hpp
@@ -18,7 +18,7 @@
 namespace Apple {
 namespace Macintosh {
 
-static const uint16_t KeypadMask = 0x100;
+static constexpr uint16_t KeypadMask = 0x100;
 
 /*!
 	Defines the keycodes that could be passed directly to a Macintosh via set_key_pressed.
diff --git a/Machines/Apple/Macintosh/Macintosh.cpp b/Machines/Apple/Macintosh/Macintosh.cpp
index 5b8a82663..0f71be531 100644
--- a/Machines/Apple/Macintosh/Macintosh.cpp
+++ b/Machines/Apple/Macintosh/Macintosh.cpp
@@ -49,7 +49,7 @@
 
 namespace {
 
-const int CLOCK_RATE = 7833600;
+constexpr int CLOCK_RATE = 7833600;
 
 }
 
diff --git a/Machines/Apple/Macintosh/Video.hpp b/Machines/Apple/Macintosh/Video.hpp
index 5836816ad..3c52289ed 100644
--- a/Machines/Apple/Macintosh/Video.hpp
+++ b/Machines/Apple/Macintosh/Video.hpp
@@ -17,11 +17,11 @@
 namespace Apple {
 namespace Macintosh {
 
-static const HalfCycles line_length(704);
-static const int number_of_lines = 370;
-static const HalfCycles frame_length(line_length * HalfCycles(number_of_lines));
-static const int sync_start = 36;
-static const int sync_end = 38;
+static constexpr HalfCycles line_length(704);
+static constexpr int number_of_lines = 370;
+static constexpr HalfCycles frame_length(line_length * HalfCycles(number_of_lines));
+static constexpr int sync_start = 36;
+static constexpr int sync_end = 38;
 
 /*!
 	Models the 68000-era Macintosh video hardware, producing a 512x348 pixel image,
diff --git a/Machines/Atari/2600/TIA.cpp b/Machines/Atari/2600/TIA.cpp
index a7d73a0d8..64a4603d2 100644
--- a/Machines/Atari/2600/TIA.cpp
+++ b/Machines/Atari/2600/TIA.cpp
@@ -13,11 +13,11 @@
 
 using namespace Atari2600;
 namespace {
-	const int cycles_per_line = 228;
-	const int first_pixel_cycle = 68;
+	constexpr int cycles_per_line = 228;
+	constexpr int first_pixel_cycle = 68;
 
-	const int sync_flag	= 0x1;
-	const int blank_flag = 0x2;
+	constexpr int sync_flag	= 0x1;
+	constexpr int blank_flag = 0x2;
 
 	uint8_t reverse_table[256];
 }
diff --git a/Machines/Atari/2600/TIASound.hpp b/Machines/Atari/2600/TIASound.hpp
index c29f50411..ec41e40de 100644
--- a/Machines/Atari/2600/TIASound.hpp
+++ b/Machines/Atari/2600/TIASound.hpp
@@ -16,7 +16,7 @@ namespace Atari2600 {
 
 // This should be a divisor of 38; audio counters are updated every 38 cycles, though lesser dividers
 // will give greater resolution to changes in audio state. 1, 2 and 19 are the only divisors of 38.
-const int CPUTicksPerAudioTick = 2;
+constexpr int CPUTicksPerAudioTick = 2;
 
 class TIASound: public Outputs::Speaker::SampleSource {
 	public:
diff --git a/Machines/Atari/ST/AtariST.cpp b/Machines/Atari/ST/AtariST.cpp
index 9d2c00a85..52c66b41c 100644
--- a/Machines/Atari/ST/AtariST.cpp
+++ b/Machines/Atari/ST/AtariST.cpp
@@ -47,7 +47,7 @@ std::vector<std::unique_ptr<Configurable::Option>> get_options() {
 	);
 }
 
-const int CLOCK_RATE = 8021247;
+constexpr int CLOCK_RATE = 8021247;
 
 using Target = Analyser::Static::Target;
 class ConcreteMachine:
diff --git a/Machines/Atari/ST/Video.cpp b/Machines/Atari/ST/Video.cpp
index b321e01fe..97ccbd842 100644
--- a/Machines/Atari/ST/Video.cpp
+++ b/Machines/Atari/ST/Video.cpp
@@ -626,9 +626,9 @@ void Video::Shifter::output_pixels(int duration, OutputBpp bpp) {
 		} break;
 		case OutputBpp::Two: {
 	#if TARGET_RT_BIG_ENDIAN
-			const int upper = 0;
+			constexpr int upper = 0;
 	#else
-			const int upper = 1;
+			constexpr int upper = 1;
 	#endif
 			if(pixel_buffer_) {
 				while(duration--) {
diff --git a/Machines/ColecoVision/ColecoVision.cpp b/Machines/ColecoVision/ColecoVision.cpp
index 965cc7604..1ed351b38 100644
--- a/Machines/ColecoVision/ColecoVision.cpp
+++ b/Machines/ColecoVision/ColecoVision.cpp
@@ -27,7 +27,7 @@
 #include "../../Analyser/Dynamic/ConfidenceCounter.hpp"
 
 namespace {
-const int sn76489_divider = 2;
+constexpr int sn76489_divider = 2;
 }
 
 namespace Coleco {
diff --git a/Machines/Electron/SoundGenerator.hpp b/Machines/Electron/SoundGenerator.hpp
index 6a4a1308f..9df5769da 100644
--- a/Machines/Electron/SoundGenerator.hpp
+++ b/Machines/Electron/SoundGenerator.hpp
@@ -22,7 +22,7 @@ class SoundGenerator: public ::Outputs::Speaker::SampleSource {
 
 		void set_is_enabled(bool is_enabled);
 
-		static const unsigned int clock_rate_divider = 8;
+		static constexpr unsigned int clock_rate_divider = 8;
 
 		// To satisfy ::SampleSource.
 		void get_samples(std::size_t number_of_samples, int16_t *target);
diff --git a/Machines/Electron/Video.cpp b/Machines/Electron/Video.cpp
index 9b7ac2f1c..97aeb31ec 100644
--- a/Machines/Electron/Video.cpp
+++ b/Machines/Electron/Video.cpp
@@ -16,24 +16,24 @@ using namespace Electron;
 #define graphics_column(v)	((((v) & 127) - first_graphics_cycle + 128) & 127)
 
 namespace {
-	static const int cycles_per_line = 128;
-	static const int lines_per_frame = 625;
-	static const int cycles_per_frame = lines_per_frame * cycles_per_line;
-	static const int crt_cycles_multiplier = 8;
-	static const int crt_cycles_per_line = crt_cycles_multiplier * cycles_per_line;
+	static constexpr int cycles_per_line = 128;
+	static constexpr int lines_per_frame = 625;
+	static constexpr int cycles_per_frame = lines_per_frame * cycles_per_line;
+	static constexpr int crt_cycles_multiplier = 8;
+	static constexpr int crt_cycles_per_line = crt_cycles_multiplier * cycles_per_line;
 
-	static const int field_divider_line = 312;	// i.e. the line, simultaneous with which, the first field's sync ends. So if
-												// the first line with pixels in field 1 is the 20th in the frame, the first line
-												// with pixels in field 2 will be 20+field_divider_line
-	static const int first_graphics_line = 31;
-	static const int first_graphics_cycle = 33;
+	static constexpr int field_divider_line = 312;	// i.e. the line, simultaneous with which, the first field's sync ends. So if
+													// the first line with pixels in field 1 is the 20th in the frame, the first line
+													// with pixels in field 2 will be 20+field_divider_line
+	static constexpr int first_graphics_line = 31;
+	static constexpr int first_graphics_cycle = 33;
 
-	static const int display_end_interrupt_line = 256;
+	static constexpr int display_end_interrupt_line = 256;
 
-	static const int real_time_clock_interrupt_1 = 16704;
-	static const int real_time_clock_interrupt_2 = 56704;
-	static const int display_end_interrupt_1 = (first_graphics_line + display_end_interrupt_line)*cycles_per_line;
-	static const int display_end_interrupt_2 = (first_graphics_line + field_divider_line + display_end_interrupt_line)*cycles_per_line;
+	static constexpr int real_time_clock_interrupt_1 = 16704;
+	static constexpr int real_time_clock_interrupt_2 = 56704;
+	static constexpr int display_end_interrupt_1 = (first_graphics_line + display_end_interrupt_line)*cycles_per_line;
+	static constexpr int display_end_interrupt_2 = (first_graphics_line + field_divider_line + display_end_interrupt_line)*cycles_per_line;
 }
 
 // MARK: - Lifecycle
@@ -272,7 +272,7 @@ void VideoOutput::set_register(int address, uint8_t value) {
 		break;
 		case 0x08: case 0x09: case 0x0a: case 0x0b:
 		case 0x0c: case 0x0d: case 0x0e: case 0x0f: {
-			static const int registers[4][4] = {
+			constexpr int registers[4][4] = {
 				{10, 8, 2, 0},
 				{14, 12, 6, 4},
 				{15, 13, 7, 5},
diff --git a/Machines/MasterSystem/MasterSystem.cpp b/Machines/MasterSystem/MasterSystem.cpp
index b32453eda..df0c3997d 100644
--- a/Machines/MasterSystem/MasterSystem.cpp
+++ b/Machines/MasterSystem/MasterSystem.cpp
@@ -29,7 +29,7 @@
 #include <iostream>
 
 namespace {
-const int sn76489_divider = 2;
+constexpr int sn76489_divider = 2;
 }
 
 namespace Sega {
diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp
index 2a45c8a09..52dd42892 100644
--- a/OSBindings/SDL/main.cpp
+++ b/OSBindings/SDL/main.cpp
@@ -43,7 +43,7 @@ struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegat
 
 struct SpeakerDelegate: public Outputs::Speaker::Speaker::Delegate {
 	// This is set to a relatively large number for now.
-	static const int buffer_size = 1024;
+	static constexpr int buffer_size = 1024;
 
 	void speaker_did_complete_samples(Outputs::Speaker::Speaker *speaker, const std::vector<int16_t> &buffer) override {
 		std::lock_guard<std::mutex> lock_guard(audio_buffer_mutex_);
@@ -106,7 +106,7 @@ class ActivityObserver: public Activity::Observer {
 			lights_.clear();
 
 			// Generate a bunch of LEDs for connected drives.
-			const float height = 0.05f;
+			constexpr float height = 0.05f;
 			const float width = height / aspect_ratio;
 			const float right_x = 1.0f - 2.0f * width;
 			float y = 1.0f - 2.0f * height;
diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp
index fa73fb94b..c97a34f2f 100644
--- a/Outputs/CRT/CRT.cpp
+++ b/Outputs/CRT/CRT.cpp
@@ -17,15 +17,15 @@ using namespace Outputs::CRT;
 
 void CRT::set_new_timing(int cycles_per_line, int height_of_display, Outputs::Display::ColourSpace colour_space, int colour_cycle_numerator, int colour_cycle_denominator, int vertical_sync_half_lines, bool should_alternate) {
 
-	const int millisecondsHorizontalRetraceTime = 7;	// Source: Dictionary of Video and Television Technology, p. 234.
-	const int scanlinesVerticalRetraceTime = 8;			// Source: ibid.
+	constexpr int millisecondsHorizontalRetraceTime = 7;	// Source: Dictionary of Video and Television Technology, p. 234.
+	constexpr int scanlinesVerticalRetraceTime = 8;			// Source: ibid.
 
-														// To quote:
-														//
-														//	"retrace interval; The interval of time for the return of the blanked scanning beam of
-														//	a TV picture tube or camera tube to the starting point of a line or field. It is about
-														//	7 microseconds for horizontal retrace and 500 to 750 microseconds for vertical retrace
-														//  in NTSC and PAL TV."
+															// To quote:
+															//
+															//	"retrace interval; The interval of time for the return of the blanked scanning beam of
+															//	a TV picture tube or camera tube to the starting point of a line or field. It is about
+															//	7 microseconds for horizontal retrace and 500 to 750 microseconds for vertical retrace
+															//  in NTSC and PAL TV."
 
 	time_multiplier_ = 65535 / cycles_per_line;
 	phase_denominator_ = int64_t(cycles_per_line) * int64_t(colour_cycle_denominator) * int64_t(time_multiplier_);
diff --git a/Processors/68000/68000.hpp b/Processors/68000/68000.hpp
index 25fa263f1..6a7f0399b 100644
--- a/Processors/68000/68000.hpp
+++ b/Processors/68000/68000.hpp
@@ -51,45 +51,45 @@ namespace MC68000 {
 struct Microcycle {
 	/// Indicates that the address strobe and exactly one of the data strobes are active; you can determine
 	/// which by inspecting the low bit of the provided address. The RW line indicates a read.
-	static const int SelectByte				= 1 << 0;
+	static constexpr int SelectByte				= 1 << 0;
 	// Maintenance note: this is bit 0 to reduce the cost of getting a host-endian
 	// bytewise address. The assumption that it is bit 0 is also used for branchless
 	// selection in a few places. See implementation of host_endian_byte_address(),
 	// value8_high(), value8_low() and value16().
 
 	/// Indicates that the address and both data select strobes are active.
-	static const int SelectWord				= 1 << 1;
+	static constexpr int SelectWord				= 1 << 1;
 
 	/// A NewAddress cycle is one in which the address strobe is initially low but becomes high;
 	/// this correlates to states 0 to 5 of a standard read/write cycle.
-	static const int NewAddress				= 1 << 2;
+	static constexpr int NewAddress				= 1 << 2;
 
 	/// A SameAddress cycle is one in which the address strobe is continuously asserted, but neither
 	/// of the data strobes are.
-	static const int SameAddress			= 1 << 3;
+	static constexpr int SameAddress			= 1 << 3;
 
 	/// A Reset cycle is one in which the RESET output is asserted.
-	static const int Reset					= 1 << 4;
+	static constexpr int Reset					= 1 << 4;
 
 	/// If set, indicates a read. Otherwise, a write.
-	static const int Read 					= 1 << 5;
+	static constexpr int Read 					= 1 << 5;
 
 	/// Contains the value of line FC0 if it is not implicit via InterruptAcknowledge.
-	static const int IsData 				= 1 << 6;
+	static constexpr int IsData 				= 1 << 6;
 
 	/// Contains the value of line FC1 if it is not implicit via InterruptAcknowledge.
-	static const int IsProgram 				= 1 << 7;
+	static constexpr int IsProgram 				= 1 << 7;
 
 	/// The interrupt acknowledge cycle is that during which the 68000 seeks to obtain the vector for
 	/// an interrupt it plans to observe. Noted on a real 68000 by all FCs being set to 1.
-	static const int InterruptAcknowledge	= 1 << 8;
+	static constexpr int InterruptAcknowledge	= 1 << 8;
 
 	/// Represents the state of the 68000's valid memory address line — indicating whether this microcycle
 	/// is synchronised with the E clock to satisfy a valid peripheral address request.
-	static const int IsPeripheral 			= 1 << 9;
+	static constexpr int IsPeripheral 			= 1 << 9;
 
 	/// Provides the 68000's bus grant line — indicating whether a bus request has been acknowledged.
-	static const int BusGrant				= 1 << 10;
+	static constexpr int BusGrant				= 1 << 10;
 
 	/// Contains a valid combination of the various static const int flags, describing the operation
 	/// performed by this Microcycle.
diff --git a/Processors/68000/Implementation/68000Storage.hpp b/Processors/68000/Implementation/68000Storage.hpp
index 772bf0d92..2670ce6fc 100644
--- a/Processors/68000/Implementation/68000Storage.hpp
+++ b/Processors/68000/Implementation/68000Storage.hpp
@@ -317,8 +317,8 @@ class ProcessorStorage {
 				// steps detail appropriately.
 				PrepareINTVector,
 			};
-			static const int SourceMask = 1 << 7;
-			static const int DestinationMask = 1 << 6;
+			static constexpr int SourceMask = 1 << 7;
+			static constexpr int DestinationMask = 1 << 6;
 			uint8_t action = uint8_t(Action::None);
 
 			static const uint16_t NoBusProgram = std::numeric_limits<uint16_t>::max();
diff --git a/Storage/Disk/DiskImage/Formats/AcornADF.cpp b/Storage/Disk/DiskImage/Formats/AcornADF.cpp
index 75546b1cc..d7ba4f197 100644
--- a/Storage/Disk/DiskImage/Formats/AcornADF.cpp
+++ b/Storage/Disk/DiskImage/Formats/AcornADF.cpp
@@ -11,8 +11,8 @@
 #include "Utility/ImplicitSectors.hpp"
 
 namespace {
-	static const int sectors_per_track = 16;
-	static const int sector_size = 1;
+	constexpr int sectors_per_track = 16;
+	constexpr int sector_size = 1;
 }
 
 using namespace Storage::Disk;
diff --git a/Storage/Disk/DiskImage/Formats/AppleDSK.cpp b/Storage/Disk/DiskImage/Formats/AppleDSK.cpp
index 879abb303..a12b59b91 100644
--- a/Storage/Disk/DiskImage/Formats/AppleDSK.cpp
+++ b/Storage/Disk/DiskImage/Formats/AppleDSK.cpp
@@ -18,8 +18,8 @@
 using namespace Storage::Disk;
 
 namespace {
-	const int number_of_tracks = 35;
-	const int bytes_per_sector = 256;
+	constexpr int number_of_tracks = 35;
+	constexpr int bytes_per_sector = 256;
 }
 
 AppleDSK::AppleDSK(const std::string &file_name) :
diff --git a/Storage/Disk/DiskImage/Formats/MSXDSK.cpp b/Storage/Disk/DiskImage/Formats/MSXDSK.cpp
index 7ed36d5fc..25f9788da 100644
--- a/Storage/Disk/DiskImage/Formats/MSXDSK.cpp
+++ b/Storage/Disk/DiskImage/Formats/MSXDSK.cpp
@@ -11,9 +11,9 @@
 #include "Utility/ImplicitSectors.hpp"
 
 namespace {
-	const int sectors_per_track = 9;
-	const int sector_size = 2;
-	const off_t track_size = (128 << sector_size)*sectors_per_track;
+	constexpr int sectors_per_track = 9;
+	constexpr int sector_size = 2;
+	constexpr off_t track_size = (128 << sector_size)*sectors_per_track;
 }
 
 using namespace Storage::Disk;
diff --git a/Storage/Disk/DiskImage/Formats/SSD.cpp b/Storage/Disk/DiskImage/Formats/SSD.cpp
index 7e455e69e..455fddc4a 100644
--- a/Storage/Disk/DiskImage/Formats/SSD.cpp
+++ b/Storage/Disk/DiskImage/Formats/SSD.cpp
@@ -9,8 +9,8 @@
 #include "SSD.hpp"
 
 namespace {
-	static const int sectors_per_track = 10;
-	static const int sector_size = 1;
+	constexpr int sectors_per_track = 10;
+	constexpr int sector_size = 1;
 }
 
 using namespace Storage::Disk;
diff --git a/Storage/Disk/DiskImage/Formats/ST.cpp b/Storage/Disk/DiskImage/Formats/ST.cpp
index 2b3a069f2..7c4a05194 100644
--- a/Storage/Disk/DiskImage/Formats/ST.cpp
+++ b/Storage/Disk/DiskImage/Formats/ST.cpp
@@ -9,8 +9,8 @@
 #include "ST.hpp"
 
 namespace {
-	static const int sectors_per_track = 10;
-	static const int sector_size = 2;
+	constexpr int sectors_per_track = 10;
+	constexpr int sector_size = 2;
 }
 
 using namespace Storage::Disk;
diff --git a/Storage/Disk/Drive.cpp b/Storage/Disk/Drive.cpp
index 04d126603..5bb509dad 100644
--- a/Storage/Disk/Drive.cpp
+++ b/Storage/Disk/Drive.cpp
@@ -122,7 +122,7 @@ bool Drive::get_tachometer() {
 	// I have made a guess here that the tachometer is a symmetric square wave;
 	// if that is correct then around 60 beats per rotation appears to be correct
 	// to proceed beyond the speed checks I've so far uncovered.
-	const float ticks_per_rotation = 60.0f; // 56 was too low; 64 too high.
+	constexpr float ticks_per_rotation = 60.0f; // 56 was too low; 64 too high.
 	return int(get_rotation() * 2.0f * ticks_per_rotation) & 1;
 }
 
@@ -264,7 +264,7 @@ void Drive::get_next_event(float duration_already_passed) {
 
 	// An interval greater than 15ms => adjust gain up the point where noise starts happening.
 	// Seed that up and leave a 15ms gap until it starts.
-	const float safe_gain_period = 15.0f / 1000000.0f;
+	constexpr float safe_gain_period = 15.0f / 1000000.0f;
 	if(interval >= safe_gain_period) {
 		random_interval_ = interval - safe_gain_period;
 		interval = safe_gain_period;
diff --git a/Storage/MassStorage/SCSI/SCSI.hpp b/Storage/MassStorage/SCSI/SCSI.hpp
index 4caf3f667..48dcb9a72 100644
--- a/Storage/MassStorage/SCSI/SCSI.hpp
+++ b/Storage/MassStorage/SCSI/SCSI.hpp
@@ -21,7 +21,7 @@ namespace SCSI {
 
 typedef int BusState;
 
-static const BusState DefaultBusState = 0;
+static constexpr BusState DefaultBusState = 0;
 
 /*!
 	SCSI bus state is encoded entirely within an int.
diff --git a/Storage/Tape/Formats/TapePRG.cpp b/Storage/Tape/Formats/TapePRG.cpp
index 868b66d37..288ebcef3 100644
--- a/Storage/Tape/Formats/TapePRG.cpp
+++ b/Storage/Tape/Formats/TapePRG.cpp
@@ -65,10 +65,10 @@ PRG::PRG(const std::string &file_name) :
 
 Storage::Tape::Tape::Pulse PRG::virtual_get_next_pulse() {
 	// these are all microseconds per pole
-	static const unsigned int leader_zero_length = 179;
-	static const unsigned int zero_length = 169;
-	static const unsigned int one_length = 247;
-	static const unsigned int marker_length = 328;
+	constexpr unsigned int leader_zero_length = 179;
+	constexpr unsigned int zero_length = 169;
+	constexpr unsigned int one_length = 247;
+	constexpr unsigned int marker_length = 328;
 
 	bit_phase_ = (bit_phase_+1)&3;
 	if(!bit_phase_) get_next_output_token();
@@ -100,10 +100,10 @@ bool PRG::is_at_end() {
 }
 
 void PRG::get_next_output_token() {
-	static const int block_length = 192;	// not counting the checksum
-	static const int countdown_bytes = 9;
-	static const int leadin_length = 20000;
-	static const int block_leadin_length = 5000;
+	constexpr int block_length = 192;	// not counting the checksum
+	constexpr int countdown_bytes = 9;
+	constexpr int leadin_length = 20000;
+	constexpr int block_leadin_length = 5000;
 
 	if(file_phase_ == FilePhaseHeaderDataGap || file_phase_ == FilePhaseAtEnd) {
 		output_token_ = Silence;
diff --git a/Storage/Tape/Parsers/Acorn.cpp b/Storage/Tape/Parsers/Acorn.cpp
index dc5193e7f..7101a3d05 100644
--- a/Storage/Tape/Parsers/Acorn.cpp
+++ b/Storage/Tape/Parsers/Acorn.cpp
@@ -11,7 +11,7 @@
 using namespace Storage::Tape::Acorn;
 
 namespace {
-const int PLLClockRate = 1920000;
+constexpr int PLLClockRate = 1920000;
 }
 
 Parser::Parser(): crc_(0x1021) {
diff --git a/Storage/Tape/Parsers/MSX.cpp b/Storage/Tape/Parsers/MSX.cpp
index 723f44fbe..c39ce7238 100644
--- a/Storage/Tape/Parsers/MSX.cpp
+++ b/Storage/Tape/Parsers/MSX.cpp
@@ -101,7 +101,7 @@ int Parser::get_byte(const FileSpeed &speed, Storage::Tape::BinaryTapePlayer &ta
 		So I'm going to look for the next two consecutive pulses that are each big
 		enough to be half of a zero.
 	*/
-	const float minimum_start_bit_duration = static_cast<float>(speed.minimum_start_bit_duration) * 0.00001145f * 0.5f;
+	const float minimum_start_bit_duration = float(speed.minimum_start_bit_duration) * 0.00001145f * 0.5f;
 	int input = 0;
 	while(!tape_player.get_tape()->is_at_end()) {
 		// Find next transition.
@@ -126,9 +126,9 @@ int Parser::get_byte(const FileSpeed &speed, Storage::Tape::BinaryTapePlayer &ta
 	int result = 0;
 	const int cycles_per_window = static_cast<int>(
 		0.5f +
-		static_cast<float>(speed.low_high_disrimination_duration) *
+		float(speed.low_high_disrimination_duration) *
 		0.0000173f *
-		static_cast<float>(tape_player.get_input_clock_rate())
+		float(tape_player.get_input_clock_rate())
 	);
 	int bits_left = 8;
 	bool level = tape_player.get_input();
@@ -137,7 +137,7 @@ int Parser::get_byte(const FileSpeed &speed, Storage::Tape::BinaryTapePlayer &ta
 		int transitions = 0;
 		int cycles_remaining = cycles_per_window;
 		while(!tape_player.get_tape()->is_at_end() && cycles_remaining) {
-			const int cycles_until_next_event = static_cast<int>(tape_player.get_cycles_until_next_event());
+			const int cycles_until_next_event = int(tape_player.get_cycles_until_next_event());
 			const int cycles_to_run_for = std::min(cycles_until_next_event, cycles_remaining);
 
 			cycles_remaining -= cycles_to_run_for;
diff --git a/Storage/Tape/Parsers/ZX8081.cpp b/Storage/Tape/Parsers/ZX8081.cpp
index 10754909f..3b8e893bb 100644
--- a/Storage/Tape/Parsers/ZX8081.cpp
+++ b/Storage/Tape/Parsers/ZX8081.cpp
@@ -29,9 +29,9 @@ void Parser::process_pulse(const Storage::Tape::Tape::Pulse &pulse) {
 }
 
 void Parser::post_pulse() {
-	const float expected_pulse_length = 300.0f / 1000000.0f;
-	const float expected_gap_length = 1300.0f / 1000000.0f;
-	float pulse_time = pulse_time_.get<float>();
+	constexpr float expected_pulse_length = 300.0f / 1000000.0f;
+	constexpr float expected_gap_length = 1300.0f / 1000000.0f;
+	auto pulse_time = pulse_time_.get<float>();
 
 	if(pulse_time > expected_gap_length * 1.25f) {
 		push_wave(WaveType::LongGap);