From e53586df1d39c883396aea85f4eb4af310d019d3 Mon Sep 17 00:00:00 2001
From: Thomas Harte <thomas.harte@gmail.com>
Date: Wed, 17 Mar 2021 22:09:44 -0400
Subject: [PATCH] Adds tape-file static analysis for a hypothetical ZX
 Spectrum.

---
 Analyser/Machines.hpp                         |  3 +-
 Analyser/Static/ZXSpectrum/StaticAnalyser.cpp | 46 ++++++++++++++++++-
 2 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/Analyser/Machines.hpp b/Analyser/Machines.hpp
index 2f36858bf..7159408f8 100644
--- a/Analyser/Machines.hpp
+++ b/Analyser/Machines.hpp
@@ -24,7 +24,8 @@ enum class Machine {
 	MSX,
 	Oric,
 	Vic20,
-	ZX8081
+	ZX8081,
+	ZXSpectrum,
 };
 
 }
diff --git a/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp b/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp
index bd9c0acf8..16b772740 100644
--- a/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp
+++ b/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp
@@ -8,6 +8,48 @@
 
 #include "StaticAnalyser.hpp"
 
-Analyser::Static::TargetList Analyser::Static::ZXSpectrum::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) {
-	return {};
+#include "../../../Storage/Tape/Parsers/Spectrum.hpp"
+
+namespace {
+
+bool IsSpectrumTape(const std::shared_ptr<Storage::Tape::Tape> &tape) {
+	using Parser = Storage::Tape::ZXSpectrum::Parser;
+	Parser parser(Parser::MachineType::ZXSpectrum);
+
+	while(true) {
+		const auto block = parser.find_block(tape);
+		if(!block) break;
+
+		// Check for a Spectrum header block.
+		if(block->type == 0x00) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+}
+
+Analyser::Static::TargetList Analyser::Static::ZXSpectrum::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
+	TargetList destination;
+	auto target = std::make_unique<Target>();
+	target->confidence = 0.5;
+
+	if(!media.tapes.empty()) {
+		bool has_spectrum_tape = false;
+		for(auto &tape: media.tapes) {
+			has_spectrum_tape |= IsSpectrumTape(tape);
+		}
+
+		if(has_spectrum_tape) {
+			target->media.tapes = media.tapes;
+		}
+	}
+
+	// If any media survived, add the target.
+	if(!target->media.empty())
+		destination.push_back(std::move(target));
+
+	return destination;
 }