debugging!

This commit is contained in:
Luigi Thirty 2017-07-24 03:29:12 -04:00
parent 028574d142
commit a0d28938b7
7 changed files with 366 additions and 246 deletions

View File

@ -12,7 +12,7 @@
2AD458D01F205EB700F05121 /* DebuggerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458CF1F205EB700F05121 /* DebuggerViewController.swift */; }; 2AD458D01F205EB700F05121 /* DebuggerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458CF1F205EB700F05121 /* DebuggerViewController.swift */; };
2AD458D21F205EB700F05121 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2AD458D11F205EB700F05121 /* Assets.xcassets */; }; 2AD458D21F205EB700F05121 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2AD458D11F205EB700F05121 /* Assets.xcassets */; };
2AD458D51F205EB700F05121 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2AD458D31F205EB700F05121 /* Main.storyboard */; }; 2AD458D51F205EB700F05121 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2AD458D31F205EB700F05121 /* Main.storyboard */; };
2AD458DF1F205F4500F05121 /* CPUState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458DE1F205F4500F05121 /* CPUState.swift */; }; 2AD458DF1F205F4500F05121 /* CPU.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458DE1F205F4500F05121 /* CPU.swift */; };
2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E01F2064CB00F05121 /* MemoryInterface.swift */; }; 2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E01F2064CB00F05121 /* MemoryInterface.swift */; };
2AD458E31F20661300F05121 /* CPUInstructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E21F20661300F05121 /* CPUInstructions.swift */; }; 2AD458E31F20661300F05121 /* CPUInstructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E21F20661300F05121 /* CPUInstructions.swift */; };
2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E41F2070DF00F05121 /* Opcodes.swift */; }; 2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E41F2070DF00F05121 /* Opcodes.swift */; };
@ -29,7 +29,7 @@
2AD458D41F205EB700F05121 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; 2AD458D41F205EB700F05121 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
2AD458D61F205EB700F05121 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 2AD458D61F205EB700F05121 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
2AD458D71F205EB700F05121 /* FruitMachine.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FruitMachine.entitlements; sourceTree = "<group>"; }; 2AD458D71F205EB700F05121 /* FruitMachine.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FruitMachine.entitlements; sourceTree = "<group>"; };
2AD458DE1F205F4500F05121 /* CPUState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPUState.swift; sourceTree = "<group>"; }; 2AD458DE1F205F4500F05121 /* CPU.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPU.swift; sourceTree = "<group>"; };
2AD458E01F2064CB00F05121 /* MemoryInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryInterface.swift; sourceTree = "<group>"; }; 2AD458E01F2064CB00F05121 /* MemoryInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryInterface.swift; sourceTree = "<group>"; };
2AD458E21F20661300F05121 /* CPUInstructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPUInstructions.swift; sourceTree = "<group>"; }; 2AD458E21F20661300F05121 /* CPUInstructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPUInstructions.swift; sourceTree = "<group>"; };
2AD458E41F2070DF00F05121 /* Opcodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Opcodes.swift; sourceTree = "<group>"; }; 2AD458E41F2070DF00F05121 /* Opcodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Opcodes.swift; sourceTree = "<group>"; };
@ -81,7 +81,7 @@
2AD458DD1F205F0D00F05121 /* M6502 */ = { 2AD458DD1F205F0D00F05121 /* M6502 */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
2AD458DE1F205F4500F05121 /* CPUState.swift */, 2AD458DE1F205F4500F05121 /* CPU.swift */,
2AD458E21F20661300F05121 /* CPUInstructions.swift */, 2AD458E21F20661300F05121 /* CPUInstructions.swift */,
2AE5BA031F23DE4400FAA343 /* Disassembly.swift */, 2AE5BA031F23DE4400FAA343 /* Disassembly.swift */,
2AD458E41F2070DF00F05121 /* Opcodes.swift */, 2AD458E41F2070DF00F05121 /* Opcodes.swift */,
@ -170,7 +170,7 @@
2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */, 2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */,
2AE5BA061F2469EB00FAA343 /* AddressConversions.swift in Sources */, 2AE5BA061F2469EB00FAA343 /* AddressConversions.swift in Sources */,
2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */, 2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */,
2AD458DF1F205F4500F05121 /* CPUState.swift in Sources */, 2AD458DF1F205F4500F05121 /* CPU.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -679,7 +679,7 @@
<customObject id="YLy-65-1bz" customClass="NSFontManager"/> <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> <customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="75" y="0.0"/> <point key="canvasLocation" x="75" y="-76"/>
</scene> </scene>
<!--Window Controller--> <!--Window Controller-->
<scene sceneID="R2V-B0-nI4"> <scene sceneID="R2V-B0-nI4">
@ -688,7 +688,7 @@
<window key="window" title="Debugger" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA"> <window key="window" title="Debugger" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/> <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/> <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="600" height="400"/> <rect key="contentRect" x="196" y="240" width="800" height="400"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/> <rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<connections> <connections>
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/> <outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
@ -700,14 +700,14 @@
</windowController> </windowController>
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> <customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="75" y="250"/> <point key="canvasLocation" x="74" y="209"/>
</scene> </scene>
<!--Debugger View Controller--> <!--Debugger View Controller-->
<scene sceneID="hIz-AP-VOD"> <scene sceneID="hIz-AP-VOD">
<objects> <objects>
<viewController id="XfG-lQ-9wD" customClass="DebuggerViewController" customModule="FruitMachine" customModuleProvider="target" sceneMemberID="viewController"> <viewController id="XfG-lQ-9wD" customClass="DebuggerViewController" customModule="FruitMachine" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" wantsLayer="YES" id="m2S-Jp-Qdl"> <view key="view" wantsLayer="YES" id="m2S-Jp-Qdl">
<rect key="frame" x="0.0" y="0.0" width="600" height="400"/> <rect key="frame" x="0.0" y="0.0" width="450" height="400"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9cE-VZ-R2W"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9cE-VZ-R2W">
@ -800,125 +800,6 @@
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
</textField> </textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HdY-Jc-lNK">
<rect key="frame" x="36" y="13" width="108" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Step" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="kSv-aI-p6H">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="btn_CPUStep:" target="XfG-lQ-9wD" id="sht-OT-bFK"/>
</connections>
</button>
<scrollView fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D58-pD-kHB">
<rect key="frame" x="146" y="20" width="434" height="362"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" ambiguous="YES" id="bpK-Jl-YbG">
<rect key="frame" x="1" y="0.0" width="432" height="361"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" headerView="Ep4-FK-mkU" viewBased="YES" id="MuT-J3-VZ6">
<rect key="frame" x="0.0" y="0.0" width="432" height="338"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn identifier="AddressCellID" width="116" minWidth="40" maxWidth="1000" id="hX8-rd-9WQ">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Address">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="Paw-o4-m30">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="CfD-bj-I9h">
<rect key="frame" x="1" y="1" width="116" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gF6-Xd-zbg">
<rect key="frame" x="0.0" y="0.0" width="116" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="rhk-Nf-Hah">
<font key="font" size="11" name="Menlo-Regular"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="gF6-Xd-zbg" id="lep-1z-ZAt"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn identifier="DataCellID" width="310" minWidth="40" maxWidth="1000" id="Ma5-Fz-J7v">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Disassembly">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="pvJ-AI-di6">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="ZF1-Mn-oL5">
<rect key="frame" x="120" y="1" width="310" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gen-Zj-0O4">
<rect key="frame" x="0.0" y="0.0" width="310" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="lxl-6b-xYm">
<font key="font" metaFont="fixedUser" size="11"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="gen-Zj-0O4" id="t04-GH-nId"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
</tableView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="jEY-yd-b3r">
<rect key="frame" x="1" y="119" width="223" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="xl3-SC-c8c">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<tableHeaderView key="headerView" id="Ep4-FK-mkU">
<rect key="frame" x="0.0" y="0.0" width="432" height="23"/>
<autoresizingMask key="autoresizingMask"/>
</tableHeaderView>
</scrollView>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="94S-pW-GeW">
<rect key="frame" x="36" y="46" width="108" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Break" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Pg2-w8-mzE">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="btn_Break:" target="XfG-lQ-9wD" id="wvE-WV-51x"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6li-po-zVA"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6li-po-zVA">
<rect key="frame" x="18" y="215" width="18" height="17"/> <rect key="frame" x="18" y="215" width="18" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
@ -937,6 +818,169 @@
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
</textField> </textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HdY-Jc-lNK">
<rect key="frame" x="36" y="46" width="108" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Step" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="kSv-aI-p6H">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="btn_CPUStep:" target="XfG-lQ-9wD" id="sht-OT-bFK"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oRf-MK-DEX">
<rect key="frame" x="36" y="13" width="108" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Run" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="e8U-eN-C1K">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="btn_CPURun:" target="XfG-lQ-9wD" id="2Qa-FX-i3o"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="94S-pW-GeW">
<rect key="frame" x="36" y="79" width="108" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Break" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Pg2-w8-mzE">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="btn_Break:" target="XfG-lQ-9wD" id="wvE-WV-51x"/>
</connections>
</button>
<scrollView fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D58-pD-kHB">
<rect key="frame" x="146" y="20" width="284" height="362"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" ambiguous="YES" id="bpK-Jl-YbG">
<rect key="frame" x="1" y="0.0" width="282" height="361"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" headerView="Ep4-FK-mkU" viewBased="YES" id="MuT-J3-VZ6">
<rect key="frame" x="0.0" y="0.0" width="282" height="338"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn identifier="AddressCellID" width="63" minWidth="40" maxWidth="1000" id="hX8-rd-9WQ">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Address">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="Paw-o4-m30">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="CfD-bj-I9h">
<rect key="frame" x="1" y="1" width="63" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gF6-Xd-zbg">
<rect key="frame" x="0.0" y="0.0" width="63" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="rhk-Nf-Hah">
<font key="font" size="11" name="Menlo-Regular"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="gF6-Xd-zbg" id="lep-1z-ZAt"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn identifier="DataCellID" width="90" minWidth="40" maxWidth="1000" id="Ma5-Fz-J7v">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Disassembly">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="pvJ-AI-di6">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="ZF1-Mn-oL5">
<rect key="frame" x="67" y="1" width="90" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gen-Zj-0O4">
<rect key="frame" x="0.0" y="0.0" width="90" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="lxl-6b-xYm">
<font key="font" metaFont="fixedUser" size="11"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="gen-Zj-0O4" id="t04-GH-nId"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn identifier="BytesCellID" width="120" minWidth="10" maxWidth="3.4028234663852886e+38" id="75d-2O-Elg">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Data">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="RRV-a9-iz9">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="Z5P-fi-p7r">
<rect key="frame" x="160" y="1" width="120" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="W5w-RR-wsz">
<rect key="frame" x="0.0" y="0.0" width="120" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="PUG-n5-Mez">
<font key="font" metaFont="fixedUser" size="11"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="W5w-RR-wsz" id="GuG-dM-2hx"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
</tableView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="jEY-yd-b3r">
<rect key="frame" x="1" y="346" width="442" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="xl3-SC-c8c">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<tableHeaderView key="headerView" id="Ep4-FK-mkU">
<rect key="frame" x="0.0" y="0.0" width="282" height="23"/>
<autoresizingMask key="autoresizingMask"/>
</tableHeaderView>
</scrollView>
</subviews> </subviews>
</view> </view>
<connections> <connections>
@ -952,7 +996,7 @@
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> <customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
<userDefaultsController representsSharedInstance="YES" id="C79-Oc-seX"/> <userDefaultsController representsSharedInstance="YES" id="C79-Oc-seX"/>
</objects> </objects>
<point key="canvasLocation" x="75" y="655"/> <point key="canvasLocation" x="74" y="764"/>
</scene> </scene>
</scenes> </scenes>
</document> </document>

View File

@ -18,13 +18,17 @@ class DebuggerViewController: NSViewController {
@IBOutlet weak var debuggerTableView: NSTableView! @IBOutlet weak var debuggerTableView: NSTableView!
let CPU = CPUState.sharedInstance var cpuInstance = CPU.sharedInstance
var isRunning = false
var disassembly: [Disassembly] = [Disassembly]() var disassembly: [Disassembly] = [Disassembly]()
func highlightCurrentInstruction() -> Bool { func highlightCurrentInstruction() -> Bool {
for (index, instruction) in disassembly.enumerated() { for (index, instruction) in disassembly.enumerated() {
if(instruction.address == CPU.program_counter) { if(instruction.address == cpuInstance.program_counter) {
debuggerTableView.selectRowIndexes(NSIndexSet(index: index) as IndexSet, byExtendingSelection: false) debuggerTableView.selectRowIndexes(NSIndexSet(index: index) as IndexSet, byExtendingSelection: false)
debuggerTableView.scrollRowToVisible(index+10)
debuggerTableView.scrollRowToVisible(index-5)
return true //instruction found return true //instruction found
} }
} }
@ -32,15 +36,15 @@ class DebuggerViewController: NSViewController {
} }
func updateCPUStatusFields() { func updateCPUStatusFields() {
text_CPU_A.stringValue = String(format:"%02X", CPU.accumulator) text_CPU_A.stringValue = String(format:"%02X", cpuInstance.accumulator)
text_CPU_X.stringValue = String(format:"%02X", CPU.index_x) text_CPU_X.stringValue = String(format:"%02X", cpuInstance.index_x)
text_CPU_Y.stringValue = String(format:"%02X", CPU.index_y) text_CPU_Y.stringValue = String(format:"%02X", cpuInstance.index_y)
text_CPU_IP.stringValue = String(format:"%04X", CPU.program_counter) text_CPU_IP.stringValue = String(format:"%04X", cpuInstance.program_counter)
text_CPU_SR.stringValue = String(format:"%02X", CPU.stack_pointer) text_CPU_SR.stringValue = String(format:"%02X", cpuInstance.stack_pointer)
text_CPU_Flags.stringValue = String(CPU.status_register.asString()) text_CPU_Flags.stringValue = String(cpuInstance.status_register.asString())
if(!highlightCurrentInstruction()) { if(!highlightCurrentInstruction()) {
disassembly = CPU.disassemble(fromAddress: CPU.program_counter, length: 256) disassembly = cpuInstance.disassemble(fromAddress: cpuInstance.program_counter, length: 256)
highlightCurrentInstruction() highlightCurrentInstruction()
} }
} }
@ -51,11 +55,11 @@ class DebuggerViewController: NSViewController {
debuggerTableView.delegate = self debuggerTableView.delegate = self
debuggerTableView.dataSource = self debuggerTableView.dataSource = self
CPU.memoryInterface.loadBinary(path: "/Users/luigi/6502/test.bin") cpuInstance.memoryInterface.loadBinary(path: "/Users/luigi/6502/test.bin")
CPU.performReset() cpuInstance.performReset()
CPU.program_counter = 0x400 //entry point for the test program cpuInstance.program_counter = 0x400 //entry point for the test program
updateCPUStatusFields() updateCPUStatusFields()
disassembly = CPU.disassemble(fromAddress: CPU.program_counter, length: 10000) disassembly = cpuInstance.disassemble(fromAddress: cpuInstance.program_counter, length: 10000)
debuggerTableView.reloadData() debuggerTableView.reloadData()
// Do any additional setup after loading the view. // Do any additional setup after loading the view.
@ -69,8 +73,7 @@ class DebuggerViewController: NSViewController {
func cpuStep() { func cpuStep() {
do { do {
try CPU.executeNextInstruction() try cpuInstance.executeNextInstruction()
updateCPUStatusFields()
} catch CPUExceptions.invalidInstruction { } catch CPUExceptions.invalidInstruction {
print("*** 6502 Exception: Invalid instruction 0xXX at 0xXXXX") print("*** 6502 Exception: Invalid instruction 0xXX at 0xXXXX")
} catch { } catch {
@ -78,13 +81,39 @@ class DebuggerViewController: NSViewController {
} }
} }
func cpuRun() {
isRunning = true
let queue = DispatchQueue(label: "com.luigithirty.m6502.instructions")
let main = DispatchQueue.main
queue.async {
while(self.isRunning == true)
{
queue.asyncAfter(deadline: .now() + .seconds(1), execute: {
self.cpuStep()
main.sync {
self.updateCPUStatusFields()
}
})
}
}
}
@IBAction func btn_CPUStep(_ sender: Any) { @IBAction func btn_CPUStep(_ sender: Any) {
cpuStep() cpuStep()
updateCPUStatusFields()
} }
@IBAction func btn_Break(_ sender: Any) { @IBAction func btn_Break(_ sender: Any) {
isRunning = false
_ = 0 _ = 0
} }
@IBAction func btn_CPURun(_ sender: Any) {
cpuRun()
}
} }
extension DebuggerViewController: NSTableViewDelegate { extension DebuggerViewController: NSTableViewDelegate {
@ -92,6 +121,7 @@ extension DebuggerViewController: NSTableViewDelegate {
fileprivate enum CellIdentifiers { fileprivate enum CellIdentifiers {
static let AddressCell = "AddressCellID" static let AddressCell = "AddressCellID"
static let DataCell = "DataCellID" static let DataCell = "DataCellID"
static let BytesCell = "BytesCellID"
} }
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
@ -112,34 +142,49 @@ extension DebuggerViewController: NSTableViewDelegate {
case .accumulator: case .accumulator:
cellText = String(format: "%@ A", operation.instruction!.mnemonic) cellText = String(format: "%@ A", operation.instruction!.mnemonic)
case .immediate: case .immediate:
cellText = String(format: "%@ #$%02X", operation.instruction!.mnemonic, operation.data[0]) cellText = String(format: "%@ #$%02X", operation.instruction!.mnemonic, operation.data[1])
case .implied: case .implied:
cellText = String(format: "%@", operation.instruction!.mnemonic) cellText = String(format: "%@", operation.instruction!.mnemonic)
case .relative: case .relative:
cellText = String(format: "%@ #$%04X", operation.instruction!.mnemonic, UInt16(operation.data[0]) + operation.address) var destination: UInt16 = operation.address
if((operation.data[1] & 0x80) == 0x80) {
destination = destination + 1 - UInt16(~operation.data[1])
} else {
destination = destination + UInt16(operation.data[1])
}
cellText = String(format: "%@ #$%04X", operation.instruction!.mnemonic, destination)
case .absolute: case .absolute:
cellText = String(format: "%@ $%02X%02X", operation.instruction!.mnemonic, operation.data[1], operation.data[0]) cellText = String(format: "%@ $%02X%02X", operation.instruction!.mnemonic, operation.data[2], operation.data[1])
case .zeropage: case .zeropage:
cellText = String(format: "%@ $%02X", operation.instruction!.mnemonic, operation.data[0]) cellText = String(format: "%@ $%02X", operation.instruction!.mnemonic, operation.data[1])
case .indirect: case .indirect:
cellText = String(format: "%@ ($%02X%02X)", operation.instruction!.mnemonic, operation.data[1], operation.data[0]) cellText = String(format: "%@ ($%02X%02X)", operation.instruction!.mnemonic, operation.data[2], operation.data[1])
case .absolute_indexed_x: case .absolute_indexed_x:
cellText = String(format: "%@ $%02X%02X,X", operation.instruction!.mnemonic, operation.data[1], operation.data[0]) cellText = String(format: "%@ $%02X%02X,X", operation.instruction!.mnemonic, operation.data[2], operation.data[1])
case .absolute_indexed_y: case .absolute_indexed_y:
cellText = String(format: "%@ $%02X%02X,Y", operation.instruction!.mnemonic, operation.data[1], operation.data[0]) cellText = String(format: "%@ $%02X%02X,Y", operation.instruction!.mnemonic, operation.data[2], operation.data[1])
case .zeropage_indexed_x: case .zeropage_indexed_x:
cellText = String(format: "%@ $%02X,X", operation.instruction!.mnemonic, operation.data[0]) cellText = String(format: "%@ $%02X,X", operation.instruction!.mnemonic, operation.data[1])
case .zeropage_indexed_y: case .zeropage_indexed_y:
cellText = String(format: "%@ $%02X,Y", operation.instruction!.mnemonic, operation.data[0]) cellText = String(format: "%@ $%02X,Y", operation.instruction!.mnemonic, operation.data[1])
case .indexed_indirect: case .indexed_indirect:
cellText = String(format: "%@ ($%02X,X)", operation.instruction!.mnemonic, operation.data[0]) cellText = String(format: "%@ ($%02X,X)", operation.instruction!.mnemonic, operation.data[1])
case .indirect_indexed: case .indirect_indexed:
cellText = String(format: "%@ ($%02X),Y", operation.instruction!.mnemonic, operation.data[0]) cellText = String(format: "%@ ($%02X),Y", operation.instruction!.mnemonic, operation.data[1])
} }
} }
cellIdentifier = CellIdentifiers.DataCell cellIdentifier = CellIdentifiers.DataCell
} }
if(tableColumn == tableView.tableColumns[2]) {
cellText = ""
for byte in operation.data {
cellText += String(format: "%02X ", byte)
}
cellIdentifier = CellIdentifiers.BytesCell
}
if let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellIdentifier), owner: nil) as? NSTableCellView { if let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellIdentifier), owner: nil) as? NSTableCellView {
cell.textField?.stringValue = cellText cell.textField?.stringValue = cellText
return cell return cell

View File

@ -105,12 +105,12 @@ struct StatusRegister {
} }
} }
class CPUState: NSObject { class CPU: NSObject {
let NMI_VECTOR: UInt16 = 0xFFFA let NMI_VECTOR: UInt16 = 0xFFFA
let RESET_VECTOR: UInt16 = 0xFFFC let RESET_VECTOR: UInt16 = 0xFFFC
let IRQ_VECTOR: UInt16 = 0xFFFE let IRQ_VECTOR: UInt16 = 0xFFFE
static var sharedInstance = CPUState() static var sharedInstance = CPU()
var cycles: Int var cycles: Int
@ -124,11 +124,10 @@ class CPUState: NSObject {
var status_register: StatusRegister var status_register: StatusRegister
var page_boundary_crossed: Bool var page_boundary_crossed: Bool
var branch_was_taken: Bool
var memoryInterface: MemoryInterface var memoryInterface: MemoryInterface
var branch_was_taken: Bool
override init() { override init() {
cycles = 0 cycles = 0
@ -149,32 +148,6 @@ class CPUState: NSObject {
} }
func disassemble(fromAddress: UInt16, length: UInt16) -> [Disassembly] {
var disassembly: [Disassembly] = [Disassembly]()
var currentAddress: UInt16 = fromAddress
let endAddress: UInt16 = fromAddress + length
while(currentAddress < endAddress) {
let instruction = memoryInterface.readByte(offset: currentAddress)
let operation = InstructionTable[instruction]
var data = [UInt8]()
if(operation != nil) {
for index in 1...operation!.bytes {
data.append(memoryInterface.readByte(offset:currentAddress + UInt16(index)))
}
disassembly.append(Disassembly(instruction: operation, address: currentAddress, data: data))
currentAddress = currentAddress + UInt16(operation!.bytes)
} else {
currentAddress = currentAddress + 1
}
}
return disassembly
}
func getOperandByte() -> UInt8 { func getOperandByte() -> UInt8 {
//Returns the operand byte after the current instruction byte. //Returns the operand byte after the current instruction byte.
return memoryInterface.readByte(offset: program_counter + 1) return memoryInterface.readByte(offset: program_counter + 1)
@ -215,7 +188,7 @@ class CPUState: NSObject {
throw CPUExceptions.invalidInstruction throw CPUExceptions.invalidInstruction
} }
operation!.action(CPUState.sharedInstance, operation!.addressingMode) operation!.action(CPU.sharedInstance, operation!.addressingMode)
self.cycles += operation!.cycles self.cycles += operation!.cycles
if(self.page_boundary_crossed) { if(self.page_boundary_crossed) {

View File

@ -30,9 +30,9 @@ class CPUInstruction: NSObject {
let bytes: Int //How many bytes long is this instruction? let bytes: Int //How many bytes long is this instruction?
let addressingMode: AddressingMode //The addressing mode of this instruction. let addressingMode: AddressingMode //The addressing mode of this instruction.
let action: (CPUState, AddressingMode) -> Void //A closure that describes this function's action. let action: (CPU, AddressingMode) -> Void //A closure that describes this function's action.
init(mnemonic: String, cycles: Int, bytes: Int, addressingMode: AddressingMode, action: @escaping (CPUState, AddressingMode) -> Void) { init(mnemonic: String, cycles: Int, bytes: Int, addressingMode: AddressingMode, action: @escaping (CPU, AddressingMode) -> Void) {
self.mnemonic = mnemonic self.mnemonic = mnemonic
self.cycles = cycles self.cycles = cycles
self.bytes = bytes self.bytes = bytes
@ -222,6 +222,7 @@ let InstructionTable: [UInt8:CPUInstruction] = [
0xF0: CPUInstruction(mnemonic: "BEQ", cycles: 2, bytes: 2, addressingMode: .relative, action: Opcodes.BEQ), 0xF0: CPUInstruction(mnemonic: "BEQ", cycles: 2, bytes: 2, addressingMode: .relative, action: Opcodes.BEQ),
0x20: CPUInstruction(mnemonic: "JSR", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.JSR), 0x20: CPUInstruction(mnemonic: "JSR", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.JSR),
0x40: CPUInstruction(mnemonic: "RTI", cycles: 6, bytes: 1, addressingMode: .implied, action: Opcodes.RTI),
0x60: CPUInstruction(mnemonic: "RTS", cycles: 6, bytes: 1, addressingMode: .implied, action: Opcodes.RTS), 0x60: CPUInstruction(mnemonic: "RTS", cycles: 6, bytes: 1, addressingMode: .implied, action: Opcodes.RTS),
0x00: CPUInstruction(mnemonic: "BRK", cycles: 7, bytes: 1, addressingMode: .implied, action: Opcodes.BRK), 0x00: CPUInstruction(mnemonic: "BRK", cycles: 7, bytes: 1, addressingMode: .implied, action: Opcodes.BRK),

View File

@ -19,3 +19,31 @@ class Disassembly: NSObject {
self.data = data self.data = data
} }
} }
extension CPU {
func disassemble(fromAddress: UInt16, length: UInt16) -> [Disassembly] {
var disassembly: [Disassembly] = [Disassembly]()
var currentAddress: UInt16 = fromAddress
let endAddress: UInt16 = fromAddress + length
while(currentAddress < endAddress) {
let instruction = memoryInterface.readByte(offset: currentAddress)
let operation = InstructionTable[instruction]
var data = [UInt8]()
if(operation != nil) {
for index in 1...operation!.bytes {
data.append(memoryInterface.readByte(offset:currentAddress + UInt16(index-1)))
}
disassembly.append(Disassembly(instruction: operation, address: currentAddress, data: data))
currentAddress = currentAddress + UInt16(operation!.bytes)
} else {
currentAddress = currentAddress + 1
}
}
return disassembly
}
}

View File

@ -8,7 +8,7 @@
import Cocoa import Cocoa
extension CPUState { extension CPU {
func popByte() -> UInt8 { func popByte() -> UInt8 {
stack_pointer = stack_pointer &+ 1 stack_pointer = stack_pointer &+ 1
@ -57,7 +57,7 @@ extension CPUState {
} }
} }
func getOperandByteForAddressingMode(state: CPUState, mode: AddressingMode) -> UInt8 { func getOperandByteForAddressingMode(state: CPU, mode: AddressingMode) -> UInt8 {
switch (mode) { switch (mode) {
case .immediate: case .immediate:
@ -93,7 +93,7 @@ func getOperandByteForAddressingMode(state: CPUState, mode: AddressingMode) -> U
} }
} }
func getOperandWordForAddressingMode(state: CPUState, mode: AddressingMode) -> UInt16 { func getOperandWordForAddressingMode(state: CPU, mode: AddressingMode) -> UInt16 {
//Function that will provide a 16-bit operand to instructions. //Function that will provide a 16-bit operand to instructions.
//All instructions have 2 data bytes, little-endian. //All instructions have 2 data bytes, little-endian.
@ -132,9 +132,7 @@ func hex2bcd(hex: UInt8) -> UInt8 {
class Opcodes: NSObject { class Opcodes: NSObject {
static func ADC(state: CPUState, addressingMode: AddressingMode) -> Void { static func _Add(state: CPU, operand: UInt8) {
let operand = UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode))
var t16: UInt16 = UInt16(state.accumulator &+ operand) + UInt16((state.status_register.carry ? UInt8(1) : UInt8(0))) var t16: UInt16 = UInt16(state.accumulator &+ operand) + UInt16((state.status_register.carry ? UInt8(1) : UInt8(0)))
let t8: UInt8 = UInt8(t16 & 0xFF) let t8: UInt8 = UInt8(t16 & 0xFF)
@ -151,28 +149,54 @@ class Opcodes: NSObject {
state.accumulator = (UInt8(t16 & 0xFF)) state.accumulator = (UInt8(t16 & 0xFF))
} }
static func LDA(state: CPUState, addressingMode: AddressingMode) -> Void { static func ADC(state: CPU, addressingMode: AddressingMode) -> Void {
_Add(state: state, operand: UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode)))
/*
let operand = UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode))
var t16: UInt16 = UInt16(state.accumulator &+ operand) + UInt16((state.status_register.carry ? UInt8(1) : UInt8(0)))
let t8: UInt8 = UInt8(t16 & 0xFF)
state.status_register.overflow = (~(state.accumulator ^ operand) & (state.accumulator ^ t8) & 0x80) == 0x80
state.status_register.zero = (t8 == 0)
state.status_register.negative = (t8 & 0x80) == 0x80
if(state.status_register.decimal) {
t16 = UInt16(hex2bcd(hex: state.accumulator) + hex2bcd(hex: operand) + (state.status_register.carry ? UInt8(1) : UInt8(0)))
} else {
state.status_register.carry = (t16 > 255)
}
state.accumulator = (UInt8(t16 & 0xFF))
*/
}
static func SBC(state: CPU, addressingMode: AddressingMode) -> Void {
_Add(state: state, operand: ~(UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode))))
}
static func LDA(state: CPU, addressingMode: AddressingMode) -> Void {
state.accumulator = getOperandByteForAddressingMode(state: state, mode: addressingMode) state.accumulator = getOperandByteForAddressingMode(state: state, mode: addressingMode)
state.updateZeroFlag(value: state.accumulator) state.updateZeroFlag(value: state.accumulator)
state.updateNegativeFlag(value: state.accumulator) state.updateNegativeFlag(value: state.accumulator)
} }
static func LDX(state: CPUState, addressingMode: AddressingMode) -> Void { static func LDX(state: CPU, addressingMode: AddressingMode) -> Void {
state.index_x = getOperandByteForAddressingMode(state: state, mode: addressingMode) state.index_x = getOperandByteForAddressingMode(state: state, mode: addressingMode)
state.updateZeroFlag(value: state.index_x) state.updateZeroFlag(value: state.index_x)
state.updateNegativeFlag(value: state.index_x) state.updateNegativeFlag(value: state.index_x)
} }
static func LDY(state: CPUState, addressingMode: AddressingMode) -> Void { static func LDY(state: CPU, addressingMode: AddressingMode) -> Void {
state.index_y = getOperandByteForAddressingMode(state: state, mode: addressingMode) state.index_y = getOperandByteForAddressingMode(state: state, mode: addressingMode)
state.updateZeroFlag(value: state.index_y) state.updateZeroFlag(value: state.index_y)
state.updateNegativeFlag(value: state.index_y) state.updateNegativeFlag(value: state.index_y)
} }
static func STA(state: CPUState, addressingMode: AddressingMode) -> Void { static func STA(state: CPU, addressingMode: AddressingMode) -> Void {
let address: UInt16 let address: UInt16
if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) { if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) {
@ -190,7 +214,7 @@ class Opcodes: NSObject {
} }
} }
static func STX(state: CPUState, addressingMode: AddressingMode) -> Void { static func STX(state: CPU, addressingMode: AddressingMode) -> Void {
let address: UInt16 let address: UInt16
if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_y) { if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_y) {
@ -208,7 +232,7 @@ class Opcodes: NSObject {
} }
} }
static func STY(state: CPUState, addressingMode: AddressingMode) -> Void { static func STY(state: CPU, addressingMode: AddressingMode) -> Void {
let address: UInt16 let address: UInt16
if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) { if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) {
@ -227,63 +251,63 @@ class Opcodes: NSObject {
} }
//Register instructions //Register instructions
static func TAX(state: CPUState, addressingMode: AddressingMode) -> Void { static func TAX(state: CPU, addressingMode: AddressingMode) -> Void {
state.index_x = state.accumulator state.index_x = state.accumulator
state.updateZeroFlag(value: state.index_x); state.updateZeroFlag(value: state.index_x);
state.updateNegativeFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x);
} }
static func TXA(state: CPUState, addressingMode: AddressingMode) -> Void { static func TXA(state: CPU, addressingMode: AddressingMode) -> Void {
state.accumulator = state.index_x state.accumulator = state.index_x
state.updateZeroFlag(value: state.accumulator); state.updateZeroFlag(value: state.accumulator);
state.updateNegativeFlag(value: state.accumulator); state.updateNegativeFlag(value: state.accumulator);
} }
static func DEX(state: CPUState, addressingMode: AddressingMode) -> Void { static func DEX(state: CPU, addressingMode: AddressingMode) -> Void {
state.index_x = state.index_x &- 1 state.index_x = state.index_x &- 1
state.updateZeroFlag(value: state.index_x); state.updateZeroFlag(value: state.index_x);
state.updateNegativeFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x);
} }
static func INX(state: CPUState, addressingMode: AddressingMode) -> Void { static func INX(state: CPU, addressingMode: AddressingMode) -> Void {
state.index_x = state.index_x &+ 1 state.index_x = state.index_x &+ 1
state.updateZeroFlag(value: state.index_x); state.updateZeroFlag(value: state.index_x);
state.updateNegativeFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x);
} }
static func TAY(state: CPUState, addressingMode: AddressingMode) -> Void { static func TAY(state: CPU, addressingMode: AddressingMode) -> Void {
state.index_y = state.accumulator state.index_y = state.accumulator
state.updateZeroFlag(value: state.index_y); state.updateZeroFlag(value: state.index_y);
state.updateNegativeFlag(value: state.index_y); state.updateNegativeFlag(value: state.index_y);
} }
static func TYA(state: CPUState, addressingMode: AddressingMode) -> Void { static func TYA(state: CPU, addressingMode: AddressingMode) -> Void {
state.accumulator = state.index_y state.accumulator = state.index_y
state.updateZeroFlag(value: state.accumulator); state.updateZeroFlag(value: state.accumulator);
state.updateNegativeFlag(value: state.accumulator); state.updateNegativeFlag(value: state.accumulator);
} }
static func DEY(state: CPUState, addressingMode: AddressingMode) -> Void { static func DEY(state: CPU, addressingMode: AddressingMode) -> Void {
state.index_y = state.index_x &- 1 state.index_y = state.index_x &- 1
state.updateZeroFlag(value: state.index_y); state.updateZeroFlag(value: state.index_y);
state.updateNegativeFlag(value: state.index_y); state.updateNegativeFlag(value: state.index_y);
} }
static func INY(state: CPUState, addressingMode: AddressingMode) -> Void { static func INY(state: CPU, addressingMode: AddressingMode) -> Void {
state.index_y = state.index_x &+ 1 state.index_y = state.index_x &+ 1
state.updateZeroFlag(value: state.index_y); state.updateZeroFlag(value: state.index_y);
state.updateNegativeFlag(value: state.index_y); state.updateNegativeFlag(value: state.index_y);
} }
static func INC(state: CPUState, addressingMode: AddressingMode) -> Void { static func INC(state: CPU, addressingMode: AddressingMode) -> Void {
let address: UInt16 let address: UInt16
var val: UInt8 var val: UInt8
@ -308,7 +332,7 @@ class Opcodes: NSObject {
state.updateNegativeFlag(value: val); state.updateNegativeFlag(value: val);
} }
static func DEC(state: CPUState, addressingMode: AddressingMode) -> Void { static func DEC(state: CPU, addressingMode: AddressingMode) -> Void {
let address: UInt16 let address: UInt16
var val: UInt8 var val: UInt8
@ -334,7 +358,7 @@ class Opcodes: NSObject {
} }
//CMP //CMP
static func CMP(state: CPUState, addressingMode: AddressingMode) -> Void { static func CMP(state: CPU, addressingMode: AddressingMode) -> Void {
let data = state.accumulator - state.getOperandByte() //CMP is a subtract that doesn't affect memory let data = state.accumulator - state.getOperandByte() //CMP is a subtract that doesn't affect memory
state.updateZeroFlag(value: data) state.updateZeroFlag(value: data)
@ -342,7 +366,7 @@ class Opcodes: NSObject {
state.status_register.carry = (data >= 0) state.status_register.carry = (data >= 0)
} }
static func CPX(state: CPUState, addressingMode: AddressingMode) -> Void { static func CPX(state: CPU, addressingMode: AddressingMode) -> Void {
let data = state.index_x - state.getOperandByte() //CMP is a subtract that doesn't affect memory let data = state.index_x - state.getOperandByte() //CMP is a subtract that doesn't affect memory
state.updateZeroFlag(value: data) state.updateZeroFlag(value: data)
@ -350,7 +374,7 @@ class Opcodes: NSObject {
state.status_register.carry = (data >= 0) state.status_register.carry = (data >= 0)
} }
static func CPY(state: CPUState, addressingMode: AddressingMode) -> Void { static func CPY(state: CPU, addressingMode: AddressingMode) -> Void {
let data = state.index_y - state.getOperandByte() //CMP is a subtract that doesn't affect memory let data = state.index_y - state.getOperandByte() //CMP is a subtract that doesn't affect memory
state.updateZeroFlag(value: data) state.updateZeroFlag(value: data)
@ -359,21 +383,21 @@ class Opcodes: NSObject {
} }
//Boolean operators //Boolean operators
static func EOR(state: CPUState, addressingMode: AddressingMode) -> Void { static func EOR(state: CPU, addressingMode: AddressingMode) -> Void {
state.accumulator = state.accumulator ^ getOperandByteForAddressingMode(state: state, mode: addressingMode) state.accumulator = state.accumulator ^ getOperandByteForAddressingMode(state: state, mode: addressingMode)
state.updateZeroFlag(value: state.accumulator) state.updateZeroFlag(value: state.accumulator)
state.updateNegativeFlag(value: state.accumulator) state.updateNegativeFlag(value: state.accumulator)
} }
static func AND(state: CPUState, addressingMode: AddressingMode) -> Void { static func AND(state: CPU, addressingMode: AddressingMode) -> Void {
state.accumulator = state.accumulator & getOperandByteForAddressingMode(state: state, mode: addressingMode) state.accumulator = state.accumulator & getOperandByteForAddressingMode(state: state, mode: addressingMode)
state.updateZeroFlag(value: state.accumulator) state.updateZeroFlag(value: state.accumulator)
state.updateNegativeFlag(value: state.accumulator) state.updateNegativeFlag(value: state.accumulator)
} }
static func ORA(state: CPUState, addressingMode: AddressingMode) -> Void { static func ORA(state: CPU, addressingMode: AddressingMode) -> Void {
state.accumulator = state.accumulator | getOperandByteForAddressingMode(state: state, mode: addressingMode) state.accumulator = state.accumulator | getOperandByteForAddressingMode(state: state, mode: addressingMode)
state.updateZeroFlag(value: state.accumulator) state.updateZeroFlag(value: state.accumulator)
@ -381,7 +405,7 @@ class Opcodes: NSObject {
} }
//Bitwise operators //Bitwise operators
static func BIT(state: CPUState, addressingMode: AddressingMode) -> Void { static func BIT(state: CPU, addressingMode: AddressingMode) -> Void {
let operand = getOperandByteForAddressingMode(state: state, mode: addressingMode) let operand = getOperandByteForAddressingMode(state: state, mode: addressingMode)
let data = state.accumulator & operand let data = state.accumulator & operand
@ -390,7 +414,7 @@ class Opcodes: NSObject {
state.status_register.overflow = (state.accumulator & UInt8(0x40)) == 0x40 state.status_register.overflow = (state.accumulator & UInt8(0x40)) == 0x40
} }
static func ASL(state: CPUState, addressingMode: AddressingMode) -> Void { static func ASL(state: CPU, addressingMode: AddressingMode) -> Void {
let operand: UInt8 let operand: UInt8
if(addressingMode == .implied) { if(addressingMode == .implied) {
@ -410,7 +434,7 @@ class Opcodes: NSObject {
} }
} }
static func LSR(state: CPUState, addressingMode: AddressingMode) -> Void { static func LSR(state: CPU, addressingMode: AddressingMode) -> Void {
let operand: UInt8 let operand: UInt8
if(addressingMode == .implied) { if(addressingMode == .implied) {
@ -430,7 +454,7 @@ class Opcodes: NSObject {
} }
} }
static func ROL(state: CPUState, addressingMode: AddressingMode) -> Void { static func ROL(state: CPU, addressingMode: AddressingMode) -> Void {
let operand: UInt8 let operand: UInt8
if(addressingMode == .implied) { if(addressingMode == .implied) {
@ -456,7 +480,7 @@ class Opcodes: NSObject {
} }
} }
static func ROR(state: CPUState, addressingMode: AddressingMode) -> Void { static func ROR(state: CPU, addressingMode: AddressingMode) -> Void {
let operand: UInt8 let operand: UInt8
if(addressingMode == .implied) { if(addressingMode == .implied) {
@ -481,52 +505,52 @@ class Opcodes: NSObject {
} }
//Processor flag instructions //Processor flag instructions
static func CLC(state: CPUState, addressingMode: AddressingMode) -> Void { static func CLC(state: CPU, addressingMode: AddressingMode) -> Void {
state.status_register.carry = false state.status_register.carry = false
} }
static func SEC(state: CPUState, addressingMode: AddressingMode) -> Void { static func SEC(state: CPU, addressingMode: AddressingMode) -> Void {
state.status_register.carry = true state.status_register.carry = true
} }
static func CLI(state: CPUState, addressingMode: AddressingMode) -> Void { static func CLI(state: CPU, addressingMode: AddressingMode) -> Void {
state.status_register.irq_disable = false state.status_register.irq_disable = false
} }
static func SEI(state: CPUState, addressingMode: AddressingMode) -> Void { static func SEI(state: CPU, addressingMode: AddressingMode) -> Void {
state.status_register.irq_disable = true state.status_register.irq_disable = true
} }
static func CLV(state: CPUState, addressingMode: AddressingMode) -> Void { static func CLV(state: CPU, addressingMode: AddressingMode) -> Void {
state.status_register.overflow = false state.status_register.overflow = false
} }
static func CLD(state: CPUState, addressingMode: AddressingMode) -> Void { static func CLD(state: CPU, addressingMode: AddressingMode) -> Void {
state.status_register.decimal = false state.status_register.decimal = false
} }
static func SED(state: CPUState, addressingMode: AddressingMode) -> Void { static func SED(state: CPU, addressingMode: AddressingMode) -> Void {
state.status_register.carry = true state.status_register.carry = true
} }
//Stack instructions //Stack instructions
static func TXS(state: CPUState, addressingMode: AddressingMode) -> Void { static func TXS(state: CPU, addressingMode: AddressingMode) -> Void {
state.stack_pointer = state.index_x state.stack_pointer = state.index_x
} }
static func TSX(state: CPUState, addressingMode: AddressingMode) -> Void { static func TSX(state: CPU, addressingMode: AddressingMode) -> Void {
state.index_x = state.stack_pointer state.index_x = state.stack_pointer
state.updateZeroFlag(value: state.index_x); state.updateZeroFlag(value: state.index_x);
state.updateNegativeFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x);
} }
static func PHA(state: CPUState, addressingMode: AddressingMode) -> Void { static func PHA(state: CPU, addressingMode: AddressingMode) -> Void {
state.memoryInterface.writeByte(offset: state.stackPointerAsUInt16(), value: state.accumulator) state.memoryInterface.writeByte(offset: state.stackPointerAsUInt16(), value: state.accumulator)
state.stack_pointer = state.stack_pointer &- 1 state.stack_pointer = state.stack_pointer &- 1
} }
static func PLA(state: CPUState, addressingMode: AddressingMode) -> Void { static func PLA(state: CPU, addressingMode: AddressingMode) -> Void {
state.stack_pointer = state.stack_pointer &+ 1 state.stack_pointer = state.stack_pointer &+ 1
state.accumulator = state.memoryInterface.readByte(offset: state.stackPointerAsUInt16()) state.accumulator = state.memoryInterface.readByte(offset: state.stackPointerAsUInt16())
@ -534,84 +558,89 @@ class Opcodes: NSObject {
state.updateNegativeFlag(value: state.accumulator); state.updateNegativeFlag(value: state.accumulator);
} }
static func PHP(state: CPUState, addressingMode: AddressingMode) -> Void { static func PHP(state: CPU, addressingMode: AddressingMode) -> Void {
state.memoryInterface.writeByte(offset: state.stackPointerAsUInt16(), value: state.status_register.asByte()) state.memoryInterface.writeByte(offset: state.stackPointerAsUInt16(), value: state.status_register.asByte())
state.stack_pointer = state.stack_pointer &- 1 state.stack_pointer = state.stack_pointer &- 1
} }
static func PLP(state: CPUState, addressingMode: AddressingMode) -> Void { static func PLP(state: CPU, addressingMode: AddressingMode) -> Void {
state.stack_pointer = state.stack_pointer &+ 1 state.stack_pointer = state.stack_pointer &+ 1
state.status_register.fromByte(state: state.memoryInterface.readByte(offset: state.stackPointerAsUInt16())) state.status_register.fromByte(state: state.memoryInterface.readByte(offset: state.stackPointerAsUInt16()))
} }
static func BPL(state: CPUState, addressingMode: AddressingMode) -> Void { static func BPL(state: CPU, addressingMode: AddressingMode) -> Void {
if(!state.status_register.negative) { if(!state.status_register.negative) {
state.doBranch() state.doBranch()
} }
} }
static func BMI(state: CPUState, addressingMode: AddressingMode) -> Void { static func BMI(state: CPU, addressingMode: AddressingMode) -> Void {
if(state.status_register.negative) { if(state.status_register.negative) {
state.doBranch() state.doBranch()
} }
} }
static func BVC(state: CPUState, addressingMode: AddressingMode) -> Void { static func BVC(state: CPU, addressingMode: AddressingMode) -> Void {
if(!state.status_register.overflow) { if(!state.status_register.overflow) {
state.doBranch() state.doBranch()
} }
} }
static func BVS(state: CPUState, addressingMode: AddressingMode) -> Void { static func BVS(state: CPU, addressingMode: AddressingMode) -> Void {
if(state.status_register.overflow) { if(state.status_register.overflow) {
state.doBranch() state.doBranch()
} }
} }
static func BCC(state: CPUState, addressingMode: AddressingMode) -> Void { static func BCC(state: CPU, addressingMode: AddressingMode) -> Void {
if(!state.status_register.carry) { if(!state.status_register.carry) {
state.doBranch() state.doBranch()
} }
} }
static func BCS(state: CPUState, addressingMode: AddressingMode) -> Void { static func BCS(state: CPU, addressingMode: AddressingMode) -> Void {
if(state.status_register.carry) { if(state.status_register.carry) {
state.doBranch() state.doBranch()
} }
} }
static func BNE(state: CPUState, addressingMode: AddressingMode) -> Void { static func BNE(state: CPU, addressingMode: AddressingMode) -> Void {
if(!state.status_register.zero) { if(!state.status_register.zero) {
state.doBranch() state.doBranch()
} }
} }
static func BEQ(state: CPUState, addressingMode: AddressingMode) -> Void { static func BEQ(state: CPU, addressingMode: AddressingMode) -> Void {
if(state.status_register.zero) { if(state.status_register.zero) {
state.doBranch() state.doBranch()
} }
} }
//Misc //Misc
static func JMP(state: CPUState, addressingMode: AddressingMode) -> Void { static func JMP(state: CPU, addressingMode: AddressingMode) -> Void {
state.program_counter = getOperandWordForAddressingMode(state: state, mode: addressingMode) state.program_counter = getOperandWordForAddressingMode(state: state, mode: addressingMode)
} }
static func JSR(state: CPUState, addressingMode: AddressingMode) -> Void { static func JSR(state: CPU, addressingMode: AddressingMode) -> Void {
state.pushWord(data: state.program_counter - 1) state.pushWord(data: state.program_counter - 1)
state.program_counter = state.getOperandWord() state.program_counter = state.getOperandWord()
} }
static func RTS(state: CPUState, addressingMode: AddressingMode) -> Void { static func RTS(state: CPU, addressingMode: AddressingMode) -> Void {
state.program_counter = state.popWord() + 1 state.program_counter = state.popWord() + 1
} }
static func BRK(state: CPUState, addressingMode: AddressingMode) -> Void { static func RTI(state: CPU, addressingMode: AddressingMode) -> Void {
state.status_register.fromByte(state: state.popByte())
state.program_counter = state.popWord()
}
static func BRK(state: CPU, addressingMode: AddressingMode) -> Void {
state.status_register.brk = true state.status_register.brk = true
state.pushWord(data: state.program_counter) state.pushWord(data: state.program_counter)
state.pushByte(data: state.status_register.asByte()) state.pushByte(data: state.status_register.asByte())
state.program_counter = state.memoryInterface.readWord(offset: 0xFFFE) state.program_counter = state.memoryInterface.readWord(offset: 0xFFFE)
} }
static func NOP(state: CPUState, addressingMode: AddressingMode) -> Void {} static func NOP(state: CPU, addressingMode: AddressingMode) -> Void {}
} }