mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-07 05:30:30 +00:00
Merge pull request #422 from TomHarte/DiskIIAnalyser
Introduces an analyser for Disk II-esque files.
This commit is contained in:
commit
9ff34d90f4
123
Analyser/Static/DiskII/StaticAnalyser.cpp
Normal file
123
Analyser/Static/DiskII/StaticAnalyser.cpp
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
//
|
||||||
|
// StaticAnalyser.cpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 03/05/2018.
|
||||||
|
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "StaticAnalyser.hpp"
|
||||||
|
|
||||||
|
#include "../AppleII/Target.hpp"
|
||||||
|
#include "../Oric/Target.hpp"
|
||||||
|
#include "../Disassembler/6502.hpp"
|
||||||
|
#include "../Disassembler/AddressMapper.hpp"
|
||||||
|
|
||||||
|
#include "../../../Storage/Disk/Track/TrackSerialiser.hpp"
|
||||||
|
#include "../../../Storage/Disk/Encodings/AppleGCR/SegmentParser.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
Analyser::Static::Target *AppleTarget(const Storage::Encodings::AppleGCR::Sector *sector_zero) {
|
||||||
|
using Target = Analyser::Static::AppleII::Target;
|
||||||
|
auto *target = new Target;
|
||||||
|
target->machine = Analyser::Machine::AppleII;
|
||||||
|
|
||||||
|
if(sector_zero && sector_zero->encoding == Storage::Encodings::AppleGCR::Sector::Encoding::FiveAndThree) {
|
||||||
|
target->disk_controller = Target::DiskController::ThirteenSector;
|
||||||
|
} else {
|
||||||
|
target->disk_controller = Target::DiskController::SixteenSector;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
Analyser::Static::Target *OricTarget(const Storage::Encodings::AppleGCR::Sector *sector_zero) {
|
||||||
|
using Target = Analyser::Static::Oric::Target;
|
||||||
|
auto *target = new Target;
|
||||||
|
target->machine = Analyser::Machine::Oric;
|
||||||
|
|
||||||
|
// TODO: configure the Oric as a Pravetz 8D with 8DOS.
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) {
|
||||||
|
// This analyser can comprehend disks only.
|
||||||
|
if(media.disks.empty()) return {};
|
||||||
|
|
||||||
|
// Grab track 0, sector 0: the boot sector.
|
||||||
|
auto track_zero = media.disks.front()->get_track_at_position(Storage::Disk::Track::Address(0, 0));
|
||||||
|
auto sector_map = Storage::Encodings::AppleGCR::sectors_from_segment(
|
||||||
|
Storage::Disk::track_serialisation(*track_zero, Storage::Time(1, 50000)));
|
||||||
|
|
||||||
|
const Storage::Encodings::AppleGCR::Sector *sector_zero = nullptr;
|
||||||
|
for(const auto &pair: sector_map) {
|
||||||
|
if(!pair.second.address.sector) {
|
||||||
|
sector_zero = &pair.second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's no boot sector then if there are also no sectors at all,
|
||||||
|
// decline to nominate a machine. Otherwise go with an Apple as the default.
|
||||||
|
TargetList targets;
|
||||||
|
if(!sector_zero) {
|
||||||
|
if(sector_map.empty()) {
|
||||||
|
return targets;
|
||||||
|
} else {
|
||||||
|
targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleTarget(nullptr)));
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the boot sector looks like it's intended for the Oric, create an Oric.
|
||||||
|
// Otherwise go with the Apple II.
|
||||||
|
|
||||||
|
auto disassembly = Analyser::Static::MOS6502::Disassemble(sector_zero->data, Analyser::Static::Disassembler::OffsetMapper(0xb800), {0xb800});
|
||||||
|
|
||||||
|
bool did_read_shift_register = false;
|
||||||
|
bool is_oric = false;
|
||||||
|
|
||||||
|
// Look for a tight BPL loop reading the Oric's shift register address of 0x31c. The Apple II just has RAM there,
|
||||||
|
// so the probability of such a loop is infinitesimal.
|
||||||
|
for(const auto &instruction: disassembly.instructions_by_address) {
|
||||||
|
// Is this a read of the shift register?
|
||||||
|
if(
|
||||||
|
(
|
||||||
|
(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDA) ||
|
||||||
|
(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDX) ||
|
||||||
|
(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDY)
|
||||||
|
) &&
|
||||||
|
instruction.second.addressing_mode == Analyser::Static::MOS6502::Instruction::Absolute &&
|
||||||
|
instruction.second.address == 0x031c) {
|
||||||
|
did_read_shift_register = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(did_read_shift_register) {
|
||||||
|
if(
|
||||||
|
instruction.second.operation == Analyser::Static::MOS6502::Instruction::BPL &&
|
||||||
|
instruction.second.address == 0xfb) {
|
||||||
|
is_oric = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
did_read_shift_register = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check also for calls into the 0x3xx page above 0x320, as that's where the Oric's boot ROM is.
|
||||||
|
for(const auto address: disassembly.outward_calls) {
|
||||||
|
is_oric |= address >= 0x320 && address < 0x400;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_oric) {
|
||||||
|
targets.push_back(std::unique_ptr<Analyser::Static::Target>(OricTarget(sector_zero)));
|
||||||
|
} else {
|
||||||
|
targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleTarget(sector_zero)));
|
||||||
|
}
|
||||||
|
return targets;
|
||||||
|
}
|
27
Analyser/Static/DiskII/StaticAnalyser.hpp
Normal file
27
Analyser/Static/DiskII/StaticAnalyser.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// StaticAnalyser.hpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 03/05/2018.
|
||||||
|
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Analyser_Static_DiskII_StaticAnalyser_hpp
|
||||||
|
#define Analyser_Static_DiskII_StaticAnalyser_hpp
|
||||||
|
|
||||||
|
#include "../StaticAnalyser.hpp"
|
||||||
|
#include "../../../Storage/TargetPlatforms.hpp"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Analyser {
|
||||||
|
namespace Static {
|
||||||
|
namespace DiskII {
|
||||||
|
|
||||||
|
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* Analyser_Static_DiskII_StaticAnalyser_hpp */
|
@ -20,6 +20,7 @@
|
|||||||
#include "Atari/StaticAnalyser.hpp"
|
#include "Atari/StaticAnalyser.hpp"
|
||||||
#include "Coleco/StaticAnalyser.hpp"
|
#include "Coleco/StaticAnalyser.hpp"
|
||||||
#include "Commodore/StaticAnalyser.hpp"
|
#include "Commodore/StaticAnalyser.hpp"
|
||||||
|
#include "DiskII/StaticAnalyser.hpp"
|
||||||
#include "MSX/StaticAnalyser.hpp"
|
#include "MSX/StaticAnalyser.hpp"
|
||||||
#include "Oric/StaticAnalyser.hpp"
|
#include "Oric/StaticAnalyser.hpp"
|
||||||
#include "ZX8081/StaticAnalyser.hpp"
|
#include "ZX8081/StaticAnalyser.hpp"
|
||||||
@ -94,10 +95,10 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
|
|||||||
Format("csw", result.tapes, Tape::CSW, TargetPlatform::AllTape) // CSW
|
Format("csw", result.tapes, Tape::CSW, TargetPlatform::AllTape) // CSW
|
||||||
Format("d64", result.disks, Disk::DiskImageHolder<Storage::Disk::D64>, TargetPlatform::Commodore) // D64
|
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("dmk", result.disks, Disk::DiskImageHolder<Storage::Disk::DMK>, TargetPlatform::MSX) // DMK
|
||||||
Format("do", result.disks, Disk::DiskImageHolder<Storage::Disk::AppleDSK>, TargetPlatform::AppleII) // DO
|
Format("do", result.disks, Disk::DiskImageHolder<Storage::Disk::AppleDSK>, TargetPlatform::DiskII) // DO
|
||||||
Format("dsd", result.disks, Disk::DiskImageHolder<Storage::Disk::SSD>, TargetPlatform::Acorn) // DSD
|
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::CPCDSK>, TargetPlatform::AmstradCPC) // DSK (Amstrad CPC)
|
||||||
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::AppleDSK>, TargetPlatform::AppleII) // DSK (Apple)
|
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::AppleDSK>, TargetPlatform::DiskII) // DSK (Apple)
|
||||||
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::MSXDSK>, TargetPlatform::MSX) // DSK (MSX)
|
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::MSXDSK>, TargetPlatform::MSX) // DSK (MSX)
|
||||||
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::OricMFMDSK>, TargetPlatform::Oric) // DSK (Oric)
|
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::OricMFMDSK>, TargetPlatform::Oric) // DSK (Oric)
|
||||||
Format("g64", result.disks, Disk::DiskImageHolder<Storage::Disk::G64>, TargetPlatform::Commodore) // G64
|
Format("g64", result.disks, Disk::DiskImageHolder<Storage::Disk::G64>, TargetPlatform::Commodore) // G64
|
||||||
@ -106,10 +107,10 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
|
|||||||
Disk::DiskImageHolder<Storage::Disk::HFE>,
|
Disk::DiskImageHolder<Storage::Disk::HFE>,
|
||||||
TargetPlatform::Acorn | TargetPlatform::AmstradCPC | TargetPlatform::Commodore | TargetPlatform::Oric)
|
TargetPlatform::Acorn | TargetPlatform::AmstradCPC | TargetPlatform::Commodore | TargetPlatform::Oric)
|
||||||
// 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("nib", result.disks, Disk::DiskImageHolder<Storage::Disk::NIB>, TargetPlatform::AppleII) // NIB
|
Format("nib", result.disks, Disk::DiskImageHolder<Storage::Disk::NIB>, TargetPlatform::DiskII) // NIB
|
||||||
Format("o", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // O
|
Format("o", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // O
|
||||||
Format("p", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P
|
Format("p", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P
|
||||||
Format("po", result.disks, Disk::DiskImageHolder<Storage::Disk::AppleDSK>, TargetPlatform::AppleII) // PO
|
Format("po", result.disks, Disk::DiskImageHolder<Storage::Disk::AppleDSK>, TargetPlatform::DiskII) // PO
|
||||||
Format("p81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P81
|
Format("p81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P81
|
||||||
|
|
||||||
// PRG
|
// PRG
|
||||||
@ -134,7 +135,7 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
|
|||||||
Format("tsx", result.tapes, Tape::TZX, TargetPlatform::MSX) // TSX
|
Format("tsx", result.tapes, Tape::TZX, TargetPlatform::MSX) // TSX
|
||||||
Format("tzx", result.tapes, Tape::TZX, TargetPlatform::ZX8081) // TZX
|
Format("tzx", result.tapes, Tape::TZX, TargetPlatform::ZX8081) // TZX
|
||||||
Format("uef", result.tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape)
|
Format("uef", result.tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape)
|
||||||
Format("woz", result.disks, Disk::DiskImageHolder<Storage::Disk::WOZ>, TargetPlatform::AppleII) // WOZ
|
Format("woz", result.disks, Disk::DiskImageHolder<Storage::Disk::WOZ>, TargetPlatform::DiskII) // WOZ
|
||||||
|
|
||||||
#undef Format
|
#undef Format
|
||||||
#undef Insert
|
#undef Insert
|
||||||
@ -168,6 +169,7 @@ TargetList Analyser::Static::GetTargets(const std::string &file_name) {
|
|||||||
if(potential_platforms & TargetPlatform::Atari2600) Append(Atari);
|
if(potential_platforms & TargetPlatform::Atari2600) Append(Atari);
|
||||||
if(potential_platforms & TargetPlatform::ColecoVision) Append(Coleco);
|
if(potential_platforms & TargetPlatform::ColecoVision) Append(Coleco);
|
||||||
if(potential_platforms & TargetPlatform::Commodore) Append(Commodore);
|
if(potential_platforms & TargetPlatform::Commodore) Append(Commodore);
|
||||||
|
if(potential_platforms & TargetPlatform::DiskII) Append(DiskII);
|
||||||
if(potential_platforms & TargetPlatform::MSX) Append(MSX);
|
if(potential_platforms & TargetPlatform::MSX) Append(MSX);
|
||||||
if(potential_platforms & TargetPlatform::Oric) Append(Oric);
|
if(potential_platforms & TargetPlatform::Oric) Append(Oric);
|
||||||
if(potential_platforms & TargetPlatform::ZX8081) Append(ZX8081);
|
if(potential_platforms & TargetPlatform::ZX8081) Append(ZX8081);
|
||||||
|
@ -587,8 +587,6 @@
|
|||||||
4BB299F81B587D8400A49093 /* txsn in Resources */ = {isa = PBXBuildFile; fileRef = 4BB298EC1B587D8400A49093 /* txsn */; };
|
4BB299F81B587D8400A49093 /* txsn in Resources */ = {isa = PBXBuildFile; fileRef = 4BB298EC1B587D8400A49093 /* txsn */; };
|
||||||
4BB299F91B587D8400A49093 /* tyan in Resources */ = {isa = PBXBuildFile; fileRef = 4BB298ED1B587D8400A49093 /* tyan */; };
|
4BB299F91B587D8400A49093 /* tyan in Resources */ = {isa = PBXBuildFile; fileRef = 4BB298ED1B587D8400A49093 /* tyan */; };
|
||||||
4BB2A9AF1E13367E001A5C23 /* CRCTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */; };
|
4BB2A9AF1E13367E001A5C23 /* CRCTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */; };
|
||||||
4BB2CB2A208BDDCF00FD192E /* AppleGCR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB2CB28208BDDCF00FD192E /* AppleGCR.cpp */; };
|
|
||||||
4BB2CB2B208BDDCF00FD192E /* AppleGCR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB2CB28208BDDCF00FD192E /* AppleGCR.cpp */; };
|
|
||||||
4BB697CB1D4B6D3E00248BDF /* TimedEventLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */; };
|
4BB697CB1D4B6D3E00248BDF /* TimedEventLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */; };
|
||||||
4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */; };
|
4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */; };
|
||||||
4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EA11B587A5100552FC2 /* AppDelegate.swift */; };
|
4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EA11B587A5100552FC2 /* AppDelegate.swift */; };
|
||||||
@ -626,6 +624,10 @@
|
|||||||
4BD4A8D01E077FD20020D856 /* PCMTrackTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BD4A8CF1E077FD20020D856 /* PCMTrackTests.mm */; };
|
4BD4A8D01E077FD20020D856 /* PCMTrackTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BD4A8CF1E077FD20020D856 /* PCMTrackTests.mm */; };
|
||||||
4BD5F1951D13528900631CD1 /* CSBestEffortUpdater.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.mm */; };
|
4BD5F1951D13528900631CD1 /* CSBestEffortUpdater.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.mm */; };
|
||||||
4BD61664206B2AC800236112 /* QuickLoadOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BD61662206B2AC700236112 /* QuickLoadOptions.xib */; };
|
4BD61664206B2AC800236112 /* QuickLoadOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BD61662206B2AC700236112 /* QuickLoadOptions.xib */; };
|
||||||
|
4BD67DCB209BE4D700AB2146 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD67DCA209BE4D600AB2146 /* StaticAnalyser.cpp */; };
|
||||||
|
4BD67DCC209BE4D700AB2146 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD67DCA209BE4D600AB2146 /* StaticAnalyser.cpp */; };
|
||||||
|
4BD67DD0209BF27B00AB2146 /* Encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD67DCE209BF27B00AB2146 /* Encoder.cpp */; };
|
||||||
|
4BD67DD1209BF27B00AB2146 /* Encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD67DCE209BF27B00AB2146 /* Encoder.cpp */; };
|
||||||
4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A539A1D117D36003C6002 /* CSAtari2600.mm */; };
|
4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A539A1D117D36003C6002 /* CSAtari2600.mm */; };
|
||||||
4BDB61EC203285AE0048AF91 /* Atari2600OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsPanel.swift */; };
|
4BDB61EC203285AE0048AF91 /* Atari2600OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsPanel.swift */; };
|
||||||
4BDDBA991EF3451200347E61 /* Z80MachineCycleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */; };
|
4BDDBA991EF3451200347E61 /* Z80MachineCycleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */; };
|
||||||
@ -642,6 +644,8 @@
|
|||||||
4BEE0A701D72496600532C7B /* PRG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6D1D72496600532C7B /* PRG.cpp */; };
|
4BEE0A701D72496600532C7B /* PRG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE0A6D1D72496600532C7B /* PRG.cpp */; };
|
||||||
4BEF6AAA1D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BEF6AA91D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm */; };
|
4BEF6AAA1D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BEF6AA91D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm */; };
|
||||||
4BEF6AAC1D35D1C400E73575 /* DPLLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */; };
|
4BEF6AAC1D35D1C400E73575 /* DPLLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */; };
|
||||||
|
4BF437EE209D0F7E008CBD6B /* SegmentParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF437EC209D0F7E008CBD6B /* SegmentParser.cpp */; };
|
||||||
|
4BF437EF209D0F7E008CBD6B /* SegmentParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF437EC209D0F7E008CBD6B /* SegmentParser.cpp */; };
|
||||||
4BFCA1241ECBDCB400AC40C1 /* AllRAMProcessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */; };
|
4BFCA1241ECBDCB400AC40C1 /* AllRAMProcessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */; };
|
||||||
4BFCA1271ECBE33200AC40C1 /* TestMachineZ80.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA1261ECBE33200AC40C1 /* TestMachineZ80.mm */; };
|
4BFCA1271ECBE33200AC40C1 /* TestMachineZ80.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA1261ECBE33200AC40C1 /* TestMachineZ80.mm */; };
|
||||||
4BFCA1291ECBE7A700AC40C1 /* zexall.com in Resources */ = {isa = PBXBuildFile; fileRef = 4BFCA1281ECBE7A700AC40C1 /* zexall.com */; };
|
4BFCA1291ECBE7A700AC40C1 /* zexall.com in Resources */ = {isa = PBXBuildFile; fileRef = 4BFCA1281ECBE7A700AC40C1 /* zexall.com */; };
|
||||||
@ -1296,8 +1300,6 @@
|
|||||||
4BB298EC1B587D8400A49093 /* txsn */ = {isa = PBXFileReference; lastKnownFileType = file; path = txsn; sourceTree = "<group>"; };
|
4BB298EC1B587D8400A49093 /* txsn */ = {isa = PBXFileReference; lastKnownFileType = file; path = txsn; sourceTree = "<group>"; };
|
||||||
4BB298ED1B587D8400A49093 /* tyan */ = {isa = PBXFileReference; lastKnownFileType = file; path = tyan; sourceTree = "<group>"; };
|
4BB298ED1B587D8400A49093 /* tyan */ = {isa = PBXFileReference; lastKnownFileType = file; path = tyan; sourceTree = "<group>"; };
|
||||||
4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CRCTests.mm; sourceTree = "<group>"; };
|
4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CRCTests.mm; sourceTree = "<group>"; };
|
||||||
4BB2CB28208BDDCF00FD192E /* AppleGCR.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AppleGCR.cpp; path = Encodings/AppleGCR.cpp; sourceTree = "<group>"; };
|
|
||||||
4BB2CB29208BDDCF00FD192E /* AppleGCR.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = AppleGCR.hpp; path = Encodings/AppleGCR.hpp; sourceTree = "<group>"; };
|
|
||||||
4BB697C61D4B558F00248BDF /* Factors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Factors.hpp; path = ../../NumberTheory/Factors.hpp; sourceTree = "<group>"; };
|
4BB697C61D4B558F00248BDF /* Factors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Factors.hpp; path = ../../NumberTheory/Factors.hpp; sourceTree = "<group>"; };
|
||||||
4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = "<group>"; };
|
4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = "<group>"; };
|
||||||
4BB697CA1D4B6D3E00248BDF /* TimedEventLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimedEventLoop.hpp; sourceTree = "<group>"; };
|
4BB697CA1D4B6D3E00248BDF /* TimedEventLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimedEventLoop.hpp; sourceTree = "<group>"; };
|
||||||
@ -1370,6 +1372,10 @@
|
|||||||
4BD5F1931D13528900631CD1 /* CSBestEffortUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSBestEffortUpdater.h; path = Updater/CSBestEffortUpdater.h; sourceTree = "<group>"; };
|
4BD5F1931D13528900631CD1 /* CSBestEffortUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSBestEffortUpdater.h; path = Updater/CSBestEffortUpdater.h; sourceTree = "<group>"; };
|
||||||
4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CSBestEffortUpdater.mm; path = Updater/CSBestEffortUpdater.mm; sourceTree = "<group>"; };
|
4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CSBestEffortUpdater.mm; path = Updater/CSBestEffortUpdater.mm; sourceTree = "<group>"; };
|
||||||
4BD61663206B2AC700236112 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/QuickLoadOptions.xib"; sourceTree = SOURCE_ROOT; };
|
4BD61663206B2AC700236112 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/QuickLoadOptions.xib"; sourceTree = SOURCE_ROOT; };
|
||||||
|
4BD67DC9209BE4D600AB2146 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = "<group>"; };
|
||||||
|
4BD67DCA209BE4D600AB2146 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = "<group>"; };
|
||||||
|
4BD67DCE209BF27B00AB2146 /* Encoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Encoder.cpp; sourceTree = "<group>"; };
|
||||||
|
4BD67DCF209BF27B00AB2146 /* Encoder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Encoder.hpp; sourceTree = "<group>"; };
|
||||||
4BD9137D1F311BC5009BCF85 /* i8255.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = i8255.hpp; path = 8255/i8255.hpp; sourceTree = "<group>"; };
|
4BD9137D1F311BC5009BCF85 /* i8255.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = i8255.hpp; path = 8255/i8255.hpp; sourceTree = "<group>"; };
|
||||||
4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMMachine.hpp; sourceTree = "<group>"; };
|
4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMMachine.hpp; sourceTree = "<group>"; };
|
||||||
4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MachineCycleTests.swift; sourceTree = "<group>"; };
|
4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MachineCycleTests.swift; sourceTree = "<group>"; };
|
||||||
@ -1416,6 +1422,9 @@
|
|||||||
4BEF6AA81D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DigitalPhaseLockedLoopBridge.h; sourceTree = "<group>"; };
|
4BEF6AA81D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DigitalPhaseLockedLoopBridge.h; sourceTree = "<group>"; };
|
||||||
4BEF6AA91D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DigitalPhaseLockedLoopBridge.mm; sourceTree = "<group>"; };
|
4BEF6AA91D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DigitalPhaseLockedLoopBridge.mm; sourceTree = "<group>"; };
|
||||||
4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DPLLTests.swift; sourceTree = "<group>"; };
|
4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DPLLTests.swift; sourceTree = "<group>"; };
|
||||||
|
4BF437EC209D0F7E008CBD6B /* SegmentParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SegmentParser.cpp; sourceTree = "<group>"; };
|
||||||
|
4BF437ED209D0F7E008CBD6B /* SegmentParser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SegmentParser.hpp; sourceTree = "<group>"; };
|
||||||
|
4BF437F0209D112F008CBD6B /* Sector.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Sector.hpp; sourceTree = "<group>"; };
|
||||||
4BF4A2D91F534DB300B171F4 /* TargetPlatforms.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TargetPlatforms.hpp; sourceTree = "<group>"; };
|
4BF4A2D91F534DB300B171F4 /* TargetPlatforms.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TargetPlatforms.hpp; sourceTree = "<group>"; };
|
||||||
4BF6606A1F281573002CB053 /* ClockReceiver.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ClockReceiver.hpp; sourceTree = "<group>"; };
|
4BF6606A1F281573002CB053 /* ClockReceiver.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ClockReceiver.hpp; sourceTree = "<group>"; };
|
||||||
4BF8295F1D8F3C87001BAE39 /* CRC.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CRC.hpp; path = ../../NumberTheory/CRC.hpp; sourceTree = "<group>"; };
|
4BF8295F1D8F3C87001BAE39 /* CRC.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CRC.hpp; path = ../../NumberTheory/CRC.hpp; sourceTree = "<group>"; };
|
||||||
@ -2239,6 +2248,7 @@
|
|||||||
4B7A90EA20410A85008514A2 /* Coleco */,
|
4B7A90EA20410A85008514A2 /* Coleco */,
|
||||||
4B8944FB201967B4007DE474 /* Commodore */,
|
4B8944FB201967B4007DE474 /* Commodore */,
|
||||||
4B894507201967B4007DE474 /* Disassembler */,
|
4B894507201967B4007DE474 /* Disassembler */,
|
||||||
|
4BD67DC8209BE4D600AB2146 /* DiskII */,
|
||||||
4B89450F201967B4007DE474 /* MSX */,
|
4B89450F201967B4007DE474 /* MSX */,
|
||||||
4B8944F6201967B4007DE474 /* Oric */,
|
4B8944F6201967B4007DE474 /* Oric */,
|
||||||
4B894504201967B4007DE474 /* ZX8081 */,
|
4B894504201967B4007DE474 /* ZX8081 */,
|
||||||
@ -2675,10 +2685,9 @@
|
|||||||
4BB697CF1D4BA44900248BDF /* Encodings */ = {
|
4BB697CF1D4BA44900248BDF /* Encodings */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4BB2CB28208BDDCF00FD192E /* AppleGCR.cpp */,
|
|
||||||
4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */,
|
4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */,
|
||||||
4BB2CB29208BDDCF00FD192E /* AppleGCR.hpp */,
|
|
||||||
4BB697CD1D4BA44400248BDF /* CommodoreGCR.hpp */,
|
4BB697CD1D4BA44400248BDF /* CommodoreGCR.hpp */,
|
||||||
|
4BD67DCD209BF27B00AB2146 /* AppleGCR */,
|
||||||
4B7136831F78724F008B8ED9 /* MFM */,
|
4B7136831F78724F008B8ED9 /* MFM */,
|
||||||
);
|
);
|
||||||
name = Encodings;
|
name = Encodings;
|
||||||
@ -2993,6 +3002,28 @@
|
|||||||
name = Updater;
|
name = Updater;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
4BD67DC8209BE4D600AB2146 /* DiskII */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
4BD67DC9209BE4D600AB2146 /* StaticAnalyser.hpp */,
|
||||||
|
4BD67DCA209BE4D600AB2146 /* StaticAnalyser.cpp */,
|
||||||
|
);
|
||||||
|
path = DiskII;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
4BD67DCD209BF27B00AB2146 /* AppleGCR */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
4BD67DCE209BF27B00AB2146 /* Encoder.cpp */,
|
||||||
|
4BF437EC209D0F7E008CBD6B /* SegmentParser.cpp */,
|
||||||
|
4BD67DCF209BF27B00AB2146 /* Encoder.hpp */,
|
||||||
|
4BF437F0209D112F008CBD6B /* Sector.hpp */,
|
||||||
|
4BF437ED209D0F7E008CBD6B /* SegmentParser.hpp */,
|
||||||
|
);
|
||||||
|
name = AppleGCR;
|
||||||
|
path = Encodings/AppleGCR;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
4BD9137C1F3115AC009BCF85 /* 8255 */ = {
|
4BD9137C1F3115AC009BCF85 /* 8255 */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -3569,6 +3600,7 @@
|
|||||||
4B055ADA1FAE9B460060FFFF /* 1770.cpp in Sources */,
|
4B055ADA1FAE9B460060FFFF /* 1770.cpp in Sources */,
|
||||||
4B055ADC1FAE9B460060FFFF /* AY38910.cpp in Sources */,
|
4B055ADC1FAE9B460060FFFF /* AY38910.cpp in Sources */,
|
||||||
4B055AD71FAE9B180060FFFF /* Keyboard.cpp in Sources */,
|
4B055AD71FAE9B180060FFFF /* Keyboard.cpp in Sources */,
|
||||||
|
4BD67DCC209BE4D700AB2146 /* StaticAnalyser.cpp in Sources */,
|
||||||
4B055AB61FAE860F0060FFFF /* TapeUEF.cpp in Sources */,
|
4B055AB61FAE860F0060FFFF /* TapeUEF.cpp in Sources */,
|
||||||
4B055A9D1FAE85DA0060FFFF /* D64.cpp in Sources */,
|
4B055A9D1FAE85DA0060FFFF /* D64.cpp in Sources */,
|
||||||
4B055ABB1FAE86170060FFFF /* Oric.cpp in Sources */,
|
4B055ABB1FAE86170060FFFF /* Oric.cpp in Sources */,
|
||||||
@ -3599,6 +3631,7 @@
|
|||||||
4B055AEE1FAE9BBF0060FFFF /* Keyboard.cpp in Sources */,
|
4B055AEE1FAE9BBF0060FFFF /* Keyboard.cpp in Sources */,
|
||||||
4B055AED1FAE9BA20060FFFF /* Z80Storage.cpp in Sources */,
|
4B055AED1FAE9BA20060FFFF /* Z80Storage.cpp in Sources */,
|
||||||
4B1B88BC202E2EC100B67DFF /* MultiKeyboardMachine.cpp in Sources */,
|
4B1B88BC202E2EC100B67DFF /* MultiKeyboardMachine.cpp in Sources */,
|
||||||
|
4BF437EF209D0F7E008CBD6B /* SegmentParser.cpp in Sources */,
|
||||||
4B055AD11FAE9B030060FFFF /* Video.cpp in Sources */,
|
4B055AD11FAE9B030060FFFF /* Video.cpp in Sources */,
|
||||||
4B055AA21FAE85DA0060FFFF /* SSD.cpp in Sources */,
|
4B055AA21FAE85DA0060FFFF /* SSD.cpp in Sources */,
|
||||||
4BEBFB4E2002C4BF000708CC /* MSXDSK.cpp in Sources */,
|
4BEBFB4E2002C4BF000708CC /* MSXDSK.cpp in Sources */,
|
||||||
@ -3639,6 +3672,7 @@
|
|||||||
4B1B88BD202E3D3D00B67DFF /* MultiMachine.cpp in Sources */,
|
4B1B88BD202E3D3D00B67DFF /* MultiMachine.cpp in Sources */,
|
||||||
4B055A971FAE85BB0060FFFF /* ZX8081.cpp in Sources */,
|
4B055A971FAE85BB0060FFFF /* ZX8081.cpp in Sources */,
|
||||||
4B055AAD1FAE85FD0060FFFF /* PCMTrack.cpp in Sources */,
|
4B055AAD1FAE85FD0060FFFF /* PCMTrack.cpp in Sources */,
|
||||||
|
4BD67DD1209BF27B00AB2146 /* Encoder.cpp in Sources */,
|
||||||
4B055AC61FAE9AEE0060FFFF /* TIASound.cpp in Sources */,
|
4B055AC61FAE9AEE0060FFFF /* TIASound.cpp in Sources */,
|
||||||
4B89451F201967B4007DE474 /* Tape.cpp in Sources */,
|
4B89451F201967B4007DE474 /* Tape.cpp in Sources */,
|
||||||
4B055AA81FAE85EF0060FFFF /* Shifter.cpp in Sources */,
|
4B055AA81FAE85EF0060FFFF /* Shifter.cpp in Sources */,
|
||||||
@ -3648,7 +3682,6 @@
|
|||||||
4B894525201967B4007DE474 /* Tape.cpp in Sources */,
|
4B894525201967B4007DE474 /* Tape.cpp in Sources */,
|
||||||
4B055ACD1FAE9B030060FFFF /* Keyboard.cpp in Sources */,
|
4B055ACD1FAE9B030060FFFF /* Keyboard.cpp in Sources */,
|
||||||
4B055AB21FAE860F0060FFFF /* CommodoreTAP.cpp in Sources */,
|
4B055AB21FAE860F0060FFFF /* CommodoreTAP.cpp in Sources */,
|
||||||
4BB2CB2B208BDDCF00FD192E /* AppleGCR.cpp in Sources */,
|
|
||||||
4B055ADF1FAE9B4C0060FFFF /* IRQDelegatePortHandler.cpp in Sources */,
|
4B055ADF1FAE9B4C0060FFFF /* IRQDelegatePortHandler.cpp in Sources */,
|
||||||
4B055AB51FAE860F0060FFFF /* TapePRG.cpp in Sources */,
|
4B055AB51FAE860F0060FFFF /* TapePRG.cpp in Sources */,
|
||||||
4B055AE01FAE9B660060FFFF /* CRT.cpp in Sources */,
|
4B055AE01FAE9B660060FFFF /* CRT.cpp in Sources */,
|
||||||
@ -3708,13 +3741,13 @@
|
|||||||
4B4518A01F75FD1C00926311 /* CPCDSK.cpp in Sources */,
|
4B4518A01F75FD1C00926311 /* CPCDSK.cpp in Sources */,
|
||||||
4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */,
|
4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */,
|
||||||
4B322E041F5A2E3C004EB04C /* Z80Base.cpp in Sources */,
|
4B322E041F5A2E3C004EB04C /* Z80Base.cpp in Sources */,
|
||||||
4BB2CB2A208BDDCF00FD192E /* AppleGCR.cpp in Sources */,
|
|
||||||
4B894530201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
4B894530201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||||
4B4518A31F75FD1C00926311 /* HFE.cpp in Sources */,
|
4B4518A31F75FD1C00926311 /* HFE.cpp in Sources */,
|
||||||
4B1B88BB202E2EC100B67DFF /* MultiKeyboardMachine.cpp in Sources */,
|
4B1B88BB202E2EC100B67DFF /* MultiKeyboardMachine.cpp in Sources */,
|
||||||
4B4518A11F75FD1C00926311 /* D64.cpp in Sources */,
|
4B4518A11F75FD1C00926311 /* D64.cpp in Sources */,
|
||||||
4B1558C01F844ECD006E9A97 /* BitReverse.cpp in Sources */,
|
4B1558C01F844ECD006E9A97 /* BitReverse.cpp in Sources */,
|
||||||
4BCF1FA41DADC3DD0039D2E7 /* Oric.cpp in Sources */,
|
4BCF1FA41DADC3DD0039D2E7 /* Oric.cpp in Sources */,
|
||||||
|
4BD67DCB209BE4D700AB2146 /* StaticAnalyser.cpp in Sources */,
|
||||||
4B9BE400203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */,
|
4B9BE400203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */,
|
||||||
4B894538201967B4007DE474 /* Tape.cpp in Sources */,
|
4B894538201967B4007DE474 /* Tape.cpp in Sources */,
|
||||||
4B54C0CB1F8D92590050900F /* Keyboard.cpp in Sources */,
|
4B54C0CB1F8D92590050900F /* Keyboard.cpp in Sources */,
|
||||||
@ -3766,6 +3799,7 @@
|
|||||||
4B89451C201967B4007DE474 /* Disk.cpp in Sources */,
|
4B89451C201967B4007DE474 /* Disk.cpp in Sources */,
|
||||||
4B302184208A550100773308 /* DiskII.cpp in Sources */,
|
4B302184208A550100773308 /* DiskII.cpp in Sources */,
|
||||||
4BEA52631DF339D7007E74F2 /* SoundGenerator.cpp in Sources */,
|
4BEA52631DF339D7007E74F2 /* SoundGenerator.cpp in Sources */,
|
||||||
|
4BD67DD0209BF27B00AB2146 /* Encoder.cpp in Sources */,
|
||||||
4BAE495920328897004BE78E /* ZX8081OptionsPanel.swift in Sources */,
|
4BAE495920328897004BE78E /* ZX8081OptionsPanel.swift in Sources */,
|
||||||
4B89451A201967B4007DE474 /* ConfidenceSummary.cpp in Sources */,
|
4B89451A201967B4007DE474 /* ConfidenceSummary.cpp in Sources */,
|
||||||
4B54C0C51F8D91D90050900F /* Keyboard.cpp in Sources */,
|
4B54C0C51F8D91D90050900F /* Keyboard.cpp in Sources */,
|
||||||
@ -3840,6 +3874,7 @@
|
|||||||
4B54C0C81F8D91E50050900F /* Keyboard.cpp in Sources */,
|
4B54C0C81F8D91E50050900F /* Keyboard.cpp in Sources */,
|
||||||
4B79A5011FC913C900EEDAD5 /* MSX.cpp in Sources */,
|
4B79A5011FC913C900EEDAD5 /* MSX.cpp in Sources */,
|
||||||
4BEE0A701D72496600532C7B /* PRG.cpp in Sources */,
|
4BEE0A701D72496600532C7B /* PRG.cpp in Sources */,
|
||||||
|
4BF437EE209D0F7E008CBD6B /* SegmentParser.cpp in Sources */,
|
||||||
4B8334861F5DA3780097E338 /* 6502Storage.cpp in Sources */,
|
4B8334861F5DA3780097E338 /* 6502Storage.cpp in Sources */,
|
||||||
4B8FE2271DA1DE2D0090D3CE /* NSBundle+DataResource.m in Sources */,
|
4B8FE2271DA1DE2D0090D3CE /* NSBundle+DataResource.m in Sources */,
|
||||||
4B2A53A01D117D36003C6002 /* CSMachine.mm in Sources */,
|
4B2A53A01D117D36003C6002 /* CSMachine.mm in Sources */,
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
</AdditionalOptions>
|
</AdditionalOptions>
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
enableASanStackUseAfterReturn = "YES"
|
enableASanStackUseAfterReturn = "YES"
|
||||||
|
@ -49,7 +49,7 @@ Gw
|
|||||||
<action selector="cancelCreateMachine:" target="-2" id="lf8-PM-c0m"/>
|
<action selector="cancelCreateMachine:" target="-2" id="lf8-PM-c0m"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="9YM-5x-pc0">
|
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9YM-5x-pc0">
|
||||||
<rect key="frame" x="20" y="14" width="398" height="34"/>
|
<rect key="frame" x="20" y="14" width="398" height="34"/>
|
||||||
<textFieldCell key="cell" allowsUndo="NO" sendsActionOnEndEditing="YES" id="xTm-Oy-oz5">
|
<textFieldCell key="cell" allowsUndo="NO" sendsActionOnEndEditing="YES" id="xTm-Oy-oz5">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
|
@ -22,6 +22,7 @@ SOURCES += glob.glob('../../Analyser/Static/Atari/*.cpp')
|
|||||||
SOURCES += glob.glob('../../Analyser/Static/Coleco/*.cpp')
|
SOURCES += glob.glob('../../Analyser/Static/Coleco/*.cpp')
|
||||||
SOURCES += glob.glob('../../Analyser/Static/Commodore/*.cpp')
|
SOURCES += glob.glob('../../Analyser/Static/Commodore/*.cpp')
|
||||||
SOURCES += glob.glob('../../Analyser/Static/Disassembler/*.cpp')
|
SOURCES += glob.glob('../../Analyser/Static/Disassembler/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Analyser/Static/DiskII/*.cpp')
|
||||||
SOURCES += glob.glob('../../Analyser/Static/MSX/*.cpp')
|
SOURCES += glob.glob('../../Analyser/Static/MSX/*.cpp')
|
||||||
SOURCES += glob.glob('../../Analyser/Static/Oric/*.cpp')
|
SOURCES += glob.glob('../../Analyser/Static/Oric/*.cpp')
|
||||||
SOURCES += glob.glob('../../Analyser/Static/ZX8081/*.cpp')
|
SOURCES += glob.glob('../../Analyser/Static/ZX8081/*.cpp')
|
||||||
@ -78,6 +79,7 @@ SOURCES += glob.glob('../../Storage/Disk/DiskImage/Formats/*.cpp')
|
|||||||
SOURCES += glob.glob('../../Storage/Disk/DiskImage/Formats/Utility/*.cpp')
|
SOURCES += glob.glob('../../Storage/Disk/DiskImage/Formats/Utility/*.cpp')
|
||||||
SOURCES += glob.glob('../../Storage/Disk/DPLL/*.cpp')
|
SOURCES += glob.glob('../../Storage/Disk/DPLL/*.cpp')
|
||||||
SOURCES += glob.glob('../../Storage/Disk/Encodings/*.cpp')
|
SOURCES += glob.glob('../../Storage/Disk/Encodings/*.cpp')
|
||||||
|
SOURCES += glob.glob('../../Storage/Disk/Encodings/AppleGCR/*.cpp')
|
||||||
SOURCES += glob.glob('../../Storage/Disk/Encodings/MFM/*.cpp')
|
SOURCES += glob.glob('../../Storage/Disk/Encodings/MFM/*.cpp')
|
||||||
SOURCES += glob.glob('../../Storage/Disk/Parsers/*.cpp')
|
SOURCES += glob.glob('../../Storage/Disk/Parsers/*.cpp')
|
||||||
SOURCES += glob.glob('../../Storage/Disk/Track/*.cpp')
|
SOURCES += glob.glob('../../Storage/Disk/Track/*.cpp')
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "AppleDSK.hpp"
|
#include "AppleDSK.hpp"
|
||||||
|
|
||||||
#include "../../Track/PCMTrack.hpp"
|
#include "../../Track/PCMTrack.hpp"
|
||||||
#include "../../Encodings/AppleGCR.hpp"
|
#include "../../Encodings/AppleGCR/Encoder.hpp"
|
||||||
|
|
||||||
using namespace Storage::Disk;
|
using namespace Storage::Disk;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "NIB.hpp"
|
#include "NIB.hpp"
|
||||||
|
|
||||||
#include "../../Track/PCMTrack.hpp"
|
#include "../../Track/PCMTrack.hpp"
|
||||||
#include "../../Encodings/AppleGCR.hpp"
|
#include "../../Encodings/AppleGCR/Encoder.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
//
|
|
||||||
// AppleGCR.hpp
|
|
||||||
// Clock Signal
|
|
||||||
//
|
|
||||||
// Created by Thomas Harte on 21/04/2018.
|
|
||||||
// Copyright © 2018 Thomas Harte. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef AppleGCR_hpp
|
|
||||||
#define AppleGCR_hpp
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include "../../Disk/Track/PCMSegment.hpp"
|
|
||||||
|
|
||||||
namespace Storage {
|
|
||||||
namespace Encodings {
|
|
||||||
|
|
||||||
namespace AppleGCR {
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@returns the eight-bit 13-sector GCR encoding for the low five bits of @c value.
|
|
||||||
*/
|
|
||||||
// unsigned int five_and_three_encoding_for_value(int value);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@returns the eight-bit 16-sector GCR encoding for the low six bits of @c value.
|
|
||||||
*/
|
|
||||||
// unsigned int six_and_two_encoding_for_value(int value);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
A block is defined to be five source bytes, which encodes to eight GCR bytes.
|
|
||||||
*/
|
|
||||||
// void encode_five_and_three_block(uint8_t *destination, uint8_t *source);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
A block is defined to be three source bytes, which encodes to four GCR bytes.
|
|
||||||
*/
|
|
||||||
// void encode_six_and_two_block(uint8_t *destination, uint8_t *source);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@returns the four bit nibble for the five-bit GCR @c quintet if a valid GCR value; INT_MAX otherwise.
|
|
||||||
*/
|
|
||||||
// unsigned int decoding_from_quintet(unsigned int quintet);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@returns the byte composed by splitting the dectet into two qintets, decoding each and composing the resulting nibbles.
|
|
||||||
*/
|
|
||||||
// unsigned int decoding_from_dectet(unsigned int dectet);
|
|
||||||
|
|
||||||
/// Describes the standard three-byte prologue that begins a header.
|
|
||||||
const uint8_t header_prologue[3] = {0xd5, 0xaa, 0x96};
|
|
||||||
/// Describes the standard three-byte prologue that begins a data section.
|
|
||||||
const uint8_t data_prologue[3] = {0xd5, 0xaa, 0xad};
|
|
||||||
/// Describes the epilogue that ends both data sections and headers.
|
|
||||||
const uint8_t epilogue[3] = {0xde, 0xaa, 0xeb};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Produces the Apple-standard '4 and 4' per-sector header. This is the same
|
|
||||||
for both the 13- and 16-sector formats, and is 112 bits long.
|
|
||||||
*/
|
|
||||||
Storage::Disk::PCMSegment header(uint8_t volume, uint8_t track, uint8_t sector);
|
|
||||||
|
|
||||||
Storage::Disk::PCMSegment six_and_two_data(const uint8_t *source);
|
|
||||||
Storage::Disk::PCMSegment six_and_two_sync(int length);
|
|
||||||
|
|
||||||
Storage::Disk::PCMSegment five_and_three_data(const uint8_t *source);
|
|
||||||
Storage::Disk::PCMSegment five_and_three_sync(int length);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* AppleGCR_hpp */
|
|
@ -6,11 +6,11 @@
|
|||||||
// Copyright © 2018 Thomas Harte. All rights reserved.
|
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "AppleGCR.hpp"
|
#include "Encoder.hpp"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const unsigned int five_and_three_mapping[] = {
|
const uint8_t five_and_three_mapping[] = {
|
||||||
0xab, 0xad, 0xae, 0xaf, 0xb5, 0xb6, 0xb7, 0xba,
|
0xab, 0xad, 0xae, 0xaf, 0xb5, 0xb6, 0xb7, 0xba,
|
||||||
0xbb, 0xbd, 0xbe, 0xbf, 0xd6, 0xd7, 0xda, 0xdb,
|
0xbb, 0xbd, 0xbe, 0xbf, 0xd6, 0xd7, 0xda, 0xdb,
|
||||||
0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xed, 0xee, 0xef,
|
0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xed, 0xee, 0xef,
|
||||||
@ -53,26 +53,6 @@ Storage::Disk::PCMSegment sync(int length, int bit_size) {
|
|||||||
|
|
||||||
using namespace Storage::Encodings;
|
using namespace Storage::Encodings;
|
||||||
|
|
||||||
|
|
||||||
/*void AppleGCR::encode_five_and_three_block(uint8_t *destination, uint8_t *source) {
|
|
||||||
destination[0] = static_cast<uint8_t>(five_and_three_encoding_for_value( source[0] >> 3 ));
|
|
||||||
destination[1] = static_cast<uint8_t>(five_and_three_encoding_for_value( (source[0] << 2) | (source[1] >> 6) ));
|
|
||||||
destination[2] = static_cast<uint8_t>(five_and_three_encoding_for_value( source[1] >> 1 ));
|
|
||||||
destination[3] = static_cast<uint8_t>(five_and_three_encoding_for_value( (source[1] << 4) | (source[2] >> 4) ));
|
|
||||||
destination[4] = static_cast<uint8_t>(five_and_three_encoding_for_value( (source[2] << 1) | (source[3] >> 7) ));
|
|
||||||
destination[5] = static_cast<uint8_t>(five_and_three_encoding_for_value( source[3] >> 2 ));
|
|
||||||
destination[6] = static_cast<uint8_t>(five_and_three_encoding_for_value( (source[3] << 3) | (source[4] >> 5) ));
|
|
||||||
destination[7] = static_cast<uint8_t>(five_and_three_encoding_for_value( source[4] ));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
/*void AppleGCR::encode_six_and_two_block(uint8_t *destination, uint8_t *source) {
|
|
||||||
destination[0] = static_cast<uint8_t>(six_and_two_encoding_for_value( source[0] >> 2 ));
|
|
||||||
destination[1] = static_cast<uint8_t>(six_and_two_encoding_for_value( (source[0] << 4) | (source[1] >> 4) ));
|
|
||||||
destination[2] = static_cast<uint8_t>(six_and_two_encoding_for_value( (source[1] << 2) | (source[2] >> 6) ));
|
|
||||||
destination[3] = static_cast<uint8_t>(six_and_two_encoding_for_value( source[2] ));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
Storage::Disk::PCMSegment AppleGCR::six_and_two_sync(int length) {
|
Storage::Disk::PCMSegment AppleGCR::six_and_two_sync(int length) {
|
||||||
return sync(length, 10);
|
return sync(length, 10);
|
||||||
}
|
}
|
||||||
@ -132,6 +112,11 @@ Storage::Disk::PCMSegment AppleGCR::five_and_three_data(const uint8_t *source) {
|
|||||||
// destination_pointer += 8;
|
// destination_pointer += 8;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// Map five-bit values up to full bytes.
|
||||||
|
for(std::size_t c = 0; c < 410; ++c) {
|
||||||
|
segment.data[3 + c] = five_and_three_mapping[segment.data[3 + c]];
|
||||||
|
}
|
||||||
|
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,24 +139,24 @@ Storage::Disk::PCMSegment AppleGCR::six_and_two_data(const uint8_t *source) {
|
|||||||
// and combined copies of the bottom two bits of the sector
|
// and combined copies of the bottom two bits of the sector
|
||||||
// contents; the 256 bytes afterwards are the remaining
|
// contents; the 256 bytes afterwards are the remaining
|
||||||
// six bits.
|
// six bits.
|
||||||
const uint8_t bit_shuffle[] = {0, 2, 1, 3};
|
const uint8_t bit_reverse[] = {0, 2, 1, 3};
|
||||||
for(std::size_t c = 0; c < 84; ++c) {
|
for(std::size_t c = 0; c < 84; ++c) {
|
||||||
segment.data[3 + c] =
|
segment.data[3 + c] =
|
||||||
static_cast<uint8_t>(
|
static_cast<uint8_t>(
|
||||||
bit_shuffle[source[c]&3] |
|
bit_reverse[source[c]&3] |
|
||||||
(bit_shuffle[source[c + 86]&3] << 2) |
|
(bit_reverse[source[c + 86]&3] << 2) |
|
||||||
(bit_shuffle[source[c + 172]&3] << 4)
|
(bit_reverse[source[c + 172]&3] << 4)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
segment.data[87] =
|
segment.data[87] =
|
||||||
static_cast<uint8_t>(
|
static_cast<uint8_t>(
|
||||||
(bit_shuffle[source[84]&3] << 0) |
|
(bit_reverse[source[84]&3] << 0) |
|
||||||
(bit_shuffle[source[170]&3] << 2)
|
(bit_reverse[source[170]&3] << 2)
|
||||||
);
|
);
|
||||||
segment.data[88] =
|
segment.data[88] =
|
||||||
static_cast<uint8_t>(
|
static_cast<uint8_t>(
|
||||||
(bit_shuffle[source[85]&3] << 0) |
|
(bit_reverse[source[85]&3] << 0) |
|
||||||
(bit_shuffle[source[171]&3] << 2)
|
(bit_reverse[source[171]&3] << 2)
|
||||||
);
|
);
|
||||||
|
|
||||||
for(std::size_t c = 0; c < 256; ++c) {
|
for(std::size_t c = 0; c < 256; ++c) {
|
60
Storage/Disk/Encodings/AppleGCR/Encoder.hpp
Normal file
60
Storage/Disk/Encodings/AppleGCR/Encoder.hpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// AppleGCR.hpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 21/04/2018.
|
||||||
|
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AppleGCR_hpp
|
||||||
|
#define AppleGCR_hpp
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include "../../../Disk/Track/PCMSegment.hpp"
|
||||||
|
|
||||||
|
namespace Storage {
|
||||||
|
namespace Encodings {
|
||||||
|
namespace AppleGCR {
|
||||||
|
|
||||||
|
/// Describes the standard three-byte prologue that begins a header.
|
||||||
|
const uint8_t header_prologue[3] = {0xd5, 0xaa, 0x96};
|
||||||
|
/// Describes the standard three-byte prologue that begins a data section.
|
||||||
|
const uint8_t data_prologue[3] = {0xd5, 0xaa, 0xad};
|
||||||
|
/// Describes the epilogue that ends both data sections and headers.
|
||||||
|
const uint8_t epilogue[3] = {0xde, 0xaa, 0xeb};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Produces the Apple-standard four-and-four per-sector header. This is the same
|
||||||
|
for both the 13- and 16-sector formats, and is 112 bits long.
|
||||||
|
*/
|
||||||
|
Storage::Disk::PCMSegment header(uint8_t volume, uint8_t track, uint8_t sector);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Produces the data section of a six-and-two format sector; the segment returned
|
||||||
|
will be 2,792 bits long, encoding the first 256 bytes from @c source.
|
||||||
|
*/
|
||||||
|
Storage::Disk::PCMSegment six_and_two_data(const uint8_t *source);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Produces @c length sync six-and-two format sync bytes. The segment returned
|
||||||
|
is @c 10*length bits long.
|
||||||
|
*/
|
||||||
|
Storage::Disk::PCMSegment six_and_two_sync(int length);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Produces the data section of a five-and-three format sector; the segment returned
|
||||||
|
will be 3,336 bits long, encoding the first 256 bytes from @c source.
|
||||||
|
*/
|
||||||
|
Storage::Disk::PCMSegment five_and_three_data(const uint8_t *source);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Produces @c length sync five-and-three format sync bytes. The segment returned
|
||||||
|
is @c 9*length bits long.
|
||||||
|
*/
|
||||||
|
Storage::Disk::PCMSegment five_and_three_sync(int length);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* AppleGCR_hpp */
|
63
Storage/Disk/Encodings/AppleGCR/Sector.hpp
Normal file
63
Storage/Disk/Encodings/AppleGCR/Sector.hpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// Sector.hpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 04/05/2018.
|
||||||
|
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Sector_h
|
||||||
|
#define Sector_h
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Storage {
|
||||||
|
namespace Encodings {
|
||||||
|
namespace AppleGCR {
|
||||||
|
|
||||||
|
struct Sector {
|
||||||
|
/*!
|
||||||
|
Describes the location of a sector, implementing < to allow for use as a set key.
|
||||||
|
*/
|
||||||
|
struct Address {
|
||||||
|
uint_fast8_t volume = 0, track = 0, sector = 0;
|
||||||
|
|
||||||
|
bool operator < (const Address &rhs) const {
|
||||||
|
return ((volume << 16) | (track << 8) | sector) < ((rhs.volume << 16) | (rhs.track << 8) | rhs.sector);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Address address;
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
|
||||||
|
bool has_data_checksum_error = false;
|
||||||
|
bool has_header_checksum_error = false;
|
||||||
|
|
||||||
|
enum class Encoding {
|
||||||
|
FiveAndThree, SixAndTwo
|
||||||
|
};
|
||||||
|
Encoding encoding = Encoding::SixAndTwo;
|
||||||
|
|
||||||
|
Sector() {}
|
||||||
|
|
||||||
|
Sector(Sector &&rhs) :
|
||||||
|
address(rhs.address),
|
||||||
|
data(std::move(rhs.data)),
|
||||||
|
has_data_checksum_error(rhs.has_data_checksum_error),
|
||||||
|
has_header_checksum_error(rhs.has_header_checksum_error),
|
||||||
|
encoding(rhs.encoding) {}
|
||||||
|
|
||||||
|
Sector(const Sector &rhs) :
|
||||||
|
address(rhs.address),
|
||||||
|
data(rhs.data),
|
||||||
|
has_data_checksum_error(rhs.has_data_checksum_error),
|
||||||
|
has_header_checksum_error(rhs.has_header_checksum_error),
|
||||||
|
encoding(rhs.encoding) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Sector_h */
|
172
Storage/Disk/Encodings/AppleGCR/SegmentParser.cpp
Normal file
172
Storage/Disk/Encodings/AppleGCR/SegmentParser.cpp
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
//
|
||||||
|
// SegmentParser.cpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 04/05/2018.
|
||||||
|
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "SegmentParser.hpp"
|
||||||
|
|
||||||
|
#include "Encoder.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const uint8_t six_and_two_unmapping[] = {
|
||||||
|
0x00, 0x01, 0xff, 0xff,
|
||||||
|
0x02, 0x03, 0xff, 0x04, 0x05, 0x06, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0x07, 0x08, 0xff, 0xff,
|
||||||
|
0xff, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0xff, 0xff,
|
||||||
|
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0xff, 0x14,
|
||||||
|
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0x1b, 0xff, 0x1c, 0x1d, 0x1e, 0xff, 0xff,
|
||||||
|
0xff, 0x1f, 0xff, 0xff, 0x20, 0x21, 0xff, 0x22,
|
||||||
|
0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0x29, 0x2a, 0x2b, 0xff, 0x2c,
|
||||||
|
0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0xff, 0xff,
|
||||||
|
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0xff, 0x39,
|
||||||
|
0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0xff, 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace Storage::Encodings::AppleGCR;
|
||||||
|
|
||||||
|
std::map<std::size_t, Sector> Storage::Encodings::AppleGCR::sectors_from_segment(const Disk::PCMSegment &&segment) {
|
||||||
|
std::map<std::size_t, Sector> result;
|
||||||
|
|
||||||
|
uint_fast8_t shift_register = 0;
|
||||||
|
|
||||||
|
const std::size_t scanning_sentinel = std::numeric_limits<std::size_t>::max();
|
||||||
|
std::unique_ptr<Sector> new_sector;
|
||||||
|
std::size_t sector_location = 0;
|
||||||
|
std::size_t pointer = scanning_sentinel;
|
||||||
|
std::array<uint_fast8_t, 8> header{{0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
|
std::array<uint_fast8_t, 3> scanner;
|
||||||
|
|
||||||
|
for(unsigned int bit = 0; bit < segment.number_of_bits; ++bit) {
|
||||||
|
// Apple GCR parsing: bytes always have the top bit set.
|
||||||
|
shift_register = static_cast<uint_fast8_t>((shift_register << 1) | segment.bit(bit));
|
||||||
|
if(!(shift_register&0x80)) continue;
|
||||||
|
|
||||||
|
// Grab the byte.
|
||||||
|
const uint_fast8_t value = shift_register;
|
||||||
|
shift_register = 0;
|
||||||
|
|
||||||
|
if(pointer == scanning_sentinel) {
|
||||||
|
scanner[0] = scanner[1];
|
||||||
|
scanner[1] = scanner[2];
|
||||||
|
scanner[2] = value;
|
||||||
|
|
||||||
|
if(
|
||||||
|
scanner[0] == header_prologue[0] &&
|
||||||
|
scanner[1] == header_prologue[1] &&
|
||||||
|
(
|
||||||
|
scanner[2] == header_prologue[2] ||
|
||||||
|
scanner[2] == data_prologue[2]
|
||||||
|
)) {
|
||||||
|
pointer = 0;
|
||||||
|
|
||||||
|
// If this is the start of a data section, and at least
|
||||||
|
// one header has been witnessed, start a sector.
|
||||||
|
if(scanner[2] == data_prologue[2]) {
|
||||||
|
new_sector.reset(new Sector);
|
||||||
|
new_sector->data.reserve(412);
|
||||||
|
} else {
|
||||||
|
sector_location = static_cast<std::size_t>(bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(new_sector) {
|
||||||
|
// If this is an epilogue, make sense of this whole sector;
|
||||||
|
// otherwise just keep the byte for later.
|
||||||
|
if(value == epilogue[1]) {
|
||||||
|
std::unique_ptr<Sector> sector = std::move(new_sector);
|
||||||
|
new_sector.reset();
|
||||||
|
pointer = scanning_sentinel;
|
||||||
|
|
||||||
|
// Check for an expected size; the first byte of the epilogue has been stored, so
|
||||||
|
// these numbers are one bigger than usual.
|
||||||
|
if(sector->data.size() != 412 && sector->data.size() != 344) continue;
|
||||||
|
sector->data.resize(sector->data.size() - 1);
|
||||||
|
|
||||||
|
// Check for apparent four and four encoding.
|
||||||
|
uint_fast8_t header_mask = 0xff;
|
||||||
|
for(auto c : header) header_mask &= c;
|
||||||
|
header_mask &= 0xaa;
|
||||||
|
if(header_mask != 0xaa) continue;
|
||||||
|
|
||||||
|
sector->address.volume = ((header[0] << 1) | 1) & header[1];
|
||||||
|
sector->address.track = ((header[2] << 1) | 1) & header[3];
|
||||||
|
sector->address.sector = ((header[4] << 1) | 1) & header[5];
|
||||||
|
|
||||||
|
// Check the header checksum.
|
||||||
|
uint_fast8_t checksum = ((header[6] << 1) | 1) & header[7];
|
||||||
|
if(checksum != (sector->address.volume^sector->address.track^sector->address.sector)) continue;
|
||||||
|
|
||||||
|
if(sector->data.size() == 343) {
|
||||||
|
// Unmap the sector contents as 6 and 2 data.
|
||||||
|
bool out_of_bounds = false;
|
||||||
|
for(auto &c : sector->data) {
|
||||||
|
if(c < 0x96 || six_and_two_unmapping[c - 0x96] == 0xff) {
|
||||||
|
out_of_bounds = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = six_and_two_unmapping[c - 0x96];
|
||||||
|
}
|
||||||
|
if(out_of_bounds) continue;
|
||||||
|
|
||||||
|
// Undo the XOR step on sector contents and check that checksum.
|
||||||
|
for(std::size_t c = 1; c < sector->data.size(); ++c) {
|
||||||
|
sector->data[c] ^= sector->data[c-1];
|
||||||
|
}
|
||||||
|
if(sector->data.back()) continue;
|
||||||
|
|
||||||
|
// Having checked the checksum, remove it.
|
||||||
|
sector->data.resize(sector->data.size() - 1);
|
||||||
|
|
||||||
|
// Undo the 6 and 2 mapping.
|
||||||
|
const uint8_t bit_reverse[] = {0, 2, 1, 3};
|
||||||
|
#define unmap(byte, nibble, shift) \
|
||||||
|
sector->data[86 + byte] = static_cast<uint8_t>(\
|
||||||
|
(sector->data[86 + byte] << 2) | bit_reverse[(sector->data[nibble] >> shift)&3]);
|
||||||
|
|
||||||
|
for(std::size_t c = 0; c < 84; ++c) {
|
||||||
|
unmap(c, c, 0);
|
||||||
|
unmap(c+86, c, 2);
|
||||||
|
unmap(c+172, c, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
unmap(84, 84, 0);
|
||||||
|
unmap(170, 84, 2);
|
||||||
|
unmap(85, 85, 0);
|
||||||
|
unmap(171, 85, 2);
|
||||||
|
|
||||||
|
#undef unmap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throw away the collection of two-bit chunks.
|
||||||
|
sector->data.erase(sector->data.begin(), sector->data.end() - 256);
|
||||||
|
|
||||||
|
// Add this sector to the map.
|
||||||
|
result.insert(std::make_pair(sector_location, std::move(*sector)));
|
||||||
|
} else {
|
||||||
|
new_sector->data.push_back(value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Just capture the header in place; it'll be decoded
|
||||||
|
// once a whole sector has been read.
|
||||||
|
header[pointer] = value;
|
||||||
|
++pointer;
|
||||||
|
if(pointer == 8) {
|
||||||
|
pointer = scanning_sentinel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
30
Storage/Disk/Encodings/AppleGCR/SegmentParser.hpp
Normal file
30
Storage/Disk/Encodings/AppleGCR/SegmentParser.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// SegmentParser.hpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 04/05/2018.
|
||||||
|
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef TrackParser_hpp
|
||||||
|
#define TrackParser_hpp
|
||||||
|
|
||||||
|
#include "Sector.hpp"
|
||||||
|
#include "../../Track/PCMSegment.hpp"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace Storage {
|
||||||
|
namespace Encodings {
|
||||||
|
namespace AppleGCR {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Scans @c segment for all included sectors, returning a set that maps from location within
|
||||||
|
the segment (counted in bits from the beginning) to sector.
|
||||||
|
*/
|
||||||
|
std::map<std::size_t, Sector> sectors_from_segment(const Disk::PCMSegment &&segment);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* TrackParser_hpp */
|
@ -33,7 +33,8 @@ struct Sector {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Address address;
|
Address address;
|
||||||
uint8_t size = 0;
|
uint8_t size = 0; // Size is stored in ordinary MFM form — the number of bytes included in this sector
|
||||||
|
// is 2^(7 + size), or 128 << size.
|
||||||
|
|
||||||
// Multiple samplings of the underlying data are accepted, to allow weak and fuzzy data to be communicated.
|
// Multiple samplings of the underlying data are accepted, to allow weak and fuzzy data to be communicated.
|
||||||
std::vector<std::vector<uint8_t>> samples;
|
std::vector<std::vector<uint8_t>> samples;
|
||||||
|
@ -19,7 +19,8 @@ namespace MFM {
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
Scans @c segment for all included sectors, returning a set that maps from location within
|
Scans @c segment for all included sectors, returning a set that maps from location within
|
||||||
the segment (counted in bits from the beginning) to sector.
|
the segment (counted in bits from the beginning and pointing to the location the disk
|
||||||
|
had reached upon detection of the ID mark) to sector.
|
||||||
*/
|
*/
|
||||||
std::map<std::size_t, Sector> sectors_from_segment(const Disk::PCMSegment &&segment, bool is_double_density);
|
std::map<std::size_t, Sector> sectors_from_segment(const Disk::PCMSegment &&segment, bool is_double_density);
|
||||||
|
|
||||||
|
@ -17,6 +17,30 @@ namespace Storage {
|
|||||||
namespace Encodings {
|
namespace Encodings {
|
||||||
namespace MFM {
|
namespace MFM {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
The MFM shifter parses a stream of bits as input in order to produce
|
||||||
|
a stream of MFM tokens as output. So e.g. it is suitable for use in parsing
|
||||||
|
the output of a PLL windowing of disk events.
|
||||||
|
|
||||||
|
It supports both FM and MFM parsing; see @c set_is_double_density.
|
||||||
|
|
||||||
|
It will ordinarily honour sync patterns; that should be turned off when within
|
||||||
|
a sector because false syncs can occur. See @c set_should_obey_syncs.
|
||||||
|
|
||||||
|
Bits should be fed in with @c add_input_bit.
|
||||||
|
|
||||||
|
The current output token can be read with @c get_token. It will usually be None but
|
||||||
|
may indicate that an index, ID, data or deleted data mark was found, that an
|
||||||
|
MFM sync mark was found, or that an ordinary byte has been decoded.
|
||||||
|
|
||||||
|
It will properly reset and/or seed a CRC generator based on the data and ID marks,
|
||||||
|
and feed it with incoming bytes. You can access that CRC generator to query its
|
||||||
|
value via @c get_crc_generator(). An easy way to check whether the disk contained
|
||||||
|
a proper CRC is to read bytes until you've just read whatever CRC was on the disk,
|
||||||
|
then check that the generator has a value of zero.
|
||||||
|
|
||||||
|
A specific instance of the CRC generator can be supplied at construction if preferred.
|
||||||
|
*/
|
||||||
class Shifter {
|
class Shifter {
|
||||||
public:
|
public:
|
||||||
Shifter();
|
Shifter();
|
||||||
|
@ -23,10 +23,11 @@ enum Type: IntType {
|
|||||||
BBCModelB = 1 << 8,
|
BBCModelB = 1 << 8,
|
||||||
ColecoVision = 1 << 9,
|
ColecoVision = 1 << 9,
|
||||||
Commodore = 1 << 10,
|
Commodore = 1 << 10,
|
||||||
MSX = 1 << 11,
|
DiskII = 1 << 11,
|
||||||
Oric = 1 << 12,
|
MSX = 1 << 12,
|
||||||
ZX80 = 1 << 13,
|
Oric = 1 << 13,
|
||||||
ZX81 = 1 << 14,
|
ZX80 = 1 << 14,
|
||||||
|
ZX81 = 1 << 15,
|
||||||
|
|
||||||
Acorn = AcornAtom | AcornElectron | BBCMaster | BBCModelA | BBCModelB,
|
Acorn = AcornAtom | AcornElectron | BBCMaster | BBCModelA | BBCModelB,
|
||||||
ZX8081 = ZX80 | ZX81,
|
ZX8081 = ZX80 | ZX81,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user