1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-10-25 09:27:01 +00:00

Compare commits

...

25 Commits

Author SHA1 Message Date
Thomas Harte
32ccce3040 Merge pull request #855 from TomHarte/QtNoKeyboardCopy
Qt: don't copy the result of get_keyboard().
2020-11-29 00:05:26 -05:00
Thomas Harte
ab3fcb3ea0 Qt: don't copy the result of get_keyboard(). 2020-11-29 00:01:11 -05:00
Thomas Harte
9610672615 Merge pull request #854 from TomHarte/OpenGLNoColourBurst
Avoids all risk of infinities when there is no colour burst
2020-11-28 23:54:29 -05:00
Thomas Harte
5ee9630624 Use compositeAmplitude in favour of its reciprocal. 2020-11-28 19:53:34 -05:00
Thomas Harte
1b3836eb1c Adds an overt branch for mono/colour composite selection. 2020-11-28 19:47:04 -05:00
Thomas Harte
1302a046e9 Merge branch 'OpenGLNoColourBurst' of github.com:TomHarte/CLK into OpenGLNoColourBurst 2020-11-28 17:19:42 -05:00
Thomas Harte
33dec3c220 Given that lineCompositeAmplitude is not normalised, ups threshold. 2020-11-28 17:19:28 -05:00
Thomas Harte
7c29c3a944 Given that lineCompositeAmplitude is not normalised, ups threshold. 2020-11-28 17:13:18 -05:00
Thomas Harte
c9ca1fc7a0 Merge pull request #853 from TomHarte/AppleIIReset
Improves Apple II keyboard input, especially under SDL.
2020-11-28 12:43:32 -05:00
Thomas Harte
a965c8de9f Resolves intended reset_all_keys. 2020-11-27 21:53:34 -05:00
Thomas Harte
0b4b271e3d Pulls out redundant check. 2020-11-27 21:04:20 -05:00
Thomas Harte
5fc6dd1a4d Regresses macOS deployment target for kiosk mode to avoid OpenGL warning. 2020-11-27 21:02:04 -05:00
Thomas Harte
79ef026b93 Allows machines to declare a preference for logical input.
It's only a preference, and the Apple II does prefer it.
2020-11-27 21:00:48 -05:00
Thomas Harte
a4ab5b0b49 Does a better job of ensuring sensible key mappings. 2020-11-27 20:49:38 -05:00
Thomas Harte
3207183f05 Merge pull request #850 from TomHarte/BigSurAgain
Takes a second stab at resolving Big Sur File -> New...
2020-11-13 20:02:29 -05:00
Thomas Harte
e803f993b7 Increases minimum macOS version to 10.14.
This is lazy, but it means I definitely don't need non-Metal fallback code.
2020-11-13 19:48:45 -05:00
Thomas Harte
5dbc87caf0 Smarter: just ensures any attached panels are closed at close(). 2020-11-13 19:09:30 -05:00
Thomas Harte
4862ccc947 Dismisses ROM requester upon that cancel too. 2020-11-13 19:01:53 -05:00
Thomas Harte
e1ecf66485 Dismisses sheet before closing document. 2020-11-13 19:00:37 -05:00
Thomas Harte
2c71ba0744 Ameliorates against a potential NSRangeException. 2020-11-13 18:29:48 -05:00
Thomas Harte
a7aeb779e9 Disables Apple Silicon binaries until I have some means to test. 2020-11-13 18:07:45 -05:00
Thomas Harte
e72cfbf447 Stop assuming that NSNotification => window.isVisible. 2020-11-13 18:04:31 -05:00
Thomas Harte
5d154e3d0c Merge pull request #849 from TomHarte/BigSur
Slightly tweaks machine picker for macOS Big Sur.
2020-11-13 12:37:36 -05:00
Thomas Harte
86a24cc928 Allows Xcode to bump its versioning on the ROM requester too. 2020-11-13 12:23:48 -05:00
Thomas Harte
e8b52d20e9 Slightly tweaks machine picker for macOS Big Sur. 2020-11-13 12:14:35 -05:00
11 changed files with 187 additions and 132 deletions

View File

@@ -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);

View File

@@ -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; }
};
/*!

View File

@@ -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";

View File

@@ -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 = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Macintosh/MusicWorks 0.42.image&quot;"
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">

View File

@@ -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)
}
}
}

View File

@@ -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 -&gt; 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"/>

View File

@@ -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

View File

@@ -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"/>

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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 +=