diff --git a/Analyser/Static/Acorn/Target.hpp b/Analyser/Static/Acorn/Target.hpp index c2f9f22b4..e7e97d467 100644 --- a/Analyser/Static/Acorn/Target.hpp +++ b/Analyser/Static/Acorn/Target.hpp @@ -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 */ diff --git a/Analyser/Static/AmstradCPC/Target.hpp b/Analyser/Static/AmstradCPC/Target.hpp index 795106435..ae656399e 100644 --- a/Analyser/Static/AmstradCPC/Target.hpp +++ b/Analyser/Static/AmstradCPC/Target.hpp @@ -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 */ diff --git a/Analyser/Static/Atari/Target.hpp b/Analyser/Static/Atari/Target.hpp index 9f0119ada..d102368cc 100644 --- a/Analyser/Static/Atari/Target.hpp +++ b/Analyser/Static/Atari/Target.hpp @@ -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 */ diff --git a/Analyser/Static/Commodore/Target.hpp b/Analyser/Static/Commodore/Target.hpp index 35b4c3426..1dc54db88 100644 --- a/Analyser/Static/Commodore/Target.hpp +++ b/Analyser/Static/Commodore/Target.hpp @@ -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 */ diff --git a/Analyser/Static/MSX/StaticAnalyser.cpp b/Analyser/Static/MSX/StaticAnalyser.cpp index 26351bf2b..9b4e4377a 100644 --- a/Analyser/Static/MSX/StaticAnalyser.cpp +++ b/Analyser/Static/MSX/StaticAnalyser.cpp @@ -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; diff --git a/Analyser/Static/MSX/Target.hpp b/Analyser/Static/MSX/Target.hpp new file mode 100644 index 000000000..6c6c2cea7 --- /dev/null +++ b/Analyser/Static/MSX/Target.hpp @@ -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 */ diff --git a/Analyser/Static/Oric/StaticAnalyser.cpp b/Analyser/Static/Oric/StaticAnalyser.cpp index 7f7391e96..e53aa6463 100644 --- a/Analyser/Static/Oric/StaticAnalyser.cpp +++ b/Analyser/Static/Oric/StaticAnalyser.cpp @@ -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)); diff --git a/Analyser/Static/Oric/Target.hpp b/Analyser/Static/Oric/Target.hpp index f920d7e5a..4bd5bb16e 100644 --- a/Analyser/Static/Oric/Target.hpp +++ b/Analyser/Static/Oric/Target.hpp @@ -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 */ diff --git a/Analyser/Static/ZX8081/StaticAnalyser.cpp b/Analyser/Static/ZX8081/StaticAnalyser.cpp index 4ee957325..a405bf8bf 100644 --- a/Analyser/Static/ZX8081/StaticAnalyser.cpp +++ b/Analyser/Static/ZX8081/StaticAnalyser.cpp @@ -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"; diff --git a/Analyser/Static/ZX8081/Target.hpp b/Analyser/Static/ZX8081/Target.hpp index 7fef01e08..5f40e0bdf 100644 --- a/Analyser/Static/ZX8081/Target.hpp +++ b/Analyser/Static/ZX8081/Target.hpp @@ -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 */ diff --git a/Machines/MSX/MSX.cpp b/Machines/MSX/MSX.cpp index 87fea0628..3502c8161 100644 --- a/Machines/MSX/MSX.cpp +++ b/Machines/MSX/MSX.cpp @@ -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)); diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index afd2dc1da..5215badf4 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -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(µdisc_); microdisc_.set_delegate(this); diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index ec30e8ebc..7d17bd357 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -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>(); diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 202c24e47..ef546f057 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -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 = ( diff --git a/OSBindings/Mac/Clock Signal/Document Controller/DocumentController.swift b/OSBindings/Mac/Clock Signal/Document Controller/DocumentController.swift index 01ec875bb..62e221294 100644 --- a/OSBindings/Mac/Clock Signal/Document Controller/DocumentController.swift +++ b/OSBindings/Mac/Clock Signal/Document Controller/DocumentController.swift @@ -9,4 +9,20 @@ import Cocoa class DocumentController: NSDocumentController { + override func newDocument(_ sender: Any?) { + // Show the new document window. + Bundle.main.loadNibNamed(NSNib.Name(rawValue: "MachinePicker"), owner: self, topLevelObjects: nil) + } + + @IBOutlet var machinePicker: MachinePicker? + @IBAction func createMachine(_ sender: NSButton?) { + let machine = machinePicker!.selectedMachine() + let document: MachineDocument = try! openUntitledDocumentAndDisplay(true) as! MachineDocument + document.configureAs(machine) + sender?.window?.close() + } + + @IBAction func cancelCreateMachine(_ sender: NSButton?) { + sender?.window?.close() + } } diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift index f2e72b86a..defa25a86 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift @@ -48,30 +48,34 @@ 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)) - }) + 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)) + }) - self.machine.delegate = self - self.bestEffortUpdater = CSBestEffortUpdater() + machine.delegate = self + self.bestEffortUpdater = CSBestEffortUpdater() - // 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 + // 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() - self.optionsPanel?.establishStoredOptions() + setupAudioQueueClockRate() - // bring OpenGL view-holding window on top of the options panel - self.openGLView.window!.makeKeyAndOrderFront(self) + // bring OpenGL view-holding window on top of the options panel + openGLView.window!.makeKeyAndOrderFront(self) - // start accepting best effort updates - self.bestEffortUpdater!.delegate = self + // start accepting best effort updates + self.bestEffortUpdater!.delegate = self + } } func machineSpeakerDidChangeInputClock(_ machine: CSMachine!) { @@ -95,9 +99,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,12 +121,14 @@ class MachineDocument: func configureAs(_ analysis: CSStaticAnalyser) { if let machine = CSMachine(analyser: analysis) { self.machine = machine - } + setupMachineOutput() - if let optionsPanelNibName = analysis.optionsPanelNibName { - Bundle.main.loadNibNamed(NSNib.Name(rawValue: optionsPanelNibName), owner: self, topLevelObjects: nil) - self.optionsPanel.machine = self.machine - showOptions(self) + if let optionsPanelNibName = analysis.optionsPanelNibName { + Bundle.main.loadNibNamed(NSNib.Name(rawValue: optionsPanelNibName), owner: self, topLevelObjects: nil) + self.optionsPanel.machine = self.machine + self.optionsPanel?.establishStoredOptions() + showOptions(self) + } } } @@ -185,7 +193,7 @@ class MachineDocument: // MARK: Input management func windowDidResignKey(_ notification: Notification) { - self.machine.clearAllKeys() +// self.machine.clearAllKeys() } func keyDown(_ event: NSEvent) { diff --git a/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.h b/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.h index 47457adeb..17082cff3 100644 --- a/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.h +++ b/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.h @@ -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; diff --git a/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm b/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm index b1849f8f1..de2b46097 100644 --- a/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm +++ b/OSBindings/Mac/Clock Signal/Machine/StaticAnalyser/CSStaticAnalyser.mm @@ -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; diff --git a/OSBindings/Mac/Clock Signal/New Group/Base.lproj/MachinePicker.xib b/OSBindings/Mac/Clock Signal/New Group/Base.lproj/MachinePicker.xib new file mode 100644 index 000000000..b3841fa84 --- /dev/null +++ b/OSBindings/Mac/Clock Signal/New Group/Base.lproj/MachinePicker.xib @@ -0,0 +1,387 @@ +<?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="DocumentController" customModule="Clock_Signal" customModuleProvider="target"> + <connections> + <outlet property="machinePicker" destination="192-Eb-Rpg" id="7p2-GL-AVt"/> + </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" animationBehavior="default" id="QvC-M9-y7g"> + <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/> + <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/> + <rect key="contentRect" x="196" y="240" width="562" height="203"/> + <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="203"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <tabView translatesAutoresizingMaskIntoConstraints="NO" id="VUb-QG-x7c"> + <rect key="frame" x="13" y="51" width="536" height="138"/> + <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 firstItem="00d-sg-Krh" firstAttribute="top" secondItem="5zS-Nj-Ynx" secondAttribute="top" constant="3" id="KHk-pr-avq"/> + <constraint firstItem="00d-sg-Krh" firstAttribute="leading" secondItem="q9q-sl-J0q" secondAttribute="trailing" constant="8" id="Sr4-Xg-lgt"/> + <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="t3s-ba-0dx"/> + <constraint firstItem="q9q-sl-J0q" firstAttribute="centerY" secondItem="00d-sg-Krh" secondAttribute="centerY" id="vA8-IA-Uwf"/> + <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="00d-sg-Krh" secondAttribute="trailing" constant="17" id="y6y-bJ-ECA"/> + </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="127.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> diff --git a/OSBindings/Mac/Clock Signal/New Group/MachinePicker.swift b/OSBindings/Mac/Clock Signal/New Group/MachinePicker.swift new file mode 100644 index 000000000..b133ea980 --- /dev/null +++ b/OSBindings/Mac/Clock Signal/New Group/MachinePicker.swift @@ -0,0 +1,90 @@ +// +// 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: - Machine builder + func selectedMachine() -> CSStaticAnalyser { + 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() + } + } +}