pcsxr-1.9.92
[pcsx_rearmed.git] / macosx / plugins / DFInput / macsrc / cfg.c
1 /*
2  * Copyright (c) 2010, Wei Mingzhi <whistler@openoffice.org>.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, see <http://www.gnu.org/licenses>.
17  */
18
19 #include "pad.h"
20
21 GLOBALDATA                      g;
22
23 long DoConfiguration();
24 void DoAbout();
25
26 static void SetDefaultConfig() {
27         memset(&g.cfg, 0, sizeof(g.cfg));
28
29         g.cfg.Threaded = 1;
30
31         g.cfg.PadDef[0].DevNum = 0;
32         g.cfg.PadDef[1].DevNum = 1;
33
34         g.cfg.PadDef[0].Type = PSE_PAD_TYPE_STANDARD;
35         g.cfg.PadDef[1].Type = PSE_PAD_TYPE_STANDARD;
36
37         // Pad1 keyboard
38         g.cfg.PadDef[0].KeyDef[DKEY_SELECT].Key = 9;
39         g.cfg.PadDef[0].KeyDef[DKEY_START].Key = 10;
40         g.cfg.PadDef[0].KeyDef[DKEY_UP].Key = 127;
41         g.cfg.PadDef[0].KeyDef[DKEY_RIGHT].Key = 125;
42         g.cfg.PadDef[0].KeyDef[DKEY_DOWN].Key = 126;
43         g.cfg.PadDef[0].KeyDef[DKEY_LEFT].Key = 124;
44         g.cfg.PadDef[0].KeyDef[DKEY_L2].Key = 16;
45         g.cfg.PadDef[0].KeyDef[DKEY_R2].Key = 18;
46         g.cfg.PadDef[0].KeyDef[DKEY_L1].Key = 14;
47         g.cfg.PadDef[0].KeyDef[DKEY_R1].Key = 15;
48         g.cfg.PadDef[0].KeyDef[DKEY_TRIANGLE].Key = 3;
49         g.cfg.PadDef[0].KeyDef[DKEY_CIRCLE].Key = 8;
50         g.cfg.PadDef[0].KeyDef[DKEY_CROSS].Key = 7;
51         g.cfg.PadDef[0].KeyDef[DKEY_SQUARE].Key = 2;
52
53         // Pad1 joystick
54         g.cfg.PadDef[0].KeyDef[DKEY_SELECT].JoyEvType = BUTTON;
55         g.cfg.PadDef[0].KeyDef[DKEY_SELECT].J.Button = 8;
56         g.cfg.PadDef[0].KeyDef[DKEY_START].JoyEvType = BUTTON;
57         g.cfg.PadDef[0].KeyDef[DKEY_START].J.Button = 9;
58         g.cfg.PadDef[0].KeyDef[DKEY_UP].JoyEvType = AXIS;
59         g.cfg.PadDef[0].KeyDef[DKEY_UP].J.Axis = -2;
60         g.cfg.PadDef[0].KeyDef[DKEY_RIGHT].JoyEvType = AXIS;
61         g.cfg.PadDef[0].KeyDef[DKEY_RIGHT].J.Axis = 1;
62         g.cfg.PadDef[0].KeyDef[DKEY_DOWN].JoyEvType = AXIS;
63         g.cfg.PadDef[0].KeyDef[DKEY_DOWN].J.Axis = 2;
64         g.cfg.PadDef[0].KeyDef[DKEY_LEFT].JoyEvType = AXIS;
65         g.cfg.PadDef[0].KeyDef[DKEY_LEFT].J.Axis = -1;
66         g.cfg.PadDef[0].KeyDef[DKEY_L2].JoyEvType = BUTTON;
67         g.cfg.PadDef[0].KeyDef[DKEY_L2].J.Button = 4;
68         g.cfg.PadDef[0].KeyDef[DKEY_L1].JoyEvType = BUTTON;
69         g.cfg.PadDef[0].KeyDef[DKEY_L1].J.Button = 6;
70         g.cfg.PadDef[0].KeyDef[DKEY_R2].JoyEvType = BUTTON;
71         g.cfg.PadDef[0].KeyDef[DKEY_R2].J.Button = 5;
72         g.cfg.PadDef[0].KeyDef[DKEY_R1].JoyEvType = BUTTON;
73         g.cfg.PadDef[0].KeyDef[DKEY_R1].J.Button = 7;
74         g.cfg.PadDef[0].KeyDef[DKEY_TRIANGLE].JoyEvType = BUTTON;
75         g.cfg.PadDef[0].KeyDef[DKEY_TRIANGLE].J.Button = 0;
76         g.cfg.PadDef[0].KeyDef[DKEY_CIRCLE].JoyEvType = BUTTON;
77         g.cfg.PadDef[0].KeyDef[DKEY_CIRCLE].J.Button = 1;
78         g.cfg.PadDef[0].KeyDef[DKEY_CROSS].JoyEvType = BUTTON;
79         g.cfg.PadDef[0].KeyDef[DKEY_CROSS].J.Button = 2;
80         g.cfg.PadDef[0].KeyDef[DKEY_SQUARE].JoyEvType = BUTTON;
81         g.cfg.PadDef[0].KeyDef[DKEY_SQUARE].J.Button = 3;
82
83         // Pad2 joystick
84         g.cfg.PadDef[1].KeyDef[DKEY_SELECT].JoyEvType = BUTTON;
85         g.cfg.PadDef[1].KeyDef[DKEY_SELECT].J.Button = 8;
86         g.cfg.PadDef[1].KeyDef[DKEY_START].JoyEvType = BUTTON;
87         g.cfg.PadDef[1].KeyDef[DKEY_START].J.Button = 9;
88         g.cfg.PadDef[1].KeyDef[DKEY_UP].JoyEvType = AXIS;
89         g.cfg.PadDef[1].KeyDef[DKEY_UP].J.Axis = -2;
90         g.cfg.PadDef[1].KeyDef[DKEY_RIGHT].JoyEvType = AXIS;
91         g.cfg.PadDef[1].KeyDef[DKEY_RIGHT].J.Axis = 1;
92         g.cfg.PadDef[1].KeyDef[DKEY_DOWN].JoyEvType = AXIS;
93         g.cfg.PadDef[1].KeyDef[DKEY_DOWN].J.Axis = 2;
94         g.cfg.PadDef[1].KeyDef[DKEY_LEFT].JoyEvType = AXIS;
95         g.cfg.PadDef[1].KeyDef[DKEY_LEFT].J.Axis = -1;
96         g.cfg.PadDef[1].KeyDef[DKEY_L2].JoyEvType = BUTTON;
97         g.cfg.PadDef[1].KeyDef[DKEY_L2].J.Button = 4;
98         g.cfg.PadDef[1].KeyDef[DKEY_L1].JoyEvType = BUTTON;
99         g.cfg.PadDef[1].KeyDef[DKEY_L1].J.Button = 6;
100         g.cfg.PadDef[1].KeyDef[DKEY_R2].JoyEvType = BUTTON;
101         g.cfg.PadDef[1].KeyDef[DKEY_R2].J.Button = 5;
102         g.cfg.PadDef[1].KeyDef[DKEY_R1].JoyEvType = BUTTON;
103         g.cfg.PadDef[1].KeyDef[DKEY_R1].J.Button = 7;
104         g.cfg.PadDef[1].KeyDef[DKEY_TRIANGLE].JoyEvType = BUTTON;
105         g.cfg.PadDef[1].KeyDef[DKEY_TRIANGLE].J.Button = 0;
106         g.cfg.PadDef[1].KeyDef[DKEY_CIRCLE].JoyEvType = BUTTON;
107         g.cfg.PadDef[1].KeyDef[DKEY_CIRCLE].J.Button = 1;
108         g.cfg.PadDef[1].KeyDef[DKEY_CROSS].JoyEvType = BUTTON;
109         g.cfg.PadDef[1].KeyDef[DKEY_CROSS].J.Button = 2;
110         g.cfg.PadDef[1].KeyDef[DKEY_SQUARE].JoyEvType = BUTTON;
111         g.cfg.PadDef[1].KeyDef[DKEY_SQUARE].J.Button = 3;
112 }
113
114 void LoadPADConfig() {
115         FILE            *fp;
116         char            buf[256];
117         int                     current, a, b, c;
118
119         SetDefaultConfig();
120
121         sprintf(buf, "%s/Library/Preferences/net.pcsx.DFInput.plist", getenv("HOME"));
122
123         fp = fopen(buf, "r");
124         if (fp == NULL) {
125                 return;
126         }
127
128         current = 0;
129
130         while (fgets(buf, 256, fp) != NULL) {
131                 if (strncmp(buf, "Threaded=", 9) == 0) {
132                         g.cfg.Threaded = atoi(&buf[9]);
133                 } else if (strncmp(buf, "[PAD", 4) == 0) {
134                         current = atoi(&buf[4]) - 1;
135                         if (current < 0) {
136                                 current = 0;
137                         } else if (current > 1) {
138                                 current = 1;
139                         }
140                 } else if (strncmp(buf, "DevNum=", 7) == 0) {
141                         g.cfg.PadDef[current].DevNum = atoi(&buf[7]);
142                 } else if (strncmp(buf, "Type=", 5) == 0) {
143                         g.cfg.PadDef[current].Type = atoi(&buf[5]);
144                 } else if (strncmp(buf, "Select=", 7) == 0) {
145                         sscanf(buf, "Select=%d,%d,%d", &a, &b, &c);
146                         g.cfg.PadDef[current].KeyDef[DKEY_SELECT].Key = a;
147                         g.cfg.PadDef[current].KeyDef[DKEY_SELECT].JoyEvType = b;
148                         g.cfg.PadDef[current].KeyDef[DKEY_SELECT].J.d = c;
149                 } else if (strncmp(buf, "L3=", 3) == 0) {
150                         sscanf(buf, "L3=%d,%d,%d", &a, &b, &c);
151                         g.cfg.PadDef[current].KeyDef[DKEY_L3].Key = a;
152                         g.cfg.PadDef[current].KeyDef[DKEY_L3].JoyEvType = b;
153                         g.cfg.PadDef[current].KeyDef[DKEY_L3].J.d = c;
154                 } else if (strncmp(buf, "R3=", 3) == 0) {
155                         sscanf(buf, "R3=%d,%d,%d", &a, &b, &c);
156                         g.cfg.PadDef[current].KeyDef[DKEY_R3].Key = a;
157                         g.cfg.PadDef[current].KeyDef[DKEY_R3].JoyEvType = b;
158                         g.cfg.PadDef[current].KeyDef[DKEY_R3].J.d = c;
159                 } else if (strncmp(buf, "Start=", 6) == 0) {
160                         sscanf(buf, "Start=%d,%d,%d", &a, &b, &c);
161                         g.cfg.PadDef[current].KeyDef[DKEY_START].Key = a;
162                         g.cfg.PadDef[current].KeyDef[DKEY_START].JoyEvType = b;
163                         g.cfg.PadDef[current].KeyDef[DKEY_START].J.d = c;
164                 } else if (strncmp(buf, "Up=", 3) == 0) {
165                         sscanf(buf, "Up=%d,%d,%d", &a, &b, &c);
166                         g.cfg.PadDef[current].KeyDef[DKEY_UP].Key = a;
167                         g.cfg.PadDef[current].KeyDef[DKEY_UP].JoyEvType = b;
168                         g.cfg.PadDef[current].KeyDef[DKEY_UP].J.d = c;
169                 } else if (strncmp(buf, "Right=", 6) == 0) {
170                         sscanf(buf, "Right=%d,%d,%d", &a, &b, &c);
171                         g.cfg.PadDef[current].KeyDef[DKEY_RIGHT].Key = a;
172                         g.cfg.PadDef[current].KeyDef[DKEY_RIGHT].JoyEvType = b;
173                         g.cfg.PadDef[current].KeyDef[DKEY_RIGHT].J.d = c;
174                 } else if (strncmp(buf, "Down=", 5) == 0) {
175                         sscanf(buf, "Down=%d,%d,%d", &a, &b, &c);
176                         g.cfg.PadDef[current].KeyDef[DKEY_DOWN].Key = a;
177                         g.cfg.PadDef[current].KeyDef[DKEY_DOWN].JoyEvType = b;
178                         g.cfg.PadDef[current].KeyDef[DKEY_DOWN].J.d = c;
179                 } else if (strncmp(buf, "Left=", 5) == 0) {
180                         sscanf(buf, "Left=%d,%d,%d", &a, &b, &c);
181                         g.cfg.PadDef[current].KeyDef[DKEY_LEFT].Key = a;
182                         g.cfg.PadDef[current].KeyDef[DKEY_LEFT].JoyEvType = b;
183                         g.cfg.PadDef[current].KeyDef[DKEY_LEFT].J.d = c;
184                 } else if (strncmp(buf, "L2=", 3) == 0) {
185                         sscanf(buf, "L2=%d,%d,%d", &a, &b, &c);
186                         g.cfg.PadDef[current].KeyDef[DKEY_L2].Key = a;
187                         g.cfg.PadDef[current].KeyDef[DKEY_L2].JoyEvType = b;
188                         g.cfg.PadDef[current].KeyDef[DKEY_L2].J.d = c;
189                 } else if (strncmp(buf, "R2=", 3) == 0) {
190                         sscanf(buf, "R2=%d,%d,%d", &a, &b, &c);
191                         g.cfg.PadDef[current].KeyDef[DKEY_R2].Key = a;
192                         g.cfg.PadDef[current].KeyDef[DKEY_R2].JoyEvType = b;
193                         g.cfg.PadDef[current].KeyDef[DKEY_R2].J.d = c;
194                 } else if (strncmp(buf, "L1=", 3) == 0) {
195                         sscanf(buf, "L1=%d,%d,%d", &a, &b, &c);
196                         g.cfg.PadDef[current].KeyDef[DKEY_L1].Key = a;
197                         g.cfg.PadDef[current].KeyDef[DKEY_L1].JoyEvType = b;
198                         g.cfg.PadDef[current].KeyDef[DKEY_L1].J.d = c;
199                 } else if (strncmp(buf, "R1=", 3) == 0) {
200                         sscanf(buf, "R1=%d,%d,%d", &a, &b, &c);
201                         g.cfg.PadDef[current].KeyDef[DKEY_R1].Key = a;
202                         g.cfg.PadDef[current].KeyDef[DKEY_R1].JoyEvType = b;
203                         g.cfg.PadDef[current].KeyDef[DKEY_R1].J.d = c;
204                 } else if (strncmp(buf, "Triangle=", 9) == 0) {
205                         sscanf(buf, "Triangle=%d,%d,%d", &a, &b, &c);
206                         g.cfg.PadDef[current].KeyDef[DKEY_TRIANGLE].Key = a;
207                         g.cfg.PadDef[current].KeyDef[DKEY_TRIANGLE].JoyEvType = b;
208                         g.cfg.PadDef[current].KeyDef[DKEY_TRIANGLE].J.d = c;
209                 } else if (strncmp(buf, "Circle=", 7) == 0) {
210                         sscanf(buf, "Circle=%d,%d,%d", &a, &b, &c);
211                         g.cfg.PadDef[current].KeyDef[DKEY_CIRCLE].Key = a;
212                         g.cfg.PadDef[current].KeyDef[DKEY_CIRCLE].JoyEvType = b;
213                         g.cfg.PadDef[current].KeyDef[DKEY_CIRCLE].J.d = c;
214                 } else if (strncmp(buf, "Cross=", 6) == 0) {
215                         sscanf(buf, "Cross=%d,%d,%d", &a, &b, &c);
216                         g.cfg.PadDef[current].KeyDef[DKEY_CROSS].Key = a;
217                         g.cfg.PadDef[current].KeyDef[DKEY_CROSS].JoyEvType = b;
218                         g.cfg.PadDef[current].KeyDef[DKEY_CROSS].J.d = c;
219                 } else if (strncmp(buf, "Square=", 7) == 0) {
220                         sscanf(buf, "Square=%d,%d,%d", &a, &b, &c);
221                         g.cfg.PadDef[current].KeyDef[DKEY_SQUARE].Key = a;
222                         g.cfg.PadDef[current].KeyDef[DKEY_SQUARE].JoyEvType = b;
223                         g.cfg.PadDef[current].KeyDef[DKEY_SQUARE].J.d = c;
224                 } else if (strncmp(buf, "LeftAnalogXP=", 13) == 0) {
225                         sscanf(buf, "LeftAnalogXP=%d,%d,%d", &a, &b, &c);
226                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XP].Key = a;
227                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XP].JoyEvType = b;
228                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XP].J.d = c;
229                 } else if (strncmp(buf, "LeftAnalogXM=", 13) == 0) {
230                         sscanf(buf, "LeftAnalogXM=%d,%d,%d", &a, &b, &c);
231                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XM].Key = a;
232                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XM].JoyEvType = b;
233                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_XM].J.d = c;
234                 } else if (strncmp(buf, "LeftAnalogYP=", 13) == 0) {
235                         sscanf(buf, "LeftAnalogYP=%d,%d,%d", &a, &b, &c);
236                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YP].Key = a;
237                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YP].JoyEvType = b;
238                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YP].J.d = c;
239                 } else if (strncmp(buf, "LeftAnalogYM=", 13) == 0) {
240                         sscanf(buf, "LeftAnalogYM=%d,%d,%d", &a, &b, &c);
241                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YM].Key = a;
242                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YM].JoyEvType = b;
243                         g.cfg.PadDef[current].AnalogDef[ANALOG_LEFT][ANALOG_YM].J.d = c;
244                 } else if (strncmp(buf, "RightAnalogXP=", 14) == 0) {
245                         sscanf(buf, "RightAnalogXP=%d,%d,%d", &a, &b, &c);
246                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XP].Key = a;
247                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XP].JoyEvType = b;
248                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XP].J.d = c;
249                 } else if (strncmp(buf, "RightAnalogXM=", 14) == 0) {
250                         sscanf(buf, "RightAnalogXM=%d,%d,%d", &a, &b, &c);
251                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XM].Key = a;
252                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XM].JoyEvType = b;
253                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_XM].J.d = c;
254                 } else if (strncmp(buf, "RightAnalogYP=", 14) == 0) {
255                         sscanf(buf, "RightAnalogYP=%d,%d,%d", &a, &b, &c);
256                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YP].Key = a;
257                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YP].JoyEvType = b;
258                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YP].J.d = c;
259                 } else if (strncmp(buf, "RightAnalogYM=", 14) == 0) {
260                         sscanf(buf, "RightAnalogYM=%d,%d,%d", &a, &b, &c);
261                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YM].Key = a;
262                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YM].JoyEvType = b;
263                         g.cfg.PadDef[current].AnalogDef[ANALOG_RIGHT][ANALOG_YM].J.d = c;
264                 }
265         }
266
267         fclose(fp);
268 }
269
270 void SavePADConfig() {
271         FILE            *fp;
272         int                     i;
273         char            buf[256];
274
275         sprintf(buf, "%s/Library/Preferences/net.pcsx.DFInput.plist", getenv("HOME"));
276
277         fp = fopen(buf, "w");
278         if (fp == NULL) {
279                 return;
280         }
281
282         fprintf(fp, "[CONFIG]\n");
283         fprintf(fp, "Threaded=%d\n", g.cfg.Threaded);
284         fprintf(fp, "\n");
285
286         for (i = 0; i < 2; i++) {
287                 fprintf(fp, "[PAD%d]\n", i + 1);
288                 fprintf(fp, "DevNum=%d\n", g.cfg.PadDef[i].DevNum);
289                 fprintf(fp, "Type=%d\n", g.cfg.PadDef[i].Type);
290
291                 fprintf(fp, "Select=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_SELECT].Key,
292                         g.cfg.PadDef[i].KeyDef[DKEY_SELECT].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_SELECT].J.d);
293                 fprintf(fp, "L3=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_L3].Key,
294                         g.cfg.PadDef[i].KeyDef[DKEY_L3].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_L3].J.d);
295                 fprintf(fp, "R3=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_R3].Key,
296                         g.cfg.PadDef[i].KeyDef[DKEY_R3].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_R3].J.d);
297                 fprintf(fp, "Start=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_START].Key,
298                         g.cfg.PadDef[i].KeyDef[DKEY_START].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_START].J.d);
299                 fprintf(fp, "Up=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_UP].Key,
300                         g.cfg.PadDef[i].KeyDef[DKEY_UP].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_UP].J.d);
301                 fprintf(fp, "Right=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_RIGHT].Key,
302                         g.cfg.PadDef[i].KeyDef[DKEY_RIGHT].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_RIGHT].J.d);
303                 fprintf(fp, "Down=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_DOWN].Key,
304                         g.cfg.PadDef[i].KeyDef[DKEY_DOWN].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_DOWN].J.d);
305                 fprintf(fp, "Left=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_LEFT].Key,
306                         g.cfg.PadDef[i].KeyDef[DKEY_LEFT].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_LEFT].J.d);
307                 fprintf(fp, "L2=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_L2].Key,
308                         g.cfg.PadDef[i].KeyDef[DKEY_L2].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_L2].J.d);
309                 fprintf(fp, "R2=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_R2].Key,
310                         g.cfg.PadDef[i].KeyDef[DKEY_R2].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_R2].J.d);
311                 fprintf(fp, "L1=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_L1].Key,
312                         g.cfg.PadDef[i].KeyDef[DKEY_L1].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_L1].J.d);
313                 fprintf(fp, "R1=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_R1].Key,
314                         g.cfg.PadDef[i].KeyDef[DKEY_R1].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_R1].J.d);
315                 fprintf(fp, "Triangle=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_TRIANGLE].Key,
316                         g.cfg.PadDef[i].KeyDef[DKEY_TRIANGLE].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_TRIANGLE].J.d);
317                 fprintf(fp, "Circle=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_CIRCLE].Key,
318                         g.cfg.PadDef[i].KeyDef[DKEY_CIRCLE].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_CIRCLE].J.d);
319                 fprintf(fp, "Cross=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_CROSS].Key,
320                         g.cfg.PadDef[i].KeyDef[DKEY_CROSS].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_CROSS].J.d);
321                 fprintf(fp, "Square=%d,%d,%d\n", g.cfg.PadDef[i].KeyDef[DKEY_SQUARE].Key,
322                         g.cfg.PadDef[i].KeyDef[DKEY_SQUARE].JoyEvType, g.cfg.PadDef[i].KeyDef[DKEY_SQUARE].J.d);
323                 fprintf(fp, "LeftAnalogXP=%d,%d,%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_XP].Key,
324                         g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_XP].JoyEvType,
325                         g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_XP].J.d);
326                 fprintf(fp, "LeftAnalogXM=%d,%d,%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_XM].Key,
327                         g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_XM].JoyEvType,
328                         g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_XM].J.d);
329                 fprintf(fp, "LeftAnalogYP=%d,%d,%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_YP].Key,
330                         g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_YP].JoyEvType,
331                         g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_YP].J.d);
332                 fprintf(fp, "LeftAnalogYM=%d,%d,%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_YM].Key,
333                         g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_YM].JoyEvType,
334                         g.cfg.PadDef[i].AnalogDef[ANALOG_LEFT][ANALOG_YM].J.d);
335                 fprintf(fp, "RightAnalogXP=%d,%d,%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_XP].Key,
336                         g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_XP].JoyEvType,
337                         g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_XP].J.d);
338                 fprintf(fp, "RightAnalogXM=%d,%d,%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_XM].Key,
339                         g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_XM].JoyEvType,
340                         g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_XM].J.d);
341                 fprintf(fp, "RightAnalogYP=%d,%d,%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_YP].Key,
342                         g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_YP].JoyEvType,
343                         g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_YP].J.d);
344                 fprintf(fp, "RightAnalogYM=%d,%d,%d\n", g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_YM].Key,
345                         g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_YM].JoyEvType,
346                         g.cfg.PadDef[i].AnalogDef[ANALOG_RIGHT][ANALOG_YM].J.d);
347
348                 fprintf(fp, "\n");
349         }
350
351         fclose(fp);
352 }
353
354 long PADconfigure(void) {
355         if (SDL_WasInit(SDL_INIT_JOYSTICK)) return -1; // cannot change settings on the fly
356
357         DoConfiguration();
358         LoadPADConfig();
359         return 0;
360 }
361
362 void PADabout(void) {
363         DoAbout();
364 }
365
366 struct {
367         uint16_t code;
368         const char *desc;
369 } KeyString[] = {
370         { 0x01, "A" },
371         { 0x0C, "B" },
372         { 0x09, "C" },
373         { 0x03, "D" },
374         { 0x0F, "E" },
375         { 0x04, "F" },
376         { 0x06, "G" },
377         { 0x05, "H" },
378         { 0x23, "I" },
379         { 0x27, "J" },
380         { 0x29, "K" },
381         { 0x26, "L" },
382         { 0x2F, "M" },
383         { 0x2E, "N" },
384         { 0x20, "O" },
385         { 0x24, "P" },
386         { 0x0D, "Q" },
387         { 0x10, "R" },
388         { 0x02, "S" },
389         { 0x12, "T" },
390         { 0x21, "U" },
391         { 0x0A, "V" },
392         { 0x0E, "W" },
393         { 0x08, "X" },
394         { 0x11, "Y" },
395         { 0x07, "Z" },
396         { 0x22, "[" },
397         { 0x1F, "]" },
398         { 0x2A, ";" },
399         { 0x28, "'" },
400         { 0x2C, "," },
401         { 0x30, "." },
402         { 0x2D, "/" },
403         { 0x33, "`" },
404         { 0x13, "1" },
405         { 0x14, "2" },
406         { 0x15, "3" },
407         { 0x16, "4" },
408         { 0x18, "5" },
409         { 0x17, "6" },
410         { 0x1B, "7" },
411         { 0x1D, "8" },
412         { 0x1A, "9" },
413         { 0x1E, "0" },
414         { 0x1C, "-" },
415         { 0x19, "=" },
416         { 0x2B, "\\" },
417         { 0x31, "Tab" },
418         { 0x39, "Shift" },
419         { 0x3C, "Control" },
420         { 0x38, "Command" },
421         { 0x32, "Spacebar" },
422         { 0x34, "Backspace" },
423         { 0x25, "Enter" },
424         { 0x7F, "Up" },
425         { 0x7E, "Down" },
426         { 0x7C, "Left" },
427         { 0x7D, "Right" },
428         { 0x73, "Insert" },
429         { 0x76, "Delete" },
430         { 0x74, "Home" },
431         { 0x78, "End" },
432         { 0x75, "Page Up" },
433         { 0x7A, "Page Down" },
434         { 0x48, "Num Lock" },
435         { 0x4C, "Keypad /" },
436         { 0x44, "Keypad *" },
437         { 0x4F, "Keypad -" },
438         { 0x46, "Keypad +" },
439         { 0x4D, "Keypad Enter" },
440         { 0x53, "Keypad 0" },
441         { 0x54, "Keypad 1" },
442         { 0x55, "Keypad 2" },
443         { 0x56, "Keypad 3" },
444         { 0x57, "Keypad 4" },
445         { 0x58, "Keypad 5" },
446         { 0x59, "Keypad 6" },
447         { 0x5A, "Keypad 7" },
448         { 0x5C, "Keypad 8" },
449         { 0x5D, "Keypad 9" },
450         { 0x42, "Keypad ." },
451         { 0x00, NULL }
452 };
453
454 static const char *XKeysymToString(uint16_t key) {
455         static char buf[64];
456         int i = 0;
457
458         while (KeyString[i].code != 0) {
459                 if (KeyString[i].code == key) {
460                         strcpy(buf, KeyString[i].desc);
461                         return buf;
462                 }
463                 i++;
464         }
465
466         sprintf(buf, "0x%.2X", key);
467         return buf;
468 }
469
470 void GetKeyDescription(char *buf, int joynum, int key) {
471         const char *hatname[16] = {"Centered", "Up", "Right", "Rightup",
472                 "Down", "", "Rightdown", "", "Left", "Leftup", "", "",
473                 "Leftdown", "", "", ""};
474
475         switch (g.cfg.PadDef[joynum].KeyDef[key].JoyEvType) {
476                 case BUTTON:
477                         sprintf(buf, "Joystick: Button %d", g.cfg.PadDef[joynum].KeyDef[key].J.Button);
478                         break;
479
480                 case AXIS:
481                         sprintf(buf, "Joystick: Axis %d%c", abs(g.cfg.PadDef[joynum].KeyDef[key].J.Axis) - 1,
482                                 g.cfg.PadDef[joynum].KeyDef[key].J.Axis > 0 ? '+' : '-');
483                         break;
484
485                 case HAT:
486                         sprintf(buf, "Joystick: Hat %d %s", (g.cfg.PadDef[joynum].KeyDef[key].J.Hat >> 8),
487                                 hatname[g.cfg.PadDef[joynum].KeyDef[key].J.Hat & 0x0F]);
488                         break;
489
490                 case NONE:
491                 default:
492                         buf[0] = '\0';
493                         break;
494         }
495
496         if (g.cfg.PadDef[joynum].KeyDef[key].Key != 0) {
497                 if (buf[0] != '\0') {
498                         strcat(buf, " / ");
499                 }
500
501                 strcat(buf, "Keyboard:");
502                 strcat(buf, " ");
503                 strcat(buf, XKeysymToString(g.cfg.PadDef[joynum].KeyDef[key].Key));
504         }
505 }
506
507 void GetAnalogDescription(char *buf, int joynum, int analognum, int dir) {
508         const char *hatname[16] = {"Centered", "Up", "Right", "Rightup",
509                 "Down", "", "Rightdown", "", "Left", "Leftup", "", "",
510                 "Leftdown", "", "", ""};
511
512         switch (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].JoyEvType) {
513                 case BUTTON:
514                         sprintf(buf, "Joystick: Button %d", g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Button);
515                         break;
516
517                 case AXIS:
518                         sprintf(buf, "Joystick: Axis %d%c", abs(g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Axis) - 1,
519                                 g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Axis > 0 ? '+' : '-');
520                         break;
521
522                 case HAT:
523                         sprintf(buf, "Joystick: Hat %d %s", (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Hat >> 8),
524                                 hatname[g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Hat & 0x0F]);
525                         break;
526
527                 case NONE:
528                 default:
529                         buf[0] = '\0';
530                         break;
531         }
532
533         if (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].Key != 0) {
534                 if (buf[0] != '\0') {
535                         strcat(buf, " / ");
536                 }
537
538                 strcat(buf, "Keyboard:");
539                 strcat(buf, " ");
540                 strcat(buf, XKeysymToString(g.cfg.PadDef[joynum].AnalogDef[analognum][dir].Key));
541         }
542 }
543
544 int CheckKeyDown() {
545         KeyMap theKeys;
546         unsigned char *keybytes;
547         int i;
548
549         GetKeys(theKeys);
550         keybytes = (unsigned char *) theKeys;
551
552         for (i = 0; i < 128; i++) {
553                 if (i == 0x3A) continue; // Ignore capslock
554
555                 if (keybytes[i >> 3] & (1 << (i & 7)))
556                         return i + 1;
557         }
558
559         return 0;
560 }
561
562 static Sint16 InitialAxisPos[256], PrevAxisPos[256];
563
564 #define NUM_AXES(js) (SDL_JoystickNumAxes(js) > 256 ? 256 : SDL_JoystickNumAxes(js))
565
566 void InitAxisPos(int padnum) {
567         int i;
568         SDL_Joystick *js;
569
570         if (g.cfg.PadDef[padnum].DevNum >= 0) {
571                 js = SDL_JoystickOpen(g.cfg.PadDef[padnum].DevNum);
572                 SDL_JoystickEventState(SDL_IGNORE);
573         } else return;
574
575         SDL_JoystickUpdate();
576
577         for (i = 0; i < NUM_AXES(js); i++) {
578                 InitialAxisPos[i] = PrevAxisPos[i] = SDL_JoystickGetAxis(js, i);
579         }
580
581         SDL_JoystickClose(js);
582 }
583
584 int ReadDKeyEvent(int padnum, int key) {
585         SDL_Joystick *js;
586         int i, changed = 0, t;
587         Sint16 axis;
588
589         if (g.cfg.PadDef[padnum].DevNum >= 0) {
590                 js = SDL_JoystickOpen(g.cfg.PadDef[padnum].DevNum);
591                 SDL_JoystickEventState(SDL_IGNORE);
592         } else {
593                 js = NULL;
594         }
595
596         for (t = 0; t < 1000000 / 1000; t++) {
597                 // check joystick events
598                 if (js != NULL) {
599                         SDL_JoystickUpdate();
600
601                         for (i = 0; i < SDL_JoystickNumButtons(js); i++) {
602                                 if (SDL_JoystickGetButton(js, i)) {
603                                         g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = BUTTON;
604                                         g.cfg.PadDef[padnum].KeyDef[key].J.Button = i;
605                                         changed = 1;
606                                         goto end;
607                                 }
608                         }
609
610                         for (i = 0; i < NUM_AXES(js); i++) {
611                                 axis = SDL_JoystickGetAxis(js, i);
612                                 if (abs(axis) > 16383 && (abs(axis - PrevAxisPos[i]) > 4096 || abs(axis - InitialAxisPos[i]) > 4096)) {
613                                         g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = AXIS;
614                                         g.cfg.PadDef[padnum].KeyDef[key].J.Axis = (i + 1) * (axis > 0 ? 1 : -1);
615                                         changed = 1;
616                                         goto end;
617                                 }
618                                 PrevAxisPos[i] = axis;
619                         }
620
621                         for (i = 0; i < SDL_JoystickNumHats(js); i++) {
622                                 axis = SDL_JoystickGetHat(js, i);
623                                 if (axis != SDL_HAT_CENTERED) {
624                                         g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = HAT;
625
626                                         if (axis & SDL_HAT_UP) {
627                                                 g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_UP);
628                                         } else if (axis & SDL_HAT_DOWN) {
629                                                 g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_DOWN);
630                                         } else if (axis & SDL_HAT_LEFT) {
631                                                 g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_LEFT);
632                                         } else if (axis & SDL_HAT_RIGHT) {
633                                                 g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_RIGHT);
634                                         }
635
636                                         changed = 1;
637                                         goto end;
638                                 }
639                         }
640                 }
641
642                 // check keyboard events
643                 i = CheckKeyDown();
644                 if (i != 0) {
645                         if (i != 0x36) g.cfg.PadDef[padnum].KeyDef[key].Key = i;
646                         changed = 1;
647                         goto end;
648                 }
649
650                 // check mouse events
651                 if (Button()) {
652                         changed = 2;
653                         goto end;
654                 }
655
656                 usleep(1000);
657         }
658
659 end:
660         if (js != NULL) {
661                 SDL_JoystickClose(js);
662         }
663
664         return changed;
665 }
666
667 int ReadAnalogEvent(int padnum, int analognum, int analogdir) {
668         SDL_Joystick *js;
669         int i, changed = 0, t;
670         Sint16 axis;
671
672         if (g.cfg.PadDef[padnum].DevNum >= 0) {
673                 js = SDL_JoystickOpen(g.cfg.PadDef[padnum].DevNum);
674                 SDL_JoystickEventState(SDL_IGNORE);
675         } else {
676                 js = NULL;
677         }
678
679         for (t = 0; t < 1000000 / 1000; t++) {
680                 // check joystick events
681                 if (js != NULL) {
682                         SDL_JoystickUpdate();
683
684                         for (i = 0; i < SDL_JoystickNumButtons(js); i++) {
685                                 if (SDL_JoystickGetButton(js, i)) {
686                                         g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = BUTTON;
687                                         g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Button = i;
688                                         changed = 1;
689                                         goto end;
690                                 }
691                         }
692
693                         for (i = 0; i < NUM_AXES(js); i++) {
694                                 axis = SDL_JoystickGetAxis(js, i);
695                                 if (abs(axis) > 16383 && (abs(axis - PrevAxisPos[i]) > 4096 || abs(axis - InitialAxisPos[i]) > 4096)) {
696                                         g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = AXIS;
697                                         g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Axis = (i + 1) * (axis > 0 ? 1 : -1);
698                                         changed = 1;
699                                         goto end;
700                                 }
701                                 PrevAxisPos[i] = axis;
702                         }
703
704                         for (i = 0; i < SDL_JoystickNumHats(js); i++) {
705                                 axis = SDL_JoystickGetHat(js, i);
706                                 if (axis != SDL_HAT_CENTERED) {
707                                         g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = HAT;
708
709                                         if (axis & SDL_HAT_UP) {
710                                                 g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_UP);
711                                         } else if (axis & SDL_HAT_DOWN) {
712                                                 g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_DOWN);
713                                         } else if (axis & SDL_HAT_LEFT) {
714                                                 g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_LEFT);
715                                         } else if (axis & SDL_HAT_RIGHT) {
716                                                 g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_RIGHT);
717                                         }
718
719                                         changed = 1;
720                                         goto end;
721                                 }
722                         }
723                 }
724
725                 // check keyboard events
726                 i = CheckKeyDown();
727                 if (i != 0) {
728                         if (i != 0x36) g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].Key = i;
729                         changed = 1;
730                         goto end;
731                 }
732
733                 // check mouse events
734                 if (Button()) {
735                         changed = 2;
736                         goto end;
737                 }
738
739                 usleep(1000);
740         }
741
742 end:
743         if (js != NULL) {
744                 SDL_JoystickClose(js);
745         }
746
747         return changed;
748 }