From 8992feb8cd19b93fa8fcd718d91638c98fe57ee7 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 15 Sep 2016 07:54:42 -0400 Subject: [PATCH] Completed a first parse at the GCR parser, proving how incredibly slow my drive is. --- StaticAnalyser/Commodore/Disk.cpp | 110 ++++++++++++++++++++++++------ StaticAnalyser/Commodore/File.hpp | 6 ++ 2 files changed, 97 insertions(+), 19 deletions(-) diff --git a/StaticAnalyser/Commodore/Disk.cpp b/StaticAnalyser/Commodore/Disk.cpp index 6275f95fa..aae3ce9a5 100644 --- a/StaticAnalyser/Commodore/Disk.cpp +++ b/StaticAnalyser/Commodore/Disk.cpp @@ -9,6 +9,7 @@ #include "Disk.hpp" #include "../../Storage/Disk/DiskDrive.hpp" #include "../../Storage/Disk/Encodings/CommodoreGCR.hpp" +#include "Utilities.hpp" #include #include @@ -18,7 +19,11 @@ using namespace StaticAnalyser::Commodore; class CommodoreGCRParser: public Storage::Disk::Drive { public: - CommodoreGCRParser() : Storage::Disk::Drive(4000000, 4, 300), shift_register_(0) {} + CommodoreGCRParser() : Storage::Disk::Drive(4000000, 4, 300), shift_register_(0), track_(1) + { + // Make sure this drive really is at track '1'. + while(!get_is_track_zero()) step(-1); + } struct Sector { @@ -30,7 +35,24 @@ class CommodoreGCRParser: public Storage::Disk::Drive { std::unique_ptr get_sector(uint8_t track, uint8_t sector) { - return nullptr; + int difference = (int)track - (int)track_; + track_ = track; + + if(difference) + { + int direction = difference < 0 ? -1 : 1; + difference *= 2 * direction; + + for(int c = 0; c < difference; c++) step(direction); + + unsigned int zone = 3; + if(track >= 18) zone = 2; + else if(track >= 25) zone = 1; + else if(track >= 31) zone = 0; + set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(zone)); + } + + return get_sector(sector); } std::unique_ptr get_sector(uint8_t sector) @@ -94,6 +116,7 @@ class CommodoreGCRParser: public Storage::Disk::Drive { unsigned int shift_register_; int index_count_; int bit_count_; + uint8_t track_; void process_input_bit(int value, unsigned int cycles_since_index_hole) { @@ -155,29 +178,78 @@ std::list StaticAnalyser::Commodore::GetFiles(const std::shared_ptr sector; - // attempt to grab a sector from track 0 - while(!parser.get_is_track_zero()) parser.step(-1); - parser.set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(0)); - sector = parser.get_next_sector(); - if(!sector) return files; - - // step out to track 18 (== 36) - for(int c = 0; c < 36; c++) parser.step(1); - - // assemble disk contents, starting with sector 1 - parser.set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(1)); + // assemble directory std::vector directory; - sector = parser.get_sector(1); - while(sector) + uint8_t next_track = 18; + uint8_t next_sector = 1; + while(1) { + sector = parser.get_sector(next_track, next_sector); + if(!sector) break; directory.insert(directory.end(), sector->data.begin(), sector->data.end()); - uint8_t next_track = sector->data[0]; - uint8_t next_sector = sector->data[1]; + next_track = sector->data[0]; + next_sector = sector->data[1]; if(!next_track) break; - sector = parser.get_sector(next_sector); + } - // TODO: track changes. Allegedly not possible, but definitely happening. + // parse directory + size_t header_pointer = (size_t)-32; + while(header_pointer+32+31 < directory.size()) + { + header_pointer += 32; + + File new_file; + switch(directory[header_pointer + 2] & 7) + { + case 0: // DEL files + default: continue; // Unknown file types + + case 1: new_file.type = File::DataSequence; break; + case 2: new_file.type = File::RelocatableProgram; break; // TODO: need a "don't know about relocatable" program? + case 3: new_file.type = File::User; break; +// case 4: new_file.type = File::Relative; break; // Can't handle REL files yet + } + + next_track = directory[header_pointer + 3]; + next_sector = directory[header_pointer + 4]; + + new_file.raw_name.reserve(16); + for(size_t c = 0; c < 16; c++) + { + new_file.raw_name.push_back(directory[header_pointer + 5 + c]); + } + new_file.name = petscii_from_bytes(&new_file.raw_name[0], 16, false); + + size_t number_of_sectors = (size_t)directory[header_pointer + 0x1e] + ((size_t)directory[header_pointer + 0x1f] << 8); + new_file.data.reserve((number_of_sectors - 1) * 254 + 252); + + bool is_first_sector = true; + while(next_track) + { + sector = parser.get_sector(next_track, next_sector); + if(!sector) break; + + next_track = sector->data[0]; + next_sector = sector->data[1]; + if(is_first_sector) + { + new_file.starting_address = (uint16_t)sector->data[2] | (uint16_t)(sector->data[3] << 8); + } + + if(next_track) + { + new_file.data.insert(new_file.data.end(), sector->data.begin() + (is_first_sector ? 4 : 2), sector->data.end()); + } + else + { + new_file.data.insert(new_file.data.end(), sector->data.begin() + 2, sector->data.begin() + next_sector); + } + + is_first_sector = false; + } + + if(!next_track) files.push_back(new_file); } return files; diff --git a/StaticAnalyser/Commodore/File.hpp b/StaticAnalyser/Commodore/File.hpp index ea81aa493..6a4eda72d 100644 --- a/StaticAnalyser/Commodore/File.hpp +++ b/StaticAnalyser/Commodore/File.hpp @@ -16,14 +16,20 @@ namespace StaticAnalyser { namespace Commodore { struct File { + File() : is_closed(false), is_locked(false) {} + std::wstring name; std::vector raw_name; uint16_t starting_address; uint16_t ending_address; + bool is_locked; + bool is_closed; enum { RelocatableProgram, NonRelocatableProgram, DataSequence, + User, + Relative } type; std::vector data;