diff --git a/Machines/Electron/Tape.cpp b/Machines/Electron/Tape.cpp index 50c4b7e86..a95d94995 100644 --- a/Machines/Electron/Tape.cpp +++ b/Machines/Electron/Tape.cpp @@ -78,8 +78,11 @@ void Tape::process_input_pulse(Storage::Tape::Tape::Pulse pulse) { crossings_[3] = Tape::Unrecognised; if(pulse.type != Storage::Tape::Tape::Pulse::Zero) { float pulse_length = (float)pulse.length.length / (float)pulse.length.clock_rate; - if(pulse_length >= 0.35 / 2400.0 && pulse_length < 0.7 / 2400.0) crossings_[3] = Tape::Short; - if(pulse_length >= 0.35 / 1200.0 && pulse_length < 0.7 / 1200.0) crossings_[3] = Tape::Long; + if(pulse_length >= 0.35 / 2400.0 && pulse_length < 0.7 / 1200.0) { + crossings_[3] = pulse_length > 1.0 / 3000.0 ? Tape::Long : Tape::Short; + } +// if(pulse_length >= 0.35 / 2400.0 && pulse_length < 0.7 / 2400.0) crossings_[3] = Tape::Short; +// if(pulse_length >= 0.35 / 1200.0 && pulse_length < 0.7 / 1200.0) crossings_[3] = Tape::Long; } if(crossings_[0] == Tape::Long && crossings_[1] == Tape::Long) { diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 23cdc4e5e..cf82f9e73 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -51,6 +51,7 @@ 4B3BA0CF1D318B44005DD7A7 /* MOS6522Bridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0C91D318B44005DD7A7 /* MOS6522Bridge.mm */; }; 4B3BA0D01D318B44005DD7A7 /* MOS6532Bridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0CB1D318B44005DD7A7 /* MOS6532Bridge.mm */; }; 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 */; }; 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 */; }; @@ -539,6 +540,8 @@ 4B3BA0CB1D318B44005DD7A7 /* MOS6532Bridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MOS6532Bridge.mm; sourceTree = ""; }; 4B3BA0CC1D318B44005DD7A7 /* TestMachine6502.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestMachine6502.h; sourceTree = ""; }; 4B3BA0CD1D318B44005DD7A7 /* TestMachine6502.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestMachine6502.mm; sourceTree = ""; }; + 4B3BF5AE1F146264005B6C36 /* CSW.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSW.cpp; sourceTree = ""; }; + 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 = ""; }; 4B44EBF41DC987AE00A7820C /* AllSuiteA.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = AllSuiteA.bin; path = AllSuiteA/AllSuiteA.bin; sourceTree = ""; }; @@ -1394,17 +1397,19 @@ 4B69FB411C4D941400B5F0AA /* Formats */ = { isa = PBXGroup; children = ( - 4B69FB451C4D950F00B5F0AA /* libz.tbd */, - 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */, - 4B69FB431C4D941400B5F0AA /* TapeUEF.hpp */, 4BC91B811D1F160E00884B76 /* CommodoreTAP.cpp */, - 4BC91B821D1F160E00884B76 /* CommodoreTAP.hpp */, - 4B2BFC5D1D613E0200BA3AA9 /* TapePRG.cpp */, - 4B2BFC5E1D613E0200BA3AA9 /* TapePRG.hpp */, + 4B3BF5AE1F146264005B6C36 /* CSW.cpp */, 4B59199A1DAC6C46005BB85C /* OricTAP.cpp */, - 4B59199B1DAC6C46005BB85C /* OricTAP.hpp */, + 4B2BFC5D1D613E0200BA3AA9 /* TapePRG.cpp */, + 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */, 4B1497861EE4A1DA00CE2596 /* ZX80O81P.cpp */, + 4BC91B821D1F160E00884B76 /* CommodoreTAP.hpp */, + 4B3BF5AF1F146264005B6C36 /* CSW.hpp */, + 4B59199B1DAC6C46005BB85C /* OricTAP.hpp */, + 4B2BFC5E1D613E0200BA3AA9 /* TapePRG.hpp */, + 4B69FB431C4D941400B5F0AA /* TapeUEF.hpp */, 4B1497871EE4A1DA00CE2596 /* ZX80O81P.hpp */, + 4B69FB451C4D950F00B5F0AA /* libz.tbd */, ); path = Formats; sourceTree = ""; @@ -2593,6 +2598,7 @@ 4BD69F941D98760000243FE1 /* AcornADF.cpp in Sources */, 4BBF99181C8FBA6F0075DAFB /* TextureTarget.cpp in Sources */, 4BC76E691C98E31700E6EF73 /* FIRFilter.cpp in Sources */, + 4B3BF5B01F146265005B6C36 /* CSW.cpp in Sources */, 4B2A332A1DB8544D002876E3 /* MemoryFuzzer.cpp in Sources */, 4B55CE5F1C3B7D960093A61B /* MachineDocument.swift in Sources */, 4B2A332F1DB86869002876E3 /* OricOptionsPanel.swift in Sources */, diff --git a/OSBindings/Mac/Clock Signal/Info.plist b/OSBindings/Mac/Clock Signal/Info.plist index 42a1aec16..4ca666175 100644 --- a/OSBindings/Mac/Clock Signal/Info.plist +++ b/OSBindings/Mac/Clock Signal/Info.plist @@ -141,6 +141,8 @@ Electron/BBC Disk Image CFBundleTypeRole Editor + LSTypeIsPackage + 0 NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument @@ -155,6 +157,8 @@ Disk Image CFBundleTypeRole Editor + LSTypeIsPackage + 0 NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument @@ -170,6 +174,8 @@ ZX80 Tape Image CFBundleTypeRole Viewer + LSTypeIsPackage + 0 NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument @@ -185,6 +191,24 @@ ZX81 Tape Image CFBundleTypeRole Viewer + LSTypeIsPackage + 0 + NSDocumentClass + $(PRODUCT_MODULE_NAME).MachineDocument + + + CFBundleTypeExtensions + + csw + + CFBundleTypeIconFile + cassette + CFBundleTypeName + Tape Image + CFBundleTypeRole + Viewer + LSTypeIsPackage + 0 NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument diff --git a/StaticAnalyser/Acorn/StaticAnalyser.cpp b/StaticAnalyser/Acorn/StaticAnalyser.cpp index 98edd262d..695c232cd 100644 --- a/StaticAnalyser/Acorn/StaticAnalyser.cpp +++ b/StaticAnalyser/Acorn/StaticAnalyser.cpp @@ -75,6 +75,7 @@ void StaticAnalyser::Acorn::AddTargets( if(tapes.size() > 0) { std::shared_ptr tape = tapes.front(); std::list files = GetFiles(tape); + tape->reset(); // continue if there are any files if(files.size()) { diff --git a/StaticAnalyser/Acorn/Tape.cpp b/StaticAnalyser/Acorn/Tape.cpp index f3b0931f0..358b643ea 100644 --- a/StaticAnalyser/Acorn/Tape.cpp +++ b/StaticAnalyser/Acorn/Tape.cpp @@ -60,6 +60,8 @@ static std::unique_ptr GetNextChunk(const std::shared_ptr> 8) | (stored_header_crc << 8)); new_chunk->header_crc_matched = stored_header_crc == calculated_header_crc; + if(!new_chunk->header_crc_matched) return nullptr; + parser.reset_crc(); new_chunk->data.reserve(new_chunk->block_length); for(int c = 0; c < new_chunk->block_length; c++) { diff --git a/StaticAnalyser/Commodore/StaticAnalyser.cpp b/StaticAnalyser/Commodore/StaticAnalyser.cpp index c1d6aa472..79668e950 100644 --- a/StaticAnalyser/Commodore/StaticAnalyser.cpp +++ b/StaticAnalyser/Commodore/StaticAnalyser.cpp @@ -68,6 +68,7 @@ void StaticAnalyser::Commodore::AddTargets( // check tapes for(auto &tape : tapes) { std::list tape_files = GetFiles(tape); + tape->reset(); if(tape_files.size()) { files.splice(files.end(), tape_files); target.tapes = tapes; diff --git a/StaticAnalyser/Oric/StaticAnalyser.cpp b/StaticAnalyser/Oric/StaticAnalyser.cpp index 342ddd728..915004994 100644 --- a/StaticAnalyser/Oric/StaticAnalyser.cpp +++ b/StaticAnalyser/Oric/StaticAnalyser.cpp @@ -84,8 +84,9 @@ void StaticAnalyser::Oric::AddTargets( int basic10_votes = 0; int basic11_votes = 0; - for(auto tape : tapes) { + for(auto &tape : tapes) { std::list tape_files = GetFiles(tape); + tape->reset(); if(tape_files.size()) { for(auto file : tape_files) { if(file.data_type == File::MachineCode) { diff --git a/StaticAnalyser/StaticAnalyser.cpp b/StaticAnalyser/StaticAnalyser.cpp index 2b18a921c..41c1b87ce 100644 --- a/StaticAnalyser/StaticAnalyser.cpp +++ b/StaticAnalyser/StaticAnalyser.cpp @@ -30,6 +30,7 @@ // Tapes #include "../Storage/Tape/Formats/CommodoreTAP.hpp" +#include "../Storage/Tape/Formats/CSW.hpp" #include "../Storage/Tape/Formats/OricTAP.hpp" #include "../Storage/Tape/Formats/TapePRG.hpp" #include "../Storage/Tape/Formats/TapeUEF.hpp" @@ -42,6 +43,8 @@ enum class TargetPlatform: TargetPlatformType { Commodore = 1 << 2, Oric = 1 << 3, ZX8081 = 1 << 4, + + AllTape = Acorn | Commodore | Oric | ZX8081, }; using namespace StaticAnalyser; @@ -94,6 +97,7 @@ std::list StaticAnalyser::GetTargets(const char *file_name) Format("a26", cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // A26 Format("adf", disks, Disk::AcornADF, TargetPlatform::Acorn) // ADF Format("bin", cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // BIN + Format("csw", tapes, Tape::CSW, TargetPlatform::AllTape) // CSW Format("d64", disks, Disk::D64, TargetPlatform::Commodore) // D64 Format("dsd", disks, Disk::SSD, TargetPlatform::Acorn) // DSD Format("dsk", disks, Disk::OricMFMDSK, TargetPlatform::Oric) // DSK diff --git a/StaticAnalyser/ZX8081/StaticAnalyser.cpp b/StaticAnalyser/ZX8081/StaticAnalyser.cpp index f7e86d02a..93fd276c0 100644 --- a/StaticAnalyser/ZX8081/StaticAnalyser.cpp +++ b/StaticAnalyser/ZX8081/StaticAnalyser.cpp @@ -35,6 +35,7 @@ void StaticAnalyser::ZX8081::AddTargets( if(!tapes.empty()) { std::vector files = GetFiles(tapes.front()); + tapes.front()->reset(); if(!files.empty()) { StaticAnalyser::Target target; target.machine = Target::ZX8081; diff --git a/Storage/Data/ZX8081.cpp b/Storage/Data/ZX8081.cpp index da5c6e481..836c85dde 100644 --- a/Storage/Data/ZX8081.cpp +++ b/Storage/Data/ZX8081.cpp @@ -51,7 +51,7 @@ static std::shared_ptr ZX81FileFromData(const std::vector &data) // Look for a file name. size_t data_pointer = 0; int c = 11; - while(c--) { + while(c < data.size() && c--) { if(data[data_pointer] & 0x80) break; data_pointer++; } diff --git a/Storage/Tape/Formats/CSW.cpp b/Storage/Tape/Formats/CSW.cpp new file mode 100644 index 000000000..2a065cb03 --- /dev/null +++ b/Storage/Tape/Formats/CSW.cpp @@ -0,0 +1,130 @@ +// +// CSW.cpp +// Clock Signal +// +// Created by Thomas Harte on 10/07/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#include "CSW.hpp" + +using namespace Storage::Tape; + +CSW::CSW(const char *file_name) : + Storage::FileHolder(file_name), + source_data_pointer_(0) { + if(file_stats_.st_size < 0x20) throw ErrorNotCSW; + + // Check signature. + char identifier[22]; + char signature[] = "Compressed Square Wave"; + fread(identifier, 1, 22, file_); + if(memcmp(identifier, signature, strlen(signature))) throw ErrorNotCSW; + + // Check terminating byte. + if(fgetc(file_) != 0x1a) throw ErrorNotCSW; + + // Get version file number. + uint8_t major_version = (uint8_t)fgetc(file_); + uint8_t minor_version = (uint8_t)fgetc(file_); + + // Reject if this is an unknown version. + if(major_version > 2 || !major_version || minor_version > 1) throw ErrorNotCSW; + + // The header now diverges based on version. + uint32_t number_of_waves = 0; + if(major_version == 1) { + pulse_.length.clock_rate = fgetc16le(); + + if(fgetc(file_) != 1) throw ErrorNotCSW; + compression_type_ = RLE; + + pulse_.type = (fgetc(file_) & 1) ? Pulse::High : Pulse::Low; + + fseek(file_, 0x20, SEEK_SET); + } else { + pulse_.length.clock_rate = fgetc32le(); + number_of_waves = fgetc32le(); + switch(fgetc(file_)) { + case 1: compression_type_ = RLE; break; + case 2: compression_type_ = ZRLE; break; + default: throw ErrorNotCSW; + } + + pulse_.type = (fgetc(file_) & 1) ? Pulse::High : Pulse::Low; + uint8_t extension_length = (uint8_t)fgetc(file_); + + if(file_stats_.st_size < 0x34 + extension_length) throw ErrorNotCSW; + fseek(file_, 0x34 + extension_length, SEEK_SET); + } + + if(compression_type_ == ZRLE) { + source_data_.resize((size_t)number_of_waves); + + std::vector file_data; + size_t remaining_data = (size_t)file_stats_.st_size - (size_t)ftell(file_); + file_data.resize(remaining_data); + fread(file_data.data(), sizeof(uint8_t), remaining_data, file_); + + uLongf output_length = (uLongf)number_of_waves; + uncompress(source_data_.data(), &output_length, file_data.data(), file_data.size()); + source_data_.resize((size_t)output_length); + } else { + rle_start_ = ftell(file_); + } + + invert_pulse(); +} + +uint8_t CSW::get_next_byte() { + switch(compression_type_) { + case RLE: return (uint8_t)fgetc(file_); + case ZRLE: { + if(source_data_pointer_ == source_data_.size()) return 0xff; + uint8_t result = source_data_[source_data_pointer_]; + source_data_pointer_++; + return result; + } + } +} + +uint32_t CSW::get_next_int32le() { + switch(compression_type_) { + case RLE: return fgetc32le(); + case ZRLE: { + if(source_data_pointer_ > source_data_.size() - 4) return 0xffff; + uint32_t result = (uint32_t)( + (source_data_[source_data_pointer_ + 0] << 0) | + (source_data_[source_data_pointer_ + 1] << 8) | + (source_data_[source_data_pointer_ + 2] << 16) | + (source_data_[source_data_pointer_ + 3] << 24)); + source_data_pointer_ += 4; + return result; + } + } +} + +void CSW::invert_pulse() { + pulse_.type = (pulse_.type == Pulse::High) ? Pulse::Low : Pulse::High; +} + +bool CSW::is_at_end() { + switch(compression_type_) { + case RLE: return (bool)feof(file_); + case ZRLE: return source_data_pointer_ == source_data_.size(); + } +} + +void CSW::virtual_reset() { + switch(compression_type_) { + case RLE: fseek(file_, rle_start_, SEEK_SET); break; + case ZRLE: source_data_pointer_ = 0; break; + } +} + +Tape::Pulse CSW::virtual_get_next_pulse() { + invert_pulse(); + pulse_.length.length = get_next_byte(); + if(!pulse_.length.length) pulse_.length.length = get_next_int32le(); + return pulse_; +} diff --git a/Storage/Tape/Formats/CSW.hpp b/Storage/Tape/Formats/CSW.hpp new file mode 100644 index 000000000..6f240e10b --- /dev/null +++ b/Storage/Tape/Formats/CSW.hpp @@ -0,0 +1,63 @@ +// +// CSW.hpp +// Clock Signal +// +// Created by Thomas Harte on 10/07/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#ifndef CSW_hpp +#define CSW_hpp + +#include "../Tape.hpp" +#include "../../FileHolder.hpp" + +#include +#include + +namespace Storage { +namespace Tape { + +/*! + Provides a @c Tape containing a CSW tape image, which is a compressed 1-bit sampling. +*/ +class CSW: public Tape, public Storage::FileHolder { + public: + /*! + Constructs a @c CSW containing content from the file with name @c file_name. + + @throws ErrorNotCSW if this file could not be opened and recognised as a valid CSW file. + */ + CSW(const char *file_name); + + enum { + ErrorNotCSW + }; + + // implemented to satisfy @c Tape + bool is_at_end(); + + private: + void virtual_reset(); + Pulse virtual_get_next_pulse(); + + Pulse pulse_; + enum CompressionType { + RLE, + ZRLE + } compression_type_; + + uint8_t get_next_byte(); + uint32_t get_next_int32le(); + void invert_pulse(); + + std::vector source_data_; + size_t source_data_pointer_; + + long rle_start_; +}; + +} +} + +#endif /* CSW_hpp */ diff --git a/Storage/Tape/Formats/ZX80O81P.hpp b/Storage/Tape/Formats/ZX80O81P.hpp index b2ceb5ff8..efc2a5425 100644 --- a/Storage/Tape/Formats/ZX80O81P.hpp +++ b/Storage/Tape/Formats/ZX80O81P.hpp @@ -24,9 +24,9 @@ namespace Tape { class ZX80O81P: public Tape, public Storage::FileHolder { public: /*! - Constructs an @c ZX80O containing content from the file with name @c file_name. + Constructs a @c ZX80O containing content from the file with name @c file_name. - @throws ErrorNotZX80O if this file could not be opened and recognised as a valid ZX80-format .O. + @throws ErrorNotZX80O81P if this file could not be opened and recognised as a valid ZX80-format .O. */ ZX80O81P(const char *file_name); diff --git a/Storage/Tape/Parsers/Acorn.cpp b/Storage/Tape/Parsers/Acorn.cpp index 35865a88f..1f7e2d8c7 100644 --- a/Storage/Tape/Parsers/Acorn.cpp +++ b/Storage/Tape/Parsers/Acorn.cpp @@ -14,27 +14,22 @@ Parser::Parser() : ::Storage::Tape::Parser(), crc_(0x1021, 0x0000) {} -int Parser::get_next_bit(const std::shared_ptr &tape) -{ +int Parser::get_next_bit(const std::shared_ptr &tape) { SymbolType symbol = get_next_symbol(tape); return (symbol == SymbolType::One) ? 1 : 0; } -int Parser::get_next_byte(const std::shared_ptr &tape) -{ +int Parser::get_next_byte(const std::shared_ptr &tape) { int value = 0; int c = 8; - if(get_next_bit(tape)) - { + if(get_next_bit(tape)) { set_error_flag(); return -1; } - while(c--) - { + while(c--) { value = (value >> 1) | (get_next_bit(tape) << 7); } - if(!get_next_bit(tape)) - { + if(!get_next_bit(tape)) { set_error_flag(); return -1; } @@ -42,15 +37,13 @@ int Parser::get_next_byte(const std::shared_ptr &tape) return value; } -int Parser::get_next_short(const std::shared_ptr &tape) -{ +int Parser::get_next_short(const std::shared_ptr &tape) { int result = get_next_byte(tape); result |= get_next_byte(tape) << 8; return result; } -int Parser::get_next_word(const std::shared_ptr &tape) -{ +int Parser::get_next_word(const std::shared_ptr &tape) { int result = get_next_short(tape); result |= get_next_short(tape) << 8; return result; @@ -59,28 +52,25 @@ int Parser::get_next_word(const std::shared_ptr &tape) void Parser::reset_crc() { crc_.reset(); } uint16_t Parser::get_crc() { return crc_.get_value(); } -void Parser::process_pulse(Storage::Tape::Tape::Pulse pulse) -{ - switch(pulse.type) - { +void Parser::process_pulse(Storage::Tape::Tape::Pulse pulse) { + switch(pulse.type) { default: break; case Storage::Tape::Tape::Pulse::High: case Storage::Tape::Tape::Pulse::Low: float pulse_length = pulse.length.get_float(); - if(pulse_length >= 0.35 / 2400.0 && pulse_length < 0.7 / 2400.0) { push_wave(WaveType::Short); return; } - if(pulse_length >= 0.35 / 1200.0 && pulse_length < 0.7 / 1200.0) { push_wave(WaveType::Long); return; } + if(pulse_length >= 0.35 / 2400.0 && pulse_length < 0.7 / 1200.0) { + push_wave(pulse_length > 1.0 / 3000.0 ? WaveType::Long : WaveType::Short); return; + } break; } push_wave(WaveType::Unrecognised); } -void Parser::inspect_waves(const std::vector &waves) -{ +void Parser::inspect_waves(const std::vector &waves) { if(waves.size() < 2) return; - if(waves[0] == WaveType::Long && waves[1] == WaveType::Long) - { + if(waves[0] == WaveType::Long && waves[1] == WaveType::Long) { push_symbol(SymbolType::Zero, 2); return; } @@ -90,8 +80,7 @@ void Parser::inspect_waves(const std::vector &waves) if( waves[0] == WaveType::Short && waves[1] == WaveType::Short && waves[2] == WaveType::Short && - waves[3] == WaveType::Short) - { + waves[3] == WaveType::Short) { push_symbol(SymbolType::One, 4); return; } diff --git a/Storage/Tape/Tape.hpp b/Storage/Tape/Tape.hpp index 7ed5920da..483f8e551 100644 --- a/Storage/Tape/Tape.hpp +++ b/Storage/Tape/Tape.hpp @@ -58,6 +58,8 @@ class Tape { /// Advances or reverses the tape to the last time before or at @c time from which a pulse starts. virtual void seek(Time &time); + virtual ~Tape() {}; + private: Time current_time_, next_time_;