diff --git a/Analyser/Dynamic/MultiMachine/MultiMachine.cpp b/Analyser/Dynamic/MultiMachine/MultiMachine.cpp
index 648b822ba..608730e75 100644
--- a/Analyser/Dynamic/MultiMachine/MultiMachine.cpp
+++ b/Analyser/Dynamic/MultiMachine/MultiMachine.cpp
@@ -95,3 +95,7 @@ void MultiMachine::pick_first() {
 	// TODO: this isn't quite correct, because it may leak OpenGL/etc resources through failure to
 	// request a close_output while the context is active.
 }
+
+void *MultiMachine::raw_pointer() {
+	return nullptr;
+}
diff --git a/Analyser/Dynamic/MultiMachine/MultiMachine.hpp b/Analyser/Dynamic/MultiMachine/MultiMachine.hpp
index 1b67b6dce..81feebef2 100644
--- a/Analyser/Dynamic/MultiMachine/MultiMachine.hpp
+++ b/Analyser/Dynamic/MultiMachine/MultiMachine.hpp
@@ -45,9 +45,11 @@ class MultiMachine: public ::Machine::DynamicMachine, public MultiCRTMachine::De
 		JoystickMachine::Machine *joystick_machine() override;
 		KeyboardMachine::Machine *keyboard_machine() override;
 		Configurable::Device *configurable_device() override;
+		void *raw_pointer() override;
 
 		void multi_crt_did_run_machines() override;
 
+
 	private:
 		std::vector<std::unique_ptr<DynamicMachine>> machines_;
 		std::mutex machines_mutex_;
diff --git a/Machines/DynamicMachine.hpp b/Machines/DynamicMachine.hpp
index 96839410d..6d261b6da 100644
--- a/Machines/DynamicMachine.hpp
+++ b/Machines/DynamicMachine.hpp
@@ -29,6 +29,18 @@ struct DynamicMachine {
 	virtual JoystickMachine::Machine *joystick_machine() = 0;
 	virtual KeyboardMachine::Machine *keyboard_machine() = 0;
 	virtual Configurable::Device *configurable_device() = 0;
+
+	/*!
+		Provides a raw pointer to the underlying machine if and only if this dynamic machine really is
+		only a single machine.
+
+		Very unsafe. Very temporary.
+
+		TODO: eliminate in favour of introspection for machine-specific inputs. This is here temporarily
+		only to permit continuity of certain features in the Mac port that have not yet made their way
+		to the SDL/console port.
+	*/
+	virtual void *raw_pointer() = 0;
 };
 
 }
diff --git a/Machines/Utility/TypedDynamicMachine.hpp b/Machines/Utility/TypedDynamicMachine.hpp
index 83b3f7087..d0ecc70c8 100644
--- a/Machines/Utility/TypedDynamicMachine.hpp
+++ b/Machines/Utility/TypedDynamicMachine.hpp
@@ -45,6 +45,10 @@ template<typename T> class TypedDynamicMachine: public ::Machine::DynamicMachine
 			return get<Configurable::Device>();
 		}
 
+		void *raw_pointer() override {
+			return get();
+		}
+
 	private:
 		template <typename Class> Class *get() {
 			return dynamic_cast<Class *>(machine_.get());
diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj
index 617d6fc15..7e51ddef7 100644
--- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj	
+++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj	
@@ -127,7 +127,6 @@
 		4B1414601B58885000E04248 /* WolfgangLorenzTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B14145F1B58885000E04248 /* WolfgangLorenzTests.swift */; };
 		4B1414621B58888700E04248 /* KlausDormannTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1414611B58888700E04248 /* KlausDormannTests.swift */; };
 		4B1497881EE4A1DA00CE2596 /* ZX80O81P.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1497861EE4A1DA00CE2596 /* ZX80O81P.cpp */; };
-		4B14978F1EE4B4D200CE2596 /* CSZX8081.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B14978E1EE4B4D200CE2596 /* CSZX8081.mm */; };
 		4B1497921EE4B5A800CE2596 /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1497901EE4B5A800CE2596 /* ZX8081.cpp */; };
 		4B1497981EE4B97F00CE2596 /* ZX8081Options.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B1497961EE4B97F00CE2596 /* ZX8081Options.xib */; };
 		4B1558C01F844ECD006E9A97 /* BitReverse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1558BE1F844ECD006E9A97 /* BitReverse.cpp */; };
@@ -144,8 +143,6 @@
 		4B2A332D1DB86821002876E3 /* OricOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B2A332B1DB86821002876E3 /* OricOptions.xib */; };
 		4B2A539F1D117D36003C6002 /* CSAudioQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A53911D117D36003C6002 /* CSAudioQueue.m */; };
 		4B2A53A01D117D36003C6002 /* CSMachine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A53961D117D36003C6002 /* CSMachine.mm */; };
-		4B2A53A11D117D36003C6002 /* CSAtari2600.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A539A1D117D36003C6002 /* CSAtari2600.mm */; };
-		4B2A53A31D117D36003C6002 /* CSVic20.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A539E1D117D36003C6002 /* CSVic20.mm */; };
 		4B2AF8691E513FC20027EE29 /* TIATests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B2AF8681E513FC20027EE29 /* TIATests.mm */; };
 		4B2B3A4B1F9B8FA70062DABF /* Typer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2B3A471F9B8FA70062DABF /* Typer.cpp */; };
 		4B2B3A4C1F9B8FA70062DABF /* MemoryFuzzer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2B3A481F9B8FA70062DABF /* MemoryFuzzer.cpp */; };
@@ -282,21 +279,20 @@
 		4B8FE21C1DA19D5F0090D3CE /* MachineDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B8FE2151DA19D5F0090D3CE /* MachineDocument.xib */; };
 		4B8FE21D1DA19D5F0090D3CE /* QuickLoadCompositeOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B8FE2171DA19D5F0090D3CE /* QuickLoadCompositeOptions.xib */; };
 		4B8FE21E1DA19D5F0090D3CE /* Vic20Options.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B8FE2191DA19D5F0090D3CE /* Vic20Options.xib */; };
-		4B8FE2201DA19D7C0090D3CE /* Atari2600OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsPanel.swift */; };
 		4B8FE2221DA19FB20090D3CE /* MachinePanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE2211DA19FB20090D3CE /* MachinePanel.swift */; };
 		4B8FE2271DA1DE2D0090D3CE /* NSBundle+DataResource.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE2261DA1DE2D0090D3CE /* NSBundle+DataResource.m */; };
 		4B924E991E74D22700B76AF1 /* AtariStaticAnalyserTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B924E981E74D22700B76AF1 /* AtariStaticAnalyserTests.mm */; };
 		4B9252CE1E74D28200B76AF1 /* Atari ROMs in Resources */ = {isa = PBXBuildFile; fileRef = 4B9252CD1E74D28200B76AF1 /* Atari ROMs */; };
 		4B92EACA1B7C112B00246143 /* 6502TimingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */; };
-		4B95FA9D1F11893B0008E395 /* ZX8081OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B95FA9C1F11893B0008E395 /* ZX8081OptionsPanel.swift */; };
 		4B98A05E1FFAD3F600ADF63B /* CSROMFetcher.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B98A05D1FFAD3F600ADF63B /* CSROMFetcher.mm */; };
 		4B98A05F1FFAD62400ADF63B /* CSROMFetcher.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B98A05D1FFAD3F600ADF63B /* CSROMFetcher.mm */; };
 		4B98A0611FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B98A0601FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm */; };
 		4B98A1CE1FFADEC500ADF63B /* MSX ROMs in Resources */ = {isa = PBXBuildFile; fileRef = 4B98A1CD1FFADEC400ADF63B /* MSX ROMs */; };
-		4B9CCDA11DA279CA0098B625 /* Vic20OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9CCDA01DA279CA0098B625 /* Vic20OptionsPanel.swift */; };
 		4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */; };
 		4BA61EB01D91515900B3C876 /* NSData+StdVector.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA61EAF1D91515900B3C876 /* NSData+StdVector.mm */; };
 		4BAD13441FF709C700FD114A /* MSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0E61051FF34737002A9DBD /* MSX.cpp */; };
+		4BAE49582032881E004BE78E /* CSZX8081.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B14978E1EE4B4D200CE2596 /* CSZX8081.mm */; };
+		4BAE495920328897004BE78E /* ZX8081OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B95FA9C1F11893B0008E395 /* ZX8081OptionsPanel.swift */; };
 		4BAF2B4E2004580C00480230 /* DMK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAF2B4C2004580C00480230 /* DMK.cpp */; };
 		4BAF2B4F2004580C00480230 /* DMK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAF2B4C2004580C00480230 /* DMK.cpp */; };
 		4BB17D4E1ED7909F00ABD1E1 /* tests.expected.json in Resources */ = {isa = PBXBuildFile; fileRef = 4BB17D4C1ED7909F00ABD1E1 /* tests.expected.json */; };
@@ -601,6 +597,8 @@
 		4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD468F51D8DF41D0084958B /* 1770.cpp */; };
 		4BD4A8D01E077FD20020D856 /* PCMTrackTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BD4A8CF1E077FD20020D856 /* PCMTrackTests.mm */; };
 		4BD5F1951D13528900631CD1 /* CSBestEffortUpdater.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.mm */; };
+		4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A539A1D117D36003C6002 /* CSAtari2600.mm */; };
+		4BDB61EC203285AE0048AF91 /* Atari2600OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsPanel.swift */; };
 		4BDDBA991EF3451200347E61 /* Z80MachineCycleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */; };
 		4BE7C9181E3D397100A5496D /* TIA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BE7C9161E3D397100A5496D /* TIA.cpp */; };
 		4BE9A6B11EDE293000CBCB47 /* zexdoc.com in Resources */ = {isa = PBXBuildFile; fileRef = 4BE9A6B01EDE293000CBCB47 /* zexdoc.com */; };
@@ -712,7 +710,6 @@
 		4B2A332C1DB86821002876E3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/OricOptions.xib"; sourceTree = SOURCE_ROOT; };
 		4B2A53901D117D36003C6002 /* CSAudioQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSAudioQueue.h; sourceTree = "<group>"; };
 		4B2A53911D117D36003C6002 /* CSAudioQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSAudioQueue.m; sourceTree = "<group>"; };
-		4B2A53941D117D36003C6002 /* CSMachine+Subclassing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CSMachine+Subclassing.h"; sourceTree = "<group>"; };
 		4B2A53951D117D36003C6002 /* CSMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSMachine.h; sourceTree = "<group>"; };
 		4B2A53961D117D36003C6002 /* CSMachine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CSMachine.mm; sourceTree = "<group>"; };
 		4B2A53971D117D36003C6002 /* KeyCodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyCodes.h; sourceTree = "<group>"; };
@@ -1542,7 +1539,6 @@
 			children = (
 				4BBC34241D2208B100FFC9DF /* CSFastLoading.h */,
 				4B2A53951D117D36003C6002 /* CSMachine.h */,
-				4B2A53941D117D36003C6002 /* CSMachine+Subclassing.h */,
 				4B643F3C1D77AE5C00D431D6 /* CSMachine+Target.h */,
 				4B98A05C1FFAD3F600ADF63B /* CSROMFetcher.hpp */,
 				4B2A53971D117D36003C6002 /* KeyCodes.h */,
@@ -3530,7 +3526,6 @@
 				4B0E61071FF34737002A9DBD /* MSX.cpp in Sources */,
 				4BBF99151C8FBA6F0075DAFB /* CRTOpenGL.cpp in Sources */,
 				4B4518A01F75FD1C00926311 /* CPCDSK.cpp in Sources */,
-				4B95FA9D1F11893B0008E395 /* ZX8081OptionsPanel.swift in Sources */,
 				4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */,
 				4B322E041F5A2E3C004EB04C /* Z80Base.cpp in Sources */,
 				4B894530201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
@@ -3553,6 +3548,7 @@
 				4B2BFDB21DAEF5FF001A68B8 /* Video.cpp in Sources */,
 				4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */,
 				4BBFFEE61F7B27F1005F3FEB /* TrackSerialiser.cpp in Sources */,
+				4BAE49582032881E004BE78E /* CSZX8081.mm in Sources */,
 				4BC3B74F1CD194CC00F86E85 /* Shader.cpp in Sources */,
 				4B894518201967B4007DE474 /* ConfidenceCounter.cpp in Sources */,
 				4B89452E201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
@@ -3563,6 +3559,7 @@
 				4B4B1A3C200198CA00A0F866 /* KonamiSCC.cpp in Sources */,
 				4BD5F1951D13528900631CD1 /* CSBestEffortUpdater.mm in Sources */,
 				4B894532201967B4007DE474 /* 6502.cpp in Sources */,
+				4BDB61EC203285AE0048AF91 /* Atari2600OptionsPanel.swift in Sources */,
 				4B4518811F75E91A00926311 /* PCMPatchedTrack.cpp in Sources */,
 				4BBB70A8202014E2002FE009 /* MultiCRTMachine.cpp in Sources */,
 				4B8805F71DCFF6C9003085B1 /* Commodore.cpp in Sources */,
@@ -3575,7 +3572,6 @@
 				4B7913CC1DFCD80E00175A82 /* Video.cpp in Sources */,
 				4B4518831F75E91A00926311 /* PCMTrack.cpp in Sources */,
 				4B45189F1F75FD1C00926311 /* AcornADF.cpp in Sources */,
-				4B2A53A11D117D36003C6002 /* CSAtari2600.mm in Sources */,
 				4B7136911F789C93008B8ED9 /* SegmentParser.cpp in Sources */,
 				4B4518A21F75FD1C00926311 /* G64.cpp in Sources */,
 				4B89452C201967B4007DE474 /* Tape.cpp in Sources */,
@@ -3583,6 +3579,7 @@
 				4BEBFB512002DB30000708CC /* DiskROM.cpp in Sources */,
 				4B89451C201967B4007DE474 /* Disk.cpp in Sources */,
 				4BEA52631DF339D7007E74F2 /* SoundGenerator.cpp in Sources */,
+				4BAE495920328897004BE78E /* ZX8081OptionsPanel.swift in Sources */,
 				4B89451A201967B4007DE474 /* ConfidenceSummary.cpp in Sources */,
 				4B54C0C51F8D91D90050900F /* Keyboard.cpp in Sources */,
 				4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */,
@@ -3623,13 +3620,10 @@
 				4B4A76301DB1A3FA007AAE2E /* AY38910.cpp in Sources */,
 				4B6A4C991F58F09E00E3F787 /* 6502Base.cpp in Sources */,
 				4B4518871F75E91A00926311 /* DigitalPhaseLockedLoop.cpp in Sources */,
-				4B2A53A31D117D36003C6002 /* CSVic20.mm in Sources */,
 				4B98A05E1FFAD3F600ADF63B /* CSROMFetcher.mm in Sources */,
-				4B8FE2201DA19D7C0090D3CE /* Atari2600OptionsPanel.swift in Sources */,
 				4B8805F41DCFD22A003085B1 /* Commodore.cpp in Sources */,
 				4B3FCC40201EC24200960631 /* MultiMachine.cpp in Sources */,
 				4B2E2D9A1C3A06EC00138695 /* Atari2600.cpp in Sources */,
-				4B9CCDA11DA279CA0098B625 /* Vic20OptionsPanel.swift in Sources */,
 				4B8805F01DCFC99C003085B1 /* Acorn.cpp in Sources */,
 				4B3051301D98ACC600B4FED8 /* Plus3.cpp in Sources */,
 				4B30512D1D989E2200B4FED8 /* Drive.cpp in Sources */,
@@ -3642,6 +3636,7 @@
 				4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */,
 				4B894524201967B4007DE474 /* Tape.cpp in Sources */,
 				4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */,
+				4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */,
 				4BFDD78C1F7F2DB4008579B9 /* ImplicitSectors.cpp in Sources */,
 				4BC3B7521CD1956900F86E85 /* OutputShader.cpp in Sources */,
 				4B5073071DDD3B9400C48FBD /* ArrayBuilder.cpp in Sources */,
@@ -3656,7 +3651,6 @@
 				4B8334861F5DA3780097E338 /* 6502Storage.cpp in Sources */,
 				4B8FE2271DA1DE2D0090D3CE /* NSBundle+DataResource.m in Sources */,
 				4B2A53A01D117D36003C6002 /* CSMachine.mm in Sources */,
-				4B14978F1EE4B4D200CE2596 /* CSZX8081.mm in Sources */,
 				4BC91B831D1F160E00884B76 /* CommodoreTAP.cpp in Sources */,
 				4B2A539F1D117D36003C6002 /* CSAudioQueue.m in Sources */,
 				4B89453E201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
diff --git a/OSBindings/Mac/Clock Signal/Documents/Atari2600OptionsPanel.swift b/OSBindings/Mac/Clock Signal/Documents/Atari2600OptionsPanel.swift
index e00c7ba0a..b4129b5a3 100644
--- a/OSBindings/Mac/Clock Signal/Documents/Atari2600OptionsPanel.swift	
+++ b/OSBindings/Mac/Clock Signal/Documents/Atari2600OptionsPanel.swift	
@@ -9,7 +9,7 @@
 class Atari2600OptionsPanel: MachinePanel {
 	var atari2600: CSAtari2600! {
 		get {
-			return self.machine as! CSAtari2600
+			return self.machine.atari2600
 		}
 	}
 
diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift
index 1763eddec..8fbdad7fc 100644
--- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift	
+++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift	
@@ -118,11 +118,11 @@ class MachineDocument:
 			self.machine = machine
 		}
 
-//		if let optionsPanelNibName = analysis.optionsPanelNibName {
-//			Bundle.main.loadNibNamed(NSNib.Name(rawValue: optionsPanelNibName), owner: self, topLevelObjects: nil)
-//			self.optionsPanel.machine = self.machine
-//			showOptions(self)
-//		}
+		if let optionsPanelNibName = analysis.optionsPanelNibName {
+			Bundle.main.loadNibNamed(NSNib.Name(rawValue: optionsPanelNibName), owner: self, topLevelObjects: nil)
+			self.optionsPanel.machine = self.machine
+			showOptions(self)
+		}
 	}
 
 	override func read(from url: URL, ofType typeName: String) throws {
diff --git a/OSBindings/Mac/Clock Signal/Documents/ZX8081OptionsPanel.swift b/OSBindings/Mac/Clock Signal/Documents/ZX8081OptionsPanel.swift
index a3b754c9a..9de95ff72 100644
--- a/OSBindings/Mac/Clock Signal/Documents/ZX8081OptionsPanel.swift	
+++ b/OSBindings/Mac/Clock Signal/Documents/ZX8081OptionsPanel.swift	
@@ -9,7 +9,7 @@
 class ZX8081OptionsPanel: MachinePanel {
 	var zx8081: CSZX8081! {
 		get {
-			return self.machine as! CSZX8081
+			return self.machine.zx8081
 		}
 	}
 
@@ -21,7 +21,7 @@ class ZX8081OptionsPanel: MachinePanel {
 		let isEnabled = sender.state == .on
 		UserDefaults.standard.set(isEnabled, forKey: self.automaticTapeMotorControlDefaultsKey)
 		self.playOrPauseTapeButton.isEnabled = !isEnabled
-		self.zx8081.useAutomaticTapeMotorControl = isEnabled
+		self.machine.useAutomaticTapeMotorControl = isEnabled
 	}
 
 	@IBOutlet var playOrPauseTapeButton: NSButton!
@@ -44,6 +44,6 @@ class ZX8081OptionsPanel: MachinePanel {
 		let automaticTapeMotorControlIsEnabled = standardUserDefaults.bool(forKey: self.automaticTapeMotorControlDefaultsKey)
 		self.automaticTapeMotorControlButton.state = automaticTapeMotorControlIsEnabled ? .on : .off
 		self.playOrPauseTapeButton.isEnabled = !automaticTapeMotorControlIsEnabled
-		self.zx8081.useAutomaticTapeMotorControl = automaticTapeMotorControlIsEnabled
+		self.machine.useAutomaticTapeMotorControl = automaticTapeMotorControlIsEnabled
 	}
 }
diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine+Subclassing.h b/OSBindings/Mac/Clock Signal/Machine/CSMachine+Subclassing.h
deleted file mode 100644
index 453f5aeaf..000000000
--- a/OSBindings/Mac/Clock Signal/Machine/CSMachine+Subclassing.h	
+++ /dev/null
@@ -1,16 +0,0 @@
-//
-//  CSMachine+Subclassing.h
-//  Clock Signal
-//
-//  Created by Thomas Harte on 04/01/2016.
-//  Copyright © 2016 Thomas Harte. All rights reserved.
-//
-
-#import "CSMachine.h"
-#include "CRTMachine.hpp"
-
-@interface CSMachine (Subclassing)
-
-- (void)setupOutputWithAspectRatio:(float)aspectRatio;
-
-@end
diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.h b/OSBindings/Mac/Clock Signal/Machine/CSMachine.h
index 0315a623a..5ac636f0a 100644
--- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.h	
+++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.h	
@@ -18,6 +18,10 @@
 - (void)machineDidChangeClockIsUnlimited:(CSMachine *)machine;
 @end
 
+// Deliberately low; to ensure CSMachine has been declared as an @class already.
+#import "CSAtari2600.h"
+#import "CSZX8081.h"
+
 @interface CSMachine : NSObject
 
 - (instancetype)init NS_UNAVAILABLE;
@@ -54,4 +58,8 @@
 @property (nonatomic, assign) BOOL useCompositeOutput;
 @property (nonatomic, assign) BOOL useAutomaticTapeMotorControl;
 
+// Special-case accessors; undefined behaviour if accessed for a machine not of the corresponding type.
+@property (nonatomic, readonly) CSAtari2600 *atari2600;
+@property (nonatomic, readonly) CSZX8081 *zx8081;
+
 @end
diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm
index b0fe69d5d..8d4a5c75e 100644
--- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm	
+++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm	
@@ -7,7 +7,6 @@
 //
 
 #import "CSMachine.h"
-#import "CSMachine+Subclassing.h"
 #import "CSMachine+Target.h"
 
 #include "CSROMFetcher.hpp"
@@ -342,4 +341,14 @@ struct MachineDelegate: CRTMachine::Machine::Delegate, public LockProtectedDeleg
 	return [[NSString stringWithUTF8String:name.c_str()] lowercaseString];
 }
 
+#pragma mark - Special machines
+
+- (CSAtari2600 *)atari2600 {
+	return [[CSAtari2600 alloc] initWithAtari2600:_machine->raw_pointer() owner:self];
+}
+
+- (CSZX8081 *)zx8081 {
+	return [[CSZX8081 alloc] initWithZX8081:_machine->raw_pointer() owner:self];
+}
+
 @end
diff --git a/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm b/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm
index da59b2b01..71638ba99 100644
--- a/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm	
+++ b/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm	
@@ -10,7 +10,6 @@
 
 #import "CSMachine.h"
 #import "CSMachine+Target.h"
-#import "CSMachine+Subclassing.h"
 
 #include "StaticAnalyser.hpp"
 
@@ -40,7 +39,7 @@
 		case Analyser::Machine::Electron:	return @"QuickLoadCompositeOptions";
 		case Analyser::Machine::MSX:		return @"QuickLoadCompositeOptions";
 		case Analyser::Machine::Oric:		return @"OricOptions";
-		case Analyser::Machine::Vic20:		return @"Vic20Options";
+		case Analyser::Machine::Vic20:		nil; //return @"Vic20Options";
 		case Analyser::Machine::ZX8081:		return @"ZX8081Options";
 		default: return nil;
 	}
diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAtari2600.h b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAtari2600.h
index c06a072f7..66984889d 100644
--- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAtari2600.h	
+++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAtari2600.h	
@@ -6,14 +6,12 @@
 //  Copyright © 2015 Thomas Harte. All rights reserved.
 //
 
-#include "CSMachine.h"
-#include "Atari2600Inputs.h"
+@class CSAtari2600;
+#import "CSMachine.h"
 
-@interface CSAtari2600 : CSMachine
+@interface CSAtari2600 : NSObject
 
-- (instancetype)init;
-
-- (void)setResetLineEnabled:(BOOL)enabled;
+- (instancetype)initWithAtari2600:(void *)atari2600 owner:(CSMachine *)machine;
 
 @property (nonatomic, assign) BOOL colourButton;
 @property (nonatomic, assign) BOOL leftPlayerDifficultyButton;
diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAtari2600.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAtari2600.mm
index 07d16c923..5f9420719 100644
--- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAtari2600.mm	
+++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSAtari2600.mm	
@@ -9,60 +9,53 @@
 #import "CSAtari2600.h"
 
 #include "Atari2600.hpp"
-#include "TypedDynamicMachine.hpp"
-#import "CSMachine+Subclassing.h"
 
 @implementation CSAtari2600 {
-	Machine::TypedDynamicMachine<Atari2600::Machine> _atari2600;
+	Atari2600::Machine *_atari2600;
+	__weak CSMachine *_machine;
 }
 
-- (instancetype)init {
-	_atari2600 = Machine::TypedDynamicMachine<Atari2600::Machine>(Atari2600::Machine::Atari2600());
-	return nil;//[super initWithMachine:&_atari2600];
-}
-
-- (void)setResetLineEnabled:(BOOL)enabled {
-	@synchronized(self) {
-		_atari2600.get()->set_reset_switch(enabled ? true : false);
+- (instancetype)initWithAtari2600:(void *)atari2600 owner:(CSMachine *)machine {
+	self = [super init];
+	if(self) {
+		_atari2600 = (Atari2600::Machine *)atari2600;
+		_machine = machine;
 	}
+	return self;
 }
 
-- (void)setupOutputWithAspectRatio:(float)aspectRatio {
-	@synchronized(self) {
-		[super setupOutputWithAspectRatio:aspectRatio];
-	}
-}
-
-#pragma mark - Switches
-
 - (void)setColourButton:(BOOL)colourButton {
 	_colourButton = colourButton;
-	@synchronized(self) {
-		_atari2600.get()->set_switch_is_enabled(Atari2600SwitchColour, colourButton);
+
+	@synchronized(_machine) {
+		_atari2600->set_switch_is_enabled(Atari2600SwitchColour, colourButton);
 	}
 }
 
 - (void)setLeftPlayerDifficultyButton:(BOOL)leftPlayerDifficultyButton {
 	_leftPlayerDifficultyButton = leftPlayerDifficultyButton;
-	@synchronized(self) {
-		_atari2600.get()->set_switch_is_enabled(Atari2600SwitchLeftPlayerDifficulty, leftPlayerDifficultyButton);
+
+	@synchronized(_machine) {
+		_atari2600->set_switch_is_enabled(Atari2600SwitchLeftPlayerDifficulty, leftPlayerDifficultyButton);
 	}
 }
 
 - (void)setRightPlayerDifficultyButton:(BOOL)rightPlayerDifficultyButton {
 	_rightPlayerDifficultyButton = rightPlayerDifficultyButton;
-	@synchronized(self) {
-		_atari2600.get()->set_switch_is_enabled(Atari2600SwitchRightPlayerDifficulty, rightPlayerDifficultyButton);
+
+	@synchronized(_machine) {
+		_atari2600->set_switch_is_enabled(Atari2600SwitchRightPlayerDifficulty, rightPlayerDifficultyButton);
 	}
 }
 
 - (void)toggleSwitch:(Atari2600Switch)toggleSwitch {
-	@synchronized(self) {
-		_atari2600.get()->set_switch_is_enabled(toggleSwitch, true);
+	@synchronized(_machine) {
+		_atari2600->set_switch_is_enabled(toggleSwitch, true);
 	}
+
 	dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
-		@synchronized(self) {
-			_atari2600.get()->set_switch_is_enabled(toggleSwitch, false);
+		@synchronized(_machine) {
+			_atari2600->set_switch_is_enabled(toggleSwitch, false);
 		}
 	});
 }
@@ -75,6 +68,4 @@
 	[self toggleSwitch:Atari2600SwitchSelect];
 }
 
-- (NSString *)userDefaultsPrefix {	return @"atari2600";	}
-
 @end
diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.h b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.h
index 7d0fe7889..3133dca67 100644
--- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.h	
+++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.h	
@@ -6,10 +6,12 @@
 //  Copyright © 2017 Thomas Harte. All rights reserved.
 //
 
+@class CSZX8081;
 #import "CSMachine.h"
-#import "CSFastLoading.h"
 
-@interface CSZX8081 : CSMachine <CSFastLoading>
+@interface CSZX8081 : NSObject
+
+- (instancetype)initWithZX8081:(void *)zx8081 owner:(CSMachine *)machine;
 
 @property (nonatomic, assign) BOOL tapeIsPlaying;
 
diff --git a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm
index 86b1adf5b..8067655b4 100644
--- a/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm	
+++ b/OSBindings/Mac/Clock Signal/Machine/Wrappers/CSZX8081.mm	
@@ -9,25 +9,27 @@
 #import "CSZX8081.h"
 
 #include "ZX8081.hpp"
-#include "TypedDynamicMachine.hpp"
 
 @implementation CSZX8081 {
-	Machine::TypedDynamicMachine<ZX8081::Machine> _zx8081;
+	ZX8081::Machine *_zx8081;
+	__weak CSMachine *_machine;
 }
 
-- (instancetype)initWithIntendedTarget:(const Analyser::Static::Target &)target {
-	_zx8081 = Machine::TypedDynamicMachine<ZX8081::Machine>(ZX8081::Machine::ZX8081(target));
-	return nil;//[super initWithMachine:&_zx8081];
+- (instancetype)initWithZX8081:(void *)zx8081 owner:(CSMachine *)machine {
+	self = [super init];
+	if(self) {
+		_zx8081 = (ZX8081::Machine *)zx8081;
+		_machine = machine;
+	}
+	return self;
 }
 
-- (NSString *)userDefaultsPrefix {	return @"zx8081";	}
-
 #pragma mark - Options
 
 - (void)setTapeIsPlaying:(BOOL)tapeIsPlaying {
-	@synchronized(self) {
+	@synchronized(_machine) {
 		_tapeIsPlaying = tapeIsPlaying;
-		_zx8081.get()->set_tape_is_playing(tapeIsPlaying ? true : false);
+		_zx8081->set_tape_is_playing(tapeIsPlaying ? true : false);
 	}
 }