1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Merge pull request #400 from TomHarte/NewCrash

Introduces a rudimentary 'new' dialogue for the Mac
This commit is contained in:
Thomas Harte 2018-04-03 23:24:00 -04:00 committed by GitHub
commit 49feca4ddf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 906 additions and 89 deletions

View File

@ -6,8 +6,8 @@
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef Target_h
#define Target_h
#ifndef Analyser_Static_Acorn_Target_h
#define Analyser_Static_Acorn_Target_h
#include "../StaticAnalyser.hpp"
@ -25,4 +25,4 @@ struct Target: public ::Analyser::Static::Target {
}
}
#endif /* Target_h */
#endif /* Analyser_Static_Acorn_Target_h */

View File

@ -6,8 +6,8 @@
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef Target_h
#define Target_h
#ifndef Analyser_Static_AmstradCPC_Target_h
#define Analyser_Static_AmstradCPC_Target_h
#include "../StaticAnalyser.hpp"
@ -30,4 +30,4 @@ struct Target: public ::Analyser::Static::Target {
}
#endif /* Target_h */
#endif /* Analyser_Static_AmstradCPC_Target_h */

View File

@ -6,8 +6,8 @@
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef Target_h
#define Target_h
#ifndef Analyser_Static_Atari_Target_h
#define Analyser_Static_Atari_Target_h
#include "../StaticAnalyser.hpp"
@ -40,4 +40,4 @@ struct Target: public ::Analyser::Static::Target {
}
}
#endif /* Target_h */
#endif /* Analyser_Static_Atari_Target_h */

View File

@ -6,8 +6,8 @@
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef Target_h
#define Target_h
#ifndef Analyser_Static_Commodore_Target_h
#define Analyser_Static_Commodore_Target_h
#include "../StaticAnalyser.hpp"
@ -39,4 +39,4 @@ struct Target: public ::Analyser::Static::Target {
}
}
#endif /* Target_h */
#endif /* Analyser_Static_Commodore_Target_h */

View File

@ -10,6 +10,8 @@
#include "Cartridge.hpp"
#include "Tape.hpp"
#include "Target.hpp"
#include "../Disassembler/Z80.hpp"
#include "../Disassembler/AddressMapper.hpp"
@ -32,7 +34,7 @@ static std::unique_ptr<Analyser::Static::Target> CartridgeTarget(
output_segments.emplace_back(start_address, segment.data);
}
std::unique_ptr<Analyser::Static::Target> target(new Analyser::Static::Target);
std::unique_ptr<Analyser::Static::MSX::Target> target(new Analyser::Static::MSX::Target);
target->machine = Analyser::Machine::MSX;
target->confidence = confidence;
@ -259,9 +261,9 @@ static std::vector<std::unique_ptr<Analyser::Static::Target>> CartridgeTargetsFr
return targets;
}
void Analyser::Static::MSX::AddTargets(const Media &media, std::vector<std::unique_ptr<Target>> &destination) {
void Analyser::Static::MSX::AddTargets(const Media &media, std::vector<std::unique_ptr<::Analyser::Static::Target>> &destination) {
// Append targets for any cartridges that look correct.
std::vector<std::unique_ptr<Target>> cartridge_targets = CartridgeTargetsFrom(media.cartridges);
auto cartridge_targets = CartridgeTargetsFrom(media.cartridges);
std::move(cartridge_targets.begin(), cartridge_targets.end(), std::back_inserter(destination));
// Consider building a target for disks and/or tapes.
@ -283,6 +285,7 @@ void Analyser::Static::MSX::AddTargets(const Media &media, std::vector<std::uniq
// Blindly accept disks for now.
target->media.disks = media.disks;
target->has_disk_drive = !media.disks.empty();
if(!target->media.empty()) {
target->machine = Machine::MSX;

View File

@ -0,0 +1,26 @@
//
// Target.hpp
// Clock Signal
//
// Created by Thomas Harte on 02/04/2018.
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef Analyser_Static_MSX_Target_h
#define Analyser_Static_MSX_Target_h
#include "../StaticAnalyser.hpp"
namespace Analyser {
namespace Static {
namespace MSX {
struct Target: public ::Analyser::Static::Target {
bool has_disk_drive = false;
};
}
}
}
#endif /* Analyser_Static_MSX_Target_h */

View File

@ -134,17 +134,17 @@ void Analyser::Static::Oric::AddTargets(const Media &media, std::vector<std::uni
for(const auto &disk: media.disks) {
Storage::Encodings::MFM::Parser parser(true, disk);
if(IsMicrodisc(parser)) {
target->has_microdisc = true;
target->has_microdrive = true;
target->media.disks.push_back(disk);
}
}
} else {
target->has_microdisc = false;
target->has_microdrive = false;
}
// TODO: really this should add two targets if not all votes agree
target->use_atmos_rom = basic11_votes >= basic10_votes;
if(target->has_microdisc) target->use_atmos_rom = true;
if(target->has_microdrive) target->use_atmos_rom = true;
if(target->media.tapes.size() || target->media.disks.size() || target->media.cartridges.size())
destination.push_back(std::move(target));

View File

@ -6,8 +6,8 @@
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef Target_h
#define Target_h
#ifndef Analyser_Static_Oric_Target_h
#define Analyser_Static_Oric_Target_h
namespace Analyser {
namespace Static {
@ -15,11 +15,11 @@ namespace Oric {
struct Target: public ::Analyser::Static::Target {
bool use_atmos_rom = false;
bool has_microdisc = false;
bool has_microdrive = false;
};
}
}
}
#endif /* Target_h */
#endif /* Analyser_Static_Oric_Target_h */

View File

@ -40,11 +40,11 @@ void Analyser::Static::ZX8081::AddTargets(const Media &media, std::vector<std::u
// Guess the machine type from the file only if it isn't already known.
switch(potential_platforms & (TargetPlatform::ZX80 | TargetPlatform::ZX81)) {
default:
target->isZX81 = files.front().isZX81;
target->is_ZX81 = files.front().isZX81;
break;
case TargetPlatform::ZX80: target->isZX81 = false; break;
case TargetPlatform::ZX81: target->isZX81 = true; break;
case TargetPlatform::ZX80: target->is_ZX81 = false; break;
case TargetPlatform::ZX81: target->is_ZX81 = true; break;
}
/*if(files.front().data.size() > 16384) {
@ -57,7 +57,7 @@ void Analyser::Static::ZX8081::AddTargets(const Media &media, std::vector<std::u
target->media.tapes = media.tapes;
// TODO: how to run software once loaded? Might require a BASIC detokeniser.
if(target->isZX81) {
if(target->is_ZX81) {
target->loading_command = "J\"\"\n";
} else {
target->loading_command = "W\n";

View File

@ -6,8 +6,8 @@
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#ifndef Target_h
#define Target_h
#ifndef Analyser_Static_ZX8081_Target_h
#define Analyser_Static_ZX8081_Target_h
#include "../StaticAnalyser.hpp"
@ -23,11 +23,12 @@ struct Target: public ::Analyser::Static::Target {
};
MemoryModel memory_model = MemoryModel::Unexpanded;
bool isZX81 = false;
bool is_ZX81 = false;
bool ZX80_uses_ZX81_ROM = false;
};
}
}
}
#endif /* Target_h */
#endif /* Analyser_Static_ZX8081_Target_h */

View File

@ -40,6 +40,8 @@
#include "../../Configurable/StandardOptions.hpp"
#include "../../ClockReceiver/ForceInline.hpp"
#include "../../Analyser/Static/MSX/Target.hpp"
namespace MSX {
std::vector<std::unique_ptr<Configurable::Option>> get_options() {
@ -183,8 +185,10 @@ class ConcreteMachine:
}
void configure_as_target(const Analyser::Static::Target *target) override {
auto *const msx_target = dynamic_cast<const Analyser::Static::MSX::Target *>(target);
// Add a disk cartridge if any disks were supplied.
if(!target->media.disks.empty()) {
if(msx_target->has_disk_drive) {
map(2, 0, 0x4000, 0x2000);
unmap(2, 0x6000, 0x2000);
memory_slots_[2].set_handler(new DiskROM(memory_slots_[2].source));

View File

@ -271,7 +271,7 @@ class ConcreteMachine:
void configure_as_target(const Analyser::Static::Target *target) override final {
auto *const oric_target = dynamic_cast<const Analyser::Static::Oric::Target *>(target);
if(oric_target->has_microdisc) {
if(oric_target->has_microdrive) {
microdisc_is_enabled_ = true;
microdisc_did_change_paging_flags(&microdisc_);
microdisc_.set_delegate(this);

View File

@ -285,7 +285,7 @@ template<bool is_zx81> class ConcreteMachine:
void configure_as_target(const Analyser::Static::Target *target) override final {
auto *const zx8081_target = dynamic_cast<const Analyser::Static::ZX8081::Target *>(target);
is_zx81_ = zx8081_target->isZX81;
is_zx81_ = zx8081_target->is_ZX81;
if(is_zx81_) {
rom_ = zx81_rom_;
tape_trap_address_ = 0x37c;
@ -295,7 +295,7 @@ template<bool is_zx81> class ConcreteMachine:
automatic_tape_motor_start_address_ = 0x0340;
automatic_tape_motor_end_address_ = 0x03c3;
} else {
rom_ = zx80_rom_;
rom_ = zx8081_target->ZX80_uses_ZX81_ROM ? zx81_rom_ : zx80_rom_;
tape_trap_address_ = 0x220;
tape_return_address_ = 0x248;
vsync_start_ = HalfCycles(26);
@ -528,7 +528,7 @@ Machine *Machine::ZX8081(const Analyser::Static::Target *target_hint) {
const Analyser::Static::ZX8081::Target *const hint = dynamic_cast<const Analyser::Static::ZX8081::Target *>(target_hint);
// Instantiate the correct type of machine.
if(hint->isZX81)
if(hint->is_ZX81)
return new ZX8081::ConcreteMachine<true>();
else
return new ZX8081::ConcreteMachine<false>();

View File

@ -291,6 +291,8 @@
4B9BE400203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */; };
4B9BE401203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */; };
4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */; };
4BA141BD2072E8A500A31EC9 /* MachinePicker.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BA141BB2072E8A400A31EC9 /* MachinePicker.xib */; };
4BA141BF2072E8AF00A31EC9 /* MachinePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BA141BE2072E8AF00A31EC9 /* MachinePicker.swift */; };
4BA61EB01D91515900B3C876 /* NSData+StdVector.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA61EAF1D91515900B3C876 /* NSData+StdVector.mm */; };
4BAD13441FF709C700FD114A /* MSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0E61051FF34737002A9DBD /* MSX.cpp */; };
4BAE49582032881E004BE78E /* CSZX8081.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B14978E1EE4B4D200CE2596 /* CSZX8081.mm */; };
@ -975,6 +977,9 @@
4B9BE3FF203A0C0600FFAE60 /* MultiSpeaker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MultiSpeaker.hpp; sourceTree = "<group>"; };
4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ZX8081.cpp; path = Data/ZX8081.cpp; sourceTree = "<group>"; };
4BA0F68D1EEA0E8400E9489E /* ZX8081.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ZX8081.hpp; path = Data/ZX8081.hpp; sourceTree = "<group>"; };
4BA141BC2072E8A400A31EC9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MachinePicker.xib; sourceTree = "<group>"; };
4BA141BE2072E8AF00A31EC9 /* MachinePicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MachinePicker.swift; sourceTree = "<group>"; };
4BA141C12073100800A31EC9 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
4BA61EAE1D91515900B3C876 /* NSData+StdVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+StdVector.h"; sourceTree = "<group>"; };
4BA61EAF1D91515900B3C876 /* NSData+StdVector.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSData+StdVector.mm"; sourceTree = "<group>"; };
4BA9C3CF1D8164A9002DDB61 /* ConfigurationTarget.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ConfigurationTarget.hpp; sourceTree = "<group>"; };
@ -2235,6 +2240,7 @@
4B047075201ABC180047AB0D /* Cartridge.hpp */,
4B894510201967B4007DE474 /* StaticAnalyser.hpp */,
4B894511201967B4007DE474 /* Tape.hpp */,
4BA141C12073100800A31EC9 /* Target.hpp */,
);
path = MSX;
sourceTree = "<group>";
@ -2259,6 +2265,16 @@
path = Implementation;
sourceTree = "<group>";
};
4BA141C02072E8B300A31EC9 /* MachinePicker */ = {
isa = PBXGroup;
children = (
4BA141BE2072E8AF00A31EC9 /* MachinePicker.swift */,
4BA141BB2072E8A400A31EC9 /* MachinePicker.xib */,
);
name = MachinePicker;
path = "New Group";
sourceTree = "<group>";
};
4BAB62AA1D3272D200DF5BA0 /* Disk */ = {
isa = PBXGroup;
children = (
@ -2622,11 +2638,12 @@
4BB73EAD1B587A5100552FC2 /* Info.plist */,
4BB73EA11B587A5100552FC2 /* AppDelegate.swift */,
4BB73EA81B587A5100552FC2 /* Assets.xcassets */,
4BB73EAA1B587A5100552FC2 /* MainMenu.xib */,
4B2A538F1D117D36003C6002 /* Audio */,
4B643F3D1D77B88000D431D6 /* Document Controller */,
4B55CE551C3B7D360093A61B /* Documents */,
4B2A53921D117D36003C6002 /* Machine */,
4BA141C02072E8B300A31EC9 /* MachinePicker */,
4BB73EAA1B587A5100552FC2 /* MainMenu.xib */,
4BE5F85A1C3E1C2500C43F01 /* Resources */,
4BD5F1961D1352A000631CD1 /* Updater */,
4B55CE5A1C3B7D6F0093A61B /* Views */,
@ -3114,6 +3131,7 @@
4B2C45421E3C3896002A2389 /* cartridge.png in Resources */,
4BB73EA91B587A5100552FC2 /* Assets.xcassets in Resources */,
4B79E4451E3AF38600141F11 /* floppy35.png in Resources */,
4BA141BD2072E8A500A31EC9 /* MachinePicker.xib in Resources */,
4B1EDB451E39A0AC009D6819 /* chip.png in Resources */,
4B2A332D1DB86821002876E3 /* OricOptions.xib in Resources */,
4BD61664206B2AC800236112 /* QuickLoadOptions.xib in Resources */,
@ -3650,6 +3668,7 @@
4B71368E1F788112008B8ED9 /* Parser.cpp in Sources */,
4B12C0ED1FCFA98D005BFD93 /* Keyboard.cpp in Sources */,
4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */,
4BA141BF2072E8AF00A31EC9 /* MachinePicker.swift in Sources */,
4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */,
4BD3A30B1EE755C800B5B501 /* Video.cpp in Sources */,
4BBF99141C8FBA6F0075DAFB /* TextureBuilder.cpp in Sources */,
@ -3829,6 +3848,14 @@
name = QuickLoadCompositeOptions.xib;
sourceTree = "<group>";
};
4BA141BB2072E8A400A31EC9 /* MachinePicker.xib */ = {
isa = PBXVariantGroup;
children = (
4BA141BC2072E8A400A31EC9 /* Base */,
);
name = MachinePicker.xib;
sourceTree = "<group>";
};
4BB73EAA1B587A5100552FC2 /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (

View File

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="16A323" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14109"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="Vic20Document" customModule="Clock_Signal" customModuleProvider="target">
<customObject id="-2" userLabel="File's Owner" customClass="MachineDocument" customModule="Clock_Signal" customModuleProvider="target">
<connections>
<outlet property="openGLView" destination="DEG-fq-cjd" id="Gxs-2u-n7B"/>
<outlet property="window" destination="xOd-HO-29H" id="JIz-fz-R2o"/>
@ -23,7 +25,7 @@
<rect key="frame" x="0.0" y="0.0" width="400" height="300"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<openGLView useAuxiliaryDepthBufferStencil="NO" allowOffline="YES" wantsBestResolutionOpenGLSurface="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DEG-fq-cjd" customClass="CSOpenGLView">
<openGLView hidden="YES" useAuxiliaryDepthBufferStencil="NO" allowOffline="YES" wantsBestResolutionOpenGLSurface="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DEG-fq-cjd" customClass="CSOpenGLView">
<rect key="frame" x="0.0" y="0.0" width="400" height="300"/>
</openGLView>
</subviews>

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9532" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9532"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14109"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@ -93,30 +94,30 @@
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
</connections>
</menuItem>
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
<menuItem title="Save…" enabled="NO" keyEquivalent="s" id="pxx-59-PXV">
<connections>
<action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
</connections>
</menuItem>
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
<menuItem title="Save As…" enabled="NO" keyEquivalent="S" id="Bw7-FT-i3A">
<connections>
<action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
</connections>
</menuItem>
<menuItem title="Revert to Saved" id="KaW-ft-85H">
<menuItem title="Revert to Saved" enabled="NO" id="KaW-ft-85H">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
<menuItem title="Page Setup…" enabled="NO" keyEquivalent="P" id="qIS-W8-SiK">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
</connections>
</menuItem>
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
<menuItem title="Print…" enabled="NO" keyEquivalent="p" id="aTl-1u-JFS">
<connections>
<action selector="printDocument:" target="-1" id="qaZ-4w-aoO"/>
</connections>
@ -128,23 +129,23 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
<items>
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
<menuItem title="Undo" enabled="NO" keyEquivalent="z" id="dRJ-4n-Yzg">
<connections>
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
<menuItem title="Redo" enabled="NO" keyEquivalent="Z" id="6dh-zS-Vam">
<connections>
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
<menuItem title="Cut" enabled="NO" keyEquivalent="x" id="uRl-iY-unG">
<connections>
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
</connections>
</menuItem>
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
<menuItem title="Copy" enabled="NO" keyEquivalent="c" id="x3v-GG-iWU">
<connections>
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
</connections>
@ -154,19 +155,19 @@
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
<menuItem title="Paste and Match Style" enabled="NO" keyEquivalent="V" id="WeT-3V-zwk">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
</connections>
</menuItem>
<menuItem title="Delete" id="pa3-QI-u2k">
<menuItem title="Delete" enabled="NO" id="pa3-QI-u2k">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
<menuItem title="Select All" enabled="NO" keyEquivalent="a" id="Ruw-6m-B2m">
<connections>
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
</connections>

View File

@ -28,6 +28,7 @@ class MachineDocument:
return nil
}
}
var optionsPanelNibName: String?
func aspectRatio() -> NSSize {
return NSSize(width: 4.0, height: 3.0)
@ -48,30 +49,57 @@ class MachineDocument:
override func windowControllerDidLoadNib(_ aController: NSWindowController) {
super.windowControllerDidLoadNib(aController)
aController.window?.contentAspectRatio = self.aspectRatio()
setupMachineOutput()
// establish the output aspect ratio and audio
let displayAspectRatio = self.aspectRatio()
aController.window?.contentAspectRatio = displayAspectRatio
openGLView.perform(glContext: {
self.machine.setView(self.openGLView, aspectRatio: Float(displayAspectRatio.width / displayAspectRatio.height))
})
}
self.machine.delegate = self
self.bestEffortUpdater = CSBestEffortUpdater()
// Attempting to show a sheet before the window is visible (such as when the NIB is loaded) results in
// a sheet mysteriously floating on its own. For now, use windowDidUpdate as a proxy to know that the window
// is visible, though it's a little premature.
func windowDidUpdate(_ notification: Notification) {
if self.shouldShowNewMachinePanel {
self.shouldShowNewMachinePanel = false
Bundle.main.loadNibNamed(NSNib.Name(rawValue: "MachinePicker"), owner: self, topLevelObjects: nil)
self.machinePicker?.establishStoredOptions()
self.windowControllers[0].window?.beginSheet(self.machinePickerPanel!, completionHandler: nil)
}
}
// callbacks from the OpenGL may come on a different thread, immediately following the .delegate set;
// hence the full setup of the best-effort updater prior to setting self as a delegate
self.openGLView.delegate = self
self.openGLView.responderDelegate = self
fileprivate func setupMachineOutput() {
if let machine = self.machine, let openGLView = self.openGLView {
// establish the output aspect ratio and audio
let aspectRatio = self.aspectRatio()
openGLView.perform(glContext: {
machine.setView(openGLView, aspectRatio: Float(aspectRatio.width / aspectRatio.height))
})
setupAudioQueueClockRate()
self.optionsPanel?.establishStoredOptions()
// attach an options panel if one is available
if let optionsPanelNibName = self.optionsPanelNibName {
Bundle.main.loadNibNamed(NSNib.Name(rawValue: optionsPanelNibName), owner: self, topLevelObjects: nil)
self.optionsPanel.machine = machine
self.optionsPanel?.establishStoredOptions()
showOptions(self)
}
// bring OpenGL view-holding window on top of the options panel
self.openGLView.window!.makeKeyAndOrderFront(self)
machine.delegate = self
self.bestEffortUpdater = CSBestEffortUpdater()
// start accepting best effort updates
self.bestEffortUpdater!.delegate = self
// callbacks from the OpenGL may come on a different thread, immediately following the .delegate set;
// hence the full setup of the best-effort updater prior to setting self as a delegate
openGLView.delegate = self
openGLView.responderDelegate = self
setupAudioQueueClockRate()
// bring OpenGL view-holding window on top of the options panel and show the content
openGLView.isHidden = false
openGLView.window!.makeKeyAndOrderFront(self)
openGLView.window!.makeFirstResponder(openGLView)
// start accepting best effort updates
self.bestEffortUpdater!.delegate = self
}
}
func machineSpeakerDidChangeInputClock(_ machine: CSMachine!) {
@ -95,9 +123,11 @@ class MachineDocument:
optionsPanel = nil
bestEffortLock.lock()
bestEffortUpdater!.delegate = nil
bestEffortUpdater!.flush()
bestEffortUpdater = nil
if let bestEffortUpdater = bestEffortUpdater {
bestEffortUpdater.delegate = nil
bestEffortUpdater.flush()
self.bestEffortUpdater = nil
}
bestEffortLock.unlock()
actionLock.lock()
@ -115,15 +145,12 @@ class MachineDocument:
func configureAs(_ analysis: CSStaticAnalyser) {
if let machine = CSMachine(analyser: analysis) {
self.machine = machine
}
if let optionsPanelNibName = analysis.optionsPanelNibName {
Bundle.main.loadNibNamed(NSNib.Name(rawValue: optionsPanelNibName), owner: self, topLevelObjects: nil)
self.optionsPanel.machine = self.machine
showOptions(self)
self.optionsPanelNibName = analysis.optionsPanelNibName
setupMachineOutput()
}
}
fileprivate var shouldShowNewMachinePanel = false
override func read(from url: URL, ofType typeName: String) throws {
if let analyser = CSStaticAnalyser(fileAt: url) {
self.displayName = analyser.displayName
@ -133,6 +160,12 @@ class MachineDocument:
}
}
convenience init(type typeName: String) throws {
self.init()
self.fileType = typeName
self.shouldShowNewMachinePanel = true
}
// MARK: the pasteboard
func paste(_ sender: AnyObject!) {
let pasteboard = NSPasteboard.general
@ -185,21 +218,42 @@ class MachineDocument:
// MARK: Input management
func windowDidResignKey(_ notification: Notification) {
self.machine.clearAllKeys()
if let machine = self.machine {
machine.clearAllKeys()
}
}
func keyDown(_ event: NSEvent) {
self.machine.setKey(event.keyCode, characters: event.characters, isPressed: true)
if let machine = self.machine {
machine.setKey(event.keyCode, characters: event.characters, isPressed: true)
}
}
func keyUp(_ event: NSEvent) {
self.machine.setKey(event.keyCode, characters: event.characters, isPressed: false)
if let machine = self.machine {
machine.setKey(event.keyCode, characters: event.characters, isPressed: false)
}
}
func flagsChanged(_ newModifiers: NSEvent) {
self.machine.setKey(VK_Shift, characters: nil, isPressed: newModifiers.modifierFlags.contains(.shift))
self.machine.setKey(VK_Control, characters: nil, isPressed: newModifiers.modifierFlags.contains(.control))
self.machine.setKey(VK_Command, characters: nil, isPressed: newModifiers.modifierFlags.contains(.command))
self.machine.setKey(VK_Option, characters: nil, isPressed: newModifiers.modifierFlags.contains(.option))
if let machine = self.machine {
machine.setKey(VK_Shift, characters: nil, isPressed: newModifiers.modifierFlags.contains(.shift))
machine.setKey(VK_Control, characters: nil, isPressed: newModifiers.modifierFlags.contains(.control))
machine.setKey(VK_Command, characters: nil, isPressed: newModifiers.modifierFlags.contains(.command))
machine.setKey(VK_Option, characters: nil, isPressed: newModifiers.modifierFlags.contains(.option))
}
}
// MARK: New machine creation
@IBOutlet var machinePicker: MachinePicker?
@IBOutlet var machinePickerPanel: NSWindow?
@IBAction func createMachine(_ sender: NSButton?) {
self.configureAs(machinePicker!.selectedMachine())
machinePicker = nil
sender?.window?.close()
}
@IBAction func cancelCreateMachine(_ sender: NSButton?) {
close()
}
}

View File

@ -10,10 +10,39 @@
@class CSMachine;
typedef NS_ENUM(NSInteger, CSMachineCPCModel) {
CSMachineCPCModel464,
CSMachineCPCModel664,
CSMachineCPCModel6128
};
typedef NS_ENUM(NSInteger, CSMachineOricModel) {
CSMachineOricModelOric1,
CSMachineOricModelOricAtmos
};
typedef NS_ENUM(NSInteger, CSMachineVic20Region) {
CSMachineVic20RegionAmerican,
CSMachineVic20RegionEuropean,
CSMachineVic20RegionDanish,
CSMachineVic20RegionSwedish,
CSMachineVic20RegionJapanese,
};
typedef int Kilobytes;
@interface CSStaticAnalyser : NSObject
- (instancetype)initWithFileAtURL:(NSURL *)url;
- (instancetype)initWithElectronDFS:(BOOL)dfs adfs:(BOOL)adfs;
- (instancetype)initWithAmstradCPCModel:(CSMachineCPCModel)model;
- (instancetype)initWithMSXHasDiskDrive:(BOOL)hasDiskDrive;
- (instancetype)initWithOricModel:(CSMachineOricModel)model hasMicrodrive:(BOOL)hasMicrodrive;
- (instancetype)initWithVic20Region:(CSMachineVic20Region)region memorySize:(Kilobytes)memorySize hasC1540:(BOOL)hasC1540;
- (instancetype)initWithZX80MemorySize:(Kilobytes)memorySize useZX81ROM:(BOOL)useZX81ROM;
- (instancetype)initWithZX81MemorySize:(Kilobytes)memorySize;
@property(nonatomic, readonly) NSString *optionsPanelNibName;
@property(nonatomic, readonly) NSString *displayName;

View File

@ -13,6 +13,13 @@
#include "StaticAnalyser.hpp"
#include "../../../../../Analyser/Static/Acorn/Target.hpp"
#include "../../../../../Analyser/Static/AmstradCPC/Target.hpp"
#include "../../../../../Analyser/Static/Commodore/Target.hpp"
#include "../../../../../Analyser/Static/MSX/Target.hpp"
#include "../../../../../Analyser/Static/Oric/Target.hpp"
#include "../../../../../Analyser/Static/ZX8081/Target.hpp"
#import "Clock_Signal-Swift.h"
@implementation CSStaticAnalyser {
@ -32,6 +39,120 @@
return self;
}
- (instancetype)initWithElectronDFS:(BOOL)dfs adfs:(BOOL)adfs {
self = [super init];
if(self) {
using Target = Analyser::Static::Acorn::Target;
std::unique_ptr<Target> target(new Target);
target->machine = Analyser::Machine::Electron;
target->has_dfs = !!dfs;
target->has_adfs = !!adfs;
_targets.push_back(std::move(target));
}
return self;
}
- (instancetype)initWithAmstradCPCModel:(CSMachineCPCModel)model {
self = [super init];
if(self) {
using Target = Analyser::Static::AmstradCPC::Target;
std::unique_ptr<Target> target(new Target);
target->machine = Analyser::Machine::AmstradCPC;
switch(model) {
case CSMachineCPCModel464: target->model = Analyser::Static::AmstradCPC::Target::Model::CPC464; break;
case CSMachineCPCModel664: target->model = Analyser::Static::AmstradCPC::Target::Model::CPC664; break;
case CSMachineCPCModel6128: target->model = Analyser::Static::AmstradCPC::Target::Model::CPC6128; break;
}
_targets.push_back(std::move(target));
}
return self;
}
- (instancetype)initWithMSXHasDiskDrive:(BOOL)hasDiskDrive {
self = [super init];
if(self) {
using Target = Analyser::Static::MSX::Target;
std::unique_ptr<Target> target(new Target);
target->machine = Analyser::Machine::MSX;
target->has_disk_drive = !!hasDiskDrive;
_targets.push_back(std::move(target));
}
return self;
}
- (instancetype)initWithOricModel:(CSMachineOricModel)model hasMicrodrive:(BOOL)hasMicrodrive {
self = [super init];
if(self) {
using Target = Analyser::Static::Oric::Target;
std::unique_ptr<Target> target(new Target);
target->machine = Analyser::Machine::Oric;
target->use_atmos_rom = (model == CSMachineOricModelOricAtmos);
target->has_microdrive = !!hasMicrodrive;
_targets.push_back(std::move(target));
}
return self;
}
- (instancetype)initWithVic20Region:(CSMachineVic20Region)region memorySize:(Kilobytes)memorySize hasC1540:(BOOL)hasC1540 {
self = [super init];
if(self) {
using Target = Analyser::Static::Commodore::Target;
std::unique_ptr<Target> target(new Target);
target->machine = Analyser::Machine::Vic20;
switch(region) {
case CSMachineVic20RegionDanish: target->region = Target::Region::Danish; break;
case CSMachineVic20RegionSwedish: target->region = Target::Region::Swedish; break;
case CSMachineVic20RegionAmerican: target->region = Target::Region::American; break;
case CSMachineVic20RegionEuropean: target->region = Target::Region::European; break;
case CSMachineVic20RegionJapanese: target->region = Target::Region::Japanese; break;
}
switch(memorySize) {
default: target->memory_model = Target::MemoryModel::Unexpanded; break;
case 8: target->memory_model = Target::MemoryModel::EightKB; break;
case 32: target->memory_model = Target::MemoryModel::ThirtyTwoKB; break;
}
target->has_c1540 = !!hasC1540;
_targets.push_back(std::move(target));
}
return self;
}
static Analyser::Static::ZX8081::Target::MemoryModel ZX8081MemoryModelFromSize(Kilobytes size) {
using MemoryModel = Analyser::Static::ZX8081::Target::MemoryModel;
switch(size) {
default: return MemoryModel::Unexpanded;
case 16: return MemoryModel::SixteenKB;
case 64: return MemoryModel::SixtyFourKB;
}
}
- (instancetype)initWithZX80MemorySize:(Kilobytes)memorySize useZX81ROM:(BOOL)useZX81ROM {
self = [super init];
if(self) {
using Target = Analyser::Static::ZX8081::Target;
std::unique_ptr<Target> target(new Target);
target->machine = Analyser::Machine::ZX8081;
target->is_ZX81 = false;
target->ZX80_uses_ZX81_ROM = !!useZX81ROM;
target->memory_model = ZX8081MemoryModelFromSize(memorySize);
_targets.push_back(std::move(target));
}
return self;
}
- (instancetype)initWithZX81MemorySize:(Kilobytes)memorySize {
self = [super init];
if(self) {
using Target = Analyser::Static::ZX8081::Target;
std::unique_ptr<Target> target(new Target);
target->machine = Analyser::Machine::ZX8081;
target->is_ZX81 = true;
target->memory_model = ZX8081MemoryModelFromSize(memorySize);
_targets.push_back(std::move(target));
}
return self;
}
- (NSString *)optionsPanelNibName {
switch(_targets.front()->machine) {
case Analyser::Machine::AmstradCPC: return nil;

View File

@ -0,0 +1,388 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14109"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="MachineDocument" customModule="Clock_Signal" customModuleProvider="target">
<connections>
<outlet property="machinePicker" destination="192-Eb-Rpg" id="7p2-GL-AVt"/>
<outlet property="machinePickerPanel" destination="QvC-M9-y7g" id="PMF-8q-M3s"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" titleVisibility="hidden" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" documentModal="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="562" height="129"/>
<rect key="screenRect" x="0.0" y="0.0" width="1366" height="768"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="562" height="205"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<tabView translatesAutoresizingMaskIntoConstraints="NO" id="VUb-QG-x7c">
<rect key="frame" x="13" y="51" width="536" height="140"/>
<font key="font" metaFont="system"/>
<tabViewItems>
<tabViewItem label="Acorn Electron" identifier="electron" id="muc-z9-Vqc">
<view key="view" id="SRc-2D-95G">
<rect key="frame" x="10" y="33" width="516" height="92"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JqM-IK-FMP">
<rect key="frame" x="15" y="73" width="164" height="18"/>
<buttonCell key="cell" type="check" title="With Disk Filing System" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="tpW-5C-xKp">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="945-wU-JOH">
<rect key="frame" x="15" y="53" width="228" height="18"/>
<buttonCell key="cell" type="check" title="With Advanced Disk Filing System" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="S0c-Jg-7Pu">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
</subviews>
<constraints>
<constraint firstItem="945-wU-JOH" firstAttribute="leading" secondItem="SRc-2D-95G" secondAttribute="leading" constant="17" id="1iM-70-oZq"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="945-wU-JOH" secondAttribute="bottom" constant="17" id="7ZL-rR-aaz"/>
<constraint firstItem="JqM-IK-FMP" firstAttribute="leading" secondItem="SRc-2D-95G" secondAttribute="leading" constant="17" id="NfY-dE-aJw"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="945-wU-JOH" secondAttribute="trailing" constant="20" id="dmY-PV-ap4"/>
<constraint firstItem="JqM-IK-FMP" firstAttribute="top" secondItem="SRc-2D-95G" secondAttribute="top" constant="3" id="ggl-QH-mV4"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="JqM-IK-FMP" secondAttribute="trailing" constant="20" id="mvO-UZ-BtT"/>
<constraint firstItem="945-wU-JOH" firstAttribute="top" secondItem="JqM-IK-FMP" secondAttribute="bottom" constant="6" id="pes-xi-zkv"/>
</constraints>
</view>
</tabViewItem>
<tabViewItem label="Amstrad CPC" identifier="cpc" id="JmB-OF-xcM">
<view key="view" id="5zS-Nj-Ynx">
<rect key="frame" x="10" y="33" width="516" height="92"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="00d-sg-Krh">
<rect key="frame" x="54" y="65" width="94" height="26"/>
<popUpButtonCell key="cell" type="push" title="CPC6128" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="6128" imageScaling="proportionallyDown" inset="2" selectedItem="klh-ZE-Agp" id="hVJ-h6-iea">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="r3D-C2-Ruq">
<items>
<menuItem title="CPC464" tag="464" id="5kZ-XF-RFl"/>
<menuItem title="CPC664" tag="664" id="Sct-ZX-Qp1"/>
<menuItem title="CPC6128" state="on" tag="6128" id="klh-ZE-Agp"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="q9q-sl-J0q">
<rect key="frame" x="8" y="70" width="42" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model" id="Cw3-q5-1bC">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="00d-sg-Krh" secondAttribute="trailing" constant="17" id="4AF-5C-2IF"/>
<constraint firstItem="00d-sg-Krh" firstAttribute="top" secondItem="5zS-Nj-Ynx" secondAttribute="top" constant="3" id="4U2-iE-UFM"/>
<constraint firstItem="q9q-sl-J0q" firstAttribute="leading" secondItem="5zS-Nj-Ynx" secondAttribute="leading" constant="10" id="Wof-5h-gfD"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="00d-sg-Krh" secondAttribute="bottom" constant="17" id="enU-LN-Nep"/>
<constraint firstItem="00d-sg-Krh" firstAttribute="leading" secondItem="q9q-sl-J0q" secondAttribute="trailing" constant="8" id="mA8-US-ndo"/>
<constraint firstItem="q9q-sl-J0q" firstAttribute="centerY" secondItem="00d-sg-Krh" secondAttribute="centerY" id="vA8-IA-Uwf"/>
</constraints>
</view>
</tabViewItem>
<tabViewItem label="MSX" identifier="msx" id="6SR-DY-zdI">
<view key="view" id="mWD-An-tR7">
<rect key="frame" x="10" y="33" width="516" height="92"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8xT-Pr-8SE">
<rect key="frame" x="15" y="73" width="124" height="18"/>
<buttonCell key="cell" type="check" title="Attach disk drive" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="CB3-nA-VTM">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
</subviews>
<constraints>
<constraint firstItem="8xT-Pr-8SE" firstAttribute="top" secondItem="mWD-An-tR7" secondAttribute="top" constant="3" id="CPl-8F-YcG"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="8xT-Pr-8SE" secondAttribute="trailing" constant="17" id="l8P-UW-8ig"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="8xT-Pr-8SE" secondAttribute="bottom" constant="17" id="mga-YX-Bek"/>
<constraint firstItem="8xT-Pr-8SE" firstAttribute="leading" secondItem="mWD-An-tR7" secondAttribute="leading" constant="17" id="q8Q-kh-Opj"/>
</constraints>
</view>
</tabViewItem>
<tabViewItem label="Oric" identifier="oric" id="NSx-DC-p4M">
<view key="view" id="sOR-e0-8iZ">
<rect key="frame" x="10" y="33" width="516" height="92"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mZw-PY-0Yv">
<rect key="frame" x="15" y="46" width="129" height="18"/>
<buttonCell key="cell" type="check" title="Attach Microdrive" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Wl2-KO-smb">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0ct-tf-uRH">
<rect key="frame" x="17" y="72" width="42" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model" id="Xm1-7x-YVl">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ENP-hI-BVZ">
<rect key="frame" x="63" y="67" width="105" height="26"/>
<popUpButtonCell key="cell" type="push" title="Oric-1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="1" imageScaling="proportionallyDown" inset="2" selectedItem="jGN-1a-biF" id="Jll-EJ-cMr">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="E9d-fH-Eak">
<items>
<menuItem title="Oric-1" state="on" tag="1" id="jGN-1a-biF"/>
<menuItem title="Oric Atmos" tag="2" id="p5O-Jq-Tft"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
</subviews>
<constraints>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="mZw-PY-0Yv" secondAttribute="bottom" constant="17" id="74q-Nf-cCV"/>
<constraint firstItem="ENP-hI-BVZ" firstAttribute="top" secondItem="sOR-e0-8iZ" secondAttribute="top" constant="1" id="Bgq-8R-8I4"/>
<constraint firstItem="mZw-PY-0Yv" firstAttribute="top" secondItem="ENP-hI-BVZ" secondAttribute="bottom" constant="8" id="Mjq-84-vdN"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="ENP-hI-BVZ" secondAttribute="trailing" constant="17" id="Sr5-QZ-xU3"/>
<constraint firstItem="ENP-hI-BVZ" firstAttribute="leading" secondItem="0ct-tf-uRH" secondAttribute="trailing" constant="8" id="Wcg-1P-z6l"/>
<constraint firstItem="0ct-tf-uRH" firstAttribute="centerY" secondItem="ENP-hI-BVZ" secondAttribute="centerY" id="e8Q-nY-gIr"/>
<constraint firstItem="mZw-PY-0Yv" firstAttribute="leading" secondItem="sOR-e0-8iZ" secondAttribute="leading" constant="17" id="equ-PG-WAg"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="mZw-PY-0Yv" secondAttribute="trailing" constant="17" id="erm-Kw-icY"/>
<constraint firstItem="0ct-tf-uRH" firstAttribute="leading" secondItem="sOR-e0-8iZ" secondAttribute="leading" constant="19" id="huH-9L-97Y"/>
</constraints>
</view>
</tabViewItem>
<tabViewItem label="Vic-20" identifier="vic20" id="cyO-PU-hSU">
<view key="view" id="fLI-XB-QCr">
<rect key="frame" x="10" y="33" width="516" height="94"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ueK-gq-gaF">
<rect key="frame" x="67" y="67" width="144" height="26"/>
<popUpButtonCell key="cell" type="push" title="European (PAL)" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="45i-0n-gau" id="yi7-eo-I0q">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="uCQ-9l-eBb">
<items>
<menuItem title="European (PAL)" state="on" id="45i-0n-gau"/>
<menuItem title="American (NTSC)" tag="1" id="jNT-iG-JUR"/>
<menuItem title="Danish (PAL)" tag="2" id="IpZ-Wv-lEe"/>
<menuItem title="Swedish (PAL)" tag="3" id="7x0-gL-mKG"/>
<menuItem title="Japanese (NTSC)" tag="4" id="kyq-LZ-O2M"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2eV-Us-eEv">
<rect key="frame" x="102" y="36" width="114" height="26"/>
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="fOl-8Q-fsA" id="rH0-7T-pJE">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="e9J-Ie-PjH">
<items>
<menuItem title="Unexpanded" state="on" id="fOl-8Q-fsA"/>
<menuItem title="8 kb" tag="8" id="hEJ-yK-WZQ"/>
<menuItem title="32 kb" tag="32" id="8E5-8M-aTA"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MTh-9p-FqC">
<rect key="frame" x="17" y="72" width="46" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Region" id="F3g-Ya-ypU">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gRS-DK-rIy">
<rect key="frame" x="15" y="41" width="83" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Memory Size" id="a4I-vG-yCp">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Lrf-gL-6EI">
<rect key="frame" x="15" y="15" width="173" height="18"/>
<buttonCell key="cell" type="check" title="Attach C-1540 disk drive" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="tsq-YD-xw8">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
</subviews>
<constraints>
<constraint firstItem="Lrf-gL-6EI" firstAttribute="leading" secondItem="fLI-XB-QCr" secondAttribute="leading" constant="17" id="2Sb-f9-Qim"/>
<constraint firstItem="MTh-9p-FqC" firstAttribute="centerY" secondItem="ueK-gq-gaF" secondAttribute="centerY" id="8KD-Bm-KRA"/>
<constraint firstItem="ueK-gq-gaF" firstAttribute="leading" secondItem="MTh-9p-FqC" secondAttribute="trailing" constant="8" id="9m6-6j-8j2"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Lrf-gL-6EI" secondAttribute="trailing" constant="17" id="M08-mP-Plz"/>
<constraint firstItem="ueK-gq-gaF" firstAttribute="top" secondItem="fLI-XB-QCr" secondAttribute="top" constant="3" id="XN3-GK-BX9"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="ueK-gq-gaF" secondAttribute="trailing" constant="17" id="YZ9-7N-ssA"/>
<constraint firstItem="MTh-9p-FqC" firstAttribute="leading" secondItem="fLI-XB-QCr" secondAttribute="leading" constant="19" id="bgZ-k9-IQC"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="2eV-Us-eEv" secondAttribute="trailing" constant="17" id="eiB-vH-17d"/>
<constraint firstItem="2eV-Us-eEv" firstAttribute="top" secondItem="ueK-gq-gaF" secondAttribute="bottom" constant="10" id="flM-aa-vxB"/>
<constraint firstItem="2eV-Us-eEv" firstAttribute="leading" secondItem="gRS-DK-rIy" secondAttribute="trailing" constant="8" id="hQ9-uy-KHg"/>
<constraint firstItem="gRS-DK-rIy" firstAttribute="leading" secondItem="fLI-XB-QCr" secondAttribute="leading" constant="17" id="iyp-1K-rdC"/>
<constraint firstItem="gRS-DK-rIy" firstAttribute="centerY" secondItem="2eV-Us-eEv" secondAttribute="centerY" id="qWf-Nb-PfJ"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="Lrf-gL-6EI" secondAttribute="bottom" constant="17" id="vNb-Sw-Mxw"/>
<constraint firstItem="Lrf-gL-6EI" firstAttribute="top" secondItem="2eV-Us-eEv" secondAttribute="bottom" constant="8" id="zBX-Qq-j5f"/>
</constraints>
</view>
</tabViewItem>
<tabViewItem label="ZX80" identifier="zx80" id="tMH-kF-GUz">
<view key="view" id="8hL-Vn-Hg0">
<rect key="frame" x="10" y="33" width="516" height="92"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="I1a-Eu-5UB">
<rect key="frame" x="102" y="65" width="114" height="26"/>
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="4Sa-jR-xOd" id="B8M-do-Yod">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="Of4-DY-mE5">
<items>
<menuItem title="Unexpanded" state="on" id="4Sa-jR-xOd"/>
<menuItem title="16 kb" tag="16" id="bWl-oP-jGn"/>
<menuItem title="64 kb" tag="64" id="WNJ-kT-TYn"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="NCX-4e-lSu">
<rect key="frame" x="15" y="70" width="83" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Memory Size" id="e6x-TE-OC5">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ReP-bV-Thu">
<rect key="frame" x="15" y="46" width="114" height="18"/>
<buttonCell key="cell" type="check" title="Use ZX81 ROM" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="VQH-nv-Pfm">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
</subviews>
<constraints>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="I1a-Eu-5UB" secondAttribute="trailing" constant="17" id="0eZ-Nf-Vli"/>
<constraint firstItem="NCX-4e-lSu" firstAttribute="centerY" secondItem="I1a-Eu-5UB" secondAttribute="centerY" id="1ve-sc-QwI"/>
<constraint firstItem="I1a-Eu-5UB" firstAttribute="leading" secondItem="NCX-4e-lSu" secondAttribute="trailing" constant="8" id="Bu6-60-74x"/>
<constraint firstItem="NCX-4e-lSu" firstAttribute="leading" secondItem="8hL-Vn-Hg0" secondAttribute="leading" constant="17" id="W09-iG-ARI"/>
<constraint firstItem="I1a-Eu-5UB" firstAttribute="top" secondItem="8hL-Vn-Hg0" secondAttribute="top" constant="3" id="fkf-wO-Q8i"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="ReP-bV-Thu" secondAttribute="bottom" constant="17" id="fmT-7E-hUT"/>
<constraint firstItem="ReP-bV-Thu" firstAttribute="top" secondItem="I1a-Eu-5UB" secondAttribute="bottom" constant="6" id="hYk-xC-63o"/>
<constraint firstItem="ReP-bV-Thu" firstAttribute="leading" secondItem="8hL-Vn-Hg0" secondAttribute="leading" constant="17" id="qen-KS-rWi"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="ReP-bV-Thu" secondAttribute="trailing" constant="17" id="r7F-DT-oRc"/>
</constraints>
</view>
</tabViewItem>
<tabViewItem label="ZX81" identifier="zx81" id="Wnn-nQ-gZ6">
<view key="view" id="bmd-gL-gzT">
<rect key="frame" x="10" y="33" width="516" height="92"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5aO-UX-HnX">
<rect key="frame" x="102" y="65" width="114" height="26"/>
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="7QC-Ij-hES" id="d3W-Gl-3Mf">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="mua-Lp-9wl">
<items>
<menuItem title="Unexpanded" state="on" id="7QC-Ij-hES"/>
<menuItem title="16 kb" tag="16" id="1HK-zJ-udx"/>
<menuItem title="64 kb" tag="64" id="PEx-W6-eGK"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8tU-73-XEE">
<rect key="frame" x="15" y="70" width="83" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Memory Size" id="z4b-oR-Yl2">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="8tU-73-XEE" firstAttribute="centerY" secondItem="5aO-UX-HnX" secondAttribute="centerY" id="1Jm-YL-OKU"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="5aO-UX-HnX" secondAttribute="trailing" constant="17" id="ALj-0x-bFb"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="5aO-UX-HnX" secondAttribute="bottom" constant="17" id="LJ2-W9-fOf"/>
<constraint firstItem="8tU-73-XEE" firstAttribute="leading" secondItem="bmd-gL-gzT" secondAttribute="leading" constant="17" id="M6Y-jN-LAf"/>
<constraint firstItem="5aO-UX-HnX" firstAttribute="top" secondItem="bmd-gL-gzT" secondAttribute="top" constant="3" id="PPD-Jz-qCL"/>
<constraint firstItem="5aO-UX-HnX" firstAttribute="leading" secondItem="8tU-73-XEE" secondAttribute="trailing" constant="8" id="j1u-n4-2IK"/>
</constraints>
</view>
</tabViewItem>
</tabViewItems>
</tabView>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hKn-1l-OSN">
<rect key="frame" x="412" y="13" width="136" height="32"/>
<buttonCell key="cell" type="push" title="Create Machine" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="MnM-xo-4Qa">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="createMachine:" target="-2" id="2wo-Zv-H4f"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JQy-Cj-AOK">
<rect key="frame" x="331" y="13" width="82" height="32"/>
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sub-rB-Req">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
Gw
</string>
</buttonCell>
<connections>
<action selector="cancelCreateMachine:" target="-2" id="lf8-PM-c0m"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="VUb-QG-x7c" secondAttribute="trailing" constant="20" id="Bem-7v-AY6"/>
<constraint firstItem="JQy-Cj-AOK" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="EiT-Mj-1SZ" secondAttribute="leading" constant="20" id="FMm-eV-4eu"/>
<constraint firstAttribute="bottom" secondItem="JQy-Cj-AOK" secondAttribute="bottom" constant="20" id="Kvh-1K-iI8"/>
<constraint firstItem="hKn-1l-OSN" firstAttribute="top" secondItem="VUb-QG-x7c" secondAttribute="bottom" constant="20" id="TqB-gT-0bf"/>
<constraint firstItem="hKn-1l-OSN" firstAttribute="leading" secondItem="JQy-Cj-AOK" secondAttribute="trailing" constant="11" id="f3Q-Om-rI0"/>
<constraint firstItem="VUb-QG-x7c" firstAttribute="leading" secondItem="EiT-Mj-1SZ" secondAttribute="leading" constant="20" id="j1W-rQ-Ypd"/>
<constraint firstAttribute="trailing" secondItem="hKn-1l-OSN" secondAttribute="trailing" constant="20" id="mJg-vd-ddP"/>
<constraint firstAttribute="bottom" secondItem="hKn-1l-OSN" secondAttribute="bottom" constant="20" id="rG2-Ea-klR"/>
<constraint firstItem="VUb-QG-x7c" firstAttribute="top" secondItem="EiT-Mj-1SZ" secondAttribute="top" constant="20" id="zT3-Ea-QQJ"/>
</constraints>
</view>
<point key="canvasLocation" x="34" y="89.5"/>
</window>
<customObject id="192-Eb-Rpg" customClass="MachinePicker" customModule="Clock_Signal" customModuleProvider="target">
<connections>
<outlet property="cpcModelTypeButton" destination="00d-sg-Krh" id="VyV-b1-A6x"/>
<outlet property="electronADFSButton" destination="945-wU-JOH" id="Fjm-W8-kvh"/>
<outlet property="electronDFSButton" destination="JqM-IK-FMP" id="C80-1k-TdQ"/>
<outlet property="machineSelector" destination="VUb-QG-x7c" id="crR-hB-jGd"/>
<outlet property="msxHasDiskDriveButton" destination="8xT-Pr-8SE" id="zGH-GA-9QF"/>
<outlet property="oricHasMicrodriveButton" destination="mZw-PY-0Yv" id="EuA-uL-PNR"/>
<outlet property="oricModelTypeButton" destination="ENP-hI-BVZ" id="n9i-Ym-miE"/>
<outlet property="vic20HasC1540Button" destination="Lrf-gL-6EI" id="21g-dJ-mOo"/>
<outlet property="vic20MemorySizeButton" destination="2eV-Us-eEv" id="5j4-jw-89d"/>
<outlet property="vic20RegionButton" destination="ueK-gq-gaF" id="qMq-uP-y4r"/>
<outlet property="zx80MemorySizeButton" destination="I1a-Eu-5UB" id="1QF-k5-aMM"/>
<outlet property="zx80UsesZX81ROMButton" destination="ReP-bV-Thu" id="Oe9-gC-jXp"/>
<outlet property="zx81MemorySizeButton" destination="5aO-UX-HnX" id="QHV-97-d19"/>
</connections>
</customObject>
</objects>
</document>

View File

@ -0,0 +1,161 @@
//
// MachinePicker.swift
// Clock Signal
//
// Created by Thomas Harte on 02/04/2018.
// Copyright © 2018 Thomas Harte. All rights reserved.
//
import Cocoa
class MachinePicker: NSObject {
@IBOutlet var machineSelector: NSTabView?
// MARK: - Electron properties
@IBOutlet var electronDFSButton: NSButton?
@IBOutlet var electronADFSButton: NSButton?
// MARK: - CPC properties
@IBOutlet var cpcModelTypeButton: NSPopUpButton?
// MARK: - MSX properties
@IBOutlet var msxHasDiskDriveButton: NSButton?
// MARK: - Oric properties
@IBOutlet var oricModelTypeButton: NSPopUpButton?
@IBOutlet var oricHasMicrodriveButton: NSButton?
// MARK: - Vic-20 properties
@IBOutlet var vic20RegionButton: NSPopUpButton?
@IBOutlet var vic20MemorySizeButton: NSPopUpButton?
@IBOutlet var vic20HasC1540Button: NSButton?
// MARK: - ZX80 properties
@IBOutlet var zx80MemorySizeButton: NSPopUpButton?
@IBOutlet var zx80UsesZX81ROMButton: NSButton?
// MARK: - ZX81 properties
@IBOutlet var zx81MemorySizeButton: NSPopUpButton?
// MARK: - Preferences
func establishStoredOptions() {
let standardUserDefaults = UserDefaults.standard
// Machine type
if let machineIdentifier = standardUserDefaults.string(forKey: "new.machine") {
machineSelector?.selectTabViewItem(withIdentifier: machineIdentifier as Any)
}
// Electron settings
electronDFSButton?.state = standardUserDefaults.bool(forKey: "new.electronDFS") ? .on : .off
electronADFSButton?.state = standardUserDefaults.bool(forKey: "new.electronADFS") ? .on : .off
// CPC settings
cpcModelTypeButton?.selectItem(withTag: standardUserDefaults.integer(forKey: "new.cpcModel"))
// MSX settings
msxHasDiskDriveButton?.state = standardUserDefaults.bool(forKey: "new.msxDiskDrive") ? .on : .off
// Oric settings
oricHasMicrodriveButton?.state = standardUserDefaults.bool(forKey: "new.oricMicrodrive") ? .on : .off
oricModelTypeButton?.selectItem(withTag: standardUserDefaults.integer(forKey: "new.oricModel"))
// Vic-20 settings
vic20RegionButton?.selectItem(withTag: standardUserDefaults.integer(forKey: "new.vic20Region"))
vic20MemorySizeButton?.selectItem(withTag: standardUserDefaults.integer(forKey: "new.vic20MemorySize"))
vic20HasC1540Button?.state = standardUserDefaults.bool(forKey: "new.vic20C1540") ? .on : .off
// ZX80
zx80MemorySizeButton?.selectItem(withTag: standardUserDefaults.integer(forKey: "new.zx80MemorySize"))
zx80UsesZX81ROMButton?.state = standardUserDefaults.bool(forKey: "new.zx80UsesZX81ROM") ? .on : .off
// ZX81
zx81MemorySizeButton?.selectItem(withTag: standardUserDefaults.integer(forKey: "new.zx81MemorySize"))
}
fileprivate func storeOptions() {
let standardUserDefaults = UserDefaults.standard
// Machine type
standardUserDefaults.set(machineSelector!.selectedTabViewItem!.identifier as! String, forKey: "new.machine")
// Electron settings
standardUserDefaults.set(electronDFSButton!.state == .on, forKey: "new.electronDFS")
standardUserDefaults.set(electronADFSButton!.state == .on, forKey: "new.electronADFS")
// CPC settings
standardUserDefaults.set(cpcModelTypeButton!.selectedTag(), forKey: "new.cpcModel")
// MSX settings
standardUserDefaults.set(msxHasDiskDriveButton?.state == .on, forKey: "new.msxDiskDrive")
// Oric settings
standardUserDefaults.set(oricHasMicrodriveButton?.state == .on, forKey: "new.oricMicrodrive")
standardUserDefaults.set(oricModelTypeButton!.selectedTag(), forKey: "new.oricModel")
// Vic-20 settings
standardUserDefaults.set(vic20RegionButton!.selectedTag(), forKey: "new.vic20Region")
standardUserDefaults.set(vic20MemorySizeButton!.selectedTag(), forKey: "new.vic20MemorySize")
standardUserDefaults.set(vic20HasC1540Button?.state == .on, forKey: "new.vic20C1540")
// ZX80
standardUserDefaults.set(zx80MemorySizeButton!.selectedTag(), forKey: "new.zx80MemorySize")
standardUserDefaults.set(zx80UsesZX81ROMButton?.state == .on, forKey: "new.zx80UsesZX81ROM")
// ZX81
standardUserDefaults.set(zx81MemorySizeButton!.selectedTag(), forKey: "new.zx81MemorySize")
}
// MARK: - Machine builder
func selectedMachine() -> CSStaticAnalyser {
storeOptions()
switch machineSelector!.selectedTabViewItem!.identifier as! String {
case "electron":
return CSStaticAnalyser(electronDFS: electronDFSButton!.state == .on, adfs: electronADFSButton!.state == .on)!
case "cpc":
switch cpcModelTypeButton!.selectedItem!.tag {
case 464: return CSStaticAnalyser(amstradCPCModel: .model464)
case 664: return CSStaticAnalyser(amstradCPCModel: .model664)
case 6128: fallthrough
default: return CSStaticAnalyser(amstradCPCModel: .model6128)
}
case "msx":
return CSStaticAnalyser(msxHasDiskDrive: msxHasDiskDriveButton!.state == .on)
case "oric":
let hasMicrodrive = oricHasMicrodriveButton!.state == .on
switch oricModelTypeButton!.selectedItem!.tag {
case 1: return CSStaticAnalyser(oricModel: .oric1, hasMicrodrive: hasMicrodrive)
default: return CSStaticAnalyser(oricModel: .oricAtmos, hasMicrodrive: hasMicrodrive)
}
case "vic20":
let memorySize = Kilobytes(vic20MemorySizeButton!.selectedItem!.tag)
let hasC1540 = vic20HasC1540Button!.state == .on
switch vic20RegionButton!.selectedItem?.tag {
case 1:
return CSStaticAnalyser(vic20Region: .american, memorySize: memorySize, hasC1540: hasC1540)
case 2:
return CSStaticAnalyser(vic20Region: .danish, memorySize: memorySize, hasC1540: hasC1540)
case 3:
return CSStaticAnalyser(vic20Region: .swedish, memorySize: memorySize, hasC1540: hasC1540)
case 4:
return CSStaticAnalyser(vic20Region: .japanese, memorySize: memorySize, hasC1540: hasC1540)
case 0: fallthrough
default:
return CSStaticAnalyser(vic20Region: .european, memorySize: memorySize, hasC1540: hasC1540)
}
case "zx80":
return CSStaticAnalyser(zx80MemorySize: Kilobytes(zx80MemorySizeButton!.selectedItem!.tag), useZX81ROM: zx80UsesZX81ROMButton!.state == .on)
case "zx81":
return CSStaticAnalyser(zx81MemorySize: Kilobytes(zx81MemorySizeButton!.selectedItem!.tag))
default: return CSStaticAnalyser()
}
}
}