diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj
index 6947d5a15..9d63cc952 100644
--- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj	
+++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj	
@@ -340,8 +340,8 @@
 		4BC9DF4F1D04691600F44158 /* 6560.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC9DF4D1D04691600F44158 /* 6560.cpp */; };
 		4BC9E1EE1D23449A003FCEE4 /* 6502InterruptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BC9E1ED1D23449A003FCEE4 /* 6502InterruptTests.swift */; };
 		4BD5F1951D13528900631CD1 /* CSBestEffortUpdater.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.m */; };
-		4BEE0A641D72454000532C7B /* PRG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A621D72454000532C7B /* PRG.cpp */; };
-		4BEE0A681D7248B300532C7B /* ROM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A661D7248B300532C7B /* ROM.cpp */; };
+		4BEE0A6F1D72496600532C7B /* Cartridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6A1D72496600532C7B /* Cartridge.cpp */; };
+		4BEE0A701D72496600532C7B /* PRG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6D1D72496600532C7B /* PRG.cpp */; };
 		4BEF6AAA1D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BEF6AA91D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm */; };
 		4BEF6AAC1D35D1C400E73575 /* DPLLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */; };
 		4BF1354C1D6D2C300054B2EA /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1354A1D6D2C300054B2EA /* StaticAnalyser.cpp */; };
@@ -763,10 +763,10 @@
 		4BCA98C21D065CA20062F44C /* 6522.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6522.hpp; sourceTree = "<group>"; };
 		4BD5F1931D13528900631CD1 /* CSBestEffortUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSBestEffortUpdater.h; path = Updater/CSBestEffortUpdater.h; sourceTree = "<group>"; };
 		4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CSBestEffortUpdater.m; path = Updater/CSBestEffortUpdater.m; sourceTree = "<group>"; };
-		4BEE0A621D72454000532C7B /* PRG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PRG.cpp; path = ROM/PRG.cpp; sourceTree = "<group>"; };
-		4BEE0A631D72454000532C7B /* PRG.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = PRG.hpp; path = ROM/PRG.hpp; sourceTree = "<group>"; };
-		4BEE0A661D7248B300532C7B /* ROM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ROM.cpp; path = ROM/ROM.cpp; sourceTree = "<group>"; };
-		4BEE0A671D7248B300532C7B /* ROM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ROM.hpp; path = ROM/ROM.hpp; sourceTree = "<group>"; };
+		4BEE0A6A1D72496600532C7B /* Cartridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Cartridge.cpp; sourceTree = "<group>"; };
+		4BEE0A6B1D72496600532C7B /* Cartridge.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Cartridge.hpp; sourceTree = "<group>"; };
+		4BEE0A6D1D72496600532C7B /* PRG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PRG.cpp; sourceTree = "<group>"; };
+		4BEE0A6E1D72496600532C7B /* PRG.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PRG.hpp; sourceTree = "<group>"; };
 		4BEF6AA81D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DigitalPhaseLockedLoopBridge.h; sourceTree = "<group>"; };
 		4BEF6AA91D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DigitalPhaseLockedLoopBridge.mm; sourceTree = "<group>"; };
 		4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DPLLTests.swift; sourceTree = "<group>"; };
@@ -994,9 +994,9 @@
 				4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */,
 				4BAB62AE1D32730D00DF5BA0 /* Storage.hpp */,
 				4BB697CA1D4B6D3E00248BDF /* TimedEventLoop.hpp */,
+				4BEE0A691D72496600532C7B /* Cartridge */,
 				4BAB62AA1D3272D200DF5BA0 /* Disk */,
 				4B69FB3A1C4D908A00B5F0AA /* Tape */,
-				4BEE0A651D72454400532C7B /* ROM */,
 			);
 			name = Storage;
 			path = ../../Storage;
@@ -1530,15 +1530,23 @@
 			path = Resources;
 			sourceTree = "<group>";
 		};
-		4BEE0A651D72454400532C7B /* ROM */ = {
+		4BEE0A691D72496600532C7B /* Cartridge */ = {
 			isa = PBXGroup;
 			children = (
-				4BEE0A621D72454000532C7B /* PRG.cpp */,
-				4BEE0A631D72454000532C7B /* PRG.hpp */,
-				4BEE0A661D7248B300532C7B /* ROM.cpp */,
-				4BEE0A671D7248B300532C7B /* ROM.hpp */,
+				4BEE0A6A1D72496600532C7B /* Cartridge.cpp */,
+				4BEE0A6B1D72496600532C7B /* Cartridge.hpp */,
+				4BEE0A6C1D72496600532C7B /* Formats */,
 			);
-			name = ROM;
+			path = Cartridge;
+			sourceTree = "<group>";
+		};
+		4BEE0A6C1D72496600532C7B /* Formats */ = {
+			isa = PBXGroup;
+			children = (
+				4BEE0A6D1D72496600532C7B /* PRG.cpp */,
+				4BEE0A6E1D72496600532C7B /* PRG.hpp */,
+			);
+			path = Formats;
 			sourceTree = "<group>";
 		};
 		4BF1354D1D6D2C360054B2EA /* StaticAnalyser */ = {
@@ -1963,7 +1971,6 @@
 				4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */,
 				4BBF99151C8FBA6F0075DAFB /* CRTOpenGL.cpp in Sources */,
 				4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */,
-				4BEE0A681D7248B300532C7B /* ROM.cpp in Sources */,
 				4BB697C71D4B558F00248BDF /* Factors.cpp in Sources */,
 				4B55CE591C3B7D360093A61B /* ElectronDocument.swift in Sources */,
 				4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */,
@@ -1973,7 +1980,6 @@
 				4BD5F1951D13528900631CD1 /* CSBestEffortUpdater.m in Sources */,
 				4B0BE4281D3481E700D5256B /* DigitalPhaseLockedLoop.cpp in Sources */,
 				4B73C71A1D036BD90074D992 /* Vic20Document.swift in Sources */,
-				4BEE0A641D72454000532C7B /* PRG.cpp in Sources */,
 				4BBF99181C8FBA6F0075DAFB /* TextureTarget.cpp in Sources */,
 				4BC76E691C98E31700E6EF73 /* FIRFilter.cpp in Sources */,
 				4B55CE5F1C3B7D960093A61B /* MachineDocument.swift in Sources */,
@@ -1999,6 +2005,8 @@
 				4BC3B7521CD1956900F86E85 /* OutputShader.cpp in Sources */,
 				4B4C83701D4F623200CD541F /* D64.cpp in Sources */,
 				4B14145B1B58879D00E04248 /* CPU6502.cpp in Sources */,
+				4BEE0A6F1D72496600532C7B /* Cartridge.cpp in Sources */,
+				4BEE0A701D72496600532C7B /* PRG.cpp in Sources */,
 				4B2A53A01D117D36003C6002 /* CSMachine.mm in Sources */,
 				4BC91B831D1F160E00884B76 /* CommodoreTAP.cpp in Sources */,
 				4B2A539F1D117D36003C6002 /* CSAudioQueue.m in Sources */,
diff --git a/StaticAnalyser/StaticAnalyser.cpp b/StaticAnalyser/StaticAnalyser.cpp
index 083edaee0..a808a1bc0 100644
--- a/StaticAnalyser/StaticAnalyser.cpp
+++ b/StaticAnalyser/StaticAnalyser.cpp
@@ -10,6 +10,8 @@
 
 #include <cstdlib>
 
+#include "../Storage/Cartridge/Formats/PRG.hpp"
+
 #include "../Storage/Disk/Formats/D64.hpp"
 #include "../Storage/Disk/Formats/G64.hpp"
 
@@ -50,8 +52,13 @@ std::list<Target> StaticAnalyser::GetTargets(const char *file_name)
 	// union of all platforms this file might be a target for.
 	std::list<std::shared_ptr<Storage::Disk::Disk>> disks;
 	std::list<std::shared_ptr<Storage::Tape::Tape>> tapes;
+	std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> cartridges;
 	TargetPlatformType potential_platforms = 0;
 
+#define Insert(list, class, platforms) \
+	list.emplace_back(new Storage::class(file_name));\
+	potential_platforms |= (TargetPlatformType)(platforms);\
+
 #define Format(extension, list, class, platforms) \
 	if(!strcmp(lowercase_extension, extension))	\
 	{	\
@@ -79,12 +86,12 @@ std::list<Target> StaticAnalyser::GetTargets(const char *file_name)
 	{
 		// try instantiating as a ROM; failing that accept as a tape
 		try {
+			Insert(cartridges, Cartridge::PRG, TargetPlatform::Commodore)
 		}
 		catch(...)
 		{
 			try {
-				tapes.emplace_back(new Storage::Tape::PRG(file_name));
-				potential_platforms |= (TargetPlatformType)TargetPlatform::Commodore;
+				Insert(tapes, Tape::PRG, TargetPlatform::Commodore)
 			} catch(...) {}
 		}
 	}
@@ -98,6 +105,7 @@ std::list<Target> StaticAnalyser::GetTargets(const char *file_name)
 	Format("uef", tapes, Tape::UEF, TargetPlatform::Acorn)				// UEF (tape)
 
 #undef Format
+#undef Insert
 
 	// Hand off to platform-specific determination of whether these things are actually compatible and,
 	// if so, how to load them. (TODO)
diff --git a/StaticAnalyser/StaticAnalyser.hpp b/StaticAnalyser/StaticAnalyser.hpp
index f229128b1..d7810ada9 100644
--- a/StaticAnalyser/StaticAnalyser.hpp
+++ b/StaticAnalyser/StaticAnalyser.hpp
@@ -11,6 +11,8 @@
 
 #include "../Storage/Tape/Tape.hpp"
 #include "../Storage/Disk/Disk.hpp"
+#include "../Storage/Cartridge/Cartridge.hpp"
+
 #include <string>
 #include <list>
 #include <vector>
@@ -54,7 +56,7 @@ struct Target {
 
 	std::list<std::shared_ptr<Storage::Disk::Disk>> disks;
 	std::list<std::shared_ptr<Storage::Tape::Tape>> tapes;
-	// TODO: ROMs. Probably can't model as raw data, but then how to handle bus complexities?
+	std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> cartridges;
 };
 
 std::list<Target> GetTargets(const char *file_name);
diff --git a/Storage/ROM/ROM.cpp b/Storage/Cartridge/Cartridge.cpp
similarity index 84%
rename from Storage/ROM/ROM.cpp
rename to Storage/Cartridge/Cartridge.cpp
index 904e7a527..eef001e7b 100644
--- a/Storage/ROM/ROM.cpp
+++ b/Storage/Cartridge/Cartridge.cpp
@@ -6,4 +6,4 @@
 //  Copyright © 2016 Thomas Harte. All rights reserved.
 //
 
-#include "ROM.hpp"
+#include "Cartridge.hpp"
diff --git a/Storage/ROM/ROM.hpp b/Storage/Cartridge/Cartridge.hpp
similarity index 59%
rename from Storage/ROM/ROM.hpp
rename to Storage/Cartridge/Cartridge.hpp
index 08ffd024c..902684072 100644
--- a/Storage/ROM/ROM.hpp
+++ b/Storage/Cartridge/Cartridge.hpp
@@ -1,18 +1,18 @@
 //
-//  ROM.hpp
+//  Cartridge.hpp
 //  Clock Signal
 //
 //  Created by Thomas Harte on 27/08/2016.
 //  Copyright © 2016 Thomas Harte. All rights reserved.
 //
 
-#ifndef ROM_hpp
-#define ROM_hpp
+#ifndef Storage_Cartridge_hpp
+#define Storage_Cartridge_hpp
 
 namespace Storage {
-namespace ROM {
+namespace Cartridge {
 
-class ROM {};
+class Cartridge {};
 
 }
 }
diff --git a/Storage/ROM/PRG.cpp b/Storage/Cartridge/Formats/PRG.cpp
similarity index 97%
rename from Storage/ROM/PRG.cpp
rename to Storage/Cartridge/Formats/PRG.cpp
index 66ea7c78d..422edd621 100644
--- a/Storage/ROM/PRG.cpp
+++ b/Storage/Cartridge/Formats/PRG.cpp
@@ -11,7 +11,7 @@
 #include <cstdio>
 #include <sys/stat.h>
 
-using namespace Storage::ROM;
+using namespace Storage::Cartridge;
 
 PRG::PRG(const char *file_name) : _contents(nullptr)
 {
diff --git a/Storage/ROM/PRG.hpp b/Storage/Cartridge/Formats/PRG.hpp
similarity index 69%
rename from Storage/ROM/PRG.hpp
rename to Storage/Cartridge/Formats/PRG.hpp
index decd58ab6..2ad1adefc 100644
--- a/Storage/ROM/PRG.hpp
+++ b/Storage/Cartridge/Formats/PRG.hpp
@@ -6,16 +6,16 @@
 //  Copyright © 2016 Thomas Harte. All rights reserved.
 //
 
-#ifndef PRG_hpp
-#define PRG_hpp
+#ifndef Storage_Cartridge_PRG_hpp
+#define Storage_Cartridge_PRG_hpp
 
 #include <vector>
-#include "ROM.hpp"
+#include "../Cartridge.hpp"
 
 namespace Storage {
-namespace ROM {
+namespace Cartridge {
 
-class PRG : public ROM {
+class PRG : public Cartridge {
 	public:
 		PRG(const char *file_name);
 		~PRG();