From 238348c885bcf51d4aa0e5175cf34837a4ddb507 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 16 Jul 2017 21:33:11 -0400 Subject: [PATCH] Performed the initial wiring to announce that this application supports TZX files and to route them to the ZX80/81 static analyser. The TZX class itself does not yet do much beyond basic validation. I think it'll be easiest if it follows in UEF's footsteps in queuing up pulses ahead of time, so some factoring out is now required. --- .../Clock Signal.xcodeproj/project.pbxproj | 6 +++ OSBindings/Mac/Clock Signal/Info.plist | 14 +++++ StaticAnalyser/StaticAnalyser.cpp | 2 + Storage/Tape/Formats/CSW.cpp | 2 +- Storage/Tape/Formats/TZX.cpp | 49 ++++++++++++++++++ Storage/Tape/Formats/TZX.hpp | 51 +++++++++++++++++++ 6 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 Storage/Tape/Formats/TZX.cpp create mode 100644 Storage/Tape/Formats/TZX.hpp diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index cf82f9e73..886946b5b 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -53,6 +53,7 @@ 4B3BA0D11D318B44005DD7A7 /* TestMachine6502.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0CD1D318B44005DD7A7 /* TestMachine6502.mm */; }; 4B3BF5B01F146265005B6C36 /* CSW.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BF5AE1F146264005B6C36 /* CSW.cpp */; }; 4B3F1B461E0388D200DB26EE /* PCMPatchedTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3F1B441E0388D200DB26EE /* PCMPatchedTrack.cpp */; }; + 4B448E811F1C45A00009ABD6 /* TZX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B448E7F1F1C45A00009ABD6 /* TZX.cpp */; }; 4B44EBF51DC987AF00A7820C /* AllSuiteA.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4B44EBF41DC987AE00A7820C /* AllSuiteA.bin */; }; 4B44EBF71DC9883B00A7820C /* 6502_functional_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4B44EBF61DC9883B00A7820C /* 6502_functional_test.bin */; }; 4B44EBF91DC9898E00A7820C /* BCDTEST_beeb in Resources */ = {isa = PBXBuildFile; fileRef = 4B44EBF81DC9898E00A7820C /* BCDTEST_beeb */; }; @@ -544,6 +545,8 @@ 4B3BF5AF1F146264005B6C36 /* CSW.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CSW.hpp; sourceTree = ""; }; 4B3F1B441E0388D200DB26EE /* PCMPatchedTrack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PCMPatchedTrack.cpp; sourceTree = ""; }; 4B3F1B451E0388D200DB26EE /* PCMPatchedTrack.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PCMPatchedTrack.hpp; sourceTree = ""; }; + 4B448E7F1F1C45A00009ABD6 /* TZX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TZX.cpp; sourceTree = ""; }; + 4B448E801F1C45A00009ABD6 /* TZX.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TZX.hpp; sourceTree = ""; }; 4B44EBF41DC987AE00A7820C /* AllSuiteA.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = AllSuiteA.bin; path = AllSuiteA/AllSuiteA.bin; sourceTree = ""; }; 4B44EBF61DC9883B00A7820C /* 6502_functional_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = 6502_functional_test.bin; path = "Klaus Dormann/6502_functional_test.bin"; sourceTree = ""; }; 4B44EBF81DC9898E00A7820C /* BCDTEST_beeb */ = {isa = PBXFileReference; lastKnownFileType = file; name = BCDTEST_beeb; path = BCDTest/BCDTEST_beeb; sourceTree = ""; }; @@ -1402,12 +1405,14 @@ 4B59199A1DAC6C46005BB85C /* OricTAP.cpp */, 4B2BFC5D1D613E0200BA3AA9 /* TapePRG.cpp */, 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */, + 4B448E7F1F1C45A00009ABD6 /* TZX.cpp */, 4B1497861EE4A1DA00CE2596 /* ZX80O81P.cpp */, 4BC91B821D1F160E00884B76 /* CommodoreTAP.hpp */, 4B3BF5AF1F146264005B6C36 /* CSW.hpp */, 4B59199B1DAC6C46005BB85C /* OricTAP.hpp */, 4B2BFC5E1D613E0200BA3AA9 /* TapePRG.hpp */, 4B69FB431C4D941400B5F0AA /* TapeUEF.hpp */, + 4B448E801F1C45A00009ABD6 /* TZX.hpp */, 4B1497871EE4A1DA00CE2596 /* ZX80O81P.hpp */, 4B69FB451C4D950F00B5F0AA /* libz.tbd */, ); @@ -2605,6 +2610,7 @@ 4B7913CC1DFCD80E00175A82 /* Video.cpp in Sources */, 4B2A53A11D117D36003C6002 /* CSAtari2600.mm in Sources */, 4BF829661D8F732B001BAE39 /* Disk.cpp in Sources */, + 4B448E811F1C45A00009ABD6 /* TZX.cpp in Sources */, 4BEA52631DF339D7007E74F2 /* Speaker.cpp in Sources */, 4BC5E4921D7ED365008CF980 /* StaticAnalyser.cpp in Sources */, 4BC830D11D6E7C690000A26F /* Tape.cpp in Sources */, diff --git a/OSBindings/Mac/Clock Signal/Info.plist b/OSBindings/Mac/Clock Signal/Info.plist index 4ca666175..bd6e68c48 100644 --- a/OSBindings/Mac/Clock Signal/Info.plist +++ b/OSBindings/Mac/Clock Signal/Info.plist @@ -212,6 +212,20 @@ NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument + + CFBundleTypeExtensions + + tzx + + CFBundleTypeIconFile + cassette + CFBundleTypeName + Tape Image + CFBundleTypeRole + Viewer + NSDocumentClass + $(PRODUCT_MODULE_NAME).MachineDocument + CFBundleExecutable $(EXECUTABLE_NAME) diff --git a/StaticAnalyser/StaticAnalyser.cpp b/StaticAnalyser/StaticAnalyser.cpp index 41c1b87ce..2d42fffbe 100644 --- a/StaticAnalyser/StaticAnalyser.cpp +++ b/StaticAnalyser/StaticAnalyser.cpp @@ -34,6 +34,7 @@ #include "../Storage/Tape/Formats/OricTAP.hpp" #include "../Storage/Tape/Formats/TapePRG.hpp" #include "../Storage/Tape/Formats/TapeUEF.hpp" +#include "../Storage/Tape/Formats/TZX.hpp" #include "../Storage/Tape/Formats/ZX80O81P.hpp" typedef int TargetPlatformType; @@ -124,6 +125,7 @@ std::list StaticAnalyser::GetTargets(const char *file_name) Format("ssd", disks, Disk::SSD, TargetPlatform::Acorn) // SSD Format("tap", tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP (Commodore) Format("tap", tapes, Tape::OricTAP, TargetPlatform::Oric) // TAP (Oric) + Format("tzx", tapes, Tape::TZX, TargetPlatform::ZX8081) // TZX Format("uef", tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape) #undef Format diff --git a/Storage/Tape/Formats/CSW.cpp b/Storage/Tape/Formats/CSW.cpp index 2a065cb03..de3a493d4 100644 --- a/Storage/Tape/Formats/CSW.cpp +++ b/Storage/Tape/Formats/CSW.cpp @@ -18,7 +18,7 @@ CSW::CSW(const char *file_name) : // Check signature. char identifier[22]; char signature[] = "Compressed Square Wave"; - fread(identifier, 1, 22, file_); + fread(identifier, 1, strlen(signature), file_); if(memcmp(identifier, signature, strlen(signature))) throw ErrorNotCSW; // Check terminating byte. diff --git a/Storage/Tape/Formats/TZX.cpp b/Storage/Tape/Formats/TZX.cpp new file mode 100644 index 000000000..0083d8e37 --- /dev/null +++ b/Storage/Tape/Formats/TZX.cpp @@ -0,0 +1,49 @@ +// +// TZX.cpp +// Clock Signal +// +// Created by Thomas Harte on 16/07/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#include "TZX.hpp" + +using namespace Storage::Tape; + +TZX::TZX(const char *file_name) : + Storage::FileHolder(file_name), + is_high_(false), + is_at_end_(false), + pulse_pointer_(0) { + + // Check for signature followed by a 0x1a + char identifier[7]; + char signature[] = "ZXTape!"; + fread(identifier, 1, strlen(signature), file_); + if(memcmp(identifier, signature, strlen(signature))) throw ErrorNotTZX; + if(fgetc(file_) != 0x1a) throw ErrorNotTZX; + + // Get version number + uint8_t major_version = (uint8_t)fgetc(file_); + uint8_t minor_version = (uint8_t)fgetc(file_); + + // Reject if an incompatible version + if(major_version != 1 || minor_version > 20) throw ErrorNotTZX; + + // seed initial block contents + parse_next_chunk(); +} + +bool TZX::is_at_end() { + return true; +} + +Tape::Pulse TZX::virtual_get_next_pulse() { + return Tape::Pulse(); +} + +void TZX::virtual_reset() { +} + +void TZX::parse_next_chunk() { +} diff --git a/Storage/Tape/Formats/TZX.hpp b/Storage/Tape/Formats/TZX.hpp new file mode 100644 index 000000000..f6adf1b3d --- /dev/null +++ b/Storage/Tape/Formats/TZX.hpp @@ -0,0 +1,51 @@ +// +// TZX.hpp +// Clock Signal +// +// Created by Thomas Harte on 16/07/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#ifndef TZX_hpp +#define TZX_hpp + +#include "../Tape.hpp" +#include "../../FileHolder.hpp" + +namespace Storage { +namespace Tape { + +/*! + Provides a @c Tape containing a CSW tape image, which is a compressed 1-bit sampling. +*/ +class TZX: public Tape, public Storage::FileHolder { + public: + /*! + Constructs a @c TZX containing content from the file with name @c file_name. + + @throws ErrorNotTZX if this file could not be opened and recognised as a valid TZX file. + */ + TZX(const char *file_name); + + enum { + ErrorNotTZX + }; + + // implemented to satisfy @c Tape + bool is_at_end(); + + private: + Pulse virtual_get_next_pulse(); + void virtual_reset(); + +// std::vector queued_pulses_; + size_t pulse_pointer_; + bool is_at_end_; + + bool is_high_; + void parse_next_chunk(); +}; + +} +} +#endif /* TZX_hpp */