mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Merge pull request #334 from TomHarte/DMK
Adds support for the DMK file format
This commit is contained in:
commit
e7bc7b94c9
@ -281,6 +281,8 @@
|
||||
4BA61EB01D91515900B3C876 /* NSData+StdVector.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA61EAF1D91515900B3C876 /* NSData+StdVector.mm */; };
|
||||
4BA799951D8B656E0045123D /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA799931D8B656E0045123D /* StaticAnalyser.cpp */; };
|
||||
4BAD13441FF709C700FD114A /* MSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0E61051FF34737002A9DBD /* MSX.cpp */; };
|
||||
4BAF2B4E2004580C00480230 /* DMK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAF2B4C2004580C00480230 /* DMK.cpp */; };
|
||||
4BAF2B4F2004580C00480230 /* DMK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAF2B4C2004580C00480230 /* DMK.cpp */; };
|
||||
4BB17D4E1ED7909F00ABD1E1 /* tests.expected.json in Resources */ = {isa = PBXBuildFile; fileRef = 4BB17D4C1ED7909F00ABD1E1 /* tests.expected.json */; };
|
||||
4BB17D4F1ED7909F00ABD1E1 /* tests.in.json in Resources */ = {isa = PBXBuildFile; fileRef = 4BB17D4D1ED7909F00ABD1E1 /* tests.in.json */; };
|
||||
4BB298F11B587D8400A49093 /* start in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E51B587D8300A49093 /* start */; };
|
||||
@ -938,6 +940,8 @@
|
||||
4BA9C3CF1D8164A9002DDB61 /* ConfigurationTarget.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ConfigurationTarget.hpp; sourceTree = "<group>"; };
|
||||
4BAB62AC1D3272D200DF5BA0 /* Disk.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Disk.hpp; sourceTree = "<group>"; };
|
||||
4BAB62AE1D32730D00DF5BA0 /* Storage.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Storage.hpp; sourceTree = "<group>"; };
|
||||
4BAF2B4C2004580C00480230 /* DMK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DMK.cpp; sourceTree = "<group>"; };
|
||||
4BAF2B4D2004580C00480230 /* DMK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DMK.hpp; sourceTree = "<group>"; };
|
||||
4BB06B211F316A3F00600C7A /* ForceInline.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ForceInline.hpp; sourceTree = "<group>"; };
|
||||
4BB146C61F49D7D700253439 /* Sleeper.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Sleeper.hpp; sourceTree = "<group>"; };
|
||||
4BB17D4C1ED7909F00ABD1E1 /* tests.expected.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = tests.expected.json; path = FUSE/tests.expected.json; sourceTree = "<group>"; };
|
||||
@ -1786,6 +1790,7 @@
|
||||
4B45188D1F75FD1B00926311 /* AcornADF.cpp */,
|
||||
4B45188F1F75FD1B00926311 /* CPCDSK.cpp */,
|
||||
4B4518911F75FD1B00926311 /* D64.cpp */,
|
||||
4BAF2B4C2004580C00480230 /* DMK.cpp */,
|
||||
4B4518931F75FD1B00926311 /* G64.cpp */,
|
||||
4B4518951F75FD1B00926311 /* HFE.cpp */,
|
||||
4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */,
|
||||
@ -1795,6 +1800,7 @@
|
||||
4B45188E1F75FD1B00926311 /* AcornADF.hpp */,
|
||||
4B4518901F75FD1B00926311 /* CPCDSK.hpp */,
|
||||
4B4518921F75FD1B00926311 /* D64.hpp */,
|
||||
4BAF2B4D2004580C00480230 /* DMK.hpp */,
|
||||
4B4518941F75FD1B00926311 /* G64.hpp */,
|
||||
4B4518961F75FD1B00926311 /* HFE.hpp */,
|
||||
4B58601D1F806AB200AEE2E3 /* MFMSectorDump.hpp */,
|
||||
@ -3406,6 +3412,7 @@
|
||||
4B055ADF1FAE9B4C0060FFFF /* IRQDelegatePortHandler.cpp in Sources */,
|
||||
4B055AB51FAE860F0060FFFF /* TapePRG.cpp in Sources */,
|
||||
4B055AE01FAE9B660060FFFF /* CRT.cpp in Sources */,
|
||||
4BAF2B4F2004580C00480230 /* DMK.cpp in Sources */,
|
||||
4B0E04F21FC9EAA800F43484 /* StaticAnalyser.cpp in Sources */,
|
||||
4B055AD01FAE9B030060FFFF /* Tape.cpp in Sources */,
|
||||
4B055A961FAE85BB0060FFFF /* Commodore.cpp in Sources */,
|
||||
@ -3439,6 +3446,7 @@
|
||||
4B2BFC5F1D613E0200BA3AA9 /* TapePRG.cpp in Sources */,
|
||||
4BC9DF4F1D04691600F44158 /* 6560.cpp in Sources */,
|
||||
4B59199C1DAC6C46005BB85C /* OricTAP.cpp in Sources */,
|
||||
4BAF2B4E2004580C00480230 /* DMK.cpp in Sources */,
|
||||
4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */,
|
||||
4B7136861F78724F008B8ED9 /* Encoder.cpp in Sources */,
|
||||
4B0E04EA1FC9E5DA00F43484 /* CAS.cpp in Sources */,
|
||||
|
@ -265,11 +265,6 @@
|
||||
<string>$(PRODUCT_MODULE_NAME).MachineDocument</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>org.akop.cocoamsx.filetype.cassette</string>
|
||||
<string>com.clocksignal.cas</string>
|
||||
</array>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>cas</string>
|
||||
@ -281,11 +276,30 @@
|
||||
<string>MSX Tape Image</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>org.akop.cocoamsx.filetype.cassette</string>
|
||||
<string>com.clocksignal.cas</string>
|
||||
</array>
|
||||
<key>LSTypeIsPackage</key>
|
||||
<integer>0</integer>
|
||||
<key>NSDocumentClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).MachineDocument</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>dmk</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>floppy35</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Disk Image</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>LSTypeIsPackage</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "../Storage/Disk/DiskImage/Formats/CPCDSK.hpp"
|
||||
#include "../Storage/Disk/DiskImage/Formats/D64.hpp"
|
||||
#include "../Storage/Disk/DiskImage/Formats/G64.hpp"
|
||||
#include "../Storage/Disk/DiskImage/Formats/DMK.hpp"
|
||||
#include "../Storage/Disk/DiskImage/Formats/HFE.hpp"
|
||||
#include "../Storage/Disk/DiskImage/Formats/MSXDSK.hpp"
|
||||
#include "../Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp"
|
||||
@ -90,6 +91,7 @@ static Media GetMediaAndPlatforms(const char *file_name, TargetPlatform::IntType
|
||||
Format("cdt", result.tapes, Tape::TZX, TargetPlatform::AmstradCPC) // CDT
|
||||
Format("csw", result.tapes, Tape::CSW, TargetPlatform::AllTape) // CSW
|
||||
Format("d64", result.disks, Disk::DiskImageHolder<Storage::Disk::D64>, TargetPlatform::Commodore) // D64
|
||||
Format("dmk", result.disks, Disk::DiskImageHolder<Storage::Disk::DMK>, TargetPlatform::MSX) // DMK
|
||||
Format("dsd", result.disks, Disk::DiskImageHolder<Storage::Disk::SSD>, TargetPlatform::Acorn) // DSD
|
||||
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::CPCDSK>, TargetPlatform::AmstradCPC) // DSK (Amstrad CPC)
|
||||
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::MSXDSK>, TargetPlatform::MSX) // DSK (MSX)
|
||||
|
@ -15,7 +15,7 @@ namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
/*!
|
||||
Provies a @c Disk containing an ADF disk image — a decoded sector dump of an Acorn ADFS disk.
|
||||
Provides a @c Disk containing an ADF disk image — a decoded sector dump of an Acorn ADFS disk.
|
||||
*/
|
||||
class AcornADF: public MFMSectorDump {
|
||||
public:
|
||||
|
@ -19,7 +19,7 @@ namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
/*!
|
||||
Provies a @c Disk containing an Amstrad CPC-stype disk image — some arrangement of sectors with status bits.
|
||||
Provides a @c Disk containing an Amstrad CPC-type disk image — some arrangement of sectors with status bits.
|
||||
*/
|
||||
class CPCDSK: public DiskImage {
|
||||
public:
|
||||
|
@ -16,7 +16,7 @@ namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
/*!
|
||||
Provies a @c Disk containing a D64 disk image — a decoded sector dump of a C1540-format disk.
|
||||
Provides a @c Disk containing a D64 disk image — a decoded sector dump of a C1540-format disk.
|
||||
*/
|
||||
class D64: public DiskImage {
|
||||
public:
|
||||
|
188
Storage/Disk/DiskImage/Formats/DMK.cpp
Normal file
188
Storage/Disk/DiskImage/Formats/DMK.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
//
|
||||
// DMK.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 08/01/2018.
|
||||
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "DMK.hpp"
|
||||
|
||||
#include "../../Encodings/MFM/Constants.hpp"
|
||||
#include "../../Encodings/MFM/Encoder.hpp"
|
||||
#include "../../Track/PCMTrack.hpp"
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
namespace {
|
||||
|
||||
std::unique_ptr<Storage::Encodings::MFM::Encoder> new_encoder(Storage::Disk::PCMSegment &segment, bool is_double_density) {
|
||||
std::unique_ptr<Storage::Encodings::MFM::Encoder> encoder;
|
||||
|
||||
if(is_double_density) {
|
||||
encoder = Storage::Encodings::MFM::GetMFMEncoder(segment.data);
|
||||
segment.length_of_a_bit = Storage::Encodings::MFM::MFMBitLength;
|
||||
} else {
|
||||
encoder = Storage::Encodings::MFM::GetFMEncoder(segment.data);
|
||||
segment.length_of_a_bit = Storage::Encodings::MFM::FMBitLength;
|
||||
}
|
||||
|
||||
return encoder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DMK::DMK(const char *file_name) :
|
||||
file_(file_name) {
|
||||
// Determine whether this DMK represents a read-only disk (whether intentionally,
|
||||
// or by virtue of placement).
|
||||
uint8_t read_only_byte = file_.get8();
|
||||
if(read_only_byte != 0x00 && read_only_byte != 0xff) throw ErrorNotDMK;
|
||||
is_read_only_ = (read_only_byte == 0xff) || file_.get_is_known_read_only();
|
||||
|
||||
// Read track count and size.
|
||||
head_position_count_ = static_cast<int>(file_.get8());
|
||||
track_length_ = static_cast<long>(file_.get16le());
|
||||
|
||||
// Track length must be at least 0x80, as that's the size of the IDAM
|
||||
// table before track contents.
|
||||
if(track_length_ < 0x80) throw ErrorNotDMK;
|
||||
|
||||
// Read the file flags and apply them.
|
||||
uint8_t flags = file_.get8();
|
||||
head_count_ = 2 - ((flags & 0x10) >> 4);
|
||||
head_position_count_ /= head_count_;
|
||||
is_purely_single_density_ = !!(flags & 0x40);
|
||||
|
||||
// Skip to the end of the header and check that this is
|
||||
// "in the emulator's native format".
|
||||
file_.seek(0xc, SEEK_SET);
|
||||
uint32_t format = file_.get32le();
|
||||
if(format) throw ErrorNotDMK;
|
||||
}
|
||||
|
||||
int DMK::get_head_position_count() {
|
||||
return head_position_count_;
|
||||
}
|
||||
|
||||
int DMK::get_head_count() {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
bool DMK::get_is_read_only() {
|
||||
return true;
|
||||
// Given that track serialisation is not yet implemented, treat all DMKs as read-only.
|
||||
// return is_read_only_;
|
||||
}
|
||||
|
||||
long DMK::get_file_offset_for_position(Track::Address address) {
|
||||
return (address.head*head_count_ + address.position) * track_length_ + 16;
|
||||
}
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> DMK::get_track_at_position(::Storage::Disk::Track::Address address) {
|
||||
file_.seek(get_file_offset_for_position(address), SEEK_SET);
|
||||
|
||||
// Read the IDAM table.
|
||||
uint16_t idam_locations[64];
|
||||
std::size_t idam_count = 0;
|
||||
for(std::size_t c = 0; c < sizeof(idam_locations) / sizeof(*idam_locations); ++c) {
|
||||
idam_locations[idam_count] = file_.get16le();
|
||||
if((idam_locations[idam_count] & 0x7fff) >= 128) {
|
||||
idam_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Grab the rest of the track.
|
||||
std::vector<uint8_t> track = file_.read(static_cast<std::size_t>(track_length_ - 0x80));
|
||||
|
||||
// Default to outputting double density unless the disk doesn't support it.
|
||||
bool is_double_density = !is_purely_single_density_;
|
||||
std::vector<PCMSegment> segments;
|
||||
std::unique_ptr<Encodings::MFM::Encoder> encoder;
|
||||
segments.emplace_back();
|
||||
encoder = new_encoder(segments.back(), is_double_density);
|
||||
|
||||
std::size_t idam_pointer = 0;
|
||||
|
||||
const std::size_t track_length = static_cast<std::size_t>(track_length_) - 0x80;
|
||||
std::size_t track_pointer = 0;
|
||||
while(track_pointer < track_length) {
|
||||
// Determine bytes left until next IDAM.
|
||||
std::size_t destination;
|
||||
if(idam_pointer != idam_count) {
|
||||
destination = (idam_locations[idam_pointer] & 0x7fff) - 0x80;
|
||||
} else {
|
||||
destination = track_length;
|
||||
}
|
||||
|
||||
// Output every intermediate byte.
|
||||
if(!is_double_density && !is_purely_single_density_) {
|
||||
is_double_density = true;
|
||||
segments.emplace_back();
|
||||
encoder = new_encoder(segments.back(), is_double_density);
|
||||
}
|
||||
while(track_pointer < destination) {
|
||||
encoder->add_byte(track[track_pointer]);
|
||||
track_pointer++;
|
||||
}
|
||||
|
||||
// Exit now if that's it.
|
||||
if(destination == track_length) break;
|
||||
|
||||
// Being now located at the IDAM, check for a change of encoding.
|
||||
bool next_is_double_density = !!(idam_locations[idam_pointer] & 0x8000);
|
||||
if(next_is_double_density != is_double_density) {
|
||||
is_double_density = next_is_double_density;
|
||||
segments.emplace_back();
|
||||
encoder = new_encoder(segments.back(), is_double_density);
|
||||
}
|
||||
|
||||
// Now at the IDAM, which will always be an FE regardless of FM/MFM encoding,
|
||||
// presumably through misunderstanding of the designer? Write out a real IDAM
|
||||
// for the current density, then the rest of the ID — four bytes for the address
|
||||
// plus two for the CRC. Keep a copy of the header while we're here, so that the
|
||||
// size of the sector is known momentarily.
|
||||
std::size_t step_rate = (!is_double_density && !is_purely_single_density_) ? 2 : 1;
|
||||
encoder->add_ID_address_mark();
|
||||
uint8_t header[6];
|
||||
for(int c = 0; c < 6; ++c) {
|
||||
track_pointer += step_rate;
|
||||
encoder->add_byte(track[track_pointer]);
|
||||
header[c] = track[track_pointer];
|
||||
}
|
||||
track_pointer += step_rate;
|
||||
|
||||
// Now write out as many bytes as are found prior to an FB or F8 (same comment as
|
||||
// above: those are the FM-esque marks, but it seems as though transcription to MFM
|
||||
// is implicit).
|
||||
while(true) {
|
||||
uint8_t next_byte = track[track_pointer];
|
||||
track_pointer += step_rate;
|
||||
if(next_byte == 0xfb || next_byte == 0xf8) {
|
||||
// Write a data or deleted data address mark.
|
||||
if(next_byte == 0xfb) encoder->add_data_address_mark();
|
||||
else encoder->add_deleted_data_address_mark();
|
||||
break;
|
||||
}
|
||||
encoder->add_byte(next_byte);
|
||||
}
|
||||
|
||||
// Now write out a data mark (the file format appears to leave these implicit?),
|
||||
// then the sector contents plus the CRC.
|
||||
encoder->add_data_address_mark();
|
||||
int sector_size = 2 + (128 << header[3]);
|
||||
while(sector_size--) {
|
||||
encoder->add_byte(track[track_pointer]);
|
||||
track_pointer += step_rate;
|
||||
}
|
||||
|
||||
idam_pointer++;
|
||||
}
|
||||
|
||||
// All segments should be exactly their number of bits in length.
|
||||
for(auto &segment : segments) {
|
||||
segment.number_of_bits = static_cast<unsigned int>(segment.data.size() * 8);
|
||||
}
|
||||
|
||||
return std::make_shared<PCMTrack>(segments);
|
||||
}
|
57
Storage/Disk/DiskImage/Formats/DMK.hpp
Normal file
57
Storage/Disk/DiskImage/Formats/DMK.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
//
|
||||
// DMK.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 08/01/2018.
|
||||
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef DMK_hpp
|
||||
#define DMK_hpp
|
||||
|
||||
#include "../DiskImage.hpp"
|
||||
#include "../../../FileHolder.hpp"
|
||||
|
||||
namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
/*!
|
||||
Provides a @c Disk containing a DMK disk image — mostly a decoded byte stream, but with
|
||||
a record of IDAM locations.
|
||||
*/
|
||||
class DMK: public DiskImage {
|
||||
public:
|
||||
/*!
|
||||
Construct a @c DMK containing content from the file with name @c file_name.
|
||||
|
||||
@throws ErrorNotDMK if this file doesn't appear to be a DMK.
|
||||
*/
|
||||
DMK(const char *file_name);
|
||||
|
||||
enum {
|
||||
ErrorNotDMK
|
||||
};
|
||||
|
||||
// implemented to satisfy @c Disk
|
||||
int get_head_position_count() override;
|
||||
int get_head_count() override;
|
||||
bool get_is_read_only() override;
|
||||
|
||||
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) override;
|
||||
|
||||
private:
|
||||
FileHolder file_;
|
||||
long get_file_offset_for_position(Track::Address address);
|
||||
|
||||
bool is_read_only_;
|
||||
int head_position_count_;
|
||||
int head_count_;
|
||||
|
||||
long track_length_;
|
||||
bool is_purely_single_density_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DMK_hpp */
|
@ -16,7 +16,7 @@ namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
/*!
|
||||
Provies a @c Disk containing a G64 disk image — a raw but perfectly-clocked GCR stream.
|
||||
Provides a @c Disk containing a G64 disk image — a raw but perfectly-clocked GCR stream.
|
||||
*/
|
||||
class G64: public DiskImage {
|
||||
public:
|
||||
|
@ -16,7 +16,7 @@ namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
/*!
|
||||
Provies a @c Disk containing an HFE disk image — a bit stream representation of a floppy.
|
||||
Provides a @c Disk containing an HFE disk image — a bit stream representation of a floppy.
|
||||
*/
|
||||
class HFE: public DiskImage {
|
||||
public:
|
||||
|
@ -16,7 +16,7 @@ namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
/*!
|
||||
Provies the base for writeable [M]FM disk images that just contain contiguous sector content dumps.
|
||||
Provides the base for writeable [M]FM disk images that just contain contiguous sector content dumps.
|
||||
*/
|
||||
class MFMSectorDump: public DiskImage {
|
||||
public:
|
||||
|
@ -8,10 +8,10 @@
|
||||
|
||||
#include "OricMFMDSK.hpp"
|
||||
|
||||
#include "../../Track/PCMTrack.hpp"
|
||||
#include "../../Encodings/MFM/Constants.hpp"
|
||||
#include "../../Encodings/MFM/Shifter.hpp"
|
||||
#include "../../Encodings/MFM/Encoder.hpp"
|
||||
#include "../../Track/PCMTrack.hpp"
|
||||
#include "../../Track/TrackSerialiser.hpp"
|
||||
|
||||
using namespace Storage::Disk;
|
||||
@ -109,9 +109,7 @@ std::shared_ptr<Track> OricMFMDSK::get_track_at_position(Track::Address address)
|
||||
}
|
||||
|
||||
segment.number_of_bits = static_cast<unsigned int>(segment.data.size() * 8);
|
||||
|
||||
std::shared_ptr<PCMTrack> track(new PCMTrack(segment));
|
||||
return track;
|
||||
return std::make_shared<PCMTrack>(segment);
|
||||
}
|
||||
|
||||
void OricMFMDSK::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) {
|
||||
|
@ -15,7 +15,7 @@ namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
/*!
|
||||
Provies a @c Disk containing a DSD or SSD disk image — a decoded sector dump of an Acorn DFS disk.
|
||||
Provides a @c Disk containing a DSD or SSD disk image — a decoded sector dump of an Acorn DFS disk.
|
||||
*/
|
||||
class SSD: public MFMSectorDump {
|
||||
public:
|
||||
|
@ -26,7 +26,7 @@ namespace Disk {
|
||||
*/
|
||||
struct PCMSegment {
|
||||
Time length_of_a_bit;
|
||||
unsigned int number_of_bits;
|
||||
unsigned int number_of_bits = 0;
|
||||
std::vector<uint8_t> data;
|
||||
|
||||
PCMSegment(Time length_of_a_bit, unsigned int number_of_bits, std::vector<uint8_t> data)
|
||||
@ -36,6 +36,11 @@ struct PCMSegment {
|
||||
int bit(std::size_t index) const {
|
||||
return (data[index >> 3] >> (7 ^ (index & 7)))&1;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
number_of_bits = 0;
|
||||
data.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
|
Loading…
Reference in New Issue
Block a user