mirror of
https://github.com/TomHarte/CLK.git
synced 2025-10-25 09:27:01 +00:00
Compare commits
25 Commits
2020-11-07
...
2020-11-29
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32ccce3040 | ||
|
|
ab3fcb3ea0 | ||
|
|
9610672615 | ||
|
|
5ee9630624 | ||
|
|
1b3836eb1c | ||
|
|
1302a046e9 | ||
|
|
33dec3c220 | ||
|
|
7c29c3a944 | ||
|
|
c9ca1fc7a0 | ||
|
|
a965c8de9f | ||
|
|
0b4b271e3d | ||
|
|
5fc6dd1a4d | ||
|
|
79ef026b93 | ||
|
|
a4ab5b0b49 | ||
|
|
3207183f05 | ||
|
|
e803f993b7 | ||
|
|
5dbc87caf0 | ||
|
|
4862ccc947 | ||
|
|
e1ecf66485 | ||
|
|
2c71ba0744 | ||
|
|
a7aeb779e9 | ||
|
|
e72cfbf447 | ||
|
|
5d154e3d0c | ||
|
|
86a24cc928 | ||
|
|
e8b52d20e9 |
@@ -804,38 +804,62 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine:
|
||||
m6502_.run_for(cycles);
|
||||
}
|
||||
|
||||
void reset_all_keys(Inputs::Keyboard *) final {
|
||||
void reset_all_keys() final {
|
||||
open_apple_is_pressed_ = closed_apple_is_pressed_ = key_is_down_ = false;
|
||||
}
|
||||
|
||||
bool prefers_logical_input() final {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set_key_pressed(Key key, char value, bool is_pressed) final {
|
||||
// If no ASCII value is supplied, look for a few special cases.
|
||||
switch(key) {
|
||||
default: break;
|
||||
case Key::F12:
|
||||
m6502_.set_reset_line(is_pressed);
|
||||
return true;
|
||||
case Key::Left: value = 0x08; break;
|
||||
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::Enter: value = 0x0d; break;
|
||||
case Key::Tab: value = '\t'; break;
|
||||
case Key::Escape: value = 0x1b; break;
|
||||
|
||||
case Key::LeftOption:
|
||||
case Key::RightMeta:
|
||||
open_apple_is_pressed_ = is_pressed;
|
||||
return true;
|
||||
|
||||
case Key::RightOption:
|
||||
case Key::LeftMeta:
|
||||
closed_apple_is_pressed_ = is_pressed;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If no ASCII value is supplied, look for a few special cases.
|
||||
if(!value) {
|
||||
switch(key) {
|
||||
case Key::Left: value = 0x08; break;
|
||||
case Key::Right: value = 0x15; break;
|
||||
case Key::Down: value = 0x0a; break;
|
||||
case Key::Up: value = 0x0b; break;
|
||||
case Key::Backspace: value = 0x7f; break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
case Key::F1: case Key::F2: case Key::F3: case Key::F4:
|
||||
case Key::F5: case Key::F6: case Key::F7: case Key::F8:
|
||||
case Key::F9: case Key::F10: case Key::F11: case Key::F12:
|
||||
case Key::PrintScreen:
|
||||
case Key::ScrollLock:
|
||||
case Key::Pause:
|
||||
case Key::Insert:
|
||||
case Key::Home:
|
||||
case Key::PageUp:
|
||||
case Key::PageDown:
|
||||
case Key::End:
|
||||
// Accept a bunch non-symbolic other keys, as
|
||||
// reset, in the hope that the user can find
|
||||
// at least one usable key.
|
||||
m6502_.set_reset_line(is_pressed);
|
||||
return true;
|
||||
|
||||
// Prior to the IIe, the keyboard could produce uppercase only.
|
||||
if(!is_iie()) value = char(toupper(value));
|
||||
default:
|
||||
if(!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prior to the IIe, the keyboard could produce uppercase only.
|
||||
if(!is_iie()) value = char(toupper(value));
|
||||
break;
|
||||
}
|
||||
|
||||
if(is_pressed) {
|
||||
keyboard_input_ = uint8_t(value | 0x80);
|
||||
|
||||
@@ -32,6 +32,11 @@ struct KeyActions {
|
||||
Instructs that all keys should now be treated as released.
|
||||
*/
|
||||
virtual void clear_all_keys() {}
|
||||
|
||||
/*!
|
||||
Indicates whether a machine most naturally accepts logical rather than physical input.
|
||||
*/
|
||||
virtual bool prefers_logical_input() { return false; }
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@@ -4084,7 +4084,7 @@
|
||||
};
|
||||
4BB73E9D1B587A5100552FC2 = {
|
||||
CreatedOnToolsVersion = 7.0;
|
||||
DevelopmentTeam = CP2SKEB3XT;
|
||||
DevelopmentTeam = DV3346VVUN;
|
||||
LastSwiftMigration = 1020;
|
||||
ProvisioningStyle = Automatic;
|
||||
SystemCapabilities = {
|
||||
@@ -5175,7 +5175,7 @@
|
||||
"$(USER_LIBRARY_DIR)/Frameworks",
|
||||
);
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
@@ -5198,7 +5198,8 @@
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_OPTIMIZATION_LEVEL = 2;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = NDEBUG;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
@@ -5252,7 +5253,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@@ -5305,7 +5306,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = macosx;
|
||||
@@ -5327,8 +5328,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Clock Signal/Clock Signal.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = DV3346VVUN;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -5373,8 +5373,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Clock Signal/Clock Signal.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = DV3346VVUN;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -5395,6 +5394,7 @@
|
||||
INFOPLIST_FILE = "Clock Signal/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MTL_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(OTHER_CFLAGS)",
|
||||
"-Wreorder",
|
||||
@@ -5416,7 +5416,6 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Clock Signal/Clock Signal.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = NO;
|
||||
INFOPLIST_FILE = "Clock SignalTests/Info.plist";
|
||||
@@ -5440,7 +5439,6 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Clock Signal/Clock Signal.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 2;
|
||||
@@ -5458,7 +5456,6 @@
|
||||
4BB73ECD1B587A5100552FC2 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = CP2SKEB3XT;
|
||||
INFOPLIST_FILE = "Clock SignalUITests/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||
@@ -5473,7 +5470,6 @@
|
||||
4BB73ECE1B587A5100552FC2 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = CP2SKEB3XT;
|
||||
INFOPLIST_FILE = "Clock SignalUITests/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Release"
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
disableMainThreadChecker = "YES"
|
||||
@@ -58,8 +58,16 @@
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Macintosh/MusicWorks 0.42.image""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "/Users/thomasharte/Library/Mobile\ Documents/com\~apple\~CloudDocs/Desktop/Soft/Apple\ II/Keplermatik.dsk"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "/Users/thomasharte/Library/Mobile\ Documents/com\~apple\~CloudDocs/Desktop/Soft/Apple\ II/WOZs/Prince\ of\ Persia\ side\ A.woz"
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "--volume=0.001"
|
||||
isEnabled = "NO">
|
||||
|
||||
@@ -88,14 +88,30 @@ class MachineDocument:
|
||||
}
|
||||
|
||||
override func close() {
|
||||
// Close any dangling sheets.
|
||||
//
|
||||
// Be warned: in 11.0 at least, if there are any panels then posting the endSheet request
|
||||
// will defer the close(), and close() will be called again at the end of that animation.
|
||||
//
|
||||
// So: MAKE SURE IT'S SAFE TO ENTER THIS FUNCTION TWICE. Hence the non-assumption here about
|
||||
// any windows still existing.
|
||||
if self.windowControllers.count > 0, let window = self.windowControllers[0].window {
|
||||
for sheet in window.sheets {
|
||||
window.endSheet(sheet)
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the machine, if any.
|
||||
machine?.stop()
|
||||
|
||||
// Dismiss panels.
|
||||
activityPanel?.setIsVisible(false)
|
||||
activityPanel = nil
|
||||
|
||||
optionsPanel?.setIsVisible(false)
|
||||
optionsPanel = nil
|
||||
|
||||
// End the update cycle.
|
||||
actionLock.lock()
|
||||
drawLock.lock()
|
||||
machine = nil
|
||||
@@ -103,6 +119,7 @@ class MachineDocument:
|
||||
actionLock.unlock()
|
||||
drawLock.unlock()
|
||||
|
||||
// Let the document controller do its thing.
|
||||
super.close()
|
||||
}
|
||||
|
||||
@@ -144,35 +161,37 @@ class MachineDocument:
|
||||
private var interactionMode: InteractionMode = .notStarted
|
||||
|
||||
// Attempting to show a sheet before the window is visible (such as when the NIB is loaded) results in
|
||||
// a sheet mysteriously floating on its own. For now, use windowDidUpdate as a proxy to know that the window
|
||||
// is visible, though it's a little premature.
|
||||
// a sheet mysteriously floating on its own. For now, use windowDidUpdate as a proxy to check whether
|
||||
// the window is visible.
|
||||
func windowDidUpdate(_ notification: Notification) {
|
||||
// Grab the regular window title, if it's not already stored.
|
||||
if self.unadornedWindowTitle.count == 0 {
|
||||
self.unadornedWindowTitle = self.windowControllers[0].window!.title
|
||||
}
|
||||
|
||||
// If an interaction mode is not yet in effect, pick the proper one and display the relevant thing.
|
||||
if self.interactionMode == .notStarted {
|
||||
// If a full machine exists, just continue showing it.
|
||||
if self.machine != nil {
|
||||
self.interactionMode = .showingMachine
|
||||
setupMachineOutput()
|
||||
return
|
||||
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 {
|
||||
self.unadornedWindowTitle = window.title
|
||||
}
|
||||
|
||||
// If a machine has been picked but is not showing, there must be ROMs missing.
|
||||
if self.machineDescription != nil {
|
||||
self.interactionMode = .showingROMRequester
|
||||
requestRoms()
|
||||
return
|
||||
}
|
||||
// If an interaction mode is not yet in effect, pick the proper one and display the relevant thing.
|
||||
if self.interactionMode == .notStarted {
|
||||
// If a full machine exists, just continue showing it.
|
||||
if self.machine != nil {
|
||||
self.interactionMode = .showingMachine
|
||||
setupMachineOutput()
|
||||
return
|
||||
}
|
||||
|
||||
// If a machine hasn't even been picked yet, show the machine picker.
|
||||
self.interactionMode = .showingMachinePicker
|
||||
Bundle.main.loadNibNamed("MachinePicker", owner: self, topLevelObjects: nil)
|
||||
self.machinePicker?.establishStoredOptions()
|
||||
self.windowControllers[0].window?.beginSheet(self.machinePickerPanel!, completionHandler: nil)
|
||||
// If a machine has been picked but is not showing, there must be ROMs missing.
|
||||
if self.machineDescription != nil {
|
||||
self.interactionMode = .showingROMRequester
|
||||
requestRoms()
|
||||
return
|
||||
}
|
||||
|
||||
// If a machine hasn't even been picked yet, show the machine picker.
|
||||
self.interactionMode = .showingMachinePicker
|
||||
Bundle.main.loadNibNamed("MachinePicker", owner: self, topLevelObjects: nil)
|
||||
self.machinePicker?.establishStoredOptions()
|
||||
window.beginSheet(self.machinePickerPanel!, completionHandler: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16097" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17506" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17506"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
@@ -17,14 +17,14 @@
|
||||
<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="720" height="205"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="3840" height="2137"/>
|
||||
<rect key="contentRect" x="196" y="240" width="725" height="205"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="720" height="205"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="725" height="205"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hKn-1l-OSN">
|
||||
<rect key="frame" x="619" y="13" width="87" height="32"/>
|
||||
<rect key="frame" x="631" y="13" width="81" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Choose" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="MnM-xo-4Qa">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
@@ -37,7 +37,7 @@ DQ
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JQy-Cj-AOK">
|
||||
<rect key="frame" x="538" y="13" width="82" height="32"/>
|
||||
<rect key="frame" x="558" y="13" width="76" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sub-rB-Req">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
@@ -50,7 +50,7 @@ Gw
|
||||
</connections>
|
||||
</button>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9YM-5x-pc0">
|
||||
<rect key="frame" x="20" y="15" width="398" height="32"/>
|
||||
<rect key="frame" x="20" y="14" width="398" height="32"/>
|
||||
<textFieldCell key="cell" allowsUndo="NO" sendsActionOnEndEditing="YES" id="xTm-Oy-oz5">
|
||||
<font key="font" metaFont="system"/>
|
||||
<string key="title">If you use File -> Open... to select a disk, tape or cartridge directly, the emulator will select and configure a machine for you.</string>
|
||||
@@ -59,16 +59,16 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<tabView translatesAutoresizingMaskIntoConstraints="NO" id="VUb-QG-x7c">
|
||||
<rect key="frame" x="13" y="51" width="694" height="140"/>
|
||||
<rect key="frame" x="13" y="50" width="699" height="141"/>
|
||||
<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="33" width="674" height="94"/>
|
||||
<rect key="frame" x="10" y="33" width="679" height="95"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="V5Z-dX-Ns4">
|
||||
<rect key="frame" x="15" y="73" width="46" height="16"/>
|
||||
<rect key="frame" x="15" y="74" 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="15" y="42" width="96" height="16"/>
|
||||
<rect key="frame" x="15" y="44" 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,10 +84,10 @@ Gw
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="jli-ac-Sij">
|
||||
<rect key="frame" x="65" y="67" width="116" height="25"/>
|
||||
<rect key="frame" x="64" y="68" width="117" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Apple II" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="VBQ-JG-AeM" id="U6V-us-O2F">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="esp-ir-7iH">
|
||||
<items>
|
||||
<menuItem title="Apple II" state="on" id="VBQ-JG-AeM"/>
|
||||
@@ -99,10 +99,10 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="LSB-WP-FMi">
|
||||
<rect key="frame" x="115" y="36" width="133" height="25"/>
|
||||
<rect key="frame" x="114" y="38" 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="proportionallyDown" inset="2" selectedItem="QaV-Yr-k9o" id="8BT-RV-2Nm">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="udQ-NK-FG8">
|
||||
<items>
|
||||
<menuItem title="Sixteen Sector" state="on" tag="16" id="QaV-Yr-k9o"/>
|
||||
@@ -130,14 +130,14 @@ Gw
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Amstrad CPC" identifier="cpc" id="JmB-OF-xcM">
|
||||
<view key="view" id="5zS-Nj-Ynx">
|
||||
<rect key="frame" x="10" y="33" width="674" height="94"/>
|
||||
<rect key="frame" x="10" y="33" width="679" height="95"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="00d-sg-Krh">
|
||||
<rect key="frame" x="65" y="67" width="95" height="25"/>
|
||||
<rect key="frame" x="64" y="68" width="96" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="CPC6128" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="6128" imageScaling="proportionallyDown" inset="2" selectedItem="klh-ZE-Agp" id="hVJ-h6-iea">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="r3D-C2-Ruq">
|
||||
<items>
|
||||
<menuItem title="CPC464" tag="464" id="5kZ-XF-RFl"/>
|
||||
@@ -148,7 +148,7 @@ Gw
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="q9q-sl-J0q">
|
||||
<rect key="frame" x="15" y="73" width="46" height="16"/>
|
||||
<rect key="frame" x="15" y="74" 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"/>
|
||||
@@ -235,7 +235,7 @@ Gw
|
||||
<rect key="frame" x="65" y="67" width="74" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Plus" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="3" imageScaling="proportionallyDown" inset="2" selectedItem="R6T-hg-rOF" id="1Kb-Q2-BGM">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="ofy-j9-YnU">
|
||||
<items>
|
||||
<menuItem title="512ke" tag="2" id="WCG-6u-ANQ"/>
|
||||
@@ -271,7 +271,7 @@ Gw
|
||||
<rect key="frame" x="69" y="67" width="145" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="European (PAL)" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="xAh-Ch-tby" id="yR4-yv-Lvu">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="BCR-rp-Kpc">
|
||||
<items>
|
||||
<menuItem title="European (PAL)" state="on" id="xAh-Ch-tby"/>
|
||||
@@ -320,7 +320,7 @@ Gw
|
||||
<rect key="frame" x="65" y="67" width="106" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Oric-1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="jGN-1a-biF" id="Jll-EJ-cMr">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="E9d-fH-Eak">
|
||||
<items>
|
||||
<menuItem title="Oric-1" state="on" id="jGN-1a-biF"/>
|
||||
@@ -334,7 +334,7 @@ Gw
|
||||
<rect key="frame" x="111" y="36" width="129" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="None" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="XhK-Jh-oTW" id="aYb-m1-H9X">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="hy3-Li-nlW">
|
||||
<items>
|
||||
<menuItem title="None" state="on" id="XhK-Jh-oTW"/>
|
||||
@@ -379,7 +379,7 @@ Gw
|
||||
<rect key="frame" x="69" y="67" width="145" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="European (PAL)" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="45i-0n-gau" id="yi7-eo-I0q">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="uCQ-9l-eBb">
|
||||
<items>
|
||||
<menuItem title="European (PAL)" state="on" id="45i-0n-gau"/>
|
||||
@@ -395,7 +395,7 @@ Gw
|
||||
<rect key="frame" x="106" y="36" width="115" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="fOl-8Q-fsA" id="rH0-7T-pJE">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="e9J-Ie-PjH">
|
||||
<items>
|
||||
<menuItem title="Unexpanded" state="on" id="fOl-8Q-fsA"/>
|
||||
@@ -456,7 +456,7 @@ Gw
|
||||
<rect key="frame" x="106" y="67" width="115" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="4Sa-jR-xOd" id="B8M-do-Yod">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="Of4-DY-mE5">
|
||||
<items>
|
||||
<menuItem title="Unexpanded" state="on" id="4Sa-jR-xOd"/>
|
||||
@@ -504,7 +504,7 @@ Gw
|
||||
<rect key="frame" x="106" y="67" width="115" height="25"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Unexpanded" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="7QC-Ij-hES" id="d3W-Gl-3Mf">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="mua-Lp-9wl">
|
||||
<items>
|
||||
<menuItem title="Unexpanded" state="on" id="7QC-Ij-hES"/>
|
||||
|
||||
@@ -51,7 +51,11 @@ class MachinePicker: NSObject {
|
||||
|
||||
// Machine type
|
||||
if let machineIdentifier = standardUserDefaults.string(forKey: "new.machine") {
|
||||
machineSelector?.selectTabViewItem(withIdentifier: machineIdentifier as Any)
|
||||
// If I've changed my mind about visible tabs between versions, there may not be one that corresponds
|
||||
// to the stored identifier. Make sure not to raise an NSRangeException in that scenario.
|
||||
if let index = machineSelector?.indexOfTabViewItem(withIdentifier: machineIdentifier as Any), index != NSNotFound {
|
||||
machineSelector?.selectTabViewItem(at: index)
|
||||
}
|
||||
}
|
||||
|
||||
// Apple II settings
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17506" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17506"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
@@ -37,7 +37,7 @@
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nvl-dm-8bK">
|
||||
<rect key="frame" x="384" y="13" width="82" height="32"/>
|
||||
<rect key="frame" x="391" y="13" width="76" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="oS1-Pk-LsO">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
|
||||
@@ -1020,7 +1020,7 @@ bool MainWindow::processEvent(QKeyEvent *event) {
|
||||
const auto keyboardMachine = machine->keyboard_machine();
|
||||
if(!keyboardMachine) return true;
|
||||
|
||||
auto keyboard = keyboardMachine->get_keyboard();
|
||||
auto &keyboard = keyboardMachine->get_keyboard();
|
||||
keyboard.set_key_pressed(*key, event->text().size() ? event->text()[0].toLatin1() : '\0', isPressed);
|
||||
if(keyboard.is_exclusive() || keyboard.observed_keys().find(*key) != keyboard.observed_keys().end()) {
|
||||
return false;
|
||||
|
||||
@@ -783,8 +783,10 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether a 'logical' keyboard has been requested.
|
||||
const bool logical_keyboard = arguments.selections.find("logical-keyboard") != arguments.selections.end();
|
||||
// Check whether a 'logical' keyboard has been requested, or the machine would prefer one anyway.
|
||||
const bool logical_keyboard =
|
||||
(arguments.selections.find("logical-keyboard") != arguments.selections.end()) ||
|
||||
(machine->keyboard_machine() && machine->keyboard_machine()->prefers_logical_input());
|
||||
if(logical_keyboard) {
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
@@ -1162,13 +1164,8 @@ int main(int argc, char *argv[]) {
|
||||
} else {
|
||||
// This is a slightly terrible way of obtaining a symbol for the key, e.g. for letters it will always return
|
||||
// the capital letter version, at least empirically. But it'll have to do for now.
|
||||
//
|
||||
// TODO: ideally have a keyboard machine declare whether it wants either key events or text input? But that
|
||||
// doesn't match machines like the IIe that, to some extent, expose both. So then eliding as attempted above,
|
||||
// and keeping ephemeral track of which symbols have been tied to which keys for the benefit of future key up
|
||||
// events is probably the way forward?
|
||||
const char *key_name = SDL_GetKeyName(keypress.keycode);
|
||||
if(keyboard_machine->get_keyboard().set_key_pressed(key, key_name[0], keypress.is_down)) {
|
||||
if(keyboard_machine->get_keyboard().set_key_pressed(key, (strlen(key_name) == 1) ? key_name[0] : 0, keypress.is_down)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,8 +194,9 @@ std::vector<std::string> ScanTarget::bindings(ShaderType type) const {
|
||||
std::string ScanTarget::sampling_function() const {
|
||||
std::string fragment_shader;
|
||||
const auto modals = BufferingScanTarget::modals();
|
||||
const bool is_svideo = modals.display_type == DisplayType::SVideo;
|
||||
|
||||
if(modals.display_type == DisplayType::SVideo) {
|
||||
if(is_svideo) {
|
||||
fragment_shader +=
|
||||
"vec2 svideo_sample(vec2 coordinate, float angle) {";
|
||||
} else {
|
||||
@@ -203,7 +204,6 @@ std::string ScanTarget::sampling_function() const {
|
||||
"float composite_sample(vec2 coordinate, float angle) {";
|
||||
}
|
||||
|
||||
const bool is_svideo = modals.display_type == DisplayType::SVideo;
|
||||
switch(modals.input_data_type) {
|
||||
case InputDataType::Luminance1:
|
||||
case InputDataType::Luminance8:
|
||||
@@ -341,7 +341,7 @@ std::unique_ptr<Shader> ScanTarget::conversion_shader() const {
|
||||
vertex_shader +=
|
||||
"compositeAngle = (mix(startCompositeAngle, endCompositeAngle, lateral) / 32.0) * 3.141592654;"
|
||||
"compositeAmplitude = lineCompositeAmplitude / 255.0;"
|
||||
"oneOverCompositeAmplitude = mix(0.0, 255.0 / lineCompositeAmplitude, step(0.01, lineCompositeAmplitude));";
|
||||
"oneOverCompositeAmplitude = mix(0.0, 255.0 / lineCompositeAmplitude, step(0.95, lineCompositeAmplitude));";
|
||||
}
|
||||
|
||||
vertex_shader +=
|
||||
@@ -379,40 +379,42 @@ std::unique_ptr<Shader> ScanTarget::conversion_shader() const {
|
||||
|
||||
switch(modals.display_type) {
|
||||
case DisplayType::CompositeColour:
|
||||
fragment_shader +=
|
||||
"vec4 angles = compositeAngle + compositeAngleOffsets;"
|
||||
fragment_shader += R"x(
|
||||
vec4 angles = compositeAngle + compositeAngleOffsets;
|
||||
|
||||
// Sample four times over, at proper angle offsets.
|
||||
"vec4 samples = vec4("
|
||||
"composite_sample(textureCoordinates[0], angles.x),"
|
||||
"composite_sample(textureCoordinates[1], angles.y),"
|
||||
"composite_sample(textureCoordinates[2], angles.z),"
|
||||
"composite_sample(textureCoordinates[3], angles.w)"
|
||||
");"
|
||||
vec4 samples = vec4(
|
||||
composite_sample(textureCoordinates[0], angles.x),
|
||||
composite_sample(textureCoordinates[1], angles.y),
|
||||
composite_sample(textureCoordinates[2], angles.z),
|
||||
composite_sample(textureCoordinates[3], angles.w)
|
||||
);
|
||||
|
||||
// Compute a luminance for use if there's no colour information, now, before
|
||||
// modifying samples.
|
||||
"float mono_luminance = dot(samples, vec4(0.15, 0.35, 0.35, 0.15));"
|
||||
// The outer structure of the OpenGL scan target means in practice that
|
||||
// compositeAmplitude will be the same value across a piece of
|
||||
// geometry. I am therefore optimistic that this conditional will not
|
||||
// cause a divergence in fragment execution.
|
||||
if(compositeAmplitude < 0.01) {
|
||||
// Compute only a luminance for use if there's no colour information.
|
||||
fragColour3 = vec3(dot(samples, vec4(0.15, 0.35, 0.35, 0.15)));
|
||||
} else {
|
||||
// Take the average to calculate luminance, then subtract that from all four samples to
|
||||
// give chrominance.
|
||||
float luminance = dot(samples, vec4(0.25));
|
||||
|
||||
// Take the average to calculate luminance, then subtract that from all four samples to
|
||||
// give chrominance.
|
||||
"float luminance = dot(samples, vec4(0.25));"
|
||||
// Split and average chrominance.
|
||||
vec2 chrominances[4] = vec2[4](
|
||||
textureLod(qamTextureName, qamTextureCoordinates[0], 0).gb,
|
||||
textureLod(qamTextureName, qamTextureCoordinates[1], 0).gb,
|
||||
textureLod(qamTextureName, qamTextureCoordinates[2], 0).gb,
|
||||
textureLod(qamTextureName, qamTextureCoordinates[3], 0).gb
|
||||
);
|
||||
vec2 channels = (chrominances[0] + chrominances[1] + chrominances[2] + chrominances[3])*0.5 - vec2(1.0);
|
||||
|
||||
// Split and average chrominance.
|
||||
"vec2 chrominances[4] = vec2[4]("
|
||||
"textureLod(qamTextureName, qamTextureCoordinates[0], 0).gb,"
|
||||
"textureLod(qamTextureName, qamTextureCoordinates[1], 0).gb,"
|
||||
"textureLod(qamTextureName, qamTextureCoordinates[2], 0).gb,"
|
||||
"textureLod(qamTextureName, qamTextureCoordinates[3], 0).gb"
|
||||
");"
|
||||
"vec2 channels = (chrominances[0] + chrominances[1] + chrominances[2] + chrominances[3])*0.5 - vec2(1.0);"
|
||||
|
||||
// Apply a colour space conversion to get RGB.
|
||||
"fragColour3 = mix("
|
||||
"lumaChromaToRGB * vec3(luminance / (1.0 - compositeAmplitude), channels),"
|
||||
"vec3(mono_luminance),"
|
||||
"step(oneOverCompositeAmplitude, 0.01)"
|
||||
");";
|
||||
// Apply a colour space conversion to get RGB.
|
||||
fragColour3 = lumaChromaToRGB * vec3(luminance / (1.0 - compositeAmplitude), channels);
|
||||
}
|
||||
)x";
|
||||
break;
|
||||
|
||||
case DisplayType::CompositeMonochrome:
|
||||
@@ -622,7 +624,7 @@ std::unique_ptr<Shader> ScanTarget::qam_separation_shader() const {
|
||||
|
||||
"compositeAngle = compositeAngle * 2.0 * 3.141592654;"
|
||||
"compositeAmplitude = lineCompositeAmplitude / 255.0;"
|
||||
"oneOverCompositeAmplitude = mix(0.0, 255.0 / lineCompositeAmplitude, step(0.01, lineCompositeAmplitude));";
|
||||
"oneOverCompositeAmplitude = mix(0.0, 255.0 / lineCompositeAmplitude, step(0.95, lineCompositeAmplitude));";
|
||||
|
||||
if(is_svideo) {
|
||||
vertex_shader +=
|
||||
|
||||
Reference in New Issue
Block a user