diff --git a/desmume/src/cocoa/DeSmuME.xcodeproj/project.pbxproj b/desmume/src/cocoa/DeSmuME.xcodeproj/project.pbxproj
index 304f95ad8..c0dd0d0a4 100644
--- a/desmume/src/cocoa/DeSmuME.xcodeproj/project.pbxproj
+++ b/desmume/src/cocoa/DeSmuME.xcodeproj/project.pbxproj
@@ -587,6 +587,7 @@
isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DeSmuME" */;
compatibilityVersion = "Xcode 2.4";
+ developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
@@ -894,6 +895,7 @@
GCC_UNROLL_LOOPS = YES;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Applications";
+ ONLY_ACTIVE_ARCH = NO;
PRODUCT_NAME = DeSmuME;
};
name = Debug;
diff --git a/desmume/src/cocoa/DeSmuME_Prefix.pch b/desmume/src/cocoa/DeSmuME_Prefix.pch
new file mode 100644
index 000000000..f204dcbd4
--- /dev/null
+++ b/desmume/src/cocoa/DeSmuME_Prefix.pch
@@ -0,0 +1,26 @@
+/* Copyright (C) 2011 Roger Manuel
+
+ This file is part of DeSmuME
+
+ DeSmuME is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DeSmuME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DeSmuME; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef __OBJC__
+ #define OBJ_C
+#endif
+
+#define DESMUME_COCOA
+#define HAVE_OPENGL
+#define HAVE_LIBZ
\ No newline at end of file
diff --git a/desmume/src/cocoa/Info.plist b/desmume/src/cocoa/Info.plist
index f0d50cfde..89be8a740 100644
--- a/desmume/src/cocoa/Info.plist
+++ b/desmume/src/cocoa/Info.plist
@@ -14,10 +14,26 @@
CFBundleTypeIconFile
DeSmuME
CFBundleTypeName
- Nintendo DS Software
+ Nintendo DS ROM
CFBundleTypeRole
Viewer
+
+ CFBundleTypeExtensions
+
+ dst
+
+ CFBundleTypeIconFile
+ DeSmuME
+ CFBundleTypeName
+ DeSmuME Save State
+ CFBundleTypeRole
+ Viewer
+ LSTypeIsPackage
+
+ NSPersistentStoreTypeKey
+ Binary
+
CFBundleExecutable
DeSmuME
@@ -32,11 +48,11 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 0.9.3
+ 0.9.7
CFBundleSignature
- ????
+ DSmM
CFBundleVersion
- 0.9.3
+ 0.9.7
NSMainNibFile
MainMenu
NSPrincipalClass
diff --git a/desmume/src/cocoa/about.m b/desmume/src/cocoa/about.m
index 865dc35d4..bbaa08d54 100644
--- a/desmume/src/cocoa/about.m
+++ b/desmume/src/cocoa/about.m
@@ -19,6 +19,20 @@
#import "globals.h"
+#define STRING_DESMUME_WEBSITE "http://www.desmume.org"
+#define STRING_DESMUME_FORUM_SITE "http://forums.desmume.org/index.php"
+#define STRING_DESMUME_BUG_SITE "http://sourceforge.net/tracker/?group_id=164579&atid=832291"
+
+#define STRING_FILENAME_README "README"
+#define STRING_FILENAME_COPYING "COPYING"
+#define STRING_FILENAME_AUTHORS "AUTHORS"
+#define STRING_FILENAME_CHANGELOG "ChangeLog"
+
+#define STRING_TABLABEL_README "Read Me"
+#define STRING_TABLABEL_LICENSE "License"
+#define STRING_TABLABEL_AUTHORS "Authors"
+#define STRING_TABLABEL_CHANGELOG "Change Log"
+
const CGFloat inner_padding = 3;
const CGFloat outer_padding = 3;
const CGFloat tab_view_height = 240;
@@ -36,6 +50,8 @@ NSTextField *about_website;
}
- (void)windowDidResize:(NSNotification*)notification;
- (void)windowWillClose:(NSNotification*)notification;
+
++ (void) readTextFile:(NSString *)dataPath label:(NSString *)labelName tab:(NSTabView *)tabView;
@end
@implementation AboutDelegate
@@ -77,23 +93,52 @@ NSTextField *about_website;
//end our modal session if the about window closses
[NSApp stopModal];
}
+
++ (void) readTextFile:(NSString *)dataPath label:(NSString *)labelName tab:(NSTabView *)tabView
+{
+ NSRect rect;
+ rect.origin.x = rect.origin.y = 0;
+
+ NSTabViewItem *tab_view_item = [[NSTabViewItem alloc] initWithIdentifier:nil];
+ [tab_view_item setLabel:labelName];
+ [tabView addTabViewItem:tab_view_item];
+
+ NSScrollView *scroll_view = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,0,0,0)];
+ [scroll_view setDrawsBackground:NO];
+ [scroll_view setHasVerticalScroller:YES];
+ [scroll_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
+ [tab_view_item setView:scroll_view];
+
+ rect.size = [[scroll_view contentView] frame].size;
+ NSTextView *text_view = [[NSTextView alloc] initWithFrame:rect];
+ [text_view insertText:[NSString stringWithContentsOfFile:dataPath encoding:NSASCIIStringEncoding error:NULL]];
+ [text_view setDrawsBackground:NO];
+ [text_view setEditable:NO];
+ [text_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
+ [scroll_view setDocumentView:text_view];
+ [text_view release];
+
+ [scroll_view release];
+
+ [tab_view_item release];
+}
@end
@implementation NSApplication (helpmenu)
- (void)launchWebsite
{
- [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://desmume.sourceforge.net"]];
+ [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@STRING_DESMUME_WEBSITE]];
}
- (void)launchForums
{
- [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://forums.desmume.org/index.php"]];
+ [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@STRING_DESMUME_FORUM_SITE]];
}
- (void)bugReport
{
- [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://sourceforge.net/tracker/?func=add&group_id=164579&atid=832291"]];
+ [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@STRING_DESMUME_BUG_SITE]];
}
@end
@@ -201,7 +246,7 @@ NSTextField *about_website;
//
about_website = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 8 + tab_view_height + inner_padding, width, 17)];
- [about_website setStringValue:@"http://www.desmume.org"];//fixme linkize
+ [about_website setStringValue:@STRING_DESMUME_WEBSITE];//fixme linkize
[about_website setEditable:NO];
[about_website setDrawsBackground:NO];
[about_website setBordered:NO];
@@ -221,126 +266,33 @@ NSTextField *about_website;
NSTabView *tab_view = [[NSTabView alloc] initWithFrame:NSMakeRect(outer_padding, outer_padding, window_width - outer_padding*2, tab_view_height)];
[tab_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
[[about_window contentView] addSubview:tab_view];
-
- NSRect rect;
- rect.origin.x = rect.origin.y = 0;
-
- //fixme if one of the files we read from is missing the entire panel doesn't show
-
- NSTabViewItem *tab_view_item;
- NSScrollView *scroll_view;
- NSTextView *text_view;
//README
- NSString *datapath = [main_bundle pathForResource:@"README" ofType:@""];
+ NSString *datapath = [main_bundle pathForResource:@STRING_FILENAME_README ofType:@""];
if(datapath != nil)
{
- tab_view_item = [[NSTabViewItem alloc] initWithIdentifier:nil];
- [tab_view_item setLabel:NSLocalizedString(@"Readme", nil)];
- [tab_view addTabViewItem:tab_view_item];
-
- scroll_view = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,0,0,0)];
- [scroll_view setDrawsBackground:NO];
- [scroll_view setHasVerticalScroller:YES];
- [scroll_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- [tab_view_item setView:scroll_view];
-
- rect.size = [[scroll_view contentView] frame].size;
- text_view = [[NSTextView alloc] initWithFrame:rect];
- [text_view insertText:[NSString stringWithContentsOfFile:datapath]];
- [text_view setDrawsBackground:NO];
- [text_view setEditable:NO];
- [text_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- [scroll_view setDocumentView:text_view];
- [text_view release];
-
- [scroll_view release];
-
- [tab_view_item release];
+ [AboutDelegate readTextFile:datapath label:NSLocalizedString(@STRING_TABLABEL_README, nil) tab:tab_view];
}
//LICENSE
- datapath = [main_bundle pathForResource:@"COPYING" ofType:@""];
+ datapath = [main_bundle pathForResource:@STRING_FILENAME_COPYING ofType:@""];
if(datapath != nil)
{
- tab_view_item = [[NSTabViewItem alloc] initWithIdentifier:nil];
- [tab_view_item setLabel:NSLocalizedString(@"License", nil)];
- [tab_view addTabViewItem:tab_view_item];
-
- scroll_view = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,0,0,0)];
- [scroll_view setDrawsBackground:NO];
- [scroll_view setHasVerticalScroller:YES];
- [scroll_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- [tab_view_item setView:scroll_view];
-
- rect.size = [[scroll_view contentView] frame].size;
- text_view = [[NSTextView alloc] initWithFrame:rect];
- [text_view insertText:[NSString stringWithContentsOfFile:datapath]];
- [text_view setDrawsBackground:NO];
- [text_view setEditable:NO];
- [text_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- [scroll_view setDocumentView:text_view];
- [text_view release];
-
- [scroll_view release];
-
- [tab_view_item release];
+ [AboutDelegate readTextFile:datapath label:NSLocalizedString(@STRING_TABLABEL_LICENSE, nil) tab:tab_view];
}
//AUTHORS
- datapath = [main_bundle pathForResource:@"AUTHORS" ofType:@""];
+ datapath = [main_bundle pathForResource:@STRING_FILENAME_AUTHORS ofType:@""];
if(datapath != nil)
{
- tab_view_item = [[NSTabViewItem alloc] initWithIdentifier:nil];
- [tab_view_item setLabel:NSLocalizedString(@"Authors", nil)];
- [tab_view addTabViewItem:tab_view_item];
-
- scroll_view = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,0,0,0)];
- [scroll_view setDrawsBackground:NO];
- [scroll_view setHasVerticalScroller:YES];
- [scroll_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- [tab_view_item setView:scroll_view];
-
- rect.size = [[scroll_view contentView] frame].size;
- text_view = [[NSTextView alloc] initWithFrame:rect];
- [text_view insertText:[NSString stringWithContentsOfFile:datapath]];
- [text_view setDrawsBackground:NO];
- [text_view setEditable:NO];
- [text_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- [scroll_view setDocumentView:text_view];
- [text_view release];
-
- [scroll_view release];
-
- [tab_view_item release];
+ [AboutDelegate readTextFile:datapath label:NSLocalizedString(@STRING_TABLABEL_AUTHORS, nil) tab:tab_view];
}
//CHANGE LOG
- datapath = [main_bundle pathForResource:@"ChangeLog" ofType:@""];
+ datapath = [main_bundle pathForResource:@STRING_FILENAME_CHANGELOG ofType:@""];
if(datapath != nil)
{
- tab_view_item = [[NSTabViewItem alloc] initWithIdentifier:nil];
- [tab_view_item setLabel:NSLocalizedString(@"Change Log", nil)];
- [tab_view addTabViewItem:tab_view_item];
-
- scroll_view = [[NSScrollView alloc] initWithFrame:NSMakeRect(0,0,0,0)];
- [scroll_view setDrawsBackground:NO];
- [scroll_view setHasVerticalScroller:YES];
- [scroll_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- [tab_view_item setView:scroll_view];
-
- rect.size = [[scroll_view contentView] frame].size;
- text_view = [[NSTextView alloc] initWithFrame:rect];
- [text_view insertText:[NSString stringWithContentsOfFile:datapath]];
- [text_view setDrawsBackground:NO];
- [text_view setEditable:NO];
- [text_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- [scroll_view setDocumentView:text_view];
- [text_view release];
-
- [scroll_view release];
-
- [tab_view_item release];
+ [AboutDelegate readTextFile:datapath label:NSLocalizedString(@STRING_TABLABEL_CHANGELOG, nil) tab:tab_view];
}
//
@@ -348,9 +300,9 @@ NSTextField *about_website;
content_min_width = [tab_view minimumSize].width;
[tab_view release];
-
+
//show the window
- rect = [about_window frame];
+ NSRect rect = [about_window frame];
if(rect.size.width < content_min_width + outer_padding*2)
rect.size.width = content_min_width + outer_padding*2;
[about_window setFrame:rect display:NO];
diff --git a/desmume/src/cocoa/cocoa_input.h b/desmume/src/cocoa/cocoa_input.h
new file mode 100644
index 000000000..1a153ce75
--- /dev/null
+++ b/desmume/src/cocoa/cocoa_input.h
@@ -0,0 +1,185 @@
+/* Copyright (C) 2011 Roger Manuel
+
+ This file is part of DeSmuME
+
+ DeSmuME is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DeSmuME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DeSmuME; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#import
+
+
+@interface CocoaDSInput : NSObject
+{
+ bool isStateChanged;
+ NSMutableDictionary *property;
+}
+
+- (id) init;
+- (void) dealloc;
+- (void) setIsStateChanged:(bool)state;
+- (bool) isStateChanged;
+- (void) setInputTime:(NSDate*)inputTime;
+- (NSDate*) getInputTime;
+
+@end
+
+@interface CocoaDSButton : CocoaDSInput
+{
+
+}
+
+- (id) init;
+- (void) dealloc;
+- (void) setPressed:(bool)inputValue;
+- (bool) getPressed;
+
+@end
+
+@interface CocoaDSTouch : CocoaDSInput
+{
+
+}
+
+- (id) init;
+- (void) dealloc;
+
+- (void) setTouching:(bool)inputValue;
+- (bool) getTouching;
+
+- (void) setX:(float)inputValue;
+- (float) getX;
+
+- (void) setY:(float)inputValue;
+- (float) getY;
+
+- (void) setPoint:(NSPoint)inputValue;
+- (NSPoint) getPoint;
+
+- (void) setTouchingWithCoords:(bool)isTouching x:(float)xValue y:(float)yValue;
+- (void) setTouchingWithPoint:(bool)isTouching point:(NSPoint)inputPoint;
+
+@end
+
+@interface CocoaDSMic : CocoaDSInput
+{
+
+}
+
+- (id) init;
+- (void) dealloc;
+- (void) setPressed:(bool)inputValue;
+- (bool) getPressed;
+
+@end
+
+
+@interface CocoaDSController : NSObject
+{
+ CocoaDSButton *ndsButton_Up;
+ CocoaDSButton *ndsButton_Down;
+ CocoaDSButton *ndsButton_Left;
+ CocoaDSButton *ndsButton_Right;
+ CocoaDSButton *ndsButton_A;
+ CocoaDSButton *ndsButton_B;
+ CocoaDSButton *ndsButton_X;
+ CocoaDSButton *ndsButton_Y;
+ CocoaDSButton *ndsButton_Select;
+ CocoaDSButton *ndsButton_Start;
+ CocoaDSButton *ndsButton_R;
+ CocoaDSButton *ndsButton_L;
+ CocoaDSButton *ndsButton_Debug;
+ CocoaDSButton *ndsButton_Lid;
+
+ CocoaDSTouch *ndsTouch;
+
+ CocoaDSMic *ndsMic;
+}
+
+- (id) init;
+- (void) dealloc;
+
+- (void) setupAllDSInputs;
+
+//touch screen
+- (void)touch:(NSPoint)point;
+- (void)releaseTouch;
+- (bool) getTouching;
+- (NSPoint) getTouchPoint;
+- (float) getTouchXCoord;
+- (float) getTouchYCoord;
+
+//button input
+- (void)pressStart;
+- (void)liftStart;
+- (bool) getStartPressed;
+
+- (void)pressSelect;
+- (void)liftSelect;
+- (bool) getSelectPressed;
+
+- (void)pressLeft;
+- (void)liftLeft;
+- (bool) getLeftPressed;
+
+- (void)pressRight;
+- (void)liftRight;
+- (bool) getRightPressed;
+
+- (void)pressUp;
+- (void)liftUp;
+- (bool) getUpPressed;
+
+- (void)pressDown;
+- (void)liftDown;
+- (bool) getDownPressed;
+
+- (void)pressA;
+- (void)liftA;
+- (bool) getAPressed;
+
+- (void)pressB;
+- (void)liftB;
+- (bool) getBPressed;
+
+- (void)pressX;
+- (void)liftX;
+- (bool) getXPressed;
+
+- (void)pressY;
+- (void)liftY;
+- (bool) getYPressed;
+
+- (void)pressL;
+- (void)liftL;
+- (bool) getLPressed;
+
+- (void)pressR;
+- (void)liftR;
+- (bool) getRPressed;
+
+- (void) pressDebug;
+- (void) liftDebug;
+- (bool) getDebugPressed;
+
+- (void) pressLid;
+- (void) liftLid;
+- (bool) getLidPressed;
+
+// Nintendo DS Mic
+- (void) pressMic;
+- (void) liftMic;
+- (bool) getMicPressed;
+
+@end
\ No newline at end of file
diff --git a/desmume/src/cocoa/cocoa_input.mm b/desmume/src/cocoa/cocoa_input.mm
new file mode 100644
index 000000000..3f463cc33
--- /dev/null
+++ b/desmume/src/cocoa/cocoa_input.mm
@@ -0,0 +1,596 @@
+/* Copyright (C) 2011 Roger Manuel
+
+ This file is part of DeSmuME
+
+ DeSmuME is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DeSmuME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DeSmuME; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#import "cocoa_input.h"
+#include "../NDSSystem.h"
+
+
+@implementation CocoaDSInput
+
+- (id) init
+{
+ isStateChanged = false;
+
+ property = [[NSMutableDictionary alloc] init];
+ [property setValue:[NSDate date] forKey:@"inputTime"];
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [property release];
+
+ [super dealloc];
+}
+
+- (void) setIsStateChanged:(bool)state
+{
+ isStateChanged = state;
+}
+
+- (bool) isStateChanged
+{
+ return isStateChanged;
+}
+
+- (void) setInputTime:(NSDate*)inputTime
+{
+ [property setValue:inputTime forKey:@"inputTime"];
+}
+
+- (NSDate*) getInputTime
+{
+ return [property objectForKey:@"inputTime"];
+}
+
+@end
+
+@implementation CocoaDSButton
+
+- (id) init
+{
+ [super init];
+ [property setValue:[NSNumber numberWithBool:false] forKey:@"press"];
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [super dealloc];
+}
+
+- (void) setPressed:(bool)inputValue
+{
+ // Check for state change and set the flag appropriately.
+ if (inputValue != [self getPressed])
+ {
+ isStateChanged = true;
+ }
+ else
+ {
+ isStateChanged = false;
+ }
+
+ [property setValue:[NSDate date] forKey:@"inputTime"];
+ [property setValue:[NSNumber numberWithBool:inputValue] forKey:@"press"];
+}
+
+- (bool) getPressed
+{
+ return [[property objectForKey:@"press"] boolValue];
+}
+
+@end
+
+@implementation CocoaDSTouch
+
+- (id) init
+{
+ [super init];
+ [property setValue:[NSNumber numberWithBool:false] forKey:@"touch"];
+ [property setValue:[NSNumber numberWithFloat:0.0] forKey:@"x"];
+ [property setValue:[NSNumber numberWithFloat:0.0] forKey:@"y"];
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [super dealloc];
+}
+
+- (void) setTouching:(bool)inputValue
+{
+ // Check for state change and set the flag appropriately.
+ if (inputValue != [self getTouching])
+ {
+ isStateChanged = true;
+ }
+ else
+ {
+ isStateChanged = false;
+ }
+
+ [property setValue:[NSDate date] forKey:@"inputTime"];
+ [property setValue:[NSNumber numberWithBool:inputValue] forKey:@"touch"];
+}
+
+- (bool) getTouching
+{
+ return [[property objectForKey:@"touch"] boolValue];
+}
+
+- (void) setX:(float)inputValue
+{
+ // Check for state change and set the flag appropriately.
+ if (inputValue != [self getX])
+ {
+ isStateChanged = true;
+ }
+ else
+ {
+ isStateChanged = false;
+ }
+
+ [property setValue:[NSDate date] forKey:@"inputTime"];
+ [property setValue:[NSNumber numberWithFloat:inputValue] forKey:@"x"];
+}
+
+- (float) getX
+{
+ return [[property objectForKey:@"x"] floatValue];
+}
+
+- (void) setY:(float)inputValue
+{
+ // Check for state change and set the flag appropriately.
+ if (inputValue != [self getY])
+ {
+ isStateChanged = true;
+ }
+ else
+ {
+ isStateChanged = false;
+ }
+
+ [property setValue:[NSDate date] forKey:@"inputTime"];
+ [property setValue:[NSNumber numberWithFloat:inputValue] forKey:@"y"];
+}
+
+- (float) getY
+{
+ return [[property objectForKey:@"y"] floatValue];
+}
+
+- (void) setPoint:(NSPoint)inputValue
+{
+ // Check for state change and set the flag appropriately.
+ if (inputValue.x != [self getX] || inputValue.y != [self getY])
+ {
+ isStateChanged = true;
+ }
+ else
+ {
+ isStateChanged = false;
+ }
+
+ [self setX:inputValue.x];
+ [self setY:inputValue.y];
+}
+
+- (NSPoint) getPoint
+{
+ NSPoint outPoint = {[self getX], [self getY]};
+ return outPoint;
+}
+
+- (void) setTouchingWithCoords:(bool)isTouching x:(float)xValue y:(float)yValue
+{
+ // Check for state change and set the flag appropriately.
+ if (isTouching != [self getTouching] ||
+ xValue != [self getX] ||
+ yValue != [self getY])
+ {
+ isStateChanged = true;
+ }
+ else
+ {
+ isStateChanged = false;
+ }
+
+ [property setValue:[NSDate date] forKey:@"inputTime"];
+ [property setValue:[NSNumber numberWithBool:isTouching] forKey:@"touch"];
+ [property setValue:[NSNumber numberWithFloat:xValue] forKey:@"x"];
+ [property setValue:[NSNumber numberWithFloat:yValue] forKey:@"y"];
+}
+
+- (void) setTouchingWithPoint:(bool)isTouching point:(NSPoint)inputPoint
+{
+ [self setTouchingWithCoords:isTouching x:inputPoint.x y:inputPoint.y];
+}
+
+@end
+
+@implementation CocoaDSMic
+
+- (id) init
+{
+ [super init];
+ [property setValue:[NSNumber numberWithBool:false] forKey:@"press"];
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [super dealloc];
+}
+
+- (void) setPressed:(bool)inputValue
+{
+ [property setValue:[NSDate date] forKey:@"inputTime"];
+ [property setValue:[NSNumber numberWithBool:inputValue] forKey:@"press"];
+}
+
+- (bool) getPressed
+{
+ return [[property objectForKey:@"press"] boolValue];
+}
+
+@end
+
+
+@implementation CocoaDSController
+
+- (id) init
+{
+ ndsButton_Up = [[CocoaDSButton alloc] init];
+ ndsButton_Down = [[CocoaDSButton alloc] init];
+ ndsButton_Left = [[CocoaDSButton alloc] init];
+ ndsButton_Right = [[CocoaDSButton alloc] init];
+ ndsButton_A = [[CocoaDSButton alloc] init];
+ ndsButton_B = [[CocoaDSButton alloc] init];
+ ndsButton_X = [[CocoaDSButton alloc] init];
+ ndsButton_Y = [[CocoaDSButton alloc] init];
+ ndsButton_Select = [[CocoaDSButton alloc] init];
+ ndsButton_Start = [[CocoaDSButton alloc] init];
+ ndsButton_R = [[CocoaDSButton alloc] init];
+ ndsButton_L = [[CocoaDSButton alloc] init];
+ ndsButton_Debug = [[CocoaDSButton alloc] init];
+ ndsButton_Lid = [[CocoaDSButton alloc] init];
+
+ ndsTouch = [[CocoaDSTouch alloc] init];
+
+ ndsMic = [[CocoaDSMic alloc] init];
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [ndsButton_Up release];
+ [ndsButton_Down release];
+ [ndsButton_Left release];
+ [ndsButton_Right release];
+ [ndsButton_A release];
+ [ndsButton_B release];
+ [ndsButton_X release];
+ [ndsButton_Y release];
+ [ndsButton_Select release];
+ [ndsButton_Start release];
+ [ndsButton_R release];
+ [ndsButton_L release];
+ [ndsButton_Debug release];
+ [ndsButton_Lid release];
+ [ndsTouch release];
+ [ndsMic release];
+
+ [super dealloc];
+}
+
+- (void) setupAllDSInputs
+{
+ // Setup the DS pad.
+ NDS_setPad([self getRightPressed],
+ [self getLeftPressed],
+ [self getDownPressed],
+ [self getUpPressed],
+ [self getSelectPressed],
+ [self getStartPressed],
+ [self getBPressed],
+ [self getAPressed],
+ [self getYPressed],
+ [self getXPressed],
+ [self getLPressed],
+ [self getRPressed],
+ [self getDebugPressed],
+ [self getLidPressed]);
+
+ // Setup the DS touch pad.
+ if ([self getTouching])
+ {
+ NDS_setTouchPos([self getTouchXCoord], [self getTouchYCoord]);
+ }
+ else
+ {
+ NDS_releaseTouch();
+ }
+
+ // Setup the DS mic.
+ NDS_setMic([self getMicPressed]);
+}
+
+- (void)touch:(NSPoint)point
+{
+ [ndsTouch setTouchingWithPoint:true point:point];
+}
+
+- (void)releaseTouch
+{
+ [ndsTouch setTouching:false];
+}
+
+- (bool) getTouching
+{
+ return [ndsTouch getTouching];
+}
+
+- (NSPoint) getTouchPoint
+{
+ return [ndsTouch getPoint];
+}
+
+- (float) getTouchXCoord
+{
+ return [ndsTouch getX];
+}
+
+- (float) getTouchYCoord
+{
+ return [ndsTouch getY];
+}
+
+- (void)pressStart
+{
+ [ndsButton_Start setPressed:true];
+}
+
+- (void)liftStart
+{
+ [ndsButton_Start setPressed:false];
+}
+
+- (bool) getStartPressed
+{
+ return [ndsButton_Start getPressed];
+}
+
+- (void)pressSelect
+{
+ [ndsButton_Select setPressed:true];
+}
+
+- (void)liftSelect
+{
+ [ndsButton_Select setPressed:false];
+}
+
+- (bool) getSelectPressed
+{
+ return [ndsButton_Select getPressed];
+}
+
+- (void)pressLeft
+{
+ [ndsButton_Left setPressed:true];
+}
+
+- (void)liftLeft
+{
+ [ndsButton_Left setPressed:false];
+}
+
+- (bool) getLeftPressed
+{
+ return [ndsButton_Left getPressed];
+}
+
+- (void)pressRight
+{
+ [ndsButton_Right setPressed:true];
+}
+
+- (void)liftRight
+{
+ [ndsButton_Right setPressed:false];
+}
+
+- (bool) getRightPressed
+{
+ return [ndsButton_Right getPressed];
+}
+
+- (void)pressUp
+{
+ [ndsButton_Up setPressed:true];
+}
+
+- (void)liftUp
+{
+ [ndsButton_Up setPressed:false];
+}
+
+- (bool) getUpPressed
+{
+ return [ndsButton_Up getPressed];
+}
+
+- (void)pressDown
+{
+ [ndsButton_Down setPressed:true];
+}
+
+- (void)liftDown
+{
+ [ndsButton_Down setPressed:false];
+}
+
+- (bool) getDownPressed
+{
+ return [ndsButton_Down getPressed];
+}
+
+- (void)pressA
+{
+ [ndsButton_A setPressed:true];
+}
+
+- (void)liftA
+{
+ [ndsButton_A setPressed:false];
+}
+
+- (bool) getAPressed
+{
+ return [ndsButton_A getPressed];
+}
+
+- (void)pressB
+{
+ [ndsButton_B setPressed:true];
+}
+
+- (void)liftB
+{
+ [ndsButton_B setPressed:false];
+}
+
+- (bool) getBPressed
+{
+ return [ndsButton_B getPressed];
+}
+
+- (void)pressX
+{
+ [ndsButton_X setPressed:true];
+}
+
+- (void)liftX
+{
+ [ndsButton_X setPressed:false];
+}
+
+- (bool) getXPressed
+{
+ return [ndsButton_X getPressed];
+}
+
+- (void)pressY
+{
+ [ndsButton_Y setPressed:true];
+}
+
+- (void)liftY
+{
+ [ndsButton_Y setPressed:false];
+}
+
+- (bool) getYPressed
+{
+ return [ndsButton_Y getPressed];
+}
+
+- (void)pressL
+{
+ [ndsButton_L setPressed:true];
+}
+
+- (void)liftL
+{
+ [ndsButton_L setPressed:false];
+}
+
+- (bool) getLPressed
+{
+ return [ndsButton_L getPressed];
+}
+
+- (void)pressR
+{
+ [ndsButton_R setPressed:true];
+}
+
+- (void)liftR
+{
+ [ndsButton_R setPressed:false];
+}
+
+- (bool) getRPressed
+{
+ return [ndsButton_R getPressed];
+}
+
+- (void) pressDebug
+{
+ [ndsButton_Debug setPressed:true];
+}
+
+- (void) liftDebug
+{
+ [ndsButton_Debug setPressed:false];
+}
+
+- (bool) getDebugPressed
+{
+ return [ndsButton_Debug getPressed];
+}
+
+- (void) pressLid
+{
+ [ndsButton_Lid setPressed:true];
+}
+
+- (void) liftLid
+{
+ [ndsButton_Lid setPressed:false];
+}
+
+- (bool) getLidPressed
+{
+ return [ndsButton_Lid getPressed];
+}
+
+- (void) pressMic
+{
+ [ndsMic setPressed:true];
+}
+
+- (void) liftMic
+{
+ [ndsMic setPressed:false];
+}
+
+- (bool) getMicPressed
+{
+ return [ndsMic getPressed];
+}
+
+@end
\ No newline at end of file
diff --git a/desmume/src/cocoa/cocoa_util.m b/desmume/src/cocoa/cocoa_util.m
index 27452e408..fd8447e47 100644
--- a/desmume/src/cocoa/cocoa_util.m
+++ b/desmume/src/cocoa/cocoa_util.m
@@ -58,3 +58,110 @@ NSString* openDialog(NSArray *file_types)
return NULL;
}
+BOOL CreateAppDirectory(NSString *directoryName)
+{
+ BOOL result = NO;
+ BOOL isDir = YES;
+
+ NSString *tempPath = nil;
+ NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
+ NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
+
+ NSArray *savePaths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
+ if ([savePaths count] > 0)
+ {
+ tempPath = [savePaths objectAtIndex:0];
+ }
+ else
+ {
+ return result;
+ }
+
+ NSFileManager *fileManager = [[NSFileManager alloc] init];
+
+ /*
+ Mac OS X v10.4 only
+
+ Code for creating new directories based on NSString paths.
+ */
+ tempPath = [[tempPath stringByAppendingString:@"/"] stringByAppendingString:appName];
+ result = [fileManager createDirectoryAtPath:tempPath attributes:nil];
+ if (result == NO)
+ {
+ if([fileManager fileExistsAtPath:tempPath isDirectory:&isDir] == NO)
+ {
+ [fileManager release];
+ return result;
+ }
+ }
+
+ tempPath = [[tempPath stringByAppendingString:@"/"] stringByAppendingString:appVersion];
+ result = [fileManager createDirectoryAtPath:tempPath attributes:nil];
+ if (result == NO)
+ {
+ if([fileManager fileExistsAtPath:tempPath isDirectory:&isDir] == NO)
+ {
+ [fileManager release];
+ return result;
+ }
+ }
+
+ if (directoryName != nil)
+ {
+ tempPath = [[tempPath stringByAppendingString:@"/"] stringByAppendingString:directoryName];
+ result = [fileManager createDirectoryAtPath:tempPath attributes:nil];
+ if (result == NO)
+ {
+ if([fileManager fileExistsAtPath:tempPath isDirectory:&isDir] == NO)
+ {
+ [fileManager release];
+ return result;
+ }
+ }
+ }
+
+ /*
+ In Mac OS X v10.4, having the File Manager create new directories where they already exist
+ returns NO. Note that this behavior is not per Apple's own documentation. Therefore, we manually
+ set result=YES at the end to make sure the function returns the right result.
+ */
+ result = YES;
+
+ /*
+ Mac OS X v10.5 and later
+
+ Yes, it's that simple...
+ */
+ //result = [fileManager createDirectoryAtPath:savePath createIntermediates:YES attributes:nil error:NULL];
+
+ [fileManager release];
+ return result;
+}
+
+NSString* GetPathUserAppSupport(NSString *directoryName)
+{
+ NSString *userAppSupportPath = nil;
+ NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
+ NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
+
+ NSArray *savePaths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
+ if ([savePaths count] > 0)
+ {
+ userAppSupportPath = [savePaths objectAtIndex:0];
+ }
+ else
+ {
+ return userAppSupportPath;
+ }
+
+ if (directoryName == nil)
+ {
+ userAppSupportPath = [[[[userAppSupportPath stringByAppendingString:@"/"] stringByAppendingString:appName] stringByAppendingString:@"/"] stringByAppendingString:appVersion];
+ }
+ else
+ {
+ userAppSupportPath = [[[[[[userAppSupportPath stringByAppendingString:@"/"] stringByAppendingString:appName] stringByAppendingString:@"/"] stringByAppendingString:appVersion] stringByAppendingString:@"/"] stringByAppendingString:directoryName];
+ }
+
+ return userAppSupportPath;
+}
\ No newline at end of file
diff --git a/desmume/src/cocoa/globals.h b/desmume/src/cocoa/globals.h
index 3bffd38c3..e4b8c82a1 100644
--- a/desmume/src/cocoa/globals.h
+++ b/desmume/src/cocoa/globals.h
@@ -27,6 +27,8 @@ extern "C"
void messageDialog(NSString *title, NSString *text);
BOOL messageDialogYN(NSString *title, NSString *text);
NSString* openDialog(NSArray *file_types);
+BOOL CreateAppDirectory(NSString *directoryName);
+NSString* GetPathUserAppSupport(NSString *directoryName);
//
#if !defined(__LP64__) && !defined(NS_BUILD_32_LIKE_64)
@@ -34,7 +36,15 @@ typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
-typedef float CGFloat;
+// Taken from CIVector.h of the Mac OS X 10.5 SDK.
+// Defines CGFloat for Mac OS X 10.4 and earlier.
+#ifndef CGFLOAT_DEFINED
+ typedef float CGFloat;
+# define CGFLOAT_MIN FLT_MIN
+# define CGFLOAT_MAX FLT_MAX
+# define CGFLOAT_IS_DOUBLE 0
+# define CGFLOAT_DEFINED 1
+#endif
#ifdef __cplusplus
}
diff --git a/desmume/src/cocoa/input.h b/desmume/src/cocoa/input.h
index 968934f16..9399c623b 100644
--- a/desmume/src/cocoa/input.h
+++ b/desmume/src/cocoa/input.h
@@ -25,11 +25,13 @@
*/
@class VideoOutputWindow;
+@class CocoaDSController;
@interface InputHandler : NSResponder
{
@private
VideoOutputWindow *my_ds;
+ CocoaDSController *dsController;
}
//preferences
+ (NSView*)createPreferencesView:(float)width;
diff --git a/desmume/src/cocoa/input.mm b/desmume/src/cocoa/input.mm
index 0994724e6..eb5af23f3 100644
--- a/desmume/src/cocoa/input.mm
+++ b/desmume/src/cocoa/input.mm
@@ -166,12 +166,14 @@ inline int testKey(NSString *chars_pressed, NSString *chars_for_key)
my_ds = nds;
[my_ds retain];
+ dsController = [nds getDSController];
+ [dsController retain];
+
return self;
}
- (void)dealloc
{
- [my_ds release];
[super dealloc];
}
@@ -182,18 +184,18 @@ inline int testKey(NSString *chars_pressed, NSString *chars_for_key)
NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
NSString *chars = [event characters];
- if(testKey(chars, [settings stringForKey:PREF_KEY_A ]))[my_ds pressA];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_B ]))[my_ds pressB];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_SELECT]))[my_ds pressSelect];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_START ]))[my_ds pressStart];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_RIGHT ]))[my_ds pressRight];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_LEFT ]))[my_ds pressLeft];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_UP ]))[my_ds pressUp];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_DOWN ]))[my_ds pressDown];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_R ]))[my_ds pressR];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_L ]))[my_ds pressL];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_X ]))[my_ds pressX];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_Y ]))[my_ds pressY];
+ if(testKey(chars, [settings stringForKey:PREF_KEY_A ]))[dsController pressA];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_B ]))[dsController pressB];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_SELECT]))[dsController pressSelect];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_START ]))[dsController pressStart];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_RIGHT ]))[dsController pressRight];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_LEFT ]))[dsController pressLeft];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_UP ]))[dsController pressUp];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_DOWN ]))[dsController pressDown];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_R ]))[dsController pressR];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_L ]))[dsController pressL];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_X ]))[dsController pressX];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_Y ]))[dsController pressY];
}
- (void)keyUp:(NSEvent*)event
@@ -201,24 +203,28 @@ inline int testKey(NSString *chars_pressed, NSString *chars_for_key)
NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
NSString *chars = [event characters];
- if(testKey(chars, [settings stringForKey:PREF_KEY_A ]))[my_ds liftA];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_B ]))[my_ds liftB];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_SELECT]))[my_ds liftSelect];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_START ]))[my_ds liftStart];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_RIGHT ]))[my_ds liftRight];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_LEFT ]))[my_ds liftLeft];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_UP ]))[my_ds liftUp];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_DOWN ]))[my_ds liftDown];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_R ]))[my_ds liftR];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_L ]))[my_ds liftL];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_X ]))[my_ds liftX];
- else if(testKey(chars, [settings stringForKey:PREF_KEY_Y ]))[my_ds liftY];
+ if(testKey(chars, [settings stringForKey:PREF_KEY_A ]))[dsController liftA];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_B ]))[dsController liftB];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_SELECT]))[dsController liftSelect];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_START ]))[dsController liftStart];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_RIGHT ]))[dsController liftRight];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_LEFT ]))[dsController liftLeft];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_UP ]))[dsController liftUp];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_DOWN ]))[dsController liftDown];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_R ]))[dsController liftR];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_L ]))[dsController liftL];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_X ]))[dsController liftX];
+ else if(testKey(chars, [settings stringForKey:PREF_KEY_Y ]))[dsController liftY];
}
- (void)mouseDown:(NSEvent*)event
{
NSPoint temp = [my_ds windowPointToDSCoords:[event locationInWindow]];
- if(temp.x >= 0 && temp.y>=0)[my_ds touch:temp];
+
+ if(temp.x >= 0 && temp.y>=0)
+ {
+ [dsController touch:temp];
+ }
}
- (void)mouseDragged:(NSEvent*)event
@@ -228,7 +234,7 @@ inline int testKey(NSString *chars_pressed, NSString *chars_for_key)
- (void)mouseUp:(NSEvent*)event
{
- [my_ds releaseTouch];
+ [dsController releaseTouch];
}
@end
diff --git a/desmume/src/cocoa/main.mm b/desmume/src/cocoa/main.mm
index f9a19f321..90475001b 100644
--- a/desmume/src/cocoa/main.mm
+++ b/desmume/src/cocoa/main.mm
@@ -56,10 +56,12 @@ extern NSMenuItem *topBG0_item;
extern NSMenuItem *topBG1_item;
extern NSMenuItem *topBG2_item;
extern NSMenuItem *topBG3_item;
+extern NSMenuItem *topOBJ_item;
extern NSMenuItem *subBG0_item;
extern NSMenuItem *subBG1_item;
extern NSMenuItem *subBG2_item;
extern NSMenuItem *subBG3_item;
+extern NSMenuItem *subOBJ_item;
extern NSMenuItem *screenshot_to_file_item;
extern NSMenuItem *screenshot_to_window_item;
@@ -235,7 +237,8 @@ void CreateMenu(AppDelegate *delegate)
[emulation_menu addItem:[NSMenuItem separatorItem]];
//Frake skip menu
-
+ // Disabling frame skipping for now since it doesn't yield any significant speed improvements. -rogerman 03/28/2011
+ /*
temp = [emulation_menu addItemWithTitle:NSLocalizedString(@"Frame Skip", nil) action:nil keyEquivalent:@""];
NSMenu *frame_skip_menu = [[NSMenu alloc] initWithTitle:NSLocalizedString(@"Frame Skip", nil)];
@@ -256,7 +259,7 @@ void CreateMenu(AppDelegate *delegate)
[frame_skip_menu release];
}
-
+ */
//Speed limit menu
temp = [emulation_menu addItemWithTitle:NSLocalizedString(@"Speed Limit", nil) action:nil keyEquivalent:@""];
@@ -366,6 +369,7 @@ void CreateMenu(AppDelegate *delegate)
topBG1_item = [layer_menu addItemWithTitle:NSLocalizedString(@"Top BG1", nil) action:@selector(toggleTopBackground1) keyEquivalent:@""];
topBG2_item = [layer_menu addItemWithTitle:NSLocalizedString(@"Top BG2", nil) action:@selector(toggleTopBackground2) keyEquivalent:@""];
topBG3_item = [layer_menu addItemWithTitle:NSLocalizedString(@"Top BG3", nil) action:@selector(toggleTopBackground3) keyEquivalent:@""];
+ topOBJ_item = [layer_menu addItemWithTitle:NSLocalizedString(@"Top OBJ", nil) action:@selector(toggleTopObject) keyEquivalent:@""];
[layer_menu addItem:[NSMenuItem separatorItem]];
@@ -373,6 +377,7 @@ void CreateMenu(AppDelegate *delegate)
subBG1_item = [layer_menu addItemWithTitle:NSLocalizedString(@"Sub BG1", nil) action:@selector(toggleSubBackground1) keyEquivalent:@""];
subBG2_item = [layer_menu addItemWithTitle:NSLocalizedString(@"Sub BG2", nil) action:@selector(toggleSubBackground2) keyEquivalent:@""];
subBG3_item = [layer_menu addItemWithTitle:NSLocalizedString(@"Sub BG3", nil) action:@selector(toggleSubBackground3) keyEquivalent:@""];
+ subOBJ_item = [layer_menu addItemWithTitle:NSLocalizedString(@"Sub OBJ", nil) action:@selector(toggleSubObject) keyEquivalent:@""];
[layer_menu release];
}
@@ -496,6 +501,7 @@ int main(int argc, char *argv[])
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
+ [panel setResolvesAliases:YES];
[panel setAllowsMultipleSelection:NO];
[panel setTitle:NSLocalizedString(@"Open ROM...", nil)];
@@ -545,12 +551,20 @@ int main(int argc, char *argv[])
- (void)application:(NSApplication*)sender openFiles:(NSArray*)filenames
{
//verify everything
- if(sender != NSApp)goto fail;
- if(!filenames)goto fail;
- if([filenames count] == 0)goto fail;
+ if(sender != NSApp ||
+ filenames == nil ||
+ [filenames count] == 0)
+ {
+ [sender replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
+ return;
+ }
+
NSString *filename = [filenames lastObject];
- if(!filename)goto fail;
- if([filename length] == 0)goto fail;
+ if(!filename || [filename length] == 0)
+ {
+ [sender replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
+ return;
+ }
if([main_window loadROM:filename])
{
@@ -558,9 +572,6 @@ int main(int argc, char *argv[])
[sender replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
return;
}
-
-fail:
- [sender replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
}
- (void)applicationWillFinishLaunching:(NSNotification*)notification
diff --git a/desmume/src/cocoa/main_window.h b/desmume/src/cocoa/main_window.h
index 10b453e7d..3f37ca70c 100644
--- a/desmume/src/cocoa/main_window.h
+++ b/desmume/src/cocoa/main_window.h
@@ -44,6 +44,8 @@
bool no_smaller_than_ds;
bool keep_proportions;
+
+ NSString *pathLoadedRom;
}
//initialization
@@ -102,10 +104,12 @@
- (void)toggleTopBackground1;
- (void)toggleTopBackground2;
- (void)toggleTopBackground3;
+- (void)toggleTopObject;
- (void)toggleSubBackground0;
- (void)toggleSubBackground1;
- (void)toggleSubBackground2;
- (void)toggleSubBackground3;
+- (void)toggleSubObject;
//screenshots
- (void)saveScreenshot;
@@ -113,4 +117,7 @@
//delegate
- (void)windowDidBecomeMain:(NSNotification*)notification;
+- (BOOL)saveStateExistsInSlot:(int)slot;
+- (NSString*) getSaveSlotFileName:(unsigned int)slotNumber;
+
@end
diff --git a/desmume/src/cocoa/main_window.mm b/desmume/src/cocoa/main_window.mm
index 69d35e1b2..11313e681 100644
--- a/desmume/src/cocoa/main_window.mm
+++ b/desmume/src/cocoa/main_window.mm
@@ -88,10 +88,12 @@ NSMenuItem *topBG0_item = nil;
NSMenuItem *topBG1_item = nil;
NSMenuItem *topBG2_item = nil;
NSMenuItem *topBG3_item = nil;
+NSMenuItem *topOBJ_item = nil;
NSMenuItem *subBG0_item = nil;
NSMenuItem *subBG1_item = nil;
NSMenuItem *subBG2_item = nil;
NSMenuItem *subBG3_item = nil;
+NSMenuItem *subOBJ_item = nil;
NSMenuItem *screenshot_to_file_item = nil;
@implementation VideoOutputWindow
@@ -232,6 +234,8 @@ NSMenuItem *screenshot_to_file_item = nil;
NSResponder *temp = [window nextResponder];
[window setNextResponder:input];
[input setNextResponder:temp];
+
+ pathLoadedRom = nil;
return self;
}
@@ -244,6 +248,7 @@ NSMenuItem *screenshot_to_file_item = nil;
[status_view release];
[status_bar_text release];
[input release];
+ [pathLoadedRom release];
[super dealloc];
}
@@ -275,6 +280,9 @@ NSMenuItem *screenshot_to_file_item = nil;
//update the rom info window, if needed
[ROMInfo changeDS:self];
+
+ pathLoadedRom = filename;
+ [pathLoadedRom retain];
}
//reset menu items
@@ -283,7 +291,7 @@ NSMenuItem *screenshot_to_file_item = nil;
int i;
for(i = 0; i < MAX_SLOTS; i++)
if([saveSlot_item[i] target] == self)
- if([self saveStateExists:i] == YES)
+ if([self saveStateExistsInSlot:i] == YES)
[saveSlot_item[i] setState:NSOnState];
else
[saveSlot_item[i] setState:NSOffState];
@@ -301,12 +309,12 @@ NSMenuItem *screenshot_to_file_item = nil;
- (void)execute
{
[super execute];
-
+
if([pause_item target] == self)
[pause_item setState:NSOffState];
if([execute_item target] == self)
[execute_item setState:NSOnState];
-
+
[self setStatusText:NSLocalizedString(@"Emulation Executing", nil)];
}
@@ -343,7 +351,7 @@ NSMenuItem *screenshot_to_file_item = nil;
- (void)setFrameSkip:(int)frameskip
{
[super setFrameSkip:frameskip];
- frameskip = [super frameSkip];
+ frameskip = dsStateBuffer->frame_skip;
if([frame_skip_auto_item target] == self)
if(frameskip < 0)
@@ -385,7 +393,8 @@ NSMenuItem *screenshot_to_file_item = nil;
[super setSpeedLimit:speedLimit];
//Set the correct menu states
- speedLimit = [super speedLimit];
+ speedLimit = dsStateBuffer->speed_limit;
+
int standard_size = 0;
if([speed_limit_25_item target] == self)
@@ -511,23 +520,65 @@ NSMenuItem *screenshot_to_file_item = nil;
- (BOOL)saveStateToSlot:(int)slot
{
- if([super saveStateToSlot:slot] == YES)
+ BOOL result = NO;
+ int i = slot;
+
+ NSString *savePath = GetPathUserAppSupport(@"States");
+ if (savePath == nil)
{
- if([saveSlot_item[slot] target] == self);
- [saveSlot_item[slot] setState:NSOnState];
+ // Throw an error message here...
+ return result;
+ }
+
+ result = CreateAppDirectory(@"States");
+ if (result == NO)
+ {
+ // Should throw an error message here...
+ return result;
+ }
+
+ NSString *fileName = [self getSaveSlotFileName:slot];
+ if (fileName == nil)
+ {
+ return result;
+ }
+
+ NSString *fullFilePath = [[savePath stringByAppendingString:@"/"] stringByAppendingString:fileName];
+ result = [self saveState:fullFilePath];
+ if(result)
+ {
+ if([saveSlot_item[i] target] == self);
+ {
+ [saveSlot_item[i] setState:NSOnState];
+ }
- //if([clear_all_saves_item target] == self);
- //[clear_all_saves_item setEnabled:YES];
-
- return YES;
+ result = YES;
}
- return NO;
+ return result;
}
- (BOOL)loadStateFromSlot:(int)slot
{
- return [super loadStateFromSlot:slot];
+ BOOL result = NO;
+
+ NSString *savePath = GetPathUserAppSupport(@"States");
+ if (savePath == nil)
+ {
+ // Should throw an error message here...
+ return result;
+ }
+
+ NSString *fileName = [self getSaveSlotFileName:slot];
+ if (fileName == nil)
+ {
+ return result;
+ }
+
+ NSString *fullFilePath = [[savePath stringByAppendingString:@"/"] stringByAppendingString:fileName];
+ result = [self loadState:fullFilePath];
+
+ return result;
}
- (BOOL)saveStateAs
@@ -666,60 +717,103 @@ NSMenuItem *screenshot_to_file_item = nil;
- (NSPoint)windowPointToDSCoords:(NSPoint)location
{
- if(video_output_view == nil)return NSMakePoint(-1, -1);
-
- NSSize temp = [[window contentView] frame].size;
+ CGFloat rotation;
+ NSSize temp;
+ float statusBarHeight;
+
+ if(video_output_view == nil)
+ {
+ return NSMakePoint(-1, -1);
+ }
+
+ rotation = [video_output_view boundsRotation];
+ statusBarHeight = [self statusBarHeight];
+
+ temp = [[window contentView] frame].size;
CGFloat x_size = temp.width - WINDOW_BORDER_PADDING*2;
- CGFloat y_size = temp.height - [self statusBarHeight];
+ CGFloat y_size = temp.height - statusBarHeight;
//If the click was to the left or under the opengl view, exit
- if((location.x < WINDOW_BORDER_PADDING) || (location.y < [self statusBarHeight]))
+ if((location.x < WINDOW_BORDER_PADDING) || (location.y < statusBarHeight))
+ {
return NSMakePoint(-1, -1);
+ }
location.x -= WINDOW_BORDER_PADDING;
- location.y -= [self statusBarHeight];
+ location.y -= statusBarHeight;
//If the click was top or right of the view...
- if(location.x >= x_size)return NSMakePoint(-1, -1);
- if(location.y >= y_size)return NSMakePoint(-1, -1);
-
- if([video_output_view boundsRotation] == 0 || [video_output_view boundsRotation] == -180)
+ if(location.x >= x_size)
{
- if([video_output_view boundsRotation] == -180)
+ return NSMakePoint(-1, -1);
+ }
+ if(location.y >= y_size)
+ {
+ return NSMakePoint(-1, -1);
+ }
+
+ if(rotation == 0)
+ {
+ if(location.y >= y_size / 2)
{
- if(location.y < y_size / 2)return NSMakePoint(-1, -1);
- location.x = x_size - location.x;
- location.y = y_size - location.y;
- } else
- if(location.y >= y_size / 2)return NSMakePoint(-1, -1);
-
+ return NSMakePoint(-1, -1);
+ }
+
//scale the coordinates
location.x *= ((float)DS_SCREEN_WIDTH) / ((float)x_size);
location.y *= ((float)DS_SCREEN_HEIGHT_COMBINED) / ((float)y_size);
-
+
//invert the y
location.y = DS_SCREEN_HEIGHT - location.y - 1;
-
- } else
+ }
+ else if(rotation = -90)
{
-
- if([video_output_view boundsRotation] == -270)
+ if(location.x >= x_size / 2)
{
- if(location.x < x_size / 2)return NSMakePoint(-1, -1);
- location.x = x_size - location.x;
-
- } else
- {
- if(location.x >= x_size / 2)return NSMakePoint(-1, -1);
- location.y = y_size - location.y;
+ return NSMakePoint(-1, -1);
}
-
+ location.y = y_size - location.y;
+
location.x *= ((float)DS_SCREEN_HEIGHT_COMBINED) / ((float)x_size);
location.y *= ((float)DS_SCREEN_WIDTH) / ((float)y_size);
-
+
//invert the y
location.x = DS_SCREEN_HEIGHT - location.x - 1;
-
+
+ float temp = location.x;
+ location.x = location.y;
+ location.y = temp;
+ }
+ else if(rotation = -180)
+ {
+ if(location.y < y_size / 2)
+ {
+ return NSMakePoint(-1, -1);
+ }
+ location.x = x_size - location.x;
+ location.y = y_size - location.y;
+
+ //scale the coordinates
+ location.x *= ((float)DS_SCREEN_WIDTH) / ((float)x_size);
+ location.y *= ((float)DS_SCREEN_HEIGHT_COMBINED) / ((float)y_size);
+
+ //invert the y
+ location.y = DS_SCREEN_HEIGHT - location.y - 1;
+ }
+ else if(rotation = -270)
+ {
+ if(location.x < x_size / 2)
+ {
+ return NSMakePoint(-1, -1);
+ }
+ location.x = x_size - location.x;
+
+ location.x *= ((float)DS_SCREEN_HEIGHT_COMBINED) / ((float)x_size);
+ location.y *= ((float)DS_SCREEN_WIDTH) / ((float)y_size);
+
+ //invert the y
+ location.x = DS_SCREEN_HEIGHT - location.x - 1;
+
float temp = location.x;
location.x = location.y;
location.y = temp;
@@ -874,10 +968,10 @@ NSMenuItem *screenshot_to_file_item = nil;
- (void)toggleTopBackground0
{
- [super toggleTopBackground0];
+ [self toggleSubScreenLayer:0];
if([topBG0_item target] == self)
- if([super showingTopBackground0] == NO)
+ if([self isSubScreenLayerDisplayed:0] == NO)
[topBG0_item setState:NSOffState];
else
[topBG0_item setState:NSOnState];
@@ -885,10 +979,10 @@ NSMenuItem *screenshot_to_file_item = nil;
- (void)toggleTopBackground1
{
- [super toggleTopBackground1];
+ [self toggleSubScreenLayer:1];
if([topBG1_item target] == self)
- if([super showingTopBackground1] == NO)
+ if([self isSubScreenLayerDisplayed:1] == NO)
[topBG1_item setState:NSOffState];
else
[topBG1_item setState:NSOnState];
@@ -896,10 +990,10 @@ NSMenuItem *screenshot_to_file_item = nil;
- (void)toggleTopBackground2
{
- [super toggleTopBackground2];
+ [self toggleSubScreenLayer:2];
if([topBG2_item target] == self)
- if([super showingTopBackground2] == NO)
+ if([self isSubScreenLayerDisplayed:2] == NO)
[topBG2_item setState:NSOffState];
else
[topBG2_item setState:NSOnState];
@@ -907,21 +1001,32 @@ NSMenuItem *screenshot_to_file_item = nil;
- (void)toggleTopBackground3
{
- [super toggleTopBackground3];
+ [self toggleSubScreenLayer:3];
if([topBG3_item target] == self)
- if([super showingTopBackground3] == NO)
+ if([self isSubScreenLayerDisplayed:3] == NO)
[topBG3_item setState:NSOffState];
else
[topBG3_item setState:NSOnState];
}
+- (void)toggleTopObject
+{
+ [self toggleSubScreenLayer:4];
+
+ if([topOBJ_item target] == self)
+ if([self isSubScreenLayerDisplayed:4] == NO)
+ [topOBJ_item setState:NSOffState];
+ else
+ [topOBJ_item setState:NSOnState];
+}
+
- (void)toggleSubBackground0
{
- [super toggleSubBackground0];
+ [self toggleMainScreenLayer:0];
if([subBG0_item target] == self)
- if([super showingSubBackground0] == NO)
+ if([self isMainScreenLayerDisplayed:0] == NO)
[subBG0_item setState:NSOffState];
else
[subBG0_item setState:NSOnState];
@@ -929,10 +1034,10 @@ NSMenuItem *screenshot_to_file_item = nil;
- (void)toggleSubBackground1
{
- [super toggleSubBackground1];
+ [self toggleMainScreenLayer:1];
if([subBG1_item target] == self)
- if([super showingSubBackground1] == NO)
+ if([self isMainScreenLayerDisplayed:1] == NO)
[subBG1_item setState:NSOffState];
else
[subBG1_item setState:NSOnState];
@@ -940,10 +1045,10 @@ NSMenuItem *screenshot_to_file_item = nil;
- (void)toggleSubBackground2
{
- [super toggleSubBackground2];
+ [self toggleMainScreenLayer:2];
if([subBG2_item target] == self)
- if([super showingSubBackground2] == NO)
+ if([self isMainScreenLayerDisplayed:2] == NO)
[subBG2_item setState:NSOffState];
else
[subBG2_item setState:NSOnState];
@@ -951,15 +1056,26 @@ NSMenuItem *screenshot_to_file_item = nil;
- (void)toggleSubBackground3
{
- [super toggleSubBackground3];
+ [self toggleMainScreenLayer:3];
if([subBG3_item target] == self)
- if([super showingSubBackground3] == NO)
+ if([self isMainScreenLayerDisplayed:3] == NO)
[subBG3_item setState:NSOffState];
else
[subBG3_item setState:NSOnState];
}
+- (void)toggleSubObject
+{
+ [self toggleMainScreenLayer:4];
+
+ if([subOBJ_item target] == self)
+ if([self isMainScreenLayerDisplayed:4] == NO)
+ [subOBJ_item setState:NSOffState];
+ else
+ [subOBJ_item setState:NSOnState];
+}
+
- (void)saveScreenshot
{//todo: this should work even if video_output_view doesn't exist
BOOL executing = [self executing];
@@ -1145,7 +1261,7 @@ NSMenuItem *screenshot_to_file_item = nil;
[saveSlot_item[i] setTarget:self];
[loadSlot_item[i] setTarget:self];
- if([self saveStateExists:i] == YES)
+ if([self saveStateExistsInSlot:i] == YES)
{
[saveSlot_item[i] setState:NSOnState];
} else
@@ -1211,10 +1327,12 @@ NSMenuItem *screenshot_to_file_item = nil;
[topBG1_item setTarget:self];
[topBG2_item setTarget:self];
[topBG3_item setTarget:self];
+ [topOBJ_item setTarget:self];
[subBG0_item setTarget:self];
[subBG1_item setTarget:self];
[subBG2_item setTarget:self];
[subBG3_item setTarget:self];
+ [subOBJ_item setTarget:self];
[screenshot_to_file_item setTarget:self];
//set checks for view window based on the options of this window
@@ -1222,38 +1340,56 @@ NSMenuItem *screenshot_to_file_item = nil;
[constrain_item setState:keep_proportions?NSOnState:NSOffState];
[min_size_item setState:no_smaller_than_ds?NSOnState:NSOffState];
[toggle_status_bar_item setState:(status_view!=nil)?NSOnState:NSOffState];
- if([self showingTopBackground0])
+
+ if([self isSubScreenLayerDisplayed:0] == YES)
[topBG0_item setState:NSOnState];
else
[topBG0_item setState:NSOffState];
- if([self showingTopBackground1])
+
+ if([self isSubScreenLayerDisplayed:1] == YES)
[topBG1_item setState:NSOnState];
else
[topBG1_item setState:NSOffState];
- if([self showingTopBackground2])
+
+ if([self isSubScreenLayerDisplayed:2] == YES)
[topBG2_item setState:NSOnState];
else
[topBG2_item setState:NSOffState];
- if([self showingTopBackground3])
+
+ if([self isSubScreenLayerDisplayed:3] == YES)
[topBG3_item setState:NSOnState];
else
[topBG3_item setState:NSOffState];
- if([self showingSubBackground0])
+
+ if([self isSubScreenLayerDisplayed:4] == YES)
+ [topOBJ_item setState:NSOnState];
+ else
+ [topOBJ_item setState:NSOffState];
+
+ if([self isMainScreenLayerDisplayed:0] == YES)
[subBG0_item setState:NSOnState];
else
[subBG0_item setState:NSOffState];
- if([self showingSubBackground1])
+
+ if([self isMainScreenLayerDisplayed:1] == YES)
[subBG1_item setState:NSOnState];
else
[subBG1_item setState:NSOffState];
- if([self showingSubBackground2])
+
+ if([self isMainScreenLayerDisplayed:2] == YES)
[subBG2_item setState:NSOnState];
else
[subBG2_item setState:NSOffState];
- if([self showingSubBackground3])
+
+ if([self isMainScreenLayerDisplayed:3] == YES)
[subBG3_item setState:NSOnState];
else
[subBG3_item setState:NSOffState];
+
+ if([self isMainScreenLayerDisplayed:4] == YES)
+ [subOBJ_item setState:NSOnState];
+ else
+ [subOBJ_item setState:NSOffState];
[self setRotation:[self rotation]];
@@ -1315,7 +1451,7 @@ NSMenuItem *screenshot_to_file_item = nil;
else
for(i = 0; i < MAX_SLOTS; i++)
if(item == loadSlot_item[i])
- if([self saveStateExists:i]==NO)return NO;
+ if([self saveStateExistsInSlot:i] == NO)return NO;
if(video_output_view == nil)
{
@@ -1340,4 +1476,33 @@ NSMenuItem *screenshot_to_file_item = nil;
return YES;
}
+- (BOOL)saveStateExistsInSlot:(int)slot
+{
+ BOOL exists = false;
+
+ NSString *searchPath = GetPathUserAppSupport(@"States");
+ NSString *searchFileName = [self getSaveSlotFileName:slot];
+
+ if (searchPath == nil || searchFileName == nil)
+ {
+ return exists;
+ }
+
+ NSFileManager *fileManager = [[NSFileManager alloc] init];
+ NSString *searchFullPath = [[searchPath stringByAppendingString:@"/"] stringByAppendingString:searchFileName];
+
+ exists = [fileManager isReadableFileAtPath:searchFullPath];
+
+ [fileManager release];
+
+ return exists;
+}
+
+- (NSString*) getSaveSlotFileName:(unsigned int)slotNumber
+{
+ NSString *fileExtension = [NSString stringWithFormat:@".ds%d", slotNumber];
+
+ return [[[pathLoadedRom lastPathComponent] stringByDeletingPathExtension] stringByAppendingString:fileExtension];
+}
+
@end
diff --git a/desmume/src/cocoa/nds_control.h b/desmume/src/cocoa/nds_control.h
index 59eab8ec5..7ef4d89d4 100644
--- a/desmume/src/cocoa/nds_control.h
+++ b/desmume/src/cocoa/nds_control.h
@@ -18,6 +18,7 @@
*/
#import "globals.h"
+#import "cocoa_input.h"
@class ScreenState;
@@ -29,6 +30,17 @@
#define MAX_SLOTS 10
#define MAX_FRAME_SKIP 10
+@interface CocoaDSStateBuffer : NSObject
+{
+ @public
+ int frame_skip;
+ int speed_limit;
+}
+
+- (id) init;
+
+@end
+
//This class is a compelte objective-c wrapper for
//the core emulation features, other objective-c code inherit
//upon or instanciate this to add interfaces for these features
@@ -65,6 +77,11 @@
NSString *current_file;
NSString *flash_file;
+
+ bool doesConfigNeedUpdate;
+ NSTimeInterval calcTimeBudget;
+
+ CocoaDSController *dsController;
#ifdef GDB_STUB
NSInteger arm9_gdb_port;
@@ -74,6 +91,9 @@
#endif
unsigned char gpu_buff[256 * 256 * 5]; //this is where the 3D rendering of the NDS is stored
+
+ @public
+ CocoaDSStateBuffer *dsStateBuffer;
}
//Instanciating, setup, and deconstruction
@@ -82,6 +102,9 @@
- (void)setErrorCallback:(SEL)callback withObject:(id)object;
- (void)dealloc;
+// Data accessors
+- (CocoaDSController*) getDSController;
+
//Firmware control
- (void)setPlayerName:(NSString*)player_name;
@@ -116,73 +139,19 @@
- (int)speedLimit;
- (void)setSaveType:(int)savetype; // see save_types in src/mmu.h
- (int)saveType; // default is 0, which is autodetect
-
-//touch screen
-- (void)touch:(NSPoint)point;
-- (void)releaseTouch;
-
-//button input
-- (void)pressStart;
-- (void)liftStart;
-- (BOOL)start;
-- (void)pressSelect;
-- (void)liftSelect;
-- (BOOL)select;
-- (void)pressLeft;
-- (void)liftLeft;
-- (BOOL)left;
-- (void)pressRight;
-- (void)liftRight;
-- (BOOL)right;
-- (void)pressUp;
-- (void)liftUp;
-- (BOOL)up;
-- (void)pressDown;
-- (void)liftDown;
-- (BOOL)down;
-- (void)pressA;
-- (void)liftA;
-- (BOOL)A;
-- (void)pressB;
-- (void)liftB;
-- (BOOL)B;
-- (void)pressX;
-- (void)liftX;
-- (BOOL)X;
-- (void)pressY;
-- (void)liftY;
-- (BOOL)Y;
-- (void)pressL;
-- (void)liftL;
-- (BOOL)L;
-- (void)pressR;
-- (void)liftR;
-- (BOOL)R;
+- (void) updateConfig;
+- (void) emulateDS;
+- (void) drawFrame;
+- (void) padTime:(NSTimeInterval)timePad;
//save states
- (BOOL)saveState:(NSString*)file;
- (BOOL)loadState:(NSString*)file;
-- (BOOL)saveStateToSlot:(int)slot; //0 to MAX_SLOTS-1, anything else is ignored
-- (BOOL)loadStateFromSlot:(int)slot;
-- (BOOL)saveStateExists:(int)slot;
-//layers
-- (void)toggleTopBackground0;
-- (BOOL)showingTopBackground0;
-- (void)toggleTopBackground1;
-- (BOOL)showingTopBackground1;
-- (void)toggleTopBackground2;
-- (BOOL)showingTopBackground2;
-- (void)toggleTopBackground3;
-- (BOOL)showingTopBackground3;
-- (void)toggleSubBackground0;
-- (BOOL)showingSubBackground0;
-- (void)toggleSubBackground1;
-- (BOOL)showingSubBackground1;
-- (void)toggleSubBackground2;
-- (BOOL)showingSubBackground2;
-- (void)toggleSubBackground3;
-- (BOOL)showingSubBackground3;
+- (BOOL) isSubScreenLayerDisplayed:(int)i;
+- (BOOL) isMainScreenLayerDisplayed:(int)i;
+- (void) toggleMainScreenLayer:(int)i;
+- (void) toggleSubScreenLayer:(int)i;
//Sound
- (BOOL)hasSound;
diff --git a/desmume/src/cocoa/nds_control.mm b/desmume/src/cocoa/nds_control.mm
index 8e848d405..bf7728718 100644
--- a/desmume/src/cocoa/nds_control.mm
+++ b/desmume/src/cocoa/nds_control.mm
@@ -20,6 +20,7 @@
#import "nds_control.h"
#import "preferences.h"
#import "screen_state.h"
+#import "main_window.h"
#ifdef DESMUME_COCOA
#import "sndOSX.h"
@@ -31,7 +32,6 @@
#endif
//DeSmuME general includes
-#define OBJ_C
#include "../NDSSystem.h"
#include "../saves.h"
#include "../render3D.h"
@@ -50,7 +50,7 @@ bool timer_based;
#define DS_MICROSECONDS_PER_FRAME (1.0 / 59.8) * 1000000.0
//accessed from other files
-volatile desmume_BOOL execute = true;
+volatile bool execute = true;
GPU3DInterface *core3DList[] = {
&gpu3DNull,
@@ -61,6 +61,13 @@ GPU3DInterface *core3DList[] = {
NULL
};
+enum
+{
+ CORE3DLIST_NULL = 0,
+ CORE3DLIST_RASTERIZE,
+ CORE3DLIST_OPENGL
+};
+
SoundInterface_struct *SNDCoreList[] = {
&SNDDummy,
#ifdef DESMUME_COCOA
@@ -69,15 +76,27 @@ SoundInterface_struct *SNDCoreList[] = {
NULL
};
-struct NDS_fw_config_data firmware;
+struct NDS_fw_config_data macDS_firmware;
bool opengl_init()
{
return true;
}
+@implementation CocoaDSStateBuffer
+
+- (id) init
+{
+ frame_skip = -1; //default to auto frame skip
+ speed_limit = 100; //default to max speed = normal speed
+
+ return self;
+}
+
+@end
+
@implementation NintendoDS
-- (id)init;
+- (id)init
{
//
self = [super init];
@@ -87,6 +106,7 @@ bool opengl_init()
error_object = nil;
frame_skip = -1; //default to auto frame skip
speed_limit = 100; //default to max speed = normal speed
+ calcTimeBudget = (NSTimeInterval)(DS_SECONDS_PER_FRAME / ((float)speed_limit / 100.0));
gui_thread = [NSThread currentThread];
current_file = nil;
flash_file = nil;
@@ -161,8 +181,8 @@ bool opengl_init()
#endif
//use default firmware
- NDS_FillDefaultFirmwareConfigData(&firmware);
- NDS_CreateDummyFirmware(&firmware);
+ NDS_FillDefaultFirmwareConfigData(&macDS_firmware);
+ NDS_CreateDummyFirmware(&macDS_firmware);
/*
* Activate the GDB stubs
@@ -256,7 +276,7 @@ bool opengl_init()
[context makeCurrentContext];
oglrender_init = &opengl_init;
- NDS_3D_SetDriver(1);
+ NDS_3D_SetDriver(CORE3DLIST_RASTERIZE);
if(!gpu3D->NDS_3D_Init())
messageDialog(NSLocalizedString(@"Error", nil), @"Unable to initialize OpenGL components");
}
@@ -290,8 +310,11 @@ bool opengl_init()
if(timer_based)
{
video_update_lock = [[NSLock alloc] init];
- [NSTimer scheduledTimerWithTimeInterval:1.0f/60.0f target:self selector:@selector(videoUpdateTimerHelper) userInfo:nil repeats:YES];
+ [NSTimer scheduledTimerWithTimeInterval:DS_SECONDS_PER_FRAME target:self selector:@selector(videoUpdateTimerHelper) userInfo:nil repeats:YES];
}
+
+ dsStateBuffer = [[CocoaDSStateBuffer alloc] init];
+ dsController = [[CocoaDSController alloc] init];
return self;
}
@@ -324,7 +347,10 @@ bool opengl_init()
//end the other thread
finish = true;
while(!finished){}
-
+
+ [dsStateBuffer release];
+ [dsController release];
+
[display_object release];
[error_object release];
[context release];
@@ -350,18 +376,23 @@ bool opengl_init()
[super dealloc];
}
+- (CocoaDSController*) getDSController
+{
+ return dsController;
+}
+
- (void)setPlayerName:(NSString*)player_name
{
//first we convert to UTF-16 which the DS uses to store the nickname
NSData *string_chars = [player_name dataUsingEncoding:NSUnicodeStringEncoding];
//copy the bytes
- firmware.nickname_len = MIN([string_chars length],MAX_FW_NICKNAME_LENGTH);
- [string_chars getBytes:firmware.nickname length:firmware.nickname_len];
- firmware.nickname[firmware.nickname_len / 2] = 0;
+ macDS_firmware.nickname_len = MIN([string_chars length],MAX_FW_NICKNAME_LENGTH);
+ [string_chars getBytes:macDS_firmware.nickname length:macDS_firmware.nickname_len];
+ macDS_firmware.nickname[macDS_firmware.nickname_len / 2] = 0;
//set the firmware
- //NDS_CreateDummyFirmware(&firmware);
+ //NDS_CreateDummyFirmware(&macDS_firmware);
}
- (BOOL)loadROM:(NSString*)filename
@@ -604,8 +635,14 @@ bool opengl_init()
- (void)setFrameSkip:(int)frameskip
{
- if(frameskip < 0)frame_skip = -1;
- else frame_skip = frameskip;
+ dsStateBuffer->frame_skip = frameskip;
+
+ if(frameskip < 0)
+ {
+ dsStateBuffer->frame_skip = -1;
+ }
+
+ doesConfigNeedUpdate = true;
}
- (int)frameSkip
@@ -615,10 +652,14 @@ bool opengl_init()
- (void)setSpeedLimit:(int)speedLimit
{
- if(speedLimit < 0)return;
- if(speedLimit > 1000)return;
+ if(speedLimit < 0 || speedLimit > 1000)
+ {
+ return;
+ }
- speed_limit = speedLimit;
+ dsStateBuffer->speed_limit = speedLimit;
+
+ doesConfigNeedUpdate = true;
}
- (int)speedLimit
@@ -639,602 +680,152 @@ bool opengl_init()
return CommonSettings.manualBackupType;
}
-
-- (void)touch:(NSPoint)point
-{
- NDS_setTouchPos((unsigned short)point.x, (unsigned short)point.y);
-}
-
-- (void)releaseTouch
-{
- NDS_releaseTouch();
-}
-
-- (void)pressStart
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFFF7;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFFF7;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xF7FF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xF7FF;
-#endif
-}
-
-- (void)liftStart
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0008;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0008;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0800;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0800;
-#endif
-}
-
-- (BOOL)start
-{
-#ifndef __BIG_ENDIAN__
- if((((u16 *)MMU.ARM7_REG)[0x130>>1] & 0x0008) == 0)
-#else
- if((((u16 *)MMU.ARM7_REG)[0x130>>1] & 0x0800) == 0)
-#endif
- return YES;
- return NO;
-}
-
-- (void)pressSelect
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFFFB;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFFFB;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFBFF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFBFF;
-#endif
-}
-
-- (void)liftSelect
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0004;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0004;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0400;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0400;
-#endif
-}
-
-- (BOOL)select
-{
-#ifndef __BIG_ENDIAN__
- if((((u16 *)MMU.ARM7_REG)[0x130>>1] & 0x0004) == 0)
-#else
- if((((u16 *)MMU.ARM7_REG)[0x130>>1] & 0x0400) == 0)
-#endif
- return YES;
- return NO;
-}
-
-- (void)pressLeft
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFFDF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFFDF;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xDFFF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xDFFF;
-#endif
-}
-
-- (void)liftLeft
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0020;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0020;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x2000;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x2000;
-#endif
-}
-
-- (BOOL)left
-{
-#ifndef __BIG_ENDIAN__
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x0020) == 0)
-#else
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x2000) == 0)
-#endif
- return YES;
- return NO;
-}
-
-- (void)pressRight
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFFEF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFFEF;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xEFFF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xEFFF;
-#endif
-}
-
-- (void)liftRight
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0010;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0010;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x1000;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x1000;
-#endif
-}
-
-- (BOOL)right
-{
-#ifndef __BIG_ENDIAN__
- if((((u16*)ARM9Mem.ARM9_REG)[0x130>>1] & 0x0010) == 0)
-#else
- if((((u16*)ARM9Mem.ARM9_REG)[0x130>>1] & 0x1000) == 0)
-#endif
- return YES;
- return NO;
-}
-
-- (void)pressUp
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFFBF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFFBF;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xBFFF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xBFFF;
-#endif
-}
-
-- (void)liftUp
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0040;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0040;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x4000;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x4000;
-#endif
-}
-
-- (BOOL)up
-{
-#ifndef __BIG_ENDIAN__
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x0040) == 0)
-#else
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x4000) == 0)
-#endif
- return YES;
- return NO;
-}
-
-- (void)pressDown
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFF7F;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFF7F;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0x7FFF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0x7FFF;
-#endif
-}
-
-- (void)liftDown
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0080;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0080;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x8000;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x8000;
-#endif
-}
-
-- (BOOL)down
-{
-#ifndef __BIG_ENDIAN__
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x0080) == 0)
-#else
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x8000) == 0)
-#endif
- return YES;
- return NO;
-}
-
-- (void)pressA
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFFFE;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFFFE;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFEFF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFEFF;
-#endif
-}
-
-- (void)liftA
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0001;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0001;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0100;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0100;
-#endif
-}
-
-- (BOOL)A
-{
-#ifndef __BIG_ENDIAN__
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x0001) == 0)
-#else
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x0100) == 0)
-#endif
- return YES;
- return NO;
-}
-
-- (void)pressB
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFFFD;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFFFD;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFDFF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFDFF;
-#endif
-}
-
-- (void)liftB
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0002;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0002;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0200;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0200;
-#endif
-}
-
-- (BOOL)B
-{
-#ifndef __BIG_ENDIAN__
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x0002) == 0)
-#else
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x0200) == 0)
-#endif
- return YES;
- return NO;
-}
-
-- (void)pressX
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)MMU.ARM7_REG)[0x136>>1] &= 0xFFFE;
-#else
- ((u16 *)MMU.ARM7_REG)[0x136>>1] &= 0xFEFF;
-#endif
-}
-
-- (void)liftX
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)MMU.ARM7_REG)[0x136>>1] |= 0x0001;
-#else
- ((u16 *)MMU.ARM7_REG)[0x136>>1] |= 0x0100;
-#endif
-}
-
-- (BOOL)X
-{
-#ifndef __BIG_ENDIAN__
- if((((u16 *)MMU.ARM7_REG)[0x136>>1] & 0x0001) == 0)
- if((((u16 *)MMU.ARM7_REG)[0x136>>1] & 0x0001) == 0)
-#else
- if((((u16 *)MMU.ARM7_REG)[0x136>>1] & 0x0100) == 0)
- if((((u16 *)MMU.ARM7_REG)[0x136>>1] & 0x0100) == 0)
-#endif
- return YES;
- return NO;
-}
-
-- (void)pressY
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)MMU.ARM7_REG)[0x136>>1] &= 0xFFFD;
-#else
- ((u16 *)MMU.ARM7_REG)[0x136>>1] &= 0xFDFF;
-#endif
-}
-
-- (void)liftY
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)MMU.ARM7_REG)[0x136>>1] |= 0x0002;
-#else
- ((u16 *)MMU.ARM7_REG)[0x136>>1] |= 0x0200;
-#endif
-}
-
-- (BOOL)Y
-{
-#ifndef __BIG_ENDIAN__
- if((((u16 *)MMU.ARM7_REG)[0x136>>1] & 0x0002) == 0)
- if((((u16 *)MMU.ARM7_REG)[0x136>>1] & 0x0002) == 0)
-#else
- if((((u16 *)MMU.ARM7_REG)[0x136>>1] & 0x0200) == 0)
- if((((u16 *)MMU.ARM7_REG)[0x136>>1] & 0x0200) == 0)
-#endif
- return YES;
- return NO;
-}
-
-- (void)pressL
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFDFF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFDFF;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFFFD;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFFFD;
-#endif
-}
-
-- (void)liftL
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0200;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0200;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0002;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0002;
-#endif
-}
-
-- (BOOL)L
-{
-#ifndef __BIG_ENDIAN__
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x0200) == 0)
-#else
- if((((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] & 0x0002) == 0)
-#endif
- return YES;
- return NO;
-}
-
-- (void)pressR
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFEFF;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFEFF;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] &= 0xFFFE;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] &= 0xFFFE;
-#endif
-}
-
-- (void)liftR
-{
-#ifndef __BIG_ENDIAN__
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0100;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0100;
-#else
- ((u16 *)ARM9Mem.ARM9_REG)[0x130>>1] |= 0x0001;
- ((u16 *)MMU.ARM7_REG)[0x130>>1] |= 0x0001;
-#endif
-}
-
-- (BOOL)R
-{
-#ifndef __BIG_ENDIAN__
- if((((u16 *)MMU.ARM7_REG)[0x130>>1] & 0x0100) == 0)
-#else
- if((((u16 *)MMU.ARM7_REG)[0x130>>1] & 0x0001) == 0)
-#endif
- return YES;
- return NO;
-}
-
- (BOOL)saveState:(NSString*)file
{
[execution_lock lock];
-
+
BOOL result = NO;
if(savestate_save([file cStringUsingEncoding:NSUTF8StringEncoding]))
result = YES;
-
+
[execution_lock unlock];
-
+
return result;
}
- (BOOL)loadState:(NSString*)file
{
[execution_lock lock];
-
+
//Set the GPU context (if it exists) incase the core needs to load anything into opengl during state load
NSOpenGLContext *prev_context = [NSOpenGLContext currentContext];
[prev_context retain];
[context makeCurrentContext];
-
+
BOOL result = NO;
if(savestate_load([file cStringUsingEncoding:NSUTF8StringEncoding]))
result = YES;
-
+
[execution_lock unlock];
-
+
if(prev_context != nil)
{
[prev_context makeCurrentContext];
[prev_context release];
} else
[NSOpenGLContext clearCurrentContext];
-
+
return result;
}
-- (BOOL)saveStateToSlot:(int)slot
+- (BOOL) isSubScreenLayerDisplayed:(int)i
{
- if(slot >= MAX_SLOTS)return NO;
- if(slot < 0)return NO;
-
- [execution_lock lock];
-
- BOOL result = NO;
-
- savestate_slot(slot + 1);//no execption handling?
- result = YES;
-
- [execution_lock unlock];
-
- return result;
-}
-
-- (BOOL)loadStateFromSlot:(int)slot
-{
- if(slot >= MAX_SLOTS)return NO;
- if(slot < 0)return NO;
-
- BOOL result = NO;
- [execution_lock lock];
-
- //Set the GPU context (if it exists) incase the core needs to load anything into opengl during state load
- NSOpenGLContext *prev_context = [NSOpenGLContext currentContext];
- [prev_context retain];
- [context makeCurrentContext];
-
- loadstate_slot(slot + 1); //no exection handling?
- result = YES;
-
- [execution_lock unlock];
-
- if(prev_context != nil)
+ GPU *theGPU = SubScreen.gpu;
+ BOOL isLayerDisplayed = NO;
+
+ // Check bounds on the layer index.
+ if(i < 0 || i > 4)
{
- [prev_context makeCurrentContext];
- [prev_context release];
- } else
- [NSOpenGLContext clearCurrentContext];
-
- return result;
+ return isLayerDisplayed;
+ }
+
+ // Check if theGPU exists.
+ if(theGPU == nil)
+ {
+ return isLayerDisplayed;
+ }
+
+ // CommonSettings.dispLayers is returned as a bool, so we convert
+ // to BOOL here.
+ if (CommonSettings.dispLayers[theGPU->core][i])
+ {
+ isLayerDisplayed = YES;
+ }
+
+ return isLayerDisplayed;
}
-- (BOOL)saveStateExists:(int)slot
+- (BOOL) isMainScreenLayerDisplayed:(int)i
{
- scan_savestates();
- if(savestates[slot].exists)
- return YES;
- return NO;
+ GPU *theGPU = MainScreen.gpu;
+ BOOL isLayerDisplayed = NO;
+
+ // Check bounds on the layer index.
+ if(i < 0 || i > 4)
+ {
+ return isLayerDisplayed;
+ }
+
+ // Check if theGPU exists.
+ if(theGPU == nil)
+ {
+ return isLayerDisplayed;
+ }
+
+ // CommonSettings.dispLayers is returned as a bool, so we convert
+ // to BOOL here.
+ if (CommonSettings.dispLayers[theGPU->core][i])
+ {
+ isLayerDisplayed = YES;
+ }
+
+ return isLayerDisplayed;
}
-- (void)toggleTopBackground0
+- (void) toggleSubScreenLayer:(int)i
{
- if(SubScreen.gpu->dispBG[0])
- GPU_remove(SubScreen.gpu, 0);
+ GPU *theGPU = SubScreen.gpu;
+ BOOL isLayerDisplayed;
+
+ // Check bounds on the layer index.
+ if(i < 0 || i > 4)
+ {
+ return;
+ }
+
+ // Check if theGPU exists.
+ if(theGPU == nil)
+ {
+ return;
+ }
+
+ isLayerDisplayed = [self isSubScreenLayerDisplayed:i];
+ if(isLayerDisplayed == YES)
+ {
+ GPU_remove(theGPU, i);
+ }
else
- GPU_addBack(SubScreen.gpu, 0);
+ {
+ GPU_addBack(theGPU, i);
+ }
}
-- (BOOL)showingTopBackground0
+- (void) toggleMainScreenLayer:(int)i
{
- return SubScreen.gpu->dispBG[0];
-}
-
-- (void)toggleTopBackground1
-{
- if(SubScreen.gpu->dispBG[1])
- GPU_remove(SubScreen.gpu, 1);
+ GPU *theGPU = MainScreen.gpu;
+ BOOL isLayerDisplayed;
+
+ // Check bounds on the layer index.
+ if(i < 0 || i > 4)
+ {
+ return;
+ }
+
+ // Check if theGPU exists.
+ if(theGPU == nil)
+ {
+ return;
+ }
+
+ isLayerDisplayed = [self isMainScreenLayerDisplayed:i];
+ if(isLayerDisplayed == YES)
+ {
+ GPU_remove(theGPU, i);
+ }
else
- GPU_addBack(SubScreen.gpu, 1);
-}
-
-- (BOOL)showingTopBackground1
-{
- return SubScreen.gpu->dispBG[1];
-}
-
-- (void)toggleTopBackground2
-{
- if(SubScreen.gpu->dispBG[2])
- GPU_remove(SubScreen.gpu, 2);
- else
- GPU_addBack(SubScreen.gpu, 2);
-}
-
-- (BOOL)showingTopBackground2
-{
- return SubScreen.gpu->dispBG[2];
-}
-
-- (void)toggleTopBackground3
-{
- if(SubScreen.gpu->dispBG[3])
- GPU_remove(SubScreen.gpu, 3);
- else
- GPU_addBack(SubScreen.gpu, 3);
-}
-
-- (BOOL)showingTopBackground3
-{
- return SubScreen.gpu->dispBG[3];
-}
-
-- (void)toggleSubBackground0
-{
- if(MainScreen.gpu->dispBG[0])
- GPU_remove(MainScreen.gpu, 0);
- else
- GPU_addBack(MainScreen.gpu, 0);
-}
-
-- (BOOL)showingSubBackground0
-{
- return MainScreen.gpu->dispBG[0];
-}
-
-- (void)toggleSubBackground1
-{
- if(MainScreen.gpu->dispBG[1])
- GPU_remove(MainScreen.gpu, 1);
- else
- GPU_addBack(MainScreen.gpu, 1);
-}
-
-- (BOOL)showingSubBackground1
-{
- return MainScreen.gpu->dispBG[1];
-}
-
-- (void)toggleSubBackground2
-{
- if(MainScreen.gpu->dispBG[2])
- GPU_remove(MainScreen.gpu, 2);
- else
- GPU_addBack(MainScreen.gpu, 2);
-}
-
-- (BOOL)showingSubBackground2
-{
- return MainScreen.gpu->dispBG[2];
-}
-
-- (void)toggleSubBackground3
-{
- if(MainScreen.gpu->dispBG[3])
- GPU_remove(MainScreen.gpu, 3);
- else
- GPU_addBack(MainScreen.gpu, 3);
-}
-
-- (BOOL)showingSubBackground3
-{
- return MainScreen.gpu->dispBG[3];
+ {
+ GPU_addBack(theGPU, i);
+ }
}
- (BOOL)hasSound
@@ -1333,114 +924,217 @@ bool opengl_init()
- (void)run:(NSOpenGLContext*)gl_context
{
NSAutoreleasePool *autorelease = [[NSAutoreleasePool alloc] init];
-
+
+ NSDate *loopStartDate;
+ NSDate *emulation_start_date;
+ NSDate *frame_start_date;
+
+ NSTimeInterval timeBudget;
+ NSTimeInterval timePad;
+
#ifdef HAVE_OPENGL
[gl_context retain];
[gl_context makeCurrentContext];
CGLLockContext((CGLContextObj)[gl_context CGLContextObj]);
#endif
-
- NSDate *frame_start_date, *frame_end_date, *ideal_frame_end_date;
-
- int frames_to_skip = 0;
-
+
//program main loop
while(!finish)
{
- if(!run)paused = true;
-
+ if(!run)
+ {
+ paused = true;
+ }
+
//run the emulator
while(run && execute) //run controls when the emulator runs, execute prevents it from continuing execution if there are errors
{
-
- paused = false;
-
- int speed_limit_this_frame = speed_limit; //dont let speed limit change midframe
- if(speed_limit_this_frame)ideal_frame_end_date = [NSDate dateWithTimeIntervalSinceNow: DS_SECONDS_PER_FRAME / ((float)speed_limit_this_frame / 100.0)];
-
- frame_start_date = [NSDate dateWithTimeIntervalSinceNow:0];
-
- [execution_lock lock];
-
- NDS_exec();
-
- [sound_lock lock];
- int x;
- for(x = 0; x <= frames_to_skip; x++)
+ /*
+ Get the start time for the loop. This will be needed when it comes
+ time to determine the total time spent, and then calculating what
+ timePad should be.
+ */
+ loopStartDate = [NSDate date];
+
+ /*
+ Some controls may affect how the loop runs.
+
+ Instead of checking and modifying the NDS config every time through
+ the loop, only change the config on an as-needed basis.
+ */
+ if(doesConfigNeedUpdate == true)
{
- SPU_Emulate_user();
- SPU_Emulate_core();
+ [self updateConfig];
+ doesConfigNeedUpdate = false;
+ }
+
+ // Force paused state.
+ paused = false;
+
+ /*
+ Set up our time budget, which is equal to calcTimeBudget, which
+ is the relationship between DS_SECONDS_PER_FRAME and speed_limit.
+ timeBudget represents how much time we have to spend doing the
+ various functions of making a new frame.
+
+ The major parts we spend our time on is:
+ - Emulation
+ - Drawing the frame
+ - Pad time
+
+ The priorities for spending time are the same as the order listed
+ above.
+
+ timePad represents any excess time that can be released back
+ to the OS.
+ */
+ timeBudget = calcTimeBudget;
+ timePad = timeBudget;
+
+ /*
+ Set up the inputs for the emulator.
+
+ The time taken up by this step should be insignificant, so we
+ won't bother calculating this in the time budget.
+ */
+ [dsController setupAllDSInputs];
+ NDS_beginProcessingInput();
+ /*
+ Shouldn't need to do any special processing steps in between.
+ We'll just jump directly to ending the input processing.
+ */
+ NDS_endProcessingInput();
+
+ emulation_start_date = [NSDate date];
+ [self emulateDS];
+
+ /*
+ Subtract the emulation time from our time budget.
+
+ For some reason, [NSDate timeIntervalSinceNow] returns a
+ negative interval if the receiver is an earlier date than now.
+ So to subtract from timeBudget, we add the interval.
+
+ Go figure.
+ */
+ timeBudget += [emulation_start_date timeIntervalSinceNow];
+
+ /*
+ If we have time left in our time budget, draw the frame.
+
+ But if we don't have time left in our time budget, then we need
+ to make a decision on whether to simply drop the frame, or just
+ draw the frame.
+
+ Currently, the decision is to just draw everything because
+ frame drawing time is very negligible. Dropping a whole bunch of
+ frames will NOT yield any significant speed increase.
+ */
+ if(timeBudget > 0)
+ {
+ frame_start_date = [NSDate date];
+ [self drawFrame];
+
+ // Subtract the drawing time from our time budget.
+ timeBudget += [frame_start_date timeIntervalSinceNow];
}
- [sound_lock unlock];
-
- [execution_lock unlock];
-
- frame_end_date = [NSDate dateWithTimeIntervalSinceNow:0];
-
- //speed limit
- if(speed_limit_this_frame)
- [NSThread sleepUntilDate:ideal_frame_end_date];
-
- if(frames_to_skip > 0)
- frames_to_skip--;
-
else
{
- if(frame_skip < 0)
- { //automatic
-
- //i don't know if theres a standard strategy, but here we calculate how much
- //longer the frame took than it should have, then set it to skip that many frames.
- frames_to_skip = [frame_end_date timeIntervalSinceDate:frame_start_date] / (float)DS_SECONDS_PER_FRAME;
- if(frames_to_skip > 10)frames_to_skip = 10;
-
- } else
- {
-
- frames_to_skip = frame_skip;
-
- }
-
- //update the screen
- ScreenState *new_screen_data = [[ScreenState alloc] initWithColorData:GPU_screen];
-
- if(timer_based)
- { //for tiger compatibility
- [video_update_lock lock];
- [current_screen release];
- current_screen = new_screen_data;
- [video_update_lock unlock];
- } else
- { //for leopard and later
-
- //this will generate a warning when compiling on tiger or earlier, but it should
- //be ok since the purpose of the if statement is to check if this will work
- [self performSelector:@selector(videoUpdateHelper:) onThread:gui_thread withObject:new_screen_data waitUntilDone:NO];
- [new_screen_data release]; //performSelector will auto retain the screen data while the other thread displays
- }
+ // Don't even bother calculating timeBudget. We've already
+ // gone over at this point.
+ [self drawFrame];
+ }
+
+ // If there is any time left in the loop, go ahead and pad it.
+ timePad += [loopStartDate timeIntervalSinceNow];
+ if(timePad > 0)
+ {
+ [self padTime:timePad];
}
-
- //execute is set to false sometimes by the emulation core
- //when there is an error, if this happens notify the other thread that emulation has stopped.
- if(!execute)
- if(!timer_based) //wont display an error on tiger or earlier
- [error_object performSelector:error_func onThread:gui_thread withObject:nil waitUntilDone:YES];
-
}
-
+
//when emulation is paused, return CPU time to the OS
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:.1]];
}
-
+
#ifdef HAVE_OPENGL
CGLUnlockContext((CGLContextObj)[gl_context CGLContextObj]);
[gl_context release];
#endif
-
+
[autorelease release];
-
+
paused = true;
finished = true;
}
+- (void) emulateDS
+{
+ [execution_lock lock];
+
+ NDS_exec();
+
+ [sound_lock lock];
+
+ SPU_Emulate_user();
+
+ [sound_lock unlock];
+
+ [execution_lock unlock];
+}
+
+- (void) drawFrame
+{
+ ScreenState *new_screen_data = [[ScreenState alloc] initWithColorData:GPU_screen];
+
+ if(timer_based)
+ { //for tiger compatibility
+ [video_update_lock lock];
+ [current_screen release];
+ current_screen = new_screen_data;
+ [video_update_lock unlock];
+ }
+ else
+ { //for leopard and later
+
+ //this will generate a warning when compiling on tiger or earlier, but it should
+ //be ok since the purpose of the if statement is to check if this will work
+ [self performSelector:@selector(videoUpdateHelper:) onThread:gui_thread withObject:new_screen_data waitUntilDone:NO];
+ [new_screen_data release]; //performSelector will auto retain the screen data while the other thread displays
+ }
+}
+
+- (void) padTime:(NSTimeInterval)timePad
+{
+#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4) // Code for Mac OS X 10.4 and earlier
+
+ [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:timePad]];
+
+#else // Code for Mac OS X 10.5 and later
+
+ [NSThread sleepForTimeInterval:timePad];
+
+#endif
+}
+
+- (void) updateConfig
+{
+ // Update the Nintendo DS config
+ frame_skip = dsStateBuffer->frame_skip;
+ speed_limit = dsStateBuffer->speed_limit;
+
+ if(speed_limit <= 0)
+ {
+ calcTimeBudget = 0;
+ }
+ else if(speed_limit > 0 && speed_limit < 1000)
+ {
+ calcTimeBudget = (NSTimeInterval)(DS_SECONDS_PER_FRAME / ((float)speed_limit / 100.0));
+ }
+ else
+ {
+ calcTimeBudget = (NSTimeInterval)(DS_SECONDS_PER_FRAME / ((float)1000.0 / 100.0));
+ }
+}
+
@end
diff --git a/desmume/src/cocoa/sndOSX.h b/desmume/src/cocoa/sndOSX.h
index 432175347..ac1a207fe 100644
--- a/desmume/src/cocoa/sndOSX.h
+++ b/desmume/src/cocoa/sndOSX.h
@@ -17,9 +17,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define OBJ_C
#include "../SPU.h"
-#undef OBJ_C
#ifdef __cplusplus
extern "C"
diff --git a/desmume/src/cocoa/sndOSX.mm b/desmume/src/cocoa/sndOSX.mm
index 43beb47a9..e81ef0779 100644
--- a/desmume/src/cocoa/sndOSX.mm
+++ b/desmume/src/cocoa/sndOSX.mm
@@ -29,9 +29,7 @@
#include
//desmume includes
-#define OBJ_C
#include "sndOSX.h"
-#undef BOOL
//globals
AudioUnit output_unit = NULL; //pointer to our audio device