mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -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)
|
for (bool bit : src)
|
||||||
{
|
{
|
||||||
if (cursor < bits.size())
|
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)
|
static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, int width)
|
||||||
{
|
{
|
||||||
cursor += width;
|
cursor += width;
|
||||||
|
lastBit = data & 1;
|
||||||
for (int i=0; i<width; i++)
|
for (int i=0; i<width; i++)
|
||||||
{
|
{
|
||||||
unsigned pos = cursor - i - 1;
|
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));
|
ByteReader br(bytes);
|
||||||
Bytes interleaved = amigaInterleave(bytes);
|
BitReader bitr(br);
|
||||||
encodeMfm(bits, cursor, interleaved, lastBit);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void write_interleaved_bytes(std::vector<bool>& bits, unsigned& cursor, uint32_t data)
|
while (!bitr.eof())
|
||||||
{
|
{
|
||||||
Bytes b(4);
|
if (cursor < bits.size())
|
||||||
ByteWriter bw(b);
|
bits[cursor++] = bitr.get();
|
||||||
bw.write_be32(data);
|
}
|
||||||
write_interleaved_bytes(bits, cursor, b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector)
|
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))
|
if ((sector->data.size() != 512) && (sector->data.size() != 528))
|
||||||
Error() << "unsupported sector size --- you must pick 512 or 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);
|
write_bits(bits, cursor, AMIGA_SECTOR_RECORD, 6*8);
|
||||||
|
|
||||||
std::vector<bool> headerBits(20*16);
|
checksum = 0;
|
||||||
unsigned headerCursor = 0;
|
|
||||||
|
|
||||||
Bytes header =
|
Bytes header =
|
||||||
{
|
{
|
||||||
0xff, /* Amiga 1.0 format byte */
|
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) sector->logicalSector,
|
||||||
(uint8_t) (AMIGA_SECTORS_PER_TRACK - sector->logicalSector)
|
(uint8_t) (AMIGA_SECTORS_PER_TRACK - sector->logicalSector)
|
||||||
};
|
};
|
||||||
write_interleaved_bytes(headerBits, headerCursor, header);
|
write_interleaved_bytes(header);
|
||||||
Bytes recoveryInfo(16);
|
Bytes recoveryInfo(16);
|
||||||
if (sector->data.size() == 528)
|
if (sector->data.size() == 528)
|
||||||
recoveryInfo = sector->data.slice(512, 16);
|
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);
|
Bytes data = sector->data.slice(0, 512);
|
||||||
unsigned dataCursor = 0;
|
write_interleaved_word(amigaChecksum(encodeMfm(amigaInterleave(data), lastBit)));
|
||||||
write_interleaved_bytes(dataBits, dataCursor, sector->data);
|
write_interleaved_bytes(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Fluxmap> AmigaEncoder::encode(
|
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> reverseBits(const std::vector<bool>& bits)
|
||||||
{
|
{
|
||||||
std::vector<bool> output(bits.rbegin(), bits.rend());
|
std::vector<bool> output(bits.rbegin(), bits.rend());
|
||||||
|
|||||||
19
lib/bytes.h
19
lib/bytes.h
@@ -310,6 +310,7 @@ public:
|
|||||||
BitWriter(ByteWriter&&) = delete;
|
BitWriter(ByteWriter&&) = delete;
|
||||||
|
|
||||||
void push(uint32_t bits, size_t size);
|
void push(uint32_t bits, size_t size);
|
||||||
|
void push(bool bit) { push(bit, 1); }
|
||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -318,6 +319,24 @@ private:
|
|||||||
ByteWriter& _bw;
|
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)
|
static inline uint8_t reverse_bits(uint8_t b)
|
||||||
{
|
{
|
||||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
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);
|
std::vector<bool>::const_iterator end);
|
||||||
extern void encodeMfm(std::vector<bool>& bits, unsigned& cursor, const Bytes& input, bool& lastBit);
|
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 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)
|
static inline Bytes decodeFmMfm(const std::vector<bool> bits)
|
||||||
{ return decodeFmMfm(bits.begin(), bits.end()); }
|
{ 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