mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			91 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "lib/core/globals.h"
 | |
| #include "lib/decoders/decoders.h"
 | |
| #include "arch/agat/agat.h"
 | |
| #include "lib/core/crc.h"
 | |
| #include "lib/data/fluxmap.h"
 | |
| #include "lib/data/fluxmapreader.h"
 | |
| #include "lib/data/fluxpattern.h"
 | |
| #include "lib/data/sector.h"
 | |
| #include "lib/core/bytes.h"
 | |
| #include "fmt/format.h"
 | |
| #include <string.h>
 | |
| 
 | |
| // clang-format off
 | |
| /*
 | |
|  * data:    X  X  X  X   X  X  X  X   X  -  -  X   -  X  -  X   -  X  X  -   X  -  X  -  = 0xff956a
 | |
|  * flux:   01 01 01 01  01 01 01 01  01 00 10 01  00 01 00 01  00 01 01 00  01 00 01 00  = 0x555549111444
 | |
|  * 
 | |
|  * data:    X  X  X  X   X  X  X  X   -  X  X  -   X  -  X  -   X  -  -  X   -  X  -  X  = 0xff6a95
 | |
|  * flux:   01 01 01 01  01 01 01 01  00 01 01 00  01 00 01 00  01 00 10 01  00 01 00 01  = 0x555514444911
 | |
|  *
 | |
|  * Each pattern is prefixed with this one:
 | |
|  *
 | |
|  * data:          -  -   -  X   -  -   X  - = 0x12
 | |
|  * flux:    (10) 10 10  10 01  00 10  01 00 = 0xa924
 | |
|  * magic:   (10) 10 00  10 01  00 10  01 00 = 0x8924
 | |
|  *                  ^
 | |
|  *
 | |
|  * This seems to be generated by emitting A4 in MFM and then a single 0 bit to
 | |
|  * shift it out of phase, so the data bits become clock bits and vice versa.
 | |
|  *
 | |
|  *           X - X - - X - -  = 0xA4
 | |
|  *          0100010010010010  = MFM encoded
 | |
|  *           1000100100100100 = with trailing zero
 | |
|  *            - - - X - - X - = effective bitstream = 0x12
 | |
|  */
 | |
| // clang-format on
 | |
| 
 | |
| static const FluxPattern SECTOR_PATTERN(64, SECTOR_ID);
 | |
| static const FluxPattern DATA_PATTERN(64, DATA_ID);
 | |
| 
 | |
| static const FluxMatchers ALL_PATTERNS = {&SECTOR_PATTERN, &DATA_PATTERN};
 | |
| 
 | |
| class AgatDecoder : public Decoder
 | |
| {
 | |
| public:
 | |
|     AgatDecoder(const DecoderProto& config): Decoder(config) {}
 | |
| 
 | |
|     nanoseconds_t advanceToNextRecord() override
 | |
|     {
 | |
|         return seekToPattern(ALL_PATTERNS);
 | |
|     }
 | |
| 
 | |
|     void decodeSectorRecord() override
 | |
|     {
 | |
|         if (readRaw64() != SECTOR_ID)
 | |
|             return;
 | |
| 
 | |
|         auto bytes = decodeFmMfm(readRawBits(64)).slice(0, 4);
 | |
|         if (bytes[3] != 0x5a)
 | |
|             return;
 | |
| 
 | |
|         _sector->logicalTrack = bytes[1] >> 1;
 | |
|         _sector->logicalSector = bytes[2];
 | |
|         _sector->logicalSide = bytes[1] & 1;
 | |
|         _sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
 | |
|     }
 | |
| 
 | |
|     void decodeDataRecord() override
 | |
|     {
 | |
|         if (readRaw64() != DATA_ID)
 | |
|             return;
 | |
| 
 | |
|         Bytes bytes = decodeFmMfm(readRawBits((AGAT_SECTOR_SIZE + 2) * 16))
 | |
|                           .slice(0, AGAT_SECTOR_SIZE + 2);
 | |
| 
 | |
|         if (bytes[AGAT_SECTOR_SIZE + 1] != 0x5a)
 | |
|             return;
 | |
| 
 | |
|         _sector->data = bytes.slice(0, AGAT_SECTOR_SIZE);
 | |
|         uint8_t wantChecksum = bytes[AGAT_SECTOR_SIZE];
 | |
|         uint8_t gotChecksum = agatChecksum(_sector->data);
 | |
|         _sector->status =
 | |
|             (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
 | |
|     }
 | |
| };
 | |
| 
 | |
| std::unique_ptr<Decoder> createAgatDecoder(const DecoderProto& config)
 | |
| {
 | |
|     return std::unique_ptr<Decoder>(new AgatDecoder(config));
 | |
| }
 |