mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			93 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "globals.h"
 | |
| #include "fluxmap.h"
 | |
| #include "decoders/fluxmapreader.h"
 | |
| #include "protocol.h"
 | |
| #include "record.h"
 | |
| #include "decoders/decoders.h"
 | |
| #include "sector.h"
 | |
| #include "c64.h"
 | |
| #include "crc.h"
 | |
| #include "bytes.h"
 | |
| #include "fmt/format.h"
 | |
| #include <string.h>
 | |
| #include <algorithm>
 | |
| 
 | |
| const FluxPattern SECTOR_RECORD_PATTERN(20, C64_SECTOR_RECORD);
 | |
| const FluxPattern DATA_RECORD_PATTERN(20, C64_DATA_RECORD);
 | |
| const FluxMatchers ANY_RECORD_PATTERN({ &SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN });
 | |
| 
 | |
| static int decode_data_gcr(uint8_t gcr)
 | |
| {
 | |
|     switch (gcr)
 | |
|     {
 | |
| 		#define GCR_ENTRY(gcr, data) \
 | |
| 			case gcr: return data;
 | |
| 		#include "data_gcr.h"
 | |
| 		#undef GCR_ENTRY
 | |
|     }
 | |
|     return -1;
 | |
| };
 | |
| 
 | |
| static Bytes decode(const std::vector<bool>& bits)
 | |
| {
 | |
|     Bytes output;
 | |
|     ByteWriter bw(output);
 | |
|     BitWriter bitw(bw);
 | |
| 
 | |
|     auto ii = bits.begin();
 | |
|     while (ii != bits.end())
 | |
|     {
 | |
|         uint8_t inputfifo = 0;
 | |
|         for (size_t i=0; i<5; i++)
 | |
|         {
 | |
|             if (ii == bits.end())
 | |
|                 break;
 | |
|             inputfifo = (inputfifo<<1) | *ii++;
 | |
|         }
 | |
| 
 | |
|         bitw.push(decode_data_gcr(inputfifo), 4);
 | |
|     }
 | |
|     bitw.flush();
 | |
| 
 | |
|     return output;
 | |
| }
 | |
| 
 | |
| AbstractDecoder::RecordType Commodore64Decoder::advanceToNextRecord()
 | |
| {
 | |
| 	const FluxMatcher* matcher = nullptr;
 | |
| 	_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
 | |
| 	if (matcher == &SECTOR_RECORD_PATTERN)
 | |
| 		return RecordType::SECTOR_RECORD;
 | |
| 	if (matcher == &DATA_RECORD_PATTERN)
 | |
| 		return RecordType::DATA_RECORD;
 | |
| 	return RecordType::UNKNOWN_RECORD;
 | |
| }
 | |
| 
 | |
| void Commodore64Decoder::decodeSectorRecord()
 | |
| {
 | |
|     readRawBits(20);
 | |
| 
 | |
|     const auto& bits = readRawBits(5*10);
 | |
|     const auto& bytes = decode(bits).slice(0, 5);
 | |
| 
 | |
|     uint8_t checksum = bytes[0];
 | |
|     _sector->logicalSector = bytes[1];
 | |
|     _sector->logicalSide = 0;
 | |
|     _sector->logicalTrack = bytes[2] - 1;
 | |
|     if (checksum == xorBytes(bytes.slice(1, 4)))
 | |
|         _sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | |
| }
 | |
| 
 | |
| void Commodore64Decoder::decodeDataRecord()
 | |
| {
 | |
|     readRawBits(20);
 | |
| 
 | |
|     const auto& bits = readRawBits(259*10);
 | |
|     const auto& bytes = decode(bits).slice(0, 259);
 | |
| 
 | |
|     _sector->data = bytes.slice(0, C64_SECTOR_LENGTH);
 | |
|     uint8_t gotChecksum = xorBytes(_sector->data);
 | |
|     uint8_t wantChecksum = bytes[256];
 | |
|     _sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | |
| }
 |