diff --git a/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp b/StaticAnalyser/AmstradCPC/StaticAnalyser.cpp index ebce0c606..2ed85e1b3 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. @@ -50,14 +56,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]); @@ -95,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"; } diff --git a/Storage/Disk/Parsers/CPM.cpp b/Storage/Disk/Parsers/CPM.cpp index eaf737404..c50d58db4 100644 --- a/Storage/Disk/Parsers/CPM.cpp +++ b/Storage/Disk/Parsers/CPM.cpp @@ -24,22 +24,26 @@ 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++; - } } std::unique_ptr result(new Catalogue);