diff --git a/OSBindings/Mac/Clock SignalTests/MacGCRTests.mm b/OSBindings/Mac/Clock SignalTests/MacGCRTests.mm
index d977237d8..16c61f431 100644
--- a/OSBindings/Mac/Clock SignalTests/MacGCRTests.mm	
+++ b/OSBindings/Mac/Clock SignalTests/MacGCRTests.mm	
@@ -163,17 +163,19 @@
 		uint8_t sector_plus_tags[524];
 
 		// Provide tags plus a sector body that are just the sector number ad infinitum.
-		memset(sector_plus_tags, sector_id, sizeof(sector_plus_tags));
+		for(size_t c = 0; c < sizeof(sector_plus_tags); ++c) {
+			sector_plus_tags[c] = uint8_t(sector_id + (c * 3));
+		}
 
 		// NB: sync lengths below are identical to those for
 		// the Apple II, as I have no idea whatsoever what they
 		// should be.
 
 		segment += Storage::Encodings::AppleGCR::Macintosh::header(
-			format,
-			track_id,
+			format ^ c,
+			track_id - c,
 			sector_id,
-			is_side_two
+			is_side_two ^ (c & 1)
 		);
 		segment += Storage::Encodings::AppleGCR::six_and_two_sync(7);
 		segment += Storage::Encodings::AppleGCR::Macintosh::data(sector_id, sector_plus_tags);
@@ -183,8 +185,26 @@
 	// Parse the prepared track to look for sectors.
 	const auto decoded_sectors = Storage::Encodings::AppleGCR::sectors_from_segment(segment);
 
-	// Assert that all sectors fed in were found and correctly decoded.
+	// Assert that the proper number of sectors was found.
 	XCTAssertEqual(decoded_sectors.size(), 8);
+
+	// Assert that the sector descriptions and contents are correct.
+	int sector = 0;
+	for(const auto &pair: decoded_sectors) {
+		XCTAssertFalse(pair.second.has_header_checksum_error);
+		XCTAssertFalse(pair.second.has_data_checksum_error);
+
+		XCTAssertEqual(pair.second.address.is_side_two, is_side_two ^ (sector & 1));
+		XCTAssertEqual(pair.second.address.format, format ^ sector);
+		XCTAssertEqual(pair.second.address.track, track_id - sector);
+		XCTAssertEqual(pair.second.address.sector, sector);
+
+		for(size_t c = 0; c < sizeof(pair.second.data.size()); ++c) {
+			XCTAssertEqual(pair.second.data[c], uint8_t(sector + (c * 3)));
+		}
+
+		++sector;
+	}
 }
 
 @end
diff --git a/Storage/Disk/Encodings/AppleGCR/Sector.hpp b/Storage/Disk/Encodings/AppleGCR/Sector.hpp
index a1a17e7dd..3515a4474 100644
--- a/Storage/Disk/Encodings/AppleGCR/Sector.hpp
+++ b/Storage/Disk/Encodings/AppleGCR/Sector.hpp
@@ -24,8 +24,8 @@ struct Sector {
 		struct {
 			/// For Apple II-type sectors, provides the volume number.
 			uint_fast8_t volume = 0;
-			/// For Macintosh-type sectors, provides the type from the sector header.
-			uint_fast8_t type = 0;
+			/// For Macintosh-type sectors, provides the format from the sector header.
+			uint_fast8_t format = 0;
 		};
 		uint_fast8_t track = 0;
 		uint_fast8_t sector = 0;
diff --git a/Storage/Disk/Encodings/AppleGCR/SegmentParser.cpp b/Storage/Disk/Encodings/AppleGCR/SegmentParser.cpp
index dce175201..1bd7e7947 100644
--- a/Storage/Disk/Encodings/AppleGCR/SegmentParser.cpp
+++ b/Storage/Disk/Encodings/AppleGCR/SegmentParser.cpp
@@ -196,15 +196,67 @@ std::map<std::size_t, Sector> Storage::Encodings::AppleGCR::sectors_from_segment
 							if(out_of_bounds) continue;
 
 							// Test the checksum.
-							if(decoded_header[4] != (decoded_header[0] ^ decoded_header[1] ^ decoded_header[2] ^ decoded_header[3])) continue;
+							if(decoded_header[4] != (decoded_header[0] ^ decoded_header[1] ^ decoded_header[2] ^ decoded_header[3]))
+								sector->has_header_checksum_error = true;
 
 							// Decode the header.
 							sector->address.track = uint8_t(decoded_header[0] | ((decoded_header[2]&0x1f) << 6));
 							sector->address.sector = decoded_header[1];
-							sector->address.type = decoded_header[3];
+							sector->address.format = decoded_header[3];
 							sector->address.is_side_two = decoded_header[2] & 0x20;
 
-							// TODO: sector contents, naturally.
+							// Reverse the GCR encoding of the sector contents to get back to 6-bit data.
+							for(auto &c: sector->data) {
+								c = unmap_six_and_two(c);
+								if(c == 0xff) {
+									out_of_bounds = true;
+									break;
+								}
+							}
+							if(out_of_bounds) continue;
+
+							// The first byte in the sector is a repeat of the sector number; test it
+							// for correctness.
+							if(sector->data[0] != sector->address.sector) continue;
+
+							// Cf. the corresponding section of Encoder.cpp for logic below.
+							int checksum[3] = {0, 0, 0};
+							for(size_t c = 0; c < 175; ++c) {
+								// Calculate the rolling checcksum in order to decode the bytes.
+								checksum[0] = (checksum[0] << 1) | (checksum[0] >> 7);
+
+								// All offsets are +1 below, to skip the initial sector number duplicate.
+								const uint8_t top_bits = sector->data[1 + c*4];
+
+								// Decode first byte.
+								sector->data[0 + c * 3] = uint8_t((sector->data[2 + c*4] + ((top_bits & 0x30) << 2)) ^ checksum[0]);
+								checksum[2] += sector->data[0 + c * 3] + (checksum[0] >> 8);
+
+								// Decode second byte;
+								sector->data[1 + c * 3] = uint8_t((sector->data[3 + c*4] + ((top_bits & 0x0c) << 4)) ^ checksum[2]);
+								checksum[1] += sector->data[1 + c * 3] + (checksum[2] >> 8);
+
+								// Decode third byte, if there is one.
+								if(c != 174) {
+									sector->data[2 + c * 3] = uint8_t((sector->data[4 + c*4] + ((top_bits & 0x03) << 6)) ^ checksum[1]);
+									checksum[0] += sector->data[2 + c * 3] + (checksum[1] >> 8);
+								}
+
+								// Reset carries.
+								checksum[0] &= 0xff;
+								checksum[1] &= 0xff;
+								checksum[2] &= 0xff;
+							}
+
+							// Test the checksum.
+							if(
+								checksum[0] != uint8_t(sector->data[703] + ((sector->data[700] & 0x03) << 6)) ||
+								checksum[1] != uint8_t(sector->data[702] + ((sector->data[700] & 0x0c) << 4)) ||
+								checksum[2] != uint8_t(sector->data[701] + ((sector->data[700] & 0x30) << 2))
+							) sector->has_data_checksum_error = true;
+
+							// Chop to size, and that's that.
+							sector->data.resize(524);
 
 							// Add this sector to the map.
 							sector->encoding = Sector::Encoding::Macintosh;