diff --git a/Analyser/Static/AmstradCPC/StaticAnalyser.cpp b/Analyser/Static/AmstradCPC/StaticAnalyser.cpp index 49b002890..65854ab26 100644 --- a/Analyser/Static/AmstradCPC/StaticAnalyser.cpp +++ b/Analyser/Static/AmstradCPC/StaticAnalyser.cpp @@ -233,7 +233,7 @@ Analyser::Static::TargetList Analyser::Static::AmstradCPC::GetTargets(const Medi for(auto &disk: media.disks) { // Check for an ordinary catalogue, making sure this isn't actually a ZX Spectrum disk. - std::unique_ptr data_catalogue = Storage::Disk::CPM::GetCatalogue(disk, data_format); + std::unique_ptr data_catalogue = Storage::Disk::CPM::GetCatalogue(disk, data_format, false); if(data_catalogue && !data_catalogue->is_zx_spectrum_booter()) { InspectCatalogue(*data_catalogue, target); target->media.disks.push_back(disk); @@ -247,7 +247,7 @@ Analyser::Static::TargetList Analyser::Static::AmstradCPC::GetTargets(const Medi } // Failing that check for a system catalogue. - std::unique_ptr system_catalogue = Storage::Disk::CPM::GetCatalogue(disk, system_format); + std::unique_ptr system_catalogue = Storage::Disk::CPM::GetCatalogue(disk, system_format, false); if(system_catalogue && !system_catalogue->is_zx_spectrum_booter()) { InspectCatalogue(*system_catalogue, target); target->media.disks.push_back(disk); diff --git a/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp b/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp index d47e8d4c0..e2ef0b88c 100644 --- a/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp +++ b/Analyser/Static/ZXSpectrum/StaticAnalyser.cpp @@ -97,7 +97,7 @@ bool IsSpectrumDisk(const std::shared_ptr &disk) { } // ... otherwise read a CPM directory and look for a BASIC program called "DISK". - const auto catalogue = Storage::Disk::CPM::GetCatalogue(disk, cpm_format); + const auto catalogue = Storage::Disk::CPM::GetCatalogue(disk, cpm_format, false); return catalogue && catalogue->is_zx_spectrum_booter(); } diff --git a/Storage/Disk/Parsers/CPM.cpp b/Storage/Disk/Parsers/CPM.cpp index 93e3efa9a..c9b03f028 100644 --- a/Storage/Disk/Parsers/CPM.cpp +++ b/Storage/Disk/Parsers/CPM.cpp @@ -15,7 +15,7 @@ using namespace Storage::Disk::CPM; -std::unique_ptr Storage::Disk::CPM::GetCatalogue(const std::shared_ptr &disk, const ParameterBlock ¶meters) { +std::unique_ptr Storage::Disk::CPM::GetCatalogue(const std::shared_ptr &disk, const ParameterBlock ¶meters, bool with_contents) { Storage::Encodings::MFM::Parser parser(Encodings::MFM::Density::Double, disk); // Assemble the actual bytes of the catalogue. @@ -87,38 +87,42 @@ std::unique_ptr Storage::Disk::CPM::GetCatalogue( // Sort the catalogue entries and then map to files. std::sort(catalogue_entries.begin(), catalogue_entries.end()); - - std::unique_ptr result(new Catalogue); + auto result = std::make_unique(); bool has_long_allocation_units = (parameters.tracks * parameters.sectors_per_track * int(sector_size) / parameters.block_size) >= 256; std::size_t bytes_per_catalogue_entry = (has_long_allocation_units ? 8 : 16) * size_t(parameters.block_size); int sectors_per_block = parameters.block_size / int(sector_size); int records_per_sector = int(sector_size) / 128; + result->files.reserve(catalogue_entries.size()); auto entry = catalogue_entries.begin(); while(entry != catalogue_entries.end()) { - // Find final catalogue entry that relates to the same file. - auto final_entry = entry + 1; - while(final_entry != catalogue_entries.end() && final_entry->is_same_file(*entry)) { - final_entry++; - } - final_entry--; + // Find first catalogue entry that relates to a different file. + auto final_entry = entry; + do { + ++final_entry; + } while(final_entry != catalogue_entries.end() && final_entry->is_same_file(*entry)); // Create file. - result->files.emplace_back(); - File &new_file = result->files.back(); + File &new_file = result->files.emplace_back(); new_file.user_number = entry->user_number; new_file.name = std::move(entry->name); new_file.type = std::move(entry->type); new_file.read_only = entry->read_only; new_file.system = entry->system; + // Skip contents if not required. + if(!with_contents) { + entry = final_entry; + continue; + } + // Create storage for data. std::size_t required_size = final_entry->extent * bytes_per_catalogue_entry + size_t(final_entry->number_of_records) * 128; new_file.data.resize(required_size); // Accumulate all data. - while(entry <= final_entry) { + while(entry != final_entry) { int record = 0; int number_of_records = (entry->number_of_records != 0x80) ? entry->number_of_records : (has_long_allocation_units ? 8 : 16); for(std::size_t block = 0; block < (has_long_allocation_units ? 8 : 16) && record < number_of_records; block++) { @@ -152,7 +156,7 @@ std::unique_ptr Storage::Disk::CPM::GetCatalogue( } } - entry++; + ++entry; } } @@ -164,7 +168,7 @@ bool Catalogue::is_zx_spectrum_booter() { const auto file = std::find_if(files.begin(), files.end(), [](const auto &file) { return file.name == "DISK "; }); if(file == files.end()) return false; - // TODO: check the file is valid ZX Spectrum BASIC. + // TODO: check the file is valid ZX Spectrum BASIC if it has contents. return true; } diff --git a/Storage/Disk/Parsers/CPM.hpp b/Storage/Disk/Parsers/CPM.hpp index 02958e822..60529a7bb 100644 --- a/Storage/Disk/Parsers/CPM.hpp +++ b/Storage/Disk/Parsers/CPM.hpp @@ -64,6 +64,6 @@ struct Catalogue { bool is_zx_spectrum_booter(); }; -std::unique_ptr GetCatalogue(const std::shared_ptr &disk, const ParameterBlock ¶meters); +std::unique_ptr GetCatalogue(const std::shared_ptr &disk, const ParameterBlock ¶meters, bool with_contents); }