diff --git a/StaticAnalyser/Acorn/Disk.cpp b/StaticAnalyser/Acorn/Disk.cpp index 7a3f9aa6f..8f9245814 100644 --- a/StaticAnalyser/Acorn/Disk.cpp +++ b/StaticAnalyser/Acorn/Disk.cpp @@ -19,8 +19,8 @@ std::unique_ptr StaticAnalyser::Acorn::GetDFSCatalogue(const std::sha std::unique_ptr catalogue(new Catalogue); 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); + std::shared_ptr names = parser.get_sector(0, 0, 0); + std::shared_ptr details = parser.get_sector(0, 0, 1); if(!names || !details) return nullptr; if(names->data.size() != 256 || details->data.size() != 256) return nullptr; @@ -61,7 +61,7 @@ std::unique_ptr StaticAnalyser::Acorn::GetDFSCatalogue(const std::sha uint8_t track = (uint8_t)(start_sector / 10); start_sector++; - std::shared_ptr next_sector = parser.get_sector(track, sector); + std::shared_ptr next_sector = parser.get_sector(0, track, sector); if(!next_sector) break; long length_from_sector = std::min(data_length, 256l); @@ -77,13 +77,13 @@ std::unique_ptr StaticAnalyser::Acorn::GetADFSCatalogue(const std::sh std::unique_ptr catalogue(new Catalogue); Storage::Encodings::MFM::Parser parser(true, disk); - std::shared_ptr free_space_map_second_half = parser.get_sector(0, 1); + std::shared_ptr free_space_map_second_half = parser.get_sector(0, 0, 1); if(!free_space_map_second_half) return nullptr; std::vector root_directory; root_directory.reserve(5 * 256); for(uint8_t c = 2; c < 7; c++) { - std::shared_ptr sector = parser.get_sector(0, c); + std::shared_ptr sector = parser.get_sector(0, 0, c); if(!sector) return nullptr; root_directory.insert(root_directory.end(), sector->data.begin(), sector->data.end()); } diff --git a/Storage/Disk/Encodings/MFM.cpp b/Storage/Disk/Encodings/MFM.cpp index 1aa908e15..1c2f19a4c 100644 --- a/Storage/Disk/Encodings/MFM.cpp +++ b/Storage/Disk/Encodings/MFM.cpp @@ -228,25 +228,26 @@ std::unique_ptr Storage::Encodings::MFM::GetFMEncoder(std::vector &disk) : Parser(is_mfm) { - drive->set_disk(disk); + drive_->set_disk(disk); } Parser::Parser(bool is_mfm, const std::shared_ptr &track) : Parser(is_mfm) { - drive->set_disk_with_track(track); + drive_->set_disk_with_track(track); } void Parser::seek_to_track(uint8_t track) { @@ -261,7 +262,20 @@ void Parser::seek_to_track(uint8_t track) { } } -std::shared_ptr Parser::get_sector(uint8_t track, uint8_t sector) { +std::shared_ptr Parser::get_sector(uint8_t head, uint8_t track, uint8_t sector) { + // Check cache for sector. + int index = get_index(head, track, sector); + auto cached_sector = sectors_by_index_.find(index); + if(cached_sector != sectors_by_index_.end()) { + return cached_sector->second; + } + + // Failing that, set the proper head and track, and search for the sector. get_sector automatically + // inserts everything found into sectors_by_index_. + if(head_ != head) { + drive_->set_head(head); + invalidate_track(); + } seek_to_track(track); return get_sector(sector); } @@ -384,8 +398,7 @@ std::vector Parser::get_track() { } -std::shared_ptr Parser::get_next_sector() -{ +std::shared_ptr Parser::get_next_sector() { std::shared_ptr sector(new Sector); index_count_ = 0; @@ -455,6 +468,10 @@ std::shared_ptr Parser::get_next_sector() if((data_crc >> 8) != get_next_byte()) continue; if((data_crc & 0xff) != get_next_byte()) continue; + // Put this sector into the cache. + int index = get_index(head_, track_, sector->sector); + sectors_by_index_[index] = sector; + return sector; } @@ -465,7 +482,7 @@ std::shared_ptr Parser::get_sector(uint8_t sector) { std::shared_ptr first_sector; index_count_ = 0; while(!first_sector && index_count_ < 2) first_sector = get_next_sector(); - if(!first_sector) return first_sector; + if(!first_sector) return nullptr; if(first_sector->sector == sector) return first_sector; while(1) { @@ -475,3 +492,7 @@ std::shared_ptr Parser::get_sector(uint8_t sector) { if(next_sector->sector == sector) return next_sector; } } + +int Parser::get_index(uint8_t head, uint8_t track, uint8_t sector) { + return head | (track << 8) | (sector << 16); +} diff --git a/Storage/Disk/Encodings/MFM.hpp b/Storage/Disk/Encodings/MFM.hpp index f482c93bd..37a8178f3 100644 --- a/Storage/Disk/Encodings/MFM.hpp +++ b/Storage/Disk/Encodings/MFM.hpp @@ -75,7 +75,7 @@ class Parser: public Storage::Disk::Controller { @returns a sector if one was found; @c nullptr otherwise. */ - std::shared_ptr get_sector(uint8_t track, uint8_t sector); + std::shared_ptr get_sector(uint8_t head, uint8_t track, uint8_t sector); /*! Attempts to read the track at @c track, starting from the index hole. @@ -92,10 +92,10 @@ class Parser: public Storage::Disk::Controller { private: Parser(bool is_mfm); - std::shared_ptr drive; + std::shared_ptr drive_; unsigned int shift_register_; int index_count_; - uint8_t track_; + uint8_t track_, head_; int bit_count_; NumberTheory::CRC16 crc_generator_; bool is_mfm_; @@ -110,6 +110,9 @@ class Parser: public Storage::Disk::Controller { std::shared_ptr get_next_sector(); std::shared_ptr get_sector(uint8_t sector); std::vector get_track(); + + std::map> sectors_by_index_; + int get_index(uint8_t head, uint8_t track, uint8_t sector); }; diff --git a/Storage/Disk/Formats/AcornADF.cpp b/Storage/Disk/Formats/AcornADF.cpp index 779bc29c0..f4e0664d7 100644 --- a/Storage/Disk/Formats/AcornADF.cpp +++ b/Storage/Disk/Formats/AcornADF.cpp @@ -87,7 +87,7 @@ void AcornADF::store_updated_track_at_position(unsigned int head, unsigned int p std::vector parsed_track; Storage::Encodings::MFM::Parser parser(true, track); for(unsigned int c = 0; c < sectors_per_track; c++) { - std::shared_ptr sector = parser.get_sector((uint8_t)position, (uint8_t)c); + std::shared_ptr sector = parser.get_sector(0, (uint8_t)position, (uint8_t)c); if(sector) { parsed_track.insert(parsed_track.end(), sector->data.begin(), sector->data.end()); } else { diff --git a/Storage/Disk/Formats/SSD.cpp b/Storage/Disk/Formats/SSD.cpp index 4903784d5..5045e536b 100644 --- a/Storage/Disk/Formats/SSD.cpp +++ b/Storage/Disk/Formats/SSD.cpp @@ -81,7 +81,7 @@ void SSD::store_updated_track_at_position(unsigned int head, unsigned int positi std::vector parsed_track; Storage::Encodings::MFM::Parser parser(false, track); for(unsigned int c = 0; c < 10; c++) { - std::shared_ptr sector = parser.get_sector((uint8_t)position, (uint8_t)c); + std::shared_ptr sector = parser.get_sector(0, (uint8_t)position, (uint8_t)c); if(sector) { parsed_track.insert(parsed_track.end(), sector->data.begin(), sector->data.end()); } else { diff --git a/Storage/Disk/Parsers/CPM.cpp b/Storage/Disk/Parsers/CPM.cpp index 2ebbe2e1f..749e8387b 100644 --- a/Storage/Disk/Parsers/CPM.cpp +++ b/Storage/Disk/Parsers/CPM.cpp @@ -24,7 +24,7 @@ std::unique_ptr Storage::Disk::CPM::GetCatalogue( int track = parameters.reserved_tracks; while(catalogue_allocation_bitmap) { if(catalogue_allocation_bitmap & 0x8000) { - std::shared_ptr sector_contents = parser.get_sector((uint8_t)track, (uint8_t)(parameters.first_sector + sector)); + std::shared_ptr sector_contents = parser.get_sector(0, (uint8_t)track, (uint8_t)(parameters.first_sector + sector)); if(!sector_contents) { return nullptr; } @@ -91,7 +91,7 @@ std::unique_ptr Storage::Disk::CPM::GetCatalogue( track = first_sector / parameters.sectors_per_track; for(int s = 0; s < sectors_per_block && record < number_of_records; s++) { - std::shared_ptr sector_contents = parser.get_sector((uint8_t)track, (uint8_t)(parameters.first_sector + sector)); + std::shared_ptr sector_contents = parser.get_sector(0, (uint8_t)track, (uint8_t)(parameters.first_sector + sector)); if(!sector_contents) break; sector++; if(sector == parameters.sectors_per_track) {