- CPU Mode from UI

- Scan Lines (CRT Monitor) mode from UI
- Echo Mode (pauses machine when just waiting for keyboard input)
This commit is contained in:
tudnai 2020-06-17 09:46:17 -07:00
parent e6e43df201
commit 0ebc75c931
7 changed files with 529 additions and 159 deletions

View File

@ -1182,7 +1182,7 @@
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController id="B8D-0N-5wS" sceneMemberID="viewController">
<window key="window" title="Forever ][ The Apple II Emulator" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
<window key="window" title="Steve ][ The Apple II Emulator" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="196" y="240" width="1280" height="840"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
@ -1260,7 +1260,7 @@
<customView hidden="YES" canDrawConcurrently="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LlM-EV-ruZ" userLabel="HiRes" customClass="HiRes" customModule="A2Mac" customModuleProvider="target">
<rect key="frame" x="16" y="16" width="1120" height="768"/>
</customView>
<imageView canDrawConcurrently="YES" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="dGn-a4-c1t" userLabel="ScanLines">
<imageView hidden="YES" canDrawConcurrently="YES" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="dGn-a4-c1t" userLabel="ScanLines">
<rect key="frame" x="16" y="16" width="1120" height="768"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyUpOrDown" image="scanlines" id="jJ6-qt-oZe"/>
</imageView>
@ -1303,6 +1303,14 @@
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="w41-S5-cTL" userLabel="Prompt">
<rect key="frame" x="16" y="554" width="29" height="14"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="]" id="CYs-wL-6Pf">
<font key="font" size="14" name="PrintChar21"/>
<color key="textColor" red="0.39607843139999999" green="0.72549019609999998" blue="0.2784313725" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bUo-E1-CYC">
<rect key="frame" x="820" y="16" width="286" height="14"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="© by Tamas Rudnai, 2020" id="tm6-Cq-r7H">
@ -1312,39 +1320,25 @@
</textFieldCell>
</textField>
<imageView canDrawConcurrently="YES" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="M1E-lz-4q8" userLabel="Splash Logo">
<rect key="frame" x="0.0" y="0.0" width="1120" height="768"/>
<contentFilters>
<ciFilter name="CIOpTile">
<configuration>
<real key="inputAngle" value="0.20000000000000001"/>
<ciVector key="inputCenter">
<real value="560"/>
<real value="410"/>
</ciVector>
<null key="inputImage"/>
<real key="inputScale" value="1.6000000000000001"/>
<real key="inputWidth" value="40"/>
</configuration>
</ciFilter>
</contentFilters>
<rect key="frame" x="-240" y="-256" width="1600" height="1280"/>
<imageCell key="cell" continuous="YES" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyUpOrDown" image="apple-rainbow" id="Zax-kI-rxd"/>
</imageView>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="M1E-lz-4q8" secondAttribute="trailing" id="2js-f4-3i4"/>
<constraint firstAttribute="bottom" secondItem="M1E-lz-4q8" secondAttribute="bottom" id="FvX-rE-H55"/>
<constraint firstItem="w41-S5-cTL" firstAttribute="leading" secondItem="D0w-YC-YlJ" secondAttribute="leading" constant="18" id="AR5-1H-lGS"/>
<constraint firstItem="uMO-wh-lu4" firstAttribute="leading" secondItem="D0w-YC-YlJ" secondAttribute="leading" constant="16" id="Hcq-uo-o7q"/>
<constraint firstItem="WWG-zg-Mnb" firstAttribute="top" secondItem="D0w-YC-YlJ" secondAttribute="top" constant="162" id="Pal-mO-Y3V"/>
<constraint firstItem="19A-Bc-mjX" firstAttribute="leading" secondItem="D0w-YC-YlJ" secondAttribute="leading" constant="16" id="QrC-1X-nvG"/>
<constraint firstItem="19A-Bc-mjX" firstAttribute="top" secondItem="D0w-YC-YlJ" secondAttribute="top" constant="90" id="SZZ-Bf-eaW"/>
<constraint firstAttribute="bottom" secondItem="bUo-E1-CYC" secondAttribute="bottom" constant="16" id="Yiw-QR-lgh"/>
<constraint firstItem="M1E-lz-4q8" firstAttribute="leading" secondItem="D0w-YC-YlJ" secondAttribute="leading" id="ZJX-b5-9Zx"/>
<constraint firstItem="uMO-wh-lu4" firstAttribute="top" secondItem="D0w-YC-YlJ" secondAttribute="top" constant="140" id="hdm-uq-Pa8"/>
<constraint firstItem="M1E-lz-4q8" firstAttribute="centerY" secondItem="D0w-YC-YlJ" secondAttribute="centerY" id="mjR-uf-mpN"/>
<constraint firstItem="w41-S5-cTL" firstAttribute="top" secondItem="D0w-YC-YlJ" secondAttribute="top" constant="200" id="pHW-JK-Jx6"/>
<constraint firstAttribute="trailing" secondItem="bUo-E1-CYC" secondAttribute="trailing" constant="16" id="phJ-qW-Sro"/>
<constraint firstItem="9jr-eX-yOC" firstAttribute="leading" secondItem="D0w-YC-YlJ" secondAttribute="leading" constant="16" id="rGe-kW-tUQ"/>
<constraint firstItem="9jr-eX-yOC" firstAttribute="top" secondItem="D0w-YC-YlJ" secondAttribute="top" constant="16" id="sFz-v2-tt5"/>
<constraint firstItem="M1E-lz-4q8" firstAttribute="centerX" secondItem="D0w-YC-YlJ" secondAttribute="centerX" id="tc8-kW-eON"/>
<constraint firstItem="WWG-zg-Mnb" firstAttribute="leading" secondItem="D0w-YC-YlJ" secondAttribute="leading" constant="18" id="vDf-7B-UwH"/>
<constraint firstItem="M1E-lz-4q8" firstAttribute="top" secondItem="D0w-YC-YlJ" secondAttribute="top" id="wqQ-J4-rRz"/>
</constraints>
</customView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Fdf-pv-iEw" userLabel="Side Panel">
@ -1394,13 +1388,26 @@
</customSpacing>
</stackView>
<stackView distribution="fill" orientation="vertical" alignment="leading" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lVP-FP-u6x" userLabel="CPU Speed Selection">
<rect key="frame" x="8" y="8" width="104" height="323"/>
<rect key="frame" x="8" y="8" width="104" height="469"/>
<subviews>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="7yw-J0-Fmj">
<rect key="frame" x="0.0" y="320" width="96" height="5"/>
<rect key="frame" x="0.0" y="466" width="96" height="5"/>
</box>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="isd-yh-gCV">
<rect key="frame" x="-2" y="444" width="98" height="18"/>
<buttonCell key="cell" type="check" title="CRT Monitor" bezelStyle="regularSquare" imagePosition="left" inset="2" id="UQ8-Nn-Kt7">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="CRTMonitorOnOff:" target="XfG-lQ-9wD" id="2V4-GI-erE"/>
</connections>
</button>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="t35-xh-L18">
<rect key="frame" x="0.0" y="435" width="96" height="5"/>
</box>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="e2E-di-h3i">
<rect key="frame" x="-2" y="298" width="83" height="18"/>
<rect key="frame" x="-2" y="413" width="83" height="18"/>
<buttonCell key="cell" type="check" title="KeybStick" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="UW9-Bt-pMv">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1410,7 +1417,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Wa3-TC-XUI">
<rect key="frame" x="-2" y="276" width="79" height="18"/>
<rect key="frame" x="-2" y="391" width="79" height="18"/>
<buttonCell key="cell" type="check" title="MouStick" bezelStyle="regularSquare" imagePosition="left" inset="2" id="BGz-fX-MyG">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1420,7 +1427,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xrz-jA-1Fh">
<rect key="frame" x="-2" y="254" width="63" height="18"/>
<rect key="frame" x="-2" y="369" width="63" height="18"/>
<buttonCell key="cell" type="check" title="Mouse" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="1RG-zY-mD2">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1430,10 +1437,10 @@
</connections>
</button>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="rIK-Xk-n9g">
<rect key="frame" x="0.0" y="245" width="96" height="5"/>
<rect key="frame" x="0.0" y="360" width="96" height="5"/>
</box>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ccb-cj-gLu">
<rect key="frame" x="-2" y="223" width="87" height="18"/>
<rect key="frame" x="-2" y="338" width="87" height="18"/>
<buttonCell key="cell" type="check" title="Quick Disk" bezelStyle="regularSquare" imagePosition="left" inset="2" id="6QV-uF-Gh7">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1443,7 +1450,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="9nQ-Yf-2xf">
<rect key="frame" x="-2" y="201" width="91" height="18"/>
<rect key="frame" x="-2" y="316" width="91" height="18"/>
<buttonCell key="cell" type="check" title="Disk Sound" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="AJi-1B-qeg">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1453,10 +1460,10 @@
</connections>
</button>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="wih-Y6-2Bz">
<rect key="frame" x="0.0" y="192" width="96" height="5"/>
<rect key="frame" x="0.0" y="307" width="96" height="5"/>
</box>
<splitView hidden="YES" dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ge3-qD-JO6">
<rect key="frame" x="0.0" y="300" width="104" height="23"/>
<rect key="frame" x="0.0" y="446" width="104" height="23"/>
<subviews>
<textField verticalHuggingPriority="750" fixedFrame="YES" id="SNE-lV-JXn" userLabel="SoundGap">
<rect key="frame" x="0.0" y="0.0" width="90" height="23"/>
@ -1485,18 +1492,21 @@
</holdingPriorities>
</splitView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="FZk-VW-alq">
<rect key="frame" x="-2" y="169" width="41" height="17"/>
<rect key="frame" x="-2" y="284" width="75" height="17"/>
<constraints>
<constraint firstAttribute="height" constant="17" id="ai1-6C-5tW"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="clipping" refusesFirstResponder="YES" alignment="center" title="Label" id="FBZ-dh-6Fs">
<textFieldCell key="cell" lineBreakMode="clipping" refusesFirstResponder="YES" alignment="center" title="0.000 MHz" id="FBZ-dh-6Fs">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="Ml4-a9-XEQ">
<rect key="frame" x="0.0" y="273" width="96" height="5"/>
</box>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Fb7-Jc-jmt">
<rect key="frame" x="-2" y="144" width="74" height="17"/>
<rect key="frame" x="-2" y="250" width="74" height="17"/>
<constraints>
<constraint firstAttribute="height" constant="17" id="xCE-LE-hVy"/>
</constraints>
@ -1507,7 +1517,7 @@
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7Pw-e8-92m">
<rect key="frame" x="-1" y="119" width="55" height="18"/>
<rect key="frame" x="-1" y="225" width="55" height="18"/>
<buttonCell key="cell" type="radio" title="1.023" bezelStyle="regularSquare" imagePosition="left" alignment="left" refusesFirstResponder="YES" state="on" inset="2" id="AgQ-Np-TYQ">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1517,7 +1527,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hU1-g7-CCX">
<rect key="frame" x="-1" y="95" width="30" height="18"/>
<rect key="frame" x="-1" y="201" width="30" height="18"/>
<buttonCell key="cell" type="radio" title="2" bezelStyle="regularSquare" imagePosition="left" alignment="left" refusesFirstResponder="YES" inset="2" id="nfH-ww-Ofp">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1527,7 +1537,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Hfg-DD-meM">
<rect key="frame" x="-1" y="71" width="31" height="18"/>
<rect key="frame" x="-1" y="177" width="31" height="18"/>
<buttonCell key="cell" type="radio" title="4" bezelStyle="regularSquare" imagePosition="left" alignment="left" refusesFirstResponder="YES" inset="2" id="dqL-yg-qaX">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1537,7 +1547,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="OsQ-RW-v8K">
<rect key="frame" x="-1" y="47" width="37" height="18"/>
<rect key="frame" x="-1" y="153" width="37" height="18"/>
<buttonCell key="cell" type="radio" title="10" bezelStyle="regularSquare" imagePosition="left" alignment="left" refusesFirstResponder="YES" inset="2" id="3Ve-WW-CIS">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1547,7 +1557,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vGb-dz-KHi">
<rect key="frame" x="-1" y="23" width="45" height="18"/>
<rect key="frame" x="-1" y="129" width="45" height="18"/>
<buttonCell key="cell" type="radio" title="100" bezelStyle="regularSquare" imagePosition="left" alignment="left" refusesFirstResponder="YES" inset="2" id="BUX-kX-vwG">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1557,7 +1567,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="umb-DW-vGc">
<rect key="frame" x="-1" y="-1" width="51" height="18"/>
<rect key="frame" x="-1" y="105" width="51" height="18"/>
<buttonCell key="cell" type="radio" title="MAX" bezelStyle="regularSquare" imagePosition="left" alignment="left" refusesFirstResponder="YES" inset="2" id="8VU-4B-7Pe">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1566,6 +1576,50 @@
<action selector="speedSelected:" target="XfG-lQ-9wD" id="Viq-Dy-2or"/>
</connections>
</button>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="1b6-qR-DoP">
<rect key="frame" x="0.0" y="95" width="96" height="5"/>
</box>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Www-DG-lcV">
<rect key="frame" x="-2" y="72" width="69" height="17"/>
<constraints>
<constraint firstAttribute="height" constant="17" id="V60-fY-1kt"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="clipping" refusesFirstResponder="YES" alignment="left" title="CPU Mode" id="RSV-DX-6Cy">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WeH-Xd-mtE">
<rect key="frame" x="-1" y="47" width="66" height="18"/>
<buttonCell key="cell" type="radio" title="Normal" bezelStyle="regularSquare" imagePosition="left" alignment="left" refusesFirstResponder="YES" state="on" inset="2" id="0UN-dl-3nf">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="setCPUMode:" target="XfG-lQ-9wD" id="Tpg-rW-JJO"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="25n-Et-ouy">
<rect key="frame" x="-1" y="23" width="45" height="18"/>
<buttonCell key="cell" type="radio" title="Eco" bezelStyle="regularSquare" imagePosition="left" alignment="left" refusesFirstResponder="YES" inset="2" id="t39-st-goM">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="setCPUMode:" target="XfG-lQ-9wD" id="5GQ-ik-x5E"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="pQx-FY-gmj">
<rect key="frame" x="-1" y="-1" width="58" height="18"/>
<buttonCell key="cell" type="radio" title="Game" bezelStyle="regularSquare" imagePosition="left" alignment="left" refusesFirstResponder="YES" inset="2" id="Dgy-OG-1MD">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="setCPUMode:" target="XfG-lQ-9wD" id="iTd-yU-Vd4"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="Ge3-qD-JO6" secondAttribute="trailing" id="CjH-r2-t3y"/>
@ -1589,6 +1643,14 @@
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
@ -1608,6 +1670,14 @@
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
</subviews>
@ -1662,6 +1732,7 @@
<outlet property="displayField" destination="SEL-hl-0c0" id="4Pc-hG-qQf"/>
<outlet property="hires" destination="LlM-EV-ruZ" id="E60-pA-HM1"/>
<outlet property="lores" destination="Gqh-qw-fjy" id="vOE-5m-Jfi"/>
<outlet property="scanLines" destination="dGn-a4-c1t" id="3Xy-Ku-95P"/>
<outlet property="speedometer" destination="FBZ-dh-6Fs" id="L0v-RY-xwB"/>
<outlet property="splashScreen" destination="D0w-YC-YlJ" id="WJB-BH-5EP"/>
</connections>
@ -1672,7 +1743,7 @@
</scene>
</scenes>
<resources>
<image name="apple-rainbow" width="800" height="800"/>
<image name="apple-rainbow" width="1600" height="1280"/>
<image name="dotmatrix_effect" width="268.79998779296875" height="184.32000732421875"/>
<image name="scanlines" width="268.79998779296875" height="184.32000732421875"/>
</resources>

View File

@ -709,8 +709,13 @@ class HiRes: NSView {
// refresh the entire screen
let boundingBox = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
currentContext?.interpolationQuality = .none
// currentContext?.interpolationQuality = .high // TODO: Make a switch that lets you turn on and off "old monitor effects"
if ( ViewController.current?.CRTMonitor ?? false ) {
currentContext?.interpolationQuality = .high // TODO: Make a switch that lets you turn on and off "old monitor effects"
}
else {
currentContext?.interpolationQuality = .none
}
currentContext?.draw(image, in: boundingBox)
}

View File

@ -52,7 +52,9 @@ class ViewController: NSViewController {
@IBOutlet weak var lores: LoRes!
@IBOutlet weak var hires: HiRes!
@IBOutlet weak var splashScreen: NSView!
@IBOutlet weak var scanLines: NSImageView!
var CRTMonitor = false
var Keyboard2Joystick = true
var Mouse2Joystick = false
var MouseInterface = true
@ -145,7 +147,7 @@ class ViewController: NSViewController {
@IBAction func Power(_ sender: Any) {
upd.suspend()
halted = true
cpuState = cpuState_inited;
//------------------------------------------------------------
// Animated Splash Screen fade out and (Text) Monitor fade in
@ -170,7 +172,7 @@ class ViewController: NSViewController {
m6502_ColdReset( Bundle.main.resourcePath, ViewController.romFileName )
self.halted = false
cpuState = cpuState_running;
self.upd.resume()
}
//------------------------------------------------------------
@ -284,6 +286,11 @@ class ViewController: NSViewController {
}
override func keyDown(with event: NSEvent) {
if ( cpuMode == cpuMode_eco ) {
cpuState = cpuState_running;
}
// print("keyDown")
// for i in 0...65536 {
@ -524,8 +531,6 @@ class ViewController: NSViewController {
var clkCounter : Double = 0
let fpsHalf = fps / 2
var halted = true;
var mouseLocation = NSPoint.zero
var shadowTxt : String = ""
@ -726,35 +731,106 @@ class ViewController: NSViewController {
}
func Update() {
clkCounter += Double(clkfrm)
// we start a new frame from here, so CPU is running even while rendering
clkfrm = 0
func Input() {
// Mouse 2 JoyStick (Game Controller / Paddle)
mouseLocation = view.window!.mouseLocationOutsideOfEventStream
if ( Mouse2Joystick ) {
pdl_prevarr[0] = pdl_valarr[0]
pdl_valarr[0] = Double(mouseLocation.x / (displayField.frame.width) )
pdl_diffarr[0] = pdl_valarr[0] - pdl_prevarr[0]
pdl_prevarr[1] = pdl_valarr[1]
pdl_valarr[1] = 1 - Double(mouseLocation.y / (displayField.frame.height) )
pdl_diffarr[1] = pdl_valarr[1] - pdl_prevarr[1]
}
if ( MouseInterface ) {
pdl_prevarr[2] = pdl_valarr[2]
pdl_valarr[2] = Double(mouseLocation.x / (displayField.frame.width) )
pdl_diffarr[2] = pdl_valarr[2] - pdl_prevarr[2]
pdl_prevarr[3] = pdl_valarr[3]
pdl_valarr[3] = 1 - Double(mouseLocation.y / (displayField.frame.height) )
pdl_diffarr[3] = pdl_valarr[3] - pdl_prevarr[3]
}
}
frameCounter += 1
if ( frameCounter % fps == 0 ) {
let currentTime = CACurrentMediaTime() as Double
let elpasedTime = currentTime - lastFrameTime
lastFrameTime = currentTime
mhz = Double( clkCounter ) / (elpasedTime * M);
clkCounter = 0
func Update() {
switch cpuState {
case cpuState_running:
clkCounter += Double(clkfrm)
// we start a new frame from here, so CPU is running even while rendering
clkfrm = 0
frameCounter += 1
if ( frameCounter % fps == 0 ) {
let currentTime = CACurrentMediaTime() as Double
let elpasedTime = currentTime - lastFrameTime
lastFrameTime = currentTime
mhz = Double( clkCounter ) / (elpasedTime * M);
clkCounter = 0
}
#if SPEEDTEST
#else
// poll input devices like mouse and joystick
Input()
// run some code
m6502_Run()
// video rendering
// if ( frameCounter % 5 == 0 ) {
Render()
// }
#endif
break
case cpuState_halting:
cpuState = cpuState_halted
// clkCounter += Double(clkfrm)
// // we start a new frame from here, so CPU is running even while rendering
// clkfrm = 0
//
// frameCounter += 1
//
// if ( frameCounter % fps == 0 ) {
// let currentTime = CACurrentMediaTime() as Double
// let elpasedTime = currentTime - lastFrameTime
// lastFrameTime = currentTime
// mhz = Double( clkCounter ) / (elpasedTime * M);
// clkCounter = 0
// }
//
// #if SPEEDTEST
// #else
//
// // poll input devices like mouse and joystick
// Input()
//
// // run some code
// m6502_Run()
//
// video rendering
// if ( frameCounter % 5 == 0 ) {
Render()
// }
// #endif
break
default:
break
}
// if ( frameCounter % 5 == 0 ) {
Render()
// }
#if SPEEDTEST
#else
if ( !halted ) {
m6502_Run()
}
#endif
}
@ -873,6 +949,23 @@ class ViewController: NSViewController {
}
@IBAction func setCPUMode(_ sender: NSButton) {
switch ( sender.title ) {
case "Eco":
cpuMode = cpuMode_eco
break
case "Game":
cpuMode = cpuMode_game
cpuState = cpuState_running
break
default:
cpuMode = cpuMode_normal
cpuState = cpuState_running
break
}
}
@IBOutlet weak var SoundGap: NSTextFieldCell!
@ -881,6 +974,11 @@ class ViewController: NSViewController {
spkr_extra_buf = Int32( sender.integerValue )
}
@IBAction func CRTMonitorOnOff(_ sender: NSButton) {
CRTMonitor = sender.state == .on
scanLines.isHidden = !CRTMonitor
}
@IBAction func Keyboard2JoystickOnOff(_ sender: NSButton) {
Keyboard2Joystick = sender.state == .on
}

View File

@ -28,6 +28,10 @@ void ViewController_spk_up_play(void);
void ViewController_spk_dn_play(void);
volatile cpuMode_s cpuMode = cpuMode_normal;
volatile cpuState_s cpuState = cpuState_unknown;
#include "../util/common.h"
@ -333,7 +337,7 @@ INLINE int m6502_Step() {
case 0x69: ADC( imm() ); return 2; // ADC imm
case 0x6A: RORA(); return 2; // ROR A
case 0x6B: ARC( imm() ); return 2; // ARR/ARC* imm 2 (undocumented)
case 0x6C: JMP( ind_addr() ); return 5; // JMP ind
case 0x6C: JMP( ind_addr() ); return 5; // JMP ind
case 0x6D: ADC( src_abs() ); return 4; // ADC abs
case 0x6E: ROR( addr_abs() ); return 6; // ROR abs
case 0x6F: RRA( abs_addr() ); return 6; // RRA* abs 6 (undocumented)
@ -367,7 +371,7 @@ INLINE int m6502_Step() {
case 0x8B: XAA( imm() ); return 2; // XAA* imm 2 (undocumented, highly unstable!)
case 0x8C: STY( addr_abs() ); return 4; // STY abs
case 0x8D: STA( addr_abs() ); return 4; // STA abs
case 0x8E: STX( addr_abs() ); return 4; // STX abs
case 0x8E: STX( addr_abs() ); return 4; // STX abs
case 0x8F: SAX( addr_abs() ); return 4; // SAX* abs 4 (undocumented)
case 0x90: BCC( rel_addr() ); return 3; // BCC rel
case 0x91: STA( addr_ind_Y() ); return 6; // STA ind,Y

View File

@ -13,6 +13,22 @@
#include "common.h"
#include "woz.h"
typedef enum cpuMode_e {
cpuMode_normal = 0,
cpuMode_eco,
cpuMode_game,
} cpuMode_s;
typedef enum cpuState_e {
cpuState_unknown = 0,
cpuState_inited,
cpuState_running,
cpuState_halting,
cpuState_halted,
} cpuState_s;
extern volatile cpuMode_s cpuMode;
extern volatile cpuState_s cpuState;
extern const double default_MHz_6502;
extern const double iigs_MHz_6502;

View File

@ -91,17 +91,10 @@ typedef enum wozTrackState_e {
} wozTrackState_t;
void woz_loadTrack( int track ) {
trackEntry_t reg = {0};
wozTrackState_t wozTrackState = wozTrackState_Start;
reg.shift = 0;
reg.data = 0;
prepared_track[0] = reg;
int vol = 0;
int trk = 0;
int sec = 0;
int bitOffs_D5_SecHdr = 0;
int vol = 0;
int trk = 0;
int sec = 0;
int bitOffs_D5_SecHdr = 0; // bit offset of D5 Sector Header
@ -115,78 +108,78 @@ void woz_loadTrack( int track ) {
reg.shift16 <<= 1;
if (reg.shift & 0x80) {
switch (wozTrackState) {
case wozTrackState_D5:
switch (wozTrackState) {
case wozTrackState_D5:
switch (reg.shift) {
case 0xAA:
// printf("D5 AA at bitOffset:%d\n", bitOffs);
wozTrackState = wozTrackState_D5_AA;
break;
default:
wozTrackState = wozTrackState_Start;
break;
}
break;
case wozTrackState_D5_AA:
case 0xAA:
// printf("D5 AA at bitOffset:%d\n", bitOffs);
wozTrackState = wozTrackState_D5_AA;
break;
default:
wozTrackState = wozTrackState_Start;
break;
}
break;
case wozTrackState_D5_AA:
switch (reg.shift) {
case 0x96:
wozTrackState = wozTrackState_vol1;
// printf("D5 AA 96 at bitOffset:%d\n", bitOffs);
// printf("Sector Header at bitOffset:%d\n", bitOffs_D5_SecHdr);
break;
default:
wozTrackState = wozTrackState_Start;
break;
}
break;
case wozTrackState_vol1:
case 0x96:
wozTrackState = wozTrackState_vol1;
// printf("D5 AA 96 at bitOffset:%d\n", bitOffs);
// printf("Sector Header at bitOffset:%d\n", bitOffs_D5_SecHdr);
break;
default:
wozTrackState = wozTrackState_Start;
break;
}
break;
case wozTrackState_vol1:
vol = (reg.shift << 1) | 1;
wozTrackState = wozTrackState_vol2;
break;
case wozTrackState_vol2:
wozTrackState = wozTrackState_vol2;
break;
case wozTrackState_vol2:
vol &= reg.shift;
wozTrackState = wozTrackState_trk1;
break;
case wozTrackState_trk1:
wozTrackState = wozTrackState_trk1;
break;
case wozTrackState_trk1:
trk = (reg.shift << 1) | 1;
wozTrackState = wozTrackState_trk2;
break;
case wozTrackState_trk2:
wozTrackState = wozTrackState_trk2;
break;
case wozTrackState_trk2:
trk &= reg.shift;
wozTrackState = wozTrackState_sec1;
break;
case wozTrackState_sec1:
wozTrackState = wozTrackState_sec1;
break;
case wozTrackState_sec1:
sec = (reg.shift << 1) | 1;
wozTrackState = wozTrackState_sec2;
break;
case wozTrackState_sec2:
wozTrackState = wozTrackState_sec2;
break;
case wozTrackState_sec2:
sec &= reg.shift;
wozTrackState = wozTrackState_Start;
printf("Vol:%d Track:%d Sector:%d at bitOffset:%d\n", vol, trk, sec, bitOffs_D5_SecHdr);
break;
default:
break;
default:
if ( reg.shift == 0xD5 ) {
// printf("D5 at bitOffset:%d\n", bitOffs);
wozTrackState = wozTrackState_D5;
bitOffs_D5_SecHdr = bitOffs;
}
break;
}
// printf("D5 at bitOffset:%d\n", bitOffs);
wozTrackState = wozTrackState_D5;
bitOffs_D5_SecHdr = bitOffs;
}
break;
}
reg.shift = 0;
}
@ -257,10 +250,11 @@ uint8_t woz_read() {
trackOffset++;
trackOffset %= usedBytes;
WOZread.data = woz_trks[track].data[trackOffset];
WOZwrite.data = WOZread.data = woz_trks[track].data[trackOffset];
}
WOZread.shift16 <<= 1;
WOZwrite.shift16 <<= 1;
if ( WOZread.valid ) {
WOZread.shift = 0;
@ -271,22 +265,29 @@ uint8_t woz_read() {
// to avoid infinite loop and to search for bit 7 high
for ( int i = 0; i < usedBytes * 8; i++ ) {
if ( WOZread.valid ) {
uint8_t byte = WOZread.shift;
WOZread.shift = 0;
// if (outdev) fprintf(outdev, "byte: %02X\n", byte);
if ( woz_decodeTrkSec(WOZwrite.shift, clkelpased, trackOffset * 8 + bitOffset) == wozTrackState_END ) {
if (disk_sfx_enabled) printf("vol:%d trk:%d sec:%d\n", vol, trk, sec);
}
return byte;
if (disk_sfx_enabled) printf("elpased:%lld read: %02X\n", clkelpased, WOZwrite.shift);
return WOZwrite.shift;
}
if ( ++bitOffset >= 8 ) {
bitOffset = 0;
trackWRoffset = trackOffset;
trackOffset++;
trackOffset %= usedBytes;
WOZread.data = woz_trks[track].data[trackOffset];
WOZwrite.data = WOZread.data = woz_trks[track].data[trackOffset];
}
WOZread.shift16 <<= 1;
WOZwrite.shift16 <<= 1;
}
// if (outdev) fprintf(outdev, "TIME OUT!\n");
}
@ -295,6 +296,97 @@ uint8_t woz_read() {
}
void woz_write( uint8_t data ) {
int track = woz_tmap.phase[disk.phase.count];
if (outdev) fprintf(outdev, "track: %d (%d) ", track, disk.phase.count);
if ( track >= 40 ) {
dbgPrintf("TRCK TOO HIGH!\n");
return;
}
static int clkBeforeSync = 0;
clkelpased = m6502.clktime + clkfrm - m6502.clklast;
m6502.clklast = m6502.clktime + clkfrm;
clkBeforeSync += clkelpased;
uint16_t usedBytes = woz_trks[track].bytes_used < WOZ_TRACK_BYTE_COUNT ? woz_trks[track].bytes_used : WOZ_TRACK_BYTE_COUNT;
if ( usedBytes ) {
if ( disk_sfx_enabled ) printf("elpased:%llu data:$%02X\n", clkelpased, data);
if ( clkelpased > 40 ) {
if ( disk_sfx_enabled ) printf("I/O ERROR : %llu (clkBefRd:%d)\n", clkelpased, clkBeforeSync);
}
// sync data?
if ( WOZwrite.shift == 0xFF ) {
// yes, we have to push in extra 2 zeros
for ( int i = 0; i < 2; i++ ) {
WOZread.shift16 <<= 1;
WOZwrite.shift16 <<= 1;
if ( ++bitOffset >= 8 ) {
bitOffset = 0;
trackWRoffset = trackOffset;
trackOffset++;
trackOffset %= usedBytes;
}
}
}
// now we can latch data
// uint8_t latch = data;
WOZwrite.data = WOZread.data = data;
// shift in 8 bits of data and write it out
for ( int i = 0; i < 8; i++ ) {
if ( ++bitOffset >= 8 ) {
// write out first part
woz_trks[track].data[trackWRoffset] = WOZwrite.shift;
bitOffset = 0;
trackWRoffset = trackOffset;
trackOffset++;
trackOffset %= usedBytes;
// simulate shift in data (path of write latch is already loaded, we should not overwrite it!)
uint8_t new = woz_trks[track].data[trackOffset];
new &= (1 << i) - 1;
WOZread.data |= new;
WOZwrite.data |= new;
break;
}
WOZread.shift16 <<= 1;
WOZwrite.shift16 <<= 1;
};
// write the remaining bits without altering WOZ track offsets and indexes
WOZread_t WOZtmp = WOZwrite;
int bo = bitOffset;
// second half
for ( int i = 8; i; i-- ) {
if ( ++bo >= 8 ) {
// write out first part
woz_trks[track].data[trackWRoffset] = WOZtmp.shift;
break;
}
WOZtmp.shift16 <<= 1;
};
}
}
int woz_loadFile( const char * filename ) {
// char fullpath[256];

View File

@ -50,6 +50,9 @@ uint8_t * WRD0MEM = Apple2_Dummy_RAM; // for writing $D000 - $DFFF
uint8_t * WRHIMEM = Apple2_Dummy_RAM; // for writing $E000 - $FFFF
static uint8_t writeState = 0; // 1 if $C08D was written
MEMcfg_t MEMcfg = { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
MEMcfg_t newMEMcfg = { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
@ -545,25 +548,44 @@ INLINE void io_RAM_EXP( uint16_t addr ) {
}
static unsigned int lastIO = 0;
INLINE uint8_t ioRead( uint16_t addr ) {
// if (outdev) fprintf(outdev, "ioRead:%04X\n", addr);
// printf("ioRead:%04X (PC:%04X)\n", addr, m6502.PC);
unsigned int IOframe = clkfrm - lastIO;
lastIO = clkfrm;
// TODO: This is for checking only, should be either removed or the entire ioRead should based on binary search, whatever is faster
// TODO: This is for speed demo only, should be either removed or the entire ioRead should based on binary search, whatever is faster
if ( addr == io_KBD ) {
// clk_6502_per_frm_max = clk_6502_per_frm_max > 32768 ? clk_6502_per_frm_max - 32768 : 0; // ECO Mode!
if ( cpuMode == cpuMode_eco ) {
// check if this is a busy keyboard poll (aka waiting for user input)
if ( IOframe < 16 ) {
clk_6502_per_frm_max = 6502; // Absolute low mode
cpuState = cpuState_halting;
}
}
return Apple2_64K_RAM[io_KBD];
}
switch ( (uint8_t)addr ) {
case (uint8_t)io_KBD:
// if ( RAM[io_KBD] > 0x7F ) printf("io_KBD:%04X\n", addr);
return Apple2_64K_RAM[io_KBD];
case (uint8_t)io_KBDSTRB:
// TODO: This is very slow!
// printf("io_KBDSTRB\n");
Apple2_64K_RAM[io_KBD] &= ~(1 << 7);
if ( cpuMode == cpuMode_eco ) {
// check if this is a busy keyboard poll (aka waiting for user input)
clk_6502_per_frm_max = clk_6502_per_frm; // Absolute low mode
cpuState = cpuState_running;
}
return Apple2_64K_RAM[io_KBDSTRB];
case (uint8_t)io_SPKR:
@ -737,12 +759,20 @@ INLINE uint8_t ioRead( uint16_t addr ) {
return 0;
case (uint8_t)io_DISK_READ + SLOT6:
return disk_read();
if ( writeState ) {
writeState = 0;
woz_write( Apple2_64K_RAM[io_DISK_WRITE + SLOT6] );
return Apple2_64K_RAM[io_DISK_WRITE + SLOT6];
}
else {
return disk_read();
}
case (uint8_t)io_DISK_WRITE + SLOT6:
dbgPrintf2("io_DISK_WRITE (S%u)\n", 6);
Apple2_64K_RAM[io_DISK_CLEAR + SLOT6] |= 1 << 7; // mark disk as write protected
// Apple2_64K_RAM[io_DISK_CLEAR + SLOT6] |= 1 << 7; // mark disk as write protected
Apple2_64K_RAM[io_DISK_CLEAR + SLOT6] &= ~(1 << 7); // mark disk as write enabled
return Apple2_64K_RAM[io_DISK_WRITE + SLOT6];
case (uint8_t)io_DISK_CLEAR + SLOT6:
@ -961,6 +991,60 @@ INLINE void ioWrite( uint16_t addr, uint8_t val ) {
io_RAM_EXP(addr);
break;
// TODO: Make code "card insertable to slot" / aka slot independent and dynamically add/remove
case (uint8_t)io_DISK_PHASE0_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE1_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE2_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE3_OFF + SLOT6:
disk_phase_off( (addr - io_DISK_PHASE0_OFF - SLOT6) / 2 );
break;
case (uint8_t)io_DISK_PHASE0_ON + SLOT6:
case (uint8_t)io_DISK_PHASE1_ON + SLOT6:
case (uint8_t)io_DISK_PHASE2_ON + SLOT6:
case (uint8_t)io_DISK_PHASE3_ON + SLOT6:
disk_phase_on( (addr - io_DISK_PHASE0_ON - SLOT6) / 2 );
break;
case (uint8_t)io_DISK_POWER_OFF + SLOT6:
dbgPrintf2("io_DISK_POWER_OFF (S%u)\n", 6);
disk_motor_off();
break;
case (uint8_t)io_DISK_POWER_ON + SLOT6:
dbgPrintf2("io_DISK_POWER_ON (S%u)\n", 6);
disk_motor_on();
break;
case (uint8_t)io_DISK_SELECT_1 + SLOT6:
dbgPrintf2("io_DISK_SELECT_1 (S%u)\n", 6);
break;
case (uint8_t)io_DISK_SELECT_2 + SLOT6:
dbgPrintf2("io_DISK_SELECT_2 (S%u)\n", 6);
break;
case (uint8_t)io_DISK_READ + SLOT6:
Apple2_64K_RAM[io_DISK_READ + SLOT6] = val;
woz_write( Apple2_64K_RAM[io_DISK_WRITE + SLOT6] );
writeState = 0;
break;
case (uint8_t)io_DISK_WRITE + SLOT6:
dbgPrintf2("io_DISK_WRITE (S%u)\n", 6);
Apple2_64K_RAM[io_DISK_WRITE + SLOT6] = val;
writeState = 1;
break;
case (uint8_t)io_DISK_CLEAR + SLOT6:
dbgPrintf2("io_DISK_CLEAR (S%u)\n", 6);
break;
case (uint8_t)io_DISK_SHIFT + SLOT6:
dbgPrintf2("io_DISK_SHIFT (S%u)\n", 6);
break;
default:
break;
}