mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	Finally make the Amiga encoder work properly. Do some FM/MFM/bits refactoring.
This commit is contained in:
		| @@ -22,13 +22,14 @@ static void write_bits(std::vector<bool>& bits, unsigned& cursor, const std::vec | ||||
| 	for (bool bit : src) | ||||
| 	{ | ||||
| 		if (cursor < bits.size()) | ||||
| 			bits[cursor++] = bit; | ||||
| 			lastBit = bits[cursor++] = bit; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, int width) | ||||
| { | ||||
| 	cursor += width; | ||||
| 	lastBit = data & 1; | ||||
| 	for (int i=0; i<width; i++) | ||||
| 	{ | ||||
| 		unsigned pos = cursor - i - 1; | ||||
| @@ -38,19 +39,16 @@ static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void write_interleaved_bytes(std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes) | ||||
| static void write_bits(std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes) | ||||
| { | ||||
| 	assert(!(bytes.size() & 3)); | ||||
| 	Bytes interleaved = amigaInterleave(bytes); | ||||
| 	encodeMfm(bits, cursor, interleaved, lastBit); | ||||
| } | ||||
| 	ByteReader br(bytes); | ||||
| 	BitReader bitr(br); | ||||
|  | ||||
| static void write_interleaved_bytes(std::vector<bool>& bits, unsigned& cursor, uint32_t data) | ||||
| { | ||||
| 	Bytes b(4); | ||||
| 	ByteWriter bw(b); | ||||
| 	bw.write_be32(data); | ||||
| 	write_interleaved_bytes(bits, cursor, b); | ||||
| 	while (!bitr.eof()) | ||||
| 	{ | ||||
| 		if (cursor < bits.size()) | ||||
| 			bits[cursor++] = bitr.get(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector) | ||||
| @@ -58,11 +56,27 @@ static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector | ||||
| 	if ((sector->data.size() != 512) && (sector->data.size() != 528)) | ||||
| 		Error() << "unsupported sector size --- you must pick 512 or 528"; | ||||
|  | ||||
| 	uint32_t checksum = 0; | ||||
|  | ||||
| 	auto write_interleaved_bytes = [&](const Bytes& bytes) | ||||
| 	{ | ||||
| 		Bytes interleaved = amigaInterleave(bytes); | ||||
| 		Bytes mfm = encodeMfm(interleaved, lastBit); | ||||
| 		checksum ^= amigaChecksum(mfm); | ||||
| 		checksum &= 0x55555555; | ||||
| 		write_bits(bits, cursor, mfm); | ||||
| 	}; | ||||
|  | ||||
| 	auto write_interleaved_word = [&](uint32_t word) | ||||
| 	{ | ||||
| 		Bytes b(4); | ||||
| 		b.writer().write_be32(word); | ||||
| 		write_interleaved_bytes(b); | ||||
| 	}; | ||||
|  | ||||
|     write_bits(bits, cursor, AMIGA_SECTOR_RECORD, 6*8); | ||||
|  | ||||
| 	std::vector<bool> headerBits(20*16); | ||||
| 	unsigned headerCursor = 0; | ||||
|  | ||||
| 	checksum = 0; | ||||
| 	Bytes header =  | ||||
| 		{ | ||||
| 			0xff, /* Amiga 1.0 format byte */ | ||||
| @@ -70,22 +84,16 @@ static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector | ||||
| 			(uint8_t) sector->logicalSector, | ||||
| 			(uint8_t) (AMIGA_SECTORS_PER_TRACK - sector->logicalSector) | ||||
| 		}; | ||||
| 	write_interleaved_bytes(headerBits, headerCursor, header); | ||||
| 	write_interleaved_bytes(header); | ||||
| 	Bytes recoveryInfo(16); | ||||
| 	if (sector->data.size() == 528) | ||||
| 		recoveryInfo = sector->data.slice(512, 16); | ||||
| 	write_interleaved_bytes(headerBits, headerCursor, recoveryInfo); | ||||
| 	write_interleaved_bytes(recoveryInfo); | ||||
| 	write_interleaved_word(checksum); | ||||
|  | ||||
| 	std::vector<bool> dataBits(512*16); | ||||
| 	unsigned dataCursor = 0; | ||||
| 	write_interleaved_bytes(dataBits, dataCursor, sector->data); | ||||
|  | ||||
| 	write_bits(bits, cursor, headerBits); | ||||
| 	uint32_t headerChecksum = amigaChecksum(toBytes(headerBits)); | ||||
| 	write_interleaved_bytes(bits, cursor, headerChecksum); | ||||
| 	uint32_t dataChecksum = amigaChecksum(toBytes(dataBits)); | ||||
| 	write_interleaved_bytes(bits, cursor, dataChecksum); | ||||
| 	write_bits(bits, cursor, dataBits); | ||||
| 	Bytes data = sector->data.slice(0, 512); | ||||
| 	write_interleaved_word(amigaChecksum(encodeMfm(amigaInterleave(data), lastBit))); | ||||
| 	write_interleaved_bytes(data); | ||||
| } | ||||
|  | ||||
| std::unique_ptr<Fluxmap> AmigaEncoder::encode( | ||||
|   | ||||
							
								
								
									
										16
									
								
								lib/bytes.cc
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								lib/bytes.cc
									
									
									
									
									
								
							| @@ -316,6 +316,22 @@ void BitWriter::flush() | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool BitReader::eof() | ||||
| { | ||||
| 	return (_bitcount == 0) && _br.eof(); | ||||
| } | ||||
|  | ||||
| bool BitReader::get() | ||||
| { | ||||
| 	if (_bitcount == 0) | ||||
| 		_fifo = _br.read_8(); | ||||
|  | ||||
| 	bool bit = _fifo & 0x80; | ||||
| 	_fifo <<= 1; | ||||
| 	_bitcount = (_bitcount+1) & 7; | ||||
| 	return bit; | ||||
| } | ||||
|  | ||||
| std::vector<bool> reverseBits(const std::vector<bool>& bits) | ||||
| { | ||||
|     std::vector<bool> output(bits.rbegin(), bits.rend()); | ||||
|   | ||||
							
								
								
									
										19
									
								
								lib/bytes.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								lib/bytes.h
									
									
									
									
									
								
							| @@ -310,6 +310,7 @@ public: | ||||
|     BitWriter(ByteWriter&&) = delete; | ||||
|  | ||||
|     void push(uint32_t bits, size_t size); | ||||
| 	void push(bool bit) { push(bit, 1); } | ||||
|     void flush(); | ||||
|  | ||||
| private: | ||||
| @@ -318,6 +319,24 @@ private: | ||||
|     ByteWriter& _bw; | ||||
| }; | ||||
|  | ||||
| class BitReader | ||||
| { | ||||
| public: | ||||
| 	BitReader(ByteReader& br): | ||||
| 		_br(br) | ||||
| 	{} | ||||
|  | ||||
| 	BitReader(ByteReader&&) = delete; | ||||
|  | ||||
| 	bool get(); | ||||
| 	bool eof(); | ||||
|  | ||||
| private: | ||||
| 	uint8_t _fifo = 0; | ||||
| 	size_t _bitcount = 0; | ||||
| 	ByteReader& _br; | ||||
| }; | ||||
|  | ||||
| static inline uint8_t reverse_bits(uint8_t b) | ||||
| { | ||||
|     b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; | ||||
|   | ||||
| @@ -23,6 +23,7 @@ extern Bytes decodeFmMfm(std::vector<bool>::const_iterator start, | ||||
|     std::vector<bool>::const_iterator end); | ||||
| extern void encodeMfm(std::vector<bool>& bits, unsigned& cursor, const Bytes& input, bool& lastBit); | ||||
| extern void encodeFm(std::vector<bool>& bits, unsigned& cursor, const Bytes& input); | ||||
| extern Bytes encodeMfm(const Bytes& input, bool& lastBit); | ||||
|  | ||||
| static inline Bytes decodeFmMfm(const std::vector<bool> bits) | ||||
| { return decodeFmMfm(bits.begin(), bits.end()); } | ||||
|   | ||||
| @@ -96,3 +96,25 @@ void encodeMfm(std::vector<bool>& bits, unsigned& cursor, const Bytes& input, bo | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| Bytes encodeMfm(const Bytes& input, bool& lastBit) | ||||
| { | ||||
| 	ByteReader br(input); | ||||
| 	BitReader bitr(br); | ||||
| 	Bytes b; | ||||
| 	ByteWriter bw(b); | ||||
| 	BitWriter bitw(bw); | ||||
|  | ||||
| 	while (!bitr.eof()) | ||||
| 	{ | ||||
| 		uint8_t bit = bitr.get(); | ||||
| 		 | ||||
| 		bitw.push(!lastBit && !bit); | ||||
| 		bitw.push(bit); | ||||
| 		lastBit = bit; | ||||
|     } | ||||
|  | ||||
| 	bitw.flush(); | ||||
| 	return b; | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user