From 583c3cfe7de7a85af889e72dd11a58d6bb08027d Mon Sep 17 00:00:00 2001
From: Thomas Harte <thomas.harte@gmail.com>
Date: Tue, 16 Jan 2018 22:27:41 -0500
Subject: [PATCH] Allows the MSX to load ROMs that aren't quite multiples of
 8kb.

---
 StaticAnalyser/Acorn/StaticAnalyser.cpp |  2 +-
 StaticAnalyser/MSX/StaticAnalyser.cpp   | 19 +++++++++++++------
 Storage/Cartridge/Cartridge.hpp         | 22 +++++++++++++++++++---
 3 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/StaticAnalyser/Acorn/StaticAnalyser.cpp b/StaticAnalyser/Acorn/StaticAnalyser.cpp
index c1ba2dfd2..ddcc86be4 100644
--- a/StaticAnalyser/Acorn/StaticAnalyser.cpp
+++ b/StaticAnalyser/Acorn/StaticAnalyser.cpp
@@ -24,7 +24,7 @@ static std::list<std::shared_ptr<Storage::Cartridge::Cartridge>>
 		if(segments.size() != 1) continue;
 
 		// which must be 8 or 16 kb in size
-		Storage::Cartridge::Cartridge::Segment segment = segments.front();
+		const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
 		if(segment.data.size() != 0x4000 && segment.data.size() != 0x2000) continue;
 
 		// is a copyright string present?
diff --git a/StaticAnalyser/MSX/StaticAnalyser.cpp b/StaticAnalyser/MSX/StaticAnalyser.cpp
index 6120d5f32..c9aa4f402 100644
--- a/StaticAnalyser/MSX/StaticAnalyser.cpp
+++ b/StaticAnalyser/MSX/StaticAnalyser.cpp
@@ -34,10 +34,10 @@ static std::list<std::shared_ptr<Storage::Cartridge::Cartridge>>
 		// Only one mapped item is allowed.
 		if(segments.size() != 1) continue;
 
-		// Which must be a multiple of 16 kb in size.
+		// Which must be no more than 63 bytes larger than a multiple of 8 kb in size.
 		Storage::Cartridge::Cartridge::Segment segment = segments.front();
 		const size_t data_size = segment.data.size();
-		if(data_size < 0x2000 || data_size & 0x3fff) continue;
+		if(data_size < 0x2000 || (data_size & 0x1fff) > 64) continue;
 
 		// Check for a ROM header at address 0; if it's not found then try 0x4000
 		// and adjust the start address;
@@ -184,10 +184,17 @@ static std::list<std::shared_ptr<Storage::Cartridge::Cartridge>>
 			}
 		}
 
-		// Apply the standard MSX start address.
-		msx_cartridges.emplace_back(new Storage::Cartridge::Cartridge({
-			Storage::Cartridge::Cartridge::Segment(start_address, segment.data)
-		}));
+		// Size down to a multiple of 8kb in size and apply the start address.
+		std::vector<Storage::Cartridge::Cartridge::Segment> output_segments;
+		if(segment.data.size() & 0x1fff) {
+			std::vector<uint8_t> truncated_data;
+			std::vector<uint8_t>::difference_type truncated_size = static_cast<std::vector<uint8_t>::difference_type>(segment.data.size() & ~0x1fff);
+			truncated_data.insert(truncated_data.begin(), segment.data.begin(), segment.data.begin() + truncated_size);
+			output_segments.emplace_back(start_address, truncated_data);
+		} else {
+			output_segments.emplace_back(start_address, segment.data);
+		}
+		msx_cartridges.emplace_back(new Storage::Cartridge::Cartridge(output_segments));
 	}
 
 	return msx_cartridges;
diff --git a/Storage/Cartridge/Cartridge.hpp b/Storage/Cartridge/Cartridge.hpp
index e5dc14c31..3b92b755a 100644
--- a/Storage/Cartridge/Cartridge.hpp
+++ b/Storage/Cartridge/Cartridge.hpp
@@ -28,12 +28,28 @@ namespace Cartridge {
 class Cartridge {
 	public:
 		struct Segment {
-			Segment(size_t start_address, size_t end_address, std::vector<uint8_t> data) :
-				start_address(start_address), end_address(end_address), data(std::move(data)) {}
+			Segment(size_t start_address, size_t end_address, std::vector<uint8_t> &&data) :
+				start_address(start_address), end_address(end_address), data(data) {}
 
-			Segment(size_t start_address, std::vector<uint8_t> data) :
+			Segment(size_t start_address, size_t end_address, const std::vector<uint8_t> &data) :
+				start_address(start_address), end_address(end_address), data(data) {}
+
+			Segment(size_t start_address, std::vector<uint8_t> &&data) :
 				Segment(start_address, start_address + data.size(), data) {}
 
+			Segment(size_t start_address, const std::vector<uint8_t> &data) :
+				Segment(start_address, start_address + data.size(), data) {}
+
+			Segment(Segment &&segment) :
+				start_address(segment.start_address),
+				end_address(segment.end_address),
+				data(std::move(segment.data)) {}
+
+			Segment(const Segment &segment) :
+				start_address(segment.start_address),
+				end_address(segment.end_address),
+				data(segment.data) {}
+
 			/// Indicates that an address is unknown.
 			static const size_t UnknownAddress;