From beaa868079d7e3e763dbf513ae10a9403fef99c9 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 25 Dec 2016 20:00:57 -0500 Subject: [PATCH] Factored the MFM parser out into encodings. --- Components/1770/1770.cpp | 2 - StaticAnalyser/Acorn/Disk.cpp | 174 +-------------------------------- Storage/Disk/Encodings/MFM.cpp | 149 ++++++++++++++++++++++++++++ Storage/Disk/Encodings/MFM.hpp | 30 ++++++ 4 files changed, 181 insertions(+), 174 deletions(-) diff --git a/Components/1770/1770.cpp b/Components/1770/1770.cpp index 4f065a3e5..c0e2a1bca 100644 --- a/Components/1770/1770.cpp +++ b/Components/1770/1770.cpp @@ -632,9 +632,7 @@ void WD1770::posit_event(Event new_event_type) update_status([] (Status &status) { status.data_request = true; }); - printf("- %d\n", counter); WAIT_FOR_EVENT(Event::DataWritten); - printf("+ %d\n", counter); distance_into_section_++; if(distance_into_section_ == 128 << header_[3]) { diff --git a/StaticAnalyser/Acorn/Disk.cpp b/StaticAnalyser/Acorn/Disk.cpp index 20fa8a0a6..c7cf4b882 100644 --- a/StaticAnalyser/Acorn/Disk.cpp +++ b/StaticAnalyser/Acorn/Disk.cpp @@ -14,180 +14,11 @@ using namespace StaticAnalyser::Acorn; -class FMParser: public Storage::Disk::Controller { - public: - std::shared_ptr drive; - - FMParser(bool is_mfm) : - Storage::Disk::Controller(4000000, 1, 300), - crc_generator_(0x1021, 0xffff), - shift_register_(0), track_(0), is_mfm_(is_mfm) - { - Storage::Time bit_length; - bit_length.length = 1; - bit_length.clock_rate = is_mfm ? 500000 : 250000; // i.e. 250 kbps (including clocks) - set_expected_bit_length(bit_length); - - drive.reset(new Storage::Disk::Drive); - set_drive(drive); - set_motor_on(true); - } - - /*! - Attempts to read the sector located at @c track and @c sector. - - @returns a sector if one was found; @c nullptr otherwise. - */ - std::shared_ptr get_sector(uint8_t track, uint8_t sector) - { - int difference = (int)track - (int)track_; - track_ = track; - - if(difference) - { - int direction = difference < 0 ? -1 : 1; - difference *= direction; - - for(int c = 0; c < difference; c++) step(direction); - } - - return get_sector(sector); - } - - private: - unsigned int shift_register_; - int index_count_; - uint8_t track_; - int bit_count_; - std::shared_ptr sector_cache_[65536]; - NumberTheory::CRC16 crc_generator_; - bool is_mfm_; - - void process_input_bit(int value, unsigned int cycles_since_index_hole) - { - shift_register_ = ((shift_register_ << 1) | (unsigned int)value) & 0xffff; - bit_count_++; - } - - void process_index_hole() - { - index_count_++; - } - - uint8_t get_next_byte() - { - bit_count_ = 0; - while(bit_count_ < 16) run_for_cycles(1); - uint8_t byte = (uint8_t)( - ((shift_register_&0x0001) >> 0) | - ((shift_register_&0x0004) >> 1) | - ((shift_register_&0x0010) >> 2) | - ((shift_register_&0x0040) >> 3) | - ((shift_register_&0x0100) >> 4) | - ((shift_register_&0x0400) >> 5) | - ((shift_register_&0x1000) >> 6) | - ((shift_register_&0x4000) >> 7)); - crc_generator_.add(byte); - return byte; - } - - std::shared_ptr get_next_sector() - { - std::shared_ptr sector(new Storage::Encodings::MFM::Sector); - index_count_ = 0; - - while(index_count_ < 2) - { - // look for an ID address mark - while(1) - { - run_for_cycles(1); - if(is_mfm_) - { - if(shift_register_ == Storage::Encodings::MFM::MFMAddressMark) - { - uint8_t mark = get_next_byte(); - if(mark == Storage::Encodings::MFM::MFMIDAddressByte) break; - } - } - else - { - if(shift_register_ == Storage::Encodings::MFM::FMIDAddressMark) break; - } - if(index_count_ >= 2) return nullptr; - } - - crc_generator_.reset(); - sector->track = get_next_byte(); - sector->side = get_next_byte(); - sector->sector = get_next_byte(); - uint8_t size = get_next_byte(); - uint16_t header_crc = crc_generator_.get_value(); - if((header_crc >> 8) != get_next_byte()) continue; - if((header_crc & 0xff) != get_next_byte()) continue; - - // look for data mark - while(1) - { - run_for_cycles(1); - if(is_mfm_) - { - if(shift_register_ == Storage::Encodings::MFM::MFMAddressMark) - { - uint8_t mark = get_next_byte(); - if(mark == Storage::Encodings::MFM::MFMDataAddressByte) break; - if(mark == Storage::Encodings::MFM::MFMIDAddressByte) return nullptr; - } - } - else - { - if(shift_register_ == Storage::Encodings::MFM::FMDataAddressMark) break; - if(shift_register_ == Storage::Encodings::MFM::FMIDAddressMark) return nullptr; - } - if(index_count_ >= 2) return nullptr; - } - - size_t data_size = (size_t)(128 << size); - sector->data.reserve(data_size); - crc_generator_.reset(); - for(size_t c = 0; c < data_size; c++) - { - sector->data.push_back(get_next_byte()); - } - uint16_t data_crc = crc_generator_.get_value(); - if((data_crc >> 8) != get_next_byte()) continue; - if((data_crc & 0xff) != get_next_byte()) continue; - - return sector; - } - - return nullptr; - } - - std::shared_ptr get_sector(uint8_t sector) - { -// uint16_t sector_address = (uint16_t)((track_ << 8) | sector); -// if(sector_cache_[sector_address]) return sector_cache_[sector_address]; - - std::shared_ptr first_sector = get_next_sector(); - if(!first_sector) return first_sector; - if(first_sector->sector == sector) return first_sector; - - while(1) - { - std::shared_ptr next_sector = get_next_sector(); - if(next_sector->sector == first_sector->sector) return nullptr; - if(next_sector->sector == sector) return next_sector; - } - } -}; - std::unique_ptr StaticAnalyser::Acorn::GetDFSCatalogue(const std::shared_ptr &disk) { // c.f. http://beebwiki.mdfs.net/Acorn_DFS_disc_format std::unique_ptr catalogue(new Catalogue); - FMParser parser(false); - parser.drive->set_disk(disk); + Storage::Encodings::MFM::Parser parser(false, disk); std::shared_ptr names = parser.get_sector(0, 0); std::shared_ptr details = parser.get_sector(0, 1); @@ -248,8 +79,7 @@ std::unique_ptr StaticAnalyser::Acorn::GetDFSCatalogue(const std::sha std::unique_ptr StaticAnalyser::Acorn::GetADFSCatalogue(const std::shared_ptr &disk) { std::unique_ptr catalogue(new Catalogue); - FMParser parser(true); - parser.drive->set_disk(disk); + Storage::Encodings::MFM::Parser parser(true, disk); std::shared_ptr free_space_map_second_half = parser.get_sector(0, 1); if(!free_space_map_second_half) return nullptr; diff --git a/Storage/Disk/Encodings/MFM.cpp b/Storage/Disk/Encodings/MFM.cpp index 8c864ff53..2af4e5bfb 100644 --- a/Storage/Disk/Encodings/MFM.cpp +++ b/Storage/Disk/Encodings/MFM.cpp @@ -211,3 +211,152 @@ std::unique_ptr Storage::Encodings::MFM::GetFMEncoder(std::vector(new FMEncoder(target)); } + +#pragma mark - Parser + +Parser::Parser(bool is_mfm, const std::shared_ptr &disk) : + Storage::Disk::Controller(4000000, 1, 300), + crc_generator_(0x1021, 0xffff), + shift_register_(0), track_(0), is_mfm_(is_mfm) +{ + Storage::Time bit_length; + bit_length.length = 1; + bit_length.clock_rate = is_mfm ? 500000 : 250000; // i.e. 250 kbps (including clocks) + set_expected_bit_length(bit_length); + + drive.reset(new Storage::Disk::Drive); + drive->set_disk(disk); + set_drive(drive); + set_motor_on(true); +} + +std::shared_ptr Parser::get_sector(uint8_t track, uint8_t sector) +{ + int difference = (int)track - (int)track_; + track_ = track; + + if(difference) + { + int direction = difference < 0 ? -1 : 1; + difference *= direction; + + for(int c = 0; c < difference; c++) step(direction); + } + + return get_sector(sector); +} + +void Parser::process_input_bit(int value, unsigned int cycles_since_index_hole) +{ + shift_register_ = ((shift_register_ << 1) | (unsigned int)value) & 0xffff; + bit_count_++; +} + +void Parser::process_index_hole() +{ + index_count_++; +} + +uint8_t Parser::get_next_byte() +{ + bit_count_ = 0; + while(bit_count_ < 16) run_for_cycles(1); + uint8_t byte = (uint8_t)( + ((shift_register_&0x0001) >> 0) | + ((shift_register_&0x0004) >> 1) | + ((shift_register_&0x0010) >> 2) | + ((shift_register_&0x0040) >> 3) | + ((shift_register_&0x0100) >> 4) | + ((shift_register_&0x0400) >> 5) | + ((shift_register_&0x1000) >> 6) | + ((shift_register_&0x4000) >> 7)); + crc_generator_.add(byte); + return byte; +} + +std::shared_ptr Parser::get_next_sector() +{ + std::shared_ptr sector(new Storage::Encodings::MFM::Sector); + index_count_ = 0; + + while(index_count_ < 2) + { + // look for an ID address mark + while(1) + { + run_for_cycles(1); + if(is_mfm_) + { + if(shift_register_ == Storage::Encodings::MFM::MFMAddressMark) + { + uint8_t mark = get_next_byte(); + if(mark == Storage::Encodings::MFM::MFMIDAddressByte) break; + } + } + else + { + if(shift_register_ == Storage::Encodings::MFM::FMIDAddressMark) break; + } + if(index_count_ >= 2) return nullptr; + } + + crc_generator_.reset(); + sector->track = get_next_byte(); + sector->side = get_next_byte(); + sector->sector = get_next_byte(); + uint8_t size = get_next_byte(); + uint16_t header_crc = crc_generator_.get_value(); + if((header_crc >> 8) != get_next_byte()) continue; + if((header_crc & 0xff) != get_next_byte()) continue; + + // look for data mark + while(1) + { + run_for_cycles(1); + if(is_mfm_) + { + if(shift_register_ == Storage::Encodings::MFM::MFMAddressMark) + { + uint8_t mark = get_next_byte(); + if(mark == Storage::Encodings::MFM::MFMDataAddressByte) break; + if(mark == Storage::Encodings::MFM::MFMIDAddressByte) return nullptr; + } + } + else + { + if(shift_register_ == Storage::Encodings::MFM::FMDataAddressMark) break; + if(shift_register_ == Storage::Encodings::MFM::FMIDAddressMark) return nullptr; + } + if(index_count_ >= 2) return nullptr; + } + + size_t data_size = (size_t)(128 << size); + sector->data.reserve(data_size); + crc_generator_.reset(); + for(size_t c = 0; c < data_size; c++) + { + sector->data.push_back(get_next_byte()); + } + uint16_t data_crc = crc_generator_.get_value(); + if((data_crc >> 8) != get_next_byte()) continue; + if((data_crc & 0xff) != get_next_byte()) continue; + + return sector; + } + + return nullptr; +} + +std::shared_ptr Parser::get_sector(uint8_t sector) +{ + std::shared_ptr first_sector = get_next_sector(); + if(!first_sector) return first_sector; + if(first_sector->sector == sector) return first_sector; + + while(1) + { + std::shared_ptr next_sector = get_next_sector(); + if(next_sector->sector == first_sector->sector) return nullptr; + if(next_sector->sector == sector) return next_sector; + } +} diff --git a/Storage/Disk/Encodings/MFM.hpp b/Storage/Disk/Encodings/MFM.hpp index 57e4b11da..6fdccdd96 100644 --- a/Storage/Disk/Encodings/MFM.hpp +++ b/Storage/Disk/Encodings/MFM.hpp @@ -12,6 +12,8 @@ #include #include #include "../Disk.hpp" +#include "../DiskController.hpp" +#include "../../../NumberTheory/CRC.hpp" namespace Storage { namespace Encodings { @@ -56,6 +58,34 @@ class Encoder { std::unique_ptr GetMFMEncoder(std::vector &target); std::unique_ptr GetFMEncoder(std::vector &target); +class Parser: public Storage::Disk::Controller { + public: + Parser(bool is_mfm, const std::shared_ptr &disk); + + /*! + Attempts to read the sector located at @c track and @c sector. + + @returns a sector if one was found; @c nullptr otherwise. + */ + std::shared_ptr get_sector(uint8_t track, uint8_t sector); + + private: + std::shared_ptr drive; + unsigned int shift_register_; + int index_count_; + uint8_t track_; + int bit_count_; + NumberTheory::CRC16 crc_generator_; + bool is_mfm_; + + void process_input_bit(int value, unsigned int cycles_since_index_hole); + void process_index_hole(); + uint8_t get_next_byte(); + std::shared_ptr get_next_sector(); + std::shared_ptr get_sector(uint8_t sector); +}; + + } } }