From d61f478a395563e665021b1b17f0ad217e5276ea Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 24 Apr 2021 23:17:47 -0400 Subject: [PATCH] Basic sketch for state snapshots: an extra field on Target. I think it doesn't make sense for states to own a target as that complicates the concept of Media. Plus they're distinct because it makes sense to have only one per Target. Let's see how this pans out. --- Analyser/Static/StaticAnalyser.cpp | 43 ++++++++++++++++--- Analyser/Static/StaticAnalyser.hpp | 12 ++++-- Machines/MachineTypes.hpp | 1 + Machines/StateProducer.hpp | 26 +++++++++++ .../Clock Signal.xcodeproj/project.pbxproj | 18 ++++++++ OSBindings/Mac/Clock Signal/Info.plist | 20 +++++++++ Storage/State/SNA.cpp | 36 ++++++++++++++++ Storage/State/SNA.hpp | 24 +++++++++++ 8 files changed, 170 insertions(+), 10 deletions(-) create mode 100644 Machines/StateProducer.hpp create mode 100644 Storage/State/SNA.cpp create mode 100644 Storage/State/SNA.hpp diff --git a/Analyser/Static/StaticAnalyser.cpp b/Analyser/Static/StaticAnalyser.cpp index e2c2e2823..e24897264 100644 --- a/Analyser/Static/StaticAnalyser.cpp +++ b/Analyser/Static/StaticAnalyser.cpp @@ -57,6 +57,9 @@ #include "../../Storage/MassStorage/Formats/DAT.hpp" #include "../../Storage/MassStorage/Formats/HFV.hpp" +// State Snapshots +#include "../../Storage/State/SNA.hpp" + // Tapes #include "../../Storage/Tape/Formats/CAS.hpp" #include "../../Storage/Tape/Formats/CommodoreTAP.hpp" @@ -73,15 +76,23 @@ using namespace Analyser::Static; -static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::IntType &potential_platforms) { - Media result; +namespace { +std::string get_extension(const std::string &name) { // Get the extension, if any; it will be assumed that extensions are reliable, so an extension is a broad-phase // test as to file format. - std::string::size_type final_dot = file_name.find_last_of("."); - if(final_dot == std::string::npos) return result; - std::string extension = file_name.substr(final_dot + 1); + std::string::size_type final_dot = name.find_last_of("."); + if(final_dot == std::string::npos) return name; + std::string extension = name.substr(final_dot + 1); std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); + return extension; +} + +} + +static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::IntType &potential_platforms) { + Media result; + const std::string extension = get_extension(file_name); #define InsertInstance(list, instance, platforms) \ list.emplace_back(instance);\ @@ -189,6 +200,7 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform:: #undef TryInsert #undef InsertInstance + return result; } @@ -199,14 +211,31 @@ Media Analyser::Static::GetMedia(const std::string &file_name) { TargetList Analyser::Static::GetTargets(const std::string &file_name) { TargetList targets; + const std::string extension = get_extension(file_name); + // Check whether the file directly identifies a target; if so then just return that. +#define Format(ext, class) \ + if(extension == ext) { \ + auto target = Storage::State::class::load(file_name); \ + if(target) { \ + targets.push_back(std::move(target)); \ + return targets; \ + } \ + } + + Format("sna", SNA); + +#undef TryInsert + + // Otherwise: + // // Collect all disks, tapes ROMs, etc as can be extrapolated from this file, forming the // union of all platforms this file might be a target for. TargetPlatform::IntType potential_platforms = 0; Media media = GetMediaAndPlatforms(file_name, potential_platforms); - // Hand off to platform-specific determination of whether these things are actually compatible and, - // if so, how to load them. + // Hand off to platform-specific determination of whether these + // things are actually compatible and, if so, how to load them. #define Append(x) if(potential_platforms & TargetPlatform::x) {\ auto new_targets = x::GetTargets(media, file_name, potential_platforms);\ std::move(new_targets.begin(), new_targets.end(), std::back_inserter(targets));\ diff --git a/Analyser/Static/StaticAnalyser.hpp b/Analyser/Static/StaticAnalyser.hpp index e806ae042..9e7372cac 100644 --- a/Analyser/Static/StaticAnalyser.hpp +++ b/Analyser/Static/StaticAnalyser.hpp @@ -15,6 +15,7 @@ #include "../../Storage/Disk/Disk.hpp" #include "../../Storage/MassStorage/MassStorageDevice.hpp" #include "../../Storage/Tape/Tape.hpp" +#include "../../Reflection/Struct.hpp" #include #include @@ -23,8 +24,10 @@ namespace Analyser { namespace Static { +struct State; + /*! - A list of disks, tapes and cartridges. + A list of disks, tapes and cartridges, and possibly a state snapshot. */ struct Media { std::vector> disks; @@ -48,13 +51,16 @@ struct Media { }; /*! - A list of disks, tapes and cartridges plus information about the machine to which to attach them and its configuration, - and instructions on how to launch the software attached, plus a measure of confidence in this target's correctness. + Describes a machine and possibly its state; conventionally subclassed to add other machine-specific configuration fields and any + necessary instructions on how to launch any software provided, plus a measure of confidence in this target's correctness. */ struct Target { Target(Machine machine) : machine(machine) {} virtual ~Target() {} + // This field is entirely optional. + std::shared_ptr state; + Machine machine; Media media; float confidence = 0.0f; diff --git a/Machines/MachineTypes.hpp b/Machines/MachineTypes.hpp index c96a02f10..f19e18d3a 100644 --- a/Machines/MachineTypes.hpp +++ b/Machines/MachineTypes.hpp @@ -20,6 +20,7 @@ #include "MediaTarget.hpp" #include "MouseMachine.hpp" #include "ScanProducer.hpp" +#include "StateProducer.hpp" #include "TimedMachine.hpp" #endif /* MachineTypes_h */ diff --git a/Machines/StateProducer.hpp b/Machines/StateProducer.hpp new file mode 100644 index 000000000..3a27e3cd0 --- /dev/null +++ b/Machines/StateProducer.hpp @@ -0,0 +1,26 @@ +// +// StateProducer.hpp +// Clock Signal +// +// Created by Thomas Harte on 24/04/2021. +// Copyright © 2021 Thomas Harte. All rights reserved. +// + +#ifndef State_h +#define State_h + +#include +#include "../Analyser/Static/StaticAnalyser.hpp" + +namespace MachineTypes { + +struct StateProducer { + // TODO. +// virtual bool get_state(Analyser::Static::State *, [[maybe_unused]] bool advance_to_simple = false) { +// return false; +// } +}; + +}; + +#endif /* State_h */ diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 24c509446..60002f0fd 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -479,6 +479,8 @@ 4B89453E201967B4007DE474 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B894517201967B4007DE474 /* StaticAnalyser.cpp */; }; 4B89453F201967B4007DE474 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B894517201967B4007DE474 /* StaticAnalyser.cpp */; }; 4B8DD3682633B2D400B3C866 /* SpectrumVideoContentionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B8DD3672633B2D400B3C866 /* SpectrumVideoContentionTests.mm */; }; + 4B8DD3862634D37E00B3C866 /* SNA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8DD3842634D37E00B3C866 /* SNA.cpp */; }; + 4B8DD3872634D37E00B3C866 /* SNA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8DD3842634D37E00B3C866 /* SNA.cpp */; }; 4B8DF4D825465B7500F3433C /* IIgsMemoryMapTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B8DF4D725465B7500F3433C /* IIgsMemoryMapTests.mm */; }; 4B8DF4F9254E36AE00F3433C /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8DF4F7254E36AD00F3433C /* Video.cpp */; }; 4B8DF4FA254E36AE00F3433C /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8DF4F7254E36AD00F3433C /* Video.cpp */; }; @@ -1429,6 +1431,9 @@ 4B8A7E85212F988200F2BBC6 /* DeferredQueue.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DeferredQueue.hpp; sourceTree = ""; }; 4B8D287E1F77207100645199 /* TrackSerialiser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TrackSerialiser.hpp; sourceTree = ""; }; 4B8DD3672633B2D400B3C866 /* SpectrumVideoContentionTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SpectrumVideoContentionTests.mm; sourceTree = ""; }; + 4B8DD375263481BB00B3C866 /* StateProducer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = StateProducer.hpp; sourceTree = ""; }; + 4B8DD3842634D37E00B3C866 /* SNA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SNA.cpp; sourceTree = ""; }; + 4B8DD3852634D37E00B3C866 /* SNA.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SNA.hpp; sourceTree = ""; }; 4B8DF4D62546561300F3433C /* MemoryMap.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MemoryMap.hpp; sourceTree = ""; }; 4B8DF4D725465B7500F3433C /* IIgsMemoryMapTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = IIgsMemoryMapTests.mm; sourceTree = ""; }; 4B8DF4ED254B840B00F3433C /* AppleClock.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = AppleClock.hpp; sourceTree = ""; }; @@ -2842,6 +2847,7 @@ 4B8805F81DCFF6CD003085B1 /* Data */, 4BAB62AA1D3272D200DF5BA0 /* Disk */, 4B6AAEA1230E3E1D0078E864 /* MassStorage */, + 4B8DD3832634D37E00B3C866 /* State */, 4B69FB3A1C4D908A00B5F0AA /* Tape */, ); name = Storage; @@ -3248,6 +3254,15 @@ path = AmstradCPC; sourceTree = ""; }; + 4B8DD3832634D37E00B3C866 /* State */ = { + isa = PBXGroup; + children = ( + 4B8DD3842634D37E00B3C866 /* SNA.cpp */, + 4B8DD3852634D37E00B3C866 /* SNA.hpp */, + ); + path = State; + sourceTree = ""; + }; 4B8DF4EC254B840B00F3433C /* AppleClock */ = { isa = PBXGroup; children = ( @@ -4018,6 +4033,7 @@ 4B92294222B04A3D00A1458F /* MouseMachine.hpp */, 4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */, 4B046DC31CFE651500E9E45E /* ScanProducer.hpp */, + 4B8DD375263481BB00B3C866 /* StateProducer.hpp */, 4BC57CD32434282000FBC404 /* TimedMachine.hpp */, 4B38F3491F2EC12000D9235D /* AmstradCPC */, 4BCE0048227CE8CA000CA200 /* Apple */, @@ -5216,6 +5232,7 @@ 4BEDA43225B3C700000C2DBD /* Executor.cpp in Sources */, 4BC1317B2346DF2B00E4FF3D /* MSA.cpp in Sources */, 4B894533201967B4007DE474 /* 6502.cpp in Sources */, + 4B8DD3872634D37E00B3C866 /* SNA.cpp in Sources */, 4B055AA91FAE85EF0060FFFF /* CommodoreGCR.cpp in Sources */, 4B055ADB1FAE9B460060FFFF /* 6560.cpp in Sources */, 4B17B58C20A8A9D9007CCA8F /* StringSerialiser.cpp in Sources */, @@ -5486,6 +5503,7 @@ 4BEBFB4D2002C4BF000708CC /* MSXDSK.cpp in Sources */, 4BBFBB6C1EE8401E00C01E7A /* ZX8081.cpp in Sources */, 4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */, + 4B8DD3862634D37E00B3C866 /* SNA.cpp in Sources */, 4B4DEC06252BFA56004583AC /* 65816Base.cpp in Sources */, 4B894524201967B4007DE474 /* Tape.cpp in Sources */, 4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */, diff --git a/OSBindings/Mac/Clock Signal/Info.plist b/OSBindings/Mac/Clock Signal/Info.plist index 5bb5dc8d1..aac5bb5fd 100644 --- a/OSBindings/Mac/Clock Signal/Info.plist +++ b/OSBindings/Mac/Clock Signal/Info.plist @@ -592,6 +592,26 @@ NSDocumentClass $(PRODUCT_MODULE_NAME).MachineDocument + + CFBundleTypeExtensions + + sna + + CFBundleTypeName + ZX Spectrum SNA image + CFBundleTypeOSTypes + + ???? + + CFBundleTypeRole + Viewer + LSHandlerRank + Owner + LSTypeIsPackage + + NSDocumentClass + $(PRODUCT_MODULE_NAME).MachineDocument + CFBundleExecutable $(EXECUTABLE_NAME) diff --git a/Storage/State/SNA.cpp b/Storage/State/SNA.cpp new file mode 100644 index 000000000..7199a5c2f --- /dev/null +++ b/Storage/State/SNA.cpp @@ -0,0 +1,36 @@ +// +// SNA.cpp +// Clock Signal +// +// Created by Thomas Harte on 24/04/2021. +// Copyright © 2021 Thomas Harte. All rights reserved. +// + +#include "SNA.hpp" + +using namespace Storage::State; + +std::unique_ptr SNA::load(const std::string &file_name) { + // 0x1a byte header: + // + // 00 I + // 01 HL' + // 03 DE' + // 05 BC' + // 07 AF' + // 09 HL + // 0B DE + // 0D BC + // 0F IY + // 11 IX + // 13 IFF2 (in bit 2) + // 14 R + // 15 AF + // 17 SP + // 19 interrupt mode + // 1A border colour + // 1B– 48kb RAM contents + + (void)file_name; + return nullptr; +} diff --git a/Storage/State/SNA.hpp b/Storage/State/SNA.hpp new file mode 100644 index 000000000..9afa703b0 --- /dev/null +++ b/Storage/State/SNA.hpp @@ -0,0 +1,24 @@ +// +// SNA.hpp +// Clock Signal +// +// Created by Thomas Harte on 24/04/2021. +// Copyright © 2021 Thomas Harte. All rights reserved. +// + +#ifndef SNA_hpp +#define SNA_hpp + +#include "../../Analyser/Static/StaticAnalyser.hpp" + +namespace Storage { +namespace State { + +struct SNA { + static std::unique_ptr load(const std::string &file_name); +}; + +} +} + +#endif /* SNA_hpp */