diff --git a/Analyser/Machines.hpp b/Analyser/Machines.hpp index 8ccbc5226..a71d16748 100644 --- a/Analyser/Machines.hpp +++ b/Analyser/Machines.hpp @@ -14,6 +14,7 @@ namespace Analyser { enum class Machine { AmstradCPC, Atari2600, + ColecoVision, Electron, MSX, Oric, diff --git a/Analyser/Static/Coleco/StaticAnalyser.cpp b/Analyser/Static/Coleco/StaticAnalyser.cpp new file mode 100644 index 000000000..0cced2590 --- /dev/null +++ b/Analyser/Static/Coleco/StaticAnalyser.cpp @@ -0,0 +1,45 @@ +// +// StaticAnalyser.cpp +// Clock Signal +// +// Created by Thomas Harte on 23/02/2018. +// Copyright © 2018 Thomas Harte. All rights reserved. +// + +#include "StaticAnalyser.hpp" + +static std::vector> + ColecoCartridgesFrom(const std::vector> &cartridges) { + std::vector> coleco_cartridges; + + for(const auto &cartridge : cartridges) { + const auto &segments = cartridge->get_segments(); + + // only one mapped item is allowed + if(segments.size() != 1) continue; + + // which must be 8, 12, 16, 24 or 32 kb in size + const Storage::Cartridge::Cartridge::Segment &segment = segments.front(); + const std::size_t data_size = segment.data.size(); + if((data_size&8191) && (data_size != 12*1024)) continue; + if(data_size < 8192 || data_size > 32768) continue; + + // the two first bytes must be 0xaa and 0x55, either way around + if(segment.data[0] != 0xaa && segment.data[0] != 0x55 && segment.data[1] != 0xaa && segment.data[1] != 0x55) continue; + if(segment.data[0] == segment.data[1]) continue; + + // probability of a random binary blob that isn't a Coleco ROM proceeding to here is 1 - 1/32768. + coleco_cartridges.push_back(cartridge); + } + + return coleco_cartridges; +} + +void Analyser::Static::Coleco::AddTargets(const Media &media, std::vector> &destination) { + std::unique_ptr target(new Target); + target->machine = Machine::ColecoVision; + target->confidence = 0.5; + target->media.cartridges = ColecoCartridgesFrom(media.cartridges); + if(!target->media.empty()) + destination.push_back(std::move(target)); +} diff --git a/Analyser/Static/Coleco/StaticAnalyser.hpp b/Analyser/Static/Coleco/StaticAnalyser.hpp new file mode 100644 index 000000000..91014b1c4 --- /dev/null +++ b/Analyser/Static/Coleco/StaticAnalyser.hpp @@ -0,0 +1,25 @@ +// +// StaticAnalyser.hpp +// Clock Signal +// +// Created by Thomas Harte on 23/02/2018. +// Copyright © 2018 Thomas Harte. All rights reserved. +// + +#ifndef StaticAnalyser_Coleco_StaticAnalyser_hpp +#define StaticAnalyser_Coleco_StaticAnalyser_hpp + +#include "../StaticAnalyser.hpp" + +namespace Analyser { +namespace Static { +namespace Coleco { + +void AddTargets(const Media &media, std::vector> &destination); + +} +} +} + + +#endif /* StaticAnalyser_hpp */ diff --git a/Analyser/Static/StaticAnalyser.cpp b/Analyser/Static/StaticAnalyser.cpp index c773d07d3..daae232ba 100644 --- a/Analyser/Static/StaticAnalyser.cpp +++ b/Analyser/Static/StaticAnalyser.cpp @@ -16,6 +16,7 @@ #include "Acorn/StaticAnalyser.hpp" #include "AmstradCPC/StaticAnalyser.hpp" #include "Atari/StaticAnalyser.hpp" +#include "Coleco/StaticAnalyser.hpp" #include "Commodore/StaticAnalyser.hpp" #include "MSX/StaticAnalyser.hpp" #include "Oric/StaticAnalyser.hpp" @@ -90,6 +91,7 @@ static Media GetMediaAndPlatforms(const char *file_name, TargetPlatform::IntType Format("bin", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // 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 @@ -115,7 +117,10 @@ static Media GetMediaAndPlatforms(const char *file_name, TargetPlatform::IntType } } - Format("rom", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Acorn | TargetPlatform::MSX) // ROM + Format( "rom", + result.cartridges, + Cartridge::BinaryDump, + TargetPlatform::Acorn | TargetPlatform::MSX | TargetPlatform::ColecoVision) // ROM 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) @@ -153,6 +158,7 @@ std::vector> Analyser::Static::GetTargets(const char *fi if(potential_platforms & TargetPlatform::Acorn) Acorn::AddTargets(media, targets); if(potential_platforms & TargetPlatform::AmstradCPC) AmstradCPC::AddTargets(media, targets); if(potential_platforms & TargetPlatform::Atari2600) Atari::AddTargets(media, targets); + if(potential_platforms & TargetPlatform::ColecoVision) Coleco::AddTargets(media, targets); if(potential_platforms & TargetPlatform::Commodore) Commodore::AddTargets(media, targets); if(potential_platforms & TargetPlatform::MSX) MSX::AddTargets(media, targets); if(potential_platforms & TargetPlatform::Oric) Oric::AddTargets(media, targets); diff --git a/Machines/ColecoVision/ColecoVision.cpp b/Machines/ColecoVision/ColecoVision.cpp new file mode 100644 index 000000000..d54bab118 --- /dev/null +++ b/Machines/ColecoVision/ColecoVision.cpp @@ -0,0 +1,27 @@ +// +// ColecoVision.cpp +// Clock Signal +// +// Created by Thomas Harte on 23/02/2018. +// Copyright © 2018 Thomas Harte. All rights reserved. +// + +#include "ColecoVision.hpp" + +namespace Coleco { +namespace Vision { + +class ConcreteMachine: + public Machine { +}; + +} +} + +using namespace Coleco::Vision; + +Machine *Machine::ColecoVision() { + return new ConcreteMachine; +} + +Machine::~Machine() {} diff --git a/Machines/ColecoVision/ColecoVision.hpp b/Machines/ColecoVision/ColecoVision.hpp new file mode 100644 index 000000000..fc6f41573 --- /dev/null +++ b/Machines/ColecoVision/ColecoVision.hpp @@ -0,0 +1,24 @@ +// +// ColecoVision.hpp +// Clock Signal +// +// Created by Thomas Harte on 23/02/2018. +// Copyright © 2018 Thomas Harte. All rights reserved. +// + +#ifndef ColecoVision_hpp +#define ColecoVision_hpp + +namespace Coleco { +namespace Vision { + +class Machine { + public: + virtual ~Machine(); + static Machine *ColecoVision(); +}; + +} +} + +#endif /* ColecoVision_hpp */ diff --git a/Machines/Utility/MachineForTarget.cpp b/Machines/Utility/MachineForTarget.cpp index 3c1641fcc..dd8f205e1 100644 --- a/Machines/Utility/MachineForTarget.cpp +++ b/Machines/Utility/MachineForTarget.cpp @@ -10,6 +10,7 @@ #include "../AmstradCPC/AmstradCPC.hpp" #include "../Atari2600/Atari2600.hpp" +#include "../ColecoVision/ColecoVision.hpp" #include "../Commodore/Vic-20/Vic20.hpp" #include "../Electron/Electron.hpp" #include "../MSX/MSX.hpp" @@ -25,13 +26,14 @@ namespace { error = Machine::Error::None; ::Machine::DynamicMachine *machine = nullptr; switch(target.machine) { - case Analyser::Machine::AmstradCPC: machine = new Machine::TypedDynamicMachine(AmstradCPC::Machine::AmstradCPC()); break; - case Analyser::Machine::Atari2600: machine = new Machine::TypedDynamicMachine(Atari2600::Machine::Atari2600()); break; - case Analyser::Machine::Electron: machine = new Machine::TypedDynamicMachine(Electron::Machine::Electron()); break; - case Analyser::Machine::MSX: machine = new Machine::TypedDynamicMachine(MSX::Machine::MSX()); break; - case Analyser::Machine::Oric: machine = new Machine::TypedDynamicMachine(Oric::Machine::Oric()); break; - case Analyser::Machine::Vic20: machine = new Machine::TypedDynamicMachine(Commodore::Vic20::Machine::Vic20()); break; - case Analyser::Machine::ZX8081: machine = new Machine::TypedDynamicMachine(ZX8081::Machine::ZX8081(target)); break; + case Analyser::Machine::AmstradCPC: machine = new Machine::TypedDynamicMachine(AmstradCPC::Machine::AmstradCPC()); break; + case Analyser::Machine::Atari2600: machine = new Machine::TypedDynamicMachine(Atari2600::Machine::Atari2600()); break; + case Analyser::Machine::ColecoVision: machine = new Machine::TypedDynamicMachine(Coleco::Vision::Machine::ColecoVision()); break; + case Analyser::Machine::Electron: machine = new Machine::TypedDynamicMachine(Electron::Machine::Electron()); break; + case Analyser::Machine::MSX: machine = new Machine::TypedDynamicMachine(MSX::Machine::MSX()); break; + case Analyser::Machine::Oric: machine = new Machine::TypedDynamicMachine(Oric::Machine::Oric()); break; + case Analyser::Machine::Vic20: machine = new Machine::TypedDynamicMachine(Commodore::Vic20::Machine::Vic20()); break; + case Analyser::Machine::ZX8081: machine = new Machine::TypedDynamicMachine(ZX8081::Machine::ZX8081(target)); break; default: error = Machine::Error::UnknownMachine; @@ -88,6 +90,7 @@ std::string Machine::ShortNameForTargetMachine(const Analyser::Machine machine) switch(machine) { case Analyser::Machine::AmstradCPC: return "AmstradCPC"; case Analyser::Machine::Atari2600: return "Atari2600"; + case Analyser::Machine::ColecoVision: return "ColecoVision"; case Analyser::Machine::Electron: return "Electron"; case Analyser::Machine::MSX: return "MSX"; case Analyser::Machine::Oric: return "Oric"; @@ -102,6 +105,7 @@ std::string Machine::LongNameForTargetMachine(Analyser::Machine machine) { switch(machine) { case Analyser::Machine::AmstradCPC: return "Amstrad CPC"; case Analyser::Machine::Atari2600: return "Atari 2600"; + case Analyser::Machine::ColecoVision: return "ColecoVision"; case Analyser::Machine::Electron: return "Acorn Electron"; case Analyser::Machine::MSX: return "MSX"; case Analyser::Machine::Oric: return "Oric"; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 5176aaf6b..290153c0a 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -220,6 +220,8 @@ 4B79E4441E3AF38600141F11 /* cassette.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4411E3AF38600141F11 /* cassette.png */; }; 4B79E4451E3AF38600141F11 /* floppy35.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4421E3AF38600141F11 /* floppy35.png */; }; 4B79E4461E3AF38600141F11 /* floppy525.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4431E3AF38600141F11 /* floppy525.png */; }; + 4B7A90E52041097C008514A2 /* ColecoVision.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7A90E42041097C008514A2 /* ColecoVision.cpp */; }; + 4B7A90ED20410A85008514A2 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7A90EC20410A85008514A2 /* StaticAnalyser.cpp */; }; 4B7BC7F51F58F27800D1B1B4 /* 6502AllRAM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A4C911F58F09E00E3F787 /* 6502AllRAM.cpp */; }; 4B7BC7F61F58F7D200D1B1B4 /* 6502Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */; }; 4B80AD001F85CACA00176895 /* BestEffortUpdater.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80ACFE1F85CAC900176895 /* BestEffortUpdater.cpp */; }; @@ -880,6 +882,10 @@ 4B79E4411E3AF38600141F11 /* cassette.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = cassette.png; sourceTree = ""; }; 4B79E4421E3AF38600141F11 /* floppy35.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = floppy35.png; sourceTree = ""; }; 4B79E4431E3AF38600141F11 /* floppy525.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = floppy525.png; sourceTree = ""; }; + 4B7A90E32041097C008514A2 /* ColecoVision.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ColecoVision.hpp; sourceTree = ""; }; + 4B7A90E42041097C008514A2 /* ColecoVision.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColecoVision.cpp; sourceTree = ""; }; + 4B7A90EB20410A85008514A2 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = ""; }; + 4B7A90EC20410A85008514A2 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = ""; }; 4B80ACFE1F85CAC900176895 /* BestEffortUpdater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BestEffortUpdater.cpp; path = ../../Concurrency/BestEffortUpdater.cpp; sourceTree = ""; }; 4B80ACFF1F85CACA00176895 /* BestEffortUpdater.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = BestEffortUpdater.hpp; path = ../../Concurrency/BestEffortUpdater.hpp; sourceTree = ""; }; 4B8334811F5D9FF70097E338 /* PartialMachineCycle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PartialMachineCycle.cpp; sourceTree = ""; }; @@ -2020,6 +2026,24 @@ name = MSX; sourceTree = ""; }; + 4B7A90E22041097C008514A2 /* ColecoVision */ = { + isa = PBXGroup; + children = ( + 4B7A90E32041097C008514A2 /* ColecoVision.hpp */, + 4B7A90E42041097C008514A2 /* ColecoVision.cpp */, + ); + path = ColecoVision; + sourceTree = ""; + }; + 4B7A90EA20410A85008514A2 /* Coleco */ = { + isa = PBXGroup; + children = ( + 4B7A90EC20410A85008514A2 /* StaticAnalyser.cpp */, + 4B7A90EB20410A85008514A2 /* StaticAnalyser.hpp */, + ); + path = Coleco; + sourceTree = ""; + }; 4B8334881F5DB8470097E338 /* Implementation */ = { isa = PBXGroup; children = ( @@ -2114,6 +2138,7 @@ 4B8944EB201967B4007DE474 /* Acorn */, 4B894514201967B4007DE474 /* AmstradCPC */, 4B8944F3201967B4007DE474 /* Atari */, + 4B7A90EA20410A85008514A2 /* Coleco */, 4B8944FB201967B4007DE474 /* Commodore */, 4B894507201967B4007DE474 /* Disassembler */, 4B89450F201967B4007DE474 /* MSX */, @@ -2647,6 +2672,7 @@ 4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */, 4B38F3491F2EC12000D9235D /* AmstradCPC */, 4B2E2D961C3A06EC00138695 /* Atari2600 */, + 4B7A90E22041097C008514A2 /* ColecoVision */, 4B4DC81D1D2C2425003C5BF8 /* Commodore */, 4B2E2D9E1C3A070900138695 /* Electron */, 4B79A4FC1FC8FF9800EEDAD5 /* MSX */, @@ -3520,6 +3546,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4B7A90E52041097C008514A2 /* ColecoVision.cpp in Sources */, 4B2BFC5F1D613E0200BA3AA9 /* TapePRG.cpp in Sources */, 4BC9DF4F1D04691600F44158 /* 6560.cpp in Sources */, 4B59199C1DAC6C46005BB85C /* OricTAP.cpp in Sources */, @@ -3528,6 +3555,7 @@ 4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */, 4B7136861F78724F008B8ED9 /* Encoder.cpp in Sources */, 4B0E04EA1FC9E5DA00F43484 /* CAS.cpp in Sources */, + 4B7A90ED20410A85008514A2 /* StaticAnalyser.cpp in Sources */, 4B58601E1F806AB200AEE2E3 /* MFMSectorDump.cpp in Sources */, 4B448E841F1C4C480009ABD6 /* PulseQueuedTape.cpp in Sources */, 4B0E61071FF34737002A9DBD /* MSX.cpp in Sources */, diff --git a/OSBindings/Mac/Clock Signal/Info.plist b/OSBindings/Mac/Clock Signal/Info.plist index b588b9cf7..12a8aee31 100644 --- a/OSBindings/Mac/Clock Signal/Info.plist +++ b/OSBindings/Mac/Clock Signal/Info.plist @@ -373,6 +373,26 @@ NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument + + CFBundleTypeExtensions + + col + + CFBundleTypeIconFile + cartridge + CFBundleTypeName + ColecoVision Cartridge + CFBundleTypeRole + Viewer + LSItemContentTypes + + public.item + + LSTypeIsPackage + 0 + NSDocumentClass + $(PRODUCT_MODULE_NAME).MachineDocument + CFBundleExecutable $(EXECUTABLE_NAME) diff --git a/Storage/TargetPlatforms.hpp b/Storage/TargetPlatforms.hpp index 560abf0be..b6b222cc8 100644 --- a/Storage/TargetPlatforms.hpp +++ b/Storage/TargetPlatforms.hpp @@ -20,11 +20,12 @@ enum Type: IntType { BBCMaster = 1 << 5, BBCModelA = 1 << 6, BBCModelB = 1 << 7, - Commodore = 1 << 8, - MSX = 1 << 9, - Oric = 1 << 10, - ZX80 = 1 << 11, - ZX81 = 1 << 12, + ColecoVision = 1 << 8, + Commodore = 1 << 9, + MSX = 1 << 10, + Oric = 1 << 11, + ZX80 = 1 << 12, + ZX81 = 1 << 13, Acorn = AcornAtom | AcornElectron | BBCMaster | BBCModelA | BBCModelB, ZX8081 = ZX80 | ZX81,