Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -230,10 +230,11 @@ enable_threads="no" # TODO enable_sockets="no" # TODO check_pedantic="no" AC_DEFINE(OF_NINTENDO_DS, 1, [Whether we are compiling for Nintendo DS]) + AC_SUBST(USE_SRCS_NINTENDO_DS, '${SRCS_NINTENDO_DS}') AC_SUBST(MAP_LDFLAGS, ['-Wl,-Map,$@.map']) ]) AC_ARG_WITH(3ds, AS_HELP_STRING([--with-3ds], [build for Nintendo 3DS])) Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -99,10 +99,11 @@ USE_SRCS_APPLETALK = @USE_SRCS_APPLETALK@ USE_SRCS_EVDEV = @USE_SRCS_EVDEV@ USE_SRCS_FILES = @USE_SRCS_FILES@ USE_SRCS_IPX = @USE_SRCS_IPX@ USE_SRCS_NINTENDO_3DS = @USE_SRCS_NINTENDO_3DS@ +USE_SRCS_NINTENDO_DS = @USE_SRCS_NINTENDO_DS@ USE_SRCS_PLUGINS = @USE_SRCS_PLUGINS@ USE_SRCS_SCTP = @USE_SRCS_SCTP@ USE_SRCS_SOCKETS = @USE_SRCS_SOCKETS@ USE_SRCS_SUBPROCESSES = @USE_SRCS_SUBPROCESSES@ USE_SRCS_TAGGED_POINTERS = @USE_SRCS_TAGGED_POINTERS@ Index: src/hid/Makefile ================================================================== --- src/hid/Makefile +++ src/hid/Makefile @@ -16,15 +16,17 @@ OHGameControllerElement.m \ OHGameControllerProfile.m \ OHGamepad.m \ ${USE_SRCS_EVDEV} \ ${USE_SRCS_NINTENDO_3DS} \ + ${USE_SRCS_NINTENDO_DS} \ ${USE_SRCS_XINPUT} SRCS_EVDEV = OHEvdevGameController.m \ OHEvdevGamepad.m SRCS_NINTENDO_3DS = OHNintendo3DSGameController.m \ OHNintendo3DSGamepad.m +SRCS_NINTENDO_DS = OHNintendoDSGameController.m SRCS_XINPUT = OHXInputGameController.m \ OHXInputGamepad.m INCLUDES := ${SRCS:.m=.h} \ ObjFWHID.h Index: src/hid/OHGameController.m ================================================================== --- src/hid/OHGameController.m +++ src/hid/OHGameController.m @@ -29,10 +29,13 @@ # import "OHEvdevGameController.h" #endif #ifdef OF_WINDOWS # import "OHXInputGameController.h" #endif +#ifdef OF_NINTENDO_DS +# import "OHNintendoDSGameController.h" +#endif #ifdef OF_NINTENDO_3DS # import "OHNintendo3DSGameController.h" #endif @implementation OHGameController @@ -42,10 +45,12 @@ { #if defined(OF_LINUX) && defined(OF_HAVE_FILES) return [OHEvdevGameController controllers]; #elif defined(OF_WINDOWS) return [OHXInputGameController controllers]; +#elif defined(OF_NINTENDO_DS) + return [OHNintendoDSGameController controllers]; #elif defined(OF_NINTENDO_3DS) return [OHNintendo3DSGameController controllers]; #else return [OFArray array]; #endif Index: src/hid/OHNintendo3DSGameController.m ================================================================== --- src/hid/OHNintendo3DSGameController.m +++ src/hid/OHNintendo3DSGameController.m @@ -35,20 +35,10 @@ #include <3ds.h> #undef id static OFArray OF_GENERIC(OHGameController *) *controllers; -/* Work around for the compiler getting confused. */ -static float -keyValue(u32 keys, u32 key) -{ - if (keys & key) - return 1; - else - return 0; -} - @implementation OHNintendo3DSGameController @synthesize gamepad = _gamepad; + (void)initialize { @@ -100,20 +90,20 @@ keys = hidKeysHeld(); hidCircleRead(&leftPos); hidCstickRead(&rightPos); - _gamepad.northButton.value = keyValue(keys, KEY_X); - _gamepad.southButton.value = keyValue(keys, KEY_B); - _gamepad.westButton.value = keyValue(keys, KEY_Y); - _gamepad.eastButton.value = keyValue(keys, KEY_A); - _gamepad.leftShoulderButton.value = keyValue(keys, KEY_L); - _gamepad.rightShoulderButton.value = keyValue(keys, KEY_R); - _gamepad.leftTriggerButton.value = keyValue(keys, KEY_ZL); - _gamepad.rightTriggerButton.value = keyValue(keys, KEY_ZR); - _gamepad.menuButton.value = keyValue(keys, KEY_START); - _gamepad.optionsButton.value = keyValue(keys, KEY_SELECT); + [_gamepad.northButton setValue: !!(keys & KEY_X)]; + [_gamepad.southButton setValue: !!(keys & KEY_B)]; + [_gamepad.westButton setValue: !!(keys & KEY_Y)]; + [_gamepad.eastButton setValue: !!(keys & KEY_A)]; + [_gamepad.leftShoulderButton setValue: !!(keys & KEY_L)]; + [_gamepad.rightShoulderButton setValue: !!(keys & KEY_R)]; + [_gamepad.leftTriggerButton setValue: !!(keys & KEY_ZL)]; + [_gamepad.rightTriggerButton setValue: !!(keys & KEY_ZR)]; + [_gamepad.menuButton setValue: !!(keys & KEY_START)]; + [_gamepad.optionsButton setValue: !!(keys & KEY_SELECT)]; if (leftPos.dx > 150) leftPos.dx = 150; if (leftPos.dx < -150) leftPos.dx = -150; @@ -134,14 +124,14 @@ _gamepad.leftThumbstick.xAxis.value = (float)leftPos.dx / 150; _gamepad.leftThumbstick.yAxis.value = -(float)leftPos.dy / 150; _gamepad.rightThumbstick.xAxis.value = (float)rightPos.dx / 150; _gamepad.rightThumbstick.yAxis.value = -(float)rightPos.dy / 150; - _gamepad.dPad.up.value = keyValue(keys, KEY_DUP); - _gamepad.dPad.down.value = keyValue(keys, KEY_DDOWN); - _gamepad.dPad.left.value = keyValue(keys, KEY_DLEFT); - _gamepad.dPad.right.value = keyValue(keys, KEY_DRIGHT); + [_gamepad.dPad.up setValue: !!(keys & KEY_DUP)]; + [_gamepad.dPad.down setValue: !!(keys & KEY_DDOWN)]; + [_gamepad.dPad.left setValue: !!(keys & KEY_DLEFT)]; + [_gamepad.dPad.right setValue: !!(keys & KEY_DRIGHT)]; } - (OFString *)name { return @"Nintendo 3DS"; Index: src/hid/OHNintendo3DSGamepad.m ================================================================== --- src/hid/OHNintendo3DSGamepad.m +++ src/hid/OHNintendo3DSGamepad.m @@ -43,20 +43,14 @@ OHGameControllerAxis *xAxis, *yAxis; OHGameControllerDirectionalPad *directionalPad; OHGameControllerButton *up, *down, *left, *right; for (size_t i = 0; i < numButtons; i++) { - OHGameControllerButton *button; - - button = [[OHGameControllerButton alloc] - initWithName: buttonNames[i]]; - @try { - [buttons setObject: button - forKey: buttonNames[i]]; - } @finally { - [button release]; - } + OHGameControllerButton *button = + [[[OHGameControllerButton alloc] + initWithName: buttonNames[i]] autorelease]; + [buttons setObject: button forKey: buttonNames[i]]; } [buttons makeImmutable]; _buttons = [buttons retain]; _axes = [[OFDictionary alloc] init]; ADDED src/hid/OHNintendoDSGameController.h Index: src/hid/OHNintendoDSGameController.h ================================================================== --- /dev/null +++ src/hid/OHNintendoDSGameController.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3.0 only, + * as published by the Free Software Foundation. + * + * This program 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 Lesser General Public License + * version 3.0 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3.0 along with this program. If not, see + * . + */ + +#import "OHGameController.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OHNintendoDSGameControllerProfile; + +@interface OHNintendoDSGameController: OHGameController +{ + OHNintendoDSGameControllerProfile *_rawProfile; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/hid/OHNintendoDSGameController.m Index: src/hid/OHNintendoDSGameController.m ================================================================== --- /dev/null +++ src/hid/OHNintendoDSGameController.m @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3.0 only, + * as published by the Free Software Foundation. + * + * This program 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 Lesser General Public License + * version 3.0 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3.0 along with this program. If not, see + * . + */ + +#include "config.h" + +#import "OHNintendoDSGameController.h" +#import "OFArray.h" +#import "OFDictionary.h" +#import "OFNumber.h" +#import "OHGameControllerButton.h" +#import "OHGameControllerDirectionalPad.h" +#import "OHGameControllerProfile.h" + +#import "OFInitializationFailedException.h" +#import "OFReadFailedException.h" + +#define asm __asm__ +#include +#undef asm + +@interface OHNintendoDSGameControllerProfile: OHGameControllerProfile +@end + +static OFArray OF_GENERIC(OHGameController *) *controllers; + +static OFString *const buttonNames[] = { + @"A", @"B", @"X", @"Y", @"L", @"R", @"Start", @"Select" +}; +static const size_t numButtons = sizeof(buttonNames) / sizeof(*buttonNames); + +@implementation OHNintendoDSGameController +@synthesize rawProfile = _rawProfile; + ++ (void)initialize +{ + void *pool; + + if (self != [OHNintendoDSGameController class]) + return; + + pool = objc_autoreleasePoolPush(); + controllers = [[OFArray alloc] initWithObject: + [[[OHNintendoDSGameController alloc] init] autorelease]]; + objc_autoreleasePoolPop(pool); +} + ++ (OFArray OF_GENERIC(OHGameController *) *)controllers +{ + return controllers; +} + +- (instancetype)init +{ + self = [super init]; + + @try { + _rawProfile = [[OHNintendoDSGameControllerProfile alloc] init]; + + [self retrieveState]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_rawProfile release]; + + [super dealloc]; +} + +- (void)retrieveState +{ + OFDictionary *buttons = _rawProfile.buttons; + OHGameControllerDirectionalPad *dPad = + [_rawProfile.directionalPads objectForKey: @"D-Pad"]; + u32 keys; + + scanKeys(); + keys = keysCurrent(); + + [[buttons objectForKey: @"A"] setValue: !!(keys & KEY_A)]; + [[buttons objectForKey: @"B"] setValue: !!(keys & KEY_B)]; + [[buttons objectForKey: @"X"] setValue: !!(keys & KEY_X)]; + [[buttons objectForKey: @"Y"] setValue: !!(keys & KEY_Y)]; + [[buttons objectForKey: @"L"] setValue: !!(keys & KEY_L)]; + [[buttons objectForKey: @"R"] setValue: !!(keys & KEY_R)]; + [[buttons objectForKey: @"Start"] setValue: !!(keys & KEY_START)]; + [[buttons objectForKey: @"Select"] setValue: !!(keys & KEY_SELECT)]; + + [dPad.up setValue: !!(keys & KEY_UP)]; + [dPad.down setValue: !!(keys & KEY_DOWN)]; + [dPad.left setValue: !!(keys & KEY_LEFT)]; + [dPad.right setValue: !!(keys & KEY_RIGHT)]; +} + +- (OFString *)name +{ + return @"Nintendo DS"; +} +@end + +@implementation OHNintendoDSGameControllerProfile +- (instancetype)init +{ + self = [super init]; + + @try { + void *pool = objc_autoreleasePoolPush(); + OFMutableDictionary *buttons = + [OFMutableDictionary dictionaryWithCapacity: numButtons]; + OHGameControllerButton *up, *down, *left, *right; + OHGameControllerDirectionalPad *dPad; + + for (size_t i = 0; i < numButtons; i++) { + OHGameControllerButton *button = + [[[OHGameControllerButton alloc] + initWithName: buttonNames[i]] autorelease]; + [buttons setObject: button forKey: buttonNames[i]]; + } + [buttons makeImmutable]; + _buttons = [buttons retain]; + + up = [[[OHGameControllerButton alloc] + initWithName: @"D-Pad Up"] autorelease]; + down = [[[OHGameControllerButton alloc] + initWithName: @"D-Pad Down"] autorelease]; + left = [[[OHGameControllerButton alloc] + initWithName: @"D-Pad Left"] autorelease]; + right = [[[OHGameControllerButton alloc] + initWithName: @"D-Pad Right"] autorelease]; + dPad = [[[OHGameControllerDirectionalPad alloc] + initWithName: @"D-Pad" + up: up + down: down + left: left + right: right] autorelease]; + + _directionalPads = [[OFDictionary alloc] + initWithObject: dPad + forKey: @"D-Pad"]; + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} +@end