diff --git a/OSBindings/Qt/mainwindow.cpp b/OSBindings/Qt/mainwindow.cpp
index 8b96cbcdb..df942ac03 100644
--- a/OSBindings/Qt/mainwindow.cpp
+++ b/OSBindings/Qt/mainwindow.cpp
@@ -251,33 +251,33 @@ void MainWindow::tile(const QMainWindow *previous) {
 
 void MainWindow::launchMachine() {
 	const QStringList appDataLocations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation);
-	missingRoms.clear();
 
 	ROMMachine::ROMFetcher rom_fetcher = [&appDataLocations, this]
-		(const std::vector<ROMMachine::ROM> &roms) -> std::vector<std::unique_ptr<std::vector<uint8_t>>> {
-		std::vector<std::unique_ptr<std::vector<uint8_t>>> results;
+		(const ROM::Request &roms) -> std::vector<std::unique_ptr<std::vector<uint8_t>>> {
+		ROM::Map results;
 
-		for(const auto &rom: roms) {
-			FILE *file = nullptr;
-			for(const auto &path: appDataLocations) {
-				const std::string source = path.toStdString() + "/ROMImages/" + rom.machine_name + "/" + rom.file_name;
-				const std::string nativeSource = QDir::toNativeSeparators(QString::fromStdString(source)).toStdString();
+		for(const auto &description: roms.all_descriptions()) {
+			for(const auto &file_name: description.file_names) {
+				FILE *file = nullptr;
+				for(const auto &path: appDataLocations) {
+					const std::string source = path.toStdString() + "/ROMImages/" + description.machine_name + "/" + file_name;
+					const std::string nativeSource = QDir::toNativeSeparators(QString::fromStdString(source)).toStdString();
 
-				file = fopen(nativeSource.c_str(), "rb");
-				if(file) break;
-			}
+					file = fopen(nativeSource.c_str(), "rb");
+					if(file) break;
+				}
 
-			if(file) {
-				auto data = fileContentsAndClose(file);
-				if(data) {
-					results.push_back(std::move(data));
-					continue;
+				if(file) {
+					auto data = fileContentsAndClose(file);
+					if(data) {
+						results[description.name] = std::move(data);
+						continue;
+					}
 				}
 			}
-
-			results.push_back(nullptr);
-			missingRoms.push_back(rom);
 		}
+
+		missingRoms = roms.subtract(results);
 		return results;
 	};
 	Machine::Error error;
@@ -291,22 +291,7 @@ void MainWindow::launchMachine() {
 
 				// Populate request text.
 				QString requestText = romRequestBaseText;
-				size_t index = 0;
-				for(const auto &rom: missingRoms) {
-					requestText += "• ";
-					requestText += rom.descriptive_name.c_str();
-
-					++index;
-					if(index == missingRoms.size()) {
-						requestText += ".\n";
-						continue;
-					}
-					if(index == missingRoms.size() - 1) {
-						requestText += "; and\n";
-						continue;
-					}
-					requestText += ";\n";
-				}
+				requestText += missingRoms.description(0, L'•');
 				ui->missingROMsBox->setPlainText(requestText);
 			} break;
 		}
@@ -736,28 +721,23 @@ void MainWindow::dropEvent(QDropEvent* event) {
 				CRC::CRC32 generator;
 				const uint32_t crc = generator.compute_crc(*contents);
 
-				bool wasUsed = false;
-				for(const auto &rom: missingRoms) {
-					if(std::find(rom.crc32s.begin(), rom.crc32s.end(), crc) != rom.crc32s.end()) {
-						foundROM = true;
+				std::optional<ROM::Description> target = ROM::Description::from_crc(crc);
+				if(target) {
+					// Ensure the destination folder exists.
+					const std::string path = appDataLocation + "/ROMImages/" + rom.machine_name;
+					const QDir dir(QString::fromStdString(path));
+					if (!dir.exists())
+						dir.mkpath(".");
 
-						// Ensure the destination folder exists.
-						const std::string path = appDataLocation + "/ROMImages/" + rom.machine_name;
-						const QDir dir(QString::fromStdString(path));
-						if (!dir.exists())
-							dir.mkpath(".");
+					// Write into place.
+					const std::string destination =  QDir::toNativeSeparators(QString::fromStdString(path+ "/" + rom.file_name)).toStdString();
+					FILE *const target = fopen(destination.c_str(), "wb");
+					fwrite(contents->data(), 1, contents->size(), target);
+					fclose(target);
 
-						// Write into place.
-						const std::string destination =  QDir::toNativeSeparators(QString::fromStdString(path+ "/" + rom.file_name)).toStdString();
-						FILE *const target = fopen(destination.c_str(), "wb");
-						fwrite(contents->data(), 1, contents->size(), target);
-						fclose(target);
-
-						wasUsed = true;
-					}
-				}
-
-				if(!wasUsed) {
+					// Note that at least one meaningful ROM was supplied.
+					foundROM = true;
+				} else {
 					if(!unusedRoms.isEmpty()) unusedRoms += ", ";
 					unusedRoms += url.fileName();
 				}
diff --git a/OSBindings/Qt/mainwindow.h b/OSBindings/Qt/mainwindow.h
index ec25e1470..b83f92633 100644
--- a/OSBindings/Qt/mainwindow.h
+++ b/OSBindings/Qt/mainwindow.h
@@ -60,7 +60,7 @@ class MainWindow : public QMainWindow, public Outputs::Speaker::Speaker::Delegat
 		void launchMachine();
 
 		QString romRequestBaseText;
-		std::vector<ROMMachine::ROM> missingRoms;
+		ROM::Request missingRoms;
 
 		// File drag and drop is supported.
 		void dragEnterEvent(QDragEnterEvent* event) override;