summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/mac/CMakeLists.txt2
-rw-r--r--app/mac/controller-adapter-gamepad.hh18
-rw-r--r--app/mac/controller-adapter-gamepad.mm32
-rw-r--r--app/mac/controller-adapter-keyboard.hh1
-rw-r--r--app/mac/controller-adapter.hh7
-rw-r--r--app/mac/scene.hh1
-rw-r--r--app/mac/scene.mm10
-rw-r--r--app/mac/view-controller.hh9
-rw-r--r--app/mac/view-controller.mm76
9 files changed, 140 insertions, 16 deletions
diff --git a/app/mac/CMakeLists.txt b/app/mac/CMakeLists.txt
index d6ea464..e0d42d0 100644
--- a/app/mac/CMakeLists.txt
+++ b/app/mac/CMakeLists.txt
@@ -23,5 +23,7 @@ target_sources(
view-controller.hh
view-controller.mm
controller-adapter.hh
+ controller-adapter-gamepad.hh
+ controller-adapter-gamepad.mm
controller-adapter-keyboard.hh
controller-adapter-keyboard.mm) \ No newline at end of file
diff --git a/app/mac/controller-adapter-gamepad.hh b/app/mac/controller-adapter-gamepad.hh
index 14bfeae..c0caeed 100644
--- a/app/mac/controller-adapter-gamepad.hh
+++ b/app/mac/controller-adapter-gamepad.hh
@@ -1,16 +1,18 @@
-//
-// Created by Hannes Schulze on 29.01.25.
-//
+#pragma once
-#ifndef NES_CONTROLLER_ADAPTER_GAMEPAD_HH
-#define NES_CONTROLLER_ADAPTER_GAMEPAD_HH
+#import "controller-adapter.hh"
+#import <GameController/GameController.h>
+NS_ASSUME_NONNULL_BEGIN
-class ControllerAdapterGamepad {
+@interface ControllerAdapterGamepad : NSObject <ControllerAdapter>
-};
+- (instancetype)initWithProfile:(GCExtendedGamepad*)profile;
+- (instancetype)init NS_UNAVAILABLE;
+@property (readonly) GCExtendedGamepad* profile;
+@end
-#endif //NES_CONTROLLER_ADAPTER_GAMEPAD_HH
+NS_ASSUME_NONNULL_END \ No newline at end of file
diff --git a/app/mac/controller-adapter-gamepad.mm b/app/mac/controller-adapter-gamepad.mm
index 132fa85..f1d8db8 100644
--- a/app/mac/controller-adapter-gamepad.mm
+++ b/app/mac/controller-adapter-gamepad.mm
@@ -1,5 +1,29 @@
-//
-// Created by Hannes Schulze on 29.01.25.
-//
-
#include "controller-adapter-gamepad.hh"
+
+@implementation ControllerAdapterGamepad
+
+- (instancetype)initWithProfile:(GCExtendedGamepad*)profile
+{
+ self = [super init];
+ if (self)
+ {
+ _profile = profile;
+ }
+ return self;
+}
+
+- (nes::button_mask)readPressedButtons
+{
+ auto res = nes::button_mask{};
+ if ([[[_profile dpad] up] isPressed]) { res.add(nes::buttons::up); }
+ if ([[[_profile dpad] down] isPressed]) { res.add(nes::buttons::down); }
+ if ([[[_profile dpad] left] isPressed]) { res.add(nes::buttons::left); }
+ if ([[[_profile dpad] right] isPressed]) { res.add(nes::buttons::right); }
+ if ([[_profile buttonA] isPressed]) { res.add(nes::buttons::a); }
+ if ([[_profile buttonB] isPressed]) { res.add(nes::buttons::b); }
+ if ([[_profile leftTrigger] isPressed]) { res.add(nes::buttons::select); }
+ if ([[_profile rightTrigger] isPressed]) { res.add(nes::buttons::start); }
+ return res;
+}
+
+@end \ No newline at end of file
diff --git a/app/mac/controller-adapter-keyboard.hh b/app/mac/controller-adapter-keyboard.hh
index d91f069..7c3ef84 100644
--- a/app/mac/controller-adapter-keyboard.hh
+++ b/app/mac/controller-adapter-keyboard.hh
@@ -1,6 +1,7 @@
#pragma once
#import "controller-adapter.hh"
+
#import <GameController/GameController.h>
NS_ASSUME_NONNULL_BEGIN
diff --git a/app/mac/controller-adapter.hh b/app/mac/controller-adapter.hh
index d0fc33a..7a4c4b4 100644
--- a/app/mac/controller-adapter.hh
+++ b/app/mac/controller-adapter.hh
@@ -1,11 +1,16 @@
#pragma once
#import "nes/util/button-mask.hh"
+
#import <Foundation/Foundation.h>
+NS_ASSUME_NONNULL_BEGIN
+
/// Adapts inputs from a GCPhysicalInputProfile to a NES button mask.
@protocol ControllerAdapter <NSObject>
- (nes::button_mask)readPressedButtons;
-@end \ No newline at end of file
+@end
+
+NS_ASSUME_NONNULL_END \ No newline at end of file
diff --git a/app/mac/scene.hh b/app/mac/scene.hh
index ed56f2f..ba8eb31 100644
--- a/app/mac/scene.hh
+++ b/app/mac/scene.hh
@@ -1,6 +1,7 @@
#pragma once
#import "controller-adapter.hh"
+
#import <SpriteKit/SpriteKit.h>
NS_ASSUME_NONNULL_BEGIN
diff --git a/app/mac/scene.mm b/app/mac/scene.mm
index 0d50a7e..4ede6e0 100644
--- a/app/mac/scene.mm
+++ b/app/mac/scene.mm
@@ -97,6 +97,16 @@ namespace
return self;
}
+- (void)keyUp:(NSEvent*)event
+{
+ // Handled by Game Controller
+}
+
+- (void)keyDown:(NSEvent*)event
+{
+ // Handled by Game Controller
+}
+
- (void)update:(NSTimeInterval)currentTime
{
_nes->ref_controller_1().set_pressed(_primaryController ? [_primaryController readPressedButtons] : nes::button_mask{});
diff --git a/app/mac/view-controller.hh b/app/mac/view-controller.hh
index 4947b99..2eecd4e 100644
--- a/app/mac/view-controller.hh
+++ b/app/mac/view-controller.hh
@@ -3,15 +3,20 @@
#import <Cocoa/Cocoa.h>
#import <GameController/GameController.h>
+NS_ASSUME_NONNULL_BEGIN
+
@interface ViewController : GCEventViewController
- (instancetype)initWithFilePath:(NSString*)filePath NS_DESIGNATED_INITIALIZER;
-- (instancetype)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE;
+- (instancetype)initWithNibName:(nullable NSString*)nibNameOrNil
+ bundle:(nullable NSBundle*)nibBundleOrNil NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder*)coder NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
@property (readonly) NSSize minimumDisplaySize;
@property (readonly) NSSize preferredDisplaySize;
-@end \ No newline at end of file
+@end
+
+NS_ASSUME_NONNULL_END \ No newline at end of file
diff --git a/app/mac/view-controller.mm b/app/mac/view-controller.mm
index 8a1fcbd..eb81b6b 100644
--- a/app/mac/view-controller.mm
+++ b/app/mac/view-controller.mm
@@ -1,5 +1,6 @@
#import "view-controller.hh"
#import "controller-adapter-keyboard.hh"
+#import "controller-adapter-gamepad.hh"
#import "scene.hh"
@implementation ViewController
@@ -7,6 +8,7 @@
Scene* _scene;
NSSize _sceneSize;
ControllerAdapterKeyboard* _keyboardController;
+ NSMutableArray<ControllerAdapterGamepad*>* _gamepadControllers;
}
- (instancetype)initWithFilePath:(NSString*)filePath
@@ -18,11 +20,35 @@
_sceneSize = [_scene size];
_keyboardController = [[ControllerAdapterKeyboard alloc] init];
- [_scene setPrimaryController:_keyboardController];
+ _gamepadControllers = [NSMutableArray array];
+ for (GCController* controller in [GCController controllers])
+ {
+ auto gamepad = [controller extendedGamepad];
+ if (gamepad)
+ {
+ auto adapter = [[ControllerAdapterGamepad alloc] initWithProfile:gamepad];
+ [_gamepadControllers addObject:adapter];
+ }
+ }
+ [self updateControllers];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(handleControllerConnected:)
+ name:GCControllerDidConnectNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(handleControllerDisconnected:)
+ name:GCControllerDidDisconnectNotification
+ object:nil];
}
return self;
}
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
- (void)loadView
{
auto view = [[SKView alloc] init];
@@ -33,6 +59,54 @@
[self setView:view];
}
+- (void)updateControllers
+{
+ // Prefer controllers, then fallback to keyboard input.
+ if ([_gamepadControllers count] >= 1)
+ {
+ [_scene setPrimaryController:[_gamepadControllers objectAtIndex:0]];
+ if ([_gamepadControllers count] >= 2)
+ {
+ [_scene setSecondaryController:[_gamepadControllers objectAtIndex:1]];
+ }
+ else
+ {
+ [_scene setSecondaryController:_keyboardController];
+ }
+ }
+ else
+ {
+ [_scene setPrimaryController:_keyboardController];
+ [_scene setSecondaryController:nil];
+ }
+}
+
+- (void)handleControllerConnected:(NSNotification*)notification
+{
+ auto controller = (GCController*)[notification object];
+ auto gamepad = [controller extendedGamepad];
+ if (gamepad)
+ {
+ auto adapter = [[ControllerAdapterGamepad alloc] initWithProfile:gamepad];
+ [_gamepadControllers addObject:adapter];
+ }
+ [self updateControllers];
+}
+
+- (void)handleControllerDisconnected:(NSNotification*)notification
+{
+ auto controller = (GCController*)[notification object];
+ for (auto i = NSUInteger{ [_gamepadControllers count] }; i > 0; --i)
+ {
+ auto adapter = [_gamepadControllers objectAtIndex:(i - 1)];
+ if ([[adapter profile] controller] == controller)
+ {
+ [_gamepadControllers removeObjectAtIndex:(i - 1)];
+ }
+ }
+ [self updateControllers];
+}
+
- (NSSize)minimumDisplaySize
{
return _sceneSize;