From 42ad670ec83954625daf1252295feb14e889d993 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 17 Aug 2017 12:47:47 -0400 Subject: [PATCH 1/4] Fixed: catalogue bitmap is in blocks, not sectors. --- Storage/Disk/Parsers/CPM.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Storage/Disk/Parsers/CPM.cpp b/Storage/Disk/Parsers/CPM.cpp index eaf737404..57d9ce7a6 100644 --- a/Storage/Disk/Parsers/CPM.cpp +++ b/Storage/Disk/Parsers/CPM.cpp @@ -24,24 +24,30 @@ 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(0, (uint8_t)track, (uint8_t)(parameters.first_sector + sector)); - if(!sector_contents) { - return nullptr; - } + size_t size_read = 0; + do { + std::shared_ptr sector_contents = parser.get_sector(0, (uint8_t)track, (uint8_t)(parameters.first_sector + sector)); + if(!sector_contents) { + return nullptr; + } - catalogue.insert(catalogue.end(), sector_contents->data.begin(), sector_contents->data.end()); - sector_size = sector_contents->data.size(); + catalogue.insert(catalogue.end(), sector_contents->data.begin(), sector_contents->data.end()); + sector_size = sector_contents->data.size(); + + size_read += sector_size; + sector++; + if(sector == parameters.sectors_per_track) { + sector = 0; + track++; + } + } while(size_read < (size_t)parameters.block_size); } catalogue_allocation_bitmap <<= 1; - - sector++; - if(sector == parameters.sectors_per_track) { - sector = 0; - track++; - } } + printf("%lu\n", catalogue.size()); + std::unique_ptr result(new Catalogue); bool has_long_allocation_units = (parameters.tracks * parameters.sectors_per_track * (int)sector_size / parameters.block_size) >= 256; size_t bytes_per_catalogue_entry = (has_long_allocation_units ? 16 : 8) * (size_t)parameters.block_size; From b0a98bd2395c4c22e3f869edc6975b5cbebe4807 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 17 Aug 2017 12:48:15 -0400 Subject: [PATCH 2/4] Added nuance: file names with unprintables are filtered, and then system files are considered if there are no remaining non-system files. --- StaticAnalyser/AmstradCPC/StaticAnalyser.cpp | 34 ++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp b/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp index ebce0c606..dc70d5f8f 100644 --- a/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp +++ b/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp @@ -50,14 +50,35 @@ static std::string RunCommandFor(const Storage::Disk::CPM::File &file) { static void InspectDataCatalogue( const Storage::Disk::CPM::Catalogue &catalogue, StaticAnalyser::Target &target) { - // Make a copy of all files and filter out any that are marked as system. std::vector candidate_files = catalogue.files; + + // Remove all files with untypable characters. candidate_files.erase( std::remove_if(candidate_files.begin(), candidate_files.end(), [](const Storage::Disk::CPM::File &file) { - return file.system; + for(auto c : file.name) { + if(c < 32) return true; + } + return false; }), candidate_files.end()); + // If that leaves a mix of 'system' (i.e. hidden) and non-system files, remove the system files. + bool are_all_system = true; + for(auto &file : candidate_files) { + if(!file.system) { + are_all_system = false; + break; + } + } + + if(!are_all_system) { + candidate_files.erase( + std::remove_if(candidate_files.begin(), candidate_files.end(), [](const Storage::Disk::CPM::File &file) { + return file.system; + }), + candidate_files.end()); + } + // If there's just one file, run that. if(candidate_files.size() == 1) { target.loadingCommand = RunCommandFor(candidate_files[0]); @@ -153,6 +174,15 @@ void StaticAnalyser::AmstradCPC::AddTargets(const Media &media, std::list system_catalogue = Storage::Disk::CPM::GetCatalogue(target.media.disks.front(), system_format); std::unique_ptr data_catalogue = Storage::Disk::CPM::GetCatalogue(target.media.disks.front(), data_format); if(data_catalogue) { From 41e4386164f0adc879411b2e4c2ddd18fae32868 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 17 Aug 2017 13:21:48 -0400 Subject: [PATCH 3/4] Added another "one thing is different" test: one thing has a different file name. Also decided to right-time the type (/extension) as well as the file name. --- StaticAnalyser/AmstradCPC/StaticAnalyser.cpp | 33 +++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp b/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp index dc70d5f8f..8cbbca2c0 100644 --- a/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp +++ b/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp @@ -28,19 +28,25 @@ static bool is_implied_extension(const std::string &extension) { strcmp_insensitive(extension.c_str(), "BIN"); } +static void right_trim(std::string &string) { + string.erase(std::find_if(string.rbegin(), string.rend(), [](int ch) { + return !std::isspace(ch); + }).base(), string.end()); +} + static std::string RunCommandFor(const Storage::Disk::CPM::File &file) { // Trim spaces from the name. std::string name = file.name; - name.erase(std::find_if(name.rbegin(), name.rend(), [](int ch) { - return !std::isspace(ch); - }).base(), name.end()); + right_trim(name); // Form the basic command. std::string command = "run\"" + name; // Consider whether the extension is required. if(!is_implied_extension(file.type)) { - command += "." + file.type; + std::string type = file.type; + right_trim(type); + command += "." + type; } // Add a newline and return. @@ -116,6 +122,25 @@ static void InspectDataCatalogue( return; } + // One more guess: if only one remaining candidate file has a different name than the others, + // assume it is intended to stand out. + std::map name_counts; + std::map indices_by_name; + size_t index = 0; + for(auto &file : candidate_files) { + name_counts[file.name]++; + indices_by_name[file.name] = index; + index++; + } + if(name_counts.size() == 2) { + for(auto &pair : name_counts) { + if(pair.second == 1) { + target.loadingCommand = RunCommandFor(candidate_files[indices_by_name[pair.first]]); + return; + } + } + } + // Desperation. target.loadingCommand = "cat\n"; } From da3e8655e9d973003798a434eb47283d8ce84686 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 17 Aug 2017 13:25:19 -0400 Subject: [PATCH 4/4] Withdrew some caveman debugging nonsense. --- StaticAnalyser/AmstradCPC/StaticAnalyser.cpp | 9 --------- Storage/Disk/Parsers/CPM.cpp | 2 -- 2 files changed, 11 deletions(-) diff --git a/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp b/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp index 8cbbca2c0..2ed85e1b3 100644 --- a/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp +++ b/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp @@ -199,15 +199,6 @@ void StaticAnalyser::AmstradCPC::AddTargets(const Media &media, std::list system_catalogue = Storage::Disk::CPM::GetCatalogue(target.media.disks.front(), system_format); std::unique_ptr data_catalogue = Storage::Disk::CPM::GetCatalogue(target.media.disks.front(), data_format); if(data_catalogue) { diff --git a/Storage/Disk/Parsers/CPM.cpp b/Storage/Disk/Parsers/CPM.cpp index 57d9ce7a6..c50d58db4 100644 --- a/Storage/Disk/Parsers/CPM.cpp +++ b/Storage/Disk/Parsers/CPM.cpp @@ -46,8 +46,6 @@ std::unique_ptr Storage::Disk::CPM::GetCatalogue( catalogue_allocation_bitmap <<= 1; } - printf("%lu\n", catalogue.size()); - std::unique_ptr result(new Catalogue); bool has_long_allocation_units = (parameters.tracks * parameters.sectors_per_track * (int)sector_size / parameters.block_size) >= 256; size_t bytes_per_catalogue_entry = (has_long_allocation_units ? 16 : 8) * (size_t)parameters.block_size;