mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-18 01:30:56 +00:00
Merge pull request #1263 from TomHarte/IMDFiles
Add read-only support for IMD files.
This commit is contained in:
commit
671e59b27a
@ -50,6 +50,7 @@
|
|||||||
#include "../../Storage/Disk/DiskImage/Formats/FAT12.hpp"
|
#include "../../Storage/Disk/DiskImage/Formats/FAT12.hpp"
|
||||||
#include "../../Storage/Disk/DiskImage/Formats/HFE.hpp"
|
#include "../../Storage/Disk/DiskImage/Formats/HFE.hpp"
|
||||||
#include "../../Storage/Disk/DiskImage/Formats/IPF.hpp"
|
#include "../../Storage/Disk/DiskImage/Formats/IPF.hpp"
|
||||||
|
#include "../../Storage/Disk/DiskImage/Formats/IMD.hpp"
|
||||||
#include "../../Storage/Disk/DiskImage/Formats/MacintoshIMG.hpp"
|
#include "../../Storage/Disk/DiskImage/Formats/MacintoshIMG.hpp"
|
||||||
#include "../../Storage/Disk/DiskImage/Formats/MSA.hpp"
|
#include "../../Storage/Disk/DiskImage/Formats/MSA.hpp"
|
||||||
#include "../../Storage/Disk/DiskImage/Formats/NIB.hpp"
|
#include "../../Storage/Disk/DiskImage/Formats/NIB.hpp"
|
||||||
@ -182,6 +183,7 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
|
|||||||
// HFE (TODO: switch to AllDisk once the MSX stops being so greedy)
|
// HFE (TODO: switch to AllDisk once the MSX stops being so greedy)
|
||||||
Format("ima", result.disks, Disk::DiskImageHolder<Storage::Disk::FAT12>, TargetPlatform::PCCompatible) // IMG (MS-DOS style)
|
Format("ima", result.disks, Disk::DiskImageHolder<Storage::Disk::FAT12>, TargetPlatform::PCCompatible) // IMG (MS-DOS style)
|
||||||
Format("image", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
|
Format("image", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
|
||||||
|
Format("imd", result.disks, Disk::DiskImageHolder<Storage::Disk::IMD>, TargetPlatform::PCCompatible) // IMD
|
||||||
Format("img", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
|
Format("img", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
|
||||||
|
|
||||||
// Treat PC booter as a potential backup only if this doesn't parse as a FAT12.
|
// Treat PC booter as a potential backup only if this doesn't parse as a FAT12.
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
42A5E8532ABBE16F00A0DD5D /* lax_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 42A5E8422ABBE16F00A0DD5D /* lax_test.bin */; };
|
42A5E8532ABBE16F00A0DD5D /* lax_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 42A5E8422ABBE16F00A0DD5D /* lax_test.bin */; };
|
||||||
42A5E8542ABBE16F00A0DD5D /* branch_backwards_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 42A5E8432ABBE16F00A0DD5D /* branch_backwards_test.bin */; };
|
42A5E8542ABBE16F00A0DD5D /* branch_backwards_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 42A5E8432ABBE16F00A0DD5D /* branch_backwards_test.bin */; };
|
||||||
42E5C3932AC46A7700DA093D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42E5C3922AC46A7700DA093D /* Carbon.framework */; };
|
42E5C3932AC46A7700DA093D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42E5C3922AC46A7700DA093D /* Carbon.framework */; };
|
||||||
|
42EB81282B23AAC300429AF4 /* IMD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42EB81262B23AAC300429AF4 /* IMD.cpp */; };
|
||||||
|
42EB81292B23AAC300429AF4 /* IMD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42EB81262B23AAC300429AF4 /* IMD.cpp */; };
|
||||||
4B018B89211930DE002A3937 /* 65C02_extended_opcodes_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */; };
|
4B018B89211930DE002A3937 /* 65C02_extended_opcodes_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */; };
|
||||||
4B01A6881F22F0DB001FD6E3 /* Z80MemptrTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */; };
|
4B01A6881F22F0DB001FD6E3 /* Z80MemptrTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */; };
|
||||||
4B0333AF2094081A0050B93D /* AppleDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0333AD2094081A0050B93D /* AppleDSK.cpp */; };
|
4B0333AF2094081A0050B93D /* AppleDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0333AD2094081A0050B93D /* AppleDSK.cpp */; };
|
||||||
@ -1195,6 +1197,8 @@
|
|||||||
42AD55312A0C4D5000ACE410 /* 68000Implementation.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 68000Implementation.hpp; sourceTree = "<group>"; };
|
42AD55312A0C4D5000ACE410 /* 68000Implementation.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 68000Implementation.hpp; sourceTree = "<group>"; };
|
||||||
42E5C3922AC46A7700DA093D /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
|
42E5C3922AC46A7700DA093D /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
|
||||||
42EB81252B21788200429AF4 /* RTC.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RTC.hpp; sourceTree = "<group>"; };
|
42EB81252B21788200429AF4 /* RTC.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RTC.hpp; sourceTree = "<group>"; };
|
||||||
|
42EB81262B23AAC300429AF4 /* IMD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IMD.cpp; sourceTree = "<group>"; };
|
||||||
|
42EB81272B23AAC300429AF4 /* IMD.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = IMD.hpp; sourceTree = "<group>"; };
|
||||||
4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = 65C02_extended_opcodes_test.bin; path = "Klaus Dormann/65C02_extended_opcodes_test.bin"; sourceTree = "<group>"; };
|
4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = 65C02_extended_opcodes_test.bin; path = "Klaus Dormann/65C02_extended_opcodes_test.bin"; sourceTree = "<group>"; };
|
||||||
4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MemptrTests.swift; sourceTree = "<group>"; };
|
4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MemptrTests.swift; sourceTree = "<group>"; };
|
||||||
4B0333AD2094081A0050B93D /* AppleDSK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AppleDSK.cpp; sourceTree = "<group>"; };
|
4B0333AD2094081A0050B93D /* AppleDSK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AppleDSK.cpp; sourceTree = "<group>"; };
|
||||||
@ -3064,6 +3068,7 @@
|
|||||||
4BEBFB4B2002C4BF000708CC /* FAT12.cpp */,
|
4BEBFB4B2002C4BF000708CC /* FAT12.cpp */,
|
||||||
4B4518931F75FD1B00926311 /* G64.cpp */,
|
4B4518931F75FD1B00926311 /* G64.cpp */,
|
||||||
4B4518951F75FD1B00926311 /* HFE.cpp */,
|
4B4518951F75FD1B00926311 /* HFE.cpp */,
|
||||||
|
42EB81262B23AAC300429AF4 /* IMD.cpp */,
|
||||||
4B5B372F2777C7FC0047F238 /* IPF.cpp */,
|
4B5B372F2777C7FC0047F238 /* IPF.cpp */,
|
||||||
4BB4BFAE22A42F290069048D /* MacintoshIMG.cpp */,
|
4BB4BFAE22A42F290069048D /* MacintoshIMG.cpp */,
|
||||||
4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */,
|
4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */,
|
||||||
@ -3084,6 +3089,7 @@
|
|||||||
4BEBFB4C2002C4BF000708CC /* FAT12.hpp */,
|
4BEBFB4C2002C4BF000708CC /* FAT12.hpp */,
|
||||||
4B4518941F75FD1B00926311 /* G64.hpp */,
|
4B4518941F75FD1B00926311 /* G64.hpp */,
|
||||||
4B4518961F75FD1B00926311 /* HFE.hpp */,
|
4B4518961F75FD1B00926311 /* HFE.hpp */,
|
||||||
|
42EB81272B23AAC300429AF4 /* IMD.hpp */,
|
||||||
4B5B37302777C7FC0047F238 /* IPF.hpp */,
|
4B5B37302777C7FC0047F238 /* IPF.hpp */,
|
||||||
4BB4BFAF22A42F290069048D /* MacintoshIMG.hpp */,
|
4BB4BFAF22A42F290069048D /* MacintoshIMG.hpp */,
|
||||||
4B58601D1F806AB200AEE2E3 /* MFMSectorDump.hpp */,
|
4B58601D1F806AB200AEE2E3 /* MFMSectorDump.hpp */,
|
||||||
@ -5959,6 +5965,7 @@
|
|||||||
4B051C912669C90B00CA44E8 /* ROMCatalogue.cpp in Sources */,
|
4B051C912669C90B00CA44E8 /* ROMCatalogue.cpp in Sources */,
|
||||||
4B055AB91FAE86170060FFFF /* Acorn.cpp in Sources */,
|
4B055AB91FAE86170060FFFF /* Acorn.cpp in Sources */,
|
||||||
4B302185208A550100773308 /* DiskII.cpp in Sources */,
|
4B302185208A550100773308 /* DiskII.cpp in Sources */,
|
||||||
|
42EB81292B23AAC300429AF4 /* IMD.cpp in Sources */,
|
||||||
4B051CB1267C1CA200CA44E8 /* Keyboard.cpp in Sources */,
|
4B051CB1267C1CA200CA44E8 /* Keyboard.cpp in Sources */,
|
||||||
4B0F1BB32602645900B85C66 /* StaticAnalyser.cpp in Sources */,
|
4B0F1BB32602645900B85C66 /* StaticAnalyser.cpp in Sources */,
|
||||||
4B055A931FAE85B50060FFFF /* BinaryDump.cpp in Sources */,
|
4B055A931FAE85B50060FFFF /* BinaryDump.cpp in Sources */,
|
||||||
@ -6057,6 +6064,7 @@
|
|||||||
4B0333AF2094081A0050B93D /* AppleDSK.cpp in Sources */,
|
4B0333AF2094081A0050B93D /* AppleDSK.cpp in Sources */,
|
||||||
4B894518201967B4007DE474 /* ConfidenceCounter.cpp in Sources */,
|
4B894518201967B4007DE474 /* ConfidenceCounter.cpp in Sources */,
|
||||||
4BCE005A227CFFCA000CA200 /* Macintosh.cpp in Sources */,
|
4BCE005A227CFFCA000CA200 /* Macintosh.cpp in Sources */,
|
||||||
|
42EB81282B23AAC300429AF4 /* IMD.cpp in Sources */,
|
||||||
4B6AAEA4230E3E1D0078E864 /* MassStorageDevice.cpp in Sources */,
|
4B6AAEA4230E3E1D0078E864 /* MassStorageDevice.cpp in Sources */,
|
||||||
4B89452E201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
4B89452E201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||||
4BC890D3230F86020025A55A /* DirectAccessDevice.cpp in Sources */,
|
4BC890D3230F86020025A55A /* DirectAccessDevice.cpp in Sources */,
|
||||||
|
@ -691,6 +691,26 @@
|
|||||||
<key>NSDocumentClass</key>
|
<key>NSDocumentClass</key>
|
||||||
<string>$(PRODUCT_MODULE_NAME).MachineDocument</string>
|
<string>$(PRODUCT_MODULE_NAME).MachineDocument</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>imd</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>IMD disk image</string>
|
||||||
|
<key>CFBundleTypeOSTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>????</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
<key>LSHandlerRank</key>
|
||||||
|
<string>Owner</string>
|
||||||
|
<key>LSTypeIsPackage</key>
|
||||||
|
<false/>
|
||||||
|
<key>NSDocumentClass</key>
|
||||||
|
<string>$(PRODUCT_MODULE_NAME).MachineDocument</string>
|
||||||
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleTypeExtensions</key>
|
<key>CFBundleTypeExtensions</key>
|
||||||
<array>
|
<array>
|
||||||
|
@ -24,19 +24,18 @@ namespace Storage::Disk {
|
|||||||
class CPCDSK: public DiskImage {
|
class CPCDSK: public DiskImage {
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
Construct an @c AcornADF containing content from the file with name @c file_name.
|
Construct a @c CPCDSK containing content from the file with name @c file_name.
|
||||||
|
|
||||||
@throws Storage::FileHolder::Error::CantOpen if this file can't be opened.
|
@throws Storage::FileHolder::Error::CantOpen if this file can't be opened.
|
||||||
@throws Error::InvalidFormat if the file doesn't appear to contain an Acorn .ADF format image.
|
@throws Error::InvalidFormat if the file doesn't appear to contain an Acorn .ADF format image.
|
||||||
*/
|
*/
|
||||||
CPCDSK(const std::string &file_name);
|
CPCDSK(const std::string &file_name);
|
||||||
|
|
||||||
// implemented to satisfy @c Disk
|
// DiskImage interface.
|
||||||
HeadPosition get_maximum_head_position() final;
|
HeadPosition get_maximum_head_position() final;
|
||||||
int get_head_count() final;
|
int get_head_count() final;
|
||||||
bool get_is_read_only() final;
|
bool get_is_read_only() final;
|
||||||
|
void set_tracks(const std::map<::Storage::Disk::Track::Address, std::shared_ptr<::Storage::Disk::Track>> &tracks) final;
|
||||||
void set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tracks) final;
|
|
||||||
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final;
|
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
163
Storage/Disk/DiskImage/Formats/IMD.cpp
Normal file
163
Storage/Disk/DiskImage/Formats/IMD.cpp
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
//
|
||||||
|
// IMD.cpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 08/12/2023.
|
||||||
|
// Copyright © 2023 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "IMD.hpp"
|
||||||
|
|
||||||
|
#include "../../Encodings/MFM/Constants.hpp"
|
||||||
|
#include "../../Encodings/MFM/Encoder.hpp"
|
||||||
|
#include "../../Encodings/MFM/SegmentParser.hpp"
|
||||||
|
#include "../../Track/TrackSerialiser.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
using namespace Storage::Disk;
|
||||||
|
|
||||||
|
// Documentation source: https://oldcomputers-ddns.org/public/pub/manuals/imd.pdf
|
||||||
|
|
||||||
|
IMD::IMD(const std::string &file_name) : file_(file_name) {
|
||||||
|
// Check for signature.
|
||||||
|
if(!file_.check_signature("IMD")) {
|
||||||
|
throw Error::InvalidFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip rest of ASCII.
|
||||||
|
while(file_.get8() != 0x1a);
|
||||||
|
|
||||||
|
// Build track map.
|
||||||
|
while(true) {
|
||||||
|
const auto location = file_.tell();
|
||||||
|
|
||||||
|
// Skip mode.
|
||||||
|
file_.seek(1, SEEK_CUR);
|
||||||
|
|
||||||
|
// Grab relevant fields.
|
||||||
|
const uint8_t cylinder = file_.get8();
|
||||||
|
const uint8_t head = file_.get8();
|
||||||
|
const uint8_t sector_count = file_.get8();
|
||||||
|
const uint8_t sector_size = file_.get8();
|
||||||
|
if(file_.eof()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cylinders_ = std::max(cylinder, cylinders_);
|
||||||
|
heads_ = std::max(uint8_t(head & 1), heads_);
|
||||||
|
|
||||||
|
// Update head and cylinder extents, record sector location for later.
|
||||||
|
track_locations_.emplace(
|
||||||
|
Storage::Disk::Track::Address(head & 1, HeadPosition(cylinder)),
|
||||||
|
location);
|
||||||
|
|
||||||
|
// Skip sector numbers.
|
||||||
|
file_.seek(sector_count, SEEK_CUR);
|
||||||
|
|
||||||
|
// Skip cylinder map.
|
||||||
|
if(head & 0x80) {
|
||||||
|
file_.seek(sector_count, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip head map.
|
||||||
|
if(head & 0x40) {
|
||||||
|
file_.seek(sector_count, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip sectors.
|
||||||
|
for(int c = 0; c < sector_count; c++) {
|
||||||
|
const uint8_t type = file_.get8();
|
||||||
|
switch(type) {
|
||||||
|
case 0x00: break; // Sector couldn't be read.
|
||||||
|
|
||||||
|
// Types with all sector data present.
|
||||||
|
case 0x01: case 0x03: case 0x05: case 0x07:
|
||||||
|
file_.seek(128 << sector_size, SEEK_CUR);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Types with a single byte present.
|
||||||
|
case 0x02: case 0x04: case 0x06: case 0x08:
|
||||||
|
file_.seek(1, SEEK_CUR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both heads_ and cylinders_ are now the maximum observed IDs, which
|
||||||
|
// are one less than the counts.
|
||||||
|
++ cylinders_;
|
||||||
|
++ heads_;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeadPosition IMD::get_maximum_head_position() {
|
||||||
|
return HeadPosition(cylinders_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int IMD::get_head_count() {
|
||||||
|
return heads_ + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<::Storage::Disk::Track> IMD::get_track_at_position(::Storage::Disk::Track::Address address) {
|
||||||
|
auto location = track_locations_.find(address);
|
||||||
|
if(location == track_locations_.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek to track, parse fully this time.
|
||||||
|
file_.seek(location->second, SEEK_SET);
|
||||||
|
|
||||||
|
const uint8_t mode = file_.get8();
|
||||||
|
const uint8_t cylinder = file_.get8();
|
||||||
|
const uint8_t head = file_.get8();
|
||||||
|
const uint8_t sector_count = file_.get8();
|
||||||
|
const uint8_t sector_size = file_.get8();
|
||||||
|
|
||||||
|
const std::vector<uint8_t> sector_ids = file_.read(sector_count);
|
||||||
|
const std::vector<uint8_t> cylinders = (head & 0x80) ? file_.read(sector_count) : std::vector<uint8_t>{};
|
||||||
|
const std::vector<uint8_t> heads = (head & 0x40) ? file_.read(sector_count) : std::vector<uint8_t>{};
|
||||||
|
|
||||||
|
std::vector<Storage::Encodings::MFM::Sector> sectors;
|
||||||
|
sectors.reserve(sector_count);
|
||||||
|
|
||||||
|
for(size_t c = 0; c < sector_count; c++) {
|
||||||
|
sectors.emplace_back();
|
||||||
|
Storage::Encodings::MFM::Sector §or = sectors.back();
|
||||||
|
|
||||||
|
// Set up sector address.
|
||||||
|
sector.address.track = cylinders.empty() ? cylinder : cylinders[c];
|
||||||
|
sector.address.side = heads.empty() ? head & 1 : heads[c];
|
||||||
|
sector.address.sector = sector_ids[c];
|
||||||
|
sector.size = sector_size;
|
||||||
|
|
||||||
|
const auto byte_size = size_t(128 << sector_size);
|
||||||
|
uint8_t type = file_.get8();
|
||||||
|
|
||||||
|
// Type 0: sector was present, but couldn't be read.
|
||||||
|
// Since body CRC errors are a separate item, just don't include a body at all.
|
||||||
|
if(!type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrement type to turn it into a bit field:
|
||||||
|
//
|
||||||
|
// b0 => is compressed within disk image;
|
||||||
|
// b1 => had deleted address mark;
|
||||||
|
// b2 => had data CRC error.
|
||||||
|
--type;
|
||||||
|
sector.is_deleted = type & 2;
|
||||||
|
sector.has_data_crc_error = type & 4;
|
||||||
|
if(type & 1) {
|
||||||
|
sector.samples.emplace_back(byte_size, file_.get8());
|
||||||
|
} else {
|
||||||
|
sector.samples.push_back(file_.read(byte_size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mode also indicates data density, but I don't have a good strategy for reconciling that if
|
||||||
|
// it were to disagree with the density implied by the quantity of sectors. So a broad 'is it MFM' test is
|
||||||
|
// applied only.
|
||||||
|
return (mode >= 3) ?
|
||||||
|
Storage::Encodings::MFM::GetMFMTrackWithSectors(sectors) :
|
||||||
|
Storage::Encodings::MFM::GetFMTrackWithSectors(sectors);
|
||||||
|
}
|
45
Storage/Disk/DiskImage/Formats/IMD.hpp
Normal file
45
Storage/Disk/DiskImage/Formats/IMD.hpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// IMD.hpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 08/12/2023.
|
||||||
|
// Copyright © 2023 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef IMD_hpp
|
||||||
|
#define IMD_hpp
|
||||||
|
|
||||||
|
#include "../DiskImage.hpp"
|
||||||
|
#include "../../../FileHolder.hpp"
|
||||||
|
|
||||||
|
namespace Storage::Disk {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Provides an @c DiskImage containing an IMD image, which is a collection of arbitrarily-numbered FM or MFM
|
||||||
|
sectors collected by track.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class IMD: public DiskImage {
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
Construct an @c IMD containing content from the file with name @c file_name.
|
||||||
|
|
||||||
|
@throws Storage::FileHolder::Error::CantOpen if this file can't be opened.
|
||||||
|
@throws Error::InvalidFormat if the file doesn't appear to contain an Acorn .ADF format image.
|
||||||
|
*/
|
||||||
|
IMD(const std::string &file_name);
|
||||||
|
|
||||||
|
// DiskImage interface.
|
||||||
|
HeadPosition get_maximum_head_position() final;
|
||||||
|
int get_head_count() final;
|
||||||
|
std::shared_ptr<::Storage::Disk::Track> get_track_at_position(::Storage::Disk::Track::Address address) final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FileHolder file_;
|
||||||
|
std::map<Storage::Disk::Track::Address, long> track_locations_;
|
||||||
|
uint8_t cylinders_ = 0, heads_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* IMD_hpp */
|
Loading…
x
Reference in New Issue
Block a user