From 41075356e229a1ea5d6ffefdcf98e0535990521f Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 26 Apr 2018 22:49:07 -0400 Subject: [PATCH] Makes a first attempt at NIB support. --- Components/DiskII/DiskII.cpp | 2 +- Storage/Disk/DiskImage/Formats/NIB.cpp | 67 +++++++++++++++++++++++--- Storage/Disk/Track/PCMSegment.hpp | 2 +- 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/Components/DiskII/DiskII.cpp b/Components/DiskII/DiskII.cpp index ee0633bff..57ff5a4be 100644 --- a/Components/DiskII/DiskII.cpp +++ b/Components/DiskII/DiskII.cpp @@ -78,7 +78,7 @@ void DiskII::set_data_register(uint8_t value) { } uint8_t DiskII::get_shift_register() { -// printf("[%02x] ", shift_register_); +// if(shift_register_ & 0x80) printf("[%02x] ", shift_register_); inputs_ &= ~input_command; return shift_register_; } diff --git a/Storage/Disk/DiskImage/Formats/NIB.cpp b/Storage/Disk/DiskImage/Formats/NIB.cpp index 075a5bf12..295c2696b 100644 --- a/Storage/Disk/DiskImage/Formats/NIB.cpp +++ b/Storage/Disk/DiskImage/Formats/NIB.cpp @@ -8,11 +8,16 @@ #include "NIB.hpp" +#include "../../Track/PCMTrack.hpp" +#include "../../Encodings/AppleGCR.hpp" + +#include + using namespace Storage::Disk; namespace { -const std::size_t track_length = 6656; +const long track_length = 6656; const std::size_t number_of_tracks = 35; } @@ -24,7 +29,7 @@ NIB::NIB(const std::string &file_name) : throw ErrorNotNIB; } - // TODO: all other validation. + // TODO: all other validation. I.e. does this look like a GCR disk? } int NIB::get_head_position_count() { @@ -33,13 +38,59 @@ int NIB::get_head_position_count() { std::shared_ptr<::Storage::Disk::Track> NIB::get_track_at_position(::Storage::Disk::Track::Address address) { // NIBs contain data for even-numbered tracks underneath a single head only. - if(address.head || (address.position&1)) return nullptr; + if(address.head) return nullptr; -// const int file_track = address.position >> 1; -// file_.seek(static_cast(file_track * track_length), SEEK_SET); -// std::vector track_data = file_.read(track_length); + const long file_track = static_cast(address.position >> 2); + file_.seek(file_track * track_length, SEEK_SET); + std::vector track_data = file_.read(track_length); - // TODO: determine which FFs are syncs, and produce track. + // NIB files leave sync bytes implicit and make no guarantees + // about overall track positioning. So the approach taken here + // is to look for the epilogue sequence (which concludes all Apple + // tracks and headers), then treat all following FFs as a sync + // region, then switch back to ordinary behaviour as soon as a + // non-FF appears. + std::vector segments; - return nullptr; + std::size_t start_index = 0; + std::set sync_starts; + + // Establish where syncs start by finding instances of 0xd5 0xaa and then regressing + // from each along all preceding FFs. + for(size_t index = 0; index < track_data.size(); ++index) { + if(track_data[index] == 0xd5 && track_data[(index+1)%track_data.size()] == 0xaa) { + size_t start = index - 1; + while(track_data[start] == 0xff) + start = (start + track_data.size() - 1) % track_data.size(); + + sync_starts.insert((start + 1) % track_data.size()); + if(start > index) + start_index = start; + } + } + + if(start_index) + segments.push_back(Encodings::AppleGCR::six_and_two_sync(static_cast(start_index))); + + std::size_t index = start_index; + for(const auto &location: sync_starts) { + // Write from index to sync_start. + PCMSegment data_segment; + data_segment.data.insert( + data_segment.data.end(), + track_data.begin() + static_cast(index), + track_data.begin() + static_cast(location)); + data_segment.number_of_bits = static_cast(data_segment.data.size() * 8); + segments.push_back(std::move(data_segment)); + + // Add a sync from sync_start to end of 0xffs. + if(location == track_length-1) break; + + index = location; + while(index < track_length && track_data[index] == 0xff) + ++index; + segments.push_back(Encodings::AppleGCR::six_and_two_sync(static_cast(index - location))); + } + + return std::shared_ptr(new PCMTrack(segments)); } diff --git a/Storage/Disk/Track/PCMSegment.hpp b/Storage/Disk/Track/PCMSegment.hpp index 96a2364de..ea9bd4779 100644 --- a/Storage/Disk/Track/PCMSegment.hpp +++ b/Storage/Disk/Track/PCMSegment.hpp @@ -25,7 +25,7 @@ namespace Disk { Bits from each byte are taken MSB to LSB. */ struct PCMSegment { - Time length_of_a_bit; + Time length_of_a_bit = Time(1); unsigned int number_of_bits = 0; std::vector data;