Cocoa GBS Player
|
@ -39,6 +39,14 @@
|
|||
@property (nonatomic, strong) IBOutlet GBCheatWindowController *cheatWindowController;
|
||||
@property (nonatomic, readonly) Document *partner;
|
||||
@property (nonatomic, readonly) bool isSlave;
|
||||
@property (strong) IBOutlet NSView *gbsPlayerView;
|
||||
@property (strong) IBOutlet NSTextField *gbsTitle;
|
||||
@property (strong) IBOutlet NSTextField *gbsAuthor;
|
||||
@property (strong) IBOutlet NSTextField *gbsCopyright;
|
||||
@property (strong) IBOutlet NSPopUpButton *gbsTracks;
|
||||
@property (strong) IBOutlet NSButton *gbsPlayPauseButton;
|
||||
@property (strong) IBOutlet NSButton *gbsRewindButton;
|
||||
@property (strong) IBOutlet NSSegmentedControl *gbsNextPrevButton;
|
||||
|
||||
-(uint8_t) readMemory:(uint16_t) addr;
|
||||
-(void) writeMemory:(uint16_t) addr value:(uint8_t)value;
|
||||
|
|
|
@ -513,6 +513,7 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
|||
|
||||
- (void) start
|
||||
{
|
||||
self.gbsPlayPauseButton.state = true;
|
||||
self.view.mouseHidingEnabled = (self.mainWindow.styleMask & NSWindowStyleMaskFullScreen) != 0;
|
||||
if (master) {
|
||||
[master start];
|
||||
|
@ -524,6 +525,7 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
|||
|
||||
- (void) stop
|
||||
{
|
||||
self.gbsPlayPauseButton.state = false;
|
||||
if (master) {
|
||||
if (!master->running) return;
|
||||
GB_debugger_set_disabled(&gb, true);
|
||||
|
@ -834,14 +836,86 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (IBAction)changeGBSTrack:(id)sender
|
||||
{
|
||||
[self performAtomicBlock:^{
|
||||
GB_gbs_switch_track(&gb, self.gbsTracks.indexOfSelectedItem);
|
||||
}];
|
||||
}
|
||||
- (IBAction)gbsNextPrevPushed:(id)sender
|
||||
{
|
||||
if (self.gbsNextPrevButton.selectedSegment == 0) {
|
||||
// Previous
|
||||
if (self.gbsTracks.indexOfSelectedItem == 0) {
|
||||
[self.gbsTracks selectItemAtIndex:self.gbsTracks.numberOfItems - 1];
|
||||
}
|
||||
else {
|
||||
[self.gbsTracks selectItemAtIndex:self.gbsTracks.indexOfSelectedItem - 1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Next
|
||||
if (self.gbsTracks.indexOfSelectedItem == self.gbsTracks.numberOfItems - 1) {
|
||||
[self.gbsTracks selectItemAtIndex: 0];
|
||||
}
|
||||
else {
|
||||
[self.gbsTracks selectItemAtIndex:self.gbsTracks.indexOfSelectedItem + 1];
|
||||
}
|
||||
}
|
||||
[self changeGBSTrack:sender];
|
||||
}
|
||||
|
||||
- (void)prepareGBSInterface: (GB_gbs_info_t *)info
|
||||
{
|
||||
GB_set_rendering_disabled(&gb, true);
|
||||
_view = nil;
|
||||
for (NSView *view in _mainWindow.contentView.subviews) {
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
[[NSBundle mainBundle] loadNibNamed:@"GBS" owner:self topLevelObjects:nil];
|
||||
[_mainWindow setContentSize:self.gbsPlayerView.bounds.size];
|
||||
_mainWindow.styleMask &= ~NSWindowStyleMaskResizable;
|
||||
[_mainWindow.contentView addSubview:self.gbsPlayerView];
|
||||
|
||||
self.gbsTitle.stringValue = [NSString stringWithCString:info->title encoding:NSISOLatin1StringEncoding] ?: @"GBS Player";
|
||||
self.gbsAuthor.stringValue = [NSString stringWithCString:info->author encoding:NSISOLatin1StringEncoding] ?: @"Unknown Composer";
|
||||
NSString *copyright = [NSString stringWithCString:info->copyright encoding:NSISOLatin1StringEncoding];
|
||||
if (copyright) {
|
||||
copyright = [@"©" stringByAppendingString:copyright];
|
||||
}
|
||||
self.gbsCopyright.stringValue = copyright ?: @"Missing copyright information";
|
||||
for (unsigned i = 0; i < info->track_count; i++) {
|
||||
[self.gbsTracks addItemWithTitle:[NSString stringWithFormat:@"Track %u", i + 1]];
|
||||
}
|
||||
[self.gbsTracks selectItemAtIndex:info->first_track];
|
||||
self.gbsPlayPauseButton.image.template = true;
|
||||
self.gbsPlayPauseButton.alternateImage.template = true;
|
||||
self.gbsRewindButton.image.template = true;
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
[self.gbsNextPrevButton imageForSegment:i].template = true;
|
||||
}
|
||||
|
||||
if (!self.audioClient.isPlaying) {
|
||||
[self.audioClient start];
|
||||
}
|
||||
|
||||
if (@available(macOS 10.10, *)) {
|
||||
_mainWindow.titlebarAppearsTransparent = true;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) loadROM
|
||||
{
|
||||
NSString *rom_warnings = [self captureOutputForBlock:^{
|
||||
GB_debugger_clear_symbols(&gb);
|
||||
if ([[self.fileType pathExtension] isEqualToString:@"isx"]) {
|
||||
if ([[[self.fileType pathExtension] lowercaseString] isEqualToString:@"isx"]) {
|
||||
GB_load_isx(&gb, self.fileURL.path.UTF8String);
|
||||
GB_load_battery(&gb, [[self.fileURL URLByDeletingPathExtension] URLByAppendingPathExtension:@"ram"].path.UTF8String);
|
||||
|
||||
}
|
||||
else if ([[[self.fileType pathExtension] lowercaseString] isEqualToString:@"gbs"]) {
|
||||
GB_gbs_info_t info;
|
||||
GB_load_gbs(&gb, self.fileURL.path.UTF8String, &info);
|
||||
[self prepareGBSInterface:&info];
|
||||
}
|
||||
else {
|
||||
GB_load_rom(&gb, [self.fileURL.path UTF8String]);
|
||||
|
@ -861,8 +935,10 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
|||
- (void)close
|
||||
{
|
||||
[self disconnectLinkCable];
|
||||
if (!self.gbsPlayerView) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:self.mainWindow.frame.size.width forKey:@"LastWindowWidth"];
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:self.mainWindow.frame.size.height forKey:@"LastWindowHeight"];
|
||||
}
|
||||
[self stop];
|
||||
[self.consoleWindow close];
|
||||
[self.memoryWindow close];
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="Document">
|
||||
<connections>
|
||||
<outlet property="gbsAuthor" destination="gaD-ZH-Beh" id="2i7-BD-bJ2"/>
|
||||
<outlet property="gbsCopyright" destination="2dl-dH-E3J" id="LnT-Vb-pN6"/>
|
||||
<outlet property="gbsNextPrevButton" destination="SRS-M5-VVL" id="YEN-01-wRX"/>
|
||||
<outlet property="gbsPlayPauseButton" destination="qxJ-pH-d0y" id="qk8-8I-9u5"/>
|
||||
<outlet property="gbsPlayerView" destination="c22-O7-iKe" id="A1w-e5-EQE"/>
|
||||
<outlet property="gbsRewindButton" destination="0yD-Sp-Ilo" id="FgR-xd-JW5"/>
|
||||
<outlet property="gbsTitle" destination="H3v-X3-48q" id="DCl-wL-oy8"/>
|
||||
<outlet property="gbsTracks" destination="I1T-VS-Vse" id="Vk4-GP-RjB"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customView id="c22-O7-iKe">
|
||||
<rect key="frame" x="0.0" y="0.0" width="332" height="142"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="H3v-X3-48q">
|
||||
<rect key="frame" x="19.5" y="103" width="296" height="19"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" selectable="YES" alignment="center" title="Title" id="BwZ-Zj-sP6">
|
||||
<font key="font" metaFont="systemBold" size="16"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="gaD-ZH-Beh">
|
||||
<rect key="frame" x="19.5" y="79" width="296" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" selectable="YES" alignment="center" title="Author" id="IgT-r1-T38">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="2dl-dH-E3J">
|
||||
<rect key="frame" x="18.5" y="24" width="296" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" selectable="YES" title="Copyright" id="nM9-oF-OV9">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qxJ-pH-d0y">
|
||||
<rect key="frame" x="61.5" y="48" width="39" height="23"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="Play" imagePosition="only" alignment="center" alternateImage="Pause" state="on" borderStyle="border" focusRingType="none" inset="2" id="3ZK-br-UrS">
|
||||
<behavior key="behavior" pushIn="YES" changeContents="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="togglePause:" target="-2" id="AUe-I7-nOK"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0yD-Sp-Ilo">
|
||||
<rect key="frame" x="19.5" y="48" width="38" height="23"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="Rewind" imagePosition="only" alignment="center" state="on" borderStyle="border" focusRingType="none" inset="2" id="ZIF-TP-Fqn">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="changeGBSTrack:" target="-2" id="jug-AS-bW7"/>
|
||||
</connections>
|
||||
</button>
|
||||
<popUpButton focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="I1T-VS-Vse">
|
||||
<rect key="frame" x="105.5" y="48" width="131" height="23"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<popUpButtonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="border" focusRingType="none" imageScaling="proportionallyDown" inset="2" id="YJh-dI-A5D">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="Knp-Ok-Pb4"/>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<action selector="changeGBSTrack:" target="-2" id="HET-AT-CfQ"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
<segmentedControl verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SRS-M5-VVL">
|
||||
<rect key="frame" x="240.5" y="48" width="72" height="23"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<segmentedCell key="cell" borderStyle="border" alignment="left" style="texturedRounded" trackingMode="momentary" id="cmq-I8-cFL">
|
||||
<font key="font" metaFont="system"/>
|
||||
<segments>
|
||||
<segment toolTip="Previous Track" image="Previous" width="33"/>
|
||||
<segment toolTip="Next Track" image="Next" width="32" tag="1"/>
|
||||
</segments>
|
||||
</segmentedCell>
|
||||
<connections>
|
||||
<action selector="gbsNextPrevPushed:" target="-2" id="roN-Iy-tDQ"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
</subviews>
|
||||
<point key="canvasLocation" x="67" y="253"/>
|
||||
</customView>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="Next" width="16" height="10"/>
|
||||
<image name="Pause" width="10" height="10"/>
|
||||
<image name="Play" width="10" height="10"/>
|
||||
<image name="Previous" width="16" height="10"/>
|
||||
<image name="Rewind" width="10" height="10"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -51,7 +51,7 @@
|
|||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>gbc</string>
|
||||
<string>isx</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>ColorCartridge</string>
|
||||
|
@ -68,6 +68,26 @@
|
|||
<key>NSDocumentClass</key>
|
||||
<string>Document</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>gbs</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>ColorCartridge</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Game Boy Sound File</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>com.github.liji32.sameboy.gbs</string>
|
||||
</array>
|
||||
<key>LSTypeIsPackage</key>
|
||||
<integer>0</integer>
|
||||
<key>NSDocumentClass</key>
|
||||
<string>Document</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>SameBoy</string>
|
||||
|
@ -156,6 +176,25 @@
|
|||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>Game Boy Sound File</string>
|
||||
<key>UTTypeIconFile</key>
|
||||
<string>ColorCartridge</string>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.github.liji32.sameboy.gbs</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>gbs</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>SameBoy needs to access your camera to emulate the Game Boy Camera</string>
|
||||
|
|
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 4.4 KiB |
|
@ -153,7 +153,7 @@ static void display_vblank(GB_gameboy_t *gb)
|
|||
}
|
||||
}
|
||||
|
||||
if (gb->border_mode == GB_BORDER_ALWAYS && !GB_is_sgb(gb)) {
|
||||
if (!gb->disable_rendering && gb->border_mode == GB_BORDER_ALWAYS && !GB_is_sgb(gb)) {
|
||||
GB_borrow_sgb_border(gb);
|
||||
uint32_t border_colors[16 * 4];
|
||||
|
||||
|
|