diff --git a/Storage/Disk/Encodings/MFM.cpp b/Storage/Disk/Encodings/MFM.cpp index 12a0d7721..ef6a9846f 100644 --- a/Storage/Disk/Encodings/MFM.cpp +++ b/Storage/Disk/Encodings/MFM.cpp @@ -12,27 +12,120 @@ using namespace Storage::Encodings::MFM; -std::shared_ptr Storage::Encodings::MFM::GetMFMTrackWithSectors(const std::vector §ors) -{ - class MFMVectorShifter: public MFMShifter { - void output_short(uint16_t value) { - data.push_back(value & 0xff); - data.push_back(value >> 8); +template class Shifter { + public: + virtual void add_byte(uint8_t input) = 0; + virtual void add_index_address_mark() = 0; + virtual void add_ID_address_mark() = 0; + virtual void add_data_address_mark() = 0; + virtual void add_deleted_data_address_mark() = 0; + + protected: + // override me! + void output_short(uint16_t value); +}; + +template class MFMShifter: public Shifter { + public: + void add_byte(uint8_t input) { + uint16_t spread_value = + (uint16_t)( + ((input & 0x01) << 0) | + ((input & 0x02) << 1) | + ((input & 0x04) << 2) | + ((input & 0x08) << 3) | + ((input & 0x10) << 4) | + ((input & 0x20) << 5) | + ((input & 0x40) << 6) | + ((input & 0x80) << 7) + ); + uint16_t or_bits = (uint16_t)((spread_value << 1) | (spread_value >> 1) | (output_ << 15)); + output_ = spread_value | ((~or_bits) & 0xaaaa); + static_cast(this)->output_short(output_); } - std::vector data; - } shifter; + void add_index_address_mark() { + static_cast(this)->output_short(output_ = 0x5224); + add_byte(0xfc); + } + + void add_ID_address_mark() { + static_cast(this)->output_short(output_ = 0x4489); + add_byte(0xfe); + } + + void add_data_address_mark() { + static_cast(this)->output_short(output_ = 0x4489); + add_byte(0xfb); + } + + void add_deleted_data_address_mark() { + static_cast(this)->output_short(output_ = 0x4489); + add_byte(0xf8); + } + + private: + uint16_t output_; +}; + +template class FMShifter: public Shifter { + public: + void add_byte(uint8_t input) { + static_cast(this)->output_short( + (uint16_t)( + ((input & 0x01) << 1) | + ((input & 0x02) << 2) | + ((input & 0x04) << 3) | + ((input & 0x08) << 4) | + ((input & 0x10) << 5) | + ((input & 0x20) << 6) | + ((input & 0x40) << 7) | + ((input & 0x80) << 8) | + 0x5555 + )); + } + + void add_index_address_mark() { + // data 0xfc, with clock 0xd7 => 1111 1100 with clock 1101 0111 => 1111 1011 1011 0101 + static_cast(this)->output_short(0xfbb5); + } + + void add_ID_address_mark() { + // data 0xfe, with clock 0xc7 => 1111 1110 with clock 1100 0111 => 1111 1010 1011 1101 + static_cast(this)->output_short(0xfabd); + } + + void add_data_address_mark() { + // data 0xfb, with clock 0xc7 => 1111 1011 with clock 1100 0111 => 1111 1010 1001 1111 + static_cast(this)->output_short(0xfa9f); + } + + void add_deleted_data_address_mark() { + // data 0xf8, with clock 0xc7 => 1111 1000 with clock 1100 0111 => 1111 1010 1001 0101 + static_cast(this)->output_short(0xfa95); + } +}; + +template std::shared_ptr + GetTrackWithSectors( + const std::vector §ors, + size_t post_index_address_mark_bytes, uint8_t post_index_address_mark_value, + size_t pre_address_mark_bytes, size_t post_address_mark_bytes, + size_t pre_data_mark_bytes, size_t post_data_bytes, + size_t inter_sector_gap) +{ + T shifter; // output the index mark shifter.add_index_address_mark(); // add the post-index mark - for(int c = 0; c < 50; c++) shifter.add_byte(0x4e); + for(int c = 0; c < post_index_address_mark_bytes; c++) shifter.add_byte(post_index_address_mark_value); // add sectors for(const Sector §or : sectors) { - for(int c = 0; c < 12; c++) shifter.add_byte(0x00); + for(int c = 0; c < pre_address_mark_bytes; c++) shifter.add_byte(0x00); shifter.add_ID_address_mark(); shifter.add_byte(sector.track); @@ -49,15 +142,15 @@ std::shared_ptr Storage::Encodings::MFM::GetMFMTrackWithSe } // TODO: CRC of bytes since the track number - for(int c = 0; c < 22; c++) shifter.add_byte(0x4e); - for(int c = 0; c < 12; c++) shifter.add_byte(0x00); + for(int c = 0; c < post_address_mark_bytes; c++) shifter.add_byte(0x4e); + for(int c = 0; c < pre_data_mark_bytes; c++) shifter.add_byte(0x00); shifter.add_data_address_mark(); for(size_t c = 0; c < sector.data.size(); c++) shifter.add_byte(sector.data[c]); // TODO: CRC of data - for(int c = 0; c < 18; c++) shifter.add_byte(0x00); - for(int c = 0; c < 32; c++) shifter.add_byte(0x4e); + for(int c = 0; c < post_data_bytes; c++) shifter.add_byte(0x00); + for(int c = 0; c < inter_sector_gap; c++) shifter.add_byte(0x4e); } // TODO: total size check @@ -65,3 +158,40 @@ std::shared_ptr Storage::Encodings::MFM::GetMFMTrackWithSe Storage::Disk::PCMSegment segment; return std::shared_ptr(new Storage::Disk::PCMTrack(std::move(segment))); } + + +std::shared_ptr Storage::Encodings::MFM::GetFMTrackWithSectors(const std::vector §ors) +{ + struct VectorShifter: public FMShifter { + void output_short(uint16_t value) { + data.push_back(value & 0xff); + data.push_back(value >> 8); + } + std::vector data; + }; + + return GetTrackWithSectors( + sectors, + 16, 0x00, + 6, 0, + 17, 14, + 0); +} + +std::shared_ptr Storage::Encodings::MFM::GetMFMTrackWithSectors(const std::vector §ors) +{ + struct VectorShifter: public MFMShifter { + void output_short(uint16_t value) { + data.push_back(value & 0xff); + data.push_back(value >> 8); + } + std::vector data; + }; + + return GetTrackWithSectors( + sectors, + 50, 0x4e, + 12, 22, + 12, 18, + 32); +} diff --git a/Storage/Disk/Encodings/MFM.hpp b/Storage/Disk/Encodings/MFM.hpp index bd5ca8210..543896559 100644 --- a/Storage/Disk/Encodings/MFM.hpp +++ b/Storage/Disk/Encodings/MFM.hpp @@ -17,100 +17,6 @@ namespace Storage { namespace Encodings { namespace MFM { -template class Shifter { - public: - virtual void add_byte(uint8_t input) = 0; - virtual void add_index_address_mark() = 0; - virtual void add_ID_address_mark() = 0; - virtual void add_data_address_mark() = 0; - virtual void add_deleted_data_address_mark() = 0; - - protected: - // override me! - void output_short(uint16_t value); -}; - -template class MFMShifter: public Shifter { - public: - void add_byte(uint8_t input) { - uint16_t spread_value = - (uint16_t)( - ((input & 0x01) << 0) | - ((input & 0x02) << 1) | - ((input & 0x04) << 2) | - ((input & 0x08) << 3) | - ((input & 0x10) << 4) | - ((input & 0x20) << 5) | - ((input & 0x40) << 6) | - ((input & 0x80) << 7) - ); - uint16_t or_bits = (uint16_t)((spread_value << 1) | (spread_value >> 1) | (output_ << 15)); - output_ = spread_value | ((~or_bits) & 0xaaaa); - static_cast(this)->output_short(output_); - } - - void add_index_address_mark() { - static_cast(this)->output_short(output_ = 0x5224); - add_byte(0xfc); - } - - void add_ID_address_mark() { - static_cast(this)->output_short(output_ = 0x4489); - add_byte(0xfe); - } - - void add_data_address_mark() { - static_cast(this)->output_short(output_ = 0x4489); - add_byte(0xfb); - } - - void add_deleted_data_address_mark() { - static_cast(this)->output_short(output_ = 0x4489); - add_byte(0xf8); - } - - private: - uint16_t output_; -}; - -template class FMShifter: public Shifter { - public: - void add_byte(uint8_t input) { - static_cast(this)->output_short( - (uint16_t)( - ((input & 0x01) << 1) | - ((input & 0x02) << 2) | - ((input & 0x04) << 3) | - ((input & 0x08) << 4) | - ((input & 0x10) << 5) | - ((input & 0x20) << 6) | - ((input & 0x40) << 7) | - ((input & 0x80) << 8) | - 0x5555 - )); - } - - void add_index_address_mark() { - // data 0xfc, with clock 0xd7 => 1111 1100 with clock 1101 0111 => 1111 1011 1011 0101 - static_cast(this)->output_short(0xfbb5); - } - - void add_ID_address_mark() { - // data 0xfe, with clock 0xc7 => 1111 1110 with clock 1100 0111 => 1111 1010 1011 1101 - static_cast(this)->output_short(0xfabd); - } - - void add_data_address_mark() { - // data 0xfb, with clock 0xc7 => 1111 1011 with clock 1100 0111 => 1111 1010 1001 1111 - static_cast(this)->output_short(0xfa9f); - } - - void add_deleted_data_address_mark() { - // data 0xf8, with clock 0xc7 => 1111 1000 with clock 1100 0111 => 1111 1010 1001 0101 - static_cast(this)->output_short(0xfa95); - } -}; - struct Sector { uint8_t track, side, sector; std::vector data;