mirror of
https://github.com/LIJI32/SameBoy.git
synced 2026-10-11 22:19:50 +00:00
Add CPU load graph to Cocoa, closes #654
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#import "GBImageView.h"
|
||||
#import "GBSplitView.h"
|
||||
#import "GBVisualizerView.h"
|
||||
#import "GBCPUView.h"
|
||||
#import "GBOSDView.h"
|
||||
#import "GBDebuggerButton.h"
|
||||
|
||||
@@ -84,6 +85,8 @@ enum model {
|
||||
@property IBOutlet NSScrollView *debuggerScrollView;
|
||||
@property IBOutlet NSView *debugBar;
|
||||
|
||||
@property IBOutlet GBCPUView *cpuView;
|
||||
@property IBOutlet NSTextField *cpuCounter;
|
||||
|
||||
+ (NSImage *) imageFromData:(NSData *)data width:(NSUInteger) width height:(NSUInteger) height scale:(double) scale;
|
||||
- (void) performAtomicBlock: (void (^)())block;
|
||||
|
||||
@@ -364,6 +364,18 @@ static void debuggerReloadCallback(GB_gameboy_t *gb)
|
||||
[_gbsVisualizer setNeedsDisplay:true];
|
||||
});
|
||||
}
|
||||
|
||||
double frameUsage = GB_debugger_get_frame_cpu_usage(&_gb);
|
||||
[_cpuView addSample:frameUsage];
|
||||
|
||||
if (self.consoleWindow.visible) {
|
||||
double secondUsage = GB_debugger_get_second_cpu_usage(&_gb);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[_cpuView setNeedsDisplay:true];
|
||||
_cpuCounter.stringValue = [NSString stringWithFormat:@"%.2f%%", secondUsage * 100];
|
||||
});
|
||||
}
|
||||
|
||||
if (type != GB_VBLANK_TYPE_REPEAT) {
|
||||
[self.view flip];
|
||||
if (_borderModeChanged) {
|
||||
@@ -1325,6 +1337,8 @@ static bool is_path_writeable(const char *path)
|
||||
GB_debugger_break(&_gb);
|
||||
[self start];
|
||||
[self.consoleWindow makeKeyAndOrderFront:nil];
|
||||
double secondUsage = GB_debugger_get_second_cpu_usage(&_gb);
|
||||
_cpuCounter.stringValue = [NSString stringWithFormat:@"%.2f%%", secondUsage * 100];
|
||||
[self.consoleInput becomeFirstResponder];
|
||||
}
|
||||
|
||||
@@ -1606,6 +1620,8 @@ enum GBWindowResizeAction
|
||||
- (IBAction)showConsoleWindow:(id)sender
|
||||
{
|
||||
[self.consoleWindow orderBack:nil];
|
||||
double secondUsage = GB_debugger_get_second_cpu_usage(&_gb);
|
||||
_cpuCounter.stringValue = [NSString stringWithFormat:@"%.2f%%", secondUsage * 100];
|
||||
}
|
||||
|
||||
- (void)queueDebuggerCommand:(NSString *)command
|
||||
|
||||
+37
-7
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23727" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23727"/>
|
||||
<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>
|
||||
@@ -15,6 +15,8 @@
|
||||
<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="cpuCounter" destination="xdx-GC-Tb8" id="oSn-U3-qvg"/>
|
||||
<outlet property="cpuView" destination="aBf-yU-8M0" id="RIb-Fj-lvt"/>
|
||||
<outlet property="debugBar" destination="sah-kv-6KJ" id="24d-aM-rs5"/>
|
||||
<outlet property="debuggerBackstepButton" destination="E87-Uq-f2l" id="PI7-Wu-f0v"/>
|
||||
<outlet property="debuggerContinueButton" destination="ybQ-jy-NgI" id="fRF-S3-xSh"/>
|
||||
@@ -283,18 +285,18 @@
|
||||
<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="0.0" width="329" height="338"/>
|
||||
<rect key="frame" x="0.0" y="78" width="329" height="260"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="Cs9-3x-ATg">
|
||||
<rect key="frame" x="0.0" y="0.0" width="329" height="338"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="329" height="260"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView 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="338"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="329" height="260"/>
|
||||
<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="338"/>
|
||||
<size key="minSize" width="329" height="260"/>
|
||||
<size key="maxSize" width="1160" height="10000000"/>
|
||||
<color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<allowedInputSourceLocales>
|
||||
@@ -309,10 +311,38 @@
|
||||
<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="338"/>
|
||||
<rect key="frame" x="313" y="0.0" width="16" height="260"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="wC1-WG-WRf">
|
||||
<rect key="frame" x="0.0" y="75" width="329" height="5"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
</box>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="aBf-yU-8M0" customClass="GBCPUView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="329" height="77"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xdx-GC-Tb8">
|
||||
<rect key="frame" x="225" y="56" width="100" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="100%" id="set-AM-fVX">
|
||||
<font key="font" metaFont="smallSystemBold"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="F9b-AT-CdX">
|
||||
<rect key="frame" x="4" y="56" width="100" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="CPU Load" id="ai6-8E-Let">
|
||||
<font key="font" metaFont="smallSystemBold"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</customView>
|
||||
</subviews>
|
||||
</customView>
|
||||
</subviews>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface GBCPUView : NSView
|
||||
- (void)addSample:(double)sample;
|
||||
@end
|
||||
@@ -0,0 +1,59 @@
|
||||
#import "GBCPUView.h"
|
||||
|
||||
#define SAMPLE_COUNT 0x100 // ~4 seconds
|
||||
|
||||
@implementation GBCPUView
|
||||
{
|
||||
double _samples[SAMPLE_COUNT];
|
||||
size_t _position;
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)dirtyRect
|
||||
{
|
||||
NSSize size = self.bounds.size;
|
||||
|
||||
NSBezierPath *line = [NSBezierPath bezierPath];
|
||||
{
|
||||
double sample = _samples[_position % SAMPLE_COUNT];
|
||||
[line moveToPoint:NSMakePoint(size.width * 0.5 / SAMPLE_COUNT,
|
||||
sample * size.height)];
|
||||
}
|
||||
|
||||
for (unsigned i = 1; i < SAMPLE_COUNT; i++) {
|
||||
double sample = _samples[(i + _position) % SAMPLE_COUNT];
|
||||
[line lineToPoint:NSMakePoint(size.width * (i + 0.5) / SAMPLE_COUNT,
|
||||
sample * size.height)];
|
||||
}
|
||||
|
||||
NSBezierPath *fill = [line copy];
|
||||
[fill lineToPoint:NSMakePoint(size.width + 0.5, 0)];
|
||||
[fill lineToPoint:NSMakePoint(0.5, 0)];
|
||||
|
||||
NSColor *strokeColor;
|
||||
if (@available(macOS 10.10, *)) {
|
||||
strokeColor = [NSColor systemGreenColor];
|
||||
}
|
||||
else {
|
||||
strokeColor = [NSColor colorWithRed:3.0 / 16 green:0.5 blue:5.0 / 16 alpha:1.0];
|
||||
}
|
||||
NSColor *fillColor = [strokeColor colorWithAlphaComponent:1 / 3.0];
|
||||
|
||||
[fillColor setFill];
|
||||
[fill fill];
|
||||
|
||||
|
||||
[strokeColor setStroke];
|
||||
[line stroke];
|
||||
|
||||
[super drawRect:dirtyRect];
|
||||
}
|
||||
|
||||
- (void)addSample:(double)sample
|
||||
{
|
||||
_samples[_position++] = sample;
|
||||
if (_position == SAMPLE_COUNT) {
|
||||
_position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1728,6 +1728,24 @@ static bool ticks(GB_gameboy_t *gb, char *arguments, char *modifiers, const debu
|
||||
return true;
|
||||
}
|
||||
|
||||
double GB_debugger_get_frame_cpu_usage(GB_gameboy_t *gb)
|
||||
{
|
||||
if (gb->last_frame_busy_cycles || gb->last_frame_idle_cycles) {
|
||||
return (double)gb->last_frame_busy_cycles / (gb->last_frame_busy_cycles + gb->last_frame_idle_cycles);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
double GB_debugger_get_second_cpu_usage(GB_gameboy_t *gb)
|
||||
{
|
||||
if (gb->last_second_busy_cycles || gb->last_second_idle_cycles) {
|
||||
return (double)gb->last_second_busy_cycles / (gb->last_second_busy_cycles + gb->last_second_idle_cycles);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
double GB_debugger_get_second_cpu_usage(GB_gameboy_t *gb);
|
||||
|
||||
static bool usage(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command)
|
||||
{
|
||||
NO_MODIFIERS
|
||||
|
||||
@@ -25,6 +25,9 @@ void GB_debugger_set_disabled(GB_gameboy_t *gb, bool disabled);
|
||||
void GB_debugger_clear_symbols(GB_gameboy_t *gb);
|
||||
void GB_debugger_set_reload_callback(GB_gameboy_t *gb, GB_debugger_reload_callback_t callback);
|
||||
|
||||
double GB_debugger_get_frame_cpu_usage(GB_gameboy_t *gb);
|
||||
double GB_debugger_get_second_cpu_usage(GB_gameboy_t *gb);
|
||||
|
||||
#ifdef GB_INTERNAL
|
||||
internal void GB_debugger_run(GB_gameboy_t *gb);
|
||||
internal void GB_debugger_handle_async_commands(GB_gameboy_t *gb);
|
||||
|
||||
Reference in New Issue
Block a user