From 881feb1bd3b7c9d307d713e041f40859e5ca511f Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 2 Jun 2019 13:39:25 -0400 Subject: [PATCH] Adds preliminary parsing of the Disk Copy 4.2 format. --- Analyser/Static/Macintosh/StaticAnalyser.cpp | 25 ++ Analyser/Static/Macintosh/StaticAnalyser.hpp | 27 ++ Analyser/Static/StaticAnalyser.cpp | 72 ++--- Machines/Apple/Macintosh/Macintosh.cpp | 2 +- Machines/Utility/MachineForTarget.cpp | 4 +- .../Clock Signal.xcodeproj/project.pbxproj | 48 ++- OSBindings/Mac/Clock Signal/Info.plist | 281 ++++++++++-------- .../Implementation/68000Implementation.hpp | 2 +- Storage/Disk/DiskImage/Formats/DiskCopy42.cpp | 120 ++++++++ Storage/Disk/DiskImage/Formats/DiskCopy42.hpp | 58 ++++ Storage/Disk/Drive.hpp | 3 + Storage/TargetPlatforms.hpp | 9 +- 12 files changed, 466 insertions(+), 185 deletions(-) create mode 100644 Analyser/Static/Macintosh/StaticAnalyser.cpp create mode 100644 Analyser/Static/Macintosh/StaticAnalyser.hpp create mode 100644 Storage/Disk/DiskImage/Formats/DiskCopy42.cpp create mode 100644 Storage/Disk/DiskImage/Formats/DiskCopy42.hpp diff --git a/Analyser/Static/Macintosh/StaticAnalyser.cpp b/Analyser/Static/Macintosh/StaticAnalyser.cpp new file mode 100644 index 000000000..d4f12d7a4 --- /dev/null +++ b/Analyser/Static/Macintosh/StaticAnalyser.cpp @@ -0,0 +1,25 @@ +// +// StaticAnalyser.cpp +// Clock Signal +// +// Created by Thomas Harte on 02/06/2019. +// Copyright © 2019 Thomas Harte. All rights reserved. +// + +#include "StaticAnalyser.hpp" + +Analyser::Static::TargetList Analyser::Static::Macintosh::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) { + // This analyser can comprehend disks only. + if(media.disks.empty()) return {}; + + // If there is at least one disk, wave it through. + Analyser::Static::TargetList targets; + + using Target = Analyser::Static::Target; + auto *target = new Target; + target->machine = Analyser::Machine::Macintosh; + target->media = media; + targets.push_back(std::unique_ptr(target)); + + return targets; +} diff --git a/Analyser/Static/Macintosh/StaticAnalyser.hpp b/Analyser/Static/Macintosh/StaticAnalyser.hpp new file mode 100644 index 000000000..8b40c0120 --- /dev/null +++ b/Analyser/Static/Macintosh/StaticAnalyser.hpp @@ -0,0 +1,27 @@ +// +// StaticAnalyser.hpp +// Clock Signal +// +// Created by Thomas Harte on 02/06/2019. +// Copyright © 2019 Thomas Harte. All rights reserved. +// + +#ifndef Analyser_Static_Macintosh_StaticAnalyser_hpp +#define Analyser_Static_Macintosh_StaticAnalyser_hpp + +#include "../StaticAnalyser.hpp" +#include "../../../Storage/TargetPlatforms.hpp" +#include + +namespace Analyser { +namespace Static { +namespace Macintosh { + +TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms); + +} +} +} + + +#endif /* Analyser_Static_Macintosh_StaticAnalyser_hpp */ diff --git a/Analyser/Static/StaticAnalyser.cpp b/Analyser/Static/StaticAnalyser.cpp index a65e9582b..163086325 100644 --- a/Analyser/Static/StaticAnalyser.cpp +++ b/Analyser/Static/StaticAnalyser.cpp @@ -21,6 +21,7 @@ #include "Coleco/StaticAnalyser.hpp" #include "Commodore/StaticAnalyser.hpp" #include "DiskII/StaticAnalyser.hpp" +#include "Macintosh/StaticAnalyser.hpp" #include "MSX/StaticAnalyser.hpp" #include "Oric/StaticAnalyser.hpp" #include "Sega/StaticAnalyser.hpp" @@ -35,6 +36,7 @@ #include "../../Storage/Disk/DiskImage/Formats/AppleDSK.hpp" #include "../../Storage/Disk/DiskImage/Formats/CPCDSK.hpp" #include "../../Storage/Disk/DiskImage/Formats/D64.hpp" +#include "../../Storage/Disk/DiskImage/Formats/DiskCopy42.hpp" #include "../../Storage/Disk/DiskImage/Formats/G64.hpp" #include "../../Storage/Disk/DiskImage/Formats/DMK.hpp" #include "../../Storage/Disk/DiskImage/Formats/HFE.hpp" @@ -85,34 +87,35 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform:: TryInsert(list, class, platforms) \ } - Format("80", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 80 - Format("81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 81 - Format("a26", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // A26 - Format("adf", result.disks, Disk::DiskImageHolder, TargetPlatform::Acorn) // ADF - Format("bin", result.cartridges, Cartridge::BinaryDump, TargetPlatform::AllCartridge) // BIN - Format("cas", result.tapes, Tape::CAS, TargetPlatform::MSX) // CAS - Format("cdt", result.tapes, Tape::TZX, TargetPlatform::AmstradCPC) // CDT - Format("col", result.cartridges, Cartridge::BinaryDump, TargetPlatform::ColecoVision) // COL - Format("csw", result.tapes, Tape::CSW, TargetPlatform::AllTape) // CSW - Format("d64", result.disks, Disk::DiskImageHolder, TargetPlatform::Commodore) // D64 - Format("dmk", result.disks, Disk::DiskImageHolder, TargetPlatform::MSX) // DMK - Format("do", result.disks, Disk::DiskImageHolder, TargetPlatform::DiskII) // DO - Format("dsd", result.disks, Disk::DiskImageHolder, TargetPlatform::Acorn) // DSD - Format("dsk", result.disks, Disk::DiskImageHolder, TargetPlatform::AmstradCPC) // DSK (Amstrad CPC) - Format("dsk", result.disks, Disk::DiskImageHolder, TargetPlatform::DiskII) // DSK (Apple) - Format("dsk", result.disks, Disk::DiskImageHolder, TargetPlatform::MSX) // DSK (MSX) - Format("dsk", result.disks, Disk::DiskImageHolder, TargetPlatform::Oric) // DSK (Oric) - Format("g64", result.disks, Disk::DiskImageHolder, TargetPlatform::Commodore) // G64 + Format("80", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 80 + Format("81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 81 + Format("a26", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // A26 + Format("adf", result.disks, Disk::DiskImageHolder, TargetPlatform::Acorn) // ADF + Format("bin", result.cartridges, Cartridge::BinaryDump, TargetPlatform::AllCartridge) // BIN + Format("cas", result.tapes, Tape::CAS, TargetPlatform::MSX) // CAS + Format("cdt", result.tapes, Tape::TZX, TargetPlatform::AmstradCPC) // CDT + Format("col", result.cartridges, Cartridge::BinaryDump, TargetPlatform::ColecoVision) // COL + Format("csw", result.tapes, Tape::CSW, TargetPlatform::AllTape) // CSW + Format("d64", result.disks, Disk::DiskImageHolder, TargetPlatform::Commodore) // D64 + Format("dmk", result.disks, Disk::DiskImageHolder, TargetPlatform::MSX) // DMK + Format("do", result.disks, Disk::DiskImageHolder, TargetPlatform::DiskII) // DO + Format("dsd", result.disks, Disk::DiskImageHolder, TargetPlatform::Acorn) // DSD + Format("dsk", result.disks, Disk::DiskImageHolder, TargetPlatform::AmstradCPC) // DSK (Amstrad CPC) + Format("dsk", result.disks, Disk::DiskImageHolder, TargetPlatform::DiskII) // DSK (Apple) + Format("dsk", result.disks, Disk::DiskImageHolder, TargetPlatform::MSX) // DSK (MSX) + Format("dsk", result.disks, Disk::DiskImageHolder, TargetPlatform::Oric) // DSK (Oric) + Format("g64", result.disks, Disk::DiskImageHolder, TargetPlatform::Commodore) // G64 Format( "hfe", result.disks, Disk::DiskImageHolder, TargetPlatform::Acorn | TargetPlatform::AmstradCPC | TargetPlatform::Commodore | TargetPlatform::Oric) // HFE (TODO: switch to AllDisk once the MSX stops being so greedy) - Format("nib", result.disks, Disk::DiskImageHolder, TargetPlatform::DiskII) // NIB - Format("o", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // O - Format("p", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P - Format("po", result.disks, Disk::DiskImageHolder, TargetPlatform::DiskII) // PO - Format("p81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P81 + Format("img", result.disks, Disk::DiskImageHolder, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2) + Format("nib", result.disks, Disk::DiskImageHolder, TargetPlatform::DiskII) // NIB + Format("o", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // O + Format("p", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P + Format("po", result.disks, Disk::DiskImageHolder, TargetPlatform::DiskII) // PO + Format("p81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P81 // PRG if(extension == "prg") { @@ -129,16 +132,16 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform:: Format( "rom", result.cartridges, Cartridge::BinaryDump, - TargetPlatform::AcornElectron | TargetPlatform::ColecoVision | TargetPlatform::MSX) // ROM - Format("sg", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Sega) // SG - Format("sms", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Sega) // SMS - Format("ssd", result.disks, Disk::DiskImageHolder, TargetPlatform::Acorn) // SSD - Format("tap", result.tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP (Commodore) - Format("tap", result.tapes, Tape::OricTAP, TargetPlatform::Oric) // TAP (Oric) - Format("tsx", result.tapes, Tape::TZX, TargetPlatform::MSX) // TSX - Format("tzx", result.tapes, Tape::TZX, TargetPlatform::ZX8081) // TZX - Format("uef", result.tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape) - Format("woz", result.disks, Disk::DiskImageHolder, TargetPlatform::DiskII) // WOZ + TargetPlatform::AcornElectron | TargetPlatform::ColecoVision | TargetPlatform::MSX) // ROM + Format("sg", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Sega) // SG + Format("sms", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Sega) // SMS + Format("ssd", result.disks, Disk::DiskImageHolder, TargetPlatform::Acorn) // SSD + Format("tap", result.tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP (Commodore) + Format("tap", result.tapes, Tape::OricTAP, TargetPlatform::Oric) // TAP (Oric) + Format("tsx", result.tapes, Tape::TZX, TargetPlatform::MSX) // TSX + Format("tzx", result.tapes, Tape::TZX, TargetPlatform::ZX8081) // TZX + Format("uef", result.tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape) + Format("woz", result.disks, Disk::DiskImageHolder, TargetPlatform::DiskII) // WOZ #undef Format #undef Insert @@ -173,9 +176,10 @@ TargetList Analyser::Static::GetTargets(const std::string &file_name) { if(potential_platforms & TargetPlatform::ColecoVision) Append(Coleco); if(potential_platforms & TargetPlatform::Commodore) Append(Commodore); if(potential_platforms & TargetPlatform::DiskII) Append(DiskII); - if(potential_platforms & TargetPlatform::Sega) Append(Sega); + if(potential_platforms & TargetPlatform::Macintosh) Append(Macintosh); if(potential_platforms & TargetPlatform::MSX) Append(MSX); if(potential_platforms & TargetPlatform::Oric) Append(Oric); + if(potential_platforms & TargetPlatform::Sega) Append(Sega); if(potential_platforms & TargetPlatform::ZX8081) Append(ZX8081); #undef Append diff --git a/Machines/Apple/Macintosh/Macintosh.cpp b/Machines/Apple/Macintosh/Macintosh.cpp index e329ab64f..697e82f41 100644 --- a/Machines/Apple/Macintosh/Macintosh.cpp +++ b/Machines/Apple/Macintosh/Macintosh.cpp @@ -111,7 +111,7 @@ class ConcreteMachine: // Update the video. TODO: only on demand. video_.run_for(cycle.length); - via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, video_.vsync()); + via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !video_.vsync()); // Update interrupt input. TODO: move this into a VIA/etc delegate callback? mc68000_.set_interrupt_level( (via_.get_interrupt_line() ? 1 : 0) ); diff --git a/Machines/Utility/MachineForTarget.cpp b/Machines/Utility/MachineForTarget.cpp index 5cf0ad735..e5b4ee453 100644 --- a/Machines/Utility/MachineForTarget.cpp +++ b/Machines/Utility/MachineForTarget.cpp @@ -38,11 +38,11 @@ namespace { BindD(Apple::Macintosh, Macintosh) Bind(Atari2600) BindD(Coleco::Vision, ColecoVision) + BindD(Commodore::Vic20, Vic20) Bind(Electron) - BindD(Sega::MasterSystem, MasterSystem) Bind(MSX) Bind(Oric) - BindD(Commodore::Vic20, Vic20) + BindD(Sega::MasterSystem, MasterSystem) Bind(ZX8081) default: diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 6c8a4f7a1..058d34306 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -587,6 +587,9 @@ 4BB299F91B587D8400A49093 /* tyan in Resources */ = {isa = PBXBuildFile; fileRef = 4BB298ED1B587D8400A49093 /* tyan */; }; 4BB2A9AF1E13367E001A5C23 /* CRCTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */; }; 4BB4BFAD22A33DE50069048D /* DriveSpeedAccumulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4BFAC22A33DE50069048D /* DriveSpeedAccumulator.cpp */; }; + 4BB4BFB022A42F290069048D /* DiskCopy42.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4BFAE22A42F290069048D /* DiskCopy42.cpp */; }; + 4BB4BFB922A4372F0069048D /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4BFB822A4372E0069048D /* StaticAnalyser.cpp */; }; + 4BB4BFBA22A4372F0069048D /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4BFB822A4372E0069048D /* StaticAnalyser.cpp */; }; 4BB697CB1D4B6D3E00248BDF /* TimedEventLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */; }; 4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */; }; 4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EA11B587A5100552FC2 /* AppDelegate.swift */; }; @@ -1332,6 +1335,10 @@ 4BB4BFAA22A300710069048D /* DeferredAudio.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DeferredAudio.hpp; sourceTree = ""; }; 4BB4BFAB22A33D710069048D /* DriveSpeedAccumulator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DriveSpeedAccumulator.hpp; sourceTree = ""; }; 4BB4BFAC22A33DE50069048D /* DriveSpeedAccumulator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DriveSpeedAccumulator.cpp; sourceTree = ""; }; + 4BB4BFAE22A42F290069048D /* DiskCopy42.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DiskCopy42.cpp; sourceTree = ""; }; + 4BB4BFAF22A42F290069048D /* DiskCopy42.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DiskCopy42.hpp; sourceTree = ""; }; + 4BB4BFB722A4372E0069048D /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = ""; }; + 4BB4BFB822A4372E0069048D /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = ""; }; 4BB697C61D4B558F00248BDF /* Factors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Factors.hpp; path = ../../NumberTheory/Factors.hpp; sourceTree = ""; }; 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = ""; }; 4BB697CA1D4B6D3E00248BDF /* TimedEventLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimedEventLoop.hpp; sourceTree = ""; }; @@ -1937,32 +1944,34 @@ isa = PBXGroup; children = ( 4B45188D1F75FD1B00926311 /* AcornADF.cpp */, - 4B0333AD2094081A0050B93D /* AppleDSK.cpp */, - 4B45188F1F75FD1B00926311 /* CPCDSK.cpp */, - 4B4518911F75FD1B00926311 /* D64.cpp */, - 4BAF2B4C2004580C00480230 /* DMK.cpp */, - 4B4518931F75FD1B00926311 /* G64.cpp */, - 4B4518951F75FD1B00926311 /* HFE.cpp */, - 4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */, - 4BEBFB4B2002C4BF000708CC /* MSXDSK.cpp */, - 4B0F94FC208C1A1600FE41D9 /* NIB.cpp */, - 4B4518971F75FD1B00926311 /* OricMFMDSK.cpp */, - 4B4518991F75FD1B00926311 /* SSD.cpp */, - 4B6ED2EE208E2F8A0047B343 /* WOZ.cpp */, 4B45188E1F75FD1B00926311 /* AcornADF.hpp */, + 4B0333AD2094081A0050B93D /* AppleDSK.cpp */, 4B0333AE2094081A0050B93D /* AppleDSK.hpp */, + 4B45188F1F75FD1B00926311 /* CPCDSK.cpp */, 4B4518901F75FD1B00926311 /* CPCDSK.hpp */, + 4B4518911F75FD1B00926311 /* D64.cpp */, 4B4518921F75FD1B00926311 /* D64.hpp */, + 4BB4BFAE22A42F290069048D /* DiskCopy42.cpp */, + 4BB4BFAF22A42F290069048D /* DiskCopy42.hpp */, + 4BAF2B4C2004580C00480230 /* DMK.cpp */, 4BAF2B4D2004580C00480230 /* DMK.hpp */, + 4B4518931F75FD1B00926311 /* G64.cpp */, 4B4518941F75FD1B00926311 /* G64.hpp */, + 4B4518951F75FD1B00926311 /* HFE.cpp */, 4B4518961F75FD1B00926311 /* HFE.hpp */, + 4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */, 4B58601D1F806AB200AEE2E3 /* MFMSectorDump.hpp */, + 4BEBFB4B2002C4BF000708CC /* MSXDSK.cpp */, 4BEBFB4C2002C4BF000708CC /* MSXDSK.hpp */, + 4B0F94FC208C1A1600FE41D9 /* NIB.cpp */, 4B0F94FD208C1A1600FE41D9 /* NIB.hpp */, + 4B4518971F75FD1B00926311 /* OricMFMDSK.cpp */, 4B4518981F75FD1B00926311 /* OricMFMDSK.hpp */, + 4B4518991F75FD1B00926311 /* SSD.cpp */, 4B45189A1F75FD1B00926311 /* SSD.hpp */, - 4B6ED2EF208E2F8A0047B343 /* WOZ.hpp */, 4BFDD7891F7F2DB4008579B9 /* Utility */, + 4B6ED2EE208E2F8A0047B343 /* WOZ.cpp */, + 4B6ED2EF208E2F8A0047B343 /* WOZ.hpp */, ); path = Formats; sourceTree = ""; @@ -2353,6 +2362,7 @@ 4B8944FB201967B4007DE474 /* Commodore */, 4B894507201967B4007DE474 /* Disassembler */, 4BD67DC8209BE4D600AB2146 /* DiskII */, + 4BB4BFB622A4372E0069048D /* Macintosh */, 4B89450F201967B4007DE474 /* MSX */, 4B8944F6201967B4007DE474 /* Oric */, 4B7F1894215486A100388727 /* Sega */, @@ -2776,6 +2786,15 @@ path = "Wolfgang Lorenz 6502 test suite"; sourceTree = ""; }; + 4BB4BFB622A4372E0069048D /* Macintosh */ = { + isa = PBXGroup; + children = ( + 4BB4BFB722A4372E0069048D /* StaticAnalyser.hpp */, + 4BB4BFB822A4372E0069048D /* StaticAnalyser.cpp */, + ); + path = Macintosh; + sourceTree = ""; + }; 4BB697C81D4B559300248BDF /* NumberTheory */ = { isa = PBXGroup; children = ( @@ -3825,6 +3844,7 @@ 4B1B88BC202E2EC100B67DFF /* MultiKeyboardMachine.cpp in Sources */, 4BF437EF209D0F7E008CBD6B /* SegmentParser.cpp in Sources */, 4B055AD11FAE9B030060FFFF /* Video.cpp in Sources */, + 4BB4BFBA22A4372F0069048D /* StaticAnalyser.cpp in Sources */, 4B055AA21FAE85DA0060FFFF /* SSD.cpp in Sources */, 4BEBFB4E2002C4BF000708CC /* MSXDSK.cpp in Sources */, 4B055ADD1FAE9B460060FFFF /* i8272.cpp in Sources */, @@ -3939,6 +3959,7 @@ 4BCE0052227CE8CA000CA200 /* DiskIICard.cpp in Sources */, 4BCF1FA41DADC3DD0039D2E7 /* Oric.cpp in Sources */, 4BD67DCB209BE4D700AB2146 /* StaticAnalyser.cpp in Sources */, + 4BB4BFB922A4372F0069048D /* StaticAnalyser.cpp in Sources */, 4B9BE400203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */, 4B894538201967B4007DE474 /* Tape.cpp in Sources */, 4B54C0CB1F8D92590050900F /* Keyboard.cpp in Sources */, @@ -3949,6 +3970,7 @@ 4B595FAD2086DFBA0083CAA8 /* AudioToggle.cpp in Sources */, 4B1497921EE4B5A800CE2596 /* ZX8081.cpp in Sources */, 4B643F3F1D77B88000D431D6 /* DocumentController.swift in Sources */, + 4BB4BFB022A42F290069048D /* DiskCopy42.cpp in Sources */, 4B05401E219D1618001BF69C /* ScanTarget.cpp in Sources */, 4B4518861F75E91A00926311 /* MFMDiskController.cpp in Sources */, 4B54C0BF1F8D8F450050900F /* Keyboard.cpp in Sources */, diff --git a/OSBindings/Mac/Clock Signal/Info.plist b/OSBindings/Mac/Clock Signal/Info.plist index 1fb197ed1..d44fd966d 100644 --- a/OSBindings/Mac/Clock Signal/Info.plist +++ b/OSBindings/Mac/Clock Signal/Info.plist @@ -14,42 +14,42 @@ CFBundleTypeIconFile cartridge.png + CFBundleTypeName + Atari 2600 Cartridge CFBundleTypeOSTypes ???? - CFBundleTypeName - Atari 2600 Cartridge CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions rom - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile chip.png CFBundleTypeName ROM Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions @@ -57,110 +57,110 @@ uef uef.gz - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cassette.png CFBundleTypeName Electron/BBC UEF Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions prg - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile floppy525.png CFBundleTypeName Commodore Program + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions tap - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cassette.png CFBundleTypeName Tape Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions g64 - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile floppy525.png CFBundleTypeName Commodore Disk + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Editor + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions d64 - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile floppy525.png CFBundleTypeName Commodore 1540/1 Disk + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Editor + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions @@ -171,44 +171,44 @@ adl adm - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile floppy35.png CFBundleTypeName Electron/BBC Disk Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Editor + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions dsk - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile floppy35.png CFBundleTypeName Disk Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Editor + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions @@ -216,22 +216,22 @@ o 80 - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cassette.png CFBundleTypeName ZX80 Tape Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions @@ -240,240 +240,240 @@ 81 p81 - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cassette.png CFBundleTypeName ZX81 Tape Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions csw - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cassette.png CFBundleTypeName Tape Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions tzx - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cassette.png CFBundleTypeName Tape Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions cdt - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cassette.png CFBundleTypeName Amstrad CPC Tape Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions hfe - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile floppy35.png CFBundleTypeName HxC Disk Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions cas - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cassette.png CFBundleTypeName MSX Tape Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions dmk - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile floppy35.png CFBundleTypeName Disk Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer - LSTypeIsPackage - LSHandlerRank Owner + LSTypeIsPackage + CFBundleTypeExtensions tsx - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cassette.png CFBundleTypeName MSX Tape Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions col - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cartridge.png CFBundleTypeName ColecoVision Cartridge + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions sms - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cartridge.png CFBundleTypeName Master System Cartridge + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions sg - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile cartridge.png CFBundleTypeName SG1000 Cartridge + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner CFBundleTypeExtensions @@ -483,22 +483,43 @@ do po - CFBundleTypeOSTypes - - ???? - CFBundleTypeIconFile floppy525.png CFBundleTypeName Apple II Disk Image + CFBundleTypeOSTypes + + ???? + CFBundleTypeRole Viewer + LSHandlerRank + Owner LSTypeIsPackage NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument - LSHandlerRank - Owner + + + CFBundleTypeExtensions + + img + hfv + + CFBundleTypeIconFile + floppy35 + CFBundleTypeName + DiskCopy 4.2 Disk Image + CFBundleTypeOSTypes + + ???? + + CFBundleTypeRole + Viewer + LSTypeIsPackage + 0 + NSDocumentClass + $(PRODUCT_MODULE_NAME).MachineDocument CFBundleExecutable diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 79ac0f4e9..1bb7cf8c6 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -283,7 +283,7 @@ template void Proces } #ifdef LOG_TRACE - should_log |= (program_counter_.full - 4) == 0x405984; + should_log |= (program_counter_.full - 4) == 0x00400690; #endif if(instructions[decoded_instruction_.full].micro_operations) { diff --git a/Storage/Disk/DiskImage/Formats/DiskCopy42.cpp b/Storage/Disk/DiskImage/Formats/DiskCopy42.cpp new file mode 100644 index 000000000..6e3c944a7 --- /dev/null +++ b/Storage/Disk/DiskImage/Formats/DiskCopy42.cpp @@ -0,0 +1,120 @@ +// +// DiskCopy42.cpp +// Clock Signal +// +// Created by Thomas Harte on 02/06/2019. +// Copyright © 2019 Thomas Harte. All rights reserved. +// + +#include "DiskCopy42.hpp" + +/* + File format specifications as referenced below are largely + sourced from the documentation at + https://wiki.68kmla.org/DiskCopy_4.2_format_specification +*/ + +using namespace Storage::Disk; + +DiskCopy42::DiskCopy42(const std::string &file_name) : + file_(file_name) { + + // File format starts with 64 bytes dedicated to the disk name; + // this is a Pascal-style string though there is apparently a + // bug in one version of Disk Copy that can cause the length to + // be one too high. + // + // Validate the length, then skip the rest of the string. + const auto name_length = file_.get8(); + if(name_length > 64) + throw Error::InvalidFormat; + + // Get the length of the data and tag blocks. + file_.seek(64, SEEK_SET); + const auto data_block_length = file_.get32be(); + const auto tag_block_length = file_.get32be(); + const auto data_checksum = file_.get32be(); + const auto tag_checksum = file_.get32be(); + + // Check that this is a comprehensible disk encoding. + const auto encoding = file_.get8(); + switch(encoding) { + default: throw Error::InvalidFormat; + + case 0: encoding_ = Encoding::GCR400; break; + case 1: encoding_ = Encoding::GCR800; break; + case 2: encoding_ = Encoding::MFM720; break; + case 3: encoding_ = Encoding::MFM1440; break; + } + format_ = file_.get8(); + + // Check the magic number. + const auto magic_number = file_.get16be(); + if(magic_number != 0x0100) + throw Error::InvalidFormat; + + // Read the data and tags, and verify that enough data + // was present. + data_ = file_.read(data_block_length); + tags_ = file_.read(tag_block_length); + + if(data_.size() != data_block_length || tags_.size() != tag_block_length) + throw Error::InvalidFormat; + + // Verify the two checksums. + const auto computed_data_checksum = checksum(data_); + const auto computed_tag_checksum = checksum(tags_, 12); + + if(computed_tag_checksum != tag_checksum || computed_data_checksum != data_checksum) + throw Error::InvalidFormat; +} + +uint32_t DiskCopy42::checksum(const std::vector &data, size_t bytes_to_skip) { + uint32_t result = 0; + + // Checksum algorith is: take each two bytes as a big-endian word; add that to a + // 32-bit accumulator and then rotate the accumulator right one position. + for(size_t c = bytes_to_skip; c < data.size(); c += 2) { + const uint16_t next_word = uint16_t((data[c] << 8) | data[c+1]); + result += next_word; + result = (result >> 1) | (result << 31); + } + + return result; +} + +HeadPosition DiskCopy42::get_maximum_head_position() { + return HeadPosition(80); +} + +int DiskCopy42::get_head_count() { + // Bit 5 in the format field indicates whether this disk is double + // sided, regardless of whether it is GCR or MFM. + return 1 + ((format_ & 0x20) >> 5); +} + +bool DiskCopy42::get_is_read_only() { + return true; +} + +std::shared_ptr<::Storage::Disk::Track> DiskCopy42::get_track_at_position(::Storage::Disk::Track::Address address) { + /* + The format_ byte has the following meanings: + + GCR: + This byte appears on disk as the GCR format nibble in every sector tag. + The low five bits are an interleave factor, either: + + '2' for 0 8 1 9 2 10 3 11 4 12 5 13 6 14 7 15; or + '4' for 0 4 8 12 1 5 9 13 2 6 10 14 3 7 11 15. + + Bit 5 indicates double sided or not. + + MFM: + The low five bits provide sector size as a multiple of 256 bytes. + Bit 5 indicates double sided or not. + */ + + // TODO. + return nullptr; +} diff --git a/Storage/Disk/DiskImage/Formats/DiskCopy42.hpp b/Storage/Disk/DiskImage/Formats/DiskCopy42.hpp new file mode 100644 index 000000000..4d13a76a8 --- /dev/null +++ b/Storage/Disk/DiskImage/Formats/DiskCopy42.hpp @@ -0,0 +1,58 @@ +// +// DiskCopy42.hpp +// Clock Signal +// +// Created by Thomas Harte on 02/06/2019. +// Copyright © 2019 Thomas Harte. All rights reserved. +// + +#ifndef DiskCopy42_hpp +#define DiskCopy42_hpp + +#include "../DiskImage.hpp" +#include "../../../FileHolder.hpp" + +namespace Storage { +namespace Disk { + +/*! + Provides a @c DiskImage containing a disk imaged by Apple's Disk Copy 4.2: sector contents + (plus tag data) in either an Apple GCR or standard MFM encoding. +*/ +class DiskCopy42: public DiskImage { + public: + /*! + Construct a @c DiskCopy42 containing content from the file with name @c file_name. + + @throws Error::InvalidFormat if this file doesn't appear to be in Disk Copy 4.2 format. + */ + DiskCopy42(const std::string &file_name); + + // implemented to satisfy @c Disk + HeadPosition get_maximum_head_position() 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: + Storage::FileHolder file_; + + enum class Encoding { + GCR400, + GCR800, + MFM720, + MFM1440 + } encoding_; + uint8_t format_; + + std::vector data_; + std::vector tags_; + + uint32_t checksum(const std::vector &, size_t bytes_to_skip = 0); +}; + +} +} + +#endif /* DiskCopy42_hpp */ diff --git a/Storage/Disk/Drive.hpp b/Storage/Disk/Drive.hpp index 1033343af..02713ea37 100644 --- a/Storage/Disk/Drive.hpp +++ b/Storage/Disk/Drive.hpp @@ -25,6 +25,7 @@ namespace Disk { class Drive: public ClockingHint::Source, public TimedEventLoop { public: Drive(unsigned int input_clock_rate, int revolutions_per_minute, int number_of_heads); + Drive(unsigned int input_clock_rate, int number_of_heads); ~Drive(); /*! @@ -138,6 +139,8 @@ class Drive: public ClockingHint::Source, public TimedEventLoop { */ std::shared_ptr step_to(HeadPosition offset); + void set(Time); + private: // Drives contain an entire disk; from that a certain track // will be currently under the head. diff --git a/Storage/TargetPlatforms.hpp b/Storage/TargetPlatforms.hpp index 37017e236..4df8a6a1c 100644 --- a/Storage/TargetPlatforms.hpp +++ b/Storage/TargetPlatforms.hpp @@ -25,10 +25,11 @@ enum Type: IntType { Commodore = 1 << 10, DiskII = 1 << 11, Sega = 1 << 12, - MSX = 1 << 13, - Oric = 1 << 14, - ZX80 = 1 << 15, - ZX81 = 1 << 16, + Macintosh = 1 << 13, + MSX = 1 << 14, + Oric = 1 << 15, + ZX80 = 1 << 16, + ZX81 = 1 << 17, Acorn = AcornAtom | AcornElectron | BBCMaster | BBCModelA | BBCModelB, ZX8081 = ZX80 | ZX81,