From d1ce7642018e529d228fb27685c9a1cc33051630 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 24 Sep 2017 22:41:16 -0400 Subject: [PATCH] Provides SectorsFromSegment, a bitstream to sector converter. --- .../Clock Signal.xcodeproj/project.pbxproj | 14 +++- Storage/Disk/Encodings/MFM/SegmentParser.cpp | 73 +++++++++++++++++++ Storage/Disk/Encodings/MFM/SegmentParser.hpp | 26 +++++++ Storage/Disk/Track/PCMSegment.hpp | 4 + 4 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 Storage/Disk/Encodings/MFM/SegmentParser.cpp create mode 100644 Storage/Disk/Encodings/MFM/SegmentParser.hpp diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 0dc1d3b41..deb965344 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -97,6 +97,7 @@ 4B7136861F78724F008B8ED9 /* Encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136841F78724F008B8ED9 /* Encoder.cpp */; }; 4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136871F78725F008B8ED9 /* Shifter.cpp */; }; 4B71368E1F788112008B8ED9 /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B71368C1F788112008B8ED9 /* Parser.cpp */; }; + 4B7136911F789C93008B8ED9 /* SegmentParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B71368F1F789C93008B8ED9 /* SegmentParser.cpp */; }; 4B7913CC1DFCD80E00175A82 /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7913CA1DFCD80E00175A82 /* Video.cpp */; }; 4B79E4441E3AF38600141F11 /* cassette.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4411E3AF38600141F11 /* cassette.png */; }; 4B79E4451E3AF38600141F11 /* floppy35.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4421E3AF38600141F11 /* floppy35.png */; }; @@ -657,6 +658,8 @@ 4B71368B1F7880D1008B8ED9 /* Sector.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Sector.hpp; sourceTree = ""; }; 4B71368C1F788112008B8ED9 /* Parser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Parser.cpp; sourceTree = ""; }; 4B71368D1F788112008B8ED9 /* Parser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Parser.hpp; sourceTree = ""; }; + 4B71368F1F789C93008B8ED9 /* SegmentParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SegmentParser.cpp; sourceTree = ""; }; + 4B7136901F789C93008B8ED9 /* SegmentParser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SegmentParser.hpp; sourceTree = ""; }; 4B77069C1EC904570053B588 /* Z80.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Z80.hpp; path = Z80/Z80.hpp; sourceTree = ""; }; 4B7913CA1DFCD80E00175A82 /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Video.cpp; path = Electron/Video.cpp; sourceTree = ""; }; 4B7913CB1DFCD80E00175A82 /* Video.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Video.hpp; path = Electron/Video.hpp; sourceTree = ""; }; @@ -1416,15 +1419,15 @@ isa = PBXGroup; children = ( 4B4518711F75E91800926311 /* PCMPatchedTrack.cpp */, - 4B4518721F75E91800926311 /* PCMPatchedTrack.hpp */, 4B4518731F75E91800926311 /* PCMSegment.cpp */, - 4B4518741F75E91800926311 /* PCMSegment.hpp */, 4B4518751F75E91800926311 /* PCMTrack.cpp */, - 4B4518761F75E91800926311 /* PCMTrack.hpp */, 4B4518771F75E91800926311 /* UnformattedTrack.cpp */, - 4B4518781F75E91800926311 /* UnformattedTrack.hpp */, + 4B4518721F75E91800926311 /* PCMPatchedTrack.hpp */, + 4B4518741F75E91800926311 /* PCMSegment.hpp */, + 4B4518761F75E91800926311 /* PCMTrack.hpp */, 4B4518881F75ECB100926311 /* Track.hpp */, 4B8D287E1F77207100645199 /* TrackSerialiser.hpp */, + 4B4518781F75E91800926311 /* UnformattedTrack.hpp */, ); path = Track; sourceTree = ""; @@ -1670,6 +1673,8 @@ 4B71368D1F788112008B8ED9 /* Parser.hpp */, 4B71368B1F7880D1008B8ED9 /* Sector.hpp */, 4B7136881F78725F008B8ED9 /* Shifter.hpp */, + 4B71368F1F789C93008B8ED9 /* SegmentParser.cpp */, + 4B7136901F789C93008B8ED9 /* SegmentParser.hpp */, ); name = MFM; path = Encodings/MFM; @@ -2921,6 +2926,7 @@ 4B4518831F75E91A00926311 /* PCMTrack.cpp in Sources */, 4B45189F1F75FD1C00926311 /* AcornADF.cpp in Sources */, 4B2A53A11D117D36003C6002 /* CSAtari2600.mm in Sources */, + 4B7136911F789C93008B8ED9 /* SegmentParser.cpp in Sources */, 4B4518A21F75FD1C00926311 /* G64.cpp in Sources */, 4BF829661D8F732B001BAE39 /* Disk.cpp in Sources */, 4B448E811F1C45A00009ABD6 /* TZX.cpp in Sources */, diff --git a/Storage/Disk/Encodings/MFM/SegmentParser.cpp b/Storage/Disk/Encodings/MFM/SegmentParser.cpp new file mode 100644 index 000000000..ded9ecd4a --- /dev/null +++ b/Storage/Disk/Encodings/MFM/SegmentParser.cpp @@ -0,0 +1,73 @@ +// +// SegmentParser.cpp +// Clock Signal +// +// Created by Thomas Harte on 24/09/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#include "SegmentParser.hpp" +#include "Shifter.hpp" + +using namespace Storage::Encodings::MFM; + +std::map Storage::Encodings::MFM::SectorsFromSegment(const Storage::Disk::PCMSegment &&segment) { + std::map result; + Shifter shifter; + + std::unique_ptr new_sector; + bool is_reading = false; + size_t position = 0; + size_t size = 0; + + for(unsigned int bit = 0; bit < segment.number_of_bits; ++bit) { + shifter.add_input_bit(segment.bit(bit)); + switch(shifter.get_token()) { + case Shifter::Token::None: + case Shifter::Token::Sync: + case Shifter::Token::Index: + break; + + case Shifter::Token::ID: + new_sector.reset(new Storage::Encodings::MFM::Sector); + is_reading = true; + position = 0; + break; + + case Shifter::Token::Data: + case Shifter::Token::DeletedData: + if(new_sector) { + is_reading = true; + new_sector->is_deleted = (shifter.get_token() == Shifter::Token::DeletedData); + } + break; + + case Shifter::Token::Byte: + if(is_reading) { + switch(position) { + case 0: new_sector->address.track = shifter.get_byte(); ++position; break; + case 1: new_sector->address.side = shifter.get_byte(); ++position; break; + case 2: new_sector->address.sector = shifter.get_byte(); ++position; break; + case 3: + new_sector->size = shifter.get_byte(); + size = (size_t)(128 << new_sector->size); + ++position; + is_reading = false; + break; + default: + new_sector->data.push_back(shifter.get_byte()); + ++position; + if(position == size + 4) { + result.insert(std::make_pair(new_sector->address, std::move(*new_sector))); + is_reading = false; + new_sector.reset(); + } + break; + } + } + break; + } + } + + return result; +} diff --git a/Storage/Disk/Encodings/MFM/SegmentParser.hpp b/Storage/Disk/Encodings/MFM/SegmentParser.hpp new file mode 100644 index 000000000..452b5dbab --- /dev/null +++ b/Storage/Disk/Encodings/MFM/SegmentParser.hpp @@ -0,0 +1,26 @@ +// +// SegmentParser.hpp +// Clock Signal +// +// Created by Thomas Harte on 24/09/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#ifndef SegmentParser_hpp +#define SegmentParser_hpp + +#include "Sector.hpp" +#include "../../Track/PCMSegment.hpp" +#include + +namespace Storage { +namespace Encodings { +namespace MFM { + +std::map SectorsFromSegment(const Disk::PCMSegment &&segment); + +} +} +} + +#endif /* SegmentParser_hpp */ diff --git a/Storage/Disk/Track/PCMSegment.hpp b/Storage/Disk/Track/PCMSegment.hpp index 60aa6fbe8..f8bebdc17 100644 --- a/Storage/Disk/Track/PCMSegment.hpp +++ b/Storage/Disk/Track/PCMSegment.hpp @@ -31,6 +31,10 @@ struct PCMSegment { PCMSegment(Time length_of_a_bit, unsigned int number_of_bits, std::vector data) : length_of_a_bit(length_of_a_bit), number_of_bits(number_of_bits), data(data) {} PCMSegment() {} + + int bit(size_t index) const { + return (data[index >> 3] >> (7 ^ (index & 7)))&1; + } }; /*!