mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-31 11:17:01 -07:00 
			
		
		
		
	Two bugs make a right, mostly. The very last carry should be ignored and when adding the low and high bytes they commonly would commonly produce a carry which was being ignored. On the test disks these two bugs cancelled themselves out, except only for track 1, side 1, sector 0. I had noticed it was suspicously off-by-one earlier for both test disks, but the cause wasn't obvious. On some old 1980s disks, with real data, it changed number of bad sectors from 224 (out of 2464) to 5 for one disk and 81 to 3 for another.
		
			
				
	
	
		
			62 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			62 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "globals.h"
 | |
| #include "fluxmap.h"
 | |
| #include "decoders/fluxmapreader.h"
 | |
| #include "decoders/decoders.h"
 | |
| #include "sector.h"
 | |
| #include "micropolis.h"
 | |
| #include "bytes.h"
 | |
| #include "fmt/format.h"
 | |
| 
 | |
| /* The sector has a preamble of MFM 0x00s and uses 0xFF as a sync pattern. */
 | |
| static const FluxPattern SECTOR_SYNC_PATTERN(32, 0xaaaa5555);
 | |
| 
 | |
| AbstractDecoder::RecordType MicropolisDecoder::advanceToNextRecord()
 | |
| {
 | |
| 	_fmr->seekToIndexMark();
 | |
| 	const FluxMatcher* matcher = nullptr;
 | |
| 	_sector->clock = _fmr->seekToPattern(SECTOR_SYNC_PATTERN, matcher);
 | |
| 	if (matcher == &SECTOR_SYNC_PATTERN) {
 | |
| 		readRawBits(16);
 | |
| 		return SECTOR_RECORD;
 | |
| 	}
 | |
| 	return UNKNOWN_RECORD;
 | |
| }
 | |
| 
 | |
| /* Adds all bytes, with carry. */
 | |
| static uint8_t checksum(const Bytes& bytes) {
 | |
| 	ByteReader br(bytes);
 | |
| 	uint16_t sum = 0;
 | |
| 	while (!br.eof()) {
 | |
| 		if (sum > 0xFF) {
 | |
| 			sum -= 0x100 - 1;
 | |
| 		}
 | |
| 		sum += br.read_8();
 | |
| 	}
 | |
| 	/* The last carry is ignored */
 | |
| 	return sum & 0xFF;
 | |
| }
 | |
| 
 | |
| void MicropolisDecoder::decodeSectorRecord()
 | |
| {
 | |
| 	auto rawbits = readRawBits(MICROPOLIS_ENCODED_SECTOR_SIZE*16);
 | |
| 	auto bytes = decodeFmMfm(rawbits).slice(0, MICROPOLIS_ENCODED_SECTOR_SIZE);
 | |
| 	ByteReader br(bytes);
 | |
| 
 | |
| 	br.read_8();  /* sync */
 | |
| 	_sector->logicalTrack = br.read_8();
 | |
| 	_sector->logicalSide = _sector->physicalSide;
 | |
| 	_sector->logicalSector = br.read_8();
 | |
| 	if (_sector->logicalSector > 15)
 | |
| 		return;
 | |
| 	if (_sector->logicalTrack > 77)
 | |
| 		return;
 | |
| 
 | |
| 	br.read(10);  /* OS data or padding */
 | |
| 	_sector->data = br.read(256);
 | |
| 	uint8_t wantChecksum = br.read_8();
 | |
| 	uint8_t gotChecksum = checksum(bytes.slice(1, 2+266));
 | |
| 	br.read(5);  /* 4 byte ECC and ECC-present flag */
 | |
| 
 | |
| 	_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | |
| }
 |