mirror of
https://github.com/TomHarte/CLK.git
synced 2025-10-25 09:27:01 +00:00
Compare commits
255 Commits
2021-06-13
...
2021-08-09
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77befb7f8e | ||
|
|
f2af8ff25d | ||
|
|
7d8894415c | ||
|
|
1f0bf1b32d | ||
|
|
fdb676da4e | ||
|
|
038ed0551e | ||
|
|
cfaf4a8a65 | ||
|
|
eab9bc1503 | ||
|
|
5bfedff8d1 | ||
|
|
c8638c0ffb | ||
|
|
8a95b91e2a | ||
|
|
c226be612f | ||
|
|
c8699d9770 | ||
|
|
a0799e14cc | ||
|
|
dea6048849 | ||
|
|
813e252539 | ||
|
|
b41e29a83b | ||
|
|
d35c7ad127 | ||
|
|
ea63415d0e | ||
|
|
52ea3b741c | ||
|
|
2731ca8c92 | ||
|
|
af1ade9433 | ||
|
|
fc248951cc | ||
|
|
84547ee1c1 | ||
|
|
a42848c62f | ||
|
|
c7b5d69431 | ||
|
|
81374b70b5 | ||
|
|
47a530fd5c | ||
|
|
58451d7c0c | ||
|
|
5c8f8c76fe | ||
|
|
ae1d1bdb5b | ||
|
|
33cc1154a2 | ||
|
|
4bc0b75c30 | ||
|
|
eb8ec1efb1 | ||
|
|
616f8efc47 | ||
|
|
29e4369420 | ||
|
|
bd7f7bc8d7 | ||
|
|
e689ca92c4 | ||
|
|
4ef3005072 | ||
|
|
174c837767 | ||
|
|
486bb911a9 | ||
|
|
754221d697 | ||
|
|
3c36c90729 | ||
|
|
3d1d15a25b | ||
|
|
000d99f26c | ||
|
|
524e2abc8c | ||
|
|
00bab98e09 | ||
|
|
6d98349be1 | ||
|
|
d24d153c08 | ||
|
|
b01561712c | ||
|
|
324edcb391 | ||
|
|
6e62e4e296 | ||
|
|
f81ecbf4a0 | ||
|
|
4370456323 | ||
|
|
a424ed7c00 | ||
|
|
a2065f59a1 | ||
|
|
c1bd7f5c67 | ||
|
|
5810a1a98e | ||
|
|
a4c011e3c0 | ||
|
|
337fd15dc0 | ||
|
|
9bc94f4536 | ||
|
|
3f4cf35384 | ||
|
|
4dd7f2cc09 | ||
|
|
1b29cc34c4 | ||
|
|
53c3c1f5ab | ||
|
|
6225abd751 | ||
|
|
c6fcd9a1eb | ||
|
|
30fbb6ea53 | ||
|
|
0e49258546 | ||
|
|
264b8dfb28 | ||
|
|
6a15b8f695 | ||
|
|
5167d256cc | ||
|
|
16bd826491 | ||
|
|
55af8fa5d9 | ||
|
|
1ec8ff20af | ||
|
|
99a65d3297 | ||
|
|
94907b51aa | ||
|
|
0085265d13 | ||
|
|
8e0893bd42 | ||
|
|
704dc9bdcb | ||
|
|
7a673a2448 | ||
|
|
33e2a4b21c | ||
|
|
3e6b804896 | ||
|
|
e98165a657 | ||
|
|
2a7727d12b | ||
|
|
c20e8f4062 | ||
|
|
4ca9db7d49 | ||
|
|
4add48cffb | ||
|
|
adbfb009f8 | ||
|
|
43ceca8711 | ||
|
|
3ef28a4f03 | ||
|
|
adcd580d5b | ||
|
|
5715c9183f | ||
|
|
ceb62ac7f9 | ||
|
|
bda0756620 | ||
|
|
6b47fb38c6 | ||
|
|
38bf8a06a7 | ||
|
|
196651d9aa | ||
|
|
6b46212a4e | ||
|
|
2a6fff2008 | ||
|
|
c5944efe50 | ||
|
|
f384370b18 | ||
|
|
0c09275a9f | ||
|
|
278671cdb9 | ||
|
|
964d2d4fa4 | ||
|
|
f371221dba | ||
|
|
27b0579ec6 | ||
|
|
283092cfbc | ||
|
|
614953a222 | ||
|
|
4fffb3cf19 | ||
|
|
850aa2b23a | ||
|
|
d715e5fd1d | ||
|
|
7826a26c7b | ||
|
|
dc0a82cf9a | ||
|
|
2e60c81bd6 | ||
|
|
763b9ba0ec | ||
|
|
bae8bb0c00 | ||
|
|
bcf483fb7e | ||
|
|
a5b7d819a7 | ||
|
|
fe07a0b1d8 | ||
|
|
d9231e5d4a | ||
|
|
b7aa1a1c84 | ||
|
|
32e144115d | ||
|
|
177cc96f49 | ||
|
|
51d98ef9ab | ||
|
|
2327c48cc4 | ||
|
|
742d44a532 | ||
|
|
52b96db2b9 | ||
|
|
0b9de78c38 | ||
|
|
2c28cb8c57 | ||
|
|
483fe82e9d | ||
|
|
29492d6138 | ||
|
|
19310e32c4 | ||
|
|
c04a395499 | ||
|
|
1c424833a9 | ||
|
|
a46ff5590d | ||
|
|
ab059b63fd | ||
|
|
3d8fc9952d | ||
|
|
8ce8fbd977 | ||
|
|
7f08218b28 | ||
|
|
2c139ad931 | ||
|
|
1119779c8b | ||
|
|
5351ac560f | ||
|
|
49f0ab0f15 | ||
|
|
a5c57e777e | ||
|
|
3c59042388 | ||
|
|
919e211bc4 | ||
|
|
daa0737ce4 | ||
|
|
36805cb120 | ||
|
|
7de69e9874 | ||
|
|
b93575bbcc | ||
|
|
116e0f0105 | ||
|
|
e4a650aaff | ||
|
|
b5312b9ba0 | ||
|
|
6afee7bb9b | ||
|
|
5729e6e13a | ||
|
|
2f53b105bb | ||
|
|
b698056f78 | ||
|
|
95c906f03d | ||
|
|
be19fa9dde | ||
|
|
81e9ba5608 | ||
|
|
f2d7b9f6a9 | ||
|
|
1ea034310a | ||
|
|
bdcab447f9 | ||
|
|
10bf6744aa | ||
|
|
895d98e266 | ||
|
|
903e343895 | ||
|
|
f8b7c59616 | ||
|
|
fcd267a3f9 | ||
|
|
f8bb66d2a0 | ||
|
|
90782d3c27 | ||
|
|
f2336d2efc | ||
|
|
c2d093fa3c | ||
|
|
1a97cc8a91 | ||
|
|
c34a548fa0 | ||
|
|
d1b89392a2 | ||
|
|
ed734754e5 | ||
|
|
520c3c9218 | ||
|
|
9230cf1726 | ||
|
|
6e616972a5 | ||
|
|
f98888824d | ||
|
|
6c8b23e708 | ||
|
|
2c2bb3765f | ||
|
|
0d165740ea | ||
|
|
88f0f2b623 | ||
|
|
0afa143375 | ||
|
|
8319aca351 | ||
|
|
a66734883a | ||
|
|
d2ab0dd839 | ||
|
|
2574407afb | ||
|
|
83a54fd6d2 | ||
|
|
e062780968 | ||
|
|
3acd0be1f7 | ||
|
|
69c0734975 | ||
|
|
c1678d7be7 | ||
|
|
117f9a9794 | ||
|
|
b49cc407c6 | ||
|
|
954386f1cc | ||
|
|
d7ff6bd04d | ||
|
|
6025516f9f | ||
|
|
d8b9cdf7a2 | ||
|
|
09dbff39f2 | ||
|
|
2fe15a6168 | ||
|
|
07dc26f8fa | ||
|
|
a08d65b1ff | ||
|
|
199621db08 | ||
|
|
0e1e8c7faa | ||
|
|
42a98e1676 | ||
|
|
23e26e0333 | ||
|
|
fadb04f3f3 | ||
|
|
4968ccf46d | ||
|
|
1dcac304d3 | ||
|
|
1651efe4fc | ||
|
|
8f24aed43e | ||
|
|
a381374e31 | ||
|
|
9411c37d23 | ||
|
|
6af6f21868 | ||
|
|
9a0022cfcb | ||
|
|
266310d9c2 | ||
|
|
fbf1adef05 | ||
|
|
311ddfb05a | ||
|
|
2fd8a8aa66 | ||
|
|
0c3e9dca28 | ||
|
|
c331d15429 | ||
|
|
4414e96710 | ||
|
|
7161783a4f | ||
|
|
cbac48da86 | ||
|
|
d9142d5427 | ||
|
|
e5e988b28f | ||
|
|
e94e051c87 | ||
|
|
5fc91effb5 | ||
|
|
6c9dacbe89 | ||
|
|
6a7eb832cc | ||
|
|
60cf8486bb | ||
|
|
90b8163d54 | ||
|
|
a1e4389f63 | ||
|
|
440b11708b | ||
|
|
f90dce5c54 | ||
|
|
606c7709cf | ||
|
|
1d1e6d1820 | ||
|
|
3eb4dd74a2 | ||
|
|
853914480c | ||
|
|
fe04410681 | ||
|
|
1f686c4e6b | ||
|
|
2a2ac1227b | ||
|
|
b5340c8f74 | ||
|
|
196c4dcdd9 | ||
|
|
c5a86f0ef7 | ||
|
|
88f2a2940b | ||
|
|
26b019a4d4 | ||
|
|
5f7b3ae313 | ||
|
|
61c127ed2e | ||
|
|
333981e2a7 | ||
|
|
8e0a6df03b | ||
|
|
2a6e9c5e8a |
@@ -23,10 +23,19 @@ namespace Activity {
|
||||
*/
|
||||
class Observer {
|
||||
public:
|
||||
/// Provides hints as to the sort of information presented on an LED.
|
||||
enum LEDPresentation: uint8_t {
|
||||
/// This LED informs the user of some sort of persistent state, e.g. scroll lock.
|
||||
/// If this flag is absent then the LED describes an ephemeral state, such as media access.
|
||||
Persistent = (1 << 0),
|
||||
};
|
||||
|
||||
/// Announces to the receiver that there is an LED of name @c name.
|
||||
virtual void register_led([[maybe_unused]] const std::string &name) {}
|
||||
virtual void register_led([[maybe_unused]] const std::string &name, [[maybe_unused]] uint8_t presentation = 0) {}
|
||||
|
||||
/// Announces to the receiver that there is a drive of name @c name.
|
||||
///
|
||||
/// If a drive has the same name as an LED, that LED goes with this drive.
|
||||
virtual void register_drive([[maybe_unused]] const std::string &name) {}
|
||||
|
||||
/// Informs the receiver of the new state of the LED with name @c name.
|
||||
|
||||
@@ -19,6 +19,7 @@ enum class Machine {
|
||||
AtariST,
|
||||
ColecoVision,
|
||||
Electron,
|
||||
Enterprise,
|
||||
Macintosh,
|
||||
MasterSystem,
|
||||
MSX,
|
||||
|
||||
84
Analyser/Static/Enterprise/StaticAnalyser.cpp
Normal file
84
Analyser/Static/Enterprise/StaticAnalyser.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// StaticAnalyser.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 24/06/2021.
|
||||
// Copyright 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "StaticAnalyser.hpp"
|
||||
#include "Target.hpp"
|
||||
|
||||
#include "../../../Storage/Disk/Parsers/FAT.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
|
||||
bool insensitive_equal(const std::string &lhs, const std::string &rhs) {
|
||||
return std::equal(
|
||||
lhs.begin(), lhs.end(),
|
||||
rhs.begin(), rhs.end(),
|
||||
[] (char l, char r) {
|
||||
return tolower(l) == tolower(r);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Analyser::Static::TargetList Analyser::Static::Enterprise::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
|
||||
// This analyser can comprehend disks only.
|
||||
if(media.disks.empty()) return {};
|
||||
|
||||
// Otherwise, assume a return will happen.
|
||||
Analyser::Static::TargetList targets;
|
||||
using Target = Analyser::Static::Enterprise::Target;
|
||||
auto *const target = new Target;
|
||||
target->media = media;
|
||||
|
||||
// Always require a BASIC.
|
||||
target->basic_version = Target::BASICVersion::Any;
|
||||
|
||||
// Inspect any supplied disks.
|
||||
if(!media.disks.empty()) {
|
||||
// DOS will be needed.
|
||||
target->dos = Target::DOS::EXDOS;
|
||||
|
||||
// Grab the volume information, which includes the root directory.
|
||||
auto volume = Storage::Disk::FAT::GetVolume(media.disks.front());
|
||||
if(volume) {
|
||||
// If there's an EXDOS.INI then this disk should be able to boot itself.
|
||||
// If not but if there's only one visible .COM or .BAS, automatically load
|
||||
// that. Otherwise, issue a :DIR.
|
||||
using File = Storage::Disk::FAT::File;
|
||||
const File *selected_file = nullptr;
|
||||
bool has_exdos_ini = false;
|
||||
bool did_pick_file = false;
|
||||
for(const auto &file: (*volume).root_directory) {
|
||||
if(insensitive_equal(file.name, "exdos") && insensitive_equal(file.extension, "ini")) {
|
||||
has_exdos_ini = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!(file.attributes & File::Attribute::Hidden) &&
|
||||
(insensitive_equal(file.extension, "com") || insensitive_equal(file.extension, "bas"))
|
||||
) {
|
||||
did_pick_file = !selected_file;
|
||||
selected_file = &file;
|
||||
}
|
||||
}
|
||||
|
||||
if(!has_exdos_ini) {
|
||||
if(did_pick_file) {
|
||||
target->loading_command = std::string("run \"") + selected_file->name + "." + selected_file->extension + "\"\n";
|
||||
} else {
|
||||
target->loading_command = ":dir\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
targets.push_back(std::unique_ptr<Analyser::Static::Target>(target));
|
||||
|
||||
return targets;
|
||||
}
|
||||
27
Analyser/Static/Enterprise/StaticAnalyser.hpp
Normal file
27
Analyser/Static/Enterprise/StaticAnalyser.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// StaticAnalyser.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 24/06/2021.
|
||||
// Copyright 2018 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Analyser_Static_Enterprise_StaticAnalyser_hpp
|
||||
#define Analyser_Static_Enterprise_StaticAnalyser_hpp
|
||||
|
||||
#include "../StaticAnalyser.hpp"
|
||||
#include "../../../Storage/TargetPlatforms.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace Analyser {
|
||||
namespace Static {
|
||||
namespace Enterprise {
|
||||
|
||||
TargetList GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* Analyser_Static_Enterprise_StaticAnalyser_hpp */
|
||||
57
Analyser/Static/Enterprise/Target.hpp
Normal file
57
Analyser/Static/Enterprise/Target.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// Target.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 14/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Analyser_Static_Enterprise_Target_h
|
||||
#define Analyser_Static_Enterprise_Target_h
|
||||
|
||||
#include "../../../Reflection/Enum.hpp"
|
||||
#include "../../../Reflection/Struct.hpp"
|
||||
#include "../StaticAnalyser.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Analyser {
|
||||
namespace Static {
|
||||
namespace Enterprise {
|
||||
|
||||
struct Target: public Analyser::Static::Target, public Reflection::StructImpl<Target> {
|
||||
ReflectableEnum(Model, Enterprise64, Enterprise128, Enterprise256);
|
||||
ReflectableEnum(EXOSVersion, v10, v20, v21, v23, Any);
|
||||
ReflectableEnum(BASICVersion, v10, v11, v21, Any, None);
|
||||
ReflectableEnum(DOS, EXDOS, None);
|
||||
ReflectableEnum(Speed, FourMHz, SixMHz);
|
||||
|
||||
Model model = Model::Enterprise128;
|
||||
EXOSVersion exos_version = EXOSVersion::Any;
|
||||
BASICVersion basic_version = BASICVersion::None;
|
||||
DOS dos = DOS::None;
|
||||
Speed speed = Speed::FourMHz;
|
||||
std::string loading_command;
|
||||
|
||||
Target() : Analyser::Static::Target(Machine::Enterprise) {
|
||||
if(needs_declare()) {
|
||||
AnnounceEnum(Model);
|
||||
AnnounceEnum(EXOSVersion);
|
||||
AnnounceEnum(BASICVersion);
|
||||
AnnounceEnum(DOS);
|
||||
AnnounceEnum(Speed);
|
||||
|
||||
DeclareField(model);
|
||||
DeclareField(exos_version);
|
||||
DeclareField(basic_version);
|
||||
DeclareField(dos);
|
||||
DeclareField(speed);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Analyser_Static_Enterprise_Target_h */
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "Coleco/StaticAnalyser.hpp"
|
||||
#include "Commodore/StaticAnalyser.hpp"
|
||||
#include "DiskII/StaticAnalyser.hpp"
|
||||
#include "Enterprise/StaticAnalyser.hpp"
|
||||
#include "Macintosh/StaticAnalyser.hpp"
|
||||
#include "MSX/StaticAnalyser.hpp"
|
||||
#include "Oric/StaticAnalyser.hpp"
|
||||
@@ -43,9 +44,9 @@
|
||||
#include "../../Storage/Disk/DiskImage/Formats/MacintoshIMG.hpp"
|
||||
#include "../../Storage/Disk/DiskImage/Formats/G64.hpp"
|
||||
#include "../../Storage/Disk/DiskImage/Formats/DMK.hpp"
|
||||
#include "../../Storage/Disk/DiskImage/Formats/FAT12.hpp"
|
||||
#include "../../Storage/Disk/DiskImage/Formats/HFE.hpp"
|
||||
#include "../../Storage/Disk/DiskImage/Formats/MSA.hpp"
|
||||
#include "../../Storage/Disk/DiskImage/Formats/MSXDSK.hpp"
|
||||
#include "../../Storage/Disk/DiskImage/Formats/NIB.hpp"
|
||||
#include "../../Storage/Disk/DiskImage/Formats/OricMFMDSK.hpp"
|
||||
#include "../../Storage/Disk/DiskImage/Formats/SSD.hpp"
|
||||
@@ -147,7 +148,7 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
|
||||
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // DSK (Macintosh, floppy disk)
|
||||
Format("dsk", result.mass_storage_devices, MassStorage::HFV, TargetPlatform::Macintosh) // DSK (Macintosh, hard disk, single volume image)
|
||||
Format("dsk", result.mass_storage_devices, MassStorage::DSK, TargetPlatform::Macintosh) // DSK (Macintosh, hard disk, full device image)
|
||||
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::MSXDSK>, TargetPlatform::MSX) // DSK (MSX)
|
||||
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::FAT12>, TargetPlatform::MSX) // DSK (MSX)
|
||||
Format("dsk", result.disks, Disk::DiskImageHolder<Storage::Disk::OricMFMDSK>, TargetPlatform::Oric) // DSK (Oric)
|
||||
Format("g64", result.disks, Disk::DiskImageHolder<Storage::Disk::G64>, TargetPlatform::Commodore) // G64
|
||||
Format( "hfe",
|
||||
@@ -157,6 +158,7 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
|
||||
// HFE (TODO: switch to AllDisk once the MSX stops being so greedy)
|
||||
Format("img", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
|
||||
Format("image", result.disks, Disk::DiskImageHolder<Storage::Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
|
||||
Format("img", result.disks, Disk::DiskImageHolder<Storage::Disk::FAT12>, TargetPlatform::Enterprise) // IMG (Enterprise/MS-DOS style)
|
||||
Format("msa", result.disks, Disk::DiskImageHolder<Storage::Disk::MSA>, TargetPlatform::AtariST) // MSA
|
||||
Format("nib", result.disks, Disk::DiskImageHolder<Storage::Disk::NIB>, TargetPlatform::DiskII) // NIB
|
||||
Format("o", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // O
|
||||
@@ -256,6 +258,7 @@ TargetList Analyser::Static::GetTargets(const std::string &file_name) {
|
||||
Append(Coleco);
|
||||
Append(Commodore);
|
||||
Append(DiskII);
|
||||
Append(Enterprise);
|
||||
Append(Macintosh);
|
||||
Append(MSX);
|
||||
Append(Oric);
|
||||
|
||||
@@ -213,7 +213,7 @@ class HalfCycles: public WrappedInt<HalfCycles> {
|
||||
|
||||
/*!
|
||||
Severs from @c this the effect of dividing by @c divisor; @c this will end up with
|
||||
the value of @c this modulo @c divisor and @c divided by @c divisor is returned.
|
||||
the value of @c this modulo @c divisor . @c this divided by @c divisor is returned.
|
||||
*/
|
||||
forceinline Cycles divide_cycles(const Cycles &divisor) {
|
||||
const HalfCycles half_divisor = HalfCycles(divisor);
|
||||
|
||||
@@ -103,9 +103,9 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
|
||||
}
|
||||
|
||||
if constexpr (has_sequence_points<T>::value) {
|
||||
time_until_event_ -= rhs;
|
||||
time_until_event_ -= rhs * multiplier;
|
||||
if(time_until_event_ <= LocalTimeScale(0)) {
|
||||
time_overrun_ = time_until_event_;
|
||||
time_overrun_ = time_until_event_ / divider;
|
||||
flush();
|
||||
update_sequence_point();
|
||||
return true;
|
||||
@@ -145,13 +145,21 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
|
||||
|
||||
/// @returns the amount of time since the object was last flushed, in the target time scale.
|
||||
[[nodiscard]] forceinline TargetTimeScale time_since_flush() const {
|
||||
// TODO: does this handle conversions properly where TargetTimeScale != LocalTimeScale?
|
||||
if constexpr (divider == 1) {
|
||||
return time_since_update_;
|
||||
}
|
||||
return TargetTimeScale(time_since_update_.as_integral() / divider);
|
||||
}
|
||||
|
||||
/// @returns the amount of time since the object was last flushed, plus the local time scale @c offset,
|
||||
/// converted to the target time scale.
|
||||
[[nodiscard]] forceinline TargetTimeScale time_since_flush(LocalTimeScale offset) const {
|
||||
if constexpr (divider == 1) {
|
||||
return time_since_update_ + offset;
|
||||
}
|
||||
return TargetTimeScale((time_since_update_ + offset).as_integral() / divider);
|
||||
}
|
||||
|
||||
/// Flushes all accumulated time.
|
||||
///
|
||||
/// This does not affect this actor's record of when the next sequence point will occur.
|
||||
@@ -185,7 +193,7 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
|
||||
/// @returns the number of cycles until the next sequence-point-based flush, if the embedded object
|
||||
/// supports sequence points; @c LocalTimeScale() otherwise.
|
||||
[[nodiscard]] LocalTimeScale cycles_until_implicit_flush() const {
|
||||
return time_until_event_;
|
||||
return time_until_event_ / divider;
|
||||
}
|
||||
|
||||
/// Indicates whether a sequence-point-caused flush will occur if the specified period is added.
|
||||
@@ -196,10 +204,43 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
|
||||
return rhs >= time_until_event_;
|
||||
}
|
||||
|
||||
/// Indicates the amount of time, in the local time scale, until the first local slot that falls wholly
|
||||
/// after @c duration, if that delay were to occur in @c offset units of time from now.
|
||||
[[nodiscard]] forceinline LocalTimeScale back_map(TargetTimeScale duration, TargetTimeScale offset) const {
|
||||
// A 1:1 mapping is easy.
|
||||
if constexpr (multiplier == 1 && divider == 1) {
|
||||
return duration;
|
||||
}
|
||||
|
||||
// Work out when this query is placed, and the time to which it relates
|
||||
const auto base = time_since_update_ + offset * divider;
|
||||
const auto target = base + duration * divider;
|
||||
|
||||
// Figure out the number of whole input steps that is required to get
|
||||
// past target, and subtract the number of whole input steps necessary
|
||||
// to get to base.
|
||||
const auto steps_to_base = base.as_integral() / multiplier;
|
||||
const auto steps_to_target = (target.as_integral() + divider - 1) / multiplier;
|
||||
|
||||
return LocalTimeScale(steps_to_target - steps_to_base);
|
||||
}
|
||||
|
||||
/// Updates this template's record of the next sequence point.
|
||||
void update_sequence_point() {
|
||||
if constexpr (has_sequence_points<T>::value) {
|
||||
time_until_event_ = object_.get_next_sequence_point();
|
||||
// Keep a fast path where no conversions will be applied; if conversions are
|
||||
// going to be applied then do a direct max -> max translation rather than
|
||||
// allowing the arithmetic to overflow.
|
||||
if constexpr (divider == 1 && std::is_same_v<LocalTimeScale, TargetTimeScale>) {
|
||||
time_until_event_ = object_.get_next_sequence_point();
|
||||
} else {
|
||||
const auto time = object_.get_next_sequence_point();
|
||||
if(time == TargetTimeScale::max()) {
|
||||
time_until_event_ = LocalTimeScale::max();
|
||||
} else {
|
||||
time_until_event_ = time * divider;
|
||||
}
|
||||
}
|
||||
assert(time_until_event_ > LocalTimeScale(0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,7 +276,10 @@ void WD1770::posit_event(int new_event_type) {
|
||||
goto test_type1_type;
|
||||
|
||||
begin_type1_spin_up:
|
||||
if((command_&0x08) || get_drive().get_motor_on()) goto test_type1_type;
|
||||
if((command_&0x08) || get_drive().get_motor_on()) {
|
||||
set_motor_on(true);
|
||||
goto test_type1_type;
|
||||
}
|
||||
SPIN_UP();
|
||||
|
||||
test_type1_type:
|
||||
@@ -387,7 +390,10 @@ void WD1770::posit_event(int new_event_type) {
|
||||
distance_into_section_ = 0;
|
||||
|
||||
if((command_&0x08) && has_motor_on_line()) goto test_type2_delay;
|
||||
if(!has_motor_on_line() && !has_head_load_line()) goto test_type2_delay;
|
||||
if(!has_motor_on_line() && !has_head_load_line()) {
|
||||
if(has_motor_on_line()) set_motor_on(true);
|
||||
goto test_type2_delay;
|
||||
}
|
||||
|
||||
if(has_motor_on_line()) goto begin_type2_spin_up;
|
||||
goto begin_type2_load_head;
|
||||
|
||||
@@ -137,10 +137,15 @@ void DiskII::decide_clocking_preference() {
|
||||
|
||||
// If in read mode, clocking is either:
|
||||
//
|
||||
// just-in-time, if drives are running or the shift register has any 1s in it or a flux event hasn't yet passed; or
|
||||
// none, given that drives are not running, the shift register has already emptied and there's no flux about to be received.
|
||||
// just-in-time, if drives are running or the shift register has any 1s in it and shifting may occur, or a flux event hasn't yet passed; or
|
||||
// none, given that drives are not running, the shift register has already emptied or stopped and there's no flux about to be received.
|
||||
if(!(inputs_ & ~input_flux)) {
|
||||
clocking_preference_ = (!motor_is_enabled_ && !shift_register_ && (inputs_&input_flux)) ? ClockingHint::Preference::None : ClockingHint::Preference::JustInTime;
|
||||
const bool is_stuck_at_nop =
|
||||
!flux_duration_ && state_machine_[(state_ & 0xf0) | inputs_ | ((shift_register_&0x80) >> 6)] == state_ && (state_ &0xf) == 0x8;
|
||||
|
||||
clocking_preference_ =
|
||||
(drive_is_sleeping_[0] && drive_is_sleeping_[1] && (!shift_register_ || is_stuck_at_nop) && (inputs_&input_flux))
|
||||
? ClockingHint::Preference::None : ClockingHint::Preference::JustInTime;
|
||||
}
|
||||
|
||||
// If in writing mode, clocking is real time.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#ifndef Joystick_hpp
|
||||
#define Joystick_hpp
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace Inputs {
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "Keyboard.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
using namespace Inputs;
|
||||
|
||||
Keyboard::Keyboard(const std::set<Key> &essential_modifiers) : essential_modifiers_(essential_modifiers) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef CachingExecutor_hpp
|
||||
#define CachingExecutor_hpp
|
||||
|
||||
#include "Sizes.hpp"
|
||||
#include "../Numeric/Sizes.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef Disassembler_hpp
|
||||
#define Disassembler_hpp
|
||||
|
||||
#include "Sizes.hpp"
|
||||
#include "../Numeric/Sizes.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
@@ -1119,7 +1119,7 @@ template <bool has_fdc> class ConcreteMachine:
|
||||
}
|
||||
|
||||
HalfCycles get_typer_frequency() const final {
|
||||
return Cycles(80'000); // Perform one key transition per frame.
|
||||
return Cycles(160'000); // Perform one key transition per frame and a half.
|
||||
}
|
||||
|
||||
// See header; sets a key as either pressed or released.
|
||||
|
||||
@@ -40,7 +40,7 @@ struct KeyboardMapper: public MachineTypes::MappedKeyboardMachine::KeyboardMappe
|
||||
struct CharacterMapper: public ::Utility::CharacterMapper {
|
||||
const uint16_t *sequence_for_character(char character) const override;
|
||||
|
||||
bool needs_pause_after_reset_all_keys() const override { return false; }
|
||||
bool needs_pause_after_reset_all_keys() const override { return true; }
|
||||
bool needs_pause_after_key(uint16_t key) const override;
|
||||
};
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
Keyboard(Processor *m6502) : m6502_(m6502) {}
|
||||
|
||||
void reset_all_keys() final {
|
||||
open_apple_is_pressed = closed_apple_is_pressed = key_is_down = false;
|
||||
open_apple_is_pressed = closed_apple_is_pressed = control_is_pressed = shift_is_pressed = key_is_down = false;
|
||||
}
|
||||
|
||||
bool set_key_pressed(Key key, char value, bool is_pressed) final {
|
||||
@@ -267,19 +267,49 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
case Key::Right: value = 0x15; break;
|
||||
case Key::Down: value = 0x0a; break;
|
||||
case Key::Up: value = 0x0b; break;
|
||||
case Key::Backspace: value = 0x7f; break;
|
||||
case Key::Backspace:
|
||||
if(is_iie()) {
|
||||
value = 0x7f;
|
||||
break;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case Key::Enter: value = 0x0d; break;
|
||||
case Key::Tab: value = '\t'; break;
|
||||
case Key::Tab:
|
||||
if (is_iie()) {
|
||||
value = '\t';
|
||||
break;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case Key::Escape: value = 0x1b; break;
|
||||
case Key::Space: value = 0x20; break;
|
||||
|
||||
case Key::LeftOption:
|
||||
case Key::RightMeta:
|
||||
open_apple_is_pressed = is_pressed;
|
||||
return true;
|
||||
if (is_iie()) {
|
||||
open_apple_is_pressed = is_pressed;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
case Key::RightOption:
|
||||
case Key::LeftMeta:
|
||||
closed_apple_is_pressed = is_pressed;
|
||||
if (is_iie()) {
|
||||
closed_apple_is_pressed = is_pressed;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
case Key::LeftControl:
|
||||
control_is_pressed = is_pressed;
|
||||
return true;
|
||||
|
||||
case Key::LeftShift:
|
||||
case Key::RightShift:
|
||||
shift_is_pressed = is_pressed;
|
||||
return true;
|
||||
|
||||
case Key::F1: case Key::F2: case Key::F3: case Key::F4:
|
||||
@@ -306,6 +336,30 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
|
||||
// Prior to the IIe, the keyboard could produce uppercase only.
|
||||
if(!is_iie()) value = char(toupper(value));
|
||||
|
||||
if(control_is_pressed && isalpha(value)) value &= 0xbf;
|
||||
|
||||
// TODO: properly map IIe keys
|
||||
if(!is_iie() && shift_is_pressed) {
|
||||
switch(value) {
|
||||
case 0x27: value = 0x22; break; // ' -> "
|
||||
case 0x2c: value = 0x3c; break; // , -> <
|
||||
case 0x2e: value = 0x3e; break; // . -> >
|
||||
case 0x2f: value = 0x3f; break; // / -> ?
|
||||
case 0x30: value = 0x29; break; // 0 -> )
|
||||
case 0x31: value = 0x21; break; // 1 -> !
|
||||
case 0x32: value = 0x40; break; // 2 -> @
|
||||
case 0x33: value = 0x23; break; // 3 -> #
|
||||
case 0x34: value = 0x24; break; // 4 -> $
|
||||
case 0x35: value = 0x25; break; // 5 -> %
|
||||
case 0x36: value = 0x5e; break; // 6 -> ^
|
||||
case 0x37: value = 0x26; break; // 7 -> &
|
||||
case 0x38: value = 0x2a; break; // 8 -> *
|
||||
case 0x39: value = 0x28; break; // 9 -> (
|
||||
case 0x3b: value = 0x3a; break; // ; -> :
|
||||
case 0x3d: value = 0x2b; break; // = -> +
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -313,7 +367,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
keyboard_input = uint8_t(value | 0x80);
|
||||
key_is_down = true;
|
||||
} else {
|
||||
if((keyboard_input & 0x7f) == value) {
|
||||
if((keyboard_input & 0x3f) == value) {
|
||||
key_is_down = false;
|
||||
}
|
||||
}
|
||||
@@ -329,6 +383,8 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
}
|
||||
}
|
||||
|
||||
bool shift_is_pressed = false;
|
||||
bool control_is_pressed = false;
|
||||
// The IIe has three keys that are wired directly to the same input as the joystick buttons.
|
||||
bool open_apple_is_pressed = false;
|
||||
bool closed_apple_is_pressed = false;
|
||||
@@ -767,7 +823,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
}
|
||||
|
||||
bool prefers_logical_input() final {
|
||||
return true;
|
||||
return is_iie();
|
||||
}
|
||||
|
||||
Inputs::Keyboard &get_keyboard() final {
|
||||
|
||||
@@ -271,7 +271,7 @@ class Keyboard {
|
||||
/// so this may not be valid prior to Mode::PerformingCommand.
|
||||
int command_ = 0;
|
||||
/// Populated during PerformingCommand as the response to the most-recently-received command, this
|
||||
/// is then shifted out to teh host computer. So it is guaranteed valid at the beginning of Mode::SendingResponse,
|
||||
/// is then shifted out to the host computer. So it is guaranteed valid at the beginning of Mode::SendingResponse,
|
||||
/// but not afterwards.
|
||||
int response_ = 0;
|
||||
|
||||
|
||||
@@ -607,7 +607,7 @@ template <bool has_scsi_bus> class ConcreteMachine:
|
||||
void set_activity_observer(Activity::Observer *observer) final {
|
||||
activity_observer_ = observer;
|
||||
if(activity_observer_) {
|
||||
activity_observer_->register_led(caps_led);
|
||||
activity_observer_->register_led(caps_led, Activity::Observer::LEDPresentation::Persistent);
|
||||
activity_observer_->set_led_status(caps_led, caps_led_state_);
|
||||
}
|
||||
|
||||
|
||||
341
Machines/Enterprise/Dave.cpp
Normal file
341
Machines/Enterprise/Dave.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
//
|
||||
// Dave.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 22/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Dave.hpp"
|
||||
|
||||
using namespace Enterprise::Dave;
|
||||
|
||||
// MARK: - Audio generator
|
||||
|
||||
Audio::Audio(Concurrency::DeferringAsyncTaskQueue &audio_queue) :
|
||||
audio_queue_(audio_queue) {}
|
||||
|
||||
void Audio::write(uint16_t address, uint8_t value) {
|
||||
address &= 0x1f;
|
||||
audio_queue_.defer([address, value, this] {
|
||||
switch(address) {
|
||||
case 0: case 2: case 4:
|
||||
channels_[address >> 1].reload = (channels_[address >> 1].reload & 0xff00) | value;
|
||||
break;
|
||||
case 1: case 3: case 5:
|
||||
channels_[address >> 1].reload = uint16_t((channels_[address >> 1].reload & 0x00ff) | ((value & 0xf) << 8));
|
||||
channels_[address >> 1].distortion = Channel::Distortion((value >> 4)&3);
|
||||
channels_[address >> 1].high_pass = value & 0x40;
|
||||
channels_[address >> 1].ring_modulate = value & 0x80;
|
||||
break;
|
||||
case 6:
|
||||
noise_.frequency = Noise::Frequency(value&3);
|
||||
noise_.polynomial = Noise::Polynomial((value >> 2)&3);
|
||||
noise_.swap_polynomial = value & 0x10;
|
||||
noise_.low_pass = value & 0x20;
|
||||
noise_.high_pass = value & 0x40;
|
||||
noise_.ring_modulate = value & 0x80;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
channels_[0].sync = value & 0x01;
|
||||
channels_[1].sync = value & 0x02;
|
||||
channels_[2].sync = value & 0x04;
|
||||
use_direct_output_[0] = value & 0x08;
|
||||
use_direct_output_[1] = value & 0x10;
|
||||
// Interrupt bits are handled separately.
|
||||
break;
|
||||
|
||||
case 8: case 9: case 10:
|
||||
channels_[address - 8].amplitude[0] = value & 0x3f;
|
||||
break;
|
||||
case 12: case 13: case 14:
|
||||
channels_[address - 12].amplitude[1] = value & 0x3f;
|
||||
break;
|
||||
case 11: noise_.amplitude[0] = value & 0x3f; break;
|
||||
case 15: noise_.amplitude[1] = value & 0x3f; break;
|
||||
|
||||
case 31:
|
||||
global_divider_reload_ = 2 + ((value >> 1)&1);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Audio::set_sample_volume_range(int16_t range) {
|
||||
audio_queue_.defer([range, this] {
|
||||
volume_ = range / (63*4);
|
||||
});
|
||||
}
|
||||
|
||||
void Audio::update_channel(int c) {
|
||||
auto output = channels_[c].output & 1;
|
||||
channels_[c].output <<= 1;
|
||||
if(channels_[c].sync) {
|
||||
channels_[c].count = channels_[c].reload;
|
||||
output = 0;
|
||||
} else {
|
||||
if(!channels_[c].count) {
|
||||
channels_[c].count = channels_[c].reload;
|
||||
|
||||
if(channels_[c].distortion == Channel::Distortion::None)
|
||||
output ^= 1;
|
||||
else
|
||||
output = poly_state_[int(channels_[c].distortion)];
|
||||
} else {
|
||||
--channels_[c].count;
|
||||
}
|
||||
|
||||
if(channels_[c].high_pass && (channels_[(c+1)%3].output&3) == 2) {
|
||||
output = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Ring modulation applies even when sync is enabled, per SIDBasic.
|
||||
if(channels_[c].ring_modulate) {
|
||||
output = ~(output ^ channels_[(c+2)%3].output) & 1;
|
||||
}
|
||||
|
||||
channels_[c].output |= output;
|
||||
}
|
||||
|
||||
void Audio::get_samples(std::size_t number_of_samples, int16_t *target) {
|
||||
struct Frame {
|
||||
int16_t left, right;
|
||||
} output_level;
|
||||
Frame *target_frames = reinterpret_cast<Frame *>(target);
|
||||
|
||||
size_t c = 0;
|
||||
while(c < number_of_samples) {
|
||||
// I'm unclear on the details of the time division multiplexing so,
|
||||
// for now, just sum the outputs.
|
||||
output_level.left =
|
||||
volume_ *
|
||||
(use_direct_output_[0] ?
|
||||
channels_[0].amplitude[0]
|
||||
: (
|
||||
channels_[0].amplitude[0] * (channels_[0].output & 1) +
|
||||
channels_[1].amplitude[0] * (channels_[1].output & 1) +
|
||||
channels_[2].amplitude[0] * (channels_[2].output & 1) +
|
||||
noise_.amplitude[0] * noise_.final_output
|
||||
));
|
||||
|
||||
output_level.right =
|
||||
volume_ *
|
||||
(use_direct_output_[1] ?
|
||||
channels_[0].amplitude[1]
|
||||
: (
|
||||
channels_[0].amplitude[1] * (channels_[0].output & 1) +
|
||||
channels_[1].amplitude[1] * (channels_[1].output & 1) +
|
||||
channels_[2].amplitude[1] * (channels_[2].output & 1) +
|
||||
noise_.amplitude[1] * noise_.final_output
|
||||
));
|
||||
|
||||
while(global_divider_ && c < number_of_samples) {
|
||||
--global_divider_;
|
||||
target_frames[c] = output_level;
|
||||
++c;
|
||||
}
|
||||
|
||||
global_divider_ = global_divider_reload_;
|
||||
if(!global_divider_) {
|
||||
global_divider_ = global_divider_reload_;
|
||||
}
|
||||
poly_state_[int(Channel::Distortion::FourBit)] = poly4_.next();
|
||||
poly_state_[int(Channel::Distortion::FiveBit)] = poly5_.next();
|
||||
poly_state_[int(Channel::Distortion::SevenBit)] = poly7_.next();
|
||||
if(noise_.swap_polynomial) {
|
||||
poly_state_[int(Channel::Distortion::SevenBit)] = poly_state_[int(Channel::Distortion::None)];
|
||||
}
|
||||
|
||||
// Update tone channels.
|
||||
update_channel(0);
|
||||
update_channel(1);
|
||||
update_channel(2);
|
||||
|
||||
// Update noise channel.
|
||||
|
||||
// Step 1: decide whether there is a tick to apply.
|
||||
bool noise_tick = false;
|
||||
if(noise_.frequency == Noise::Frequency::DivideByFour) {
|
||||
if(!noise_.count) {
|
||||
noise_tick = true;
|
||||
noise_.count = 3;
|
||||
} else {
|
||||
--noise_.count;
|
||||
}
|
||||
} else {
|
||||
noise_tick = (channels_[int(noise_.frequency) - 1].output&3) == 2;
|
||||
}
|
||||
|
||||
// Step 2: tick if necessary.
|
||||
int noise_output = noise_.output & 1;
|
||||
noise_.output <<= 1;
|
||||
if(noise_tick) {
|
||||
switch(noise_.polynomial) {
|
||||
case Noise::Polynomial::SeventeenBit:
|
||||
poly_state_[int(Channel::Distortion::None)] = uint8_t(poly17_.next());
|
||||
break;
|
||||
case Noise::Polynomial::FifteenBit:
|
||||
poly_state_[int(Channel::Distortion::None)] = uint8_t(poly15_.next());
|
||||
break;
|
||||
case Noise::Polynomial::ElevenBit:
|
||||
poly_state_[int(Channel::Distortion::None)] = uint8_t(poly11_.next());
|
||||
break;
|
||||
case Noise::Polynomial::NineBit:
|
||||
poly_state_[int(Channel::Distortion::None)] = uint8_t(poly9_.next());
|
||||
break;
|
||||
}
|
||||
|
||||
noise_output = poly_state_[int(Channel::Distortion::None)];
|
||||
}
|
||||
noise_.output |= noise_output;
|
||||
|
||||
// Low pass: sample channel 2 on downward transitions of the prima facie output.
|
||||
if(noise_.low_pass && (noise_.output & 3) == 2) {
|
||||
noise_.output = (noise_.output & ~1) | (channels_[2].output & 1);
|
||||
}
|
||||
|
||||
// Apply noise high-pass.
|
||||
if(noise_.high_pass && (channels_[0].output & 3) == 2) {
|
||||
noise_.output &= ~1;
|
||||
}
|
||||
|
||||
// Update noise ring modulation, if any.
|
||||
if(noise_.ring_modulate) {
|
||||
noise_.final_output = !((noise_.output ^ channels_[1].output) & 1);
|
||||
} else {
|
||||
noise_.final_output = noise_.output & 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Interrupt source
|
||||
|
||||
uint8_t TimedInterruptSource::get_new_interrupts() {
|
||||
const uint8_t result = interrupts_;
|
||||
interrupts_ = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
void TimedInterruptSource::write(uint16_t address, uint8_t value) {
|
||||
address &= 0x1f;
|
||||
switch(address) {
|
||||
default: break;
|
||||
|
||||
case 0: case 2:
|
||||
channels_[address >> 1].reload = (channels_[address >> 1].reload & 0xff00) | value;
|
||||
break;
|
||||
case 1: case 3:
|
||||
channels_[address >> 1].reload = uint16_t((channels_[address >> 1].reload & 0x00ff) | ((value & 0xf) << 8));
|
||||
break;
|
||||
|
||||
case 7:
|
||||
channels_[0].sync = value & 0x01;
|
||||
channels_[1].sync = value & 0x02;
|
||||
rate_ = InterruptRate((value >> 5) & 3);
|
||||
break;
|
||||
|
||||
case 31:
|
||||
global_divider_ = Cycles(2 + ((value >> 1)&1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TimedInterruptSource::update_channel(int c, bool is_linked, int decrement) {
|
||||
if(channels_[c].sync) {
|
||||
channels_[c].value = channels_[c].reload;
|
||||
} else {
|
||||
if(decrement <= channels_[c].value) {
|
||||
channels_[c].value -= decrement;
|
||||
} else {
|
||||
// The decrement is greater than the current value, therefore
|
||||
// there'll be at least one flip.
|
||||
//
|
||||
// After decreasing the decrement by the current value + 1,
|
||||
// it'll be clear how many decrements are left after reload.
|
||||
//
|
||||
// Dividing that by the number of decrements necessary for a
|
||||
// flip will provide the total number of flips.
|
||||
const int decrements_after_flip = decrement - (channels_[c].value + 1);
|
||||
const int num_flips = 1 + decrements_after_flip / (channels_[c].reload + 1);
|
||||
|
||||
// If this is a linked channel, set the interrupt mask if a transition
|
||||
// from high to low is amongst the included flips.
|
||||
if(is_linked && num_flips + channels_[c].level >= 2) {
|
||||
interrupts_ |= uint8_t(Interrupt::VariableFrequency);
|
||||
programmable_level_ ^= true;
|
||||
}
|
||||
channels_[c].level ^= (num_flips & 1);
|
||||
|
||||
// Apply the modulo number of decrements to the reload value to
|
||||
// figure out where things stand now.
|
||||
channels_[c].value = channels_[c].reload - decrements_after_flip % (channels_[c].reload + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimedInterruptSource::run_for(Cycles duration) {
|
||||
// Determine total number of ticks.
|
||||
run_length_ += duration;
|
||||
const Cycles cycles = run_length_.divide(global_divider_);
|
||||
if(cycles == Cycles(0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the two-second counter, from which the 1Hz, 50Hz and 1000Hz signals
|
||||
// are derived.
|
||||
const int previous_counter = two_second_counter_;
|
||||
two_second_counter_ = (two_second_counter_ + cycles.as<int>()) % 500'000;
|
||||
|
||||
// Check for a 1Hz rollover.
|
||||
if(previous_counter / 250'000 != two_second_counter_ / 250'000) {
|
||||
interrupts_ |= uint8_t(Interrupt::OneHz);
|
||||
}
|
||||
|
||||
// Check for 1kHz or 50Hz rollover;
|
||||
switch(rate_) {
|
||||
default: break;
|
||||
case InterruptRate::OnekHz:
|
||||
if(previous_counter / 250 != two_second_counter_ / 250) {
|
||||
interrupts_ |= uint8_t(Interrupt::VariableFrequency);
|
||||
programmable_level_ ^= true;
|
||||
}
|
||||
break;
|
||||
case InterruptRate::FiftyHz:
|
||||
if(previous_counter / 5'000 != two_second_counter_ / 5'000) {
|
||||
interrupts_ |= uint8_t(Interrupt::VariableFrequency);
|
||||
programmable_level_ ^= true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the two tone channels.
|
||||
update_channel(0, rate_ == InterruptRate::ToneGenerator0, cycles.as<int>());
|
||||
update_channel(1, rate_ == InterruptRate::ToneGenerator1, cycles.as<int>());
|
||||
}
|
||||
|
||||
Cycles TimedInterruptSource::get_next_sequence_point() const {
|
||||
// Since both the 1kHz and 50Hz timers are integer dividers of the 1Hz timer, there's no need
|
||||
// to factor that one in when determining the next sequence point for either of those.
|
||||
switch(rate_) {
|
||||
default:
|
||||
case InterruptRate::OnekHz: return Cycles(250 - (two_second_counter_ % 250));
|
||||
case InterruptRate::FiftyHz: return Cycles(5000 - (two_second_counter_ % 5000));
|
||||
|
||||
case InterruptRate::ToneGenerator0:
|
||||
case InterruptRate::ToneGenerator1: {
|
||||
const auto &channel = channels_[int(rate_) - int(InterruptRate::ToneGenerator0)];
|
||||
const int cycles_until_interrupt = channel.value + 1 + (!channel.level) * (channel.reload + 1);
|
||||
|
||||
return Cycles(std::min(
|
||||
250'000 - (two_second_counter_ % 250'000),
|
||||
cycles_until_interrupt
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t TimedInterruptSource::get_divider_state() {
|
||||
return uint8_t((two_second_counter_ / 250'000) * 4 | programmable_level_);
|
||||
}
|
||||
188
Machines/Enterprise/Dave.hpp
Normal file
188
Machines/Enterprise/Dave.hpp
Normal file
@@ -0,0 +1,188 @@
|
||||
//
|
||||
// Dave.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 22/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Dave_hpp
|
||||
#define Dave_hpp
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||
#include "../../Concurrency/AsyncTaskQueue.hpp"
|
||||
#include "../../Numeric/LFSR.hpp"
|
||||
#include "../../Outputs/Speaker/Implementation/SampleSource.hpp"
|
||||
|
||||
namespace Enterprise {
|
||||
namespace Dave {
|
||||
|
||||
enum class Interrupt: uint8_t {
|
||||
VariableFrequency = 0x02,
|
||||
OneHz = 0x08,
|
||||
Nick = 0x20,
|
||||
};
|
||||
|
||||
/*!
|
||||
Models the audio-production subset of Dave's behaviour.
|
||||
*/
|
||||
class Audio: public Outputs::Speaker::SampleSource {
|
||||
public:
|
||||
Audio(Concurrency::DeferringAsyncTaskQueue &audio_queue);
|
||||
|
||||
/// Modifies an register in the audio range; only the low 4 bits are
|
||||
/// used for register decoding so it's assumed that the caller has
|
||||
/// already identified this write as being to an audio register.
|
||||
void write(uint16_t address, uint8_t value);
|
||||
|
||||
// MARK: - SampleSource.
|
||||
void set_sample_volume_range(int16_t range);
|
||||
static constexpr bool get_is_stereo() { return true; } // Dave produces stereo sound.
|
||||
void get_samples(std::size_t number_of_samples, int16_t *target);
|
||||
|
||||
private:
|
||||
Concurrency::DeferringAsyncTaskQueue &audio_queue_;
|
||||
|
||||
// Global divider (i.e. 8MHz/12Mhz switch).
|
||||
uint8_t global_divider_;
|
||||
uint8_t global_divider_reload_ = 2;
|
||||
|
||||
// Tone channels.
|
||||
struct Channel {
|
||||
// User-set values.
|
||||
uint16_t reload = 0;
|
||||
bool high_pass = false;
|
||||
bool ring_modulate = false;
|
||||
enum class Distortion {
|
||||
None = 0,
|
||||
FourBit = 1,
|
||||
FiveBit = 2,
|
||||
SevenBit = 3,
|
||||
} distortion = Distortion::None;
|
||||
uint8_t amplitude[2]{};
|
||||
bool sync = false;
|
||||
|
||||
// Current state.
|
||||
uint16_t count = 0;
|
||||
int output = 0;
|
||||
} channels_[3];
|
||||
void update_channel(int);
|
||||
|
||||
// Noise channel.
|
||||
struct Noise {
|
||||
// User-set values.
|
||||
uint8_t amplitude[2]{};
|
||||
enum class Frequency {
|
||||
DivideByFour,
|
||||
ToneChannel0,
|
||||
ToneChannel1,
|
||||
ToneChannel2,
|
||||
} frequency = Frequency::DivideByFour;
|
||||
enum class Polynomial {
|
||||
SeventeenBit,
|
||||
FifteenBit,
|
||||
ElevenBit,
|
||||
NineBit
|
||||
} polynomial = Polynomial::SeventeenBit;
|
||||
bool swap_polynomial = false;
|
||||
bool low_pass = false;
|
||||
bool high_pass = false;
|
||||
bool ring_modulate = false;
|
||||
|
||||
// Current state.
|
||||
int count = 0;
|
||||
int output = 0;
|
||||
bool final_output = false;
|
||||
} noise_;
|
||||
void update_noise();
|
||||
|
||||
bool use_direct_output_[2]{};
|
||||
|
||||
// Global volume, per SampleSource obligations.
|
||||
int16_t volume_ = 0;
|
||||
|
||||
// Polynomials that are always running.
|
||||
Numeric::LFSRv<0xc> poly4_;
|
||||
Numeric::LFSRv<0x14> poly5_;
|
||||
Numeric::LFSRv<0x60> poly7_;
|
||||
|
||||
// The selectable, noise-related polynomial.
|
||||
Numeric::LFSRv<0x110> poly9_;
|
||||
Numeric::LFSRv<0x500> poly11_;
|
||||
Numeric::LFSRv<0x6000> poly15_;
|
||||
Numeric::LFSRv<0x12000> poly17_;
|
||||
|
||||
// Current state of the active polynomials.
|
||||
uint8_t poly_state_[4];
|
||||
};
|
||||
|
||||
/*!
|
||||
Provides Dave's timed interrupts — those that are provided at 1 kHz,
|
||||
50 Hz or according to the rate of tone generators 0 or 1, plus the fixed
|
||||
1 Hz interrupt.
|
||||
*/
|
||||
class TimedInterruptSource {
|
||||
public:
|
||||
/// Modifies an register in the audio range; only the low 4 bits are
|
||||
/// used for register decoding so it's assumed that the caller has
|
||||
/// already identified this write as being to an audio register.
|
||||
void write(uint16_t address, uint8_t value);
|
||||
|
||||
/// Returns a bitmask of interrupts that have become active since
|
||||
/// the last time this method was called; flags are as defined in
|
||||
/// @c Enterprise::Dave::Interrupt
|
||||
uint8_t get_new_interrupts();
|
||||
|
||||
/// Returns the current high or low states of the inputs that trigger
|
||||
/// the interrupts modelled here, as a bit mask compatible with that
|
||||
/// exposed by Dave as the register at 0xb4.
|
||||
uint8_t get_divider_state();
|
||||
|
||||
/// Advances the interrupt source.
|
||||
void run_for(Cycles);
|
||||
|
||||
/// @returns The amount of time from now until the earliest that
|
||||
/// @c get_new_interrupts() _might_ have new interrupts to report.
|
||||
Cycles get_next_sequence_point() const;
|
||||
|
||||
private:
|
||||
static constexpr Cycles clock_rate{250000};
|
||||
static constexpr Cycles half_clock_rate{125000};
|
||||
|
||||
// Global divider (i.e. 8MHz/12Mhz switch).
|
||||
Cycles global_divider_ = Cycles(2);
|
||||
Cycles run_length_;
|
||||
|
||||
// Interrupts that have fired since get_new_interrupts()
|
||||
// was last called.
|
||||
uint8_t interrupts_ = 0;
|
||||
|
||||
// A counter for the 1Hz interrupt.
|
||||
int two_second_counter_ = 0;
|
||||
|
||||
// A counter specific to the 1kHz and 50Hz timers, if in use.
|
||||
enum class InterruptRate {
|
||||
OnekHz,
|
||||
FiftyHz,
|
||||
ToneGenerator0,
|
||||
ToneGenerator1,
|
||||
} rate_ = InterruptRate::OnekHz;
|
||||
bool programmable_level_ = false;
|
||||
|
||||
// A local duplicate of the counting state of the first two audio
|
||||
// channels, maintained in case either of those is used as an
|
||||
// interrupt source.
|
||||
struct Channel {
|
||||
int value = 100, reload = 100;
|
||||
bool sync = false;
|
||||
bool level = false;
|
||||
} channels_[2];
|
||||
void update_channel(int c, bool is_linked, int decrement);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Dave_hpp */
|
||||
78
Machines/Enterprise/EXDos.cpp
Normal file
78
Machines/Enterprise/EXDos.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// EXDos.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 20/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "EXDos.hpp"
|
||||
|
||||
// TODO: disk_did_change_ should be on the drive. Some drives report it.
|
||||
|
||||
using namespace Enterprise;
|
||||
|
||||
EXDos::EXDos() : WD1770(P1770) {
|
||||
emplace_drives(4, 8000000, 300, 2);
|
||||
set_control_register(0x00);
|
||||
}
|
||||
|
||||
void EXDos::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, size_t drive) {
|
||||
get_drive(drive).set_disk(disk);
|
||||
disk_did_change_ = true;
|
||||
}
|
||||
|
||||
// Documentation for the control register:
|
||||
//
|
||||
// Write:
|
||||
// b7 in use (???)
|
||||
// b6 disk change reset
|
||||
// b5 0 = double density, 1 = single density
|
||||
// b4 side 1 select
|
||||
// b3, b3, b1, b0 select drive 3, 2, 1, 0
|
||||
//
|
||||
// Read:
|
||||
// b7 data request from WD1770
|
||||
// b6 disk change
|
||||
// b5, b4, b3, b2: not used
|
||||
// b1 interrupt request from WD1770
|
||||
// b0 drive ready
|
||||
|
||||
void EXDos::set_control_register(uint8_t control) {
|
||||
if(control & 0x40) disk_did_change_ = false;
|
||||
set_is_double_density(!(control & 0x20));
|
||||
|
||||
// Set side.
|
||||
const int head = (control >> 4) & 1;
|
||||
for(size_t c = 0; c < 4; c++) {
|
||||
get_drive(c).set_head(head);
|
||||
}
|
||||
|
||||
// Select drive, ensuring handover of the motor-on state.
|
||||
const bool motor_state = get_drive().get_motor_on();
|
||||
for_all_drives([] (Storage::Disk::Drive &drive, size_t) {
|
||||
drive.set_motor_on(false);
|
||||
});
|
||||
set_drive(control & 0xf);
|
||||
get_drive().set_motor_on(motor_state);
|
||||
}
|
||||
|
||||
uint8_t EXDos::get_control_register() {
|
||||
const uint8_t status =
|
||||
(get_data_request_line() ? 0x80 : 0x00) |
|
||||
(disk_did_change_ ? 0x40 : 0x00) |
|
||||
(get_interrupt_request_line() ? 0x02 : 0x00) |
|
||||
(get_drive().get_is_ready() ? 0x01 : 0x00);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void EXDos::set_motor_on(bool on) {
|
||||
get_drive().set_motor_on(on);
|
||||
}
|
||||
|
||||
void EXDos::set_activity_observer(Activity::Observer *observer) {
|
||||
for_all_drives([observer] (Storage::Disk::Drive &drive, size_t index) {
|
||||
drive.set_activity_observer(observer, "Drive " + std::to_string(index+1), true);
|
||||
});
|
||||
}
|
||||
36
Machines/Enterprise/EXDos.hpp
Normal file
36
Machines/Enterprise/EXDos.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// EXDos.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 20/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef EXDos_hpp
|
||||
#define EXDos_hpp
|
||||
|
||||
#include "../../Components/1770/1770.hpp"
|
||||
#include "../../Activity/Observer.hpp"
|
||||
|
||||
namespace Enterprise {
|
||||
|
||||
class EXDos final : public WD::WD1770 {
|
||||
public:
|
||||
EXDos();
|
||||
|
||||
void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, size_t drive);
|
||||
|
||||
void set_control_register(uint8_t control);
|
||||
uint8_t get_control_register();
|
||||
|
||||
void set_activity_observer(Activity::Observer *observer);
|
||||
|
||||
private:
|
||||
bool disk_did_change_ = false;
|
||||
|
||||
void set_motor_on(bool on) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* EXDos_hpp */
|
||||
765
Machines/Enterprise/Enterprise.cpp
Normal file
765
Machines/Enterprise/Enterprise.cpp
Normal file
@@ -0,0 +1,765 @@
|
||||
//
|
||||
// Enterprise.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 10/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Enterprise.hpp"
|
||||
|
||||
#include "Dave.hpp"
|
||||
#include "EXDos.hpp"
|
||||
#include "Keyboard.hpp"
|
||||
#include "Nick.hpp"
|
||||
|
||||
#include "../MachineTypes.hpp"
|
||||
#include "../Utility/Typer.hpp"
|
||||
|
||||
#include "../../Analyser/Static/Enterprise/Target.hpp"
|
||||
#include "../../ClockReceiver/JustInTime.hpp"
|
||||
#include "../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
|
||||
#include "../../Processors/Z80/Z80.hpp"
|
||||
|
||||
#define LOG_PREFIX "[Enterprise] "
|
||||
#include "../../Outputs/Log.hpp"
|
||||
|
||||
namespace Enterprise {
|
||||
|
||||
/*
|
||||
Notes to self on timing:
|
||||
|
||||
Nick divides each line into 57 windows; each window lasts 16 cycles and dedicates the
|
||||
first 10 of those to VRAM accesses, leaving the final six for a Z80 video RAM access
|
||||
if one has been requested.
|
||||
|
||||
The Z80 has a separate, asynchronous 4Mhz clock. That's that.
|
||||
|
||||
The documentation is also very forward in emphasising that Nick generates phaselocked
|
||||
(i.e. in-phase) PAL video.
|
||||
|
||||
So: 57*16 = 912 cycles/line.
|
||||
|
||||
A standard PAL line lasts 64µs and during that time outputs 283.7516 colour cycles.
|
||||
|
||||
I shall _guess_ that the Enterprise stretches each line to 284 colour cycles rather than
|
||||
reducing it to 283.
|
||||
|
||||
Therefore 912 cycles occurs in 284/283.7516 * 64 µs.
|
||||
|
||||
So one line = 181760000 / 2837516 µs = 45440000 / 709379 µs
|
||||
=> one cycle = 45440000 / 709379*912 = 45440000 / 646953648 = 2840000 / 40434603 µs
|
||||
=> clock rate of 40434603 / 2840000 Mhz
|
||||
|
||||
And, therefore, the ratio to a 4Mhz Z80 clock is:
|
||||
|
||||
40434603 / (2840000 * 4)
|
||||
= 40434603 / 11360000
|
||||
i.e. roughly 3.55 Nick cycles per Z80 cycle.
|
||||
|
||||
If that's true then the 6-cycle window is around 1.69 Z80 cycles long. Given that the Z80
|
||||
clock in an Enterprise can be stopped in half-cycle increments only, the Z80 can only be
|
||||
guaranteed to have around a 1.19 cycle minimum for its actual access. I'm therefore further
|
||||
postulating that the clock stoppage takes place so as to align the final cycle of a relevant
|
||||
access over the available window.
|
||||
|
||||
*/
|
||||
|
||||
template <bool has_disk_controller, bool is_6mhz> class ConcreteMachine:
|
||||
public Activity::Source,
|
||||
public Configurable::Device,
|
||||
public CPU::Z80::BusHandler,
|
||||
public Machine,
|
||||
public MachineTypes::AudioProducer,
|
||||
public MachineTypes::MappedKeyboardMachine,
|
||||
public MachineTypes::MediaTarget,
|
||||
public MachineTypes::ScanProducer,
|
||||
public MachineTypes::TimedMachine,
|
||||
public Utility::TypeRecipient<CharacterMapper> {
|
||||
private:
|
||||
constexpr uint8_t min_ram_slot(const Analyser::Static::Enterprise::Target &target) {
|
||||
size_t ram_size = 128*1024;
|
||||
switch(target.model) {
|
||||
case Analyser::Static::Enterprise::Target::Model::Enterprise64: ram_size = 64*1024; break;
|
||||
case Analyser::Static::Enterprise::Target::Model::Enterprise128: ram_size = 128*1024; break;
|
||||
case Analyser::Static::Enterprise::Target::Model::Enterprise256: ram_size = 256*1024; break;
|
||||
}
|
||||
|
||||
return uint8_t(0x100 - ram_size / 0x4000);
|
||||
}
|
||||
|
||||
static constexpr double clock_rate = is_6mhz ? 6'000'000.0 : 4'000'000.0;
|
||||
using NickType =
|
||||
std::conditional_t<is_6mhz,
|
||||
JustInTimeActor<Nick, HalfCycles, 13478201, 5680000>,
|
||||
JustInTimeActor<Nick, HalfCycles, 40434603, 11360000>>;
|
||||
|
||||
public:
|
||||
ConcreteMachine(const Analyser::Static::Enterprise::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
|
||||
min_ram_slot_(min_ram_slot(target)),
|
||||
z80_(*this),
|
||||
nick_(ram_.end() - 65536),
|
||||
dave_audio_(audio_queue_),
|
||||
speaker_(dave_audio_) {
|
||||
|
||||
// Request a clock of 4Mhz; this'll be mapped upwards for Nick and downwards for Dave elsewhere.
|
||||
set_clock_rate(clock_rate);
|
||||
speaker_.set_input_rate(float(clock_rate) / float(dave_divider));
|
||||
|
||||
ROM::Request request;
|
||||
using Target = Analyser::Static::Enterprise::Target;
|
||||
|
||||
// Pick one or more EXOS ROMs.
|
||||
switch(target.exos_version) {
|
||||
case Target::EXOSVersion::v10: request = request && ROM::Request(ROM::Name::EnterpriseEXOS10); break;
|
||||
case Target::EXOSVersion::v20: request = request && ROM::Request(ROM::Name::EnterpriseEXOS20); break;
|
||||
case Target::EXOSVersion::v21: request = request && ROM::Request(ROM::Name::EnterpriseEXOS21); break;
|
||||
case Target::EXOSVersion::v23: request = request && ROM::Request(ROM::Name::EnterpriseEXOS23); break;
|
||||
case Target::EXOSVersion::Any:
|
||||
request =
|
||||
request && (
|
||||
ROM::Request(ROM::Name::EnterpriseEXOS10) || ROM::Request(ROM::Name::EnterpriseEXOS20) ||
|
||||
ROM::Request(ROM::Name::EnterpriseEXOS21) || ROM::Request(ROM::Name::EnterpriseEXOS23)
|
||||
);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Similarly pick one or more BASIC ROMs.
|
||||
switch(target.basic_version) {
|
||||
case Target::BASICVersion::v10:
|
||||
request = request && (
|
||||
ROM::Request(ROM::Name::EnterpriseBASIC10) ||
|
||||
(ROM::Request(ROM::Name::EnterpriseBASIC10Part1) && ROM::Request(ROM::Name::EnterpriseBASIC10Part2))
|
||||
);
|
||||
break;
|
||||
case Target::BASICVersion::v11:
|
||||
request = request && (
|
||||
ROM::Request(ROM::Name::EnterpriseBASIC11) ||
|
||||
ROM::Request(ROM::Name::EnterpriseBASIC11Suffixed)
|
||||
);
|
||||
case Target::BASICVersion::v21:
|
||||
request = request && ROM::Request(ROM::Name::EnterpriseBASIC21);
|
||||
break;
|
||||
case Target::BASICVersion::Any:
|
||||
request =
|
||||
request && (
|
||||
ROM::Request(ROM::Name::EnterpriseBASIC10) ||
|
||||
(ROM::Request(ROM::Name::EnterpriseBASIC10Part1) && ROM::Request(ROM::Name::EnterpriseBASIC10Part2)) ||
|
||||
ROM::Request(ROM::Name::EnterpriseBASIC11) ||
|
||||
ROM::Request(ROM::Name::EnterpriseBASIC21)
|
||||
);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Possibly add in a DOS.
|
||||
switch(target.dos) {
|
||||
case Target::DOS::EXDOS: request = request && ROM::Request(ROM::Name::EnterpriseEXDOS); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Get and validate ROMs.
|
||||
auto roms = rom_fetcher(request);
|
||||
if(!request.validate(roms)) {
|
||||
throw ROMMachine::Error::MissingROMs;
|
||||
}
|
||||
|
||||
// Extract the appropriate EXOS ROM.
|
||||
exos_.fill(0xff);
|
||||
for(const auto rom_name: { ROM::Name::EnterpriseEXOS10, ROM::Name::EnterpriseEXOS20, ROM::Name::EnterpriseEXOS21, ROM::Name::EnterpriseEXOS23 }) {
|
||||
const auto exos = roms.find(rom_name);
|
||||
if(exos != roms.end()) {
|
||||
memcpy(exos_.data(), exos->second.data(), std::min(exos_.size(), exos->second.size()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the appropriate BASIC ROM[s] (if any).
|
||||
basic_.fill(0xff);
|
||||
bool has_basic = false;
|
||||
for(const auto rom_name: { ROM::Name::EnterpriseBASIC10, ROM::Name::EnterpriseBASIC11, ROM::Name::EnterpriseBASIC11Suffixed, ROM::Name::EnterpriseBASIC21 }) {
|
||||
const auto basic = roms.find(rom_name);
|
||||
if(basic != roms.end()) {
|
||||
memcpy(basic_.data(), basic->second.data(), std::min(basic_.size(), basic->second.size()));
|
||||
has_basic = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!has_basic) {
|
||||
const auto basic1 = roms.find(ROM::Name::EnterpriseBASIC10Part1);
|
||||
const auto basic2 = roms.find(ROM::Name::EnterpriseBASIC10Part2);
|
||||
if(basic1 != roms.end() && basic2 != roms.end()) {
|
||||
memcpy(&basic_[0x0000], basic1->second.data(), std::min(size_t(8192), basic1->second.size()));
|
||||
memcpy(&basic_[0x2000], basic2->second.data(), std::min(size_t(8192), basic2->second.size()));
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the appropriate DOS ROMs.
|
||||
epdos_rom_.fill(0xff);
|
||||
const auto epdos = roms.find(ROM::Name::EnterpriseEPDOS);
|
||||
if(epdos != roms.end()) {
|
||||
memcpy(epdos_rom_.data(), epdos->second.data(), std::min(epdos_rom_.size(), epdos->second.size()));
|
||||
}
|
||||
exdos_rom_.fill(0xff);
|
||||
const auto exdos = roms.find(ROM::Name::EnterpriseEXDOS);
|
||||
if(exdos != roms.end()) {
|
||||
memcpy(exdos_rom_.data(), exdos->second.data(), std::min(exdos_rom_.size(), exdos->second.size()));
|
||||
}
|
||||
|
||||
// Seed key state.
|
||||
clear_all_keys();
|
||||
|
||||
// Take a reasonable guess at the initial memory configuration:
|
||||
// put EXOS into the first bank since this is a Z80 and therefore
|
||||
// starts from address 0; the third instruction in EXOS is a jump
|
||||
// to $c02e so it's reasonable to assume EXOS is in the highest bank
|
||||
// too, and it appears to act correctly if it's the first 16kb that's
|
||||
// in the highest bank. From there I guess: all banks are initialised
|
||||
// to 0.
|
||||
page<0>(0x00);
|
||||
page<1>(0x00);
|
||||
page<2>(0x00);
|
||||
page<3>(0x00);
|
||||
|
||||
// Pass on any media.
|
||||
insert_media(target.media);
|
||||
if(!target.loading_command.empty()) {
|
||||
type_string(target.loading_command);
|
||||
}
|
||||
|
||||
// Ensure the splash screen is automatically skipped if any media has been provided.
|
||||
if(!target.media.empty()) {
|
||||
should_skip_splash_screen_ = !target.media.empty();
|
||||
typer_delay_ = 2;
|
||||
}
|
||||
}
|
||||
|
||||
~ConcreteMachine() {
|
||||
audio_queue_.flush();
|
||||
}
|
||||
|
||||
// MARK: - Z80::BusHandler.
|
||||
forceinline void advance_nick(HalfCycles duration) {
|
||||
if(nick_ += duration) {
|
||||
const auto nick = nick_.last_valid();
|
||||
const bool nick_interrupt_line = nick->get_interrupt_line();
|
||||
if(nick_interrupt_line && !previous_nick_interrupt_line_) {
|
||||
set_interrupts(uint8_t(Dave::Interrupt::Nick), nick_.last_sequence_point_overrun());
|
||||
}
|
||||
previous_nick_interrupt_line_ = nick_interrupt_line;
|
||||
}
|
||||
}
|
||||
|
||||
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
|
||||
using PartialMachineCycle = CPU::Z80::PartialMachineCycle;
|
||||
const uint16_t address = cycle.address ? *cycle.address : 0x0000;
|
||||
|
||||
// Calculate an access penalty, if applicable.
|
||||
//
|
||||
// Rule applied here, which is slightly inferred:
|
||||
//
|
||||
// Non-video reads and writes are delayed by exactly a cycle or not delayed at all,
|
||||
// depending on the programmer's configuration of Dave.
|
||||
//
|
||||
// Video reads and writes, and Nick port accesses, are delayed so that the last
|
||||
// clock cycle of the machine cycle falls wholly inside the designated Z80 access
|
||||
// window, per Nick.
|
||||
//
|
||||
// The switch statement below just attempts to implement that logic.
|
||||
//
|
||||
HalfCycles penalty;
|
||||
switch(cycle.operation) {
|
||||
default: break;
|
||||
|
||||
// For non-video pauses, insert during the initial part of the bus cycle.
|
||||
case PartialMachineCycle::ReadStart:
|
||||
case PartialMachineCycle::WriteStart:
|
||||
if(!is_video_[address >> 14] && wait_mode_ == WaitMode::OnAllAccesses) {
|
||||
penalty = dave_delay_;
|
||||
}
|
||||
break;
|
||||
case PartialMachineCycle::ReadOpcodeStart: {
|
||||
if(is_video_[address >> 14]) {
|
||||
// Query Nick for the amount of delay that would occur with one cycle left
|
||||
// in this read opcode.
|
||||
const auto delay_time = nick_.time_since_flush(HalfCycles(2));
|
||||
const auto delay = nick_.last_valid()->get_time_until_z80_slot(delay_time);
|
||||
penalty = nick_.back_map(delay, delay_time);
|
||||
} else if(wait_mode_ != WaitMode::None) {
|
||||
penalty = dave_delay_;
|
||||
}
|
||||
} break;
|
||||
|
||||
// Video pauses: insert right at the end of the bus cycle.
|
||||
case PartialMachineCycle::Write:
|
||||
// Ensure all video that should have been collected prior to
|
||||
// this write has been.
|
||||
if(is_video_[address >> 14]) {
|
||||
nick_.flush();
|
||||
}
|
||||
[[fallthrough]];
|
||||
|
||||
case PartialMachineCycle::Read:
|
||||
if(is_video_[address >> 14]) {
|
||||
// Get delay, in Nick cycles, for a Z80 access that occurs in 0.5
|
||||
// cycles from now (i.e. with one cycle left to run).
|
||||
const auto delay_time = nick_.time_since_flush(HalfCycles(1));
|
||||
const auto delay = nick_.last_valid()->get_time_until_z80_slot(delay_time);
|
||||
penalty = nick_.back_map(delay, delay_time);
|
||||
}
|
||||
break;
|
||||
|
||||
case PartialMachineCycle::Input:
|
||||
case PartialMachineCycle::Output: {
|
||||
if((address & 0xf0) == 0x80) {
|
||||
// Get delay, in Nick cycles, for a Z80 access that occurs in 0.5
|
||||
// cycles from now (i.e. with one cycle left to run).
|
||||
const auto delay_time = nick_.time_since_flush(HalfCycles(1));
|
||||
const auto delay = nick_.last_valid()->get_time_until_z80_slot(delay_time);
|
||||
penalty = nick_.back_map(delay, delay_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const HalfCycles full_length = cycle.length + penalty;
|
||||
time_since_audio_update_ += full_length;
|
||||
advance_nick(full_length);
|
||||
if(dave_timer_ += full_length) {
|
||||
set_interrupts(dave_timer_.last_valid()->get_new_interrupts(), dave_timer_.last_sequence_point_overrun());
|
||||
}
|
||||
|
||||
// The WD/etc runs at a nominal 8Mhz.
|
||||
if constexpr (has_disk_controller) {
|
||||
exdos_.run_for(Cycles(full_length.as_integral()));
|
||||
}
|
||||
|
||||
switch(cycle.operation) {
|
||||
default: break;
|
||||
|
||||
case PartialMachineCycle::Interrupt:
|
||||
*cycle.value = 0xff;
|
||||
break;
|
||||
|
||||
case PartialMachineCycle::Input:
|
||||
switch(address & 0xff) {
|
||||
default:
|
||||
LOG("Unhandled input from " << PADHEX(2) << (address & 0xff));
|
||||
*cycle.value = 0xff;
|
||||
break;
|
||||
|
||||
case 0x10: case 0x11: case 0x12: case 0x13:
|
||||
case 0x14: case 0x15: case 0x16: case 0x17:
|
||||
if constexpr (has_disk_controller) {
|
||||
*cycle.value = exdos_.read(address);
|
||||
} else {
|
||||
*cycle.value = 0xff;
|
||||
}
|
||||
break;
|
||||
case 0x18: case 0x19: case 0x1a: case 0x1b:
|
||||
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
|
||||
if constexpr (has_disk_controller) {
|
||||
*cycle.value = exdos_.get_control_register();
|
||||
} else {
|
||||
*cycle.value = 0xff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x80: case 0x81: case 0x82: case 0x83:
|
||||
case 0x84: case 0x85: case 0x86: case 0x87:
|
||||
case 0x88: case 0x89: case 0x8a: case 0x8b:
|
||||
case 0x8c: case 0x8d: case 0x8e: case 0x8f:
|
||||
*cycle.value = nick_->read();
|
||||
break;
|
||||
|
||||
case 0xb0: *cycle.value = pages_[0]; break;
|
||||
case 0xb1: *cycle.value = pages_[1]; break;
|
||||
case 0xb2: *cycle.value = pages_[2]; break;
|
||||
case 0xb3: *cycle.value = pages_[3]; break;
|
||||
|
||||
case 0xb4:
|
||||
*cycle.value =
|
||||
(nick_->get_interrupt_line() ? 0x10 : 0x00) |
|
||||
dave_timer_->get_divider_state() |
|
||||
interrupt_state_;
|
||||
break;
|
||||
case 0xb5:
|
||||
if(active_key_line_ < key_lines_.size()) {
|
||||
*cycle.value = key_lines_[active_key_line_];
|
||||
} else {
|
||||
*cycle.value = 0xff;
|
||||
}
|
||||
break;
|
||||
case 0xb6: {
|
||||
// TODO: selected keyboard row, 0 to 9, should return one bit of joystick
|
||||
// input. That being the case:
|
||||
//
|
||||
// b0: joystick input
|
||||
// b1, b2: unused (in theory read from control port, but not used by any hardware)
|
||||
// b3: 0 = printer ready; 1 = not ready
|
||||
// b4: serial, data in
|
||||
// b5: serial, status in
|
||||
// b6: tape input volume level, 0 = high, 1 = low
|
||||
// b7: tape data input
|
||||
*cycle.value = 0xff;
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PartialMachineCycle::Output:
|
||||
switch(address & 0xff) {
|
||||
default:
|
||||
LOG("Unhandled output: " << PADHEX(2) << *cycle.value << " to " << PADHEX(2) << (address & 0xff));
|
||||
break;
|
||||
|
||||
case 0x10: case 0x11: case 0x12: case 0x13:
|
||||
case 0x14: case 0x15: case 0x16: case 0x17:
|
||||
if constexpr(has_disk_controller) {
|
||||
exdos_.write(address, *cycle.value);
|
||||
}
|
||||
break;
|
||||
case 0x18: case 0x19: case 0x1a: case 0x1b:
|
||||
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
|
||||
if constexpr(has_disk_controller) {
|
||||
exdos_.set_control_register(*cycle.value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x80: case 0x81: case 0x82: case 0x83:
|
||||
case 0x84: case 0x85: case 0x86: case 0x87:
|
||||
case 0x88: case 0x89: case 0x8a: case 0x8b:
|
||||
case 0x8c: case 0x8d: case 0x8e: case 0x8f:
|
||||
nick_->write(address, *cycle.value);
|
||||
break;
|
||||
|
||||
case 0xb0: page<0>(*cycle.value); break;
|
||||
case 0xb1: page<1>(*cycle.value); break;
|
||||
case 0xb2: page<2>(*cycle.value); break;
|
||||
case 0xb3: page<3>(*cycle.value); break;
|
||||
|
||||
case 0xbf:
|
||||
switch((*cycle.value >> 2)&3) {
|
||||
default: wait_mode_ = WaitMode::None; break;
|
||||
case 0: wait_mode_ = WaitMode::OnAllAccesses; break;
|
||||
case 1: wait_mode_ = WaitMode::OnM1; break;
|
||||
}
|
||||
|
||||
// Dave delays (i.e. those affecting memory areas not associated with Nick)
|
||||
// are one cycle in 8Mhz mode, two cycles in 12Mhz mode.
|
||||
dave_delay_ = HalfCycles(2 + ((*cycle.value)&2));
|
||||
|
||||
[[fallthrough]];
|
||||
|
||||
case 0xa0: case 0xa1: case 0xa2: case 0xa3:
|
||||
case 0xa4: case 0xa5: case 0xa6: case 0xa7:
|
||||
case 0xa8: case 0xa9: case 0xaa: case 0xab:
|
||||
case 0xac: case 0xad: case 0xae: case 0xaf:
|
||||
update_audio();
|
||||
dave_audio_.write(address, *cycle.value);
|
||||
dave_timer_->write(address, *cycle.value);
|
||||
break;
|
||||
|
||||
case 0xb4:
|
||||
interrupt_mask_ = *cycle.value & 0x55;
|
||||
interrupt_state_ &= ~*cycle.value;
|
||||
update_interrupts();
|
||||
break;
|
||||
case 0xb5:
|
||||
// Logic here: the ROM scans the keyboard by checking ascending
|
||||
// lines. It also seems to provide a line of 0 when using port B5
|
||||
// for non-keyboard uses.
|
||||
//
|
||||
// So: use the rollover from line 9 back to line 0 as a trigger to
|
||||
// spot that a scan of the keyboard just finished. Which makes it
|
||||
// time to enqueue the next keypress.
|
||||
//
|
||||
// Re: should_skip_splash_screen_ and typer_delay_, assume that a
|
||||
// single keypress is necessary to get past the Enterprise splash
|
||||
// screen, then a pause in keypressing while BASIC or whatever
|
||||
// starts up, then presses can resume.
|
||||
if(active_key_line_ == 9 && !(*cycle.value & 0xf) && (should_skip_splash_screen_ || typer_)) {
|
||||
if(should_skip_splash_screen_) {
|
||||
set_key_state(uint16_t(Key::Space), typer_delay_);
|
||||
if(typer_delay_) {
|
||||
--typer_delay_;
|
||||
} else {
|
||||
typer_delay_ = 60;
|
||||
should_skip_splash_screen_ = false;
|
||||
}
|
||||
} else {
|
||||
if(!typer_delay_) {
|
||||
if(!typer_->type_next_character()) {
|
||||
clear_all_keys();
|
||||
typer_ = nullptr;
|
||||
}
|
||||
} else {
|
||||
--typer_delay_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
active_key_line_ = *cycle.value & 0xf;
|
||||
// TODO:
|
||||
//
|
||||
// b4: strobe output for printer
|
||||
// b5: tape sound control (?)
|
||||
// b6: tape motor control 1, 1 = on
|
||||
// b7: tape motor control 2, 1 = on
|
||||
break;
|
||||
case 0xb6:
|
||||
// Just 8 bits of printer data.
|
||||
LOG("TODO: printer output " << PADHEX(2) << *cycle.value);
|
||||
break;
|
||||
case 0xb7:
|
||||
// b0 = serial data out
|
||||
// b1 = serial status out
|
||||
LOG("TODO: serial output " << PADHEX(2) << *cycle.value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PartialMachineCycle::Read:
|
||||
case PartialMachineCycle::ReadOpcode:
|
||||
if(read_pointers_[address >> 14]) {
|
||||
*cycle.value = read_pointers_[address >> 14][address];
|
||||
} else {
|
||||
*cycle.value = 0xff;
|
||||
}
|
||||
break;
|
||||
|
||||
case PartialMachineCycle::Write:
|
||||
if(write_pointers_[address >> 14]) {
|
||||
write_pointers_[address >> 14][address] = *cycle.value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return penalty;
|
||||
}
|
||||
|
||||
void flush() {
|
||||
nick_.flush();
|
||||
update_audio();
|
||||
audio_queue_.perform();
|
||||
}
|
||||
|
||||
private:
|
||||
// MARK: - Memory layout
|
||||
std::array<uint8_t, 256 * 1024> ram_{};
|
||||
std::array<uint8_t, 64 * 1024> exos_;
|
||||
std::array<uint8_t, 16 * 1024> basic_;
|
||||
std::array<uint8_t, 16 * 1024> exdos_rom_;
|
||||
std::array<uint8_t, 32 * 1024> epdos_rom_;
|
||||
const uint8_t min_ram_slot_;
|
||||
|
||||
const uint8_t *read_pointers_[4] = {nullptr, nullptr, nullptr, nullptr};
|
||||
uint8_t *write_pointers_[4] = {nullptr, nullptr, nullptr, nullptr};
|
||||
uint8_t pages_[4] = {0x80, 0x80, 0x80, 0x80};
|
||||
|
||||
template <size_t slot> void page(uint8_t offset) {
|
||||
pages_[slot] = offset;
|
||||
|
||||
#define Map(location, source) \
|
||||
if(offset >= location && offset < location + source.size() / 0x4000) { \
|
||||
page<slot>(&source[(offset - location) * 0x4000], nullptr); \
|
||||
is_video_[slot] = false; \
|
||||
return; \
|
||||
}
|
||||
|
||||
Map(0, exos_);
|
||||
Map(16, basic_);
|
||||
Map(32, exdos_rom_);
|
||||
Map(48, epdos_rom_);
|
||||
|
||||
#undef Map
|
||||
|
||||
// Of whatever size of RAM I've declared above, use only the final portion.
|
||||
// This correlated with Nick always having been handed the final 64kb and,
|
||||
// at least while the RAM is the first thing declared above, does a little
|
||||
// to benefit data locality. Albeit not in a useful sense.
|
||||
if(offset >= min_ram_slot_) {
|
||||
const auto ram_floor = 4194304 - ram_.size();
|
||||
const size_t address = offset * 0x4000 - ram_floor;
|
||||
is_video_[slot] = offset >= 0xfc; // TODO: this hard-codes a 64kb video assumption.
|
||||
page<slot>(&ram_[address], &ram_[address]);
|
||||
return;
|
||||
}
|
||||
|
||||
page<slot>(nullptr, nullptr);
|
||||
}
|
||||
|
||||
template <size_t slot> void page(const uint8_t *read, uint8_t *write) {
|
||||
read_pointers_[slot] = read ? read - (slot * 0x4000) : nullptr;
|
||||
write_pointers_[slot] = write ? write - (slot * 0x4000) : nullptr;
|
||||
}
|
||||
|
||||
// MARK: - Memory Timing
|
||||
|
||||
// The wait mode affects all memory accesses _outside of the video area_.
|
||||
enum class WaitMode {
|
||||
None,
|
||||
OnM1,
|
||||
OnAllAccesses
|
||||
} wait_mode_ = WaitMode::OnAllAccesses;
|
||||
bool is_video_[4]{};
|
||||
|
||||
// MARK: - ScanProducer
|
||||
void set_scan_target(Outputs::Display::ScanTarget *scan_target) override {
|
||||
nick_.last_valid()->set_scan_target(scan_target);
|
||||
}
|
||||
|
||||
Outputs::Display::ScanStatus get_scaled_scan_status() const override {
|
||||
return nick_.last_valid()->get_scaled_scan_status();
|
||||
}
|
||||
|
||||
void set_display_type(Outputs::Display::DisplayType display_type) final {
|
||||
nick_.last_valid()->set_display_type(display_type);
|
||||
}
|
||||
|
||||
Outputs::Display::DisplayType get_display_type() const final {
|
||||
return nick_.last_valid()->get_display_type();
|
||||
}
|
||||
|
||||
// MARK: - AudioProducer
|
||||
|
||||
Outputs::Speaker::Speaker *get_speaker() final {
|
||||
return &speaker_;
|
||||
}
|
||||
|
||||
// MARK: - TimedMachine
|
||||
void run_for(const Cycles cycles) override {
|
||||
z80_.run_for(cycles);
|
||||
}
|
||||
|
||||
// MARK: - KeyboardMachine
|
||||
Enterprise::KeyboardMapper keyboard_mapper_;
|
||||
KeyboardMapper *get_keyboard_mapper() final {
|
||||
return &keyboard_mapper_;
|
||||
}
|
||||
|
||||
uint8_t active_key_line_ = 0;
|
||||
std::array<uint8_t, 10> key_lines_;
|
||||
void set_key_state(uint16_t key, bool is_pressed) final {
|
||||
if(is_pressed) {
|
||||
key_lines_[key >> 8] &= ~uint8_t(key);
|
||||
} else {
|
||||
key_lines_[key >> 8] |= uint8_t(key);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_all_keys() final {
|
||||
key_lines_.fill(0xff);
|
||||
}
|
||||
|
||||
// MARK: - Utility::TypeRecipient
|
||||
void type_string(const std::string &string) final {
|
||||
Utility::TypeRecipient<CharacterMapper>::add_typer(string);
|
||||
|
||||
if(z80_.get_is_resetting()) {
|
||||
should_skip_splash_screen_ = true;
|
||||
typer_delay_ = 1;
|
||||
} else {
|
||||
should_skip_splash_screen_ = false;
|
||||
typer_delay_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool can_type(char c) const final {
|
||||
return Utility::TypeRecipient<CharacterMapper>::can_type(c);
|
||||
}
|
||||
|
||||
bool should_skip_splash_screen_ = false;
|
||||
int typer_delay_ = 30;
|
||||
|
||||
// MARK: - MediaTarget
|
||||
bool insert_media(const Analyser::Static::Media &media) final {
|
||||
if constexpr (has_disk_controller) {
|
||||
if(!media.disks.empty()) {
|
||||
exdos_.set_disk(media.disks.front(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// MARK: - Interrupts
|
||||
|
||||
uint8_t interrupt_mask_ = 0x00, interrupt_state_ = 0x00;
|
||||
void set_interrupts(uint8_t mask, HalfCycles offset = HalfCycles(0)) {
|
||||
interrupt_state_ |= uint8_t(mask);
|
||||
update_interrupts(offset);
|
||||
}
|
||||
void update_interrupts(HalfCycles offset = HalfCycles(0)) {
|
||||
z80_.set_interrupt_line((interrupt_state_ >> 1) & interrupt_mask_, offset);
|
||||
}
|
||||
|
||||
// MARK: - Chips.
|
||||
CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
|
||||
NickType nick_;
|
||||
bool previous_nick_interrupt_line_ = false;
|
||||
// Cf. timing guesses above.
|
||||
|
||||
Concurrency::DeferringAsyncTaskQueue audio_queue_;
|
||||
Dave::Audio dave_audio_;
|
||||
Outputs::Speaker::LowpassSpeaker<Dave::Audio> speaker_;
|
||||
HalfCycles time_since_audio_update_;
|
||||
|
||||
HalfCycles dave_delay_ = HalfCycles(2);
|
||||
|
||||
// The divider supplied to the JustInTimeActor and the manual divider used in
|
||||
// update_audio() should match.
|
||||
static constexpr int dave_divider = 8;
|
||||
JustInTimeActor<Dave::TimedInterruptSource, HalfCycles, 1, dave_divider> dave_timer_;
|
||||
inline void update_audio() {
|
||||
speaker_.run_for(audio_queue_, time_since_audio_update_.divide_cycles(Cycles(dave_divider)));
|
||||
}
|
||||
|
||||
// MARK: - EXDos card.
|
||||
EXDos exdos_;
|
||||
|
||||
// MARK: - Activity Source
|
||||
void set_activity_observer(Activity::Observer *observer) final {
|
||||
if constexpr (has_disk_controller) {
|
||||
exdos_.set_activity_observer(observer);
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Configuration options.
|
||||
std::unique_ptr<Reflection::Struct> get_options() final {
|
||||
auto options = std::make_unique<Options>(Configurable::OptionsType::UserFriendly);
|
||||
options->output = get_video_signal_configurable();
|
||||
return options;
|
||||
}
|
||||
|
||||
void set_options(const std::unique_ptr<Reflection::Struct> &str) final {
|
||||
const auto options = dynamic_cast<Options *>(str.get());
|
||||
set_video_signal_configurable(options->output);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using namespace Enterprise;
|
||||
|
||||
Machine *Machine::Enterprise(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) {
|
||||
using Target = Analyser::Static::Enterprise::Target;
|
||||
const Target *const enterprise_target = dynamic_cast<const Target *>(target);
|
||||
|
||||
#define BuildMachine(exdos, sixmhz) \
|
||||
if((enterprise_target->dos == Target::DOS::None) != exdos && (enterprise_target->speed == Target::Speed::SixMHz) == sixmhz) { \
|
||||
return new Enterprise::ConcreteMachine<exdos, sixmhz>(*enterprise_target, rom_fetcher); \
|
||||
}
|
||||
|
||||
BuildMachine(false, false);
|
||||
BuildMachine(false, true);
|
||||
BuildMachine(true, false);
|
||||
BuildMachine(true, true);
|
||||
|
||||
#undef BuildMachine
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Machine::~Machine() {}
|
||||
47
Machines/Enterprise/Enterprise.hpp
Normal file
47
Machines/Enterprise/Enterprise.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Enterprise.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 10/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Enterprise_hpp
|
||||
#define Enterprise_hpp
|
||||
|
||||
#include "../../Analyser/Static/StaticAnalyser.hpp"
|
||||
#include "../../Configurable/Configurable.hpp"
|
||||
#include "../../Configurable/StandardOptions.hpp"
|
||||
#include "../ROMMachine.hpp"
|
||||
|
||||
namespace Enterprise {
|
||||
|
||||
/*!
|
||||
@abstract Represents an Elan Enterprise.
|
||||
|
||||
@discussion An instance of Enterprise::Machine represents the current state of an
|
||||
Elan Enterprise.
|
||||
*/
|
||||
class Machine {
|
||||
public:
|
||||
virtual ~Machine();
|
||||
|
||||
static Machine *Enterprise(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher);
|
||||
|
||||
/// Defines the runtime options available for an Enterprise.
|
||||
class Options: public Reflection::StructImpl<Options>, public Configurable::DisplayOption<Options> {
|
||||
friend Configurable::DisplayOption<Options>;
|
||||
public:
|
||||
Options(Configurable::OptionsType type) :
|
||||
Configurable::DisplayOption<Options>(type == Configurable::OptionsType::UserFriendly ? Configurable::Display::RGB : Configurable::Display::CompositeColour) {
|
||||
if(needs_declare()) {
|
||||
declare_display_option();
|
||||
limit_enum(&output, Configurable::Display::RGB, Configurable::Display::CompositeColour, Configurable::Display::CompositeMonochrome, -1);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* Enterprise_hpp */
|
||||
151
Machines/Enterprise/Keyboard.cpp
Normal file
151
Machines/Enterprise/Keyboard.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// Keyboard.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 17/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Keyboard.hpp"
|
||||
|
||||
using namespace Enterprise;
|
||||
|
||||
uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) const {
|
||||
#define BIND(source, dest) case Inputs::Keyboard::Key::source: return uint16_t(Key::dest)
|
||||
switch(key) {
|
||||
default: break;
|
||||
|
||||
BIND(Backslash, Backslash);
|
||||
BIND(CapsLock, Lock);
|
||||
BIND(Tab, Tab);
|
||||
BIND(Escape, Escape);
|
||||
BIND(Hyphen, Hyphen);
|
||||
BIND(Equals, Caret);
|
||||
BIND(Backspace, Erase);
|
||||
BIND(Delete, Delete);
|
||||
BIND(Semicolon, Semicolon);
|
||||
BIND(Quote, Colon);
|
||||
BIND(OpenSquareBracket, OpenSquareBracket);
|
||||
BIND(CloseSquareBracket, CloseSquareBracket);
|
||||
|
||||
BIND(End, Stop);
|
||||
BIND(Insert, Insert);
|
||||
BIND(BackTick, At);
|
||||
|
||||
BIND(k1, k1); BIND(k2, k2); BIND(k3, k3); BIND(k4, k4); BIND(k5, k5);
|
||||
BIND(k6, k6); BIND(k7, k7); BIND(k8, k8); BIND(k9, k9); BIND(k0, k0);
|
||||
|
||||
BIND(F1, F1); BIND(F2, F2); BIND(F3, F3); BIND(F4, F4);
|
||||
BIND(F5, F5); BIND(F6, F6); BIND(F7, F7); BIND(F8, F8);
|
||||
|
||||
BIND(Keypad1, F1); BIND(Keypad2, F2); BIND(Keypad3, F3); BIND(Keypad4, F4);
|
||||
BIND(Keypad5, F5); BIND(Keypad6, F6); BIND(Keypad7, F7); BIND(Keypad8, F8);
|
||||
|
||||
BIND(Q, Q); BIND(W, W); BIND(E, E); BIND(R, R); BIND(T, T);
|
||||
BIND(Y, Y); BIND(U, U); BIND(I, I); BIND(O, O); BIND(P, P);
|
||||
|
||||
BIND(A, A); BIND(S, S); BIND(D, D); BIND(F, F); BIND(G, G);
|
||||
BIND(H, H); BIND(J, J); BIND(K, K); BIND(L, L);
|
||||
|
||||
BIND(Z, Z); BIND(X, X); BIND(C, C); BIND(V, V);
|
||||
BIND(B, B); BIND(N, N); BIND(M, M);
|
||||
|
||||
BIND(FullStop, FullStop);
|
||||
BIND(Comma, Comma);
|
||||
BIND(ForwardSlash, ForwardSlash);
|
||||
|
||||
BIND(Space, Space); BIND(Enter, Enter);
|
||||
|
||||
BIND(LeftShift, LeftShift);
|
||||
BIND(RightShift, RightShift);
|
||||
BIND(LeftOption, Alt);
|
||||
BIND(RightOption, Alt);
|
||||
BIND(LeftControl, Control);
|
||||
BIND(RightControl, Control);
|
||||
|
||||
BIND(Left, Left);
|
||||
BIND(Right, Right);
|
||||
BIND(Up, Up);
|
||||
BIND(Down, Down);
|
||||
}
|
||||
#undef BIND
|
||||
|
||||
return MachineTypes::MappedKeyboardMachine::KeyNotMapped;
|
||||
}
|
||||
|
||||
const uint16_t *CharacterMapper::sequence_for_character(char character) const {
|
||||
#define KEYS(x) {uint16_t(x), MachineTypes::MappedKeyboardMachine::KeyEndSequence}
|
||||
#define SHIFT(x) {uint16_t(Key::LeftShift), uint16_t(x), MachineTypes::MappedKeyboardMachine::KeyEndSequence}
|
||||
#define _ {MachineTypes::MappedKeyboardMachine::KeyNotMapped}
|
||||
static KeySequence key_sequences[] = {
|
||||
/* NUL */ _, /* SOH */ _,
|
||||
/* STX */ _, /* ETX */ _,
|
||||
/* EOT */ _, /* ENQ */ _,
|
||||
/* ACK */ _, /* BEL */ _,
|
||||
/* BS */ KEYS(Key::Erase), /* HT */ KEYS(Key::Tab),
|
||||
/* LF */ KEYS(Key::Enter), /* VT */ _,
|
||||
/* FF */ _, /* CR */ KEYS(Key::Enter),
|
||||
/* SO */ _, /* SI */ _,
|
||||
/* DLE */ _, /* DC1 */ _,
|
||||
/* DC2 */ _, /* DC3 */ _,
|
||||
/* DC4 */ _, /* NAK */ _,
|
||||
/* SYN */ _, /* ETB */ _,
|
||||
/* CAN */ _, /* EM */ _,
|
||||
/* SUB */ _, /* ESC */ KEYS(Key::Escape),
|
||||
/* FS */ _, /* GS */ _,
|
||||
/* RS */ _, /* US */ _,
|
||||
/* space */ KEYS(Key::Space), /* ! */ SHIFT(Key::k1),
|
||||
/* " */ SHIFT(Key::k2), /* # */ _,
|
||||
/* $ */ SHIFT(Key::k4), /* % */ SHIFT(Key::k5),
|
||||
/* & */ SHIFT(Key::k6), /* ' */ SHIFT(Key::k7),
|
||||
/* ( */ SHIFT(Key::k8), /* ) */ SHIFT(Key::k9),
|
||||
/* * */ SHIFT(Key::Colon), /* + */ SHIFT(Key::Semicolon),
|
||||
/* , */ KEYS(Key::Comma), /* - */ KEYS(Key::Hyphen),
|
||||
/* . */ KEYS(Key::FullStop), /* / */ KEYS(Key::ForwardSlash),
|
||||
/* 0 */ KEYS(Key::k0), /* 1 */ KEYS(Key::k1),
|
||||
/* 2 */ KEYS(Key::k2), /* 3 */ KEYS(Key::k3),
|
||||
/* 4 */ KEYS(Key::k4), /* 5 */ KEYS(Key::k5),
|
||||
/* 6 */ KEYS(Key::k6), /* 7 */ KEYS(Key::k7),
|
||||
/* 8 */ KEYS(Key::k8), /* 9 */ KEYS(Key::k9),
|
||||
/* : */ KEYS(Key::Colon), /* ; */ KEYS(Key::Semicolon),
|
||||
/* < */ SHIFT(Key::Comma), /* = */ SHIFT(Key::Hyphen),
|
||||
/* > */ SHIFT(Key::FullStop), /* ? */ SHIFT(Key::ForwardSlash),
|
||||
/* @ */ KEYS(Key::At), /* A */ SHIFT(Key::A),
|
||||
/* B */ SHIFT(Key::B), /* C */ SHIFT(Key::C),
|
||||
/* D */ SHIFT(Key::D), /* E */ SHIFT(Key::E),
|
||||
/* F */ SHIFT(Key::F), /* G */ SHIFT(Key::G),
|
||||
/* H */ SHIFT(Key::H), /* I */ SHIFT(Key::I),
|
||||
/* J */ SHIFT(Key::J), /* K */ SHIFT(Key::K),
|
||||
/* L */ SHIFT(Key::L), /* M */ SHIFT(Key::M),
|
||||
/* N */ SHIFT(Key::N), /* O */ SHIFT(Key::O),
|
||||
/* P */ SHIFT(Key::P), /* Q */ SHIFT(Key::Q),
|
||||
/* R */ SHIFT(Key::R), /* S */ SHIFT(Key::S),
|
||||
/* T */ SHIFT(Key::T), /* U */ SHIFT(Key::U),
|
||||
/* V */ SHIFT(Key::V), /* W */ SHIFT(Key::W),
|
||||
/* X */ SHIFT(Key::X), /* Y */ SHIFT(Key::Y),
|
||||
/* Z */ SHIFT(Key::Z), /* [ */ KEYS(Key::OpenSquareBracket),
|
||||
/* \ */ KEYS(Key::Backslash), /* ] */ KEYS(Key::CloseSquareBracket),
|
||||
/* ^ */ SHIFT(Key::Caret), /* _ */ SHIFT(Key::k0),
|
||||
/* ` */ SHIFT(Key::At), /* a */ KEYS(Key::A),
|
||||
/* b */ KEYS(Key::B), /* c */ KEYS(Key::C),
|
||||
/* d */ KEYS(Key::D), /* e */ KEYS(Key::E),
|
||||
/* f */ KEYS(Key::F), /* g */ KEYS(Key::G),
|
||||
/* h */ KEYS(Key::H), /* i */ KEYS(Key::I),
|
||||
/* j */ KEYS(Key::J), /* k */ KEYS(Key::K),
|
||||
/* l */ KEYS(Key::L), /* m */ KEYS(Key::M),
|
||||
/* n */ KEYS(Key::N), /* o */ KEYS(Key::O),
|
||||
/* p */ KEYS(Key::P), /* q */ KEYS(Key::Q),
|
||||
/* r */ KEYS(Key::R), /* s */ KEYS(Key::S),
|
||||
/* t */ KEYS(Key::T), /* u */ KEYS(Key::U),
|
||||
/* v */ KEYS(Key::V), /* w */ KEYS(Key::W),
|
||||
/* x */ KEYS(Key::X), /* y */ KEYS(Key::Y),
|
||||
/* z */ KEYS(Key::Z), /* { */ SHIFT(Key::OpenSquareBracket),
|
||||
/* | */ SHIFT(Key::Backslash), /* } */ SHIFT(Key::CloseSquareBracket),
|
||||
/* ~ */ SHIFT(Key::Caret)
|
||||
};
|
||||
#undef _
|
||||
#undef SHIFT
|
||||
#undef KEYS
|
||||
|
||||
return table_lookup_sequence_for_character(key_sequences, character);
|
||||
}
|
||||
66
Machines/Enterprise/Keyboard.hpp
Normal file
66
Machines/Enterprise/Keyboard.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// Keyboard.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 17/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Machines_Enterprise_Keyboard_hpp
|
||||
#define Machines_Enterprise_Keyboard_hpp
|
||||
|
||||
#include "../KeyboardMachine.hpp"
|
||||
#include "../Utility/Typer.hpp"
|
||||
|
||||
namespace Enterprise {
|
||||
|
||||
#define KeyCode(line, mask) (line << 8) | mask
|
||||
|
||||
enum class Key: uint16_t {
|
||||
N = 0x0000 | 0x01, Backslash = 0x0000 | 0x02, B = 0x0000 | 0x04, C = 0x0000 | 0x08,
|
||||
V = 0x0000 | 0x10, X = 0x0000 | 0x20, Z = 0x0000 | 0x40, LeftShift = 0x0000 | 0x80,
|
||||
|
||||
H = 0x0100 | 0x01, Lock = 0x0100 | 0x02, G = 0x0100 | 0x04, D = 0x0100 | 0x08,
|
||||
F = 0x0100 | 0x10, S = 0x0100 | 0x20, A = 0x0100 | 0x40, Control = 0x0100 | 0x80,
|
||||
|
||||
U = 0x0200 | 0x01, Q = 0x0200 | 0x02, Y = 0x0200 | 0x04, R = 0x0200 | 0x08,
|
||||
T = 0x0200 | 0x10, E = 0x0200 | 0x20, W = 0x0200 | 0x40, Tab = 0x0200 | 0x80,
|
||||
|
||||
k7 = 0x0300 | 0x01, k1 = 0x0300 | 0x02, k6 = 0x0300 | 0x04, k4 = 0x0300 | 0x08,
|
||||
k5 = 0x0300 | 0x10, k3 = 0x0300 | 0x20, k2 = 0x0300 | 0x40, Escape = 0x0300 | 0x80,
|
||||
|
||||
F4 = 0x0400 | 0x01, F8 = 0x0400 | 0x02, F3 = 0x0400 | 0x04, F6 = 0x0400 | 0x08,
|
||||
F5 = 0x0400 | 0x10, F7 = 0x0400 | 0x20, F2 = 0x0400 | 0x40, F1 = 0x0400 | 0x80,
|
||||
|
||||
k8 = 0x0500 | 0x01, k9 = 0x0500 | 0x04, Hyphen = 0x0500 | 0x08,
|
||||
k0 = 0x0500 | 0x10, Caret = 0x0500 | 0x20, Erase = 0x0500 | 0x40,
|
||||
|
||||
J = 0x0600 | 0x01, K = 0x0600 | 0x04, Semicolon = 0x0600 | 0x08,
|
||||
L = 0x0600 | 0x10, Colon = 0x0600 | 0x20, CloseSquareBracket = 0x0600 | 0x40,
|
||||
|
||||
Stop = 0x0700 | 0x01, Down = 0x0700 | 0x02, Right = 0x0700 | 0x04, Up = 0x0700 | 0x08,
|
||||
Hold = 0x0700 | 0x10, Left = 0x0700 | 0x20, Enter = 0x0700 | 0x40, Alt = 0x0700 | 0x80,
|
||||
|
||||
M = 0x0800 | 0x01, Delete = 0x0800 | 0x02, Comma = 0x0800 | 0x04,
|
||||
ForwardSlash = 0x0800 | 0x08,
|
||||
FullStop = 0x0800 | 0x10,
|
||||
RightShift = 0x0800 | 0x20, Space = 0x0800 | 0x40, Insert = 0x0800 | 0x80,
|
||||
|
||||
I = 0x0900 | 0x01, O = 0x0900 | 0x04, At = 0x0900 | 0x08,
|
||||
P = 0x0900 | 0x10,
|
||||
OpenSquareBracket = 0x0900 | 0x20
|
||||
};
|
||||
|
||||
#undef KeyCode
|
||||
|
||||
struct KeyboardMapper: public MachineTypes::MappedKeyboardMachine::KeyboardMapper {
|
||||
uint16_t mapped_key_for_key(Inputs::Keyboard::Key key) const final;
|
||||
};
|
||||
|
||||
struct CharacterMapper: public ::Utility::CharacterMapper {
|
||||
const uint16_t *sequence_for_character(char character) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* Keyboard_hpp */
|
||||
629
Machines/Enterprise/Nick.cpp
Normal file
629
Machines/Enterprise/Nick.cpp
Normal file
@@ -0,0 +1,629 @@
|
||||
//
|
||||
// Nick.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 14/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Nick.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace {
|
||||
|
||||
uint16_t mapped_colour(uint8_t source) {
|
||||
// On the Enterprise, red and green are 3-bit quantities; blue is a 2-bit quantity.
|
||||
int red = ((source&0x01) << 2) | ((source&0x08) >> 2) | ((source&0x40) >> 6);
|
||||
int green = ((source&0x02) << 1) | ((source&0x10) >> 3) | ((source&0x80) >> 7);
|
||||
int blue = ((source&0x04) >> 1) | ((source&0x20) >> 5);
|
||||
|
||||
assert(red <= 7);
|
||||
assert(green <= 7);
|
||||
assert(blue <= 3);
|
||||
|
||||
red = (red << 1) + (red >> 3);
|
||||
green = (green << 1) + (green >> 3);
|
||||
blue = (blue << 2) + blue;
|
||||
|
||||
assert(red <= 15);
|
||||
assert(green <= 15);
|
||||
assert(blue <= 15);
|
||||
|
||||
// Duplicate bits where necessary to map to a full 4-bit range per channel.
|
||||
const uint8_t parts[2] = {
|
||||
uint8_t(
|
||||
red
|
||||
),
|
||||
uint8_t(
|
||||
(green << 4) + blue
|
||||
)
|
||||
};
|
||||
return *reinterpret_cast<const uint16_t *>(parts);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using namespace Enterprise;
|
||||
|
||||
Nick::Nick(const uint8_t *ram) :
|
||||
crt_(57*16, 16, Outputs::Display::Type::PAL50, Outputs::Display::InputDataType::Red4Green4Blue4),
|
||||
ram_(ram) {
|
||||
|
||||
// Just use RGB for now.
|
||||
set_display_type(Outputs::Display::DisplayType::RGB);
|
||||
|
||||
// Crop to the centre 90% of the display.
|
||||
crt_.set_visible_area(Outputs::Display::Rect(0.05f, 0.05f, 0.9f, 0.9f));
|
||||
}
|
||||
|
||||
void Nick::write(uint16_t address, uint8_t value) {
|
||||
switch(address & 3) {
|
||||
case 0:
|
||||
// Ignored: everything to do with external colour.
|
||||
for(int c = 0; c < 8; c++) {
|
||||
palette_[c + 8] = mapped_colour(uint8_t(((value & 0x1f) << 3) + c));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(output_type_ == OutputType::Border) {
|
||||
set_output_type(OutputType::Border, true);
|
||||
}
|
||||
border_colour_ = mapped_colour(value);
|
||||
break;
|
||||
case 2:
|
||||
line_parameter_base_ = uint16_t((line_parameter_base_ & 0xf000) | (value << 4));
|
||||
break;
|
||||
case 3:
|
||||
line_parameter_base_ = uint16_t((line_parameter_base_ & 0x0ff0) | (value << 12));
|
||||
|
||||
// Still a mystery to me: the exact meaning of the top two bits here. For now
|
||||
// just treat a 0 -> 1 transition of the MSB as a forced frame restart.
|
||||
if((value^line_parameter_control_) & value & 0x80) {
|
||||
// For now: just force this to be the final line of this mode block.
|
||||
// I'm unclear whether I should also reset the horizontal counter
|
||||
// (i.e. completely abandon current video phase).
|
||||
lines_remaining_ = 0xff;
|
||||
should_reload_line_parameters_ = true;
|
||||
}
|
||||
line_parameter_control_ = value & 0xc0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Nick::read() {
|
||||
return last_read_;
|
||||
}
|
||||
|
||||
Cycles Nick::get_time_until_z80_slot(Cycles after_period) const {
|
||||
// Place Z80 accesses in the first six cycles in each sixteen-cycle window.
|
||||
// That models video accesses as being the final ten. Which has the net effect
|
||||
// of responding to the line parameter table interrupt flag as soon as it's
|
||||
// loaded.
|
||||
|
||||
// Assumed below: the Z80 can start its final cycle anywhere in the first three
|
||||
// of the permitted six.
|
||||
const int offset = (horizontal_counter_ + after_period.as<int>()) & 15;
|
||||
if(offset < 3) {
|
||||
return 0;
|
||||
} else {
|
||||
return 16 - offset;
|
||||
}
|
||||
}
|
||||
|
||||
void Nick::run_for(Cycles duration) {
|
||||
constexpr int line_length = 912;
|
||||
|
||||
#define add_window(x) \
|
||||
line_data_pointer_[0] += is_sync_or_pixels_ * line_data_per_column_increments_[0] * (x); \
|
||||
line_data_pointer_[1] += is_sync_or_pixels_ * line_data_per_column_increments_[1] * (x); \
|
||||
window += x; \
|
||||
if(window != 57 && window == left_margin_) is_sync_or_pixels_ = true; \
|
||||
if(window != 57 && window == right_margin_) is_sync_or_pixels_ = false;
|
||||
|
||||
int clocks_remaining = duration.as<int>();
|
||||
while(clocks_remaining) {
|
||||
// Determine how many cycles are left this line.
|
||||
const int clocks_this_line = std::min(clocks_remaining, line_length - horizontal_counter_);
|
||||
|
||||
// Convert that into a [start/current] and end window.
|
||||
int window = horizontal_counter_ >> 4;
|
||||
const int end_window = (horizontal_counter_ + clocks_this_line) >> 4;
|
||||
|
||||
// Advance the line counters.
|
||||
clocks_remaining -= clocks_this_line;
|
||||
horizontal_counter_ = (horizontal_counter_ + clocks_this_line) % line_length;
|
||||
|
||||
// Do nothing if a window boundary isn't crossed.
|
||||
if(window == end_window) continue;
|
||||
|
||||
// HSYNC is signalled for four windows at the start of the line.
|
||||
// I currently believe this happens regardless of Vsync mode.
|
||||
if(!window) {
|
||||
set_output_type(OutputType::Sync);
|
||||
|
||||
// There's no increment to get to 0, it happens when the horizontal_counter_
|
||||
// is reset. So test for active bit effect manually.
|
||||
if(!left_margin_) is_sync_or_pixels_ = true;
|
||||
if(!right_margin_) is_sync_or_pixels_ = false;
|
||||
}
|
||||
|
||||
// Default to noting read.
|
||||
last_read_ = 0xff;
|
||||
|
||||
while(window < 4 && window < end_window) {
|
||||
if(should_reload_line_parameters_) {
|
||||
switch(window) {
|
||||
// First slot: line count, mode and interrupt flag.
|
||||
case 0:
|
||||
// Byte 0: lines remaining.
|
||||
lines_remaining_ = ram_[line_parameter_pointer_];
|
||||
|
||||
// Byte 1: current interrupt output plus graphics modes...
|
||||
last_read_ = ram_[line_parameter_pointer_ + 1];
|
||||
|
||||
// Set the new interrupt line output.
|
||||
interrupt_line_ = ram_[line_parameter_pointer_ + 1] & 0x80;
|
||||
|
||||
// Determine the mode and depth, and hence the column size.
|
||||
mode_ = Mode((ram_[line_parameter_pointer_ + 1] >> 1)&7);
|
||||
bpp_ = 1 << ((ram_[line_parameter_pointer_ + 1] >> 5)&3);
|
||||
switch(mode_) {
|
||||
default:
|
||||
case Mode::Pixel:
|
||||
column_size_ = 16 / bpp_;
|
||||
line_data_per_column_increments_[0] = 2;
|
||||
line_data_per_column_increments_[1] = 0;
|
||||
break;
|
||||
|
||||
case Mode::LPixel:
|
||||
case Mode::CH64:
|
||||
case Mode::CH128:
|
||||
case Mode::CH256:
|
||||
column_size_ = 8 / bpp_;
|
||||
line_data_per_column_increments_[0] = 1;
|
||||
line_data_per_column_increments_[1] = 0;
|
||||
break;
|
||||
|
||||
case Mode::Attr:
|
||||
column_size_ = 8;
|
||||
line_data_per_column_increments_[0] = 1;
|
||||
line_data_per_column_increments_[1] = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
vres_ = ram_[line_parameter_pointer_ + 1] & 0x10;
|
||||
reload_line_parameter_pointer_ = ram_[line_parameter_pointer_ + 1] & 0x01;
|
||||
break;
|
||||
|
||||
// Second slot: margins and ALT/IND bits.
|
||||
case 1:
|
||||
// Determine the margins.
|
||||
left_margin_ = ram_[line_parameter_pointer_ + 2] & 0x3f;
|
||||
right_margin_ = ram_[line_parameter_pointer_ + 3] & 0x3f;
|
||||
last_read_ = ram_[line_parameter_pointer_ + 3];
|
||||
|
||||
// Set up the alternative palettes,
|
||||
switch(mode_) {
|
||||
default:
|
||||
break;
|
||||
|
||||
// NB: LSBALT/MSBALT and ALTIND0/ALTIND1 appear to have opposite effects on palette selection.
|
||||
|
||||
case Mode::Pixel:
|
||||
case Mode::LPixel: {
|
||||
const uint8_t flags = ram_[line_parameter_pointer_ + 2];
|
||||
|
||||
// Use MSBALT and LSBALT to pick the alt_ind_palettes.
|
||||
//
|
||||
// LSBALT = b6 of params[2], if set => character codes with bit 6 set should use palette indices 4... instead of 0... .
|
||||
// MSBALT = b7 of params[2], if set => character codes with bit 7 set should use palette indices 2 and 3.
|
||||
two_colour_mask_ = 0xff &~ (((flags&0x80) >> 7) | ((flags&0x40) << 1));
|
||||
|
||||
alt_ind_palettes[0] = palette_;
|
||||
alt_ind_palettes[2] = alt_ind_palettes[0] + ((flags & 0x80) ? 2 : 0);
|
||||
|
||||
alt_ind_palettes[1] = alt_ind_palettes[0] + ((flags & 0x40) ? 4 : 0);
|
||||
alt_ind_palettes[3] = alt_ind_palettes[2] + ((flags & 0x40) ? 4 : 0);
|
||||
} break;
|
||||
|
||||
case Mode::CH64:
|
||||
case Mode::CH128:
|
||||
case Mode::CH256: {
|
||||
const uint8_t flags = ram_[line_parameter_pointer_ + 3];
|
||||
|
||||
// Use ALTIND0 and ALTIND1 to pick the alt_ind_palettes.
|
||||
//
|
||||
// ALTIND1 = b6 of params[3], if set => character codes with bit 7 set should use palette indices 2 and 3.
|
||||
// ALTIND0 = b7 of params[3], if set => character codes with bit 6 set should use palette indices 4... instead of 0... .
|
||||
alt_ind_palettes[0] = palette_;
|
||||
alt_ind_palettes[2] = alt_ind_palettes[0] + ((flags & 0x40) ? 2 : 0);
|
||||
|
||||
alt_ind_palettes[1] = alt_ind_palettes[0] + ((flags & 0x80) ? 4 : 0);
|
||||
alt_ind_palettes[3] = alt_ind_palettes[2] + ((flags & 0x80) ? 4 : 0);
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
|
||||
// Third slot: Line data pointer 1.
|
||||
case 2:
|
||||
start_line_data_pointer_[0] = ram_[line_parameter_pointer_ + 4];
|
||||
start_line_data_pointer_[0] |= ram_[line_parameter_pointer_ + 5] << 8;
|
||||
|
||||
line_data_pointer_[0] = start_line_data_pointer_[0];
|
||||
last_read_ = ram_[line_parameter_pointer_ + 5];
|
||||
break;
|
||||
|
||||
// Fourth slot: Line data pointer 2.
|
||||
case 3:
|
||||
start_line_data_pointer_[1] = ram_[line_parameter_pointer_ + 6];
|
||||
start_line_data_pointer_[1] |= ram_[line_parameter_pointer_ + 7] << 8;
|
||||
|
||||
line_data_pointer_[1] = start_line_data_pointer_[1];
|
||||
last_read_ = ram_[line_parameter_pointer_ + 7];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++output_duration_;
|
||||
add_window(1);
|
||||
}
|
||||
if(window == 4) {
|
||||
if(mode_ == Mode::Vsync) {
|
||||
set_output_type(is_sync_or_pixels_ ? OutputType::Sync : OutputType::Blank);
|
||||
} else {
|
||||
set_output_type(OutputType::Blank);
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with vsync mode out here.
|
||||
if(mode_ == Mode::Vsync) {
|
||||
if(window >= 4) {
|
||||
while(window < end_window) {
|
||||
// Skip straight to the next event.
|
||||
int next_event = end_window;
|
||||
if(window < left_margin_) next_event = std::min(next_event, left_margin_);
|
||||
if(window < right_margin_) next_event = std::min(next_event, right_margin_);
|
||||
|
||||
output_duration_ += next_event - window;
|
||||
add_window(next_event - window);
|
||||
set_output_type(is_sync_or_pixels_ ? OutputType::Sync : OutputType::Blank);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If present then the colour burst is output for the period from
|
||||
// the start of window 6 to the end of window 10.
|
||||
//
|
||||
// The first 8 palette entries also need to be fetched here.
|
||||
while(window < first_pixel_window_ && window < end_window) {
|
||||
if(window == 6) {
|
||||
set_output_type(OutputType::ColourBurst);
|
||||
}
|
||||
|
||||
if(should_reload_line_parameters_ && window < 8) {
|
||||
const int base = (window - 4) << 1;
|
||||
assert(base < 7);
|
||||
palette_[base] = mapped_colour(ram_[line_parameter_pointer_ + base + 8]);
|
||||
palette_[base + 1] = mapped_colour(ram_[line_parameter_pointer_ + base + 9]);
|
||||
last_read_ = ram_[line_parameter_pointer_ + base + 9];
|
||||
}
|
||||
|
||||
++output_duration_;
|
||||
add_window(1);
|
||||
}
|
||||
|
||||
if(window >= first_pixel_window_) {
|
||||
if(window == first_pixel_window_) {
|
||||
set_output_type(is_sync_or_pixels_ ? OutputType::Pixels : OutputType::Border);
|
||||
}
|
||||
|
||||
while(window < end_window) {
|
||||
int next_event = end_window;
|
||||
if(window < left_margin_) next_event = std::min(next_event, left_margin_);
|
||||
if(window < right_margin_) next_event = std::min(next_event, right_margin_);
|
||||
|
||||
if(is_sync_or_pixels_) {
|
||||
|
||||
#define DispatchBpp(func) \
|
||||
switch(bpp_) { \
|
||||
default: \
|
||||
case 1: func(1)(pixel_pointer_, output_duration); break; \
|
||||
case 2: func(2)(pixel_pointer_, output_duration); break; \
|
||||
case 4: func(4)(pixel_pointer_, output_duration); break; \
|
||||
case 8: func(8)(pixel_pointer_, output_duration); break; \
|
||||
}
|
||||
|
||||
#define pixel(x) output_pixel<x, false>
|
||||
#define lpixel(x) output_pixel<x, true>
|
||||
#define ch256(x) output_character<x, 8>
|
||||
#define ch128(x) output_character<x, 7>
|
||||
#define ch64(x) output_character<x, 6>
|
||||
#define attr(x) output_attributed<x>
|
||||
|
||||
int columns_remaining = next_event - window;
|
||||
while(columns_remaining) {
|
||||
if(!pixel_pointer_) {
|
||||
if(output_duration_) {
|
||||
set_output_type(OutputType::Pixels, true);
|
||||
}
|
||||
pixel_pointer_ = allocated_pointer_ = reinterpret_cast<uint16_t *>(crt_.begin_data(allocation_size));
|
||||
}
|
||||
|
||||
if(allocated_pointer_) {
|
||||
const int output_duration = std::min(columns_remaining, int(allocated_pointer_ + allocation_size - pixel_pointer_) / column_size_);
|
||||
|
||||
switch(mode_) {
|
||||
default:
|
||||
case Mode::Pixel: DispatchBpp(pixel); break;
|
||||
case Mode::LPixel: DispatchBpp(lpixel); break;
|
||||
case Mode::CH256: DispatchBpp(ch256); break;
|
||||
case Mode::CH128: DispatchBpp(ch128); break;
|
||||
case Mode::CH64: DispatchBpp(ch64); break;
|
||||
case Mode::Attr: DispatchBpp(attr); break;
|
||||
}
|
||||
|
||||
pixel_pointer_ += output_duration * column_size_;
|
||||
output_duration_ += output_duration;
|
||||
if(pixel_pointer_ - allocated_pointer_ == allocation_size) {
|
||||
set_output_type(OutputType::Pixels, true);
|
||||
}
|
||||
columns_remaining -= output_duration;
|
||||
add_window(output_duration);
|
||||
} else {
|
||||
output_duration_ += columns_remaining;
|
||||
add_window(columns_remaining);
|
||||
columns_remaining = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#undef attr
|
||||
#undef ch64
|
||||
#undef ch128
|
||||
#undef ch256
|
||||
#undef pixel
|
||||
#undef lpixel
|
||||
#undef DispatchBpp
|
||||
} else {
|
||||
output_duration_ += next_event - window;
|
||||
add_window(next_event - window);
|
||||
}
|
||||
|
||||
set_output_type(is_sync_or_pixels_ ? OutputType::Pixels : OutputType::Border);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for end of line.
|
||||
if(!horizontal_counter_) {
|
||||
assert(window == 57);
|
||||
|
||||
++lines_remaining_;
|
||||
if(!lines_remaining_) {
|
||||
should_reload_line_parameters_ = true;
|
||||
|
||||
// Check for end-of-frame.
|
||||
if(reload_line_parameter_pointer_) {
|
||||
line_parameter_pointer_ = line_parameter_base_;
|
||||
} else {
|
||||
line_parameter_pointer_ += 16;
|
||||
}
|
||||
} else {
|
||||
should_reload_line_parameters_ = false;
|
||||
}
|
||||
|
||||
// Deal with VRES and other address reloading, dependant upon mode.
|
||||
switch(mode_) {
|
||||
default: break;
|
||||
case Mode::CH64:
|
||||
case Mode::CH128:
|
||||
case Mode::CH256:
|
||||
line_data_pointer_[0] = start_line_data_pointer_[0];
|
||||
++line_data_pointer_[1];
|
||||
break;
|
||||
|
||||
case Mode::Pixel:
|
||||
case Mode::LPixel:
|
||||
case Mode::Attr:
|
||||
// Reload the pixel or attribute address if VRES is clear.
|
||||
if(!vres_) {
|
||||
line_data_pointer_[0] = start_line_data_pointer_[0];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef add_window
|
||||
|
||||
}
|
||||
|
||||
void Nick::set_output_type(OutputType type, bool force_flush) {
|
||||
if(type == output_type_ && !force_flush) {
|
||||
return;
|
||||
}
|
||||
if(output_duration_) {
|
||||
switch(output_type_) {
|
||||
case OutputType::Border: {
|
||||
uint16_t *const colour_pointer = reinterpret_cast<uint16_t *>(crt_.begin_data(1));
|
||||
if(colour_pointer) *colour_pointer = border_colour_;
|
||||
crt_.output_level(output_duration_*16);
|
||||
} break;
|
||||
|
||||
case OutputType::Pixels: {
|
||||
crt_.output_data(output_duration_*16, size_t(output_duration_*column_size_));
|
||||
pixel_pointer_ = nullptr;
|
||||
allocated_pointer_ = nullptr;
|
||||
} break;
|
||||
|
||||
case OutputType::Sync: crt_.output_sync(output_duration_*16); break;
|
||||
case OutputType::Blank: crt_.output_blank(output_duration_*16); break;
|
||||
case OutputType::ColourBurst: crt_.output_colour_burst(output_duration_*16, 0); break;
|
||||
}
|
||||
}
|
||||
|
||||
output_duration_ = 0;
|
||||
output_type_ = type;
|
||||
}
|
||||
|
||||
// MARK: - Sequence points.
|
||||
|
||||
Cycles Nick::get_next_sequence_point() const {
|
||||
constexpr int load_point = 16; // i.e. 16 cycles after the start of the line, the
|
||||
// interrupt line may change. That is, after the
|
||||
// second byte of the mode line has been read.
|
||||
|
||||
// Any mode line may cause a change in the interrupt output, so as a first blush
|
||||
// just always report the time until the end of the mode line.
|
||||
if(lines_remaining_ || horizontal_counter_ >= load_point) {
|
||||
return Cycles(load_point + (912 - horizontal_counter_) + (0xff - lines_remaining_) * 912);
|
||||
} else {
|
||||
return Cycles(load_point - horizontal_counter_);
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CRT passthroughs.
|
||||
|
||||
void Nick::set_scan_target(Outputs::Display::ScanTarget *scan_target) {
|
||||
crt_.set_scan_target(scan_target);
|
||||
}
|
||||
|
||||
Outputs::Display::ScanStatus Nick::get_scaled_scan_status() const {
|
||||
return crt_.get_scaled_scan_status();
|
||||
}
|
||||
|
||||
void Nick::set_display_type(Outputs::Display::DisplayType display_type) {
|
||||
first_pixel_window_ = display_type == Outputs::Display::DisplayType::RGB ? 8 : 10;
|
||||
crt_.set_display_type(display_type);
|
||||
}
|
||||
|
||||
Outputs::Display::DisplayType Nick::get_display_type() const {
|
||||
return crt_.get_display_type();
|
||||
}
|
||||
|
||||
// MARK: - Specific pixel outputters.
|
||||
|
||||
#define output1bpp(x) \
|
||||
target[0] = palette[(x & 0x80) >> 7]; \
|
||||
target[1] = palette[(x & 0x40) >> 6]; \
|
||||
target[2] = palette[(x & 0x20) >> 5]; \
|
||||
target[3] = palette[(x & 0x10) >> 4]; \
|
||||
target[4] = palette[(x & 0x08) >> 3]; \
|
||||
target[5] = palette[(x & 0x04) >> 2]; \
|
||||
target[6] = palette[(x & 0x02) >> 1]; \
|
||||
target[7] = palette[(x & 0x01) >> 0]; \
|
||||
target += 8
|
||||
|
||||
#define output2bpp(x) \
|
||||
target[0] = palette_[((x & 0x80) >> 7) | ((x & 0x08) >> 2)]; \
|
||||
target[1] = palette_[((x & 0x40) >> 6) | ((x & 0x04) >> 1)]; \
|
||||
target[2] = palette_[((x & 0x20) >> 5) | ((x & 0x02) >> 0)]; \
|
||||
target[3] = palette_[((x & 0x10) >> 4) | ((x & 0x01) << 1)]; \
|
||||
target += 4
|
||||
|
||||
#define output4bpp(x) \
|
||||
target[0] = palette_[((x & 0x02) << 2) | ((x & 0x20) >> 3) | ((x & 0x08) >> 2) | ((x & 0x80) >> 7)]; \
|
||||
target[1] = palette_[((x & 0x01) << 3) | ((x & 0x10) >> 2) | ((x & 0x04) >> 1) | ((x & 0x40) >> 6)]; \
|
||||
target += 2
|
||||
|
||||
#define output8bpp(x) \
|
||||
target[0] = mapped_colour(x); \
|
||||
++target
|
||||
|
||||
template <int bpp, bool is_lpixel> void Nick::output_pixel(uint16_t *target, int columns) const {
|
||||
static_assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8);
|
||||
|
||||
int index = 0;
|
||||
for(int c = 0; c < columns; c++) {
|
||||
uint8_t pixels[2] = {
|
||||
ram_[(line_data_pointer_[0] + index) & 0xffff],
|
||||
ram_[(line_data_pointer_[0] + index + 1) & 0xffff]
|
||||
};
|
||||
index += is_lpixel ? 1 : 2;
|
||||
last_read_ = pixels[1];
|
||||
|
||||
switch(bpp) {
|
||||
default:
|
||||
case 1: {
|
||||
const uint16_t *palette = alt_ind_palettes[((pixels[0] >> 6) & 0x02) | (pixels[0]&1)];
|
||||
pixels[0] &= two_colour_mask_;
|
||||
output1bpp(pixels[0]);
|
||||
|
||||
if constexpr (!is_lpixel) {
|
||||
palette = alt_ind_palettes[((pixels[1] >> 6) & 0x02) | (pixels[1]&1)];
|
||||
pixels[1] &= two_colour_mask_;
|
||||
output1bpp(pixels[1]);
|
||||
}
|
||||
} break;
|
||||
|
||||
case 2:
|
||||
output2bpp(pixels[0]);
|
||||
if constexpr (!is_lpixel) {
|
||||
output2bpp(pixels[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
output4bpp(pixels[0]);
|
||||
if constexpr (!is_lpixel) {
|
||||
output4bpp(pixels[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 8:
|
||||
output8bpp(pixels[0]);
|
||||
if constexpr (!is_lpixel) {
|
||||
output8bpp(pixels[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <int bpp, int index_bits> void Nick::output_character(uint16_t *target, int columns) const {
|
||||
static_assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8);
|
||||
|
||||
for(int c = 0; c < columns; c++) {
|
||||
const uint8_t character = ram_[(line_data_pointer_[0] + c) & 0xffff];
|
||||
const uint8_t pixels = ram_[(
|
||||
(line_data_pointer_[1] << index_bits) +
|
||||
(character & ((1 << index_bits) - 1))
|
||||
) & 0xffff];
|
||||
last_read_ = pixels;
|
||||
|
||||
switch(bpp) {
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
|
||||
case 1: {
|
||||
// This applies ALTIND0 and ALTIND1.
|
||||
const uint16_t *palette = alt_ind_palettes[character >> 6];
|
||||
output1bpp(pixels);
|
||||
} break;
|
||||
|
||||
case 2: output2bpp(pixels); break;
|
||||
case 4: output4bpp(pixels); break;
|
||||
case 8: output8bpp(pixels); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <int bpp> void Nick::output_attributed(uint16_t *target, int columns) const {
|
||||
static_assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8);
|
||||
|
||||
for(int c = 0; c < columns; c++) {
|
||||
const uint8_t pixels = ram_[(line_data_pointer_[1] + c) & 0xffff];
|
||||
const uint8_t attributes = ram_[(line_data_pointer_[0] + c) & 0xffff];
|
||||
last_read_ = pixels;
|
||||
|
||||
const uint16_t palette[2] = {
|
||||
palette_[attributes >> 4], palette_[attributes & 0x0f]
|
||||
};
|
||||
output1bpp(pixels);
|
||||
}
|
||||
}
|
||||
|
||||
#undef output1bpp
|
||||
#undef output2bpp
|
||||
#undef output4bpp
|
||||
#undef output8bpp
|
||||
126
Machines/Enterprise/Nick.hpp
Normal file
126
Machines/Enterprise/Nick.hpp
Normal file
@@ -0,0 +1,126 @@
|
||||
//
|
||||
// Nick.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 14/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Nick_hpp
|
||||
#define Nick_hpp
|
||||
|
||||
#include <cstdint>
|
||||
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||
#include "../../Outputs/CRT/CRT.hpp"
|
||||
|
||||
namespace Enterprise {
|
||||
|
||||
class Nick {
|
||||
public:
|
||||
Nick(const uint8_t *ram);
|
||||
|
||||
/// Writes to a Nick register; only the low two bits are decoded.
|
||||
void write(uint16_t address, uint8_t value);
|
||||
|
||||
/// Reads from the Nick range. Nobody seems to be completely clear what
|
||||
/// this should return; I've set it up to return the last fetched video or mode
|
||||
/// line byte during periods when those things are being fetched, 0xff at all
|
||||
/// other times. Including during refresh, since I don't know what addresses
|
||||
/// are generated then.
|
||||
///
|
||||
/// This likely isn't accurate, but is the most accurate guess I could make.
|
||||
uint8_t read();
|
||||
|
||||
void run_for(Cycles);
|
||||
Cycles get_time_until_z80_slot(Cycles after_period) const;
|
||||
|
||||
void set_scan_target(Outputs::Display::ScanTarget *scan_target);
|
||||
Outputs::Display::ScanStatus get_scaled_scan_status() const;
|
||||
|
||||
/// @returns The amount of time until the next potential change in interrupt output.
|
||||
Cycles get_next_sequence_point() const;
|
||||
|
||||
/*!
|
||||
@returns The current state of the interrupt line — @c true for active;
|
||||
@c false for inactive.
|
||||
*/
|
||||
inline bool get_interrupt_line() const {
|
||||
return interrupt_line_;
|
||||
}
|
||||
|
||||
/// Sets the type of output.
|
||||
void set_display_type(Outputs::Display::DisplayType);
|
||||
|
||||
/// Gets the type of output.
|
||||
Outputs::Display::DisplayType get_display_type() const;
|
||||
|
||||
private:
|
||||
Outputs::CRT::CRT crt_;
|
||||
const uint8_t *const ram_;
|
||||
|
||||
// CPU-provided state.
|
||||
uint8_t line_parameter_control_ = 0xc0;
|
||||
uint16_t line_parameter_base_ = 0x0000;
|
||||
uint16_t border_colour_ = 0;
|
||||
|
||||
// Ephemerals, related to current video position.
|
||||
int horizontal_counter_ = 0;
|
||||
uint16_t line_parameter_pointer_ = 0x0000;
|
||||
bool should_reload_line_parameters_ = true;
|
||||
uint16_t line_data_pointer_[2];
|
||||
uint16_t start_line_data_pointer_[2];
|
||||
mutable uint8_t last_read_ = 0xff;
|
||||
|
||||
// Current mode line parameters.
|
||||
uint8_t lines_remaining_ = 0x00;
|
||||
uint8_t two_colour_mask_ = 0xff;
|
||||
int left_margin_ = 0, right_margin_ = 0;
|
||||
const uint16_t *alt_ind_palettes[4];
|
||||
enum class Mode {
|
||||
Vsync,
|
||||
Pixel,
|
||||
Attr,
|
||||
CH256,
|
||||
CH128,
|
||||
CH64,
|
||||
Unused,
|
||||
LPixel,
|
||||
} mode_ = Mode::Vsync;
|
||||
bool is_sync_or_pixels_ = false;
|
||||
int bpp_ = 0;
|
||||
int column_size_ = 0;
|
||||
bool interrupt_line_ = true;
|
||||
int line_data_per_column_increments_[2] = {0, 0};
|
||||
bool vres_ = false;
|
||||
bool reload_line_parameter_pointer_ = false;
|
||||
|
||||
// The destination for new pixels.
|
||||
static constexpr int allocation_size = 336;
|
||||
static_assert((allocation_size % 16) == 0, "Allocation size must be a multiple of 16");
|
||||
uint16_t *pixel_pointer_ = nullptr, *allocated_pointer_ = nullptr;
|
||||
|
||||
// Output transitions.
|
||||
enum class OutputType {
|
||||
Sync, Blank, Pixels, Border, ColourBurst
|
||||
};
|
||||
void set_output_type(OutputType, bool force_flush = false);
|
||||
int output_duration_ = 0;
|
||||
OutputType output_type_ = OutputType::Sync;
|
||||
|
||||
// Current palette.
|
||||
uint16_t palette_[16]{};
|
||||
|
||||
// The first column with pixels on it; will be either 8 or 10 depending
|
||||
// on whether the colour burst is meaningful to the current display type.
|
||||
int first_pixel_window_ = 10;
|
||||
|
||||
// Specific outputters.
|
||||
template <int bpp, bool is_lpixel> void output_pixel(uint16_t *target, int columns) const;
|
||||
template <int bpp, int index_bits> void output_character(uint16_t *target, int columns) const;
|
||||
template <int bpp> void output_attributed(uint16_t *target, int columns) const;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif /* Nick_hpp */
|
||||
@@ -303,7 +303,7 @@ class ConcreteMachine:
|
||||
case 0x00: // i.e. even ports less than 0x40.
|
||||
if(is_master_system(model_)) {
|
||||
// TODO: Obey the RAM enable.
|
||||
printf("Memory control: %02x\n", memory_control_);
|
||||
LOG("Memory control: " << PADHEX(2) << memory_control_);
|
||||
memory_control_ = *cycle.value;
|
||||
page_cartridge();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "../ColecoVision/ColecoVision.hpp"
|
||||
#include "../Commodore/Vic-20/Vic20.hpp"
|
||||
#include "../Electron/Electron.hpp"
|
||||
#include "../Enterprise/Enterprise.hpp"
|
||||
#include "../MasterSystem/MasterSystem.hpp"
|
||||
#include "../MSX/MSX.hpp"
|
||||
#include "../Oric/Oric.hpp"
|
||||
@@ -34,6 +35,7 @@
|
||||
#include "../../Analyser/Static/Atari2600/Target.hpp"
|
||||
#include "../../Analyser/Static/AtariST/Target.hpp"
|
||||
#include "../../Analyser/Static/Commodore/Target.hpp"
|
||||
#include "../../Analyser/Static/Enterprise/Target.hpp"
|
||||
#include "../../Analyser/Static/Macintosh/Target.hpp"
|
||||
#include "../../Analyser/Static/MSX/Target.hpp"
|
||||
#include "../../Analyser/Static/Oric/Target.hpp"
|
||||
@@ -49,7 +51,7 @@ Machine::DynamicMachine *Machine::MachineForTarget(const Analyser::Static::Targe
|
||||
|
||||
Machine::DynamicMachine *machine = nullptr;
|
||||
try {
|
||||
#define BindD(name, m) case Analyser::Machine::m: machine = new Machine::TypedDynamicMachine<name::Machine>(name::Machine::m(target, rom_fetcher)); break;
|
||||
#define BindD(name, m) case Analyser::Machine::m: machine = new Machine::TypedDynamicMachine<::name::Machine>(name::Machine::m(target, rom_fetcher)); break;
|
||||
#define Bind(m) BindD(m, m)
|
||||
switch(target->machine) {
|
||||
Bind(AmstradCPC)
|
||||
@@ -61,6 +63,7 @@ Machine::DynamicMachine *Machine::MachineForTarget(const Analyser::Static::Targe
|
||||
BindD(Coleco::Vision, ColecoVision)
|
||||
BindD(Commodore::Vic20, Vic20)
|
||||
Bind(Electron)
|
||||
Bind(Enterprise)
|
||||
Bind(MSX)
|
||||
Bind(Oric)
|
||||
BindD(Sega::MasterSystem, MasterSystem)
|
||||
@@ -127,6 +130,7 @@ std::string Machine::ShortNameForTargetMachine(const Analyser::Machine machine)
|
||||
case Analyser::Machine::AtariST: return "AtariST";
|
||||
case Analyser::Machine::ColecoVision: return "ColecoVision";
|
||||
case Analyser::Machine::Electron: return "Electron";
|
||||
case Analyser::Machine::Enterprise: return "Enterprise";
|
||||
case Analyser::Machine::Macintosh: return "Macintosh";
|
||||
case Analyser::Machine::MasterSystem: return "MasterSystem";
|
||||
case Analyser::Machine::MSX: return "MSX";
|
||||
@@ -148,6 +152,7 @@ std::string Machine::LongNameForTargetMachine(Analyser::Machine machine) {
|
||||
case Analyser::Machine::AtariST: return "Atari ST";
|
||||
case Analyser::Machine::ColecoVision: return "ColecoVision";
|
||||
case Analyser::Machine::Electron: return "Acorn Electron";
|
||||
case Analyser::Machine::Enterprise: return "Enterprise";
|
||||
case Analyser::Machine::Macintosh: return "Apple Macintosh";
|
||||
case Analyser::Machine::MasterSystem: return "Sega Master System";
|
||||
case Analyser::Machine::MSX: return "MSX";
|
||||
@@ -177,6 +182,7 @@ std::vector<std::string> Machine::AllMachines(Type type, bool long_names) {
|
||||
AddName(AppleIIgs);
|
||||
AddName(AtariST);
|
||||
AddName(Electron);
|
||||
AddName(Enterprise);
|
||||
AddName(Macintosh);
|
||||
AddName(MSX);
|
||||
AddName(Oric);
|
||||
@@ -201,6 +207,7 @@ std::map<std::string, std::unique_ptr<Reflection::Struct>> Machine::AllOptionsBy
|
||||
Emplace(AtariST, Atari::ST::Machine);
|
||||
Emplace(ColecoVision, Coleco::Vision::Machine);
|
||||
Emplace(Electron, Electron::Machine);
|
||||
Emplace(Enterprise, Enterprise::Machine);
|
||||
Emplace(Macintosh, Apple::Macintosh::Machine);
|
||||
Emplace(MasterSystem, Sega::MasterSystem::Machine);
|
||||
Emplace(MSX, MSX::Machine);
|
||||
@@ -226,6 +233,7 @@ std::map<std::string, std::unique_ptr<Analyser::Static::Target>> Machine::Target
|
||||
Add(AppleIIgs);
|
||||
Add(AtariST);
|
||||
AddMapped(Electron, Acorn);
|
||||
Add(Enterprise);
|
||||
Add(Macintosh);
|
||||
Add(MSX);
|
||||
Add(Oric);
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "MemoryPacker.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
void Memory::PackBigEndian16(const std::vector<uint8_t> &source, uint16_t *target) {
|
||||
for(size_t c = 0; c < source.size(); c += 2) {
|
||||
target[c >> 1] = uint16_t(source[c] << 8) | uint16_t(source[c+1]);
|
||||
|
||||
@@ -27,8 +27,15 @@ Request::Request(Name name, bool optional) {
|
||||
}
|
||||
|
||||
Request Request::append(Node::Type type, const Request &rhs) {
|
||||
// Start with the easiest case: this is already an appropriate
|
||||
// request, and so is the new thing.
|
||||
// If either side is empty, act appropriately.
|
||||
if(node.empty() && !rhs.node.empty()) {
|
||||
return rhs;
|
||||
}
|
||||
if(rhs.node.empty()) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Just copy in the RHS child nodes if types match.
|
||||
if(node.type == type && rhs.node.type == type) {
|
||||
Request new_request = *this;
|
||||
new_request.node.children.insert(new_request.node.children.end(), rhs.node.children.begin(), rhs.node.children.end());
|
||||
@@ -373,6 +380,34 @@ Description::Description(Name name) {
|
||||
case Name::CPC6128Firmware: *this = Description(name, "AmstradCPC", "the CPC 6128 firmware", "os6128.rom", 16*1024, 0x0219bb74u); break;
|
||||
case Name::CPC6128BASIC: *this = Description(name, "AmstradCPC", "the CPC 6128 BASIC ROM", "basic6128.rom", 16*1024, 0xca6af63du); break;
|
||||
|
||||
case Name::AmigaKickstart10:
|
||||
*this = Description(name, "Amiga", "the Kickstart 1.0 ROM", "Kickstart-v1.0-1985-Commodore-A1000-NTSC.rom", 256*1024, 0x299790ffu);
|
||||
break;
|
||||
case Name::AmigaKickstart11:
|
||||
*this = Description(name, "Amiga", "the Kickstart 1.1 ROM", "Kickstart-v1.1-rev31.34-1985-Commodore-A1000.NTSC.rom", 256*1024, 0xd060572au);
|
||||
break;
|
||||
case Name::AmigaKickstart12:
|
||||
*this = Description(name, "Amiga", "the Kickstart 1.2 ROM", "Kickstart-v1.2-rev33.166-1986-Commodore-A1000.rom", 256*1024, 0x9ed783d0u);
|
||||
break;
|
||||
case Name::AmigaA500Kickstart13:
|
||||
*this = Description(name, "Amiga", "the A500/A1000/A2000/CDTV Kickstart 1.3 ROM", "Kickstart-v1.3-rev34.5-1987-Commodore-A500-A1000-A2000-CDTV.rom", 256*1024, 0xc4f0f55fu);
|
||||
break;
|
||||
case Name::AmigaA3000Kickstart13:
|
||||
*this = Description(name, "Amiga", "the A3000 Kickstart 1.3 ROM", "Kickstart-v1.3-rev34.5-1987-Commodore-A3000.rom", 256*1024, 0xe0f37258u);
|
||||
break;
|
||||
case Name::AmigaKickstart20:
|
||||
*this = Description(name, "Amiga", "the Kickstart 2.0 ROM", "Kickstart-v2.0-rev36.143-1990-Commodore-A3000.rom", 512*1024, 0xb333d3c6u);
|
||||
break;
|
||||
case Name::AmigaA500PlusKickstart204:
|
||||
*this = Description(name, "Amiga", "the A500+ Kickstart 2.04 ROM", "Kickstart-v2.04-rev37.175-1991-Commodore-A500plus.rom", 512*1024, 0xc3bdb240u);
|
||||
break;
|
||||
case Name::AmigaA600Kickstart205:
|
||||
*this = Description(name, "Amiga", "the Kickstart 2.05 ROM", "Kickstart-v2.05-rev37.299-1991-Commodore-A600.rom", 512*1024, 0x83028fb5u);
|
||||
break;
|
||||
case Name::AmigaA500Kickstart31:
|
||||
*this = Description(name, "Amiga", "the A500/A600/A2000 Kickstart 3.1 ROM", "Kickstart-v3.1-rev40.63-1993-Commodore-A500-A600-A2000.rom", 512*1024, 0xfc24ae0du);
|
||||
break;
|
||||
|
||||
case Name::AppleIIEnhancedE: *this = Description(name, "AppleII", "the Enhanced Apple IIe ROM", "apple2e.rom", 32*1024, 0x65989942u); break;
|
||||
case Name::AppleIIe: *this = Description(name, "AppleII", "the Apple IIe ROM", "apple2eu.rom", 32*1024, 0xe12be18du); break;
|
||||
case Name::AppleIIPlus: *this = Description(name, "AppleII", "the Apple II+ ROM", "apple2.rom", 12*1024, 0xf66f9c26u); break;
|
||||
@@ -404,6 +439,62 @@ Description::Description(Name name) {
|
||||
*this = Description(name, "DiskII", "the Disk II 13-sector state machine ROM", "state-machine-13.rom", 256, 0x62e22620u);
|
||||
break;
|
||||
|
||||
case Name::EnterpriseEXOS10: {
|
||||
const std::initializer_list<std::string> filenames = {"exos10.bin", "Exos (198x)(Enterprise).bin"};
|
||||
*this = Description(name, "Enterprise", "the Enterprise EXOS ROM v1.0", filenames, 32 * 1024, 0x30b26387u);
|
||||
} break;
|
||||
case Name::EnterpriseEXOS20: {
|
||||
const std::initializer_list<std::string> filenames = {"exos20.bin", "Expandible OS v2.0 (1984)(Intelligent Software).bin"};
|
||||
*this = Description(name, "Enterprise", "the Enterprise EXOS ROM v2.0", filenames, 32 * 1024, 0xd421795fu);
|
||||
} break;
|
||||
case Name::EnterpriseEXOS21: {
|
||||
const std::initializer_list<std::string> filenames = {"exos21.bin", "Expandible OS v2.1 (1985)(Intelligent Software).bin"};
|
||||
*this = Description(name, "Enterprise", "the Enterprise EXOS ROM v2.1", filenames, 32 * 1024, 0x982a3b44u);
|
||||
} break;
|
||||
case Name::EnterpriseEXOS23: {
|
||||
const std::initializer_list<std::string> filenames = {"exos23.bin", "Expandible OS v2.3 (1987)(Intelligent Software).bin"};
|
||||
*this = Description(name, "Enterprise", "the Enterprise EXOS ROM v2.1", filenames, 64 * 1024, 0x24838410u);
|
||||
} break;
|
||||
|
||||
case Name::EnterpriseBASIC10: {
|
||||
const std::initializer_list<std::string> filenames = {"basic10.bin"};
|
||||
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v1.0", filenames, 16 * 1024, 0xd62e4fb7u);
|
||||
} break;
|
||||
case Name::EnterpriseBASIC10Part1: {
|
||||
const std::initializer_list<std::string> filenames = {"BASIC 1.0 - EPROM 1-2 (198x)(Enterprise).bin"};
|
||||
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v1.0, Part 1", filenames, 8193, 0x37bf48e1u);
|
||||
} break;
|
||||
case Name::EnterpriseBASIC10Part2: {
|
||||
const std::initializer_list<std::string> filenames = {"BASIC 1.0 - EPROM 2-2 (198x)(Enterprise).bin"};
|
||||
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v1.0, Part 2", filenames, 8193, 0xc5298c79u);
|
||||
} break;
|
||||
case Name::EnterpriseBASIC11: {
|
||||
const std::initializer_list<std::string> filenames = {"basic11.bin"};
|
||||
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v1.1", filenames, 16 * 1024, 0x683cf455u);
|
||||
} break;
|
||||
case Name::EnterpriseBASIC11Suffixed: {
|
||||
const std::initializer_list<std::string> filenames = {"BASIC 1.1 - EPROM 1.1 (198x)(Enterprise).bin"};
|
||||
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v1.1, with trailing byte", filenames, 16385, 0xc96b7602u);
|
||||
} break;
|
||||
case Name::EnterpriseBASIC21: {
|
||||
const std::initializer_list<std::string> filenames = {
|
||||
"basic21.bin",
|
||||
"BASIC Interpreter v2.1 (1985)(Intelligent Software).bin",
|
||||
"BASIC Interpreter v2.1 (1985)(Intelligent Software)[a].bin"
|
||||
};
|
||||
const std::initializer_list<uint32_t> crcs = { 0x55f96251, 0x683cf455 };
|
||||
*this = Description(name, "Enterprise", "the Enterprise BASIC ROM v2.1", filenames, 16 * 1024, crcs);
|
||||
} break;
|
||||
|
||||
case Name::EnterpriseEPDOS: {
|
||||
const std::initializer_list<std::string> filenames = {"epdos.bin", "EPDOS v1.7 (19xx)(Haluska, Laszlo).bin"};
|
||||
*this = Description(name, "Enterprise", "the Enterprise EPDOS ROM", filenames, 32 * 1024, 0x201319ebu);
|
||||
} break;
|
||||
case Name::EnterpriseEXDOS: {
|
||||
const std::initializer_list<std::string> filenames = {"exdos.bin", "EX-DOS EPROM (198x)(Enterprise).bin"};
|
||||
*this = Description(name, "Enterprise", "the Enterprise EXDOS ROM", filenames, 16 * 1024, 0xe6daa0e9u);
|
||||
} break;
|
||||
|
||||
case Name::Macintosh128k: *this = Description(name, "Macintosh", "the Macintosh 128k ROM", "mac128k.rom", 64*1024, 0x6d0c8a28u); break;
|
||||
case Name::Macintosh512k: *this = Description(name, "Macintosh", "the Macintosh 512k ROM", "mac512k.rom", 64*1024, 0xcf759e0d); break;
|
||||
case Name::MacintoshPlus: {
|
||||
|
||||
@@ -31,6 +31,17 @@ enum Name {
|
||||
PRESAdvancedPlus6,
|
||||
Acorn1770DFS,
|
||||
|
||||
// Amiga.
|
||||
AmigaKickstart10,
|
||||
AmigaKickstart11,
|
||||
AmigaKickstart12,
|
||||
AmigaA500Kickstart13,
|
||||
AmigaA3000Kickstart13,
|
||||
AmigaKickstart20,
|
||||
AmigaA500PlusKickstart204,
|
||||
AmigaA600Kickstart205,
|
||||
AmigaA500Kickstart31,
|
||||
|
||||
// Amstrad CPC.
|
||||
AMSDOS,
|
||||
CPC464Firmware, CPC464BASIC,
|
||||
@@ -71,6 +82,22 @@ enum Name {
|
||||
DiskIIStateMachine13Sector,
|
||||
DiskIIBoot13Sector,
|
||||
|
||||
// Enterprise.
|
||||
EnterpriseEXOS10,
|
||||
EnterpriseEXOS20,
|
||||
EnterpriseEXOS21,
|
||||
EnterpriseEXOS23,
|
||||
|
||||
EnterpriseBASIC10,
|
||||
EnterpriseBASIC10Part1,
|
||||
EnterpriseBASIC10Part2,
|
||||
EnterpriseBASIC11,
|
||||
EnterpriseBASIC11Suffixed,
|
||||
EnterpriseBASIC21,
|
||||
|
||||
EnterpriseEPDOS,
|
||||
EnterpriseEXDOS,
|
||||
|
||||
// Macintosh.
|
||||
Macintosh128k,
|
||||
Macintosh512k,
|
||||
@@ -237,6 +264,10 @@ struct Request {
|
||||
bool is_optional = false;
|
||||
std::vector<Node> children;
|
||||
|
||||
bool empty() const {
|
||||
return type == Type::One && name == Name::None;
|
||||
}
|
||||
|
||||
void add_descriptions(std::vector<Description> &) const;
|
||||
bool validate(Map &) const;
|
||||
void visit(
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "Sizes.hpp"
|
||||
|
||||
namespace Numeric {
|
||||
|
||||
template <typename IntType> struct LSFRPolynomial {};
|
||||
@@ -67,8 +69,8 @@ template <typename IntType = uint64_t, IntType polynomial = LSFRPolynomial<IntTy
|
||||
determining the bit that was just shifted out.
|
||||
*/
|
||||
IntType next() {
|
||||
const auto result = value_ & 1;
|
||||
value_ = (value_ >> 1) ^ (result * polynomial);
|
||||
const auto result = IntType(value_ & 1);
|
||||
value_ = IntType((value_ >> 1) ^ (result * polynomial));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -76,6 +78,8 @@ template <typename IntType = uint64_t, IntType polynomial = LSFRPolynomial<IntTy
|
||||
IntType value_ = 0;
|
||||
};
|
||||
|
||||
template <uint64_t polynomial> class LFSRv: public LFSR<typename MinIntTypeValue<polynomial>::type, polynomial> {};
|
||||
|
||||
}
|
||||
|
||||
#endif /* LFSR_h */
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#define Sizes_h
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
/*!
|
||||
Maps to the smallest integral type that can contain max_value, from the following options:
|
||||
@@ -15,8 +15,19 @@
|
||||
4B051C912669C90B00CA44E8 /* ROMCatalogue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051C5826670A9300CA44E8 /* ROMCatalogue.cpp */; };
|
||||
4B051C922669C90B00CA44E8 /* ROMCatalogue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051C5826670A9300CA44E8 /* ROMCatalogue.cpp */; };
|
||||
4B051C93266D9D6900CA44E8 /* ROMImages in Resources */ = {isa = PBXBuildFile; fileRef = 4BC9DF441D044FCA00F44158 /* ROMImages */; };
|
||||
4B051C95266EF50200CA44E8 /* AppleIIOptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B051C94266EF50200CA44E8 /* AppleIIOptionsPanel.swift */; };
|
||||
4B051C95266EF50200CA44E8 /* AppleIIController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B051C94266EF50200CA44E8 /* AppleIIController.swift */; };
|
||||
4B051C97266EF5F600CA44E8 /* CSAppleII.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B051C96266EF5F600CA44E8 /* CSAppleII.mm */; };
|
||||
4B051CA22676F52200CA44E8 /* Enterprise.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051CA12676F52200CA44E8 /* Enterprise.cpp */; };
|
||||
4B051CA32676F52200CA44E8 /* Enterprise.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051CA12676F52200CA44E8 /* Enterprise.cpp */; };
|
||||
4B051CA826781D6500CA44E8 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051CA726781D6500CA44E8 /* StaticAnalyser.cpp */; };
|
||||
4B051CA926781D6500CA44E8 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051CA726781D6500CA44E8 /* StaticAnalyser.cpp */; };
|
||||
4B051CAC26783E2000CA44E8 /* Nick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051CAA26783E2000CA44E8 /* Nick.cpp */; };
|
||||
4B051CAD26783E2000CA44E8 /* Nick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051CAA26783E2000CA44E8 /* Nick.cpp */; };
|
||||
4B051CB0267C1CA200CA44E8 /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051CAE267C1CA200CA44E8 /* Keyboard.cpp */; };
|
||||
4B051CB1267C1CA200CA44E8 /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051CAE267C1CA200CA44E8 /* Keyboard.cpp */; };
|
||||
4B051CB3267D3FF800CA44E8 /* EnterpriseNickTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B051CB2267D3FF800CA44E8 /* EnterpriseNickTests.mm */; };
|
||||
4B051CB62680158600CA44E8 /* EXDos.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051CB42680158600CA44E8 /* EXDos.cpp */; };
|
||||
4B051CB72680158600CA44E8 /* EXDos.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B051CB42680158600CA44E8 /* EXDos.cpp */; };
|
||||
4B05401E219D1618001BF69C /* ScanTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B05401D219D1618001BF69C /* ScanTarget.cpp */; };
|
||||
4B05401F219D1618001BF69C /* ScanTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B05401D219D1618001BF69C /* ScanTarget.cpp */; };
|
||||
4B055A7A1FAE78A00060FFFF /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B055A771FAE78210060FFFF /* SDL2.framework */; };
|
||||
@@ -230,6 +241,8 @@
|
||||
4B4518A31F75FD1C00926311 /* HFE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518951F75FD1B00926311 /* HFE.cpp */; };
|
||||
4B4518A41F75FD1C00926311 /* OricMFMDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518971F75FD1B00926311 /* OricMFMDSK.cpp */; };
|
||||
4B4518A51F75FD1C00926311 /* SSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518991F75FD1B00926311 /* SSD.cpp */; };
|
||||
4B47770B268FBE4D005C2340 /* FAT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B477709268FBE4D005C2340 /* FAT.cpp */; };
|
||||
4B47770D26900685005C2340 /* EnterpriseDaveTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B47770C26900685005C2340 /* EnterpriseDaveTests.mm */; };
|
||||
4B47F6C5241C87A100ED06F7 /* Struct.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B47F6C4241C87A100ED06F7 /* Struct.cpp */; };
|
||||
4B47F6C6241C87A100ED06F7 /* Struct.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B47F6C4241C87A100ED06F7 /* Struct.cpp */; };
|
||||
4B49F0A923346F7A0045E6A6 /* MacintoshOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B49F0A723346F7A0045E6A6 /* MacintoshOptions.xib */; };
|
||||
@@ -312,7 +325,7 @@
|
||||
4B778F0023A5EB990000D260 /* G64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518931F75FD1B00926311 /* G64.cpp */; };
|
||||
4B778F0123A5EBA00000D260 /* MacintoshIMG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4BFAE22A42F290069048D /* MacintoshIMG.cpp */; };
|
||||
4B778F0223A5EBA40000D260 /* MFMSectorDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */; };
|
||||
4B778F0323A5EBB00000D260 /* MSXDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB4B2002C4BF000708CC /* MSXDSK.cpp */; };
|
||||
4B778F0323A5EBB00000D260 /* FAT12.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB4B2002C4BF000708CC /* FAT12.cpp */; };
|
||||
4B778F0423A5EBB00000D260 /* OricMFMDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518971F75FD1B00926311 /* OricMFMDSK.cpp */; };
|
||||
4B778F0523A5EBB00000D260 /* ST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BE0A3EC237BB170002AB46F /* ST.cpp */; };
|
||||
4B778F0623A5EC150000D260 /* CAS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0E04E81FC9E5DA00F43484 /* CAS.cpp */; };
|
||||
@@ -546,7 +559,7 @@
|
||||
4B8FE21B1DA19D5F0090D3CE /* Atari2600Options.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B8FE2131DA19D5F0090D3CE /* Atari2600Options.xib */; };
|
||||
4B8FE21C1DA19D5F0090D3CE /* MachineDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B8FE2151DA19D5F0090D3CE /* MachineDocument.xib */; };
|
||||
4B8FE21D1DA19D5F0090D3CE /* QuickLoadCompositeOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B8FE2171DA19D5F0090D3CE /* QuickLoadCompositeOptions.xib */; };
|
||||
4B8FE2221DA19FB20090D3CE /* MachinePanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE2211DA19FB20090D3CE /* MachinePanel.swift */; };
|
||||
4B8FE2221DA19FB20090D3CE /* MachineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE2211DA19FB20090D3CE /* MachineController.swift */; };
|
||||
4B8FE2271DA1DE2D0090D3CE /* NSBundle+DataResource.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE2261DA1DE2D0090D3CE /* NSBundle+DataResource.m */; };
|
||||
4B90467422C6FADD000E2074 /* 68000BitwiseTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B90467322C6FADD000E2074 /* 68000BitwiseTests.mm */; };
|
||||
4B90467622C6FD6E000E2074 /* 68000ArithmeticTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B90467522C6FD6E000E2074 /* 68000ArithmeticTests.mm */; };
|
||||
@@ -575,7 +588,7 @@
|
||||
4BA91E1D216D85BA00F79557 /* MasterSystemVDPTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA91E1C216D85BA00F79557 /* MasterSystemVDPTests.mm */; };
|
||||
4BAD13441FF709C700FD114A /* MSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0E61051FF34737002A9DBD /* MSX.cpp */; };
|
||||
4BAE49582032881E004BE78E /* CSZX8081.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B14978E1EE4B4D200CE2596 /* CSZX8081.mm */; };
|
||||
4BAE495920328897004BE78E /* ZX8081OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B95FA9C1F11893B0008E395 /* ZX8081OptionsPanel.swift */; };
|
||||
4BAE495920328897004BE78E /* ZX8081Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B95FA9C1F11893B0008E395 /* ZX8081Controller.swift */; };
|
||||
4BAF2B4E2004580C00480230 /* DMK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAF2B4C2004580C00480230 /* DMK.cpp */; };
|
||||
4BAF2B4F2004580C00480230 /* DMK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAF2B4C2004580C00480230 /* DMK.cpp */; };
|
||||
4BB0A65B2044FD3000FB3688 /* SN76489.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB0A6592044FD3000FB3688 /* SN76489.cpp */; };
|
||||
@@ -934,7 +947,7 @@
|
||||
4BDACBEC22FFA5D20045EF7E /* ncr5380.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BDACBEA22FFA5D20045EF7E /* ncr5380.cpp */; };
|
||||
4BDACBED22FFA5D20045EF7E /* ncr5380.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BDACBEA22FFA5D20045EF7E /* ncr5380.cpp */; };
|
||||
4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A539A1D117D36003C6002 /* CSAtari2600.mm */; };
|
||||
4BDB61EC203285AE0048AF91 /* Atari2600OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsPanel.swift */; };
|
||||
4BDB61EC203285AE0048AF91 /* Atari2600OptionsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsController.swift */; };
|
||||
4BDDBA991EF3451200347E61 /* Z80MachineCycleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */; };
|
||||
4BE0A3EE237BB170002AB46F /* ST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BE0A3EC237BB170002AB46F /* ST.cpp */; };
|
||||
4BE0A3EF237BB170002AB46F /* ST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BE0A3EC237BB170002AB46F /* ST.cpp */; };
|
||||
@@ -950,8 +963,8 @@
|
||||
4BE9A6B11EDE293000CBCB47 /* zexdoc.com in Resources */ = {isa = PBXBuildFile; fileRef = 4BE9A6B01EDE293000CBCB47 /* zexdoc.com */; };
|
||||
4BEA525E1DF33323007E74F2 /* Tape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEA525D1DF33323007E74F2 /* Tape.cpp */; };
|
||||
4BEA52631DF339D7007E74F2 /* SoundGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEA52611DF339D7007E74F2 /* SoundGenerator.cpp */; };
|
||||
4BEBFB4D2002C4BF000708CC /* MSXDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB4B2002C4BF000708CC /* MSXDSK.cpp */; };
|
||||
4BEBFB4E2002C4BF000708CC /* MSXDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB4B2002C4BF000708CC /* MSXDSK.cpp */; };
|
||||
4BEBFB4D2002C4BF000708CC /* FAT12.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB4B2002C4BF000708CC /* FAT12.cpp */; };
|
||||
4BEBFB4E2002C4BF000708CC /* FAT12.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB4B2002C4BF000708CC /* FAT12.cpp */; };
|
||||
4BEBFB512002DB30000708CC /* DiskROM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB4F2002DB30000708CC /* DiskROM.cpp */; };
|
||||
4BEBFB522002DB30000708CC /* DiskROM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB4F2002DB30000708CC /* DiskROM.cpp */; };
|
||||
4BEDA3BA25B25563000C2DBD /* Decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BEDA3B425B25563000C2DBD /* Decoder.cpp */; };
|
||||
@@ -987,6 +1000,8 @@
|
||||
4BFCA1291ECBE7A700AC40C1 /* zexall.com in Resources */ = {isa = PBXBuildFile; fileRef = 4BFCA1281ECBE7A700AC40C1 /* zexall.com */; };
|
||||
4BFCA12B1ECBE7C400AC40C1 /* ZexallTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA12A1ECBE7C400AC40C1 /* ZexallTests.swift */; };
|
||||
4BFDD78C1F7F2DB4008579B9 /* ImplicitSectors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFDD78B1F7F2DB4008579B9 /* ImplicitSectors.cpp */; };
|
||||
4BFEA2EF2682A7B900EBF94C /* Dave.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFEA2ED2682A7B900EBF94C /* Dave.cpp */; };
|
||||
4BFEA2F02682A7B900EBF94C /* Dave.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFEA2ED2682A7B900EBF94C /* Dave.cpp */; };
|
||||
4BFF1D3922337B0300838EA1 /* 68000Storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFF1D3822337B0300838EA1 /* 68000Storage.cpp */; };
|
||||
4BFF1D3A22337B0300838EA1 /* 68000Storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFF1D3822337B0300838EA1 /* 68000Storage.cpp */; };
|
||||
4BFF1D3D2235C3C100838EA1 /* EmuTOSTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BFF1D3C2235C3C100838EA1 /* EmuTOSTests.mm */; };
|
||||
@@ -1025,9 +1040,21 @@
|
||||
4B04B65622A58CB40006AB58 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
|
||||
4B051C5826670A9300CA44E8 /* ROMCatalogue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ROMCatalogue.cpp; sourceTree = "<group>"; };
|
||||
4B051C5926670A9300CA44E8 /* ROMCatalogue.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMCatalogue.hpp; sourceTree = "<group>"; };
|
||||
4B051C94266EF50200CA44E8 /* AppleIIOptionsPanel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppleIIOptionsPanel.swift; sourceTree = "<group>"; };
|
||||
4B051C94266EF50200CA44E8 /* AppleIIController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppleIIController.swift; sourceTree = "<group>"; };
|
||||
4B051C96266EF5F600CA44E8 /* CSAppleII.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CSAppleII.mm; sourceTree = "<group>"; };
|
||||
4B051C98266EF60500CA44E8 /* CSAppleII.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSAppleII.h; sourceTree = "<group>"; };
|
||||
4B051CA02676F52200CA44E8 /* Enterprise.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Enterprise.hpp; sourceTree = "<group>"; };
|
||||
4B051CA12676F52200CA44E8 /* Enterprise.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Enterprise.cpp; sourceTree = "<group>"; };
|
||||
4B051CA526781D6500CA44E8 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = "<group>"; };
|
||||
4B051CA626781D6500CA44E8 /* Target.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
|
||||
4B051CA726781D6500CA44E8 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = "<group>"; };
|
||||
4B051CAA26783E2000CA44E8 /* Nick.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Nick.cpp; sourceTree = "<group>"; };
|
||||
4B051CAB26783E2000CA44E8 /* Nick.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Nick.hpp; sourceTree = "<group>"; };
|
||||
4B051CAE267C1CA200CA44E8 /* Keyboard.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Keyboard.cpp; sourceTree = "<group>"; };
|
||||
4B051CAF267C1CA200CA44E8 /* Keyboard.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Keyboard.hpp; sourceTree = "<group>"; };
|
||||
4B051CB2267D3FF800CA44E8 /* EnterpriseNickTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EnterpriseNickTests.mm; sourceTree = "<group>"; };
|
||||
4B051CB42680158600CA44E8 /* EXDos.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = EXDos.cpp; sourceTree = "<group>"; };
|
||||
4B051CB52680158600CA44E8 /* EXDos.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = EXDos.hpp; sourceTree = "<group>"; };
|
||||
4B05401D219D1618001BF69C /* ScanTarget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ScanTarget.cpp; sourceTree = "<group>"; };
|
||||
4B055A6A1FAE763F0060FFFF /* Clock Signal Kiosk */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Clock Signal Kiosk"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4B055A771FAE78210060FFFF /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = ../../../../Library/Frameworks/SDL2.framework; sourceTree = SOURCE_ROOT; };
|
||||
@@ -1251,6 +1278,9 @@
|
||||
4B45189A1F75FD1B00926311 /* SSD.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SSD.hpp; sourceTree = "<group>"; };
|
||||
4B4518A71F76004200926311 /* TapeParser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = TapeParser.hpp; path = Parsers/TapeParser.hpp; sourceTree = "<group>"; };
|
||||
4B4518A81F76022000926311 /* DiskImageImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DiskImageImplementation.hpp; sourceTree = "<group>"; };
|
||||
4B477709268FBE4D005C2340 /* FAT.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FAT.cpp; path = Parsers/FAT.cpp; sourceTree = "<group>"; };
|
||||
4B47770A268FBE4D005C2340 /* FAT.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = FAT.hpp; path = Parsers/FAT.hpp; sourceTree = "<group>"; };
|
||||
4B47770C26900685005C2340 /* EnterpriseDaveTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EnterpriseDaveTests.mm; sourceTree = "<group>"; };
|
||||
4B47F6C4241C87A100ED06F7 /* Struct.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Struct.cpp; sourceTree = "<group>"; };
|
||||
4B49F0A823346F7A0045E6A6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/MacintoshOptions.xib"; sourceTree = SOURCE_ROOT; };
|
||||
4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AY38910.cpp; sourceTree = "<group>"; };
|
||||
@@ -1515,8 +1545,8 @@
|
||||
4B8FE2141DA19D5F0090D3CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/Atari2600Options.xib"; sourceTree = SOURCE_ROOT; };
|
||||
4B8FE2161DA19D5F0090D3CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/MachineDocument.xib"; sourceTree = SOURCE_ROOT; };
|
||||
4B8FE2181DA19D5F0090D3CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/QuickLoadCompositeOptions.xib"; sourceTree = SOURCE_ROOT; };
|
||||
4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsPanel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Atari2600OptionsPanel.swift; sourceTree = "<group>"; };
|
||||
4B8FE2211DA19FB20090D3CE /* MachinePanel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MachinePanel.swift; sourceTree = "<group>"; };
|
||||
4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Atari2600OptionsController.swift; sourceTree = "<group>"; };
|
||||
4B8FE2211DA19FB20090D3CE /* MachineController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MachineController.swift; sourceTree = "<group>"; };
|
||||
4B8FE2251DA1DE2D0090D3CE /* NSBundle+DataResource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+DataResource.h"; sourceTree = "<group>"; };
|
||||
4B8FE2261DA1DE2D0090D3CE /* NSBundle+DataResource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+DataResource.m"; sourceTree = "<group>"; };
|
||||
4B90467222C6FA31000E2074 /* TestRunner68000.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TestRunner68000.hpp; sourceTree = "<group>"; };
|
||||
@@ -1533,7 +1563,7 @@
|
||||
4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 6502TimingTests.swift; sourceTree = "<group>"; };
|
||||
4B9378E222A199C600973513 /* Audio.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Audio.cpp; sourceTree = "<group>"; };
|
||||
4B9378E322A199C600973513 /* Audio.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Audio.hpp; sourceTree = "<group>"; };
|
||||
4B95FA9C1F11893B0008E395 /* ZX8081OptionsPanel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZX8081OptionsPanel.swift; sourceTree = "<group>"; };
|
||||
4B95FA9C1F11893B0008E395 /* ZX8081Controller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZX8081Controller.swift; sourceTree = "<group>"; };
|
||||
4B961408222760E0001A7BF2 /* Screenshot.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Screenshot.hpp; sourceTree = "<group>"; };
|
||||
4B96F7CB263E30B00092AEE1 /* RawSectorDump.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RawSectorDump.hpp; sourceTree = "<group>"; };
|
||||
4B96F7CC263E33B10092AEE1 /* DSK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DSK.cpp; sourceTree = "<group>"; };
|
||||
@@ -1998,8 +2028,8 @@
|
||||
4BEA52601DF3343A007E74F2 /* Interrupts.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Interrupts.hpp; sourceTree = "<group>"; };
|
||||
4BEA52611DF339D7007E74F2 /* SoundGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SoundGenerator.cpp; sourceTree = "<group>"; };
|
||||
4BEA52621DF339D7007E74F2 /* SoundGenerator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SoundGenerator.hpp; sourceTree = "<group>"; };
|
||||
4BEBFB4B2002C4BF000708CC /* MSXDSK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MSXDSK.cpp; sourceTree = "<group>"; };
|
||||
4BEBFB4C2002C4BF000708CC /* MSXDSK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MSXDSK.hpp; sourceTree = "<group>"; };
|
||||
4BEBFB4B2002C4BF000708CC /* FAT12.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FAT12.cpp; sourceTree = "<group>"; };
|
||||
4BEBFB4C2002C4BF000708CC /* FAT12.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = FAT12.hpp; sourceTree = "<group>"; };
|
||||
4BEBFB4F2002DB30000708CC /* DiskROM.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DiskROM.cpp; sourceTree = "<group>"; };
|
||||
4BEBFB502002DB30000708CC /* DiskROM.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DiskROM.hpp; sourceTree = "<group>"; };
|
||||
4BEDA3B425B25563000C2DBD /* Decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Decoder.cpp; sourceTree = "<group>"; };
|
||||
@@ -2049,6 +2079,9 @@
|
||||
4BFDD78A1F7F2DB4008579B9 /* ImplicitSectors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ImplicitSectors.hpp; sourceTree = "<group>"; };
|
||||
4BFDD78B1F7F2DB4008579B9 /* ImplicitSectors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImplicitSectors.cpp; sourceTree = "<group>"; };
|
||||
4BFE7B861FC39BF100160B38 /* StandardOptions.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = StandardOptions.hpp; sourceTree = "<group>"; };
|
||||
4BFEA2ED2682A7B900EBF94C /* Dave.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Dave.cpp; sourceTree = "<group>"; };
|
||||
4BFEA2EE2682A7B900EBF94C /* Dave.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Dave.hpp; sourceTree = "<group>"; };
|
||||
4BFEA2F12682A90200EBF94C /* Sizes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Sizes.hpp; sourceTree = "<group>"; };
|
||||
4BFF1D342233778C00838EA1 /* 68000.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 68000.hpp; sourceTree = "<group>"; };
|
||||
4BFF1D37223379D500838EA1 /* 68000Storage.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 68000Storage.hpp; sourceTree = "<group>"; };
|
||||
4BFF1D3822337B0300838EA1 /* 68000Storage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = 68000Storage.cpp; sourceTree = "<group>"; };
|
||||
@@ -2090,6 +2123,33 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
4B051C9F2676F52200CA44E8 /* Enterprise */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BFEA2ED2682A7B900EBF94C /* Dave.cpp */,
|
||||
4B051CA12676F52200CA44E8 /* Enterprise.cpp */,
|
||||
4B051CB42680158600CA44E8 /* EXDos.cpp */,
|
||||
4B051CAE267C1CA200CA44E8 /* Keyboard.cpp */,
|
||||
4B051CAA26783E2000CA44E8 /* Nick.cpp */,
|
||||
4BFEA2EE2682A7B900EBF94C /* Dave.hpp */,
|
||||
4B051CA02676F52200CA44E8 /* Enterprise.hpp */,
|
||||
4B051CB52680158600CA44E8 /* EXDos.hpp */,
|
||||
4B051CAF267C1CA200CA44E8 /* Keyboard.hpp */,
|
||||
4B051CAB26783E2000CA44E8 /* Nick.hpp */,
|
||||
);
|
||||
path = Enterprise;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B051CA426781D6500CA44E8 /* Enterprise */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B051CA726781D6500CA44E8 /* StaticAnalyser.cpp */,
|
||||
4B051CA526781D6500CA44E8 /* StaticAnalyser.hpp */,
|
||||
4B051CA626781D6500CA44E8 /* Target.hpp */,
|
||||
);
|
||||
path = Enterprise;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B055A761FAE78210060FFFF /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2602,7 +2662,9 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B3FE75C1F3CF68B00448EE4 /* CPM.cpp */,
|
||||
4B477709268FBE4D005C2340 /* FAT.cpp */,
|
||||
4B3FE75D1F3CF68B00448EE4 /* CPM.hpp */,
|
||||
4B47770A268FBE4D005C2340 /* FAT.hpp */,
|
||||
);
|
||||
name = Parsers;
|
||||
sourceTree = "<group>";
|
||||
@@ -2655,34 +2717,36 @@
|
||||
4B45188C1F75FD1B00926311 /* Formats */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B80CD74256CA15E00176FCC /* 2MG.cpp */,
|
||||
4B45188D1F75FD1B00926311 /* AcornADF.cpp */,
|
||||
4B0333AD2094081A0050B93D /* AppleDSK.cpp */,
|
||||
4B45188F1F75FD1B00926311 /* CPCDSK.cpp */,
|
||||
4B4518911F75FD1B00926311 /* D64.cpp */,
|
||||
4BAF2B4C2004580C00480230 /* DMK.cpp */,
|
||||
4BEBFB4B2002C4BF000708CC /* FAT12.cpp */,
|
||||
4B4518931F75FD1B00926311 /* G64.cpp */,
|
||||
4B4518951F75FD1B00926311 /* HFE.cpp */,
|
||||
4BB4BFAE22A42F290069048D /* MacintoshIMG.cpp */,
|
||||
4B58601C1F806AB200AEE2E3 /* MFMSectorDump.cpp */,
|
||||
4BC131782346DF2B00E4FF3D /* MSA.cpp */,
|
||||
4BEBFB4B2002C4BF000708CC /* MSXDSK.cpp */,
|
||||
4B0F94FC208C1A1600FE41D9 /* NIB.cpp */,
|
||||
4B4518971F75FD1B00926311 /* OricMFMDSK.cpp */,
|
||||
4B4518991F75FD1B00926311 /* SSD.cpp */,
|
||||
4BE0A3EC237BB170002AB46F /* ST.cpp */,
|
||||
4B7BA03323C58B1E00B98D9E /* STX.cpp */,
|
||||
4B6ED2EE208E2F8A0047B343 /* WOZ.cpp */,
|
||||
4B80CD75256CA15E00176FCC /* 2MG.hpp */,
|
||||
4B45188E1F75FD1B00926311 /* AcornADF.hpp */,
|
||||
4B0333AE2094081A0050B93D /* AppleDSK.hpp */,
|
||||
4B4518901F75FD1B00926311 /* CPCDSK.hpp */,
|
||||
4B4518921F75FD1B00926311 /* D64.hpp */,
|
||||
4BAF2B4D2004580C00480230 /* DMK.hpp */,
|
||||
4BEBFB4C2002C4BF000708CC /* FAT12.hpp */,
|
||||
4B4518941F75FD1B00926311 /* G64.hpp */,
|
||||
4B4518961F75FD1B00926311 /* HFE.hpp */,
|
||||
4BB4BFAF22A42F290069048D /* MacintoshIMG.hpp */,
|
||||
4B58601D1F806AB200AEE2E3 /* MFMSectorDump.hpp */,
|
||||
4BC131792346DF2B00E4FF3D /* MSA.hpp */,
|
||||
4BEBFB4C2002C4BF000708CC /* MSXDSK.hpp */,
|
||||
4B0F94FD208C1A1600FE41D9 /* NIB.hpp */,
|
||||
4B4518981F75FD1B00926311 /* OricMFMDSK.hpp */,
|
||||
4B45189A1F75FD1B00926311 /* SSD.hpp */,
|
||||
@@ -2690,8 +2754,6 @@
|
||||
4B7BA03223C58B1E00B98D9E /* STX.hpp */,
|
||||
4B6ED2EF208E2F8A0047B343 /* WOZ.hpp */,
|
||||
4BFDD7891F7F2DB4008579B9 /* Utility */,
|
||||
4B80CD74256CA15E00176FCC /* 2MG.cpp */,
|
||||
4B80CD75256CA15E00176FCC /* 2MG.hpp */,
|
||||
);
|
||||
path = Formats;
|
||||
sourceTree = "<group>";
|
||||
@@ -2784,11 +2846,11 @@
|
||||
4B55CE551C3B7D360093A61B /* Documents */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B051C94266EF50200CA44E8 /* AppleIIOptionsPanel.swift */,
|
||||
4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsPanel.swift */,
|
||||
4B051C94266EF50200CA44E8 /* AppleIIController.swift */,
|
||||
4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsController.swift */,
|
||||
4B55CE5E1C3B7D960093A61B /* MachineDocument.swift */,
|
||||
4B8FE2211DA19FB20090D3CE /* MachinePanel.swift */,
|
||||
4B95FA9C1F11893B0008E395 /* ZX8081OptionsPanel.swift */,
|
||||
4B8FE2211DA19FB20090D3CE /* MachineController.swift */,
|
||||
4B95FA9C1F11893B0008E395 /* ZX8081Controller.swift */,
|
||||
4B08A56720D72BEF0016CE5A /* Activity.xib */,
|
||||
4BC5FC2E20CDDDEE00410AA0 /* AppleIIOptions.xib */,
|
||||
4B8FE2131DA19D5F0090D3CE /* Atari2600Options.xib */,
|
||||
@@ -3048,6 +3110,7 @@
|
||||
children = (
|
||||
4B7BA03E23D55E7900B98D9E /* CRC.hpp */,
|
||||
4B7BA03F23D55E7900B98D9E /* LFSR.hpp */,
|
||||
4BFEA2F12682A90200EBF94C /* Sizes.hpp */,
|
||||
);
|
||||
name = Numeric;
|
||||
path = ../../Numeric;
|
||||
@@ -3185,6 +3248,7 @@
|
||||
4B8944FB201967B4007DE474 /* Commodore */,
|
||||
4B894507201967B4007DE474 /* Disassembler */,
|
||||
4BD67DC8209BE4D600AB2146 /* DiskII */,
|
||||
4B051CA426781D6500CA44E8 /* Enterprise */,
|
||||
4BB4BFB622A4372E0069048D /* Macintosh */,
|
||||
4B89450F201967B4007DE474 /* MSX */,
|
||||
4B8944F6201967B4007DE474 /* Oric */,
|
||||
@@ -3990,12 +4054,8 @@
|
||||
4BB73EB51B587A5100552FC2 /* Clock SignalTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BC9E1ED1D23449A003FCEE4 /* 6502InterruptTests.swift */,
|
||||
4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */,
|
||||
4BC751B11D157E61006C31D9 /* 6522Tests.swift */,
|
||||
4B1E85801D176468001EF87D /* 6532Tests.swift */,
|
||||
4B4F478925367EDC004245B8 /* 65816AddressingTests.swift */,
|
||||
4B8DF5132550D62900F3433C /* 65816kromTests.swift */,
|
||||
4B85322922778E4200F26553 /* Comparative68000.hpp */,
|
||||
4B90467222C6FA31000E2074 /* TestRunner68000.hpp */,
|
||||
4B90467522C6FD6E000E2074 /* 68000ArithmeticTests.mm */,
|
||||
4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */,
|
||||
4B90467322C6FADD000E2074 /* 68000BitwiseTests.mm */,
|
||||
@@ -4004,43 +4064,49 @@
|
||||
4BC5C3DF22C994CC00795658 /* 68000MoveTests.mm */,
|
||||
4B9D0C4E22C7E0CF00DE1AD3 /* 68000RollShiftTests.mm */,
|
||||
4BD388872239E198002D14B5 /* 68000Tests.mm */,
|
||||
4BB73EB61B587A5100552FC2 /* AllSuiteATests.swift */,
|
||||
4B924E981E74D22700B76AF1 /* AtariStaticAnalyserTests.mm */,
|
||||
4BE34437238389E10058E78F /* AtariSTVideoTests.mm */,
|
||||
4B049CDC1DA3C82F00322067 /* BCDTest.swift */,
|
||||
4B3BA0C41D318B44005DD7A7 /* Bridges */,
|
||||
4B3BA0C21D318AEB005DD7A7 /* C1540Tests.swift */,
|
||||
4B85322922778E4200F26553 /* Comparative68000.hpp */,
|
||||
4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */,
|
||||
4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */,
|
||||
4BFF1D3C2235C3C100838EA1 /* EmuTOSTests.mm */,
|
||||
4BBF49AE1ED2880200AB3669 /* FUSETests.swift */,
|
||||
4B47770C26900685005C2340 /* EnterpriseDaveTests.mm */,
|
||||
4B051CB2267D3FF800CA44E8 /* EnterpriseNickTests.mm */,
|
||||
4B8DF4D725465B7500F3433C /* IIgsMemoryMapTests.mm */,
|
||||
4BB73EB81B587A5100552FC2 /* Info.plist */,
|
||||
4B4F477B253530B7004245B8 /* Jeek816Tests.swift */,
|
||||
4B1414611B58888700E04248 /* KlausDormannTests.swift */,
|
||||
4BEE1EBF22B5E236000A26A6 /* MacGCRTests.mm */,
|
||||
4BE90FFC22D5864800FB464D /* MacintoshVideoTests.mm */,
|
||||
4BA91E1C216D85BA00F79557 /* MasterSystemVDPTests.mm */,
|
||||
4B98A0601FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm */,
|
||||
4BC0CB272446BC7B00A79DBB /* OPLTests.mm */,
|
||||
4BD91D762401C2B8007BDC91 /* PatrikRakTests.swift */,
|
||||
4B121F9A1E06293F00BFDA12 /* PCMSegmentEventSourceTests.mm */,
|
||||
4BD4A8CF1E077FD20020D856 /* PCMTrackTests.mm */,
|
||||
4B3F76B825A1635300178AEC /* PowerPCDecoderTests.mm */,
|
||||
4BE76CF822641ED300ACD6FA /* QLTests.mm */,
|
||||
4B8DD3672633B2D400B3C866 /* SpectrumVideoContentionTests.mm */,
|
||||
4B1414631B588A1100E04248 /* Test Binaries */,
|
||||
4B90467222C6FA31000E2074 /* TestRunner68000.hpp */,
|
||||
4B2AF8681E513FC20027EE29 /* TIATests.mm */,
|
||||
4B1D08051E0F7A1100763741 /* TimeTests.mm */,
|
||||
4B14145F1B58885000E04248 /* WolfgangLorenzTests.swift */,
|
||||
4BEE4BD325A26E2B00011BD2 /* x86DecoderTests.mm */,
|
||||
4BDA8234261E8E000021AA19 /* Z80ContentionTests.mm */,
|
||||
4BB73EB81B587A5100552FC2 /* Info.plist */,
|
||||
4BC9E1ED1D23449A003FCEE4 /* 6502InterruptTests.swift */,
|
||||
4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */,
|
||||
4BC751B11D157E61006C31D9 /* 6522Tests.swift */,
|
||||
4B1E85801D176468001EF87D /* 6532Tests.swift */,
|
||||
4B4F478925367EDC004245B8 /* 65816AddressingTests.swift */,
|
||||
4B8DF5132550D62900F3433C /* 65816kromTests.swift */,
|
||||
4BB73EB61B587A5100552FC2 /* AllSuiteATests.swift */,
|
||||
4B049CDC1DA3C82F00322067 /* BCDTest.swift */,
|
||||
4B3BA0C21D318AEB005DD7A7 /* C1540Tests.swift */,
|
||||
4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */,
|
||||
4BBF49AE1ED2880200AB3669 /* FUSETests.swift */,
|
||||
4B4F477B253530B7004245B8 /* Jeek816Tests.swift */,
|
||||
4B1414611B58888700E04248 /* KlausDormannTests.swift */,
|
||||
4BD91D762401C2B8007BDC91 /* PatrikRakTests.swift */,
|
||||
4B14145F1B58885000E04248 /* WolfgangLorenzTests.swift */,
|
||||
4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */,
|
||||
4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */,
|
||||
4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */,
|
||||
4BFCA12A1ECBE7C400AC40C1 /* ZexallTests.swift */,
|
||||
4B3BA0C41D318B44005DD7A7 /* Bridges */,
|
||||
4B1414631B588A1100E04248 /* Test Binaries */,
|
||||
);
|
||||
path = "Clock SignalTests";
|
||||
sourceTree = "<group>";
|
||||
@@ -4075,6 +4141,7 @@
|
||||
4B7A90E22041097C008514A2 /* ColecoVision */,
|
||||
4B4DC81D1D2C2425003C5BF8 /* Commodore */,
|
||||
4B2E2D9E1C3A070900138695 /* Electron */,
|
||||
4B051C9F2676F52200CA44E8 /* Enterprise */,
|
||||
4B7F188B2154825D00388727 /* MasterSystem */,
|
||||
4B79A4FC1FC8FF9800EEDAD5 /* MSX */,
|
||||
4BCF1FA51DADC3E10039D2E7 /* Oric */,
|
||||
@@ -5177,6 +5244,7 @@
|
||||
4B055AB41FAE860F0060FFFF /* OricTAP.cpp in Sources */,
|
||||
4B055AB71FAE860F0060FFFF /* TZX.cpp in Sources */,
|
||||
4B2BF19123DCC6A200C3AD60 /* BD500.cpp in Sources */,
|
||||
4B051CA926781D6500CA44E8 /* StaticAnalyser.cpp in Sources */,
|
||||
4B055ADA1FAE9B460060FFFF /* 1770.cpp in Sources */,
|
||||
4B80CD77256CA16600176FCC /* 2MG.cpp in Sources */,
|
||||
4B0F1BE62602FF9D00B85C66 /* ZX8081.cpp in Sources */,
|
||||
@@ -5186,6 +5254,7 @@
|
||||
4B055AB61FAE860F0060FFFF /* TapeUEF.cpp in Sources */,
|
||||
4B055A9D1FAE85DA0060FFFF /* D64.cpp in Sources */,
|
||||
4B0ACC2B23775819008902D0 /* Video.cpp in Sources */,
|
||||
4B051CA32676F52200CA44E8 /* Enterprise.cpp in Sources */,
|
||||
4B055ABB1FAE86170060FFFF /* Oric.cpp in Sources */,
|
||||
4B12C0EE1FCFAD1A005BFD93 /* Keyboard.cpp in Sources */,
|
||||
4BCD634A22D6756400F567F1 /* MacintoshDoubleDensityDrive.cpp in Sources */,
|
||||
@@ -5214,6 +5283,7 @@
|
||||
4BB307BC235001C300457D33 /* 6850.cpp in Sources */,
|
||||
4B055AB31FAE860F0060FFFF /* CSW.cpp in Sources */,
|
||||
4B89451D201967B4007DE474 /* Disk.cpp in Sources */,
|
||||
4BFEA2F02682A7B900EBF94C /* Dave.cpp in Sources */,
|
||||
4BDACBED22FFA5D20045EF7E /* ncr5380.cpp in Sources */,
|
||||
4BC131772346DE9100E4FF3D /* StaticAnalyser.cpp in Sources */,
|
||||
4B055ACF1FAE9B030060FFFF /* SoundGenerator.cpp in Sources */,
|
||||
@@ -5230,7 +5300,7 @@
|
||||
4BB4BFBA22A4372F0069048D /* StaticAnalyser.cpp in Sources */,
|
||||
4B055AA21FAE85DA0060FFFF /* SSD.cpp in Sources */,
|
||||
4B2E86E325DC95150024F1E9 /* Joystick.cpp in Sources */,
|
||||
4BEBFB4E2002C4BF000708CC /* MSXDSK.cpp in Sources */,
|
||||
4BEBFB4E2002C4BF000708CC /* FAT12.cpp in Sources */,
|
||||
4B055ADD1FAE9B460060FFFF /* i8272.cpp in Sources */,
|
||||
4B055A9C1FAE85DA0060FFFF /* CPCDSK.cpp in Sources */,
|
||||
4B2BF19223DCC6A800C3AD60 /* STX.cpp in Sources */,
|
||||
@@ -5248,6 +5318,7 @@
|
||||
4BC131712346DE5000E4FF3D /* StaticAnalyser.cpp in Sources */,
|
||||
4B055ACA1FAE9AFB0060FFFF /* Vic20.cpp in Sources */,
|
||||
4BE21200253FC80900435408 /* StaticAnalyser.cpp in Sources */,
|
||||
4B051CB72680158600CA44E8 /* EXDos.cpp in Sources */,
|
||||
4B8318B222D3E53C006DB630 /* Video.cpp in Sources */,
|
||||
4B055ABC1FAE86170060FFFF /* ZX8081.cpp in Sources */,
|
||||
4B055AC91FAE9AFB0060FFFF /* Keyboard.cpp in Sources */,
|
||||
@@ -5292,6 +5363,7 @@
|
||||
4B055AAD1FAE85FD0060FFFF /* PCMTrack.cpp in Sources */,
|
||||
4BD67DD1209BF27B00AB2146 /* Encoder.cpp in Sources */,
|
||||
4BE2121A253FCE9C00435408 /* AppleIIgs.cpp in Sources */,
|
||||
4B051CAD26783E2000CA44E8 /* Nick.cpp in Sources */,
|
||||
4B89451F201967B4007DE474 /* Tape.cpp in Sources */,
|
||||
4B055AA81FAE85EF0060FFFF /* Shifter.cpp in Sources */,
|
||||
4BEDA3BC25B25563000C2DBD /* Decoder.cpp in Sources */,
|
||||
@@ -5338,6 +5410,7 @@
|
||||
4B051C912669C90B00CA44E8 /* ROMCatalogue.cpp in Sources */,
|
||||
4B055AB91FAE86170060FFFF /* Acorn.cpp in Sources */,
|
||||
4B302185208A550100773308 /* DiskII.cpp in Sources */,
|
||||
4B051CB1267C1CA200CA44E8 /* Keyboard.cpp in Sources */,
|
||||
4B0F1BB32602645900B85C66 /* StaticAnalyser.cpp in Sources */,
|
||||
4B055A931FAE85B50060FFFF /* BinaryDump.cpp in Sources */,
|
||||
4B89452D201967B4007DE474 /* Tape.cpp in Sources */,
|
||||
@@ -5416,7 +5489,7 @@
|
||||
4B3FE75E1F3CF68B00448EE4 /* CPM.cpp in Sources */,
|
||||
4B2BFDB21DAEF5FF001A68B8 /* Video.cpp in Sources */,
|
||||
4BEDA3BF25B25563000C2DBD /* Decoder.cpp in Sources */,
|
||||
4B051C95266EF50200CA44E8 /* AppleIIOptionsPanel.swift in Sources */,
|
||||
4B051C95266EF50200CA44E8 /* AppleIIController.swift in Sources */,
|
||||
4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */,
|
||||
4BE8EB6625C750B50040BC40 /* DAT.cpp in Sources */,
|
||||
4BBFFEE61F7B27F1005F3FEB /* TrackSerialiser.cpp in Sources */,
|
||||
@@ -5429,13 +5502,13 @@
|
||||
4BC890D3230F86020025A55A /* DirectAccessDevice.cpp in Sources */,
|
||||
4B7BA03723CEB86000B98D9E /* BD500.cpp in Sources */,
|
||||
4B38F3481F2EC11D00D9235D /* AmstradCPC.cpp in Sources */,
|
||||
4B8FE2221DA19FB20090D3CE /* MachinePanel.swift in Sources */,
|
||||
4B8FE2221DA19FB20090D3CE /* MachineController.swift in Sources */,
|
||||
4B4518A41F75FD1C00926311 /* OricMFMDSK.cpp in Sources */,
|
||||
4B4B1A3C200198CA00A0F866 /* KonamiSCC.cpp in Sources */,
|
||||
4BB0A65B2044FD3000FB3688 /* SN76489.cpp in Sources */,
|
||||
4B80CD6F2568A82C00176FCC /* DiskIIDrive.cpp in Sources */,
|
||||
4B894532201967B4007DE474 /* 6502.cpp in Sources */,
|
||||
4BDB61EC203285AE0048AF91 /* Atari2600OptionsPanel.swift in Sources */,
|
||||
4BDB61EC203285AE0048AF91 /* Atari2600OptionsController.swift in Sources */,
|
||||
4B2E86E225DC95150024F1E9 /* Joystick.cpp in Sources */,
|
||||
4BBB70A8202014E2002FE009 /* MultiProducer.cpp in Sources */,
|
||||
4B8805F71DCFF6C9003085B1 /* Commodore.cpp in Sources */,
|
||||
@@ -5461,6 +5534,7 @@
|
||||
4B7BA03023C2B19C00B98D9E /* Jasmin.cpp in Sources */,
|
||||
4B7136911F789C93008B8ED9 /* SegmentParser.cpp in Sources */,
|
||||
4BEDA3BA25B25563000C2DBD /* Decoder.cpp in Sources */,
|
||||
4BFEA2EF2682A7B900EBF94C /* Dave.cpp in Sources */,
|
||||
4B4518A21F75FD1C00926311 /* G64.cpp in Sources */,
|
||||
4B89452C201967B4007DE474 /* Tape.cpp in Sources */,
|
||||
4B448E811F1C45A00009ABD6 /* TZX.cpp in Sources */,
|
||||
@@ -5470,7 +5544,7 @@
|
||||
4B302184208A550100773308 /* DiskII.cpp in Sources */,
|
||||
4BEA52631DF339D7007E74F2 /* SoundGenerator.cpp in Sources */,
|
||||
4BD67DD0209BF27B00AB2146 /* Encoder.cpp in Sources */,
|
||||
4BAE495920328897004BE78E /* ZX8081OptionsPanel.swift in Sources */,
|
||||
4BAE495920328897004BE78E /* ZX8081Controller.swift in Sources */,
|
||||
4B89451A201967B4007DE474 /* ConfidenceSummary.cpp in Sources */,
|
||||
4BE0A3EE237BB170002AB46F /* ST.cpp in Sources */,
|
||||
4B54C0C51F8D91D90050900F /* Keyboard.cpp in Sources */,
|
||||
@@ -5492,11 +5566,13 @@
|
||||
4B12C0ED1FCFA98D005BFD93 /* Keyboard.cpp in Sources */,
|
||||
4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */,
|
||||
4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */,
|
||||
4B051CA22676F52200CA44E8 /* Enterprise.cpp in Sources */,
|
||||
4B7F1897215486A200388727 /* StaticAnalyser.cpp in Sources */,
|
||||
4B47F6C5241C87A100ED06F7 /* Struct.cpp in Sources */,
|
||||
4B5FADBA1DE3151600AEC565 /* FileHolder.cpp in Sources */,
|
||||
4B643F3A1D77AD1900D431D6 /* CSStaticAnalyser.mm in Sources */,
|
||||
4B622AE5222E0AD5008B59F2 /* DisplayMetrics.cpp in Sources */,
|
||||
4B051CB0267C1CA200CA44E8 /* Keyboard.cpp in Sources */,
|
||||
4B1497881EE4A1DA00CE2596 /* ZX80O81P.cpp in Sources */,
|
||||
4B894520201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
4BB4BFAD22A33DE50069048D /* DriveSpeedAccumulator.cpp in Sources */,
|
||||
@@ -5505,11 +5581,13 @@
|
||||
4B74CF812312FA9C00500CE8 /* HFV.cpp in Sources */,
|
||||
4B17B58B20A8A9D9007CCA8F /* StringSerialiser.cpp in Sources */,
|
||||
4B2E2D9D1C3A070400138695 /* Electron.cpp in Sources */,
|
||||
4B051CA826781D6500CA44E8 /* StaticAnalyser.cpp in Sources */,
|
||||
4B3940E71DA83C8300427841 /* AsyncTaskQueue.cpp in Sources */,
|
||||
4B0E04FA1FC9FA3100F43484 /* 9918.cpp in Sources */,
|
||||
4B69FB3D1C4D908A00B5F0AA /* Tape.cpp in Sources */,
|
||||
4B4518841F75E91A00926311 /* UnformattedTrack.cpp in Sources */,
|
||||
4B65086022F4CF8D009C1100 /* Keyboard.cpp in Sources */,
|
||||
4B47770B268FBE4D005C2340 /* FAT.cpp in Sources */,
|
||||
4B894528201967B4007DE474 /* Disk.cpp in Sources */,
|
||||
4B2E86CF25D8D8C70024F1E9 /* Keyboard.cpp in Sources */,
|
||||
4BBB70A4202011C2002FE009 /* MultiMediaTarget.cpp in Sources */,
|
||||
@@ -5538,7 +5616,7 @@
|
||||
4B894536201967B4007DE474 /* Z80.cpp in Sources */,
|
||||
4BCA6CC81D9DD9F000C2D7B2 /* CommodoreROM.cpp in Sources */,
|
||||
4BC1317A2346DF2B00E4FF3D /* MSA.cpp in Sources */,
|
||||
4BEBFB4D2002C4BF000708CC /* MSXDSK.cpp in Sources */,
|
||||
4BEBFB4D2002C4BF000708CC /* FAT12.cpp in Sources */,
|
||||
4BBFBB6C1EE8401E00C01E7A /* ZX8081.cpp in Sources */,
|
||||
4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */,
|
||||
4B8DD3862634D37E00B3C866 /* SNA.cpp in Sources */,
|
||||
@@ -5549,9 +5627,11 @@
|
||||
4BFDD78C1F7F2DB4008579B9 /* ImplicitSectors.cpp in Sources */,
|
||||
4B894526201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
4BEE0A6F1D72496600532C7B /* Cartridge.cpp in Sources */,
|
||||
4B051CB62680158600CA44E8 /* EXDos.cpp in Sources */,
|
||||
4B8805FB1DCFF807003085B1 /* Oric.cpp in Sources */,
|
||||
4B6ED2F0208E2F8A0047B343 /* WOZ.cpp in Sources */,
|
||||
4B15A9FC208249BB005E6C8D /* StaticAnalyser.cpp in Sources */,
|
||||
4B051CAC26783E2000CA44E8 /* Nick.cpp in Sources */,
|
||||
4B5FADC01DE3BF2B00AEC565 /* Microdisc.cpp in Sources */,
|
||||
4B0F1BDA2602FF9800B85C66 /* Video.cpp in Sources */,
|
||||
4B051C922669C90B00CA44E8 /* ROMCatalogue.cpp in Sources */,
|
||||
@@ -5684,7 +5764,7 @@
|
||||
4B3BA0CF1D318B44005DD7A7 /* MOS6522Bridge.mm in Sources */,
|
||||
4B778F6023A5F3460000D260 /* Disk.cpp in Sources */,
|
||||
4B778F5C23A5F3070000D260 /* MSX.cpp in Sources */,
|
||||
4B778F0323A5EBB00000D260 /* MSXDSK.cpp in Sources */,
|
||||
4B778F0323A5EBB00000D260 /* FAT12.cpp in Sources */,
|
||||
4B778F4023A5F1910000D260 /* z8530.cpp in Sources */,
|
||||
4B778EFD23A5EB8E0000D260 /* AppleDSK.cpp in Sources */,
|
||||
4B778EFB23A5EB7E0000D260 /* HFE.cpp in Sources */,
|
||||
@@ -5692,10 +5772,12 @@
|
||||
4BFCA12B1ECBE7C400AC40C1 /* ZexallTests.swift in Sources */,
|
||||
4B778F2223A5EDDD0000D260 /* PulseQueuedTape.cpp in Sources */,
|
||||
4B778EF123A5D6B50000D260 /* 9918.cpp in Sources */,
|
||||
4B051CB3267D3FF800CA44E8 /* EnterpriseNickTests.mm in Sources */,
|
||||
4B9D0C4D22C7DA1A00DE1AD3 /* 68000ControlFlowTests.mm in Sources */,
|
||||
4BB2A9AF1E13367E001A5C23 /* CRCTests.mm in Sources */,
|
||||
4B778F5623A5F2AF0000D260 /* CPM.cpp in Sources */,
|
||||
4B778F1C23A5ED3F0000D260 /* TimedEventLoop.cpp in Sources */,
|
||||
4B47770D26900685005C2340 /* EnterpriseDaveTests.mm in Sources */,
|
||||
4B3BA0D01D318B44005DD7A7 /* MOS6532Bridge.mm in Sources */,
|
||||
4B778F3823A5F11C0000D260 /* SegmentParser.cpp in Sources */,
|
||||
4B778F0723A5EC150000D260 /* CommodoreTAP.cpp in Sources */,
|
||||
|
||||
@@ -85,8 +85,12 @@
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "--new=amstradcpc"
|
||||
isEnabled = "NO">
|
||||
argument = "--new=enterprise"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "--basic-version=any"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/ColecoVision/Galaxian (1983)(Atari).col""
|
||||
@@ -126,15 +130,15 @@
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "--model=mac512k"
|
||||
isEnabled = "YES">
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "--new=macintosh"
|
||||
isEnabled = "YES">
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "--use-square-pixels"
|
||||
isEnabled = "YES">
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
</CommandLineArguments>
|
||||
</LaunchAction>
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
debugDocumentVersioning = "YES"
|
||||
migratedStopOnEveryIssue = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUShaderValidationMode = "2"
|
||||
allowLocationSimulation = "NO">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
|
||||
@@ -1,113 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14113" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14113"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
<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="activityPanel" destination="ZW7-Bw-4RP" id="GRG-Q6-RQU"/>
|
||||
<outlet property="activityView" destination="tpZ-0B-QQu" id="afo-Oq-Nyl"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Activity" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="ZW7-Bw-4RP" customClass="NSPanel">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" nonactivatingPanel="YES" HUD="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="300" y="76" width="200" height="131"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<view key="contentView" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="131"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<levelIndicator verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ySY-ir-hzb" userLabel="First indicator">
|
||||
<rect key="frame" x="20" y="95" width="17" height="16"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="ySY-ir-hzb" secondAttribute="height" multiplier="1:1" id="UX0-hT-7Td"/>
|
||||
</constraints>
|
||||
<levelIndicatorCell key="cell" alignment="left" maxValue="1" warningValue="2" criticalValue="2" levelIndicatorStyle="continuousCapacity" id="DhQ-Di-tRT"/>
|
||||
</levelIndicator>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Tah-UQ-vdf">
|
||||
<rect key="frame" x="44" y="94" width="59" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Activity 1" id="a5P-Ci-RzC">
|
||||
<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>
|
||||
<levelIndicator verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ncQ-wN-C61" userLabel="Second indicator">
|
||||
<rect key="frame" x="20" y="70" width="17" height="16"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="ncQ-wN-C61" secondAttribute="height" multiplier="1:1" id="176-v3-mVW"/>
|
||||
</constraints>
|
||||
<levelIndicatorCell key="cell" alignment="left" maxValue="1" warningValue="2" criticalValue="2" levelIndicatorStyle="continuousCapacity" id="jlb-bk-FPd"/>
|
||||
</levelIndicator>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="14O-Lq-Npx">
|
||||
<rect key="frame" x="44" y="69" width="61" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Activity 2" id="NE1-CO-pGI">
|
||||
<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>
|
||||
<levelIndicator verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0rV-Th-Zwt" userLabel="Third indicator">
|
||||
<rect key="frame" x="20" y="45" width="17" height="16"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="0rV-Th-Zwt" secondAttribute="height" multiplier="1:1" id="Ai8-b3-Nn5"/>
|
||||
</constraints>
|
||||
<levelIndicatorCell key="cell" alignment="left" maxValue="1" warningValue="2" criticalValue="2" levelIndicatorStyle="continuousCapacity" id="CJy-Jn-eCL"/>
|
||||
</levelIndicator>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Acy-tT-OFH">
|
||||
<rect key="frame" x="44" y="44" width="61" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Activity 3" id="FSR-y6-7WE">
|
||||
<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>
|
||||
<levelIndicator verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bvH-EJ-TYb" userLabel="Fourth indicator">
|
||||
<rect key="frame" x="20" y="20" width="17" height="16"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="bvH-EJ-TYb" secondAttribute="height" multiplier="1:1" id="cKc-q1-2Q4"/>
|
||||
</constraints>
|
||||
<levelIndicatorCell key="cell" alignment="left" maxValue="1" warningValue="2" criticalValue="2" levelIndicatorStyle="continuousCapacity" id="eoN-hl-30l"/>
|
||||
</levelIndicator>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="R0g-Oa-VB5">
|
||||
<rect key="frame" x="44" y="19" width="62" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Activity 4" id="aGr-cd-jC0">
|
||||
<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="14O-Lq-Npx" firstAttribute="centerY" secondItem="ncQ-wN-C61" secondAttribute="centerY" id="0Ht-U2-sPg"/>
|
||||
<constraint firstItem="bvH-EJ-TYb" firstAttribute="top" secondItem="0rV-Th-Zwt" secondAttribute="bottom" constant="9" id="0xw-qA-6vP"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="14O-Lq-Npx" secondAttribute="trailing" constant="20" id="5eo-XI-a3W"/>
|
||||
<constraint firstItem="Tah-UQ-vdf" firstAttribute="centerY" secondItem="ySY-ir-hzb" secondAttribute="centerY" id="6Hn-ts-mTi"/>
|
||||
<constraint firstItem="R0g-Oa-VB5" firstAttribute="leading" secondItem="bvH-EJ-TYb" secondAttribute="trailing" constant="10" id="Dgy-JI-nA1"/>
|
||||
<constraint firstItem="R0g-Oa-VB5" firstAttribute="centerY" secondItem="bvH-EJ-TYb" secondAttribute="centerY" id="Gfq-mB-Y1z"/>
|
||||
<constraint firstItem="Acy-tT-OFH" firstAttribute="centerY" secondItem="0rV-Th-Zwt" secondAttribute="centerY" id="ImF-rK-oOr"/>
|
||||
<constraint firstItem="Acy-tT-OFH" firstAttribute="leading" secondItem="0rV-Th-Zwt" secondAttribute="trailing" constant="10" id="JSU-pZ-l9Q"/>
|
||||
<constraint firstItem="ySY-ir-hzb" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="KMh-EO-rxE"/>
|
||||
<constraint firstItem="0rV-Th-Zwt" firstAttribute="top" secondItem="ncQ-wN-C61" secondAttribute="bottom" constant="9" id="Q2g-yM-nlJ"/>
|
||||
<constraint firstItem="ncQ-wN-C61" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="QUI-Hc-Bcl"/>
|
||||
<constraint firstItem="0rV-Th-Zwt" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="bKh-4L-mqj"/>
|
||||
<constraint firstItem="bvH-EJ-TYb" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="cPA-Ls-fLj"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Tah-UQ-vdf" secondAttribute="trailing" constant="20" id="igX-7U-TeE"/>
|
||||
<constraint firstItem="14O-Lq-Npx" firstAttribute="leading" secondItem="ncQ-wN-C61" secondAttribute="trailing" constant="10" id="jjP-qH-Pqg"/>
|
||||
<constraint firstItem="Tah-UQ-vdf" firstAttribute="leading" secondItem="ySY-ir-hzb" secondAttribute="trailing" constant="10" id="lux-Nz-K7E"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Acy-tT-OFH" secondAttribute="trailing" constant="20" id="mEe-VT-dNr"/>
|
||||
<constraint firstItem="ncQ-wN-C61" firstAttribute="top" secondItem="ySY-ir-hzb" secondAttribute="bottom" constant="9" id="mSc-jj-amw"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="R0g-Oa-VB5" secondAttribute="trailing" constant="20" id="sR8-Ph-suC"/>
|
||||
<constraint firstItem="ySY-ir-hzb" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="20" id="wbj-48-DYq"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<point key="canvasLocation" x="84" y="115"/>
|
||||
</window>
|
||||
<visualEffectView hidden="YES" wantsLayer="YES" appearanceType="vibrantDark" blendingMode="withinWindow" material="HUDWindow" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="131"/>
|
||||
<subviews>
|
||||
<levelIndicator verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ySY-ir-hzb" userLabel="First indicator">
|
||||
<rect key="frame" x="8" y="105" width="16" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="ySY-ir-hzb" secondAttribute="height" multiplier="1:1" id="UX0-hT-7Td"/>
|
||||
</constraints>
|
||||
<levelIndicatorCell key="cell" alignment="left" maxValue="1" warningValue="2" criticalValue="2" levelIndicatorStyle="continuousCapacity" id="DhQ-Di-tRT"/>
|
||||
</levelIndicator>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Tah-UQ-vdf">
|
||||
<rect key="frame" x="30" y="107" width="59" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Activity 1" id="a5P-Ci-RzC">
|
||||
<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>
|
||||
<levelIndicator verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ncQ-wN-C61" userLabel="Second indicator">
|
||||
<rect key="frame" x="8" y="81" width="16" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="ncQ-wN-C61" secondAttribute="height" multiplier="1:1" id="176-v3-mVW"/>
|
||||
</constraints>
|
||||
<levelIndicatorCell key="cell" alignment="left" maxValue="1" warningValue="2" criticalValue="2" levelIndicatorStyle="continuousCapacity" id="jlb-bk-FPd"/>
|
||||
</levelIndicator>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="14O-Lq-Npx">
|
||||
<rect key="frame" x="30" y="83" width="61" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Activity 2" id="NE1-CO-pGI">
|
||||
<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>
|
||||
<levelIndicator verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0rV-Th-Zwt" userLabel="Third indicator">
|
||||
<rect key="frame" x="8" y="57" width="16" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="0rV-Th-Zwt" secondAttribute="height" multiplier="1:1" id="Ai8-b3-Nn5"/>
|
||||
</constraints>
|
||||
<levelIndicatorCell key="cell" alignment="left" maxValue="1" warningValue="2" criticalValue="2" levelIndicatorStyle="continuousCapacity" id="CJy-Jn-eCL"/>
|
||||
</levelIndicator>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Acy-tT-OFH">
|
||||
<rect key="frame" x="30" y="59" width="61" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Activity 3" id="FSR-y6-7WE">
|
||||
<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>
|
||||
<levelIndicator verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bvH-EJ-TYb" userLabel="Fourth indicator">
|
||||
<rect key="frame" x="8" y="33" width="16" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="bvH-EJ-TYb" secondAttribute="height" multiplier="1:1" id="cKc-q1-2Q4"/>
|
||||
</constraints>
|
||||
<levelIndicatorCell key="cell" alignment="left" maxValue="1" warningValue="2" criticalValue="2" levelIndicatorStyle="continuousCapacity" id="eoN-hl-30l"/>
|
||||
</levelIndicator>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="R0g-Oa-VB5">
|
||||
<rect key="frame" x="30" y="35" width="62" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Activity 4" id="aGr-cd-jC0">
|
||||
<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="14O-Lq-Npx" firstAttribute="centerY" secondItem="ncQ-wN-C61" secondAttribute="centerY" id="0Ht-U2-sPg"/>
|
||||
<constraint firstItem="bvH-EJ-TYb" firstAttribute="top" secondItem="0rV-Th-Zwt" secondAttribute="bottom" constant="8" symbolic="YES" id="0xw-qA-6vP"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="14O-Lq-Npx" secondAttribute="trailing" constant="8" id="5eo-XI-a3W"/>
|
||||
<constraint firstItem="Tah-UQ-vdf" firstAttribute="centerY" secondItem="ySY-ir-hzb" secondAttribute="centerY" id="6Hn-ts-mTi"/>
|
||||
<constraint firstItem="R0g-Oa-VB5" firstAttribute="leading" secondItem="bvH-EJ-TYb" secondAttribute="trailing" constant="8" symbolic="YES" id="Dgy-JI-nA1"/>
|
||||
<constraint firstItem="R0g-Oa-VB5" firstAttribute="centerY" secondItem="bvH-EJ-TYb" secondAttribute="centerY" id="Gfq-mB-Y1z"/>
|
||||
<constraint firstItem="Acy-tT-OFH" firstAttribute="centerY" secondItem="0rV-Th-Zwt" secondAttribute="centerY" id="ImF-rK-oOr"/>
|
||||
<constraint firstItem="Acy-tT-OFH" firstAttribute="leading" secondItem="0rV-Th-Zwt" secondAttribute="trailing" constant="8" symbolic="YES" id="JSU-pZ-l9Q"/>
|
||||
<constraint firstItem="ySY-ir-hzb" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="8" id="KMh-EO-rxE"/>
|
||||
<constraint firstItem="0rV-Th-Zwt" firstAttribute="top" secondItem="ncQ-wN-C61" secondAttribute="bottom" constant="8" symbolic="YES" id="Q2g-yM-nlJ"/>
|
||||
<constraint firstItem="ncQ-wN-C61" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="8" id="QUI-Hc-Bcl"/>
|
||||
<constraint firstItem="0rV-Th-Zwt" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="8" id="bKh-4L-mqj"/>
|
||||
<constraint firstItem="bvH-EJ-TYb" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="8" id="cPA-Ls-fLj"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Tah-UQ-vdf" secondAttribute="trailing" constant="8" id="igX-7U-TeE"/>
|
||||
<constraint firstItem="14O-Lq-Npx" firstAttribute="leading" secondItem="ncQ-wN-C61" secondAttribute="trailing" constant="8" symbolic="YES" id="jjP-qH-Pqg"/>
|
||||
<constraint firstItem="Tah-UQ-vdf" firstAttribute="leading" secondItem="ySY-ir-hzb" secondAttribute="trailing" constant="8" symbolic="YES" id="lux-Nz-K7E"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Acy-tT-OFH" secondAttribute="trailing" constant="8" id="mEe-VT-dNr"/>
|
||||
<constraint firstItem="ncQ-wN-C61" firstAttribute="top" secondItem="ySY-ir-hzb" secondAttribute="bottom" constant="8" symbolic="YES" id="mSc-jj-amw"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="R0g-Oa-VB5" secondAttribute="trailing" constant="8" id="sR8-Ph-suC"/>
|
||||
<constraint firstItem="ySY-ir-hzb" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="8" id="wbj-48-DYq"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="57" y="80"/>
|
||||
</visualEffectView>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@@ -8,62 +8,58 @@
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="MachineDocument" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="optionsPanel" destination="ZW7-Bw-4RP" id="JpE-wG-zRR"/>
|
||||
<outlet property="optionsController" destination="9AQ-Iv-Pbm" id="fMh-25-smM"/>
|
||||
<outlet property="optionsView" destination="tpZ-0B-QQu" id="n0E-oR-8fl"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Options" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="ZW7-Bw-4RP" customClass="AppleIIOptionsPanel" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" nonactivatingPanel="YES" HUD="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="80" y="150" width="200" height="159"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1440"/>
|
||||
<view key="contentView" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="84"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kDb-7g-cVx">
|
||||
<rect key="frame" x="18" y="47" width="162" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Use Square Pixels" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="h9q-Wb-em8">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionDidChange:" target="ZW7-Bw-4RP" id="pNS-aK-0no"/>
|
||||
</connections>
|
||||
</button>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ex3-VM-58z">
|
||||
<rect key="frame" x="17" y="16" width="167" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Colour" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="1" imageScaling="proportionallyDown" inset="2" selectedItem="gOu-dv-tre" id="u3N-Je-c2L">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="BUS-Pl-jBm">
|
||||
<items>
|
||||
<menuItem title="Colour" state="on" tag="1" id="gOu-dv-tre"/>
|
||||
<menuItem title="Monochrome" tag="3" id="qhQ-ab-jRo"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<action selector="setDisplayType:" target="ZW7-Bw-4RP" id="f7A-2O-wR8"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="ex3-VM-58z" secondAttribute="bottom" constant="20" symbolic="YES" id="4ZS-q5-TJL"/>
|
||||
<constraint firstItem="ex3-VM-58z" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="8Pj-Ns-TrJ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="kDb-7g-cVx" secondAttribute="trailing" constant="20" symbolic="YES" id="KHa-of-eY7"/>
|
||||
<constraint firstItem="kDb-7g-cVx" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" symbolic="YES" id="OcZ-Xa-394"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ex3-VM-58z" secondAttribute="trailing" constant="20" id="QWA-lY-ugz"/>
|
||||
<constraint firstItem="ex3-VM-58z" firstAttribute="top" secondItem="kDb-7g-cVx" secondAttribute="bottom" constant="8" id="jDW-N8-c4V"/>
|
||||
<constraint firstItem="kDb-7g-cVx" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="20" symbolic="YES" id="wdj-PF-zxO"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<visualEffectView hidden="YES" wantsLayer="YES" appearanceType="vibrantDark" blendingMode="withinWindow" material="HUDWindow" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="68"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kDb-7g-cVx">
|
||||
<rect key="frame" x="10" y="39" width="178" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Use Square Pixels" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="h9q-Wb-em8">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionDidChange:" target="9AQ-Iv-Pbm" id="5ef-un-Yck"/>
|
||||
</connections>
|
||||
</button>
|
||||
<popUpButton wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ex3-VM-58z">
|
||||
<rect key="frame" x="9" y="8" width="183" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Colour" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="1" imageScaling="proportionallyDown" inset="2" selectedItem="gOu-dv-tre" id="u3N-Je-c2L">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="BUS-Pl-jBm">
|
||||
<items>
|
||||
<menuItem title="Colour" state="on" tag="1" id="gOu-dv-tre"/>
|
||||
<menuItem title="Monochrome" tag="3" id="qhQ-ab-jRo"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<action selector="setDisplayType:" target="9AQ-Iv-Pbm" id="Bad-uY-0fe"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="ex3-VM-58z" secondAttribute="bottom" constant="12" id="4ZS-q5-TJL"/>
|
||||
<constraint firstItem="ex3-VM-58z" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="12" id="8Pj-Ns-TrJ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="kDb-7g-cVx" secondAttribute="trailing" constant="12" id="KHa-of-eY7"/>
|
||||
<constraint firstItem="kDb-7g-cVx" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="12" id="OcZ-Xa-394"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ex3-VM-58z" secondAttribute="trailing" constant="12" id="QWA-lY-ugz"/>
|
||||
<constraint firstItem="ex3-VM-58z" firstAttribute="top" secondItem="kDb-7g-cVx" secondAttribute="bottom" constant="8" id="jDW-N8-c4V"/>
|
||||
<constraint firstItem="kDb-7g-cVx" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="12" id="wdj-PF-zxO"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="-311" y="120"/>
|
||||
</visualEffectView>
|
||||
<customObject id="9AQ-Iv-Pbm" customClass="AppleIIController" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="displayTypeButton" destination="ex3-VM-58z" id="lmZ-aN-lcj"/>
|
||||
<outlet property="squarePixelButton" destination="kDb-7g-cVx" id="zbx-o8-7yC"/>
|
||||
<outlet property="displayTypeButton" destination="ex3-VM-58z" id="bmb-7c-ZF7"/>
|
||||
<outlet property="squarePixelButton" destination="kDb-7g-cVx" id="iGT-6U-vTO"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-161" y="104.5"/>
|
||||
</window>
|
||||
</customObject>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@@ -8,97 +8,95 @@
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="MachineDocument" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="optionsPanel" destination="gsl-7V-TTU" id="BEE-05-h0B"/>
|
||||
<outlet property="optionsController" destination="rEM-g1-brS" id="xZh-zY-yuv"/>
|
||||
<outlet property="optionsView" destination="fX1-EX-wGf" id="dPS-F9-xmL"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Options" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="gsl-7V-TTU" customClass="Atari2600OptionsPanel" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" nonactivatingPanel="YES" HUD="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="80" y="150" width="200" height="121"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1440"/>
|
||||
<view key="contentView" id="aQh-Pm-DEo">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="121"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rQO-uD-fwn">
|
||||
<rect key="frame" x="13" y="74" width="88" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Reset" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="l3H-0m-aK0">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionWasPressed:" target="gsl-7V-TTU" id="wbx-SP-OZc"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="3qw-C1-NYW">
|
||||
<rect key="frame" x="18" y="58" width="162" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Black and White" bezelStyle="regularSquare" imagePosition="left" inset="2" id="UP7-mf-IKo">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionDidChange:" target="gsl-7V-TTU" id="s5e-66-aY1"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="Xbc-cw-Sc2">
|
||||
<rect key="frame" x="18" y="36" width="162" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Left Player Difficulty" bezelStyle="regularSquare" imagePosition="left" inset="2" id="wlJ-8s-PEh">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionDidChange:" target="gsl-7V-TTU" id="PbG-zF-y0W"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="kPV-Tm-TTc">
|
||||
<rect key="frame" x="18" y="14" width="162" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Right Player Difficulty" bezelStyle="regularSquare" imagePosition="left" inset="2" id="F05-cA-66S">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionDidChange:" target="gsl-7V-TTU" id="XMR-tK-HN5"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nt7-8K-xY9">
|
||||
<rect key="frame" x="99" y="74" width="88" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Select" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="8Na-Z1-EXS">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionWasPressed:" target="gsl-7V-TTU" id="db2-Bu-6h9"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="3qw-C1-NYW" firstAttribute="leading" secondItem="aQh-Pm-DEo" secondAttribute="leading" constant="20" id="1Ri-ZO-GJy"/>
|
||||
<constraint firstItem="nt7-8K-xY9" firstAttribute="leading" secondItem="rQO-uD-fwn" secondAttribute="trailing" constant="12" id="46p-Z3-kgW"/>
|
||||
<constraint firstItem="nt7-8K-xY9" firstAttribute="top" secondItem="aQh-Pm-DEo" secondAttribute="top" constant="20" id="6Uc-12-11y"/>
|
||||
<constraint firstItem="Xbc-cw-Sc2" firstAttribute="leading" secondItem="aQh-Pm-DEo" secondAttribute="leading" constant="20" id="7es-iv-JOh"/>
|
||||
<constraint firstItem="kPV-Tm-TTc" firstAttribute="top" secondItem="Xbc-cw-Sc2" secondAttribute="bottom" constant="6" id="Env-nl-M2e"/>
|
||||
<constraint firstAttribute="trailing" secondItem="kPV-Tm-TTc" secondAttribute="trailing" constant="20" id="Fim-Ej-8Ux"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Xbc-cw-Sc2" secondAttribute="trailing" constant="20" id="HkS-6c-WZm"/>
|
||||
<constraint firstItem="3qw-C1-NYW" firstAttribute="top" secondItem="nt7-8K-xY9" secondAttribute="bottom" constant="6" id="Hxq-Pm-o4G"/>
|
||||
<constraint firstAttribute="trailing" secondItem="nt7-8K-xY9" secondAttribute="trailing" constant="20" id="JRO-de-WQp"/>
|
||||
<constraint firstItem="rQO-uD-fwn" firstAttribute="top" secondItem="aQh-Pm-DEo" secondAttribute="top" constant="20" id="N3p-aY-2Nx"/>
|
||||
<constraint firstItem="nt7-8K-xY9" firstAttribute="width" secondItem="rQO-uD-fwn" secondAttribute="width" id="NOc-hJ-8Mm"/>
|
||||
<constraint firstItem="Xbc-cw-Sc2" firstAttribute="top" secondItem="3qw-C1-NYW" secondAttribute="bottom" constant="6" id="ORX-bF-2WS"/>
|
||||
<constraint firstItem="kPV-Tm-TTc" firstAttribute="leading" secondItem="aQh-Pm-DEo" secondAttribute="leading" constant="20" id="x8p-Hm-xeu"/>
|
||||
<constraint firstItem="rQO-uD-fwn" firstAttribute="leading" secondItem="aQh-Pm-DEo" secondAttribute="leading" constant="20" id="xhD-iY-vt2"/>
|
||||
<constraint firstAttribute="trailing" secondItem="3qw-C1-NYW" secondAttribute="trailing" constant="20" id="yff-e9-OBY"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<visualEffectView hidden="YES" wantsLayer="YES" appearanceType="vibrantDark" blendingMode="withinWindow" material="HUDWindow" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="fX1-EX-wGf">
|
||||
<rect key="frame" x="0.0" y="0.0" width="202" height="112"/>
|
||||
<subviews>
|
||||
<button wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="pzn-mL-BPh">
|
||||
<rect key="frame" x="5" y="73" width="97" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Reset" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="W9s-t2-TJ5">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionWasPressed:" target="rEM-g1-brS" id="ZHe-AL-yL6"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="nEt-YK-aWs">
|
||||
<rect key="frame" x="10" y="33" width="180" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Left Player Difficulty" bezelStyle="regularSquare" imagePosition="left" inset="2" id="YOY-n5-F4C">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionDidChange:" target="rEM-g1-brS" id="BNC-7F-wGh"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="pDu-eg-6n6">
|
||||
<rect key="frame" x="10" y="11" width="180" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Right Player Difficulty" bezelStyle="regularSquare" imagePosition="left" inset="2" id="Q2e-Fa-VyK">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionDidChange:" target="rEM-g1-brS" id="R7C-ej-dZT"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YqD-w8-fXK">
|
||||
<rect key="frame" x="100" y="73" width="97" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Select" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="0DC-Xk-VFt">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionWasPressed:" target="rEM-g1-brS" id="Bhc-5F-4Vj"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="251" verticalCompressionResistancePriority="751" translatesAutoresizingMaskIntoConstraints="NO" id="YZK-m7-ihU">
|
||||
<rect key="frame" x="10" y="55" width="180" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Black and White" bezelStyle="regularSquare" imagePosition="left" inset="2" id="IxG-1J-fdG">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optionDidChange:" target="rEM-g1-brS" id="4cx-8C-XGe"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="nEt-YK-aWs" firstAttribute="leading" secondItem="fX1-EX-wGf" secondAttribute="leading" constant="12" id="20c-09-a5v"/>
|
||||
<constraint firstAttribute="bottom" secondItem="pDu-eg-6n6" secondAttribute="bottom" constant="12" id="8QS-y2-cgI"/>
|
||||
<constraint firstItem="pDu-eg-6n6" firstAttribute="leading" secondItem="fX1-EX-wGf" secondAttribute="leading" constant="12" id="Dee-tQ-00F"/>
|
||||
<constraint firstAttribute="trailing" secondItem="pDu-eg-6n6" secondAttribute="trailing" constant="12" id="IWs-rY-q36"/>
|
||||
<constraint firstItem="pDu-eg-6n6" firstAttribute="top" secondItem="nEt-YK-aWs" secondAttribute="bottom" constant="6" symbolic="YES" id="JSd-1z-mM4"/>
|
||||
<constraint firstAttribute="trailing" secondItem="nEt-YK-aWs" secondAttribute="trailing" constant="12" id="N00-Kz-j5a"/>
|
||||
<constraint firstAttribute="trailing" secondItem="YqD-w8-fXK" secondAttribute="trailing" constant="12" id="RgG-Tb-nuK"/>
|
||||
<constraint firstItem="pzn-mL-BPh" firstAttribute="leading" secondItem="fX1-EX-wGf" secondAttribute="leading" constant="12" id="Yxt-HC-m81"/>
|
||||
<constraint firstItem="YZK-m7-ihU" firstAttribute="leading" secondItem="fX1-EX-wGf" secondAttribute="leading" constant="12" id="ZTU-hR-Diu"/>
|
||||
<constraint firstItem="YqD-w8-fXK" firstAttribute="top" secondItem="pzn-mL-BPh" secondAttribute="top" id="bXS-W9-gSe"/>
|
||||
<constraint firstItem="YqD-w8-fXK" firstAttribute="leading" secondItem="pzn-mL-BPh" secondAttribute="trailing" constant="12" symbolic="YES" id="bnf-6C-Sld"/>
|
||||
<constraint firstItem="nEt-YK-aWs" firstAttribute="top" secondItem="YZK-m7-ihU" secondAttribute="bottom" constant="6" symbolic="YES" id="nFp-NE-u5J"/>
|
||||
<constraint firstItem="YqD-w8-fXK" firstAttribute="width" secondItem="pzn-mL-BPh" secondAttribute="width" id="sqT-6s-tFr"/>
|
||||
<constraint firstAttribute="trailing" secondItem="YZK-m7-ihU" secondAttribute="trailing" constant="12" id="x5C-Rx-M6l"/>
|
||||
<constraint firstItem="YqD-w8-fXK" firstAttribute="bottom" secondItem="pzn-mL-BPh" secondAttribute="bottom" id="xcM-in-P3E"/>
|
||||
<constraint firstItem="YZK-m7-ihU" firstAttribute="top" secondItem="pzn-mL-BPh" secondAttribute="bottom" constant="8" id="yJE-zt-BYM"/>
|
||||
<constraint firstItem="pzn-mL-BPh" firstAttribute="top" secondItem="fX1-EX-wGf" secondAttribute="top" constant="12" id="zJ3-Ii-K5M"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="139" y="230"/>
|
||||
</visualEffectView>
|
||||
<customObject id="rEM-g1-brS" customClass="Atari2600OptionsController" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="colourButton" destination="3qw-C1-NYW" id="5HZ-fq-XtP"/>
|
||||
<outlet property="leftPlayerDifficultyButton" destination="Xbc-cw-Sc2" id="OfB-Hr-fDC"/>
|
||||
<outlet property="resetButton" destination="rQO-uD-fwn" id="XsE-tH-9oS"/>
|
||||
<outlet property="rightPlayerDifficultyButton" destination="kPV-Tm-TTc" id="BGU-Hi-AZl"/>
|
||||
<outlet property="selectButton" destination="nt7-8K-xY9" id="AF6-Qk-HZN"/>
|
||||
<outlet property="colourButton" destination="YZK-m7-ihU" id="9AM-ZO-ck4"/>
|
||||
<outlet property="leftPlayerDifficultyButton" destination="nEt-YK-aWs" id="wm4-PF-Yni"/>
|
||||
<outlet property="resetButton" destination="pzn-mL-BPh" id="6TY-c7-uRd"/>
|
||||
<outlet property="rightPlayerDifficultyButton" destination="pDu-eg-6n6" id="TTh-ls-InF"/>
|
||||
<outlet property="selectButton" destination="YqD-w8-fXK" id="NUa-y2-gCe"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="157" y="12.5"/>
|
||||
</window>
|
||||
</customObject>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@@ -1,56 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14113" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14113"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
<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="optionsPanel" destination="ZW7-Bw-4RP" id="JpE-wG-zRR"/>
|
||||
<outlet property="optionsController" destination="MXS-dG-Doo" id="zwz-gg-WjA"/>
|
||||
<outlet property="optionsView" destination="tpZ-0B-QQu" id="xhc-MP-y9X"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Options" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="ZW7-Bw-4RP" customClass="MachinePanel" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" nonactivatingPanel="YES" HUD="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="80" y="150" width="200" height="61"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<view key="contentView" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="61"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rh8-km-57n">
|
||||
<rect key="frame" x="18" y="17" width="165" height="26"/>
|
||||
<popUpButtonCell key="cell" type="push" title="RGB Monitor" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="tJM-kX-gaK" id="8SX-c5-ud1">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="L06-TO-EF0">
|
||||
<items>
|
||||
<menuItem title="RGB Monitor" state="on" id="tJM-kX-gaK"/>
|
||||
<menuItem title="S-Video" tag="2" id="Mtc-Ht-iY8"/>
|
||||
<menuItem title="Television" tag="1" id="fFm-fS-rWG"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<action selector="setDisplayType:" target="ZW7-Bw-4RP" id="PAH-CZ-zlk"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="20" id="B6L-VS-2cN"/>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="VRo-6R-IKd"/>
|
||||
<constraint firstAttribute="bottom" secondItem="rh8-km-57n" secondAttribute="bottom" constant="20" id="jHA-lf-e7V"/>
|
||||
<constraint firstAttribute="trailing" secondItem="rh8-km-57n" secondAttribute="trailing" constant="20" id="urO-Ac-aqK"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<visualEffectView hidden="YES" wantsLayer="YES" appearanceType="vibrantDark" blendingMode="withinWindow" material="HUDWindow" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="44"/>
|
||||
<subviews>
|
||||
<popUpButton wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rh8-km-57n">
|
||||
<rect key="frame" x="9" y="8" width="183" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="RGB Monitor" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="tJM-kX-gaK" id="8SX-c5-ud1">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="L06-TO-EF0">
|
||||
<items>
|
||||
<menuItem title="RGB Monitor" state="on" id="tJM-kX-gaK"/>
|
||||
<menuItem title="S-Video" tag="2" id="Mtc-Ht-iY8"/>
|
||||
<menuItem title="Television" tag="1" id="fFm-fS-rWG"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<action selector="setDisplayType:" target="MXS-dG-Doo" id="5Vp-mv-kZU"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="12" id="B6L-VS-2cN"/>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="12" id="VRo-6R-IKd"/>
|
||||
<constraint firstAttribute="bottom" secondItem="rh8-km-57n" secondAttribute="bottom" constant="12" id="jHA-lf-e7V"/>
|
||||
<constraint firstAttribute="trailing" secondItem="rh8-km-57n" secondAttribute="trailing" constant="12" id="urO-Ac-aqK"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="-118" y="120"/>
|
||||
</visualEffectView>
|
||||
<customObject id="MXS-dG-Doo" customClass="MachineController" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="displayTypeButton" destination="rh8-km-57n" id="FB2-Zg-VKq"/>
|
||||
<outlet property="displayTypeButton" destination="rh8-km-57n" id="3ln-Pl-G3k"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="175" y="33.5"/>
|
||||
</window>
|
||||
</customObject>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
<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="scanTargetView" destination="DEG-fq-cjd" id="5aX-3R-eXQ"/>
|
||||
<outlet property="volumeSlider" destination="zaz-lB-Iyt" id="flY-Th-oG4"/>
|
||||
<outlet property="volumeView" destination="4ap-Gi-2AO" id="v4e-k6-Fqf"/>
|
||||
<outlet property="volumeSlider" destination="bmN-Nb-BBh" id="1aU-pu-mfB"/>
|
||||
<outlet property="volumeView" destination="l9e-qt-jMo" id="4cE-4e-RhG"/>
|
||||
<outlet property="window" destination="xOd-HO-29H" id="JIz-fz-R2o"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
@@ -21,7 +21,7 @@
|
||||
<windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="80" y="250" width="600" height="450"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1440"/>
|
||||
<value key="minSize" type="size" width="228" height="171"/>
|
||||
<view key="contentView" id="gIp-Ho-8D9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="450"/>
|
||||
@@ -30,57 +30,50 @@
|
||||
<view hidden="YES" wantsLayer="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DEG-fq-cjd" customClass="CSScanTargetView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="450"/>
|
||||
</view>
|
||||
<box hidden="YES" boxType="custom" cornerRadius="4" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="4ap-Gi-2AO">
|
||||
<rect key="frame" x="150" y="20" width="300" height="48"/>
|
||||
<view key="contentView" id="gwO-Ty-LCX">
|
||||
<rect key="frame" x="1" y="1" width="298" height="46"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Hzw-P6-1dH">
|
||||
<rect key="frame" x="258" y="8" width="32" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="32" id="WrK-W9-mPP"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSTouchBarAudioOutputVolumeHighTemplate" id="5dB-4Y-iEl"/>
|
||||
<color key="contentTintColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</imageView>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="p0w-Ti-Tu9">
|
||||
<rect key="frame" x="8" y="8" width="32" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="32" id="dZn-Fc-fRU"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSTouchBarAudioOutputVolumeOffTemplate" id="mUH-aA-T9N"/>
|
||||
<color key="contentTintColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</imageView>
|
||||
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="zaz-lB-Iyt">
|
||||
<rect key="frame" x="46" y="14" width="206" height="19"/>
|
||||
<sliderCell key="cell" continuous="YES" state="on" alignment="left" maxValue="1" doubleValue="1" tickMarkPosition="above" sliderType="linear" id="Zvz-Og-dGA"/>
|
||||
<connections>
|
||||
<action selector="setVolume:" target="-2" id="eEc-5v-I2c"/>
|
||||
</connections>
|
||||
</slider>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="p0w-Ti-Tu9" firstAttribute="leading" secondItem="gwO-Ty-LCX" secondAttribute="leading" constant="8" id="1t0-CW-zp9"/>
|
||||
<constraint firstItem="Hzw-P6-1dH" firstAttribute="top" secondItem="gwO-Ty-LCX" secondAttribute="top" constant="8" id="OHP-c3-2Aa"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Hzw-P6-1dH" secondAttribute="trailing" constant="8" id="W24-Wx-bdQ"/>
|
||||
<constraint firstItem="zaz-lB-Iyt" firstAttribute="centerY" secondItem="p0w-Ti-Tu9" secondAttribute="centerY" id="f3C-My-T0S"/>
|
||||
<constraint firstItem="zaz-lB-Iyt" firstAttribute="leading" secondItem="p0w-Ti-Tu9" secondAttribute="trailing" constant="8" id="n0g-y6-wHP"/>
|
||||
<constraint firstItem="p0w-Ti-Tu9" firstAttribute="centerY" secondItem="gwO-Ty-LCX" secondAttribute="centerY" id="uTt-VY-o8c"/>
|
||||
<constraint firstItem="Hzw-P6-1dH" firstAttribute="leading" secondItem="zaz-lB-Iyt" secondAttribute="trailing" constant="8" id="xCS-qF-Gz8"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Hzw-P6-1dH" secondAttribute="bottom" constant="8" id="yaF-k8-W5B"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<visualEffectView hidden="YES" wantsLayer="YES" appearanceType="vibrantDark" blendingMode="withinWindow" material="HUDWindow" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="l9e-qt-jMo" userLabel="Volume View">
|
||||
<rect key="frame" x="130" y="20" width="340" height="36"/>
|
||||
<subviews>
|
||||
<imageView wantsLayer="YES" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="3hK-SA-aKj">
|
||||
<rect key="frame" x="8" y="12" width="32.5" height="14"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="32" id="tY0-07-0UK"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSTouchBarAudioOutputVolumeOffTemplate" id="HbG-Ey-djw"/>
|
||||
<color key="contentTintColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
</imageView>
|
||||
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bmN-Nb-BBh">
|
||||
<rect key="frame" x="46" y="2" width="248" height="28"/>
|
||||
<sliderCell key="cell" continuous="YES" state="on" alignment="left" minValue="1" maxValue="2" doubleValue="2" tickMarkPosition="above" sliderType="linear" id="wtR-Vo-Q9e"/>
|
||||
<connections>
|
||||
<action selector="setVolume:" target="-2" id="Ptv-pk-zbl"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<imageView wantsLayer="YES" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="pG5-Iv-llF">
|
||||
<rect key="frame" x="300" y="11.5" width="32.5" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="32" id="Nq1-7v-zbT"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSTouchBarAudioOutputVolumeHighTemplate" id="iJG-ib-H5S"/>
|
||||
<color key="contentTintColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="300" id="HKL-vy-Mov"/>
|
||||
<constraint firstItem="bmN-Nb-BBh" firstAttribute="top" secondItem="l9e-qt-jMo" secondAttribute="top" constant="8" id="Bdo-LI-B9k"/>
|
||||
<constraint firstAttribute="bottom" secondItem="bmN-Nb-BBh" secondAttribute="bottom" constant="8" id="Lu6-q8-0Ie"/>
|
||||
<constraint firstItem="bmN-Nb-BBh" firstAttribute="leading" secondItem="3hK-SA-aKj" secondAttribute="trailing" constant="8" symbolic="YES" id="Lvd-Pp-IyL"/>
|
||||
<constraint firstAttribute="width" constant="340" id="S3o-RO-Jjm"/>
|
||||
<constraint firstAttribute="trailing" secondItem="pG5-Iv-llF" secondAttribute="trailing" constant="8" id="fMW-9R-UvR"/>
|
||||
<constraint firstItem="pG5-Iv-llF" firstAttribute="leading" secondItem="bmN-Nb-BBh" secondAttribute="trailing" constant="8" symbolic="YES" id="tMb-ac-ZX2"/>
|
||||
<constraint firstItem="3hK-SA-aKj" firstAttribute="centerY" secondItem="bmN-Nb-BBh" secondAttribute="centerY" id="wuj-yd-xkH"/>
|
||||
<constraint firstItem="3hK-SA-aKj" firstAttribute="leading" secondItem="l9e-qt-jMo" secondAttribute="leading" constant="8" id="y3G-8K-adU"/>
|
||||
<constraint firstItem="pG5-Iv-llF" firstAttribute="centerY" secondItem="bmN-Nb-BBh" secondAttribute="centerY" id="yjF-sC-XSG"/>
|
||||
</constraints>
|
||||
<color key="fillColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</box>
|
||||
</visualEffectView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="l9e-qt-jMo" firstAttribute="centerX" secondItem="gIp-Ho-8D9" secondAttribute="centerX" id="63A-k7-XRW"/>
|
||||
<constraint firstItem="DEG-fq-cjd" firstAttribute="centerX" secondItem="gIp-Ho-8D9" secondAttribute="centerX" id="ES5-nL-N3h"/>
|
||||
<constraint firstItem="4ap-Gi-2AO" firstAttribute="centerX" secondItem="DEG-fq-cjd" secondAttribute="centerX" id="T41-z9-BsM"/>
|
||||
<constraint firstItem="4ap-Gi-2AO" firstAttribute="bottom" secondItem="DEG-fq-cjd" secondAttribute="bottom" constant="-20" id="Tly-Uu-96H"/>
|
||||
<constraint firstAttribute="bottom" secondItem="l9e-qt-jMo" secondAttribute="bottom" constant="20" symbolic="YES" id="QG7-P0-OBj"/>
|
||||
<constraint firstItem="DEG-fq-cjd" firstAttribute="height" secondItem="gIp-Ho-8D9" secondAttribute="height" id="YoB-qI-LFX"/>
|
||||
<constraint firstItem="DEG-fq-cjd" firstAttribute="centerY" secondItem="gIp-Ho-8D9" secondAttribute="centerY" id="d5Y-3a-CEI"/>
|
||||
<constraint firstItem="DEG-fq-cjd" firstAttribute="width" secondItem="gIp-Ho-8D9" secondAttribute="width" id="mYS-bH-DST"/>
|
||||
@@ -99,7 +92,7 @@
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSTouchBarAudioOutputVolumeHighTemplate" width="23" height="30"/>
|
||||
<image name="NSTouchBarAudioOutputVolumeOffTemplate" width="23" height="30"/>
|
||||
<image name="NSTouchBarAudioOutputVolumeHighTemplate" width="22" height="15"/>
|
||||
<image name="NSTouchBarAudioOutputVolumeOffTemplate" width="14" height="14"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
@@ -1,49 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
<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="optionsPanel" destination="ZW7-Bw-4RP" id="JpE-wG-zRR"/>
|
||||
<outlet property="optionsController" destination="Lt7-Vu-Vry" id="Tvy-Sa-5oy"/>
|
||||
<outlet property="optionsView" destination="tpZ-0B-QQu" id="Sat-aY-EKi"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Options" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="ZW7-Bw-4RP" customClass="MachinePanel" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" nonactivatingPanel="YES" HUD="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="80" y="150" width="200" height="54"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<view key="contentView" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="54"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="zPG-yW-4Gy">
|
||||
<rect key="frame" x="18" y="18" width="164" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Start Quickly" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="alI-Mw-35c">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setFastBooting:" target="ZW7-Bw-4RP" id="AgA-2q-qUU"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="zPG-yW-4Gy" secondAttribute="bottom" constant="20" id="7u0-BP-FXG"/>
|
||||
<constraint firstAttribute="trailing" secondItem="zPG-yW-4Gy" secondAttribute="trailing" constant="20" id="Mtb-hf-4ap"/>
|
||||
<constraint firstItem="zPG-yW-4Gy" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="imk-5k-8nm"/>
|
||||
<constraint firstItem="zPG-yW-4Gy" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="20" id="jAt-iF-uaT"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<visualEffectView hidden="YES" wantsLayer="YES" appearanceType="vibrantDark" blendingMode="withinWindow" material="HUDWindow" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="56"/>
|
||||
<subviews>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="zPG-yW-4Gy">
|
||||
<rect key="frame" x="10" y="11" width="178" height="34"/>
|
||||
<buttonCell key="cell" type="check" title="Start Quickly" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="alI-Mw-35c">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setFastBooting:" target="Lt7-Vu-Vry" id="8X7-my-U0u"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="zPG-yW-4Gy" secondAttribute="bottom" constant="12" id="7u0-BP-FXG"/>
|
||||
<constraint firstAttribute="trailing" secondItem="zPG-yW-4Gy" secondAttribute="trailing" constant="12" id="Mtb-hf-4ap"/>
|
||||
<constraint firstItem="zPG-yW-4Gy" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="12" id="imk-5k-8nm"/>
|
||||
<constraint firstItem="zPG-yW-4Gy" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="12" id="jAt-iF-uaT"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="6" y="154"/>
|
||||
</visualEffectView>
|
||||
<customObject id="Lt7-Vu-Vry" customClass="MachineController" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="fastBootingButton" destination="zPG-yW-4Gy" id="3Mq-l2-NEp"/>
|
||||
<outlet property="fastBootingButton" destination="zPG-yW-4Gy" id="JcX-R1-SMn"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-50" y="2"/>
|
||||
</window>
|
||||
</customObject>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
@@ -141,25 +141,6 @@
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="H8h-7b-M4v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="View" id="HyV-fh-RgO">
|
||||
<items>
|
||||
<menuItem title="Show Activity" keyEquivalent="a" id="WCd-6R-baV">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="showActivity:" target="-1" id="oeF-uJ-cOS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show Options" keyEquivalent="o" id="GtG-CV-Uro">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="showOptions:" target="-1" id="M6T-DE-Duo"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Input" id="5bL-VY-cxd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Input" id="6yv-Cf-E9r">
|
||||
|
||||
@@ -1,70 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
<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="optionsPanel" destination="ZW7-Bw-4RP" id="JpE-wG-zRR"/>
|
||||
<outlet property="optionsController" destination="nbv-6C-VPa" id="na0-4N-RFd"/>
|
||||
<outlet property="optionsView" destination="tpZ-0B-QQu" id="Sz4-GS-B5l"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Options" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="ZW7-Bw-4RP" customClass="MachinePanel" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" nonactivatingPanel="YES" HUD="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="80" y="150" width="200" height="83"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<view key="contentView" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="222" height="83"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="zPG-yW-4Gy">
|
||||
<rect key="frame" x="18" y="47" width="186" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Load Quickly" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="alI-Mw-35c">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setFastLoading:" target="ZW7-Bw-4RP" id="yyv-gz-xoa"/>
|
||||
</connections>
|
||||
</button>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rh8-km-57n">
|
||||
<rect key="frame" x="18" y="17" width="187" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="SCART" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="tJM-kX-gaK" id="8SX-c5-ud1">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="L06-TO-EF0">
|
||||
<items>
|
||||
<menuItem title="SCART" state="on" id="tJM-kX-gaK"/>
|
||||
<menuItem title="Composite" tag="1" id="fFm-fS-rWG"/>
|
||||
<menuItem title="Composite Monochrome" tag="3" id="hjs-qh-WKP"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<action selector="setDisplayType:" target="ZW7-Bw-4RP" id="PAH-CZ-zlk"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="zPG-yW-4Gy" secondAttribute="trailing" constant="20" id="Mtb-hf-4ap"/>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="top" secondItem="zPG-yW-4Gy" secondAttribute="bottom" constant="8" id="ScX-pe-t0x"/>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="VRo-6R-IKd"/>
|
||||
<constraint firstAttribute="bottom" secondItem="rh8-km-57n" secondAttribute="bottom" constant="20" id="g0Y-mW-nla"/>
|
||||
<constraint firstItem="zPG-yW-4Gy" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="imk-5k-8nm"/>
|
||||
<constraint firstItem="zPG-yW-4Gy" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="20" id="jAt-iF-uaT"/>
|
||||
<constraint firstAttribute="trailing" secondItem="rh8-km-57n" secondAttribute="trailing" constant="20" id="urO-Ac-aqK"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<visualEffectView hidden="YES" wantsLayer="YES" appearanceType="vibrantDark" blendingMode="withinWindow" material="HUDWindow" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="221" height="72"/>
|
||||
<subviews>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="zPG-yW-4Gy">
|
||||
<rect key="frame" x="10" y="39" width="199" height="22"/>
|
||||
<buttonCell key="cell" type="check" title="Load Quickly" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="alI-Mw-35c">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setFastLoading:" target="nbv-6C-VPa" id="tpC-fs-r5t"/>
|
||||
</connections>
|
||||
</button>
|
||||
<popUpButton wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rh8-km-57n">
|
||||
<rect key="frame" x="9" y="8" width="204" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="SCART" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="tJM-kX-gaK" id="8SX-c5-ud1">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="L06-TO-EF0">
|
||||
<items>
|
||||
<menuItem title="SCART" state="on" id="tJM-kX-gaK"/>
|
||||
<menuItem title="Composite" tag="1" id="fFm-fS-rWG"/>
|
||||
<menuItem title="Composite Monochrome" tag="3" id="hjs-qh-WKP"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<action selector="setDisplayType:" target="nbv-6C-VPa" id="hhU-gc-qm2"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="zPG-yW-4Gy" secondAttribute="trailing" constant="12" id="Mtb-hf-4ap"/>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="top" secondItem="zPG-yW-4Gy" secondAttribute="bottom" constant="8" id="ScX-pe-t0x"/>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="12" id="VRo-6R-IKd"/>
|
||||
<constraint firstAttribute="bottom" secondItem="rh8-km-57n" secondAttribute="bottom" constant="12" id="g0Y-mW-nla"/>
|
||||
<constraint firstItem="zPG-yW-4Gy" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="12" id="imk-5k-8nm"/>
|
||||
<constraint firstItem="zPG-yW-4Gy" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="12" id="jAt-iF-uaT"/>
|
||||
<constraint firstAttribute="trailing" secondItem="rh8-km-57n" secondAttribute="trailing" constant="12" id="urO-Ac-aqK"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="-309.5" y="-24"/>
|
||||
</visualEffectView>
|
||||
<customObject id="nbv-6C-VPa" customClass="MachineController" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="displayTypeButton" destination="rh8-km-57n" id="FB2-Zg-VKq"/>
|
||||
<outlet property="fastLoadingButton" destination="zPG-yW-4Gy" id="aMA-R2-EL8"/>
|
||||
<outlet property="displayTypeButton" destination="rh8-km-57n" id="yf3-5z-J6H"/>
|
||||
<outlet property="fastLoadingButton" destination="zPG-yW-4Gy" id="u4B-6W-Oez"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-50" y="16.5"/>
|
||||
</window>
|
||||
</customObject>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@@ -1,69 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14113" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14113"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
<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="optionsPanel" destination="ZW7-Bw-4RP" id="JpE-wG-zRR"/>
|
||||
<outlet property="optionsController" destination="bLp-5J-WqC" id="nhC-Od-QqW"/>
|
||||
<outlet property="optionsView" destination="tpZ-0B-QQu" id="Uje-4H-rLo"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Options" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="ZW7-Bw-4RP" customClass="MachinePanel" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" nonactivatingPanel="YES" HUD="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="80" y="150" width="200" height="83"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<view key="contentView" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="83"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="e1J-pw-zGw">
|
||||
<rect key="frame" x="18" y="47" width="164" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Load Quickly" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="tD6-UB-ESB">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setFastLoading:" target="ZW7-Bw-4RP" id="JmG-Ks-jSh"/>
|
||||
</connections>
|
||||
</button>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rh8-km-57n">
|
||||
<rect key="frame" x="18" y="17" width="165" height="26"/>
|
||||
<popUpButtonCell key="cell" type="push" title="RGB Monitor" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="tJM-kX-gaK" id="8SX-c5-ud1">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="L06-TO-EF0">
|
||||
<items>
|
||||
<menuItem title="RGB Monitor" state="on" id="tJM-kX-gaK"/>
|
||||
<menuItem title="S-Video" tag="2" id="Mtc-Ht-iY8"/>
|
||||
<menuItem title="Television" tag="1" id="fFm-fS-rWG"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<action selector="setDisplayType:" target="ZW7-Bw-4RP" id="PAH-CZ-zlk"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="top" secondItem="e1J-pw-zGw" secondAttribute="bottom" constant="8" id="GLg-6X-Lj2"/>
|
||||
<constraint firstItem="e1J-pw-zGw" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="HSD-3d-Bl7"/>
|
||||
<constraint firstAttribute="trailing" secondItem="e1J-pw-zGw" secondAttribute="trailing" constant="20" id="Q9M-FH-92N"/>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="VRo-6R-IKd"/>
|
||||
<constraint firstItem="e1J-pw-zGw" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="20" id="ul9-lf-Y3u"/>
|
||||
<constraint firstAttribute="trailing" secondItem="rh8-km-57n" secondAttribute="trailing" constant="20" id="urO-Ac-aqK"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<visualEffectView hidden="YES" wantsLayer="YES" appearanceType="vibrantDark" blendingMode="withinWindow" material="HUDWindow" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="71"/>
|
||||
<subviews>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="e1J-pw-zGw">
|
||||
<rect key="frame" x="10" y="39" width="178" height="21"/>
|
||||
<buttonCell key="cell" type="check" title="Load Quickly" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="tD6-UB-ESB">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setFastLoading:" target="bLp-5J-WqC" id="cKN-Dr-jRZ"/>
|
||||
</connections>
|
||||
</button>
|
||||
<popUpButton wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rh8-km-57n">
|
||||
<rect key="frame" x="9" y="8" width="183" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="RGB Monitor" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="tJM-kX-gaK" id="8SX-c5-ud1">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="L06-TO-EF0">
|
||||
<items>
|
||||
<menuItem title="RGB Monitor" state="on" id="tJM-kX-gaK"/>
|
||||
<menuItem title="S-Video" tag="2" id="Mtc-Ht-iY8"/>
|
||||
<menuItem title="Television" tag="1" id="fFm-fS-rWG"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<action selector="setDisplayType:" target="bLp-5J-WqC" id="tYR-gr-Qq6"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="top" secondItem="e1J-pw-zGw" secondAttribute="bottom" constant="8" id="GLg-6X-Lj2"/>
|
||||
<constraint firstItem="e1J-pw-zGw" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="12" id="HSD-3d-Bl7"/>
|
||||
<constraint firstAttribute="trailing" secondItem="e1J-pw-zGw" secondAttribute="trailing" constant="12" id="Q9M-FH-92N"/>
|
||||
<constraint firstItem="rh8-km-57n" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="12" id="VRo-6R-IKd"/>
|
||||
<constraint firstAttribute="bottom" secondItem="rh8-km-57n" secondAttribute="bottom" constant="12" id="rwd-hx-LPv"/>
|
||||
<constraint firstItem="e1J-pw-zGw" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="12" id="ul9-lf-Y3u"/>
|
||||
<constraint firstAttribute="trailing" secondItem="rh8-km-57n" secondAttribute="trailing" constant="12" id="urO-Ac-aqK"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="39" y="114.5"/>
|
||||
</visualEffectView>
|
||||
<customObject id="bLp-5J-WqC" customClass="MachineController" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="displayTypeButton" destination="rh8-km-57n" id="FB2-Zg-VKq"/>
|
||||
<outlet property="fastLoadingButton" destination="e1J-pw-zGw" id="jj7-OZ-mOH"/>
|
||||
<outlet property="displayTypeButton" destination="rh8-km-57n" id="uX3-tS-5Qu"/>
|
||||
<outlet property="fastLoadingButton" destination="e1J-pw-zGw" id="x6U-1J-qCU"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="175" y="45"/>
|
||||
</window>
|
||||
</customObject>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@@ -1,49 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14113" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14113"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
<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="optionsPanel" destination="ZW7-Bw-4RP" id="JpE-wG-zRR"/>
|
||||
<outlet property="optionsController" destination="cWS-AS-crO" id="KeQ-V1-s46"/>
|
||||
<outlet property="optionsView" destination="e1J-pw-zGw" id="ALr-SV-afm"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Options" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="ZW7-Bw-4RP" customClass="MachinePanel" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" nonactivatingPanel="YES" HUD="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="80" y="150" width="200" height="54"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<view key="contentView" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="54"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="e1J-pw-zGw">
|
||||
<rect key="frame" x="18" y="18" width="164" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Load Quickly" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="tD6-UB-ESB">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setFastLoading:" target="ZW7-Bw-4RP" id="JmG-Ks-jSh"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="e1J-pw-zGw" secondAttribute="bottom" constant="20" id="5ce-DO-a4T"/>
|
||||
<constraint firstItem="e1J-pw-zGw" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="HSD-3d-Bl7"/>
|
||||
<constraint firstAttribute="trailing" secondItem="e1J-pw-zGw" secondAttribute="trailing" constant="20" id="Q9M-FH-92N"/>
|
||||
<constraint firstItem="e1J-pw-zGw" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="20" id="ul9-lf-Y3u"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<visualEffectView wantsLayer="YES" appearanceType="vibrantDark" blendingMode="withinWindow" material="HUDWindow" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="tpZ-0B-QQu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="200" height="44"/>
|
||||
<subviews>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="e1J-pw-zGw">
|
||||
<rect key="frame" x="10" y="11" width="178" height="22"/>
|
||||
<buttonCell key="cell" type="check" title="Load Quickly" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="tD6-UB-ESB">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setFastLoading:" target="cWS-AS-crO" id="aed-8n-jk7"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="e1J-pw-zGw" secondAttribute="bottom" constant="12" id="5ce-DO-a4T"/>
|
||||
<constraint firstItem="e1J-pw-zGw" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="12" id="HSD-3d-Bl7"/>
|
||||
<constraint firstAttribute="trailing" secondItem="e1J-pw-zGw" secondAttribute="trailing" constant="12" id="Q9M-FH-92N"/>
|
||||
<constraint firstItem="e1J-pw-zGw" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="12" id="ul9-lf-Y3u"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="-118" y="114"/>
|
||||
</visualEffectView>
|
||||
<customObject id="cWS-AS-crO" customClass="MachineController" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="fastLoadingButton" destination="e1J-pw-zGw" id="jj7-OZ-mOH"/>
|
||||
<outlet property="fastLoadingButton" destination="e1J-pw-zGw" id="YjF-pM-Gum"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="175" y="30"/>
|
||||
</window>
|
||||
</customObject>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@@ -1,77 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14113" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14113"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
<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="optionsPanel" destination="ota-g7-hOL" id="zeO-di-9i3"/>
|
||||
<outlet property="optionsController" destination="ehh-jE-OeP" id="e6i-od-09b"/>
|
||||
<outlet property="optionsView" destination="7Pv-WL-2Rq" id="2Qq-nM-Xap"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Options" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="ota-g7-hOL" customClass="ZX8081OptionsPanel" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" nonactivatingPanel="YES" HUD="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" topStrut="YES"/>
|
||||
<rect key="contentRect" x="80" y="150" width="261" height="100"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<view key="contentView" id="7Pv-WL-2Rq">
|
||||
<rect key="frame" x="0.0" y="0.0" width="261" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="sBT-cU-h7s">
|
||||
<rect key="frame" x="18" y="64" width="225" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Load Tapes Quickly" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="w0l-ha-esm">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setFastLoading:" target="ota-g7-hOL" id="me0-h2-Ga5"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="qSb-72-6Os">
|
||||
<rect key="frame" x="18" y="44" width="225" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Control Tape Motor Automatically" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="CzC-YT-lgA">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setAutomaticTapeMotorConrol:" target="ota-g7-hOL" id="bpF-1P-tga"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tkN-gI-RmT">
|
||||
<rect key="frame" x="20" y="19" width="221" height="19"/>
|
||||
<buttonCell key="cell" type="roundRect" title="Play Tape" bezelStyle="roundedRect" alignment="center" enabled="NO" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="cTq-f9-Gzx">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="cellTitle"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="playOrPauseTape:" target="ota-g7-hOL" id="O0K-pL-nOr"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="qSb-72-6Os" firstAttribute="leading" secondItem="7Pv-WL-2Rq" secondAttribute="leading" constant="20" id="05p-Jn-ueX"/>
|
||||
<constraint firstAttribute="trailing" secondItem="sBT-cU-h7s" secondAttribute="trailing" constant="20" id="79b-2A-2c7"/>
|
||||
<constraint firstItem="sBT-cU-h7s" firstAttribute="top" secondItem="7Pv-WL-2Rq" secondAttribute="top" constant="20" id="E5m-wo-X92"/>
|
||||
<constraint firstItem="qSb-72-6Os" firstAttribute="top" secondItem="sBT-cU-h7s" secondAttribute="bottom" constant="6" id="WxD-kP-vwf"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tkN-gI-RmT" secondAttribute="bottom" constant="20" id="Xnu-On-nOA"/>
|
||||
<constraint firstItem="tkN-gI-RmT" firstAttribute="leading" secondItem="7Pv-WL-2Rq" secondAttribute="leading" constant="20" id="fHf-K0-PsU"/>
|
||||
<constraint firstItem="tkN-gI-RmT" firstAttribute="top" secondItem="qSb-72-6Os" secondAttribute="bottom" constant="8" id="gLh-vE-Cqk"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qSb-72-6Os" secondAttribute="trailing" constant="20" id="mQz-p8-aYf"/>
|
||||
<constraint firstItem="sBT-cU-h7s" firstAttribute="leading" secondItem="7Pv-WL-2Rq" secondAttribute="leading" constant="20" id="nDy-Xc-Ug9"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tkN-gI-RmT" secondAttribute="trailing" constant="20" id="vgD-A3-m6T"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<visualEffectView hidden="YES" wantsLayer="YES" appearanceType="vibrantDark" blendingMode="behindWindow" material="HUDWindow" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="7Pv-WL-2Rq">
|
||||
<rect key="frame" x="0.0" y="0.0" width="267" height="100"/>
|
||||
<subviews>
|
||||
<button ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sBT-cU-h7s">
|
||||
<rect key="frame" x="10" y="63" width="245" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Load Tapes Quickly" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="w0l-ha-esm">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setFastLoading:" target="ehh-jE-OeP" id="QEr-7F-9Ms"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qSb-72-6Os">
|
||||
<rect key="frame" x="10" y="41" width="245" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Control Tape Motor Automatically" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="CzC-YT-lgA">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="setAutomaticTapeMotorConrol:" target="ehh-jE-OeP" id="CgR-12-6cc"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tkN-gI-RmT">
|
||||
<rect key="frame" x="12" y="11" width="243" height="19"/>
|
||||
<buttonCell key="cell" type="roundRect" title="Play Tape" bezelStyle="roundedRect" alignment="center" enabled="NO" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="cTq-f9-Gzx">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="cellTitle"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="playOrPauseTape:" target="ehh-jE-OeP" id="lxp-zi-DWI"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="qSb-72-6Os" firstAttribute="leading" secondItem="7Pv-WL-2Rq" secondAttribute="leading" constant="12" id="05p-Jn-ueX"/>
|
||||
<constraint firstAttribute="trailing" secondItem="sBT-cU-h7s" secondAttribute="trailing" constant="12" id="79b-2A-2c7"/>
|
||||
<constraint firstItem="sBT-cU-h7s" firstAttribute="top" secondItem="7Pv-WL-2Rq" secondAttribute="top" constant="12" id="E5m-wo-X92"/>
|
||||
<constraint firstItem="qSb-72-6Os" firstAttribute="top" secondItem="sBT-cU-h7s" secondAttribute="bottom" constant="6" symbolic="YES" id="WxD-kP-vwf"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tkN-gI-RmT" secondAttribute="bottom" constant="12" id="Xnu-On-nOA"/>
|
||||
<constraint firstItem="tkN-gI-RmT" firstAttribute="leading" secondItem="7Pv-WL-2Rq" secondAttribute="leading" constant="12" id="fHf-K0-PsU"/>
|
||||
<constraint firstItem="tkN-gI-RmT" firstAttribute="top" secondItem="qSb-72-6Os" secondAttribute="bottom" constant="8" id="gLh-vE-Cqk"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qSb-72-6Os" secondAttribute="trailing" constant="12" id="mQz-p8-aYf"/>
|
||||
<constraint firstItem="sBT-cU-h7s" firstAttribute="leading" secondItem="7Pv-WL-2Rq" secondAttribute="leading" constant="12" id="nDy-Xc-Ug9"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tkN-gI-RmT" secondAttribute="trailing" constant="12" id="vgD-A3-m6T"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="38.5" y="118"/>
|
||||
</visualEffectView>
|
||||
<customObject id="ehh-jE-OeP" customClass="ZX8081Controller" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="automaticTapeMotorControlButton" destination="qSb-72-6Os" id="bB6-FP-TKM"/>
|
||||
<outlet property="fastLoadingButton" destination="sBT-cU-h7s" id="uWa-EB-mbd"/>
|
||||
<outlet property="playOrPauseTapeButton" destination="tkN-gI-RmT" id="UnJ-nb-3mv"/>
|
||||
<outlet property="automaticTapeMotorControlButton" destination="qSb-72-6Os" id="SBE-HT-AUj"/>
|
||||
<outlet property="fastLoadingButton" destination="sBT-cU-h7s" id="3oI-QE-BRI"/>
|
||||
<outlet property="playOrPauseTapeButton" destination="tkN-gI-RmT" id="cX3-Tp-ZFT"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="28.5" y="15"/>
|
||||
</window>
|
||||
</customObject>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// AppleIIOptionsPanel.swift
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 07/06/2021.
|
||||
// Copyright 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
class AppleIIController: MachineController {
|
||||
var appleII: CSAppleII! {
|
||||
get {
|
||||
return self.machine.appleII
|
||||
}
|
||||
}
|
||||
var squarePixelsUserDefaultsKey: String {
|
||||
return prefixedUserDefaultsKey("useSquarePixels")
|
||||
}
|
||||
|
||||
@IBOutlet var squarePixelButton: NSButton!
|
||||
|
||||
@IBAction func optionDidChange(_ sender: AnyObject!) {
|
||||
let useSquarePixels = squarePixelButton.state == .on
|
||||
appleII.useSquarePixels = useSquarePixels
|
||||
|
||||
let standardUserDefaults = UserDefaults.standard
|
||||
standardUserDefaults.set(useSquarePixels, forKey: squarePixelsUserDefaultsKey)
|
||||
}
|
||||
|
||||
override func establishStoredOptions() {
|
||||
super.establishStoredOptions()
|
||||
|
||||
let standardUserDefaults = UserDefaults.standard
|
||||
let useSquarePixels = standardUserDefaults.bool(forKey: squarePixelsUserDefaultsKey)
|
||||
appleII.useSquarePixels = useSquarePixels
|
||||
squarePixelButton.state = useSquarePixels ? .on : .off
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
// Copyright 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
class Atari2600OptionsPanel: MachinePanel {
|
||||
class Atari2600OptionsController: MachineController {
|
||||
var atari2600: CSAtari2600! {
|
||||
get {
|
||||
return self.machine.atari2600
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// MachinePanel.swift
|
||||
// MachineController.swift
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 02/10/2016.
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
class MachinePanel: NSPanel {
|
||||
class MachineController: NSObject {
|
||||
var machine: CSMachine!
|
||||
|
||||
// MARK: IBActions
|
||||
@@ -46,24 +46,15 @@ class MachineDocument:
|
||||
/// The OpenGL view to receive this machine's display.
|
||||
@IBOutlet weak var scanTargetView: CSScanTargetView!
|
||||
|
||||
/// The options panel, if any.
|
||||
@IBOutlet var optionsPanel: MachinePanel!
|
||||
|
||||
/// An action to display the options panel, if there is one.
|
||||
@IBAction func showOptions(_ sender: AnyObject!) {
|
||||
optionsPanel?.setIsVisible(true)
|
||||
}
|
||||
/// The options view, if any.
|
||||
@IBOutlet var optionsView: NSView!
|
||||
@IBOutlet var optionsController: MachineController!
|
||||
|
||||
/// The activity panel, if one is deemed appropriate.
|
||||
@IBOutlet var activityPanel: NSPanel!
|
||||
|
||||
/// An action to display the activity panel, if there is one.
|
||||
@IBAction func showActivity(_ sender: AnyObject!) {
|
||||
activityPanel.setIsVisible(true)
|
||||
}
|
||||
@IBOutlet var activityView: NSView!
|
||||
|
||||
/// The volume view.
|
||||
@IBOutlet var volumeView: NSBox!
|
||||
@IBOutlet var volumeView: NSView!
|
||||
@IBOutlet var volumeSlider: NSSlider!
|
||||
|
||||
// MARK: - NSDocument Overrides and NSWindowDelegate methods.
|
||||
@@ -87,14 +78,6 @@ class MachineDocument:
|
||||
}
|
||||
}
|
||||
|
||||
private func dismissPanels() {
|
||||
activityPanel?.setIsVisible(false)
|
||||
activityPanel = nil
|
||||
|
||||
optionsPanel?.setIsVisible(false)
|
||||
optionsPanel = nil
|
||||
}
|
||||
|
||||
override func close() {
|
||||
// Close any dangling sheets.
|
||||
//
|
||||
@@ -112,9 +95,6 @@ class MachineDocument:
|
||||
// Stop the machine, if any.
|
||||
machine?.stop()
|
||||
|
||||
// Dismiss panels.
|
||||
dismissPanels()
|
||||
|
||||
// End the update cycle.
|
||||
actionLock.lock()
|
||||
drawLock.lock()
|
||||
@@ -134,7 +114,9 @@ class MachineDocument:
|
||||
override func windowControllerDidLoadNib(_ aController: NSWindowController) {
|
||||
super.windowControllerDidLoadNib(aController)
|
||||
aController.window?.contentAspectRatio = self.aspectRatio()
|
||||
volumeSlider.floatValue = userDefaultsVolume()
|
||||
volumeSlider.floatValue = pow(2.0, userDefaultsVolume())
|
||||
|
||||
volumeView.layer!.cornerRadius = 5.0
|
||||
}
|
||||
|
||||
private var missingROMs: String = ""
|
||||
@@ -171,9 +153,10 @@ class MachineDocument:
|
||||
func windowDidUpdate(_ notification: Notification) {
|
||||
if self.windowControllers.count > 0, let window = self.windowControllers[0].window, window.isVisible {
|
||||
// Grab the regular window title, if it's not already stored.
|
||||
if self.unadornedWindowTitle.count == 0 {
|
||||
if self.unadornedWindowTitle == "" {
|
||||
self.unadornedWindowTitle = window.title
|
||||
}
|
||||
updateWindowTitle()
|
||||
|
||||
// If an interaction mode is not yet in effect, pick the proper one and display the relevant thing.
|
||||
if self.interactionMode == .notStarted {
|
||||
@@ -200,7 +183,11 @@ class MachineDocument:
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Connections Between Machine and the Outside World
|
||||
func windowDidEnterFullScreen(_ notification: Notification) {
|
||||
updateActivityViewVisibility()
|
||||
}
|
||||
|
||||
// MARK: - Connections Between Machine and the Outside World.
|
||||
|
||||
private func setupMachineOutput() {
|
||||
if let machine = self.machine, let scanTargetView = self.scanTargetView, machine.view != scanTargetView {
|
||||
@@ -208,17 +195,39 @@ class MachineDocument:
|
||||
let aspectRatio = self.aspectRatio()
|
||||
machine.setView(scanTargetView, aspectRatio: Float(aspectRatio.width / aspectRatio.height))
|
||||
|
||||
// Get rid of all existing accessory panels.
|
||||
dismissPanels()
|
||||
|
||||
// Attach an options panel if one is available.
|
||||
if let optionsPanelNibName = self.machineDescription?.optionsPanelNibName {
|
||||
Bundle.main.loadNibNamed(optionsPanelNibName, owner: self, topLevelObjects: nil)
|
||||
self.optionsPanel.machine = machine
|
||||
self.optionsPanel?.establishStoredOptions()
|
||||
showOptions(self)
|
||||
if let optionsNibName = self.machineDescription?.optionsNibName {
|
||||
Bundle.main.loadNibNamed(optionsNibName, owner: self, topLevelObjects: nil)
|
||||
if let optionsController = self.optionsController {
|
||||
optionsController.machine = machine
|
||||
optionsController.establishStoredOptions()
|
||||
}
|
||||
if let optionsView = self.optionsView, let superview = self.volumeView.superview {
|
||||
// Apply rounded edges.
|
||||
optionsView.layer!.cornerRadius = 5.0
|
||||
|
||||
// Add to the superview.
|
||||
superview.addSubview(optionsView)
|
||||
|
||||
// Apply constraints to appear centred and above the volume view.
|
||||
let constraints = [
|
||||
optionsView.centerXAnchor.constraint(equalTo: volumeView.centerXAnchor),
|
||||
optionsView.bottomAnchor.constraint(equalTo: volumeView.topAnchor, constant: -8.0),
|
||||
]
|
||||
superview.addConstraints(constraints)
|
||||
}
|
||||
}
|
||||
|
||||
// Set up a fader for the volume and options.
|
||||
var fadingViews: [NSView] = []
|
||||
if let optionsView = self.optionsView {
|
||||
fadingViews.append(optionsView)
|
||||
}
|
||||
if let volumeView = self.volumeView {
|
||||
fadingViews.append(volumeView)
|
||||
}
|
||||
optionsFader = ViewFader(views: fadingViews)
|
||||
|
||||
// Create and populate an activity display if required.
|
||||
setupActivityDisplay()
|
||||
|
||||
@@ -390,6 +399,7 @@ class MachineDocument:
|
||||
}
|
||||
|
||||
// MARK: - MachinePicker Outlets and Actions
|
||||
|
||||
@IBOutlet var machinePicker: MachinePicker?
|
||||
@IBOutlet var machinePickerPanel: NSWindow?
|
||||
@IBAction func createMachine(_ sender: NSButton?) {
|
||||
@@ -408,6 +418,7 @@ class MachineDocument:
|
||||
}
|
||||
|
||||
// MARK: - ROMRequester Outlets and Actions
|
||||
|
||||
@IBOutlet var romRequesterPanel: NSWindow?
|
||||
@IBOutlet var romRequesterText: NSTextField?
|
||||
@IBOutlet var romReceiverErrorField: NSTextField?
|
||||
@@ -512,7 +523,8 @@ class MachineDocument:
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Joystick-via-the-keyboard selection
|
||||
// MARK: - Joystick-via-the-keyboard selection.
|
||||
|
||||
@IBAction func useKeyboardAsPhysicalKeyboard(_ sender: NSMenuItem?) {
|
||||
machine.inputMode = .keyboardPhysical
|
||||
}
|
||||
@@ -558,9 +570,6 @@ class MachineDocument:
|
||||
menuItem.state = machine.inputMode == .joystick ? .on : .off
|
||||
return true
|
||||
|
||||
case #selector(self.showActivity(_:)):
|
||||
return self.activityPanel != nil
|
||||
|
||||
case #selector(self.insertMedia(_:)):
|
||||
return self.machine != nil && self.machine.canInsertMedia
|
||||
|
||||
@@ -570,6 +579,8 @@ class MachineDocument:
|
||||
return super.validateUserInterfaceItem(item)
|
||||
}
|
||||
|
||||
// MARK: - Screenshots.
|
||||
|
||||
/// Saves a screenshot of the machine's current display.
|
||||
@IBAction func saveScreenshot(_ sender: AnyObject!) {
|
||||
// Grab a date formatter and form a file name.
|
||||
@@ -591,38 +602,57 @@ class MachineDocument:
|
||||
}
|
||||
|
||||
// MARK: - Window Title Updates.
|
||||
|
||||
private var unadornedWindowTitle = ""
|
||||
private var mouseIsCaptured = false
|
||||
private var windowTitleSuffix = ""
|
||||
|
||||
private func updateWindowTitle() {
|
||||
var title = self.unadornedWindowTitle
|
||||
if windowTitleSuffix != "" {
|
||||
title += windowTitleSuffix
|
||||
}
|
||||
if mouseIsCaptured {
|
||||
title += " (press ⌘+control to release mouse)"
|
||||
}
|
||||
self.windowControllers[0].window?.title = title
|
||||
}
|
||||
|
||||
internal func scanTargetViewDidCaptureMouse(_ view: CSScanTargetView) {
|
||||
self.windowControllers[0].window?.title = self.unadornedWindowTitle + " (press ⌘+control to release mouse)"
|
||||
mouseIsCaptured = true
|
||||
updateWindowTitle()
|
||||
}
|
||||
|
||||
internal func scanTargetViewDidReleaseMouse(_ view: CSScanTargetView) {
|
||||
self.windowControllers[0].window?.title = self.unadornedWindowTitle
|
||||
mouseIsCaptured = false
|
||||
updateWindowTitle()
|
||||
}
|
||||
|
||||
// MARK: - Activity Display.
|
||||
|
||||
private class LED {
|
||||
let levelIndicator: NSLevelIndicator
|
||||
init(levelIndicator: NSLevelIndicator) {
|
||||
init(levelIndicator: NSLevelIndicator, isPersistent: Bool) {
|
||||
self.levelIndicator = levelIndicator
|
||||
self.isPersistent = isPersistent
|
||||
}
|
||||
var isLit = false
|
||||
var isBlinking = false
|
||||
var isPersistent = false
|
||||
}
|
||||
private var leds: [String: LED] = [:]
|
||||
private var activityFader: ViewFader! = nil
|
||||
|
||||
func setupActivityDisplay() {
|
||||
var leds = machine.leds
|
||||
if leds.count > 0 {
|
||||
Bundle.main.loadNibNamed("Activity", owner: self, topLevelObjects: nil)
|
||||
showActivity(nil)
|
||||
|
||||
// Inspect the activity panel for indicators.
|
||||
var activityIndicators: [NSLevelIndicator] = []
|
||||
var textFields: [NSTextField] = []
|
||||
if let contentView = self.activityPanel.contentView {
|
||||
for view in contentView.subviews {
|
||||
if let activityView = self.activityView {
|
||||
for view in activityView.subviews {
|
||||
if let levelIndicator = view as? NSLevelIndicator {
|
||||
activityIndicators.append(levelIndicator)
|
||||
}
|
||||
@@ -646,20 +676,34 @@ class MachineDocument:
|
||||
|
||||
// Apply labels and create leds entries.
|
||||
for c in 0 ..< leds.count {
|
||||
textFields[c].stringValue = leds[c]
|
||||
self.leds[leds[c]] = LED(levelIndicator: activityIndicators[c])
|
||||
textFields[c].stringValue = leds[c].name
|
||||
self.leds[leds[c].name] = LED(levelIndicator: activityIndicators[c], isPersistent: leds[c].isPersisent)
|
||||
}
|
||||
|
||||
// Add a constraints to minimise window height.
|
||||
let heightConstraint = NSLayoutConstraint(
|
||||
item: self.activityPanel.contentView!,
|
||||
attribute: .bottom,
|
||||
relatedBy: .equal,
|
||||
toItem: activityIndicators[leds.count-1],
|
||||
attribute: .bottom,
|
||||
multiplier: 1.0,
|
||||
constant: 20.0)
|
||||
self.activityPanel.contentView?.addConstraint(heightConstraint)
|
||||
// Create a fader.
|
||||
activityFader = ViewFader(views: [self.activityView!])
|
||||
|
||||
// Add view to window, and constrain.
|
||||
if let superview = activityIndicators[leds.count-1].superview {
|
||||
superview.addConstraint(
|
||||
activityIndicators[leds.count-1].bottomAnchor.constraint(equalTo: activityIndicators[leds.count-1].superview!.bottomAnchor, constant: -8.0)
|
||||
)
|
||||
}
|
||||
if let windowView = self.volumeView.superview {
|
||||
windowView.addSubview(self.activityView)
|
||||
|
||||
let constraints = [
|
||||
self.activityView.rightAnchor.constraint(equalTo: windowView.rightAnchor),
|
||||
self.activityView.topAnchor.constraint(equalTo: windowView.topAnchor),
|
||||
]
|
||||
windowView.addConstraints(constraints)
|
||||
|
||||
activityView.layer!.cornerRadius = 5.0
|
||||
activityView.layer!.maskedCorners = [.layerMinXMinYCorner]
|
||||
}
|
||||
|
||||
// Show or hide activity view as per current state.
|
||||
updateActivityViewVisibility(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -669,7 +713,7 @@ class MachineDocument:
|
||||
// pile up — allow there to be only one in flight at a time.
|
||||
if let led = leds[ledName] {
|
||||
DispatchQueue.main.async {
|
||||
if !led.isBlinking {
|
||||
if !led.isBlinking && led.isLit {
|
||||
led.levelIndicator.floatValue = 0.0
|
||||
led.isBlinking = true
|
||||
|
||||
@@ -685,62 +729,128 @@ class MachineDocument:
|
||||
func machine(_ machine: CSMachine, led ledName: String, didChangeToLit isLit: Bool) {
|
||||
// If there is such an LED, switch it appropriately.
|
||||
if let led = leds[ledName] {
|
||||
DispatchQueue.main.async {
|
||||
DispatchQueue.main.async { [self] in
|
||||
// Do nothing for no change of state.
|
||||
if led.isLit == isLit {
|
||||
return
|
||||
}
|
||||
|
||||
led.levelIndicator.floatValue = isLit ? 1.0 : 0.0
|
||||
led.isLit = isLit
|
||||
|
||||
// Possibly show or hide the activity subview.
|
||||
self.updateActivityViewVisibility(false, changed: ledName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Volume Control.
|
||||
@IBAction func setVolume(_ sender: NSSlider!) {
|
||||
if let machine = self.machine {
|
||||
machine.setVolume(sender.floatValue)
|
||||
setUserDefaultsVolume(sender.floatValue)
|
||||
private func updateActivityViewVisibility(_ isAppLaunch : Bool = false, changed: String? = nil) {
|
||||
if let window = self.windowControllers.first?.window, let activityFader = self.activityFader {
|
||||
// Rules applied below:
|
||||
//
|
||||
// Fullscreen:
|
||||
// (i) always show activity view if any persistent LEDs are present;
|
||||
// (ii) otherwise, show activity view only while at least one LED is lit.
|
||||
//
|
||||
// Windowed:
|
||||
// (i) show while any non-persistent LED is lit;
|
||||
// (ii) show transiently to indicate a change of state in any persistent LED.
|
||||
//
|
||||
let hasLitLEDs = !self.leds.filter {
|
||||
$0.value.isLit && (!$0.value.isPersistent || window.styleMask.contains(.fullScreen)) ||
|
||||
($0.value.isPersistent && window.styleMask.contains(.fullScreen))
|
||||
}.isEmpty
|
||||
let shouldShowTransient = !window.styleMask.contains(.fullScreen) && changed != nil && self.leds[changed!]!.isPersistent
|
||||
|
||||
if hasLitLEDs {
|
||||
activityFader.animateIn()
|
||||
} else if shouldShowTransient {
|
||||
activityFader.showTransiently(for: 1.0)
|
||||
} else {
|
||||
activityFader.animateOut(delay: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This class is pure nonsense to work around Xcode's opaque behaviour.
|
||||
// If I make the main class a sub of CAAnimationDelegate then the compiler
|
||||
// generates a bridging header that doesn't include QuartzCore and therefore
|
||||
// can't find a declaration of the CAAnimationDelegate protocol. Doesn't
|
||||
// seem to matter what I add explicitly to the link stage, which version of
|
||||
// macOS I set as the target, etc.
|
||||
//
|
||||
// So, the workaround: make my CAAnimationDelegate something that doesn't
|
||||
// appear in the bridging header.
|
||||
fileprivate class ViewFader: NSObject, CAAnimationDelegate {
|
||||
var volumeView: NSView
|
||||
// MARK: - In-window panels (i.e. options, volume).
|
||||
|
||||
init(view: NSView) {
|
||||
volumeView = view
|
||||
}
|
||||
|
||||
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
|
||||
volumeView.isHidden = true
|
||||
}
|
||||
}
|
||||
fileprivate var animationFader: ViewFader? = nil
|
||||
private var optionsFader: ViewFader! = nil
|
||||
|
||||
internal func scanTargetViewDidShowOSMouseCursor(_ view: CSScanTargetView) {
|
||||
// The OS mouse cursor became visible, so show the volume controls.
|
||||
animationFader = nil
|
||||
volumeView.layer?.removeAllAnimations()
|
||||
volumeView.isHidden = false
|
||||
volumeView.layer?.opacity = 1.0
|
||||
optionsFader.animateIn()
|
||||
}
|
||||
|
||||
internal func scanTargetViewWillHideOSMouseCursor(_ view: CSScanTargetView) {
|
||||
internal func scanTargetViewWouldHideOSMouseCursor(_ view: CSScanTargetView) {
|
||||
// The OS mouse cursor will be hidden, so hide the volume controls.
|
||||
if !volumeView.isHidden && volumeView.layer?.animation(forKey: "opacity") == nil {
|
||||
let fadeAnimation = CABasicAnimation(keyPath: "opacity")
|
||||
fadeAnimation.fromValue = 1.0
|
||||
fadeAnimation.toValue = 0.0
|
||||
fadeAnimation.duration = 0.2
|
||||
animationFader = ViewFader(view: volumeView)
|
||||
fadeAnimation.delegate = animationFader
|
||||
volumeView.layer?.add(fadeAnimation, forKey: "opacity")
|
||||
volumeView.layer?.opacity = 0.0
|
||||
optionsFader.animateOut(delay: 0.0)
|
||||
}
|
||||
|
||||
// MARK: - Helpers for fading things in and out.
|
||||
|
||||
/// Maintains a list of views and offers in-and-out animations on those,
|
||||
/// testing current state as necessary and otherwise coordinating with
|
||||
/// CoreAnimation.
|
||||
private class ViewFader: NSObject, CAAnimationDelegate {
|
||||
private var views: [NSView]
|
||||
|
||||
init(views: [NSView]) {
|
||||
self.views = views
|
||||
for view in views {
|
||||
view.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
func animationDidStop(_ animation: CAAnimation, finished: Bool) {
|
||||
if finished {
|
||||
for view in views {
|
||||
view.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func animateIn() {
|
||||
for view in views {
|
||||
view.layer?.removeAllAnimations()
|
||||
view.isHidden = false
|
||||
}
|
||||
}
|
||||
|
||||
func animateOut(delay : TimeInterval) {
|
||||
// Do nothing if already animating out or invisible.
|
||||
if views[0].isHidden || views[0].layer?.animation(forKey: "opacity") != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for view in views {
|
||||
let fadeAnimation = CABasicAnimation(keyPath: "opacity")
|
||||
fadeAnimation.beginTime = CACurrentMediaTime() + delay
|
||||
fadeAnimation.fromValue = 1.0
|
||||
fadeAnimation.toValue = 0.0
|
||||
fadeAnimation.duration = 0.2
|
||||
fadeAnimation.delegate = self
|
||||
|
||||
fadeAnimation.fillMode = .forwards
|
||||
fadeAnimation.isRemovedOnCompletion = false
|
||||
|
||||
view.layer?.removeAllAnimations()
|
||||
view.layer!.add(fadeAnimation, forKey: "opacity")
|
||||
}
|
||||
}
|
||||
|
||||
func showTransiently(for period: TimeInterval) {
|
||||
animateIn()
|
||||
animateOut(delay: period)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Volume Control.
|
||||
|
||||
@IBAction func setVolume(_ sender: NSSlider!) {
|
||||
if let machine = self.machine {
|
||||
let linearValue = log2(sender.floatValue)
|
||||
machine.setVolume(linearValue)
|
||||
setUserDefaultsVolume(linearValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// Copyright 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
class ZX8081OptionsPanel: MachinePanel {
|
||||
class ZX8081Controller: MachineController {
|
||||
var zx8081: CSZX8081! {
|
||||
get {
|
||||
return self.machine.zx8081
|
||||
@@ -33,6 +33,11 @@ typedef NS_ENUM(NSInteger, CSMachineKeyboardInputMode) {
|
||||
CSMachineKeyboardInputModeJoystick,
|
||||
};
|
||||
|
||||
@interface CSMachineLED: NSObject
|
||||
@property(nonatomic, nonnull, readonly) NSString *name;
|
||||
@property(nonatomic, readonly) BOOL isPersisent;
|
||||
@end
|
||||
|
||||
// Deliberately low; to ensure CSMachine has been declared as an @class already.
|
||||
#import "CSAtari2600.h"
|
||||
#import "CSZX8081.h"
|
||||
@@ -99,7 +104,7 @@ typedef NS_ENUM(NSInteger, CSMachineKeyboardInputMode) {
|
||||
@property (nonatomic, nullable) CSJoystickManager *joystickManager;
|
||||
|
||||
// LED list.
|
||||
@property (nonatomic, readonly, nonnull) NSArray<NSString *> *leds;
|
||||
@property (nonatomic, readonly, nonnull) NSArray<CSMachineLED *> *leds;
|
||||
|
||||
// Special-case accessors; undefined behaviour if accessed for a machine not of the corresponding type.
|
||||
@property (nonatomic, readonly, nullable) CSAtari2600 *atari2600;
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
@interface CSMachine() <CSScanTargetViewDisplayLinkDelegate>
|
||||
- (void)speaker:(Outputs::Speaker::Speaker *)speaker didCompleteSamples:(const int16_t *)samples length:(int)length;
|
||||
- (void)speakerDidChangeInputClock:(Outputs::Speaker::Speaker *)speaker;
|
||||
- (void)addLED:(NSString *)led;
|
||||
- (void)addLED:(NSString *)led isPersistent:(BOOL)isPersistent;
|
||||
@end
|
||||
|
||||
struct LockProtectedDelegate {
|
||||
@@ -61,8 +61,8 @@ struct SpeakerDelegate: public Outputs::Speaker::Speaker::Delegate, public LockP
|
||||
};
|
||||
|
||||
struct ActivityObserver: public Activity::Observer {
|
||||
void register_led(const std::string &name) final {
|
||||
[machine addLED:[NSString stringWithUTF8String:name.c_str()]];
|
||||
void register_led(const std::string &name, uint8_t flags) final {
|
||||
[machine addLED:[NSString stringWithUTF8String:name.c_str()] isPersistent:(flags & Activity::Observer::LEDPresentation::Persistent) ? YES : NO];
|
||||
}
|
||||
|
||||
void set_led_status(const std::string &name, bool lit) final {
|
||||
@@ -76,6 +76,19 @@ struct ActivityObserver: public Activity::Observer {
|
||||
__unsafe_unretained CSMachine *machine;
|
||||
};
|
||||
|
||||
@implementation CSMachineLED
|
||||
|
||||
- (instancetype)initWithName:(NSString *)name isPersistent:(BOOL)isPersistent {
|
||||
self = [super init];
|
||||
if(self) {
|
||||
_name = name;
|
||||
_isPersisent = isPersistent;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CSMachine {
|
||||
SpeakerDelegate _speakerDelegate;
|
||||
ActivityObserver _activityObserver;
|
||||
@@ -86,7 +99,7 @@ struct ActivityObserver: public Activity::Observer {
|
||||
MachineTypes::JoystickMachine *_joystickMachine;
|
||||
|
||||
CSJoystickManager *_joystickManager;
|
||||
NSMutableArray<NSString *> *_leds;
|
||||
NSMutableArray<CSMachineLED *> *_leds;
|
||||
|
||||
CSHighPrecisionTimer *_timer;
|
||||
std::atomic_flag _isUpdating;
|
||||
@@ -623,11 +636,11 @@ struct ActivityObserver: public Activity::Observer {
|
||||
|
||||
#pragma mark - Activity observation
|
||||
|
||||
- (void)addLED:(NSString *)led {
|
||||
[_leds addObject:led];
|
||||
- (void)addLED:(NSString *)led isPersistent:(BOOL)isPersistent {
|
||||
[_leds addObject:[[CSMachineLED alloc] initWithName:led isPersistent:isPersistent]];
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)leds {
|
||||
- (NSArray<CSMachineLED *> *)leds {
|
||||
return _leds;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,35 @@ typedef NS_ENUM(NSInteger, CSMachineCPCModel) {
|
||||
CSMachineCPCModel6128
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, CSMachineEnterpriseModel) {
|
||||
CSMachineEnterpriseModel64,
|
||||
CSMachineEnterpriseModel128,
|
||||
CSMachineEnterpriseModel256,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, CSMachineEnterpriseSpeed) {
|
||||
CSMachineEnterpriseSpeed4MHz,
|
||||
CSMachineEnterpriseSpeed6MHz
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, CSMachineEnterpriseEXOS) {
|
||||
CSMachineEnterpriseEXOSVersion21,
|
||||
CSMachineEnterpriseEXOSVersion20,
|
||||
CSMachineEnterpriseEXOSVersion10,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, CSMachineEnterpriseBASIC) {
|
||||
CSMachineEnterpriseBASICVersion21,
|
||||
CSMachineEnterpriseBASICVersion11,
|
||||
CSMachineEnterpriseBASICVersion10,
|
||||
CSMachineEnterpriseBASICNone,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, CSMachineEnterpriseDOS) {
|
||||
CSMachineEnterpriseDOSEXDOS,
|
||||
CSMachineEnterpriseDOSNone,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, CSMachineMacintoshModel) {
|
||||
CSMachineMacintoshModel128k,
|
||||
CSMachineMacintoshModel512k,
|
||||
@@ -96,6 +125,7 @@ typedef int Kilobytes;
|
||||
- (instancetype)initWithAppleIIgsModel:(CSMachineAppleIIgsModel)model memorySize:(Kilobytes)memorySize;
|
||||
- (instancetype)initWithAtariSTModel:(CSMachineAtariSTModel)model;
|
||||
- (instancetype)initWithElectronDFS:(BOOL)dfs adfs:(BOOL)adfs ap6:(BOOL)ap6 sidewaysRAM:(BOOL)sidewaysRAM;
|
||||
- (instancetype)initWithEnterpriseModel:(CSMachineEnterpriseModel)model speed:(CSMachineEnterpriseSpeed)speed exosVersion:(CSMachineEnterpriseEXOS)exosVersion basicVersion:(CSMachineEnterpriseBASIC)basicVersion dos:(CSMachineEnterpriseDOS)dos;
|
||||
- (instancetype)initWithMacintoshModel:(CSMachineMacintoshModel)model;
|
||||
- (instancetype)initWithMSXRegion:(CSMachineMSXRegion)region hasDiskDrive:(BOOL)hasDiskDrive;
|
||||
- (instancetype)initWithOricModel:(CSMachineOricModel)model diskInterface:(CSMachineOricDiskInterface)diskInterface;
|
||||
@@ -104,7 +134,7 @@ typedef int Kilobytes;
|
||||
- (instancetype)initWithZX80MemorySize:(Kilobytes)memorySize useZX81ROM:(BOOL)useZX81ROM;
|
||||
- (instancetype)initWithZX81MemorySize:(Kilobytes)memorySize;
|
||||
|
||||
@property(nonatomic, readonly, nullable) NSString *optionsPanelNibName;
|
||||
@property(nonatomic, readonly, nullable) NSString *optionsNibName;
|
||||
@property(nonatomic, readonly) NSString *displayName;
|
||||
|
||||
@end
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "../../../../../Analyser/Static/AppleIIgs/Target.hpp"
|
||||
#include "../../../../../Analyser/Static/AtariST/Target.hpp"
|
||||
#include "../../../../../Analyser/Static/Commodore/Target.hpp"
|
||||
#include "../../../../../Analyser/Static/Enterprise/Target.hpp"
|
||||
#include "../../../../../Analyser/Static/Macintosh/Target.hpp"
|
||||
#include "../../../../../Analyser/Static/MSX/Target.hpp"
|
||||
#include "../../../../../Analyser/Static/Oric/Target.hpp"
|
||||
@@ -130,6 +131,51 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithEnterpriseModel:(CSMachineEnterpriseModel)model speed:(CSMachineEnterpriseSpeed)speed exosVersion:(CSMachineEnterpriseEXOS)exosVersion basicVersion:(CSMachineEnterpriseBASIC)basicVersion dos:(CSMachineEnterpriseDOS)dos {
|
||||
self = [super init];
|
||||
if(self) {
|
||||
using Target = Analyser::Static::Enterprise::Target;
|
||||
auto target = std::make_unique<Target>();
|
||||
|
||||
switch(model) {
|
||||
case CSMachineEnterpriseModel64: target->model = Target::Model::Enterprise64; break;
|
||||
default:
|
||||
case CSMachineEnterpriseModel128: target->model = Target::Model::Enterprise128; break;
|
||||
case CSMachineEnterpriseModel256: target->model = Target::Model::Enterprise256; break;
|
||||
}
|
||||
|
||||
switch(speed) {
|
||||
case CSMachineEnterpriseSpeed6MHz: target->speed = Target::Speed::SixMHz; break;
|
||||
default:
|
||||
case CSMachineEnterpriseSpeed4MHz: target->speed = Target::Speed::FourMHz; break;
|
||||
}
|
||||
|
||||
switch(exosVersion) {
|
||||
case CSMachineEnterpriseEXOSVersion21: target->exos_version = Target::EXOSVersion::v21; break;
|
||||
default:
|
||||
case CSMachineEnterpriseEXOSVersion20: target->exos_version = Target::EXOSVersion::v20; break;
|
||||
case CSMachineEnterpriseEXOSVersion10: target->exos_version = Target::EXOSVersion::v10; break;
|
||||
}
|
||||
|
||||
switch(basicVersion) {
|
||||
case CSMachineEnterpriseBASICNone: target->basic_version = Target::BASICVersion::None; break;
|
||||
default:
|
||||
case CSMachineEnterpriseBASICVersion21: target->basic_version = Target::BASICVersion::v21; break;
|
||||
case CSMachineEnterpriseBASICVersion11: target->basic_version = Target::BASICVersion::v11; break;
|
||||
case CSMachineEnterpriseBASICVersion10: target->basic_version = Target::BASICVersion::v10; break;
|
||||
}
|
||||
|
||||
switch(dos) {
|
||||
case CSMachineEnterpriseDOSEXDOS: target->dos = Target::DOS::EXDOS; break;
|
||||
default:
|
||||
case CSMachineEnterpriseDOSNone: target->dos = Target::DOS::None; break;
|
||||
}
|
||||
|
||||
_targets.push_back(std::move(target));
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithMacintoshModel:(CSMachineMacintoshModel)model {
|
||||
self = [super init];
|
||||
if(self) {
|
||||
@@ -267,7 +313,7 @@ static Analyser::Static::ZX8081::Target::MemoryModel ZX8081MemoryModelFromSize(K
|
||||
|
||||
// MARK: - NIB mapping
|
||||
|
||||
- (NSString *)optionsPanelNibName {
|
||||
- (NSString *)optionsNibName {
|
||||
switch(_targets.front()->machine) {
|
||||
// case Analyser::Machine::AmstradCPC: return @"QuickLoadCompositeOptions";
|
||||
case Analyser::Machine::AmstradCPC: return @"CompositeOptions";
|
||||
@@ -276,6 +322,7 @@ static Analyser::Static::ZX8081::Target::MemoryModel ZX8081MemoryModelFromSize(K
|
||||
case Analyser::Machine::AtariST: return @"CompositeOptions";
|
||||
case Analyser::Machine::ColecoVision: return @"CompositeOptions";
|
||||
case Analyser::Machine::Electron: return @"QuickLoadCompositeOptions";
|
||||
case Analyser::Machine::Enterprise: return @"CompositeOptions";
|
||||
case Analyser::Machine::Macintosh: return @"MacintoshOptions";
|
||||
case Analyser::Machine::MasterSystem: return @"CompositeOptions";
|
||||
case Analyser::Machine::MSX: return @"QuickLoadCompositeOptions";
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17701"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
@@ -17,10 +17,10 @@
|
||||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="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="590" height="316"/>
|
||||
<rect key="contentRect" x="196" y="240" width="590" height="353"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1440"/>
|
||||
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="590" height="316"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="590" height="353"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hKn-1l-OSN">
|
||||
@@ -59,16 +59,16 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<tabView type="noTabsBezelBorder" translatesAutoresizingMaskIntoConstraints="NO" id="VUb-QG-x7c">
|
||||
<rect key="frame" x="154" y="56" width="420" height="206"/>
|
||||
<rect key="frame" x="154" y="56" width="420" height="243"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<tabViewItems>
|
||||
<tabViewItem label="Apple II" identifier="appleii" id="P59-QG-LOa">
|
||||
<view key="view" id="dHz-Yv-GNq">
|
||||
<rect key="frame" x="10" y="7" width="400" height="186"/>
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="V5Z-dX-Ns4">
|
||||
<rect key="frame" x="18" y="163" width="46" height="16"/>
|
||||
<rect key="frame" x="18" y="185" width="46" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model:" id="qV3-2P-3JW">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -76,7 +76,7 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WnO-ef-IC6">
|
||||
<rect key="frame" x="18" y="133" width="96" height="16"/>
|
||||
<rect key="frame" x="18" y="155" width="96" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Disk controller:" id="kbf-rc-Y4M">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -84,7 +84,7 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="jli-ac-Sij">
|
||||
<rect key="frame" x="67" y="157" width="117" height="25"/>
|
||||
<rect key="frame" x="67" y="179" width="117" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Apple II" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="VBQ-JG-AeM" id="U6V-us-O2F">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -99,7 +99,7 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="LSB-WP-FMi">
|
||||
<rect key="frame" x="117" y="127" width="134" height="25"/>
|
||||
<rect key="frame" x="117" y="149" width="134" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Sixteen Sector" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="16" imageScaling="axesIndependently" inset="2" selectedItem="QaV-Yr-k9o" id="8BT-RV-2Nm">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -115,11 +115,11 @@ Gw
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="WnO-ef-IC6" firstAttribute="leading" secondItem="dHz-Yv-GNq" secondAttribute="leading" constant="20" symbolic="YES" id="5RF-1w-9HW"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="LSB-WP-FMi" secondAttribute="bottom" constant="5" id="865-cv-qVk"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="LSB-WP-FMi" secondAttribute="bottom" constant="20" symbolic="YES" id="865-cv-qVk"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="LSB-WP-FMi" secondAttribute="trailing" constant="20" symbolic="YES" id="9GL-al-1qi"/>
|
||||
<constraint firstItem="WnO-ef-IC6" firstAttribute="centerY" secondItem="LSB-WP-FMi" secondAttribute="centerY" id="Fuj-zT-MIm"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="jli-ac-Sij" secondAttribute="trailing" constant="20" symbolic="YES" id="I8d-OR-ICN"/>
|
||||
<constraint firstItem="jli-ac-Sij" firstAttribute="top" secondItem="dHz-Yv-GNq" secondAttribute="top" constant="5" id="Qi1-CV-A0c"/>
|
||||
<constraint firstItem="jli-ac-Sij" firstAttribute="top" secondItem="dHz-Yv-GNq" secondAttribute="top" constant="20" symbolic="YES" id="Qi1-CV-A0c"/>
|
||||
<constraint firstItem="V5Z-dX-Ns4" firstAttribute="leading" secondItem="dHz-Yv-GNq" secondAttribute="leading" constant="20" symbolic="YES" id="SWc-iX-1We"/>
|
||||
<constraint firstItem="LSB-WP-FMi" firstAttribute="leading" secondItem="WnO-ef-IC6" secondAttribute="trailing" constant="8" symbolic="YES" id="bte-XA-xNQ"/>
|
||||
<constraint firstItem="LSB-WP-FMi" firstAttribute="top" secondItem="jli-ac-Sij" secondAttribute="bottom" constant="10" symbolic="YES" id="ki5-JR-vRe"/>
|
||||
@@ -129,12 +129,12 @@ Gw
|
||||
</view>
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Apple IIgs" identifier="appleiigs" id="u5E-8n-ghF">
|
||||
<view key="view" ambiguous="YES" id="jOM-9f-vkk">
|
||||
<rect key="frame" x="10" y="7" width="400" height="76"/>
|
||||
<view key="view" id="jOM-9f-vkk">
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0d9-IG-gKU">
|
||||
<rect key="frame" x="18" y="53" width="46" height="16"/>
|
||||
<rect key="frame" x="18" y="185" width="46" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model:" id="kiv-1P-FWc">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -142,7 +142,7 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="LES-76-Ovz">
|
||||
<rect key="frame" x="18" y="23" width="85" height="16"/>
|
||||
<rect key="frame" x="18" y="155" width="85" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Memory size:" id="OLJ-nC-yyj">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -150,7 +150,7 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gcS-uy-mzl">
|
||||
<rect key="frame" x="67" y="47" width="89" height="25"/>
|
||||
<rect key="frame" x="67" y="179" width="89" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="ROM 03" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="2" imageScaling="axesIndependently" inset="2" selectedItem="0TS-DO-O9h" id="hjw-g8-e2f">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -164,7 +164,7 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nQa-YS-utT">
|
||||
<rect key="frame" x="106" y="17" width="82" height="25"/>
|
||||
<rect key="frame" x="106" y="149" width="82" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="8 mb" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="8192" imageScaling="axesIndependently" inset="2" selectedItem="UHg-gU-Xnn" id="dl3-cq-uWO">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -182,24 +182,24 @@ Gw
|
||||
<constraint firstItem="LES-76-Ovz" firstAttribute="leading" secondItem="jOM-9f-vkk" secondAttribute="leading" constant="20" symbolic="YES" id="2D3-Ve-6CN"/>
|
||||
<constraint firstItem="0d9-IG-gKU" firstAttribute="leading" secondItem="jOM-9f-vkk" secondAttribute="leading" constant="20" symbolic="YES" id="8Xz-86-tDf"/>
|
||||
<constraint firstItem="0d9-IG-gKU" firstAttribute="centerY" secondItem="gcS-uy-mzl" secondAttribute="centerY" id="Eww-Qq-eBT"/>
|
||||
<constraint firstItem="gcS-uy-mzl" firstAttribute="top" secondItem="jOM-9f-vkk" secondAttribute="top" constant="5" id="F6i-cP-7AR"/>
|
||||
<constraint firstItem="gcS-uy-mzl" firstAttribute="top" secondItem="jOM-9f-vkk" secondAttribute="top" constant="20" symbolic="YES" id="F6i-cP-7AR"/>
|
||||
<constraint firstItem="gcS-uy-mzl" firstAttribute="leading" secondItem="0d9-IG-gKU" secondAttribute="trailing" constant="8" symbolic="YES" id="LUm-rI-LYP"/>
|
||||
<constraint firstItem="LES-76-Ovz" firstAttribute="centerY" secondItem="nQa-YS-utT" secondAttribute="centerY" id="UdP-U6-OFE"/>
|
||||
<constraint firstItem="nQa-YS-utT" firstAttribute="leading" secondItem="LES-76-Ovz" secondAttribute="trailing" constant="8" symbolic="YES" id="Xm1-iG-Dgj"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="gcS-uy-mzl" secondAttribute="trailing" constant="20" symbolic="YES" id="a38-Cx-CEh"/>
|
||||
<constraint firstItem="nQa-YS-utT" firstAttribute="top" secondItem="gcS-uy-mzl" secondAttribute="bottom" constant="10" symbolic="YES" id="aM9-m8-s7z"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="nQa-YS-utT" secondAttribute="trailing" constant="20" symbolic="YES" id="cqx-Jc-rUb"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="nQa-YS-utT" secondAttribute="bottom" constant="5" id="sbT-If-NTU"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="nQa-YS-utT" secondAttribute="bottom" constant="20" symbolic="YES" id="sbT-If-NTU"/>
|
||||
</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="7" width="400" height="76"/>
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="00d-sg-Krh">
|
||||
<rect key="frame" x="67" y="47" width="96" height="25"/>
|
||||
<rect key="frame" x="67" y="179" width="96" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="CPC6128" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="6128" imageScaling="axesIndependently" inset="2" selectedItem="klh-ZE-Agp" id="hVJ-h6-iea">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -213,7 +213,7 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="q9q-sl-J0q">
|
||||
<rect key="frame" x="18" y="53" width="46" height="16"/>
|
||||
<rect key="frame" x="18" y="185" width="46" height="16"/>
|
||||
<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"/>
|
||||
@@ -224,8 +224,8 @@ Gw
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="00d-sg-Krh" secondAttribute="trailing" constant="20" symbolic="YES" id="4AF-5C-2IF"/>
|
||||
<constraint firstItem="q9q-sl-J0q" firstAttribute="leading" secondItem="5zS-Nj-Ynx" secondAttribute="leading" constant="20" symbolic="YES" id="Wof-5h-gfD"/>
|
||||
<constraint firstItem="00d-sg-Krh" firstAttribute="top" secondItem="5zS-Nj-Ynx" secondAttribute="top" constant="5" id="c92-uU-NRr"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="00d-sg-Krh" secondAttribute="bottom" constant="5" id="enU-LN-Nep"/>
|
||||
<constraint firstItem="00d-sg-Krh" firstAttribute="top" secondItem="5zS-Nj-Ynx" secondAttribute="top" constant="20" symbolic="YES" id="c92-uU-NRr"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="00d-sg-Krh" secondAttribute="bottom" constant="20" symbolic="YES" id="enU-LN-Nep"/>
|
||||
<constraint firstItem="00d-sg-Krh" firstAttribute="leading" secondItem="q9q-sl-J0q" secondAttribute="trailing" constant="8" symbolic="YES" id="mA8-US-ndo"/>
|
||||
<constraint firstItem="q9q-sl-J0q" firstAttribute="centerY" secondItem="00d-sg-Krh" secondAttribute="centerY" id="vA8-IA-Uwf"/>
|
||||
</constraints>
|
||||
@@ -233,11 +233,11 @@ Gw
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Atari ST" identifier="atarist" id="a6Y-mx-yFn">
|
||||
<view key="view" id="nnv-Wi-7hc">
|
||||
<rect key="frame" x="10" y="7" width="400" height="76"/>
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nLf-LI-nWO">
|
||||
<rect key="frame" x="18" y="57" width="728" height="16"/>
|
||||
<rect key="frame" x="18" y="187" width="364" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="At present only a 512k Atari ST is supported." id="gBA-ke-mur">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -247,39 +247,39 @@ Gw
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="nLf-LI-nWO" firstAttribute="leading" secondItem="nnv-Wi-7hc" secondAttribute="leading" constant="20" symbolic="YES" id="EIm-9Q-Rcj"/>
|
||||
<constraint firstItem="nLf-LI-nWO" firstAttribute="top" secondItem="nnv-Wi-7hc" secondAttribute="top" constant="3" id="f9w-Lj-5dn"/>
|
||||
<constraint firstItem="nLf-LI-nWO" firstAttribute="top" secondItem="nnv-Wi-7hc" secondAttribute="top" constant="20" symbolic="YES" id="f9w-Lj-5dn"/>
|
||||
<constraint firstAttribute="trailing" secondItem="nLf-LI-nWO" secondAttribute="trailing" constant="20" symbolic="YES" id="m3L-Nx-Aqz"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Electron" identifier="electron" id="muc-z9-Vqc">
|
||||
<view key="view" id="SRc-2D-95G">
|
||||
<rect key="frame" x="10" y="7" width="400" height="76"/>
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JqM-IK-FMP">
|
||||
<rect key="frame" x="18" y="56" width="168" height="18"/>
|
||||
<rect key="frame" x="18" y="186" width="168" 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="18" y="34" width="232" height="18"/>
|
||||
<rect key="frame" x="18" y="164" width="232" 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>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="cG2-Ph-S3Z">
|
||||
<rect key="frame" x="18" y="12" width="231" height="18"/>
|
||||
<rect key="frame" x="18" y="142" width="231" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="With Advanced Plus 6 Utility ROM" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="yjF-XS-zx6">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lzo-8g-o4S">
|
||||
<rect key="frame" x="18" y="-10" width="284" height="18"/>
|
||||
<rect key="frame" x="18" y="120" width="284" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="Fill unused ROM banks with sideways RAM" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="JEz-eK-uWp">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
@@ -289,13 +289,13 @@ Gw
|
||||
<constraints>
|
||||
<constraint firstItem="945-wU-JOH" firstAttribute="leading" secondItem="SRc-2D-95G" secondAttribute="leading" constant="20" symbolic="YES" id="1iM-70-oZq"/>
|
||||
<constraint firstItem="cG2-Ph-S3Z" firstAttribute="top" secondItem="945-wU-JOH" secondAttribute="bottom" constant="6" symbolic="YES" id="E9b-RP-9vj"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="lzo-8g-o4S" secondAttribute="bottom" constant="5" id="FM6-AA-Vhf"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="lzo-8g-o4S" secondAttribute="bottom" constant="20" symbolic="YES" id="FM6-AA-Vhf"/>
|
||||
<constraint firstItem="JqM-IK-FMP" firstAttribute="leading" secondItem="SRc-2D-95G" secondAttribute="leading" constant="20" symbolic="YES" id="NfY-dE-aJw"/>
|
||||
<constraint firstItem="lzo-8g-o4S" firstAttribute="top" secondItem="cG2-Ph-S3Z" secondAttribute="bottom" constant="6" symbolic="YES" id="S45-42-Gtv"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="lzo-8g-o4S" secondAttribute="trailing" constant="20" symbolic="YES" id="X3p-qJ-ENH"/>
|
||||
<constraint firstItem="lzo-8g-o4S" firstAttribute="leading" secondItem="SRc-2D-95G" secondAttribute="leading" constant="20" symbolic="YES" id="b5a-SX-2ty"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="945-wU-JOH" secondAttribute="trailing" constant="20" symbolic="YES" id="dmY-PV-ap4"/>
|
||||
<constraint firstItem="JqM-IK-FMP" firstAttribute="top" secondItem="SRc-2D-95G" secondAttribute="top" constant="3" id="ggl-QH-mV4"/>
|
||||
<constraint firstItem="JqM-IK-FMP" firstAttribute="top" secondItem="SRc-2D-95G" secondAttribute="top" constant="20" symbolic="YES" id="ggl-QH-mV4"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="cG2-Ph-S3Z" secondAttribute="trailing" constant="20" symbolic="YES" id="m6t-dP-71d"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="JqM-IK-FMP" secondAttribute="trailing" constant="20" symbolic="YES" id="mvO-UZ-BtT"/>
|
||||
<constraint firstItem="cG2-Ph-S3Z" firstAttribute="leading" secondItem="SRc-2D-95G" secondAttribute="leading" constant="20" symbolic="YES" id="npw-IZ-6xU"/>
|
||||
@@ -303,13 +303,159 @@ Gw
|
||||
</constraints>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Enterprise" identifier="enterprise" id="zhO-EO-wUe">
|
||||
<view key="view" id="1cs-PX-RAH">
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="PhH-bu-pb5">
|
||||
<rect key="frame" x="80" y="179" width="129" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Enterprise 128" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="128" imageScaling="axesIndependently" inset="2" selectedItem="roH-nL-f8o" id="z9O-XC-XBv">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="ojI-Vb-iHz">
|
||||
<items>
|
||||
<menuItem title="Enterprise 256" tag="256" id="Al3-A0-tvw"/>
|
||||
<menuItem title="Enterprise 128" state="on" tag="128" id="roH-nL-f8o"/>
|
||||
<menuItem title="Enterprise 64" tag="64" id="vNG-Tv-bDI"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Lfl-5c-b8j">
|
||||
<rect key="frame" x="67" y="149" width="77" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="4 Mhz" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="4" imageScaling="axesIndependently" inset="2" selectedItem="5N6-tD-uN7" id="BU2-NJ-Kii">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="ANK-p0-M77">
|
||||
<items>
|
||||
<menuItem title="4 Mhz" state="on" tag="4" id="5N6-tD-uN7"/>
|
||||
<menuItem title="6 Mhz" tag="6" id="bVT-qO-U7n"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nen-Za-7zH">
|
||||
<rect key="frame" x="64" y="119" width="107" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Version 2.1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="21" imageScaling="axesIndependently" inset="2" selectedItem="Qja-xZ-wVM" id="xGG-ri-8Sb">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="uNC-hA-d5z">
|
||||
<items>
|
||||
<menuItem title="Version 2.1" state="on" tag="21" id="Qja-xZ-wVM"/>
|
||||
<menuItem title="Version 2.0" tag="20" id="XTj-l7-KX3"/>
|
||||
<menuItem title="Version 1.0" tag="10" id="Ky2-2D-wcY"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hIr-GH-7xi">
|
||||
<rect key="frame" x="67" y="89" width="105" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Version 2.1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="21" imageScaling="axesIndependently" inset="2" selectedItem="TME-cv-Jh1" id="9mQ-GW-lq9">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="VcH-Xm-1hY">
|
||||
<items>
|
||||
<menuItem title="Version 2.1" state="on" tag="21" id="TME-cv-Jh1"/>
|
||||
<menuItem title="Version 1.1" tag="11" id="7P2-aF-6fp"/>
|
||||
<menuItem title="Version 1.0" tag="10" id="j8p-uY-BhG"/>
|
||||
<menuItem title="None" id="eGk-Bj-IVT"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="syE-e7-TjU">
|
||||
<rect key="frame" x="57" y="59" width="83" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="EXDOS" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="1" imageScaling="axesIndependently" inset="2" selectedItem="8rP-2w-PdU" id="NvO-Zm-2Rq">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" title="DOS" id="sdr-al-7mi">
|
||||
<items>
|
||||
<menuItem title="EXDOS" state="on" tag="1" id="8rP-2w-PdU"/>
|
||||
<menuItem title="None" id="qoS-KO-iEZ"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ykc-W1-YaS">
|
||||
<rect key="frame" x="18" y="125" width="43" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="EXOS:" id="gUC-PN-zVL">
|
||||
<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="frx-nk-c3P">
|
||||
<rect key="frame" x="18" y="185" width="59" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Machine:" id="uTv-hH-mIC">
|
||||
<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="dzd-tH-BjX">
|
||||
<rect key="frame" x="18" y="95" width="46" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="BASIC:" id="ai1-oR-X6Y">
|
||||
<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="pxr-Bq-yh0">
|
||||
<rect key="frame" x="18" y="65" width="36" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="DOS:" id="NFk-cp-DfS">
|
||||
<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="rHr-bh-QMV">
|
||||
<rect key="frame" x="17" y="155" width="47" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Speed:" id="sAw-C9-Sf7">
|
||||
<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="dzd-tH-BjX" firstAttribute="centerY" secondItem="hIr-GH-7xi" secondAttribute="centerY" id="3TV-RU-Kgh"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="hIr-GH-7xi" secondAttribute="trailing" constant="20" symbolic="YES" id="44v-9O-y7L"/>
|
||||
<constraint firstItem="frx-nk-c3P" firstAttribute="centerY" secondItem="PhH-bu-pb5" secondAttribute="centerY" id="6Wc-aR-wuL"/>
|
||||
<constraint firstItem="dzd-tH-BjX" firstAttribute="leading" secondItem="1cs-PX-RAH" secondAttribute="leading" constant="20" symbolic="YES" id="7RZ-Om-TAa"/>
|
||||
<constraint firstItem="ykc-W1-YaS" firstAttribute="centerY" secondItem="nen-Za-7zH" secondAttribute="centerY" id="CLa-6E-8BB"/>
|
||||
<constraint firstItem="nen-Za-7zH" firstAttribute="top" secondItem="Lfl-5c-b8j" secondAttribute="bottom" constant="10" symbolic="YES" id="Df8-qv-3dY"/>
|
||||
<constraint firstItem="PhH-bu-pb5" firstAttribute="leading" secondItem="frx-nk-c3P" secondAttribute="trailing" constant="8" symbolic="YES" id="ENF-TY-TQ7"/>
|
||||
<constraint firstItem="nen-Za-7zH" firstAttribute="leading" secondItem="ykc-W1-YaS" secondAttribute="trailing" constant="8" symbolic="YES" id="GWR-VI-9PG"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="syE-e7-TjU" secondAttribute="bottom" constant="20" symbolic="YES" id="K3s-FA-zMB"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="PhH-bu-pb5" secondAttribute="trailing" constant="20" symbolic="YES" id="LwB-ef-uF4"/>
|
||||
<constraint firstItem="PhH-bu-pb5" firstAttribute="top" secondItem="1cs-PX-RAH" secondAttribute="top" constant="20" symbolic="YES" id="Myt-i4-jVq"/>
|
||||
<constraint firstItem="Lfl-5c-b8j" firstAttribute="top" secondItem="PhH-bu-pb5" secondAttribute="bottom" constant="10" symbolic="YES" id="Nl3-hL-jwg"/>
|
||||
<constraint firstItem="pxr-Bq-yh0" firstAttribute="leading" secondItem="1cs-PX-RAH" secondAttribute="leading" constant="20" symbolic="YES" id="Qzp-IY-Pa0"/>
|
||||
<constraint firstItem="PhH-bu-pb5" firstAttribute="leading" secondItem="frx-nk-c3P" secondAttribute="trailing" constant="8" symbolic="YES" id="T3e-u7-fiQ"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="syE-e7-TjU" secondAttribute="trailing" constant="20" symbolic="YES" id="TEX-Nw-y2K"/>
|
||||
<constraint firstItem="frx-nk-c3P" firstAttribute="leading" secondItem="1cs-PX-RAH" secondAttribute="leading" constant="20" symbolic="YES" id="TgR-RR-eA1"/>
|
||||
<constraint firstItem="pxr-Bq-yh0" firstAttribute="centerY" secondItem="syE-e7-TjU" secondAttribute="centerY" id="UYw-uz-Am0"/>
|
||||
<constraint firstItem="hIr-GH-7xi" firstAttribute="top" secondItem="nen-Za-7zH" secondAttribute="bottom" constant="10" symbolic="YES" id="VOc-2v-s3u"/>
|
||||
<constraint firstItem="syE-e7-TjU" firstAttribute="top" secondItem="hIr-GH-7xi" secondAttribute="bottom" constant="10" symbolic="YES" id="W9S-on-Heq"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Lfl-5c-b8j" secondAttribute="trailing" constant="20" symbolic="YES" id="WQi-pe-tXt"/>
|
||||
<constraint firstItem="rHr-bh-QMV" firstAttribute="leading" secondItem="1cs-PX-RAH" secondAttribute="leading" constant="19" id="XZf-lB-NnA"/>
|
||||
<constraint firstItem="ykc-W1-YaS" firstAttribute="leading" secondItem="1cs-PX-RAH" secondAttribute="leading" constant="20" symbolic="YES" id="bAP-lx-pdi"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="nen-Za-7zH" secondAttribute="trailing" constant="20" symbolic="YES" id="eEI-5Q-TnO"/>
|
||||
<constraint firstItem="syE-e7-TjU" firstAttribute="leading" secondItem="pxr-Bq-yh0" secondAttribute="trailing" constant="8" symbolic="YES" id="fmM-Ma-Jyu"/>
|
||||
<constraint firstItem="hIr-GH-7xi" firstAttribute="leading" secondItem="dzd-tH-BjX" secondAttribute="trailing" constant="8" symbolic="YES" id="jDQ-TF-Ogf"/>
|
||||
<constraint firstItem="rHr-bh-QMV" firstAttribute="centerY" secondItem="Lfl-5c-b8j" secondAttribute="centerY" id="mnp-JF-dVQ"/>
|
||||
<constraint firstItem="Lfl-5c-b8j" firstAttribute="leading" secondItem="rHr-bh-QMV" secondAttribute="trailing" constant="8" symbolic="YES" id="yfb-SL-v1H"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Macintosh" identifier="mac" id="lmR-z3-xSm">
|
||||
<view key="view" id="7Yf-vi-Q0W">
|
||||
<rect key="frame" x="10" y="7" width="400" height="76"/>
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZOY-4E-Cfl">
|
||||
<rect key="frame" x="18" y="53" width="46" height="16"/>
|
||||
<rect key="frame" x="18" y="185" width="46" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model:" id="h9r-i6-66j">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -317,7 +463,7 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xa6-NA-JY5">
|
||||
<rect key="frame" x="67" y="47" width="75" height="25"/>
|
||||
<rect key="frame" x="67" y="179" width="75" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Plus" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="3" imageScaling="axesIndependently" inset="2" selectedItem="R6T-hg-rOF" id="1Kb-Q2-BGM">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -333,9 +479,9 @@ Gw
|
||||
</popUpButton>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="xa6-NA-JY5" firstAttribute="top" secondItem="7Yf-vi-Q0W" secondAttribute="top" constant="5" id="3hY-Ca-mnR"/>
|
||||
<constraint firstItem="xa6-NA-JY5" firstAttribute="top" secondItem="7Yf-vi-Q0W" secondAttribute="top" constant="20" symbolic="YES" id="3hY-Ca-mnR"/>
|
||||
<constraint firstItem="ZOY-4E-Cfl" firstAttribute="leading" secondItem="7Yf-vi-Q0W" secondAttribute="leading" constant="20" symbolic="YES" id="5s6-87-VT6"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="xa6-NA-JY5" secondAttribute="bottom" constant="5" id="KYf-GJ-Y7k"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="xa6-NA-JY5" secondAttribute="bottom" constant="20" symbolic="YES" id="KYf-GJ-Y7k"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="xa6-NA-JY5" secondAttribute="trailing" constant="20" symbolic="YES" id="LZ5-xH-fU0"/>
|
||||
<constraint firstItem="ZOY-4E-Cfl" firstAttribute="centerY" secondItem="xa6-NA-JY5" secondAttribute="centerY" id="Wa5-KX-3Me"/>
|
||||
<constraint firstItem="xa6-NA-JY5" firstAttribute="leading" secondItem="ZOY-4E-Cfl" secondAttribute="trailing" constant="8" symbolic="YES" id="ktS-sr-F8L"/>
|
||||
@@ -344,18 +490,18 @@ Gw
|
||||
</tabViewItem>
|
||||
<tabViewItem label="MSX" identifier="msx" id="6SR-DY-zdI">
|
||||
<view key="view" id="mWD-An-tR7">
|
||||
<rect key="frame" x="10" y="7" width="400" height="76"/>
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8xT-Pr-8SE">
|
||||
<rect key="frame" x="18" y="26" width="128" height="18"/>
|
||||
<rect key="frame" x="18" y="158" width="128" 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>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="LG6-mP-SeG">
|
||||
<rect key="frame" x="71" y="47" width="146" height="25"/>
|
||||
<rect key="frame" x="71" y="179" width="146" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="European (PAL)" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="xAh-Ch-tby" id="yR4-yv-Lvu">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -369,7 +515,7 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZaD-7v-rMS">
|
||||
<rect key="frame" x="18" y="53" width="50" height="16"/>
|
||||
<rect key="frame" x="18" y="185" width="50" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Region:" id="x4m-eh-Nif">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -380,9 +526,9 @@ Gw
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="LG6-mP-SeG" secondAttribute="trailing" constant="20" symbolic="YES" id="0Oc-n7-gaM"/>
|
||||
<constraint firstItem="8xT-Pr-8SE" firstAttribute="top" secondItem="LG6-mP-SeG" secondAttribute="bottom" constant="8" symbolic="YES" id="LBt-4m-GDc"/>
|
||||
<constraint firstItem="LG6-mP-SeG" firstAttribute="top" secondItem="mWD-An-tR7" secondAttribute="top" constant="5" id="bcb-ZZ-VpQ"/>
|
||||
<constraint firstItem="LG6-mP-SeG" firstAttribute="top" secondItem="mWD-An-tR7" secondAttribute="top" constant="20" symbolic="YES" id="bcb-ZZ-VpQ"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="8xT-Pr-8SE" secondAttribute="trailing" constant="20" symbolic="YES" id="l8P-UW-8ig"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="8xT-Pr-8SE" secondAttribute="bottom" constant="3" id="mga-YX-Bek"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="8xT-Pr-8SE" secondAttribute="bottom" constant="20" symbolic="YES" id="mga-YX-Bek"/>
|
||||
<constraint firstItem="8xT-Pr-8SE" firstAttribute="leading" secondItem="mWD-An-tR7" secondAttribute="leading" constant="20" symbolic="YES" id="q8Q-kh-Opj"/>
|
||||
<constraint firstItem="LG6-mP-SeG" firstAttribute="leading" secondItem="ZaD-7v-rMS" secondAttribute="trailing" constant="8" symbolic="YES" id="svb-nH-GlP"/>
|
||||
<constraint firstItem="ZaD-7v-rMS" firstAttribute="leading" secondItem="mWD-An-tR7" secondAttribute="leading" constant="20" symbolic="YES" id="zgh-a5-FNF"/>
|
||||
@@ -392,11 +538,11 @@ Gw
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Oric" identifier="oric" id="NSx-DC-p4M">
|
||||
<view key="view" id="sOR-e0-8iZ">
|
||||
<rect key="frame" x="10" y="7" width="400" height="76"/>
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0ct-tf-uRH">
|
||||
<rect key="frame" x="18" y="53" width="46" height="16"/>
|
||||
<rect key="frame" x="18" y="185" width="46" height="16"/>
|
||||
<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"/>
|
||||
@@ -404,7 +550,7 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ENP-hI-BVZ">
|
||||
<rect key="frame" x="67" y="47" width="107" height="25"/>
|
||||
<rect key="frame" x="67" y="179" width="107" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Oric-1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="jGN-1a-biF" id="Jll-EJ-cMr">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -418,7 +564,7 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="fYL-p6-wyn">
|
||||
<rect key="frame" x="113" y="17" width="130" height="25"/>
|
||||
<rect key="frame" x="113" y="149" width="130" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="None" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="XhK-Jh-oTW" id="aYb-m1-H9X">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -434,7 +580,7 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="okM-ZI-NbF">
|
||||
<rect key="frame" x="18" y="23" width="92" height="16"/>
|
||||
<rect key="frame" x="18" y="155" width="92" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Disk interface:" id="SFK-hS-tFC">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -443,7 +589,7 @@ Gw
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="ENP-hI-BVZ" firstAttribute="top" secondItem="sOR-e0-8iZ" secondAttribute="top" constant="5" id="Bgq-8R-8I4"/>
|
||||
<constraint firstItem="ENP-hI-BVZ" firstAttribute="top" secondItem="sOR-e0-8iZ" secondAttribute="top" constant="20" symbolic="YES" id="Bgq-8R-8I4"/>
|
||||
<constraint firstItem="fYL-p6-wyn" firstAttribute="leading" secondItem="okM-ZI-NbF" secondAttribute="trailing" constant="8" symbolic="YES" id="Pra-lC-JPB"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="ENP-hI-BVZ" secondAttribute="trailing" constant="20" symbolic="YES" id="Sr5-QZ-xU3"/>
|
||||
<constraint firstItem="ENP-hI-BVZ" firstAttribute="leading" secondItem="0ct-tf-uRH" secondAttribute="trailing" constant="8" symbolic="YES" id="Wcg-1P-z6l"/>
|
||||
@@ -453,17 +599,17 @@ Gw
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="fYL-p6-wyn" secondAttribute="trailing" constant="20" symbolic="YES" id="ewV-Dw-zj2"/>
|
||||
<constraint firstItem="0ct-tf-uRH" firstAttribute="leading" secondItem="sOR-e0-8iZ" secondAttribute="leading" constant="20" symbolic="YES" id="huH-9L-97Y"/>
|
||||
<constraint firstItem="fYL-p6-wyn" firstAttribute="top" secondItem="ENP-hI-BVZ" secondAttribute="bottom" constant="10" symbolic="YES" id="l3T-Ve-0Jw"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="fYL-p6-wyn" secondAttribute="bottom" constant="5" id="mN9-AZ-wSn"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="fYL-p6-wyn" secondAttribute="bottom" constant="20" symbolic="YES" id="mN9-AZ-wSn"/>
|
||||
</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="7" width="400" height="76"/>
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ueK-gq-gaF">
|
||||
<rect key="frame" x="71" y="47" width="146" height="25"/>
|
||||
<rect key="frame" x="71" y="179" width="146" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="European (PAL)" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="45i-0n-gau" id="yi7-eo-I0q">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -479,7 +625,7 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2eV-Us-eEv">
|
||||
<rect key="frame" x="108" y="17" width="116" height="25"/>
|
||||
<rect key="frame" x="108" y="149" width="116" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="fOl-8Q-fsA" id="rH0-7T-pJE">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -493,7 +639,7 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MTh-9p-FqC">
|
||||
<rect key="frame" x="18" y="53" width="50" height="16"/>
|
||||
<rect key="frame" x="18" y="185" width="50" height="16"/>
|
||||
<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"/>
|
||||
@@ -501,7 +647,7 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gRS-DK-rIy">
|
||||
<rect key="frame" x="18" y="23" width="87" height="16"/>
|
||||
<rect key="frame" x="18" y="155" width="87" height="16"/>
|
||||
<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"/>
|
||||
@@ -509,7 +655,7 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Lrf-gL-6EI">
|
||||
<rect key="frame" x="18" y="-4" width="177" height="18"/>
|
||||
<rect key="frame" x="18" y="128" width="177" 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"/>
|
||||
@@ -521,7 +667,7 @@ Gw
|
||||
<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" symbolic="YES" id="9m6-6j-8j2"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Lrf-gL-6EI" secondAttribute="trailing" constant="20" symbolic="YES" id="M08-mP-Plz"/>
|
||||
<constraint firstItem="ueK-gq-gaF" firstAttribute="top" secondItem="fLI-XB-QCr" secondAttribute="top" constant="5" id="XN3-GK-BX9"/>
|
||||
<constraint firstItem="ueK-gq-gaF" firstAttribute="top" secondItem="fLI-XB-QCr" secondAttribute="top" constant="20" symbolic="YES" id="XN3-GK-BX9"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="ueK-gq-gaF" secondAttribute="trailing" constant="20" symbolic="YES" id="YZ9-7N-ssA"/>
|
||||
<constraint firstItem="MTh-9p-FqC" firstAttribute="leading" secondItem="fLI-XB-QCr" secondAttribute="leading" constant="20" symbolic="YES" id="bgZ-k9-IQC"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="2eV-Us-eEv" secondAttribute="trailing" constant="20" symbolic="YES" id="eiB-vH-17d"/>
|
||||
@@ -529,18 +675,18 @@ Gw
|
||||
<constraint firstItem="2eV-Us-eEv" firstAttribute="leading" secondItem="gRS-DK-rIy" secondAttribute="trailing" constant="8" symbolic="YES" id="hQ9-uy-KHg"/>
|
||||
<constraint firstItem="gRS-DK-rIy" firstAttribute="leading" secondItem="fLI-XB-QCr" secondAttribute="leading" constant="20" symbolic="YES" 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="3" id="vNb-Sw-Mxw"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="Lrf-gL-6EI" secondAttribute="bottom" constant="20" symbolic="YES" id="vNb-Sw-Mxw"/>
|
||||
<constraint firstItem="Lrf-gL-6EI" firstAttribute="top" secondItem="2eV-Us-eEv" secondAttribute="bottom" constant="8" symbolic="YES" 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="7" width="400" height="76"/>
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="I1a-Eu-5UB">
|
||||
<rect key="frame" x="108" y="47" width="116" height="25"/>
|
||||
<rect key="frame" x="108" y="179" width="116" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="4Sa-jR-xOd" id="B8M-do-Yod">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -554,7 +700,7 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="NCX-4e-lSu">
|
||||
<rect key="frame" x="18" y="53" width="87" height="16"/>
|
||||
<rect key="frame" x="18" y="185" width="87" height="16"/>
|
||||
<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"/>
|
||||
@@ -562,7 +708,7 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ReP-bV-Thu">
|
||||
<rect key="frame" x="18" y="26" width="118" height="18"/>
|
||||
<rect key="frame" x="18" y="158" width="118" 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"/>
|
||||
@@ -574,8 +720,8 @@ Gw
|
||||
<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" symbolic="YES" id="Bu6-60-74x"/>
|
||||
<constraint firstItem="NCX-4e-lSu" firstAttribute="leading" secondItem="8hL-Vn-Hg0" secondAttribute="leading" constant="20" symbolic="YES" id="W09-iG-ARI"/>
|
||||
<constraint firstItem="I1a-Eu-5UB" firstAttribute="top" secondItem="8hL-Vn-Hg0" secondAttribute="top" constant="5" id="fkf-wO-Q8i"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="ReP-bV-Thu" secondAttribute="bottom" constant="3" id="fmT-7E-hUT"/>
|
||||
<constraint firstItem="I1a-Eu-5UB" firstAttribute="top" secondItem="8hL-Vn-Hg0" secondAttribute="top" constant="20" symbolic="YES" id="fkf-wO-Q8i"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="ReP-bV-Thu" secondAttribute="bottom" constant="20" symbolic="YES" id="fmT-7E-hUT"/>
|
||||
<constraint firstItem="ReP-bV-Thu" firstAttribute="top" secondItem="I1a-Eu-5UB" secondAttribute="bottom" constant="8" symbolic="YES" id="hYk-xC-63o"/>
|
||||
<constraint firstItem="ReP-bV-Thu" firstAttribute="leading" secondItem="8hL-Vn-Hg0" secondAttribute="leading" constant="20" symbolic="YES" id="qen-KS-rWi"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="ReP-bV-Thu" secondAttribute="trailing" constant="20" symbolic="YES" id="r7F-DT-oRc"/>
|
||||
@@ -584,11 +730,11 @@ Gw
|
||||
</tabViewItem>
|
||||
<tabViewItem label="ZX81" identifier="zx81" id="Wnn-nQ-gZ6">
|
||||
<view key="view" id="bmd-gL-gzT">
|
||||
<rect key="frame" x="10" y="7" width="400" height="186"/>
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5aO-UX-HnX">
|
||||
<rect key="frame" x="108" y="157" width="116" height="25"/>
|
||||
<rect key="frame" x="108" y="179" width="116" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="axesIndependently" inset="2" selectedItem="7QC-Ij-hES" id="d3W-Gl-3Mf">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
@@ -602,7 +748,7 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8tU-73-XEE">
|
||||
<rect key="frame" x="18" y="163" width="87" height="16"/>
|
||||
<rect key="frame" x="18" y="185" width="87" height="16"/>
|
||||
<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"/>
|
||||
@@ -613,37 +759,37 @@ Gw
|
||||
<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="20" symbolic="YES" id="ALj-0x-bFb"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="5aO-UX-HnX" secondAttribute="bottom" constant="5" id="LJ2-W9-fOf"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="5aO-UX-HnX" secondAttribute="bottom" constant="20" symbolic="YES" id="LJ2-W9-fOf"/>
|
||||
<constraint firstItem="8tU-73-XEE" firstAttribute="leading" secondItem="bmd-gL-gzT" secondAttribute="leading" constant="20" symbolic="YES" id="M6Y-jN-LAf"/>
|
||||
<constraint firstItem="5aO-UX-HnX" firstAttribute="top" secondItem="bmd-gL-gzT" secondAttribute="top" constant="5" id="PPD-Jz-qCL"/>
|
||||
<constraint firstItem="5aO-UX-HnX" firstAttribute="top" secondItem="bmd-gL-gzT" secondAttribute="top" constant="20" symbolic="YES" id="PPD-Jz-qCL"/>
|
||||
<constraint firstItem="5aO-UX-HnX" firstAttribute="leading" secondItem="8tU-73-XEE" secondAttribute="trailing" constant="8" symbolic="YES" id="j1u-n4-2IK"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
<tabViewItem label="ZX Spectrum" identifier="spectrum" id="HQv-oF-k8b">
|
||||
<view key="view" id="bMx-F6-JUb">
|
||||
<rect key="frame" x="10" y="7" width="400" height="186"/>
|
||||
<rect key="frame" x="10" y="7" width="400" height="223"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gFZ-d4-WFv">
|
||||
<rect key="frame" x="67" y="157" width="76" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="16kb" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" tag="16" imageScaling="axesIndependently" inset="2" selectedItem="Fo7-NL-Kv5" id="tYs-sA-oek">
|
||||
<rect key="frame" x="67" y="179" width="76" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="16kb" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="16" imageScaling="axesIndependently" inset="2" selectedItem="Fo7-NL-Kv5" id="tYs-sA-oek">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="8lt-dk-zPr">
|
||||
<items>
|
||||
<menuItem title="16kb" tag="16" id="Fo7-NL-Kv5"/>
|
||||
<menuItem title="16kb" state="on" tag="16" id="Fo7-NL-Kv5"/>
|
||||
<menuItem title="48kb" tag="48" id="xks-Rv-Umd"/>
|
||||
<menuItem title="128kb" tag="128" id="w8h-lY-JLX"/>
|
||||
<menuItem title="+2" tag="2" id="Vvu-ua-pjg"/>
|
||||
<menuItem title="+2a" state="on" tag="21" id="bFk-nC-Txe"/>
|
||||
<menuItem title="+2a" tag="21" id="bFk-nC-Txe"/>
|
||||
<menuItem title="+3" tag="3" id="jwx-fZ-vXp"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="fJ3-ma-Byy">
|
||||
<rect key="frame" x="18" y="163" width="46" height="16"/>
|
||||
<rect key="frame" x="18" y="185" width="46" height="16"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Model:" id="JId-Tp-LrE">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -655,23 +801,23 @@ Gw
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="gFZ-d4-WFv" secondAttribute="trailing" constant="20" symbolic="YES" id="90E-uI-MQg"/>
|
||||
<constraint firstItem="fJ3-ma-Byy" firstAttribute="leading" secondItem="bMx-F6-JUb" secondAttribute="leading" constant="20" symbolic="YES" id="9kE-iQ-dxd"/>
|
||||
<constraint firstItem="fJ3-ma-Byy" firstAttribute="centerY" secondItem="gFZ-d4-WFv" secondAttribute="centerY" id="LxG-5E-Q5Y"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="gFZ-d4-WFv" secondAttribute="bottom" constant="5" id="d8S-vX-B5e"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="gFZ-d4-WFv" secondAttribute="bottom" constant="20" symbolic="YES" id="d8S-vX-B5e"/>
|
||||
<constraint firstItem="gFZ-d4-WFv" firstAttribute="leading" secondItem="fJ3-ma-Byy" secondAttribute="trailing" constant="8" symbolic="YES" id="hKS-47-R2y"/>
|
||||
<constraint firstItem="gFZ-d4-WFv" firstAttribute="top" secondItem="bMx-F6-JUb" secondAttribute="top" constant="5" id="wsX-Wq-iPt"/>
|
||||
<constraint firstItem="gFZ-d4-WFv" firstAttribute="top" secondItem="bMx-F6-JUb" secondAttribute="top" constant="20" symbolic="YES" id="wsX-Wq-iPt"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
</tabViewItems>
|
||||
</tabView>
|
||||
<scrollView borderType="line" autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="10" verticalLineScroll="24" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" id="z5Q-Bs-hJj">
|
||||
<rect key="frame" x="20" y="60" width="130" height="201"/>
|
||||
<rect key="frame" x="20" y="60" width="130" height="238"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" heightSizable="YES"/>
|
||||
<clipView key="contentView" id="O8s-Vw-9yQ">
|
||||
<rect key="frame" x="1" y="1" width="128" height="199"/>
|
||||
<rect key="frame" x="1" y="1" width="128" height="236"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="24" id="3go-Eb-GOy">
|
||||
<rect key="frame" x="0.0" y="0.0" width="128" height="199"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="128" height="236"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<size key="intercellSpacing" width="17" height="0.0"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -708,7 +854,7 @@ Gw
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="VAc-6N-O7q">
|
||||
<rect key="frame" x="18" y="269" width="554" height="27"/>
|
||||
<rect key="frame" x="18" y="306" width="554" height="27"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Choose a machine" id="32m-Vs-dPO">
|
||||
<font key="font" textStyle="title2" name=".SFNS-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -737,7 +883,7 @@ Gw
|
||||
<constraint firstItem="9YM-5x-pc0" firstAttribute="top" secondItem="z5Q-Bs-hJj" secondAttribute="bottom" constant="14" id="suf-rn-Bmy"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<point key="canvasLocation" x="-1" y="88"/>
|
||||
<point key="canvasLocation" x="-1" y="106.5"/>
|
||||
</window>
|
||||
<customObject id="192-Eb-Rpg" customClass="MachinePicker" customModule="Clock_Signal" customModuleProvider="target">
|
||||
<connections>
|
||||
@@ -750,6 +896,11 @@ Gw
|
||||
<outlet property="electronAP6Button" destination="cG2-Ph-S3Z" id="vkq-1J-KBG"/>
|
||||
<outlet property="electronDFSButton" destination="JqM-IK-FMP" id="C80-1k-TdQ"/>
|
||||
<outlet property="electronSidewaysRAMButton" destination="lzo-8g-o4S" id="LtS-wv-tMf"/>
|
||||
<outlet property="enterpriseBASICButton" destination="hIr-GH-7xi" id="fM6-It-9UO"/>
|
||||
<outlet property="enterpriseDOSButton" destination="syE-e7-TjU" id="sCW-Bj-ZTW"/>
|
||||
<outlet property="enterpriseEXOSButton" destination="nen-Za-7zH" id="NwS-ua-FdA"/>
|
||||
<outlet property="enterpriseModelButton" destination="PhH-bu-pb5" id="8wD-sW-aBw"/>
|
||||
<outlet property="enterpriseSpeedButton" destination="Lfl-5c-b8j" id="ClN-yN-Nbx"/>
|
||||
<outlet property="machineNameTable" destination="3go-Eb-GOy" id="Ppf-S0-IP1"/>
|
||||
<outlet property="machineSelector" destination="VUb-QG-x7c" id="crR-hB-jGd"/>
|
||||
<outlet property="macintoshModelTypeButton" destination="xa6-NA-JY5" id="2jX-PY-v2z"/>
|
||||
|
||||
@@ -27,14 +27,21 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
||||
@IBOutlet var appleIIgsModelButton: NSPopUpButton!
|
||||
@IBOutlet var appleIIgsMemorySizeButton: NSPopUpButton!
|
||||
|
||||
// MARK: - CPC properties
|
||||
@IBOutlet var cpcModelTypeButton: NSPopUpButton!
|
||||
|
||||
// MARK: - Electron properties
|
||||
@IBOutlet var electronDFSButton: NSButton!
|
||||
@IBOutlet var electronADFSButton: NSButton!
|
||||
@IBOutlet var electronAP6Button: NSButton!
|
||||
@IBOutlet var electronSidewaysRAMButton: NSButton!
|
||||
|
||||
// MARK: - CPC properties
|
||||
@IBOutlet var cpcModelTypeButton: NSPopUpButton!
|
||||
// MARK: - Enterprise properties
|
||||
@IBOutlet var enterpriseModelButton: NSPopUpButton!
|
||||
@IBOutlet var enterpriseSpeedButton: NSPopUpButton!
|
||||
@IBOutlet var enterpriseEXOSButton: NSPopUpButton!
|
||||
@IBOutlet var enterpriseBASICButton: NSPopUpButton!
|
||||
@IBOutlet var enterpriseDOSButton: NSPopUpButton!
|
||||
|
||||
// MARK: - Macintosh properties
|
||||
@IBOutlet var macintoshModelTypeButton: NSPopUpButton!
|
||||
@@ -93,14 +100,21 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
||||
appleIIgsModelButton.selectItem(withTag: standardUserDefaults.integer(forKey: "new.appleIIgsModel"))
|
||||
appleIIgsMemorySizeButton.selectItem(withTag: standardUserDefaults.integer(forKey: "new.appleIIgsMemorySize"))
|
||||
|
||||
// CPC settings
|
||||
cpcModelTypeButton.selectItem(withTag: standardUserDefaults.integer(forKey: "new.cpcModel"))
|
||||
|
||||
// Electron settings
|
||||
electronDFSButton.state = standardUserDefaults.bool(forKey: "new.electronDFS") ? .on : .off
|
||||
electronADFSButton.state = standardUserDefaults.bool(forKey: "new.electronADFS") ? .on : .off
|
||||
electronAP6Button.state = standardUserDefaults.bool(forKey: "new.electronAP6") ? .on : .off
|
||||
electronSidewaysRAMButton.state = standardUserDefaults.bool(forKey: "new.electronSidewaysRAM") ? .on : .off
|
||||
|
||||
// CPC settings
|
||||
cpcModelTypeButton.selectItem(withTag: standardUserDefaults.integer(forKey: "new.cpcModel"))
|
||||
// Enterprise settings
|
||||
enterpriseModelButton.selectItem(withTag: standardUserDefaults.integer(forKey: "new.enterpriseModel"))
|
||||
enterpriseSpeedButton.selectItem(withTag: standardUserDefaults.integer(forKey: "new.enterpriseSpeed"))
|
||||
enterpriseEXOSButton.selectItem(withTag: standardUserDefaults.integer(forKey: "new.enterpriseEXOSVersion"))
|
||||
enterpriseBASICButton.selectItem(withTag: standardUserDefaults.integer(forKey: "new.enterpriseBASICVersion"))
|
||||
enterpriseDOSButton.selectItem(withTag: standardUserDefaults.integer(forKey: "new.enterpriseDOS"))
|
||||
|
||||
// Macintosh settings
|
||||
macintoshModelTypeButton.selectItem(withTag: standardUserDefaults.integer(forKey: "new.macintoshModel"))
|
||||
@@ -143,14 +157,21 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
||||
standardUserDefaults.set(appleIIgsModelButton.selectedTag(), forKey: "new.appleIIgsModel")
|
||||
standardUserDefaults.set(appleIIgsMemorySizeButton.selectedTag(), forKey: "new.appleIIgsMemorySize")
|
||||
|
||||
// CPC settings
|
||||
standardUserDefaults.set(cpcModelTypeButton.selectedTag(), forKey: "new.cpcModel")
|
||||
|
||||
// Electron settings
|
||||
standardUserDefaults.set(electronDFSButton.state == .on, forKey: "new.electronDFS")
|
||||
standardUserDefaults.set(electronADFSButton.state == .on, forKey: "new.electronADFS")
|
||||
standardUserDefaults.set(electronAP6Button.state == .on, forKey: "new.electronAP6")
|
||||
standardUserDefaults.set(electronSidewaysRAMButton.state == .on, forKey: "new.electronSidewaysRAM")
|
||||
|
||||
// CPC settings
|
||||
standardUserDefaults.set(cpcModelTypeButton.selectedTag(), forKey: "new.cpcModel")
|
||||
// Enterprise settings
|
||||
standardUserDefaults.set(enterpriseModelButton.selectedTag(), forKey: "new.enterpriseModel")
|
||||
standardUserDefaults.set(enterpriseSpeedButton.selectedTag(), forKey: "new.enterpriseSpeed")
|
||||
standardUserDefaults.set(enterpriseEXOSButton.selectedTag(), forKey: "new.enterpriseEXOSVersion")
|
||||
standardUserDefaults.set(enterpriseBASICButton.selectedTag(), forKey: "new.enterpriseBASICVersion")
|
||||
standardUserDefaults.set(enterpriseDOSButton.selectedTag(), forKey: "new.enterpriseDOS")
|
||||
|
||||
// Macintosh settings
|
||||
standardUserDefaults.set(macintoshModelTypeButton.selectedTag(), forKey: "new.macintoshModel")
|
||||
@@ -205,12 +226,6 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
||||
storeOptions()
|
||||
|
||||
switch machineSelector.selectedTabViewItem!.identifier as! String {
|
||||
case "electron":
|
||||
return CSStaticAnalyser(
|
||||
electronDFS: electronDFSButton.state == .on,
|
||||
adfs: electronADFSButton.state == .on,
|
||||
ap6: electronAP6Button.state == .on,
|
||||
sidewaysRAM: electronSidewaysRAMButton.state == .on)
|
||||
|
||||
case "appleii":
|
||||
var model: CSMachineAppleIIModel = .appleII
|
||||
@@ -241,22 +256,71 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
||||
default: model = .ROM00
|
||||
}
|
||||
|
||||
let memorySize = Kilobytes(appleIIgsMemorySizeButton.selectedItem!.tag)
|
||||
let memorySize = Kilobytes(appleIIgsMemorySizeButton.selectedTag())
|
||||
return CSStaticAnalyser(appleIIgsModel: model, memorySize: memorySize)
|
||||
|
||||
case "atarist":
|
||||
return CSStaticAnalyser(atariSTModel: .model512k)
|
||||
|
||||
case "cpc":
|
||||
switch cpcModelTypeButton.selectedItem!.tag {
|
||||
switch cpcModelTypeButton.selectedTag() {
|
||||
case 464: return CSStaticAnalyser(amstradCPCModel: .model464)
|
||||
case 664: return CSStaticAnalyser(amstradCPCModel: .model664)
|
||||
case 6128: fallthrough
|
||||
default: return CSStaticAnalyser(amstradCPCModel: .model6128)
|
||||
}
|
||||
|
||||
case "electron":
|
||||
return CSStaticAnalyser(
|
||||
electronDFS: electronDFSButton.state == .on,
|
||||
adfs: electronADFSButton.state == .on,
|
||||
ap6: electronAP6Button.state == .on,
|
||||
sidewaysRAM: electronSidewaysRAMButton.state == .on)
|
||||
|
||||
case "enterprise":
|
||||
var model: CSMachineEnterpriseModel = .model128
|
||||
switch enterpriseModelButton.selectedTag() {
|
||||
case 64: model = .model64
|
||||
case 256: model = .model256
|
||||
case 128: fallthrough
|
||||
default: model = .model128
|
||||
}
|
||||
|
||||
var speed: CSMachineEnterpriseSpeed = .speed4MHz
|
||||
switch enterpriseSpeedButton.selectedTag() {
|
||||
case 6: speed = .speed6MHz
|
||||
case 4: fallthrough
|
||||
default: speed = .speed4MHz
|
||||
}
|
||||
|
||||
var exos: CSMachineEnterpriseEXOS = .version21
|
||||
switch enterpriseEXOSButton.selectedTag() {
|
||||
case 10: exos = .version10
|
||||
case 20: exos = .version20
|
||||
case 21: fallthrough
|
||||
default: exos = .version21
|
||||
}
|
||||
|
||||
var basic: CSMachineEnterpriseBASIC = .version21
|
||||
switch enterpriseBASICButton.selectedTag() {
|
||||
case 0: basic = .none
|
||||
case 10: basic = .version10
|
||||
case 11: basic = .version11
|
||||
case 21: fallthrough
|
||||
default: basic = .version21
|
||||
}
|
||||
|
||||
var dos: CSMachineEnterpriseDOS = .dosNone
|
||||
switch enterpriseDOSButton.selectedTag() {
|
||||
case 1: dos = .DOSEXDOS
|
||||
case 0: fallthrough
|
||||
default: dos = .dosNone
|
||||
}
|
||||
|
||||
return CSStaticAnalyser(enterpriseModel: model, speed: speed, exosVersion: exos, basicVersion: basic, dos: dos)
|
||||
|
||||
case "mac":
|
||||
switch macintoshModelTypeButton.selectedItem!.tag {
|
||||
switch macintoshModelTypeButton.selectedTag() {
|
||||
case 0: return CSStaticAnalyser(macintoshModel: .model128k)
|
||||
case 1: return CSStaticAnalyser(macintoshModel: .model512k)
|
||||
case 2: return CSStaticAnalyser(macintoshModel: .model512ke)
|
||||
@@ -266,7 +330,7 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
||||
|
||||
case "msx":
|
||||
let hasDiskDrive = msxHasDiskDriveButton.state == .on
|
||||
switch msxRegionButton.selectedItem!.tag {
|
||||
switch msxRegionButton.selectedTag() {
|
||||
case 2:
|
||||
return CSStaticAnalyser(msxRegion: .japanese, hasDiskDrive: hasDiskDrive)
|
||||
case 1:
|
||||
@@ -287,7 +351,7 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
||||
|
||||
}
|
||||
var model: CSMachineOricModel = .oric1
|
||||
switch oricModelTypeButton.selectedItem!.tag {
|
||||
switch oricModelTypeButton.selectedTag() {
|
||||
case 1: model = .oricAtmos
|
||||
case 2: model = .pravetz
|
||||
default: break
|
||||
@@ -297,7 +361,7 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
||||
|
||||
case "spectrum":
|
||||
var model: CSMachineSpectrumModel = .plus2a
|
||||
switch spectrumModelTypeButton.selectedItem!.tag {
|
||||
switch spectrumModelTypeButton.selectedTag() {
|
||||
case 16: model = .sixteenK
|
||||
case 48: model = .fortyEightK
|
||||
case 128: model = .oneTwoEightK
|
||||
@@ -310,9 +374,9 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
||||
return CSStaticAnalyser(spectrumModel: model)
|
||||
|
||||
case "vic20":
|
||||
let memorySize = Kilobytes(vic20MemorySizeButton.selectedItem!.tag)
|
||||
let memorySize = Kilobytes(vic20MemorySizeButton.selectedTag())
|
||||
let hasC1540 = vic20HasC1540Button.state == .on
|
||||
switch vic20RegionButton.selectedItem!.tag {
|
||||
switch vic20RegionButton.selectedTag() {
|
||||
case 1:
|
||||
return CSStaticAnalyser(vic20Region: .american, memorySize: memorySize, hasC1540: hasC1540)
|
||||
case 2:
|
||||
@@ -327,10 +391,10 @@ class MachinePicker: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
||||
}
|
||||
|
||||
case "zx80":
|
||||
return CSStaticAnalyser(zx80MemorySize: Kilobytes(zx80MemorySizeButton.selectedItem!.tag), useZX81ROM: zx80UsesZX81ROMButton.state == .on)
|
||||
return CSStaticAnalyser(zx80MemorySize: Kilobytes(zx80MemorySizeButton.selectedTag()), useZX81ROM: zx80UsesZX81ROMButton.state == .on)
|
||||
|
||||
case "zx81":
|
||||
return CSStaticAnalyser(zx81MemorySize: Kilobytes(zx81MemorySizeButton.selectedItem!.tag))
|
||||
return CSStaticAnalyser(zx81MemorySize: Kilobytes(zx81MemorySizeButton.selectedTag()))
|
||||
|
||||
default: return CSStaticAnalyser()
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ struct Line {
|
||||
struct SourceInterpolator {
|
||||
float4 position [[position]];
|
||||
float2 textureCoordinates;
|
||||
half unitColourPhase; // i.e. one unit per circle.
|
||||
half colourPhase; // i.e. 2*pi units per circle, just regular radians.
|
||||
float unitColourPhase; // i.e. one unit per circle.
|
||||
float colourPhase; // i.e. 2*pi units per circle, just regular radians.
|
||||
half colourAmplitude [[flat]];
|
||||
};
|
||||
|
||||
|
||||
@@ -80,10 +80,12 @@
|
||||
- (void)scanTargetViewDidShowOSMouseCursor:(nonnull CSScanTargetView *)view;
|
||||
|
||||
/*!
|
||||
Announces that the OS mouse cursor will now be hidden.
|
||||
Announces that the OS mouse cursor would now be hidden; 'would' means that if this is not
|
||||
a mouse capture-enabled view then it will be hidden, but otherwise it might or might not be
|
||||
as per whatever is user-friendly.
|
||||
@param view The view making the announcement.
|
||||
*/
|
||||
- (void)scanTargetViewWillHideOSMouseCursor:(nonnull CSScanTargetView *)view;
|
||||
- (void)scanTargetViewWouldHideOSMouseCursor:(nonnull CSScanTargetView *)view;
|
||||
|
||||
/*!
|
||||
Announces receipt of a file by drag and drop to the delegate.
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
|
||||
#include <stdatomic.h>
|
||||
|
||||
static const NSTimeInterval standardMouseHideInterval = 3.0;
|
||||
static const NSTimeInterval quickMouseHideInterval = 0.1;
|
||||
|
||||
@interface CSScanTargetView () <NSDraggingDestination, CSApplicationEventDelegate>
|
||||
@end
|
||||
|
||||
@@ -237,28 +240,31 @@ static CVReturn DisplayLinkCallback(__unused CVDisplayLinkRef displayLink, const
|
||||
[self addTrackingArea:_mouseTrackingArea];
|
||||
}
|
||||
|
||||
- (void)scheduleMouseHide {
|
||||
if(!self.shouldCaptureMouse) {
|
||||
[_mouseHideTimer invalidate];
|
||||
- (void)scheduleMouseHideAfter:(NSTimeInterval)interval {
|
||||
[_mouseHideTimer invalidate];
|
||||
|
||||
_mouseHideTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 repeats:NO block:^(__unused NSTimer * _Nonnull timer) {
|
||||
_mouseHideTimer = [NSTimer scheduledTimerWithTimeInterval:interval repeats:NO block:^(__unused NSTimer * _Nonnull timer) {
|
||||
// Don't actually hide the mouse if this is a mouse-capture machine; that makes
|
||||
// it fairly confusing as to current application state.
|
||||
if(!self.shouldCaptureMouse) {
|
||||
[NSCursor setHiddenUntilMouseMoves:YES];
|
||||
[self.responderDelegate scanTargetViewWillHideOSMouseCursor:self];
|
||||
}];
|
||||
}
|
||||
}
|
||||
[self.responderDelegate scanTargetViewWouldHideOSMouseCursor:self];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent *)event {
|
||||
[self.responderDelegate scanTargetViewDidShowOSMouseCursor:self];
|
||||
[super mouseEntered:event];
|
||||
[self scheduleMouseHide];
|
||||
|
||||
[self.responderDelegate scanTargetViewDidShowOSMouseCursor:self];
|
||||
[self scheduleMouseHideAfter:standardMouseHideInterval];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent *)event {
|
||||
[super mouseExited:event];
|
||||
[_mouseHideTimer invalidate];
|
||||
_mouseHideTimer = nil;
|
||||
[self.responderDelegate scanTargetViewWillHideOSMouseCursor:self];
|
||||
|
||||
// Schedule a really short mouse-hiding interval.
|
||||
[self scheduleMouseHideAfter:quickMouseHideInterval];
|
||||
}
|
||||
|
||||
- (void)releaseMouse {
|
||||
@@ -275,30 +281,26 @@ static CVReturn DisplayLinkCallback(__unused CVDisplayLinkRef displayLink, const
|
||||
#pragma mark - Mouse motion
|
||||
|
||||
- (void)applyMouseMotion:(NSEvent *)event {
|
||||
if(!self.shouldCaptureMouse) {
|
||||
if(!_mouseIsCaptured) {
|
||||
// Mouse capture is off, so don't play games with the cursor, just schedule it to
|
||||
// hide in the near future.
|
||||
[self scheduleMouseHide];
|
||||
[self scheduleMouseHideAfter:standardMouseHideInterval];
|
||||
[self.responderDelegate scanTargetViewDidShowOSMouseCursor:self];
|
||||
} else {
|
||||
if(_mouseIsCaptured) {
|
||||
// Mouse capture is on, so move the cursor back to the middle of the window, and
|
||||
// forward the deltas to the listener.
|
||||
//
|
||||
// TODO: should I really need to invert the y coordinate myself? It suggests I
|
||||
// might have an error in mapping here.
|
||||
const NSPoint windowCentre = [self convertPoint:CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5) toView:nil];
|
||||
const NSPoint screenCentre = [self.window convertPointToScreen:windowCentre];
|
||||
const CGRect screenFrame = self.window.screen.frame;
|
||||
CGWarpMouseCursorPosition(NSMakePoint(
|
||||
screenFrame.origin.x + screenCentre.x,
|
||||
screenFrame.origin.y + screenFrame.size.height - screenCentre.y
|
||||
));
|
||||
// Mouse capture is on, so move the cursor back to the middle of the window, and
|
||||
// forward the deltas to the listener.
|
||||
//
|
||||
// TODO: should I really need to invert the y coordinate myself? It suggests I
|
||||
// might have an error in mapping here.
|
||||
const NSPoint windowCentre = [self convertPoint:CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5) toView:nil];
|
||||
const NSPoint screenCentre = [self.window convertPointToScreen:windowCentre];
|
||||
const CGRect screenFrame = self.window.screen.frame;
|
||||
CGWarpMouseCursorPosition(NSMakePoint(
|
||||
screenFrame.origin.x + screenCentre.x,
|
||||
screenFrame.origin.y + screenFrame.size.height - screenCentre.y
|
||||
));
|
||||
|
||||
[self.responderDelegate mouseMoved:event];
|
||||
} else {
|
||||
[self.responderDelegate scanTargetViewDidShowOSMouseCursor:self];
|
||||
}
|
||||
[self.responderDelegate mouseMoved:event];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,7 +332,7 @@ static CVReturn DisplayLinkCallback(__unused CVDisplayLinkRef displayLink, const
|
||||
_mouseIsCaptured = YES;
|
||||
[NSCursor hide];
|
||||
CGAssociateMouseAndMouseCursorPosition(false);
|
||||
[self.responderDelegate scanTargetViewWillHideOSMouseCursor:self];
|
||||
[self.responderDelegate scanTargetViewWouldHideOSMouseCursor:self];
|
||||
[self.responderDelegate scanTargetViewDidCaptureMouse:self];
|
||||
if(self.shouldUsurpCommand) {
|
||||
((CSApplication *)[NSApplication sharedApplication]).eventDelegate = self;
|
||||
|
||||
102
OSBindings/Mac/Clock SignalTests/EnterpriseDaveTests.mm
Normal file
102
OSBindings/Mac/Clock SignalTests/EnterpriseDaveTests.mm
Normal file
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// EnterpriseDaveTests.m
|
||||
// Clock SignalTests
|
||||
//
|
||||
// Created by Thomas Harte on 02/07/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "../../../Machines/Enterprise/Dave.hpp"
|
||||
#include <memory>
|
||||
|
||||
@interface EnterpriseDaveTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation EnterpriseDaveTests {
|
||||
std::unique_ptr<Enterprise::Dave::TimedInterruptSource> _interruptSource;
|
||||
}
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
_interruptSource = std::make_unique<Enterprise::Dave::TimedInterruptSource>();
|
||||
}
|
||||
|
||||
/// Tests that the programmable timer flag toggles and produces interrupts
|
||||
/// at the rate specified, and that the flag toggles when interrupts are signalled.
|
||||
- (void)performTestExpectedInterrupts:(double)expectedInterruptsPerSecond mode:(int)mode {
|
||||
// If a programmable timer mode is requested, synchronise both channels.
|
||||
if(mode >= 2) {
|
||||
_interruptSource->write(0xa7, 3);
|
||||
_interruptSource->run_for(Cycles(2));
|
||||
}
|
||||
|
||||
// Set mode (and disable sync, if it was applied).
|
||||
_interruptSource->write(0xa7, mode << 5);
|
||||
|
||||
int toggles = 0;
|
||||
int interrupts = 0;
|
||||
uint8_t dividerState = _interruptSource->get_divider_state() & 1;
|
||||
int nextSequencePoint = _interruptSource->get_next_sequence_point().as<int>();
|
||||
|
||||
for(int c = 0; c < 250000 * 5; c++) {
|
||||
// Advance one cycle. Clock is 500,000 Hz.
|
||||
_interruptSource->run_for(Cycles(2));
|
||||
--nextSequencePoint;
|
||||
|
||||
// Check for a status bit change.
|
||||
const uint8_t newDividerState = _interruptSource->get_divider_state();
|
||||
const bool didToggle = (dividerState^newDividerState)&0x1;
|
||||
dividerState = newDividerState;
|
||||
toggles += didToggle;
|
||||
|
||||
// Check for the relevant interrupt.
|
||||
const uint8_t newInterrupts = _interruptSource->get_new_interrupts();
|
||||
if(newInterrupts) {
|
||||
XCTAssertEqual(nextSequencePoint, 0);
|
||||
nextSequencePoint = _interruptSource->get_next_sequence_point().as<int>();
|
||||
|
||||
if(newInterrupts & 0x02) {
|
||||
++interrupts;
|
||||
XCTAssertTrue(didToggle);
|
||||
} else {
|
||||
// Failing that, confirm that the other interrupt happend.
|
||||
XCTAssertTrue(newInterrupts & 0x08);
|
||||
}
|
||||
}
|
||||
|
||||
XCTAssertEqual(nextSequencePoint, _interruptSource->get_next_sequence_point().as<int>(), @"At cycle %d", c);
|
||||
}
|
||||
|
||||
XCTAssertEqual(toggles, int(expectedInterruptsPerSecond * 5.0));
|
||||
XCTAssertEqual(interrupts, int(expectedInterruptsPerSecond * 5.0));
|
||||
}
|
||||
|
||||
- (void)test1kHzTimer {
|
||||
[self performTestExpectedInterrupts:1000.0 mode:0];
|
||||
}
|
||||
|
||||
- (void)test50HzTimer {
|
||||
[self performTestExpectedInterrupts:50.0 mode:1];
|
||||
}
|
||||
|
||||
- (void)testTone0Timer {
|
||||
// Set tone generator 0 as the interrupt source, with a divider of 137;
|
||||
// apply sync momentarily.
|
||||
_interruptSource->write(0, 137);
|
||||
_interruptSource->write(1, 0);
|
||||
|
||||
[self performTestExpectedInterrupts:250000.0/(138.0 * 2.0) mode:2];
|
||||
}
|
||||
|
||||
- (void)testTone1Timer {
|
||||
// Set tone generator 1 as the interrupt source, with a divider of 961;
|
||||
// apply sync momentarily.
|
||||
_interruptSource->write(2, 961 & 0xff);
|
||||
_interruptSource->write(3, (961 >> 8) & 0xff);
|
||||
|
||||
[self performTestExpectedInterrupts:250000.0/(962.0 * 2.0) mode:3];
|
||||
}
|
||||
|
||||
@end
|
||||
72
OSBindings/Mac/Clock SignalTests/EnterpriseNickTests.mm
Normal file
72
OSBindings/Mac/Clock SignalTests/EnterpriseNickTests.mm
Normal file
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// EnterpriseNickTests.m
|
||||
// Clock SignalTests
|
||||
//
|
||||
// Created by Thomas Harte on 18/06/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "../../../Machines/Enterprise/Nick.hpp"
|
||||
#include <memory>
|
||||
|
||||
@interface EnterpriseNickTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation EnterpriseNickTests {
|
||||
std::unique_ptr<Enterprise::Nick> _nick;
|
||||
uint8_t _ram[64*1024];
|
||||
int _totalLines;
|
||||
}
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
|
||||
// Create a Nick.
|
||||
_nick = std::make_unique<Enterprise::Nick>(_ram);
|
||||
|
||||
// Add a basic line table of blocks proceeding in length: 1, 2, 3, 4, etc and toggling the interrupt bit.
|
||||
_totalLines = 0;
|
||||
int nextLength = 0;
|
||||
int pointer = 0;
|
||||
uint8_t interruptFlag = 0x80;
|
||||
while(nextLength < 256) {
|
||||
_ram[pointer] = 0x100 - nextLength;
|
||||
_ram[pointer+1] = interruptFlag;
|
||||
|
||||
pointer += 16;
|
||||
++nextLength;
|
||||
interruptFlag ^= 0x80;
|
||||
_totalLines += nextLength;
|
||||
}
|
||||
|
||||
// For now: assume Nick starts at address 0 from creation.
|
||||
}
|
||||
|
||||
- (void)testInterruptPrediction {
|
||||
// Run for the number of cycles implied by the number of lines.
|
||||
int next_sequence_point = _nick->get_next_sequence_point().as<int>();
|
||||
bool last_interrupt_line = _nick->get_interrupt_line();
|
||||
|
||||
for(int c = 0; c < _totalLines*912; c++) {
|
||||
// Check that interrupt line transitions happen only on declared sequence points.
|
||||
_nick->run_for(Cycles(1));
|
||||
--next_sequence_point;
|
||||
const bool interrupt_line = _nick->get_interrupt_line();
|
||||
|
||||
if(interrupt_line != last_interrupt_line) {
|
||||
XCTAssertEqual(next_sequence_point, 0);
|
||||
}
|
||||
last_interrupt_line = interrupt_line;
|
||||
|
||||
if(!next_sequence_point) {
|
||||
next_sequence_point = _nick->get_next_sequence_point().as<int>();
|
||||
} else {
|
||||
const int expected_next_sequence_point = _nick->get_next_sequence_point().as<int>();
|
||||
XCTAssertEqual(next_sequence_point, expected_next_sequence_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -47,6 +47,7 @@ SOURCES += \
|
||||
$$SRC/Analyser/Static/Commodore/*.cpp \
|
||||
$$SRC/Analyser/Static/Disassembler/*.cpp \
|
||||
$$SRC/Analyser/Static/DiskII/*.cpp \
|
||||
$$SRC/Analyser/Static/Enterprise/*.cpp \
|
||||
$$SRC/Analyser/Static/Macintosh/*.cpp \
|
||||
$$SRC/Analyser/Static/MSX/*.cpp \
|
||||
$$SRC/Analyser/Static/Oric/*.cpp \
|
||||
@@ -92,6 +93,7 @@ SOURCES += \
|
||||
$$SRC/Machines/Commodore/1540/Implementation/*.cpp \
|
||||
$$SRC/Machines/Commodore/Vic-20/*.cpp \
|
||||
$$SRC/Machines/Electron/*.cpp \
|
||||
$$SRC/Machines/Enterprise/*.cpp \
|
||||
$$SRC/Machines/MasterSystem/*.cpp \
|
||||
$$SRC/Machines/MSX/*.cpp \
|
||||
$$SRC/Machines/Oric/*.cpp \
|
||||
@@ -166,6 +168,7 @@ HEADERS += \
|
||||
$$SRC/Analyser/Static/Commodore/*.hpp \
|
||||
$$SRC/Analyser/Static/Disassembler/*.hpp \
|
||||
$$SRC/Analyser/Static/DiskII/*.hpp \
|
||||
$$SRC/Analyser/Static/Enterprise/*.hpp \
|
||||
$$SRC/Analyser/Static/Macintosh/*.hpp \
|
||||
$$SRC/Analyser/Static/MSX/*.hpp \
|
||||
$$SRC/Analyser/Static/Oric/*.hpp \
|
||||
@@ -221,6 +224,7 @@ HEADERS += \
|
||||
$$SRC/Machines/Commodore/1540/Implementation/*.hpp \
|
||||
$$SRC/Machines/Commodore/Vic-20/*.hpp \
|
||||
$$SRC/Machines/Electron/*.hpp \
|
||||
$$SRC/Machines/Enterprise/*.hpp \
|
||||
$$SRC/Machines/MasterSystem/*.hpp \
|
||||
$$SRC/Machines/MSX/*.hpp \
|
||||
$$SRC/Machines/Oric/*.hpp \
|
||||
|
||||
@@ -424,6 +424,10 @@ void MainWindow::launchMachine() {
|
||||
addEnhancementsMenu(settingsPrefix, true, false);
|
||||
break;
|
||||
|
||||
case Analyser::Machine::Enterprise:
|
||||
addDisplayMenu(settingsPrefix, "Composite", "", "", "RGB");
|
||||
break;
|
||||
|
||||
case Analyser::Machine::Macintosh:
|
||||
addEnhancementsMenu(settingsPrefix, false, true);
|
||||
break;
|
||||
@@ -953,6 +957,7 @@ void MainWindow::setButtonPressed(int index, bool isPressed) {
|
||||
#include "../../Analyser/Static/AppleIIgs/Target.hpp"
|
||||
#include "../../Analyser/Static/AtariST/Target.hpp"
|
||||
#include "../../Analyser/Static/Commodore/Target.hpp"
|
||||
#include "../../Analyser/Static/Enterprise/Target.hpp"
|
||||
#include "../../Analyser/Static/Macintosh/Target.hpp"
|
||||
#include "../../Analyser/Static/MSX/Target.hpp"
|
||||
#include "../../Analyser/Static/Oric/Target.hpp"
|
||||
@@ -973,6 +978,7 @@ void MainWindow::startMachine() {
|
||||
TEST(amstradCPC);
|
||||
TEST(atariST);
|
||||
TEST(electron);
|
||||
TEST(enterprise);
|
||||
TEST(macintosh);
|
||||
TEST(msx);
|
||||
TEST(oric);
|
||||
@@ -1057,6 +1063,43 @@ void MainWindow::start_electron() {
|
||||
launchTarget(std::move(target));
|
||||
}
|
||||
|
||||
void MainWindow::start_enterprise() {
|
||||
using Target = Analyser::Static::Enterprise::Target;
|
||||
auto target = std::make_unique<Target>();
|
||||
|
||||
switch(ui->enterpriseModelComboBox->currentIndex()) {
|
||||
default: target->model = Target::Model::Enterprise64; break;
|
||||
case 1: target->model = Target::Model::Enterprise128; break;
|
||||
case 2: target->model = Target::Model::Enterprise256; break;
|
||||
}
|
||||
|
||||
switch(ui->enterpriseSpeedComboBox->currentIndex()) {
|
||||
default: target->speed = Target::Speed::FourMHz; break;
|
||||
case 1: target->speed = Target::Speed::SixMHz; break;
|
||||
}
|
||||
|
||||
switch(ui->enterpriseEXOSComboBox->currentIndex()) {
|
||||
default: target->exos_version = Target::EXOSVersion::v10; break;
|
||||
case 1: target->exos_version = Target::EXOSVersion::v20; break;
|
||||
case 2: target->exos_version = Target::EXOSVersion::v21; break;
|
||||
case 3: target->exos_version = Target::EXOSVersion::v23; break;
|
||||
}
|
||||
|
||||
switch(ui->enterpriseBASICComboBox->currentIndex()) {
|
||||
default: target->basic_version = Target::BASICVersion::None; break;
|
||||
case 1: target->basic_version = Target::BASICVersion::v10; break;
|
||||
case 2: target->basic_version = Target::BASICVersion::v11; break;
|
||||
case 3: target->basic_version = Target::BASICVersion::v21; break;
|
||||
}
|
||||
|
||||
switch(ui->enterpriseDOSComboBox->currentIndex()) {
|
||||
default: target->dos = Target::DOS::None; break;
|
||||
case 1: target->dos = Target::DOS::EXDOS; break;
|
||||
}
|
||||
|
||||
launchTarget(std::move(target));
|
||||
}
|
||||
|
||||
void MainWindow::start_macintosh() {
|
||||
using Target = Analyser::Static::Macintosh::Target;
|
||||
auto target = std::make_unique<Target>();
|
||||
@@ -1212,6 +1255,13 @@ void MainWindow::launchTarget(std::unique_ptr<Analyser::Static::Target> &&target
|
||||
CheckBox(electronAP6CheckBox, "electron.hasAP6"); \
|
||||
CheckBox(electronSidewaysRAMCheckBox, "electron.fillSidewaysRAM"); \
|
||||
\
|
||||
/* Enterprise. */ \
|
||||
ComboBox(enterpriseModelComboBox, "enterprise.model"); \
|
||||
ComboBox(enterpriseSpeedComboBox, "enterprise.speed"); \
|
||||
ComboBox(enterpriseEXOSComboBox, "enterprise.exos"); \
|
||||
ComboBox(enterpriseBASICComboBox, "enterprise.basic"); \
|
||||
ComboBox(enterpriseDOSComboBox, "enterprise.dos"); \
|
||||
\
|
||||
/* Macintosh. */ \
|
||||
ComboBox(macintoshModelComboBox, "macintosh.model"); \
|
||||
\
|
||||
@@ -1265,6 +1315,7 @@ void MainWindow::restoreSelections() {
|
||||
// MARK: - Activity observation
|
||||
|
||||
void MainWindow::addActivityObserver() {
|
||||
ledStatuses.clear();
|
||||
auto activitySource = machine->activity_source();
|
||||
if(!activitySource) return;
|
||||
|
||||
@@ -1272,7 +1323,7 @@ void MainWindow::addActivityObserver() {
|
||||
activitySource->set_activity_observer(this);
|
||||
}
|
||||
|
||||
void MainWindow::register_led(const std::string &name) {
|
||||
void MainWindow::register_led(const std::string &name, uint8_t) {
|
||||
std::lock_guard guard(ledStatusesLock);
|
||||
ledStatuses[name] = false;
|
||||
QMetaObject::invokeMethod(this, "updateStatusBarText");
|
||||
|
||||
@@ -91,6 +91,7 @@ class MainWindow : public QMainWindow, public Outputs::Speaker::Speaker::Delegat
|
||||
void start_amstradCPC();
|
||||
void start_atariST();
|
||||
void start_electron();
|
||||
void start_enterprise();
|
||||
void start_macintosh();
|
||||
void start_msx();
|
||||
void start_oric();
|
||||
@@ -151,7 +152,7 @@ class MainWindow : public QMainWindow, public Outputs::Speaker::Speaker::Delegat
|
||||
|
||||
KeyboardMapper keyMapper;
|
||||
|
||||
void register_led(const std::string &) override;
|
||||
void register_led(const std::string &, uint8_t) override;
|
||||
void set_led_status(const std::string &, bool) override;
|
||||
|
||||
std::recursive_mutex ledStatusesLock;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<item>
|
||||
<widget class="QTabWidget" name="machineSelectionTabs">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>5</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="appleIITab">
|
||||
<attribute name="title">
|
||||
@@ -310,6 +310,159 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="enterpriseTab">
|
||||
<attribute name="title">
|
||||
<string>Enterprise</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="enterpriseLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="enterpriseHorizontalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="enterpriseFormLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="enterpriseModelLabel">
|
||||
<property name="text">
|
||||
<string>Model:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="enterpriseModelComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Enterprise 64</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Enterprise 128</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Enterprise 256</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="enterpriseSpeedLabel">
|
||||
<property name="text">
|
||||
<string>Speed:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="enterpriseSpeedComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>4 MHz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>6 MHz</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="enterpriseEXOSLabel">
|
||||
<property name="text">
|
||||
<string>EXOS:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="enterpriseEXOSComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Version 1.0</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Version 2.0</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Version 2.1</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="enterpriseBASICLabel">
|
||||
<property name="text">
|
||||
<string>BASIC:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="enterpriseBASICComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Version 1.0</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Version 1.1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Version 2.1</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="enterpriseDOSLabel">
|
||||
<property name="text">
|
||||
<string>DOS:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="enterpriseDOSComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>EXDOS</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="enterpriseHSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="macintoshTab">
|
||||
<attribute name="title">
|
||||
<string>Macintosh</string>
|
||||
@@ -533,75 +686,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="spectrumTab">
|
||||
<attribute name="title">
|
||||
<string>Spectrum</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="spectrumLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="spectrumHorizontalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="spectrumFormLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="spectrumModelLabel">
|
||||
<property name="text">
|
||||
<string>Model:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="spectrumModelComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>16kb</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>48kb</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>128kb</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>+2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>+2a</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>+3</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="spectrumHSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="vic20Tab">
|
||||
<attribute name="title">
|
||||
<string>Vic-20</string>
|
||||
@@ -830,6 +914,75 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="spectrumTab">
|
||||
<attribute name="title">
|
||||
<string>ZX Spectrum</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="spectrumLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="spectrumHorizontalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="spectrumFormLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="spectrumModelLabel">
|
||||
<property name="text">
|
||||
<string>Model:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="spectrumModelComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>16kb</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>48kb</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>128kb</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>+2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>+2a</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>+3</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="spectrumHSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignBottom">
|
||||
|
||||
@@ -31,6 +31,7 @@ SOURCES += glob.glob('../../Analyser/Static/Coleco/*.cpp')
|
||||
SOURCES += glob.glob('../../Analyser/Static/Commodore/*.cpp')
|
||||
SOURCES += glob.glob('../../Analyser/Static/Disassembler/*.cpp')
|
||||
SOURCES += glob.glob('../../Analyser/Static/DiskII/*.cpp')
|
||||
SOURCES += glob.glob('../../Analyser/Static/Enterprise/*.cpp')
|
||||
SOURCES += glob.glob('../../Analyser/Static/Macintosh/*.cpp')
|
||||
SOURCES += glob.glob('../../Analyser/Static/MSX/*.cpp')
|
||||
SOURCES += glob.glob('../../Analyser/Static/Oric/*.cpp')
|
||||
@@ -79,6 +80,7 @@ SOURCES += glob.glob('../../Machines/Commodore/*.cpp')
|
||||
SOURCES += glob.glob('../../Machines/Commodore/1540/Implementation/*.cpp')
|
||||
SOURCES += glob.glob('../../Machines/Commodore/Vic-20/*.cpp')
|
||||
SOURCES += glob.glob('../../Machines/Electron/*.cpp')
|
||||
SOURCES += glob.glob('../../Machines/Enterprise/*.cpp')
|
||||
SOURCES += glob.glob('../../Machines/MasterSystem/*.cpp')
|
||||
SOURCES += glob.glob('../../Machines/MSX/*.cpp')
|
||||
SOURCES += glob.glob('../../Machines/Oric/*.cpp')
|
||||
|
||||
@@ -271,7 +271,7 @@ class ActivityObserver: public Activity::Observer {
|
||||
|
||||
private:
|
||||
std::vector<std::string> leds_;
|
||||
void register_led(const std::string &name) final {
|
||||
void register_led(const std::string &name, uint8_t) final {
|
||||
std::lock_guard lock_guard(mutex);
|
||||
leds_.push_back(name);
|
||||
}
|
||||
@@ -832,8 +832,11 @@ int main(int argc, char *argv[]) {
|
||||
} else if(volume < 0.0 || volume > 1.0) {
|
||||
std::cerr << "Cannot run with volume " << volume_string << "; volumes must be between 0.0 and 1.0." << std::endl;
|
||||
} else {
|
||||
const auto speaker = machine->audio_producer()->get_speaker();
|
||||
if(speaker) speaker->set_output_volume(volume);
|
||||
const auto audio_producer = machine->audio_producer();
|
||||
if(audio_producer) {
|
||||
const auto speaker = machine->audio_producer()->get_speaker();
|
||||
if(speaker) speaker->set_output_volume(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -907,26 +910,29 @@ int main(int argc, char *argv[]) {
|
||||
machine->scan_producer()->set_scan_target(&scan_target);
|
||||
|
||||
// For now, lie about audio output intentions.
|
||||
auto speaker = machine->audio_producer()->get_speaker();
|
||||
if(speaker) {
|
||||
// Create an audio pipe.
|
||||
SDL_AudioSpec desired_audio_spec;
|
||||
SDL_AudioSpec obtained_audio_spec;
|
||||
const auto audio_producer = machine->audio_producer();
|
||||
if(audio_producer) {
|
||||
auto speaker = audio_producer->get_speaker();
|
||||
if(speaker) {
|
||||
// Create an audio pipe.
|
||||
SDL_AudioSpec desired_audio_spec;
|
||||
SDL_AudioSpec obtained_audio_spec;
|
||||
|
||||
SDL_zero(desired_audio_spec);
|
||||
desired_audio_spec.freq = 48000; // TODO: how can I get SDL to reveal the output rate of this machine?
|
||||
desired_audio_spec.format = AUDIO_S16;
|
||||
desired_audio_spec.channels = 1 + int(speaker->get_is_stereo());
|
||||
desired_audio_spec.samples = Uint16(SpeakerDelegate::buffered_samples);
|
||||
desired_audio_spec.callback = SpeakerDelegate::SDL_audio_callback;
|
||||
desired_audio_spec.userdata = &speaker_delegate;
|
||||
SDL_zero(desired_audio_spec);
|
||||
desired_audio_spec.freq = 48000; // TODO: how can I get SDL to reveal the output rate of this machine?
|
||||
desired_audio_spec.format = AUDIO_S16;
|
||||
desired_audio_spec.channels = 1 + int(speaker->get_is_stereo());
|
||||
desired_audio_spec.samples = Uint16(SpeakerDelegate::buffered_samples);
|
||||
desired_audio_spec.callback = SpeakerDelegate::SDL_audio_callback;
|
||||
desired_audio_spec.userdata = &speaker_delegate;
|
||||
|
||||
speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
|
||||
speaker->set_output_rate(obtained_audio_spec.freq, desired_audio_spec.samples, obtained_audio_spec.channels == 2);
|
||||
speaker_delegate.is_stereo = obtained_audio_spec.channels == 2;
|
||||
speaker->set_delegate(&speaker_delegate);
|
||||
SDL_PauseAudioDevice(speaker_delegate.audio_device, 0);
|
||||
speaker->set_output_rate(obtained_audio_spec.freq, desired_audio_spec.samples, obtained_audio_spec.channels == 2);
|
||||
speaker_delegate.is_stereo = obtained_audio_spec.channels == 2;
|
||||
speaker->set_delegate(&speaker_delegate);
|
||||
SDL_PauseAudioDevice(speaker_delegate.audio_device, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#define WDC65816_hpp
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -145,6 +145,12 @@ struct PartialMachineCycle {
|
||||
forceinline bool is_wait() const {
|
||||
return operation >= Operation::ReadOpcodeWait && operation <= Operation::InterruptWait;
|
||||
}
|
||||
/*!
|
||||
@returns @c true if this partial machine cycle is a memory access; @c false otherwise.
|
||||
*/
|
||||
forceinline bool is_memory_access() const {
|
||||
return operation <= Operation::Write;
|
||||
}
|
||||
|
||||
enum Line {
|
||||
CLK = 1 << 0,
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# Clock Signal
|
||||
Clock Signal ('CLK') is an emulator for tourists that seeks to be invisible. Users directly launch classic software, avoiding the learning curves associated with emulators and with classic machines.
|
||||
|
||||
macOS and source releases are [hosted on GitHub](https://github.com/TomHarte/CLK/releases). For desktop Linux it is also available as a [Snap](https://snapcraft.io/clock-signal).
|
||||
|
||||
This emulator seeks to offer:
|
||||
* single-click load of any piece of source media for any supported platform;
|
||||
* with a heavy signal processing tilt for accurate reproduction of original outputs;
|
||||
@@ -15,6 +17,7 @@ It currently contains emulations of the:
|
||||
* Atari ST;
|
||||
* ColecoVision;
|
||||
* Commodore Vic-20 (and Commodore 1540/1);
|
||||
* Enterprise 64/128;
|
||||
* Macintosh 512ke and Plus;
|
||||
* MSX 1;
|
||||
* Oric 1/Atmos;
|
||||
@@ -22,7 +25,7 @@ It currently contains emulations of the:
|
||||
* Sinclair ZX80/81; and
|
||||
* Sinclair ZX Spectrum.
|
||||
|
||||
macOS and source releases are [hosted on GitHub](https://github.com/TomHarte/CLK/releases). For desktop Linux it is also available as a [Snap](https://snapcraft.io/clock-signal). On the Mac it is a native Cocoa and Metal application; under Linux, BSD and other UNIXes and UNIX-alikes it uses OpenGL and can be built either with Qt or with SDL.
|
||||
On the Mac it is a native Cocoa and Metal application; under Linux, BSD and other UNIXes and UNIX-alikes it uses OpenGL and can be built either with Qt or with SDL.
|
||||
|
||||
## Single-step Loading
|
||||
|
||||
@@ -83,6 +86,7 @@ This emulator attempts cycle-accurate emulation of all supported machines. In so
|
||||
| | 
|
||||
| | 
|
||||
| | 
|
||||
| | 
|
||||
|
||||

|
||||

|
||||
@@ -91,4 +95,4 @@ This emulator attempts cycle-accurate emulation of all supported machines. In so
|
||||
|
||||
I've been asked several times whether it is possible to sponsor this project; I think that's a poor fit for this emulator's highly-malleable scope, and it makes me uncomfortable because as the author I primarily see only its defects.
|
||||
|
||||
An Amazon US wishlist is now attached in the hope of avoiding the question in future. A lot of it is old books now available only secondhand — I like to read about potential future additions well in advance of starting on them. Per the optimism of some book sellers, please don't purchase anything that is currnetly listed only at an absurd price; they were sorted by secondhand price when added to the list, with cheapest being $5.
|
||||
An Amazon US wishlist is now attached in the hope of avoiding the question in future. A lot of it is old books now available only secondhand — I like to read about potential future additions well in advance of starting on them. Despite the optimism of some book sellers, please don't purchase anything that is currently listed only at an absurd price; they were sorted by secondhand price when added to the list, with the cheapest being $5.
|
||||
|
||||
BIN
READMEImages/EnterpriseHERO.png
Normal file
BIN
READMEImages/EnterpriseHERO.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
BIN
READMEImages/EnterpriseStartup.png
Normal file
BIN
READMEImages/EnterpriseStartup.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
5
ROMImages/Enterprise/readme.txt
Normal file
5
ROMImages/Enterprise/readme.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
ROM files would ordinarily go here; the copyright status of these is uncertain so they have not been included in this repository.
|
||||
|
||||
Expected files:
|
||||
|
||||
exos.rom
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#include "FIRFilter.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#ifndef M_PI
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define USE_ACCELERATE
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace SignalProcessing {
|
||||
|
||||
@@ -49,8 +49,10 @@ class Controller:
|
||||
void run_for(const Cycles cycles);
|
||||
|
||||
/*!
|
||||
Sets the current drive(s). Normally this will be exactly one, but some machines allow
|
||||
zero or multiple drives to be attached, with useless results.
|
||||
Sets the current drive(s), by bit mask. Normally this will be exactly one, but some
|
||||
machines allow zero or multiple drives to be attached, with useless results.
|
||||
|
||||
E.g. supply 1 to select drive 0, 2 to select drive 1, 4 to select drive 2, etc.
|
||||
*/
|
||||
void set_drive(int index_mask);
|
||||
|
||||
|
||||
57
Storage/Disk/DiskImage/Formats/FAT12.cpp
Normal file
57
Storage/Disk/DiskImage/Formats/FAT12.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// FAT12.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 07/01/2018.
|
||||
// Copyright 2018 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "FAT12.hpp"
|
||||
|
||||
#include "Utility/ImplicitSectors.hpp"
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
FAT12::FAT12(const std::string &file_name) :
|
||||
MFMSectorDump(file_name) {
|
||||
// The only sanity check here is whether a sensible
|
||||
// geometry is encoded in the first sector, or can be guessed.
|
||||
off_t file_size = file_.stats().st_size;
|
||||
|
||||
if(file_size < 512) throw Error::InvalidFormat;
|
||||
|
||||
// Inspect the FAT.
|
||||
file_.seek(11, SEEK_SET);
|
||||
sector_size_ = file_.get16le();
|
||||
file_.seek(19, SEEK_SET);
|
||||
const uint16_t total_sectors = file_.get16le();
|
||||
file_.seek(24, SEEK_SET);
|
||||
sector_count_ = file_.get16le();
|
||||
head_count_ = file_.get16le();
|
||||
|
||||
// Throw if there would seemingly be an incomplete track.
|
||||
if(file_size != total_sectors*sector_size_) throw Error::InvalidFormat;
|
||||
if(total_sectors % (head_count_ * sector_count_)) throw Error::InvalidFormat;
|
||||
track_count_ = int(total_sectors / (head_count_ * sector_count_));
|
||||
|
||||
// Check that there is a valid power-of-two sector size.
|
||||
uint8_t log_sector_size = 2;
|
||||
while(log_sector_size < 5 && (1 << (7+log_sector_size)) != sector_size_) {
|
||||
++log_sector_size;
|
||||
}
|
||||
if(log_sector_size >= 5) throw Error::InvalidFormat;
|
||||
|
||||
set_geometry(sector_count_, log_sector_size, 1, true);
|
||||
}
|
||||
|
||||
HeadPosition FAT12::get_maximum_head_position() {
|
||||
return HeadPosition(track_count_);
|
||||
}
|
||||
|
||||
int FAT12::get_head_count() {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
long FAT12::get_file_offset_for_position(Track::Address address) {
|
||||
return (address.position.as_int()*head_count_ + address.head) * sector_size_ * sector_count_;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// MSXDSK.hpp
|
||||
// FAT12.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 07/01/2018.
|
||||
@@ -17,12 +17,12 @@ namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
/*!
|
||||
Provides a @c DiskImage descriging an MSX-style disk image:
|
||||
Provides a @c DiskImage holding an MSDOS-style FAT12 disk image:
|
||||
a sector dump of appropriate proportions.
|
||||
*/
|
||||
class MSXDSK: public MFMSectorDump {
|
||||
class FAT12: public MFMSectorDump {
|
||||
public:
|
||||
MSXDSK(const std::string &file_name);
|
||||
FAT12(const std::string &file_name);
|
||||
HeadPosition get_maximum_head_position() final;
|
||||
int get_head_count() final;
|
||||
|
||||
@@ -31,6 +31,8 @@ class MSXDSK: public MFMSectorDump {
|
||||
|
||||
int head_count_;
|
||||
int track_count_;
|
||||
int sector_count_;
|
||||
int sector_size_;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
//
|
||||
// MSXDSK.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 07/01/2018.
|
||||
// Copyright 2018 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "MSXDSK.hpp"
|
||||
|
||||
#include "Utility/ImplicitSectors.hpp"
|
||||
|
||||
namespace {
|
||||
constexpr int sectors_per_track = 9;
|
||||
constexpr int sector_size = 2;
|
||||
constexpr off_t track_size = (128 << sector_size)*sectors_per_track;
|
||||
}
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
MSXDSK::MSXDSK(const std::string &file_name) :
|
||||
MFMSectorDump(file_name) {
|
||||
// The only sanity check here is whether a sensible
|
||||
// geometry can be guessed.
|
||||
off_t file_size = file_.stats().st_size;
|
||||
|
||||
// Throw if there would seemingly be an incomplete track.
|
||||
if(file_size % track_size) throw Error::InvalidFormat;
|
||||
|
||||
track_count_ = int(file_size / track_size);
|
||||
head_count_ = 1;
|
||||
|
||||
// Throw if too large or too small or too large for single sided and
|
||||
// clearly not double sided.
|
||||
if(track_count_ < 40) throw Error::InvalidFormat;
|
||||
if(track_count_ > 82*2) throw Error::InvalidFormat;
|
||||
if(track_count_ > 82 && track_count_&1) throw Error::InvalidFormat;
|
||||
|
||||
// The below effectively prefers the idea of a single-sided 80-track disk
|
||||
// to a double-sided 40-track disk. Emulators have to guess.
|
||||
if(track_count_ > 82) {
|
||||
track_count_ /= 2;
|
||||
head_count_ = 2;
|
||||
}
|
||||
|
||||
set_geometry(sectors_per_track, sector_size, 1, true);
|
||||
}
|
||||
|
||||
HeadPosition MSXDSK::get_maximum_head_position() {
|
||||
return HeadPosition(track_count_);
|
||||
}
|
||||
|
||||
int MSXDSK::get_head_count() {
|
||||
return head_count_;
|
||||
}
|
||||
|
||||
long MSXDSK::get_file_offset_for_position(Track::Address address) {
|
||||
return (address.position.as_int()*head_count_ + address.head) * 512 * 9;
|
||||
}
|
||||
@@ -57,6 +57,6 @@ void Storage::Disk::decode_sectors(Track &track, uint8_t *const destination, uin
|
||||
if(pair.second.address.sector < first_sector) continue;
|
||||
if(pair.second.size != sector_size) continue;
|
||||
if(pair.second.samples.empty()) continue;
|
||||
std::memcpy(&destination[pair.second.address.sector * byte_size], pair.second.samples[0].data(), std::min(pair.second.samples[0].size(), byte_size));
|
||||
std::memcpy(&destination[(pair.second.address.sector - first_sector) * byte_size], pair.second.samples[0].data(), std::min(pair.second.samples[0].size(), byte_size));
|
||||
}
|
||||
}
|
||||
|
||||
179
Storage/Disk/Parsers/FAT.cpp
Normal file
179
Storage/Disk/Parsers/FAT.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
//
|
||||
// FAT.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 02/07/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "FAT.hpp"
|
||||
|
||||
#include "../Encodings/MFM/Parser.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
FAT::Volume::CHS FAT::Volume::chs_for_sector(int sector) const {
|
||||
const auto track = sector / sectors_per_track;
|
||||
|
||||
// Sides are interleaved.
|
||||
return CHS{
|
||||
track / head_count,
|
||||
track % head_count,
|
||||
1 + (sector % sectors_per_track)
|
||||
};
|
||||
}
|
||||
|
||||
int FAT::Volume::sector_for_cluster(uint16_t cluster) const {
|
||||
// The first cluster in the data area is numbered as 2.
|
||||
return ((cluster - 2) * sectors_per_cluster) + first_data_sector;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename CharT> std::string trim(CharT start, CharT end) {
|
||||
std::string result(start, end);
|
||||
result.erase(std::find_if(result.rbegin(), result.rend(), [](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
}).base(), result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
FAT::Directory directory_from(const std::vector<uint8_t> &contents) {
|
||||
FAT::Directory result;
|
||||
|
||||
// Worst case: parse until the amount of data supplied is fully consumed.
|
||||
for(size_t base = 0; base < contents.size(); base += 32) {
|
||||
// An entry starting with byte 0 indicates end-of-directory.
|
||||
if(!contents[base]) {
|
||||
break;
|
||||
}
|
||||
|
||||
// An entry starting in 0xe5 is merely deleted.
|
||||
if(contents[base] == 0xe5) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise create and populate a new entry.
|
||||
result.emplace_back();
|
||||
result.back().name = trim(&contents[base], &contents[base+8]);
|
||||
result.back().extension = trim(&contents[base+8], &contents[base+11]);
|
||||
result.back().attributes = contents[base + 11];
|
||||
result.back().time = uint16_t(contents[base+22] | (contents[base+23] << 8));
|
||||
result.back().date = uint16_t(contents[base+24] | (contents[base+25] << 8));
|
||||
result.back().starting_cluster = uint16_t(contents[base+26] | (contents[base+27] << 8));
|
||||
result.back().size = uint32_t(
|
||||
contents[base+28] |
|
||||
(contents[base+29] << 8) |
|
||||
(contents[base+30] << 16) |
|
||||
(contents[base+31] << 24)
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::optional<FAT::Volume> FAT::GetVolume(const std::shared_ptr<Storage::Disk::Disk> &disk) {
|
||||
Storage::Encodings::MFM::Parser parser(true, disk);
|
||||
|
||||
// Grab the boot sector; that'll be enough to establish the volume.
|
||||
Storage::Encodings::MFM::Sector *const boot_sector = parser.get_sector(0, 0, 1);
|
||||
if(!boot_sector || boot_sector->samples.empty() || boot_sector->samples[0].size() < 512) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Obtain volume details.
|
||||
const auto &data = boot_sector->samples[0];
|
||||
FAT::Volume volume;
|
||||
volume.bytes_per_sector = uint16_t(data[11] | (data[12] << 8));
|
||||
volume.sectors_per_cluster = data[13];
|
||||
volume.reserved_sectors = uint16_t(data[14] | (data[15] << 8));
|
||||
volume.fat_copies = data[16];
|
||||
const uint16_t root_directory_entries = uint16_t(data[17] | (data[18] << 8));
|
||||
volume.total_sectors = uint16_t(data[19] | (data[20] << 8));
|
||||
volume.sectors_per_fat = uint16_t(data[22] | (data[23] << 8));
|
||||
volume.sectors_per_track = uint16_t(data[24] | (data[25] << 8));
|
||||
volume.head_count = uint16_t(data[26] | (data[27] << 8));
|
||||
volume.correct_signature = data[510] == 0x55 && data[511] == 0xaa;
|
||||
|
||||
const size_t root_directory_sectors = (root_directory_entries*32 + volume.bytes_per_sector - 1) / volume.bytes_per_sector;
|
||||
volume.first_data_sector = int(volume.reserved_sectors + volume.sectors_per_fat*volume.fat_copies + root_directory_sectors);
|
||||
|
||||
// Grab the FAT.
|
||||
std::vector<uint8_t> source_fat;
|
||||
for(int c = 0; c < volume.sectors_per_fat; c++) {
|
||||
const int sector_number = volume.reserved_sectors + c;
|
||||
const auto address = volume.chs_for_sector(sector_number);
|
||||
|
||||
Storage::Encodings::MFM::Sector *const fat_sector =
|
||||
parser.get_sector(address.head, address.cylinder, uint8_t(address.sector));
|
||||
if(!fat_sector || fat_sector->samples.empty() || fat_sector->samples[0].size() != volume.bytes_per_sector) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::copy(fat_sector->samples[0].begin(), fat_sector->samples[0].end(), std::back_inserter(source_fat));
|
||||
}
|
||||
|
||||
// Decode the FAT.
|
||||
// TODO: stop assuming FAT12 here.
|
||||
for(size_t c = 0; c < source_fat.size(); c += 3) {
|
||||
const uint32_t double_cluster = uint32_t(source_fat[c] + (source_fat[c + 1] << 8) + (source_fat[c + 2] << 16));
|
||||
volume.fat.push_back(uint16_t(double_cluster & 0xfff));
|
||||
volume.fat.push_back(uint16_t(double_cluster >> 12));
|
||||
}
|
||||
|
||||
// Grab the root directory.
|
||||
std::vector<uint8_t> root_directory;
|
||||
for(size_t c = 0; c < root_directory_sectors; c++) {
|
||||
const auto sector_number = int(volume.reserved_sectors + c + volume.sectors_per_fat*volume.fat_copies);
|
||||
const auto address = volume.chs_for_sector(sector_number);
|
||||
|
||||
Storage::Encodings::MFM::Sector *const sector =
|
||||
parser.get_sector(address.head, address.cylinder, uint8_t(address.sector));
|
||||
if(!sector || sector->samples.empty() || sector->samples[0].size() != volume.bytes_per_sector) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::copy(sector->samples[0].begin(), sector->samples[0].end(), std::back_inserter(root_directory));
|
||||
}
|
||||
volume.root_directory = directory_from(root_directory);
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
std::optional<std::vector<uint8_t>> FAT::GetFile(const std::shared_ptr<Storage::Disk::Disk> &disk, const Volume &volume, const File &file) {
|
||||
Storage::Encodings::MFM::Parser parser(true, disk);
|
||||
|
||||
std::vector<uint8_t> contents;
|
||||
|
||||
// In FAT cluster numbers describe a linked list via the FAT table, with values above $FF0 being reserved
|
||||
// (relevantly: FF7 means bad cluster; FF8–FFF mean end-of-file).
|
||||
uint16_t cluster = file.starting_cluster;
|
||||
do {
|
||||
const int sector = volume.sector_for_cluster(cluster);
|
||||
|
||||
for(int c = 0; c < volume.sectors_per_cluster; c++) {
|
||||
const auto address = volume.chs_for_sector(sector + c);
|
||||
|
||||
Storage::Encodings::MFM::Sector *const sector_contents =
|
||||
parser.get_sector(address.head, address.cylinder, uint8_t(address.sector));
|
||||
if(!sector_contents || sector_contents->samples.empty() || sector_contents->samples[0].size() != volume.bytes_per_sector) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::copy(sector_contents->samples[0].begin(), sector_contents->samples[0].end(), std::back_inserter(contents));
|
||||
}
|
||||
|
||||
cluster = volume.fat[cluster];
|
||||
} while(cluster < 0xff0);
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::optional<FAT::Directory> FAT::GetDirectory(const std::shared_ptr<Storage::Disk::Disk> &disk, const Volume &volume, const File &file) {
|
||||
const auto contents = GetFile(disk, volume, file);
|
||||
if(!contents) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return directory_from(*contents);
|
||||
}
|
||||
79
Storage/Disk/Parsers/FAT.hpp
Normal file
79
Storage/Disk/Parsers/FAT.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// FAT.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 02/07/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Storage_Disk_Parsers_FAT_hpp
|
||||
#define Storage_Disk_Parsers_FAT_hpp
|
||||
|
||||
#include "../Disk.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Storage {
|
||||
namespace Disk {
|
||||
namespace FAT {
|
||||
|
||||
struct File {
|
||||
std::string name;
|
||||
std::string extension;
|
||||
uint8_t attributes = 0;
|
||||
uint16_t time = 0; // TODO: offer time/date decoders.
|
||||
uint16_t date = 0;
|
||||
uint16_t starting_cluster = 0;
|
||||
uint32_t size = 0;
|
||||
|
||||
enum Attribute: uint8_t {
|
||||
ReadOnly = (1 << 0),
|
||||
Hidden = (1 << 1),
|
||||
System = (1 << 2),
|
||||
VolumeLabel = (1 << 3),
|
||||
Directory = (1 << 4),
|
||||
Archive = (1 << 5),
|
||||
};
|
||||
};
|
||||
|
||||
using Directory = std::vector<File>;
|
||||
|
||||
struct Volume {
|
||||
uint16_t bytes_per_sector = 0;
|
||||
uint8_t sectors_per_cluster = 0;
|
||||
uint16_t reserved_sectors = 0;
|
||||
uint8_t fat_copies = 0;
|
||||
uint16_t total_sectors = 0;
|
||||
uint16_t sectors_per_fat = 0;
|
||||
uint16_t sectors_per_track = 0;
|
||||
uint16_t head_count = 0;
|
||||
uint16_t hidden_sectors = 0;
|
||||
bool correct_signature = false;
|
||||
int first_data_sector = 0;
|
||||
|
||||
std::vector<uint16_t> fat;
|
||||
Directory root_directory;
|
||||
|
||||
struct CHS {
|
||||
int cylinder;
|
||||
int head;
|
||||
int sector;
|
||||
};
|
||||
/// @returns a direct sector -> CHS address translation.
|
||||
CHS chs_for_sector(int sector) const;
|
||||
/// @returns the CHS address for the numbered cluster within the data area.
|
||||
int sector_for_cluster(uint16_t cluster) const;
|
||||
};
|
||||
|
||||
std::optional<Volume> GetVolume(const std::shared_ptr<Storage::Disk::Disk> &disk);
|
||||
std::optional<std::vector<uint8_t>> GetFile(const std::shared_ptr<Storage::Disk::Disk> &disk, const Volume &volume, const File &file);
|
||||
std::optional<Directory> GetDirectory(const std::shared_ptr<Storage::Disk::Disk> &disk, const Volume &volume, const File &file);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FAT_hpp */
|
||||
@@ -29,13 +29,14 @@ enum Type: IntType {
|
||||
Coleco = 1 << 10,
|
||||
Commodore = 1 << 11,
|
||||
DiskII = 1 << 12,
|
||||
Sega = 1 << 13,
|
||||
Macintosh = 1 << 14,
|
||||
MSX = 1 << 15,
|
||||
Oric = 1 << 16,
|
||||
ZX80 = 1 << 17,
|
||||
ZX81 = 1 << 18,
|
||||
ZXSpectrum = 1 << 19,
|
||||
Enterprise = 1 << 13,
|
||||
Sega = 1 << 14,
|
||||
Macintosh = 1 << 15,
|
||||
MSX = 1 << 16,
|
||||
Oric = 1 << 17,
|
||||
ZX80 = 1 << 18,
|
||||
ZX81 = 1 << 19,
|
||||
ZXSpectrum = 1 << 20,
|
||||
|
||||
Acorn = AcornAtom | AcornElectron | BBCMaster | BBCModelA | BBCModelB,
|
||||
ZX8081 = ZX80 | ZX81,
|
||||
|
||||
Reference in New Issue
Block a user