Update the Cocoa debugger interface with buttons, add an interrupt command

This commit is contained in:
Lior Halphon 2022-10-01 16:06:11 +03:00
parent ecaa92f853
commit 36cf778232
21 changed files with 358 additions and 70 deletions

BIN
Cocoa/ContinueTemplate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

View File

@ -4,6 +4,8 @@
#import "GBSplitView.h"
#import "GBVisualizerView.h"
#import "GBOSDView.h"
#import "GBOptionalVisualEffectView.h"
#import "GBDebuggerButton.h"
@class GBCheatWindowController;
@class GBPaletteView;
@ -58,6 +60,13 @@
@property uint8_t oamHeight;
@property (strong) IBOutlet NSView *audioRecordingAccessoryView;
@property (strong) IBOutlet NSPopUpButton *audioFormatButton;
@property (strong) IBOutlet GBOptionalVisualEffectView *debuggerSidebarEffectView;
@property (strong) IBOutlet GBDebuggerButton *debuggerContinueButton;
@property (strong) IBOutlet GBDebuggerButton *debuggerNextButton;
@property (strong) IBOutlet GBDebuggerButton *debuggerStepButton;
@property (strong) IBOutlet GBDebuggerButton *debuggerFinishButton;
+ (NSImage *) imageFromData:(NSData *)data width:(NSUInteger) width height:(NSUInteger) height scale:(double) scale;
-(uint8_t) readMemory:(uint16_t) addr;

View File

@ -74,7 +74,7 @@ enum model {
bool fullScreen;
bool in_sync_input;
bool _debuggerCommandWhilePaused;
NSString *_debuggerCommandWhilePaused;
HFController *hex_controller;
NSString *lastConsoleInput;
@ -549,6 +549,10 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
- (void) start
{
dispatch_async(dispatch_get_main_queue(), ^{
[self updateDebuggerButtons];
[slave updateDebuggerButtons];
});
self.gbsPlayPauseButton.state = true;
self.view.mouseHidingEnabled = (self.mainWindow.styleMask & NSWindowStyleMaskFullScreen) != 0;
if (master) {
@ -562,6 +566,10 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
- (void) stop
{
dispatch_async(dispatch_get_main_queue(), ^{
[self updateDebuggerButtons];
[slave updateDebuggerButtons];
});
self.gbsPlayPauseButton.state = false;
if (master) {
if (!master->running) return;
@ -1151,16 +1159,21 @@ static bool is_path_writeable(const char *path)
[[NSUserDefaults standardUserDefaults] setBool:!_audioClient.isPlaying forKey:@"Mute"];
}
- (bool) isPaused
{
if (self.partner) {
return !self.partner->running || GB_debugger_is_stopped(&gb) || GB_debugger_is_stopped(&self.partner->gb);
}
return (!running) || GB_debugger_is_stopped(&gb);
}
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)anItem
{
if ([anItem action] == @selector(mute:)) {
[(NSMenuItem *)anItem setState:!_audioClient.isPlaying];
}
else if ([anItem action] == @selector(togglePause:)) {
if (master) {
[(NSMenuItem *)anItem setState:(!master->running) || (GB_debugger_is_stopped(&gb)) || (GB_debugger_is_stopped(&gb))];
}
[(NSMenuItem *)anItem setState:(!running) || (GB_debugger_is_stopped(&gb))];
[(NSMenuItem *)anItem setState:self.isPaused];
return !GB_debugger_is_stopped(&gb);
}
else if ([anItem action] == @selector(reset:) && anItem.tag != MODEL_NONE) {
@ -1322,15 +1335,27 @@ static bool is_path_writeable(const char *path)
[self.consoleWindow orderBack:nil];
}
- (IBAction)consoleInput:(NSTextField *)sender
- (void)queueDebuggerCommand:(NSString *)command
{
if (!master && !running && !GB_debugger_is_stopped(&gb)) {
_debuggerCommandWhilePaused = true;
_debuggerCommandWhilePaused = command;
GB_debugger_break(&gb);
[self start];
return;
}
if (!in_sync_input) {
[self log:">"];
}
[self log:[command UTF8String]];
[self log:"\n"];
[has_debugger_input lock];
[debugger_input_queue addObject:command];
[has_debugger_input unlockWithCondition:1];
}
- (IBAction)consoleInput:(NSTextField *)sender
{
NSString *line = [sender stringValue];
if ([line isEqualToString:@""] && lastConsoleInput) {
line = lastConsoleInput;
@ -1341,15 +1366,8 @@ static bool is_path_writeable(const char *path)
else {
line = @"";
}
if (!in_sync_input) {
[self log:">"];
}
[self log:[line UTF8String]];
[self log:"\n"];
[has_debugger_input lock];
[debugger_input_queue addObject:line];
[has_debugger_input unlockWithCondition:1];
[self queueDebuggerCommand: line];
[sender setStringValue:@""];
}
@ -1397,7 +1415,7 @@ static bool is_path_writeable(const char *path)
[console_output_lock unlock];
}
- (char *) getDebuggerInput
- (char *)getDebuggerInput
{
bool isPlaying = _audioClient.isPlaying;
if (isPlaying) {
@ -1408,11 +1426,16 @@ static bool is_path_writeable(const char *path)
[audioLock unlock];
in_sync_input = true;
[self updateSideView];
dispatch_async(dispatch_get_main_queue(), ^{
[self updateDebuggerButtons];
});
[self.partner updateDebuggerButtons];
[self log:">"];
if (_debuggerCommandWhilePaused) {
_debuggerCommandWhilePaused = false;
NSString *command = _debuggerCommandWhilePaused;
_debuggerCommandWhilePaused = nil;
dispatch_async(dispatch_get_main_queue(), ^{
[self consoleInput:self.consoleInput];
[self queueDebuggerCommand:command];
});
}
[has_debugger_input lockWhenCondition:1];
@ -1426,6 +1449,8 @@ static bool is_path_writeable(const char *path)
shouldClearSideView = false;
[self.debuggerSideView setString:@""];
}
[self updateDebuggerButtons];
[self.partner updateDebuggerButtons];
});
if (isPlaying) {
[_audioClient start];
@ -2231,7 +2256,7 @@ static bool is_path_writeable(const char *path)
/* NSSplitView renders its separator without the proper vibrancy, so we made it transparent and move an
NSBox-based separator that renders properly so it acts like the split view's separator. */
NSRect rect = self.debuggerVerticalLine.frame;
rect.origin.x = [[[splitview arrangedSubviews] firstObject] frame].size.width - 1;
rect.origin.x = [[[splitview arrangedSubviews] firstObject] frame].size.width - 2;
self.debuggerVerticalLine.frame = rect;
}
@ -2573,4 +2598,49 @@ static bool is_path_writeable(const char *path)
}];
}
- (void)updateDebuggerButtons
{
bool updateContinue = false;
if (@available(macOS 10.10, *)) {
if ([self.consoleInput.placeholderAttributedString.string isEqualToString:self.debuggerContinueButton.alternateTitle]) {
[self.debuggerContinueButton mouseExited:nil];
updateContinue = true;
}
}
if (self.isPaused) {
self.debuggerContinueButton.toolTip = self.debuggerContinueButton.title = @"Continue";
self.debuggerContinueButton.alternateTitle = @"continue";
self.debuggerContinueButton.imagePosition = NSImageOnly;
if (@available(macOS 10.14, *)) {
self.debuggerContinueButton.contentTintColor = nil;
}
self.debuggerContinueButton.image = [NSImage imageNamed:@"ContinueTemplate"];
self.debuggerNextButton.enabled = true;
self.debuggerStepButton.enabled = true;
self.debuggerFinishButton.enabled = true;
}
else {
self.debuggerContinueButton.toolTip = self.debuggerContinueButton.title = @"Interrupt";
self.debuggerContinueButton.alternateTitle = @"interrupt";
self.debuggerContinueButton.imagePosition = NSImageOnly;
if (@available(macOS 10.14, *)) {
self.debuggerContinueButton.contentTintColor = [NSColor controlAccentColor];
}
self.debuggerContinueButton.image = [NSImage imageNamed:@"InterruptTemplate"];
self.debuggerNextButton.enabled = false;
self.debuggerStepButton.enabled = false;
self.debuggerFinishButton.enabled = false;
}
if (updateContinue) {
[self.debuggerContinueButton mouseEntered:nil];
}
}
- (IBAction)debuggerButtonPressed:(NSButton *)sender
{
[self queueDebuggerCommand:sender.alternateTitle];
}
@end

View File

@ -3,6 +3,7 @@
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
<capability name="System colors introduced in macOS 10.14" minToolsVersion="10.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -14,9 +15,14 @@
<outlet property="consoleInput" destination="l22-S8-uji" id="Heu-am-YgB"/>
<outlet property="consoleOutput" destination="doS-dM-hnl" id="Gn5-ju-Wb0"/>
<outlet property="consoleWindow" destination="21F-Ah-yHX" id="eQ4-ug-LsT"/>
<outlet property="debuggerContinueButton" destination="G4h-KO-Z3g" id="Dad-5e-XYM"/>
<outlet property="debuggerFinishButton" destination="vtb-n5-Qlz" id="9vv-fJ-gxp"/>
<outlet property="debuggerNextButton" destination="cOi-Rs-9gS" id="Xjx-uM-D0u"/>
<outlet property="debuggerSideView" destination="JgV-7E-iwp" id="RaA-fw-3i1"/>
<outlet property="debuggerSideViewInput" destination="w0g-eK-jM4" id="GBf-WK-ryI"/>
<outlet property="debuggerSidebarEffectView" destination="4Z2-33-dYY" id="Ja6-bC-rQg"/>
<outlet property="debuggerSplitView" destination="pUc-ZN-vl5" id="0sG-0D-cID"/>
<outlet property="debuggerStepButton" destination="DsN-Ce-QoH" id="Ts4-uK-pvI"/>
<outlet property="debuggerVerticalLine" destination="7bR-gM-1At" id="rfy-7Z-388"/>
<outlet property="feedImageView" destination="Ar0-nN-eop" id="wHa-St-o4G"/>
<outlet property="gridButton" destination="fL6-2S-Rgd" id="jtV-jh-GHC"/>
@ -87,50 +93,31 @@
<rect key="frame" x="0.0" y="0.0" width="921" height="400"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" mirrorLayoutDirectionWhenInternationalizing="never" translatesAutoresizingMaskIntoConstraints="NO" id="l22-S8-uji">
<rect key="frame" x="0.0" y="0.0" width="921" height="24"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" focusRingType="none" id="p3j-nS-44f" customClass="GBTerminalTextFieldCell">
<font key="font" metaFont="fixedUser" size="11"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" red="0.16470588235294117" green="0.16470588235294117" blue="0.16470588235294117" alpha="1" colorSpace="calibratedRGB"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<action selector="consoleInput:" target="-2" id="ylQ-vw-ARS"/>
</connections>
</textField>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="960-dL-7ZY">
<rect key="frame" x="0.0" y="23" width="921" height="5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</box>
<box horizontalHuggingPriority="750" boxType="separator" id="7bR-gM-1At">
<rect key="frame" x="590" y="25" width="5" height="376"/>
<rect key="frame" x="590" y="0.0" width="5" height="401"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" heightSizable="YES"/>
</box>
<splitView dividerStyle="thin" vertical="YES" id="pUc-ZN-vl5" customClass="GBSplitView">
<rect key="frame" x="0.0" y="25" width="921" height="376"/>
<rect key="frame" x="0.0" y="0.0" width="921" height="401"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<customView fixedFrame="YES" id="2rj-7i-kxc">
<rect key="frame" x="0.0" y="0.0" width="591" height="376"/>
<customView fixedFrame="YES" id="2rj-7i-kxc" customClass="GBOptionalVisualEffectView">
<rect key="frame" x="0.0" y="0.0" width="591" height="401"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="oTo-zx-o6N">
<rect key="frame" x="0.0" y="0.0" width="591" height="376"/>
<rect key="frame" x="0.0" y="52" width="591" height="349"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" copiesOnScroll="NO" id="EQe-Ad-L7S">
<rect key="frame" x="0.0" y="0.0" width="591" height="376"/>
<autoresizingMask key="autoresizingMask"/>
<rect key="frame" x="0.0" y="0.0" width="591" height="349"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView ambiguous="YES" editable="NO" drawsBackground="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" baseWritingDirection="leftToRight" findStyle="bar" allowsNonContiguousLayout="YES" id="doS-dM-hnl">
<rect key="frame" x="0.0" y="0.0" width="591" height="376"/>
<textView ambiguous="YES" editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" baseWritingDirection="leftToRight" findStyle="bar" allowsNonContiguousLayout="YES" id="doS-dM-hnl">
<rect key="frame" x="0.0" y="0.0" width="591" height="349"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="0.14901960784313725" green="0.14901960784313725" blue="0.14901960784313725" alpha="1" colorSpace="calibratedRGB"/>
<size key="minSize" width="591" height="376"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.25" colorSpace="custom" customColorSpace="sRGB"/>
<size key="minSize" width="591" height="349"/>
<size key="maxSize" width="1160" height="10000000"/>
<color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
@ -138,29 +125,112 @@
</allowedInputSourceLocales>
</textView>
</subviews>
<color key="backgroundColor" red="0.16470588235294117" green="0.16470588235294117" blue="0.16470588235294117" alpha="1" colorSpace="calibratedRGB"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="3fZ-tl-Zi7">
<rect key="frame" x="-100" y="-100" width="87" height="18"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="cwi-6E-rbh">
<rect key="frame" x="575" y="0.0" width="16" height="376"/>
<rect key="frame" x="575" y="0.0" width="16" height="349"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<textField focusRingType="none" verticalHuggingPriority="750" mirrorLayoutDirectionWhenInternationalizing="never" id="l22-S8-uji">
<rect key="frame" x="0.0" y="0.0" width="593" height="26"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" focusRingType="none" drawsBackground="YES" id="p3j-nS-44f" customClass="GBTerminalTextFieldCell">
<font key="font" metaFont="fixedUser" size="11"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.25" colorSpace="custom" customColorSpace="calibratedRGB"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<action selector="consoleInput:" target="-2" id="ylQ-vw-ARS"/>
</connections>
</textField>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="xJr-K6-B4B">
<rect key="frame" x="0.0" y="49" width="591" height="4"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</box>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="9DF-fj-a2v">
<rect key="frame" x="0.0" y="24" width="591" height="4"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</box>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="G4h-KO-Z3g" customClass="GBDebuggerButton">
<rect key="frame" x="0.0" y="26" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Interrupt" alternateTitle="interrupt" bezelStyle="rounded" image="InterruptTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="wfO-32-eG5">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<color key="contentTintColor" name="controlAccentColor" catalog="System" colorSpace="catalog"/>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="SjG-90-8dJ"/>
<outlet property="textField" destination="l22-S8-uji" id="NZ8-eJ-Uyd"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cOi-Rs-9gS" customClass="GBDebuggerButton">
<rect key="frame" x="26" y="26" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Step Over" alternateTitle="next" bezelStyle="rounded" image="NextTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="buW-ke-lgF">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="g7E-UM-SHV"/>
<outlet property="textField" destination="l22-S8-uji" id="1uM-AA-yHi"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DsN-Ce-QoH" customClass="GBDebuggerButton">
<rect key="frame" x="52" y="26" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Step Into" alternateTitle="step" bezelStyle="rounded" image="StepTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="ATJ-Vx-zbo">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="QMw-82-HKJ"/>
<outlet property="textField" destination="l22-S8-uji" id="qaF-TF-cwg"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vtb-n5-Qlz" customClass="GBDebuggerButton">
<rect key="frame" x="76" y="26" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Step Out" alternateTitle="finish" bezelStyle="rounded" image="FinishTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="8mF-ii-5Hx">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="krr-9m-Jfz"/>
<outlet property="textField" destination="l22-S8-uji" id="uYK-tU-BnO"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oCa-UH-1mi" customClass="GBDebuggerButton">
<rect key="frame" x="565" y="26" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Help" alternateTitle="help" bezelStyle="rounded" image="HelpTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="tvn-kY-8FO">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="PwN-rf-AcB"/>
<outlet property="textField" destination="l22-S8-uji" id="blK-B3-MWI"/>
</connections>
</button>
</subviews>
</customView>
<customView fixedFrame="YES" id="4Z2-33-dYY">
<rect key="frame" x="592" y="0.0" width="329" height="376"/>
<customView fixedFrame="YES" id="4Z2-33-dYY" customClass="GBOptionalVisualEffectView">
<rect key="frame" x="592" y="0.0" width="329" height="401"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" scrollerKnobStyle="dark" translatesAutoresizingMaskIntoConstraints="NO" id="V9U-Ua-F4z">
<rect key="frame" x="0.0" y="329" width="329" height="47"/>
<rect key="frame" x="0.0" y="354" width="329" height="47"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" copiesOnScroll="NO" id="YHx-TM-zIC">
<rect key="frame" x="0.0" y="0.0" width="329" height="47"/>
<autoresizingMask key="autoresizingMask"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView ambiguous="YES" drawsBackground="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" allowsCharacterPickerTouchBarItem="NO" allowsUndo="YES" allowsNonContiguousLayout="YES" textCompletion="NO" spellingCorrection="YES" id="w0g-eK-jM4">
<rect key="frame" x="0.0" y="0.0" width="329" height="47"/>
@ -186,22 +256,22 @@
</scroller>
</scrollView>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="5qI-qZ-nkh">
<rect key="frame" x="0.0" y="327" width="327" height="5"/>
<rect key="frame" x="0.0" y="352" width="329" height="5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
</box>
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vts-CC-ZjQ">
<rect key="frame" x="0.0" y="2" width="329" height="328"/>
<rect key="frame" x="0.0" y="0.0" width="329" height="354"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" copiesOnScroll="NO" id="Cs9-3x-ATg">
<rect key="frame" x="0.0" y="0.0" width="329" height="328"/>
<autoresizingMask key="autoresizingMask"/>
<rect key="frame" x="0.0" y="0.0" width="329" height="354"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView ambiguous="YES" editable="NO" drawsBackground="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" baseWritingDirection="leftToRight" findStyle="bar" allowsNonContiguousLayout="YES" spellingCorrection="YES" id="JgV-7E-iwp">
<rect key="frame" x="0.0" y="0.0" width="329" height="328"/>
<rect key="frame" x="0.0" y="0.0" width="329" height="354"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" red="0.14901960780000001" green="0.14901960780000001" blue="0.14901960780000001" alpha="1" colorSpace="calibratedRGB"/>
<size key="minSize" width="329" height="328"/>
<size key="minSize" width="329" height="354"/>
<size key="maxSize" width="1160" height="10000000"/>
<color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
@ -216,7 +286,7 @@
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="4jm-Gm-D2R">
<rect key="frame" x="313" y="0.0" width="16" height="328"/>
<rect key="frame" x="313" y="0.0" width="16" height="354"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
@ -778,7 +848,7 @@
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" heightSizable="YES"/>
<clipView key="contentView" id="mzf-yu-RID">
<rect key="frame" x="1" y="0.0" width="398" height="274"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" headerView="pvX-uJ-qK5" id="tA3-8T-bxb">
<rect key="frame" x="0.0" y="0.0" width="398" height="257"/>
@ -877,7 +947,12 @@
</customObject>
</objects>
<resources>
<image name="FinishTemplate" width="14" height="14"/>
<image name="HelpTemplate" width="14" height="14"/>
<image name="InterruptTemplate" width="14" height="14"/>
<image name="NSFolder" width="32" height="32"/>
<image name="NSStopProgressFreestandingTemplate" width="14" height="14"/>
<image name="NextTemplate" width="14" height="14"/>
<image name="StepTemplate" width="14" height="14"/>
</resources>
</document>

BIN
Cocoa/FinishTemplate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

BIN
Cocoa/FinishTemplate@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

7
Cocoa/GBDebuggerButton.h Normal file
View File

@ -0,0 +1,7 @@
#import <Cocoa/Cocoa.h>
@class GBDocument;
@interface GBDebuggerButton : NSButton
@property (weak) IBOutlet NSTextField *textField;
@end

48
Cocoa/GBDebuggerButton.m Normal file
View File

@ -0,0 +1,48 @@
#import "GBDebuggerButton.h"
@implementation GBDebuggerButton
{
NSTrackingArea *_trackingArea;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
self.toolTip = self.title;
return self;
}
- (void)mouseEntered:(NSEvent *)event
{
if (@available(macOS 10.10, *)) {
NSDictionary *attributes = @{
NSForegroundColorAttributeName: [NSColor colorWithWhite:1.0 alpha:0.5],
NSFontAttributeName: self.textField.font
};
self.textField.placeholderAttributedString =
[[NSAttributedString alloc] initWithString:self.alternateTitle attributes:attributes];
}
}
- (void)mouseExited:(NSEvent *)event
{
if (@available(macOS 10.10, *)) {
if ([self.textField.placeholderAttributedString.string isEqualToString:self.alternateTitle]) {
self.textField.placeholderAttributedString = nil;
}
}
}
-(void)updateTrackingAreas
{
[super updateTrackingAreas];
if (_trackingArea) {
[self removeTrackingArea:_trackingArea];
}
_trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds]
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways
owner:self
userInfo:nil];
[self addTrackingArea:_trackingArea];
}
@end

View File

@ -1,7 +1,11 @@
#import <Carbon/Carbon.h>
#import "GBTerminalTextFieldCell.h"
#import "NSTextFieldCell+Inset.h"
@interface GBTerminalTextView : NSTextView
{
@public __weak NSTextField *_field;
}
@property GB_gameboy_t *gb;
@end
@ -10,7 +14,7 @@
GBTerminalTextView *field_editor;
}
- (NSTextView *)fieldEditorForView:(NSView *)controlView
- (NSTextView *)fieldEditorForView:(NSTextField *)controlView
{
if (field_editor) {
field_editor.gb = self.gb;
@ -19,6 +23,10 @@
field_editor = [[GBTerminalTextView alloc] init];
[field_editor setFieldEditor:true];
field_editor.gb = self.gb;
field_editor->_field = (NSTextField *)controlView;
((NSTextFieldCell *)controlView.cell).textInset =
field_editor.textContainerInset =
NSMakeSize(0, 2);
return field_editor;
}
@ -185,14 +193,21 @@
return [super resignFirstResponder];
}
-(void)drawRect:(NSRect)dirtyRect
- (NSColor *)backgroundColor
{
return nil;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
if (reverse_search_mode && [super string].length == 0) {
NSMutableDictionary *attributes = [self.typingAttributes mutableCopy];
NSColor *color = [attributes[NSForegroundColorAttributeName] colorWithAlphaComponent:0.5];
[attributes setObject:color forKey:NSForegroundColorAttributeName];
[[[NSAttributedString alloc] initWithString:@"Reverse search..." attributes:attributes] drawAtPoint:NSMakePoint(2, 0)];
[[[NSAttributedString alloc] initWithString:@"Reverse search..." attributes:attributes] drawAtPoint:NSMakePoint(2, 2)];
}
else {
[super drawRect:dirtyRect];
}
}

BIN
Cocoa/HelpTemplate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

BIN
Cocoa/HelpTemplate@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

BIN
Cocoa/InterruptTemplate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

View File

@ -0,0 +1,6 @@
#import <AppKit/AppKit.h>
#import <Cocoa/Cocoa.h>
@interface NSTextFieldCell (Inset)
@property NSSize textInset;
@end

View File

@ -0,0 +1,39 @@
#import "NSTextFieldCell+Inset.h"
#import <AppKit/AppKit.h>
#import <objc/runtime.h>
@interface NSTextFieldCell ()
- (CGRect)_textLayerDrawingRectForCellFrame:(CGRect)rect;
@property NSSize textInset;
@end
@implementation NSTextFieldCell (Inset)
- (void)setTextInset:(NSSize)textInset
{
objc_setAssociatedObject(self, @selector(textInset), @(textInset), OBJC_ASSOCIATION_RETAIN);
}
- (NSSize)textInset
{
return [objc_getAssociatedObject(self, _cmd) sizeValue];
}
- (CGRect)_textLayerDrawingRectForCellFrameHook:(CGRect)rect
{
CGRect ret = [self _textLayerDrawingRectForCellFrameHook:rect];
NSSize inset = self.textInset;
ret.origin.x += inset.width;
ret.origin.y += inset.height;
ret.size.width -= inset.width;
ret.size.height -= inset.height;
return ret;
}
+ (void)load
{
method_exchangeImplementations(class_getInstanceMethod(self, @selector(_textLayerDrawingRectForCellFrame:)),
class_getInstanceMethod(self, @selector(_textLayerDrawingRectForCellFrameHook:)));
}
@end

BIN
Cocoa/NextTemplate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

BIN
Cocoa/NextTemplate@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

BIN
Cocoa/StepTemplate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 B

BIN
Cocoa/StepTemplate@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

View File

@ -710,7 +710,7 @@ static const char *lstrip(const char *str)
#define STOPPED_ONLY \
if (!gb->debug_stopped) { \
GB_log(gb, "Program is running. \n"); \
GB_log(gb, "Program is running, use 'interrupt' to stop execution.\n"); \
return false; \
}
@ -749,6 +749,24 @@ static bool cont(GB_gameboy_t *gb, char *arguments, char *modifiers, const debug
return false;
}
static bool interrupt(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
{
NO_MODIFIERS
if (strlen(lstrip(arguments))) {
print_usage(gb, command);
return true;
}
if (gb->debug_stopped) {
GB_log(gb, "Program already stopped.\n");
return true;
}
gb->debug_stopped = true;
return true;
}
static bool next(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
{
NO_MODIFIERS
@ -1966,6 +1984,7 @@ static bool help(GB_gameboy_t *gb, char *arguments, char *modifiers, const debug
/* Commands without implementations are aliases of the previous non-alias commands */
static const debugger_command_t commands[] = {
{"continue", 1, cont, "Continue running until next stop"},
{"interrupt", 1, interrupt, "Interrupt the program execution"},
{"next", 1, next, "Run the next instruction, skipping over function calls"},
{"step", 1, step, "Run the next instruction, stepping into function calls"},
{"finish", 1, finish, "Run until the current function returns"},