![SND\MaddTheSane_cp](/assets/img/avatar_default.png)
This change allows the user to use SDL2’s GameController API instead of the Joystick API. The Game Controller API maps the buttons similar to an Xbox 360 controller, so some tricky mapping needed to be done. Note that it currently only supports OS X. git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@89828 e17a0e51-4ae3-4d35-97c3-1a29b211df97
467 lines
18 KiB
Objective-C
Executable File
467 lines
18 KiB
Objective-C
Executable File
/*
|
|
* Copyright (c) 2010, Wei Mingzhi <whistler_wmz@users.sf.net>.
|
|
* All Rights Reserved.
|
|
*
|
|
* Based on: HIDInput by Gil Pedersen.
|
|
* Copyright (c) 2004, Gil Pedersen.
|
|
*
|
|
* This program 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.
|
|
*
|
|
* 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses>.
|
|
*/
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
#import "PadController.h"
|
|
#include "pad.h"
|
|
|
|
static inline void RunOnMainThreadSync(dispatch_block_t block)
|
|
{
|
|
if ([NSThread isMainThread]) {
|
|
block();
|
|
} else {
|
|
dispatch_sync(dispatch_get_main_queue(), block);
|
|
}
|
|
}
|
|
|
|
static NSWindow *padWindow = nil;
|
|
static PadController *padController = nil;
|
|
|
|
#define APP_ID @"net.pcsxr.DFInputPlugin"
|
|
#define PrefsKey APP_ID @" Settings"
|
|
|
|
#define kDFThreading @"Threading"
|
|
#define kDFPad1 @"Pad 1"
|
|
#define kDFPad2 @"Pad 2"
|
|
|
|
static void SetDefaultConfig() {
|
|
memset(&g.cfg, 0, sizeof(g.cfg));
|
|
|
|
g.cfg.Threaded = 1;
|
|
|
|
g.cfg.PadDef[0].DevNum = 0;
|
|
g.cfg.PadDef[1].DevNum = 1;
|
|
|
|
g.cfg.PadDef[0].Type = PSE_PAD_TYPE_STANDARD;
|
|
g.cfg.PadDef[1].Type = PSE_PAD_TYPE_STANDARD;
|
|
|
|
// Pad1 keyboard
|
|
g.cfg.PadDef[0].KeyDef[DKEY_SELECT].Key = 9;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_START].Key = 10;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_UP].Key = 127;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_RIGHT].Key = 125;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_DOWN].Key = 126;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_LEFT].Key = 124;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_L2].Key = 16;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_R2].Key = 18;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_L1].Key = 14;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_R1].Key = 15;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_TRIANGLE].Key = 3;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_CIRCLE].Key = 8;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_CROSS].Key = 7;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_SQUARE].Key = 2;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_ANALOG].Key = 12;
|
|
|
|
// Pad1 joystick
|
|
g.cfg.PadDef[0].KeyDef[DKEY_SELECT].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_SELECT].J.Button = 8;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_START].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_START].J.Button = 9;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_UP].JoyEvType = AXIS;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_UP].J.Axis = -2;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_RIGHT].JoyEvType = AXIS;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_RIGHT].J.Axis = 1;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_DOWN].JoyEvType = AXIS;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_DOWN].J.Axis = 2;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_LEFT].JoyEvType = AXIS;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_LEFT].J.Axis = -1;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_L2].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_L2].J.Button = 4;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_L1].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_L1].J.Button = 6;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_R2].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_R2].J.Button = 5;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_R1].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_R1].J.Button = 7;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_TRIANGLE].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_TRIANGLE].J.Button = 0;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_CIRCLE].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_CIRCLE].J.Button = 1;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_CROSS].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_CROSS].J.Button = 2;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_SQUARE].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[0].KeyDef[DKEY_SQUARE].J.Button = 3;
|
|
|
|
// Pad2 joystick
|
|
g.cfg.PadDef[1].KeyDef[DKEY_SELECT].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_SELECT].J.Button = 8;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_START].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_START].J.Button = 9;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_UP].JoyEvType = AXIS;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_UP].J.Axis = -2;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_RIGHT].JoyEvType = AXIS;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_RIGHT].J.Axis = 1;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_DOWN].JoyEvType = AXIS;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_DOWN].J.Axis = 2;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_LEFT].JoyEvType = AXIS;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_LEFT].J.Axis = -1;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_L2].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_L2].J.Button = 4;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_L1].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_L1].J.Button = 6;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_R2].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_R2].J.Button = 5;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_R1].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_R1].J.Button = 7;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_TRIANGLE].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_TRIANGLE].J.Button = 0;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_CIRCLE].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_CIRCLE].J.Button = 1;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_CROSS].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_CROSS].J.Button = 2;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_SQUARE].JoyEvType = BUTTON;
|
|
g.cfg.PadDef[1].KeyDef[DKEY_SQUARE].J.Button = 3;
|
|
}
|
|
|
|
void LoadPADConfig()
|
|
{
|
|
SetDefaultConfig();
|
|
BOOL tryToLoadOld = YES;
|
|
//Do we have the new settings?
|
|
//This is placed here so we don't have the prefskey defined.
|
|
NSUserDefaults *usrDefaults = [NSUserDefaults standardUserDefaults];
|
|
if ([usrDefaults objectForKey:PrefsKey]) {
|
|
//Yes we do, don't load the old.
|
|
tryToLoadOld = NO;
|
|
}
|
|
|
|
[usrDefaults registerDefaults:
|
|
@{PrefsKey: @{kDFPad1: DefaultPadArray(0),
|
|
kDFPad2: DefaultPadArray(1),
|
|
kDFThreading: @YES}}];
|
|
|
|
//Load the old preferences if present and we don't have new ones.
|
|
NSFileManager *fm = [NSFileManager defaultManager];
|
|
NSString *oldPrefPath = [NSString pathWithComponents:@[NSHomeDirectory(), @"Library", @"Preferences", @"net.pcsxr.DFInput.plist"]];
|
|
if ([fm fileExistsAtPath:oldPrefPath] && tryToLoadOld) {
|
|
char buf[256] = {0};
|
|
int current = 0, a = 0, b = 0, c = 0;
|
|
|
|
FILE *fp = fopen([oldPrefPath fileSystemRepresentation], "r");
|
|
if (fp == NULL) {
|
|
return;
|
|
}
|
|
|
|
while (fgets(buf, 256, fp) != NULL) {
|
|
if (strncmp(buf, "Threaded=", 9) == 0) {
|
|
g.cfg.Threaded = atoi(&buf[9]);
|
|
} else if (strncmp(buf, "[PAD", 4) == 0) {
|
|
current = atoi(&buf[4]) - 1;
|
|
if (current < 0) {
|
|
current = 0;
|
|
} else if (current > 1) {
|
|
current = 1;
|
|
}
|
|
} else if (strncmp(buf, "DevNum=", 7) == 0) {
|
|
g.cfg.PadDef[current].DevNum = atoi(&buf[7]);
|
|
} else if (strncmp(buf, "Type=", 5) == 0) {
|
|
g.cfg.PadDef[current].Type = atoi(&buf[5]);
|
|
} else if (strncmp(buf, "Select=", 7) == 0) {
|
|
sscanf(buf, "Select=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_SELECT].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_SELECT].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_SELECT].J.d = c;
|
|
} else if (strncmp(buf, "L3=", 3) == 0) {
|
|
sscanf(buf, "L3=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_L3].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_L3].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_L3].J.d = c;
|
|
} else if (strncmp(buf, "R3=", 3) == 0) {
|
|
sscanf(buf, "R3=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_R3].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_R3].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_R3].J.d = c;
|
|
} else if (strncmp(buf, "Analog=", 7) == 0) {
|
|
sscanf(buf, "Analog=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_ANALOG].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_ANALOG].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_ANALOG].J.d = c;
|
|
} else if (strncmp(buf, "Start=", 6) == 0) {
|
|
sscanf(buf, "Start=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_START].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_START].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_START].J.d = c;
|
|
} else if (strncmp(buf, "Up=", 3) == 0) {
|
|
sscanf(buf, "Up=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_UP].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_UP].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_UP].J.d = c;
|
|
} else if (strncmp(buf, "Right=", 6) == 0) {
|
|
sscanf(buf, "Right=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_RIGHT].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_RIGHT].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_RIGHT].J.d = c;
|
|
} else if (strncmp(buf, "Down=", 5) == 0) {
|
|
sscanf(buf, "Down=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_DOWN].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_DOWN].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_DOWN].J.d = c;
|
|
} else if (strncmp(buf, "Left=", 5) == 0) {
|
|
sscanf(buf, "Left=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_LEFT].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_LEFT].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_LEFT].J.d = c;
|
|
} else if (strncmp(buf, "L2=", 3) == 0) {
|
|
sscanf(buf, "L2=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_L2].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_L2].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_L2].J.d = c;
|
|
} else if (strncmp(buf, "R2=", 3) == 0) {
|
|
sscanf(buf, "R2=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_R2].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_R2].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_R2].J.d = c;
|
|
} else if (strncmp(buf, "L1=", 3) == 0) {
|
|
sscanf(buf, "L1=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_L1].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_L1].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_L1].J.d = c;
|
|
} else if (strncmp(buf, "R1=", 3) == 0) {
|
|
sscanf(buf, "R1=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_R1].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_R1].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_R1].J.d = c;
|
|
} else if (strncmp(buf, "Triangle=", 9) == 0) {
|
|
sscanf(buf, "Triangle=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_TRIANGLE].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_TRIANGLE].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_TRIANGLE].J.d = c;
|
|
} else if (strncmp(buf, "Circle=", 7) == 0) {
|
|
sscanf(buf, "Circle=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_CIRCLE].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_CIRCLE].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_CIRCLE].J.d = c;
|
|
} else if (strncmp(buf, "Cross=", 6) == 0) {
|
|
sscanf(buf, "Cross=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_CROSS].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_CROSS].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_CROSS].J.d = c;
|
|
} else if (strncmp(buf, "Square=", 7) == 0) {
|
|
sscanf(buf, "Square=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].KeyDef[DKEY_SQUARE].Key = a;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_SQUARE].JoyEvType = b;
|
|
g.cfg.PadDef[current].KeyDef[DKEY_SQUARE].J.d = c;
|
|
} else if (strncmp(buf, "LeftAnalogXP=", 13) == 0) {
|
|
sscanf(buf, "LeftAnalogXP=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XP].Key = a;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XP].JoyEvType = b;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XP].J.d = c;
|
|
} else if (strncmp(buf, "LeftAnalogXM=", 13) == 0) {
|
|
sscanf(buf, "LeftAnalogXM=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XM].Key = a;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XM].JoyEvType = b;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XM].J.d = c;
|
|
} else if (strncmp(buf, "LeftAnalogYP=", 13) == 0) {
|
|
sscanf(buf, "LeftAnalogYP=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YP].Key = a;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YP].JoyEvType = b;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YP].J.d = c;
|
|
} else if (strncmp(buf, "LeftAnalogYM=", 13) == 0) {
|
|
sscanf(buf, "LeftAnalogYM=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YM].Key = a;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YM].JoyEvType = b;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YM].J.d = c;
|
|
} else if (strncmp(buf, "RightAnalogXP=", 14) == 0) {
|
|
sscanf(buf, "RightAnalogXP=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XP].Key = a;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XP].JoyEvType = b;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XP].J.d = c;
|
|
} else if (strncmp(buf, "RightAnalogXM=", 14) == 0) {
|
|
sscanf(buf, "RightAnalogXM=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XM].Key = a;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XM].JoyEvType = b;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XM].J.d = c;
|
|
} else if (strncmp(buf, "RightAnalogYP=", 14) == 0) {
|
|
sscanf(buf, "RightAnalogYP=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YP].Key = a;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YP].JoyEvType = b;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YP].J.d = c;
|
|
} else if (strncmp(buf, "RightAnalogYM=", 14) == 0) {
|
|
sscanf(buf, "RightAnalogYM=%d,%d,%d", &a, &b, &c);
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YM].Key = a;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YM].JoyEvType = b;
|
|
g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YM].J.d = c;
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
//Save to new preferences
|
|
SavePADConfig();
|
|
//Delete the old preferences
|
|
[fm removeItemAtPath:oldPrefPath error:NULL];
|
|
} else {
|
|
NSDictionary *dfPrefs = [usrDefaults dictionaryForKey:PrefsKey];
|
|
g.cfg.Threaded = [dfPrefs[kDFThreading] boolValue];
|
|
LoadPadArray(0, dfPrefs[kDFPad1]);
|
|
LoadPadArray(1, dfPrefs[kDFPad2]);
|
|
}
|
|
}
|
|
|
|
void SavePADConfig()
|
|
{
|
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
NSMutableDictionary *pad1Dict, *pad2Dict;
|
|
NSDictionary *prefDict = [defaults dictionaryForKey:PrefsKey];
|
|
pad1Dict = [[NSMutableDictionary alloc] initWithDictionary:prefDict[kDFPad1]];
|
|
pad2Dict = [[NSMutableDictionary alloc] initWithDictionary:prefDict[kDFPad2]];
|
|
prefDict = nil;
|
|
|
|
[pad1Dict addEntriesFromDictionary:SavePadArray(0)];
|
|
[pad2Dict addEntriesFromDictionary:SavePadArray(1)];
|
|
|
|
[defaults setObject:@{kDFThreading: g.cfg.Threaded ? @YES : @NO,
|
|
kDFPad1: pad1Dict,
|
|
kDFPad2: pad2Dict} forKey:PrefsKey];
|
|
[defaults synchronize];
|
|
}
|
|
|
|
void DoAbout()
|
|
{
|
|
// Get parent application instance
|
|
NSBundle *bundle = [NSBundle bundleWithIdentifier:APP_ID];
|
|
|
|
// Get Credits.rtf
|
|
NSString *path = [bundle pathForResource:@"Credits" ofType:@"rtf"];
|
|
NSAttributedString *credits;
|
|
if (!path) {
|
|
path = [bundle pathForResource:@"Credits" ofType:@"rtfd"];
|
|
}
|
|
if (path) {
|
|
credits = [[NSAttributedString alloc] initWithPath:path documentAttributes:NULL];
|
|
} else {
|
|
credits = [[NSAttributedString alloc] initWithString:@""];
|
|
}
|
|
|
|
// Get Application Icon
|
|
NSImage *icon = [[NSWorkspace sharedWorkspace] iconForFile:[bundle bundlePath]];
|
|
NSSize size = NSMakeSize(64, 64);
|
|
[icon setSize:size];
|
|
|
|
NSDictionary *infoPaneDict =
|
|
@{@"ApplicationName": [bundle objectForInfoDictionaryKey:@"CFBundleName"],
|
|
@"ApplicationIcon": icon,
|
|
@"ApplicationVersion": [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"],
|
|
@"Version": [bundle objectForInfoDictionaryKey:@"CFBundleVersion"],
|
|
@"Copyright": [bundle objectForInfoDictionaryKey:@"NSHumanReadableCopyright"],
|
|
@"Credits": credits};
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[NSApp orderFrontStandardAboutPanelWithOptions:infoPaneDict];
|
|
});
|
|
}
|
|
|
|
long DoConfiguration()
|
|
{
|
|
RunOnMainThreadSync(^{
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
|
#else
|
|
SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE);
|
|
#endif
|
|
LoadPADConfig();
|
|
|
|
if (padWindow == nil) {
|
|
if (padController == nil) {
|
|
padController = [[PadController alloc] initWithWindowNibName:@"NetPcsxrHIDInputPluginMain"];
|
|
}
|
|
padWindow = [padController window];
|
|
}
|
|
|
|
[padWindow center];
|
|
[padWindow makeKeyAndOrderFront:nil];
|
|
});
|
|
|
|
return 0;
|
|
}
|
|
|
|
@implementation PadController
|
|
|
|
- (IBAction)cancel:(id)sender
|
|
{
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
|
#else
|
|
SDL_Quit();
|
|
#endif
|
|
[self close];
|
|
}
|
|
|
|
- (IBAction)ok:(id)sender
|
|
{
|
|
SavePADConfig();
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
|
#else
|
|
SDL_Quit();
|
|
#endif
|
|
[self close];
|
|
}
|
|
|
|
- (void)awakeFromNib
|
|
{
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(windowWillClose:)
|
|
name:NSWindowWillCloseNotification object:[self window]];
|
|
|
|
[controllerView1 addSubview: controllerView];
|
|
[controllerView setController:0];
|
|
}
|
|
|
|
- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem
|
|
{
|
|
PadView *newView = nil;
|
|
if ([[tabViewItem identifier] isEqualToString:@"pad1"])
|
|
newView = controllerView1;
|
|
else if ([[tabViewItem identifier] isEqualToString:@"pad2"])
|
|
newView = controllerView2;
|
|
|
|
if (nil != newView) {
|
|
[controllerView removeFromSuperviewWithoutNeedingDisplay];
|
|
[newView addSubview: controllerView];
|
|
[controllerView setFrame:[newView frame]];
|
|
[controllerView setController:[newView isEqual:controllerView1] ? 0 : 1];
|
|
}
|
|
}
|
|
|
|
- (void)windowBecameKey:(NSNotification *)notification
|
|
{
|
|
if ([[controllerView1 subviews] count] > 0)
|
|
[controllerView setController:0];
|
|
else if ([[controllerView2 subviews] count] > 0)
|
|
[controllerView setController:1];
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
name:NSWindowDidBecomeKeyNotification object:[self window]];
|
|
}
|
|
|
|
- (void)windowWillClose:(NSNotification *)aNotification
|
|
{
|
|
if ([aNotification object] == [self window]) {
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(windowBecameKey:)
|
|
name:NSWindowDidBecomeKeyNotification object:[self window]];
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
#import "OSXPlugLocalization.h"
|
|
PLUGLOCIMP([padController class])
|