~random-stuff/random-stuff/snes9x-OLD

1 by OV2
Initial 1.52 import
1
/***********************************************************************************
2
  Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
4
  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
                             Jerremy Koot (jkoot@snes9x.com)
6
7
  (c) Copyright 2002 - 2004  Matthew Kendora
8
9
  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
11
  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
13
  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
15
  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
                             Kris Bleakley (codeviolation@hotmail.com)
17
18
  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
                             Nach (n-a-c-h@users.sourceforge.net),
87 by OV2
Update copyright in all files
20
21
  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
1 by OV2
Initial 1.52 import
22
23
  (c) Copyright 2006 - 2007  nitsuja
24
290 by Brandon Wright
Update some copyrights, bump version number.
25
  (c) Copyright 2009 - 2016  BearOso,
1 by OV2
Initial 1.52 import
26
                             OV2
27
28
29
  BS-X C emulator code
30
  (c) Copyright 2005 - 2006  Dreamer Nom,
31
                             zones
32
33
  C4 x86 assembler and some C emulation code
34
  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
                             Nach,
36
                             zsKnight (zsknight@zsnes.com)
37
38
  C4 C++ code
39
  (c) Copyright 2003 - 2006  Brad Jorsch,
40
                             Nach
41
42
  DSP-1 emulator code
43
  (c) Copyright 1998 - 2006  _Demo_,
44
                             Andreas Naive (andreasnaive@gmail.com),
45
                             Gary Henderson,
46
                             Ivar (ivar@snes9x.com),
47
                             John Weidman,
48
                             Kris Bleakley,
49
                             Matthew Kendora,
50
                             Nach,
51
                             neviksti (neviksti@hotmail.com)
52
53
  DSP-2 emulator code
54
  (c) Copyright 2003         John Weidman,
55
                             Kris Bleakley,
56
                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
                             Matthew Kendora,
58
                             neviksti
59
60
  DSP-3 emulator code
61
  (c) Copyright 2003 - 2006  John Weidman,
62
                             Kris Bleakley,
63
                             Lancer,
64
                             z80 gaiden
65
66
  DSP-4 emulator code
67
  (c) Copyright 2004 - 2006  Dreamer Nom,
68
                             John Weidman,
69
                             Kris Bleakley,
70
                             Nach,
71
                             z80 gaiden
72
73
  OBC1 emulator code
74
  (c) Copyright 2001 - 2004  zsKnight,
75
                             pagefault (pagefault@zsnes.com),
76
                             Kris Bleakley
77
                             Ported from x86 assembler to C by sanmaiwashi
78
79
  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
  (c) Copyright 2002         Matthew Kendora with research by
81
                             zsKnight,
82
                             John Weidman,
83
                             Dark Force
84
85
  SPC7110 and RTC C++ emulator code used in 1.52+
86
  (c) Copyright 2009         byuu,
87
                             neviksti
88
89
  S-DD1 C emulator code
90
  (c) Copyright 2003         Brad Jorsch with research by
91
                             Andreas Naive,
92
                             John Weidman
93
94
  S-RTC C emulator code
95
  (c) Copyright 2001 - 2006  byuu,
96
                             John Weidman
97
98
  ST010 C++ emulator code
99
  (c) Copyright 2003         Feather,
100
                             John Weidman,
101
                             Kris Bleakley,
102
                             Matthew Kendora
103
104
  Super FX x86 assembler emulator code
105
  (c) Copyright 1998 - 2003  _Demo_,
106
                             pagefault,
107
                             zsKnight
108
109
  Super FX C emulator code
110
  (c) Copyright 1997 - 1999  Ivar,
111
                             Gary Henderson,
112
                             John Weidman
113
114
  Sound emulator code used in 1.5-1.51
115
  (c) Copyright 1998 - 2003  Brad Martin
116
  (c) Copyright 1998 - 2006  Charles Bilyue'
117
118
  Sound emulator code used in 1.52+
119
  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
295 by Brandon Wright
Add byuu copyright for his S-SMP
121
  S-SMP emulator code used in 1.54+
122
  (c) Copyright 2016         byuu
123
1 by OV2
Initial 1.52 import
124
  SH assembler code partly based on x86 assembler code
125
  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
126
127
  2xSaI filter
128
  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
129
130
  HQ2x, HQ3x, HQ4x filters
131
  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
132
133
  NTSC filter
134
  (c) Copyright 2006 - 2007  Shay Green
135
136
  GTK+ GUI code
290 by Brandon Wright
Update some copyrights, bump version number.
137
  (c) Copyright 2004 - 2016  BearOso
1 by OV2
Initial 1.52 import
138
139
  Win32 GUI code
140
  (c) Copyright 2003 - 2006  blip,
141
                             funkyass,
142
                             Matthew Kendora,
143
                             Nach,
144
                             nitsuja
298 by Brandon Wright
Bump OV2 Windows port copyright.
145
  (c) Copyright 2009 - 2016  OV2
1 by OV2
Initial 1.52 import
146
147
  Mac OS GUI code
148
  (c) Copyright 1998 - 2001  John Stiles
87 by OV2
Update copyright in all files
149
  (c) Copyright 2001 - 2011  zones
1 by OV2
Initial 1.52 import
150
151
152
  Specific ports contains the works of other authors. See headers in
153
  individual files.
154
155
156
  Snes9x homepage: http://www.snes9x.com/
157
158
  Permission to use, copy, modify and/or distribute Snes9x in both binary
159
  and source form, for non-commercial purposes, is hereby granted without
160
  fee, providing that this license information and copyright notice appear
161
  with all copies and any derived work.
162
163
  This software is provided 'as-is', without any express or implied
164
  warranty. In no event shall the authors be held liable for any damages
165
  arising from the use of this software or it's derivatives.
166
167
  Snes9x is freeware for PERSONAL USE only. Commercial users should
168
  seek permission of the copyright holders first. Commercial use includes,
169
  but is not limited to, charging money for Snes9x or software derived from
170
  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
171
  using Snes9x as a promotion for your commercial product.
172
173
  The copyright holders request that bug fixes and improvements to the code
174
  should be forwarded to them so everyone can benefit from the modifications
175
  in future versions.
176
177
  Super NES and Super Nintendo Entertainment System are trademarks of
178
  Nintendo Co., Limited and its subsidiary companies.
179
 ***********************************************************************************/
180
181
/***********************************************************************************
182
  SNES9X for Mac OS (c) Copyright John Stiles
183
184
  Snes9x for Mac OS X
185
85 by zones
Update changelog / update minizip to 1.01h / update docs / Mac: changed MusicBox to Cocoa interface
186
  (c) Copyright 2001 - 2011  zones
1 by OV2
Initial 1.52 import
187
  (c) Copyright 2002 - 2005  107
188
  (c) Copyright 2002         PB1400c
189
  (c) Copyright 2004         Alexander and Sander
190
  (c) Copyright 2004 - 2005  Steven Seeger
191
  (c) Copyright 2005         Ryan Vogt
192
 ***********************************************************************************/
193
194
195
#include "port.h"
196
197
#include <IOKit/hid/IOHIDUsageTables.h>
198
#include "HID_Utilities_External.h"
199
200
#include "mac-prefix.h"
201
#include "mac-dialog.h"
202
#include "mac-os.h"
203
#include "mac-joypad.h"
204
205
#define	kUp(i)					(i * 4)
206
#define	kDn(i)					(i * 4 + 1)
207
#define	kLf(i)					(i * 4 + 2)
208
#define	kRt(i)					(i * 4 + 3)
209
210
#define	kPadElemTypeNone		0
211
#define	kPadElemTypeHat4		1
212
#define	kPadElemTypeHat8		2
213
#define	kPadElemTypeAxis		3
214
#define	kPadElemTypeButton		4
215
#define	kPadElemTypeOtherHat4	5
216
#define	kPadElemTypeOtherHat8	6
217
218
#define	kPadXAxis				1
219
#define	kPadYAxis				0
220
#define	kPadHat					0
221
222
#define	kMaskUp					0x0800
223
#define	kMaskDn					0x0400
224
#define	kMaskLf					0x0200
225
#define	kMaskRt					0x0100
226
227
typedef	hu_device_t		*pRecDevice;
228
typedef	hu_element_t	*pRecElement;
229
230
typedef struct	actionStruct
231
{
232
	pRecDevice 	fDevice;
233
	pRecElement	fElement;
234
	long		fValue;
235
	long		fOldValue;
236
}	actionRec, *actionPtr;
237
238
typedef struct	padDirectionInfo
239
{
240
	int			type;
241
	pRecDevice	device [2];
242
	pRecElement	element[2];
243
	long		max    [2];
244
	long		maxmid [2];
245
	long		mid    [2];
246
	long		midmin [2];
247
	long		min    [2];
248
}	directionInfo;
249
250
static actionRec		gActionRecs[kNeedCount];
251
static directionInfo	gDirectionInfo[MAC_MAX_PLAYERS];
252
static int				gDirectionHint[MAC_MAX_PLAYERS];
253
254
static const HIViewID	gControlIDs[kNeedCount] =
255
{
256
	{ '1_Up', 0 },
257
	{ '1_Dn', 0 },
258
	{ '1_Lf', 0 },
259
	{ '1_Rt', 0 },
260
261
	{ '2_Up', 0 },
262
	{ '2_Dn', 0 },
263
	{ '2_Lf', 0 },
264
	{ '2_Rt', 0 },
265
266
	{ '3_Up', 0 },
267
	{ '3_Dn', 0 },
268
	{ '3_Lf', 0 },
269
	{ '3_Rt', 0 },
270
271
	{ '4_Up', 0 },
272
	{ '4_Dn', 0 },
273
	{ '4_Lf', 0 },
274
	{ '4_Rt', 0 },
275
276
	{ '5_Up', 0 },
277
	{ '5_Dn', 0 },
278
	{ '5_Lf', 0 },
279
	{ '5_Rt', 0 },
280
281
	{ '6_Up', 0 },
282
	{ '6_Dn', 0 },
283
	{ '6_Lf', 0 },
284
	{ '6_Rt', 0 },
285
286
	{ '7_Up', 0 },
287
	{ '7_Dn', 0 },
288
	{ '7_Lf', 0 },
289
	{ '7_Rt', 0 },
290
291
	{ '8_Up', 0 },
292
	{ '8_Dn', 0 },
293
	{ '8_Lf', 0 },
294
	{ '8_Rt', 0 },
295
296
	{ '1__B', 0 },
297
	{ '1__A', 0 },
298
	{ '1__X', 0 },
299
	{ '1__Y', 0 },
300
	{ '1__L', 0 },
301
	{ '1__R', 0 },
302
	{ '1Sel', 0 },
303
	{ '1Srt', 0 },
304
305
	{ '2__B', 0 },
306
	{ '2__A', 0 },
307
	{ '2__X', 0 },
308
	{ '2__Y', 0 },
309
	{ '2__L', 0 },
310
	{ '2__R', 0 },
311
	{ '2Sel', 0 },
312
	{ '2Srt', 0 },
313
314
	{ '3__B', 0 },
315
	{ '3__A', 0 },
316
	{ '3__X', 0 },
317
	{ '3__Y', 0 },
318
	{ '3__L', 0 },
319
	{ '3__R', 0 },
320
	{ '3Sel', 0 },
321
	{ '3Srt', 0 },
322
323
	{ '4__B', 0 },
324
	{ '4__A', 0 },
325
	{ '4__X', 0 },
326
	{ '4__Y', 0 },
327
	{ '4__L', 0 },
328
	{ '4__R', 0 },
329
	{ '4Sel', 0 },
330
	{ '4Srt', 0 },
331
332
	{ '5__B', 0 },
333
	{ '5__A', 0 },
334
	{ '5__X', 0 },
335
	{ '5__Y', 0 },
336
	{ '5__L', 0 },
337
	{ '5__R', 0 },
338
	{ '5Sel', 0 },
339
	{ '5Srt', 0 },
340
341
	{ '6__B', 0 },
342
	{ '6__A', 0 },
343
	{ '6__X', 0 },
344
	{ '6__Y', 0 },
345
	{ '6__L', 0 },
346
	{ '6__R', 0 },
347
	{ '6Sel', 0 },
348
	{ '6Srt', 0 },
349
350
	{ '7__B', 0 },
351
	{ '7__A', 0 },
352
	{ '7__X', 0 },
353
	{ '7__Y', 0 },
354
	{ '7__L', 0 },
355
	{ '7__R', 0 },
356
	{ '7Sel', 0 },
357
	{ '7Srt', 0 },
358
359
	{ '8__B', 0 },
360
	{ '8__A', 0 },
361
	{ '8__X', 0 },
362
	{ '8__Y', 0 },
363
	{ '8__L', 0 },
364
	{ '8__R', 0 },
365
	{ '8Sel', 0 },
366
	{ '8Srt', 0 },
367
368
	{ '__FF', 0 },
369
	{ '_Frz', 0 },
370
	{ '_DeF', 0 },
371
	{ '_Snp', 0 },
372
	{ '_Esc', 0 },
373
	{ '_SPC', 0 },
374
	{ 'MouL', 0 },
375
	{ 'MouR', 0 },
376
	{ 'ScoT', 0 },
377
	{ 'ScoP', 0 },
378
	{ 'ScoC', 0 },
379
	{ 'Ofsc', 0 },
380
	{ '__Fn', 0 },
381
	{ '_Alt', 0 },
382
	{ 'FFUp', 0 },
383
	{ 'FFDn', 0 },
384
	{ '__TC', 0 }
385
};
386
387
static char	gNeeds[kNeedCount][64] =
388
{
389
	"1P Up",
390
	"1P Down",
391
	"1P Left",
392
	"1P Right",
393
394
	"2P Up",
395
	"2P Down",
396
	"2P Left",
397
	"2P Right",
398
399
	"3P Up",
400
	"3P Down",
401
	"3P Left",
402
	"3P Right",
403
404
	"4P Up",
405
	"4P Down",
406
	"4P Left",
407
	"4P Right",
408
409
	"5P Up",
410
	"5P Down",
411
	"5P Left",
412
	"5P Right",
413
414
	"6P Up",
415
	"6P Down",
416
	"6P Left",
417
	"6P Right",
418
419
	"7P Up",
420
	"7P Down",
421
	"7P Left",
422
	"7P Right",
423
424
	"8P Up",
425
	"8P Down",
426
	"8P Left",
427
	"8P Right",
428
429
	"1P B Button",
430
	"1P A Button",
431
	"1P X Button",
432
	"1P Y Button",
433
	"1P L Button",
434
	"1P R Button",
435
	"1P Select",
436
	"1P Start",
437
438
	"2P B Button",
439
	"2P A Button",
440
	"2P X Button",
441
	"2P Y Button",
442
	"2P L Button",
443
	"2P R Button",
444
	"2P Select",
445
	"2P Start",
446
447
	"3P B Button",
448
	"3P A Button",
449
	"3P X Button",
450
	"3P Y Button",
451
	"3P L Button",
452
	"3P R Button",
453
	"3P Select",
454
	"3P Start",
455
456
	"4P B Button",
457
	"4P A Button",
458
	"4P X Button",
459
	"4P Y Button",
460
	"4P L Button",
461
	"4P R Button",
462
	"4P Select",
463
	"4P Start",
464
465
	"5P B Button",
466
	"5P A Button",
467
	"5P X Button",
468
	"5P Y Button",
469
	"5P L Button",
470
	"5P R Button",
471
	"5P Select",
472
	"5P Start",
473
474
	"6P B Button",
475
	"6P A Button",
476
	"6P X Button",
477
	"6P Y Button",
478
	"6P L Button",
479
	"6P R Button",
480
	"6P Select",
481
	"6P Start",
482
483
	"7P B Button",
484
	"7P A Button",
485
	"7P X Button",
486
	"7P Y Button",
487
	"7P L Button",
488
	"7P R Button",
489
	"7P Select",
490
	"7P Start",
491
492
	"8P B Button",
493
	"8P A Button",
494
	"8P X Button",
495
	"8P Y Button",
496
	"8P L Button",
497
	"8P R Button",
498
	"8P Select",
499
	"8P Start",
500
501
	"Fast Forward",
502
	"Freeze Game",
503
	"Defrost Game",
504
	"Screenshot",
505
	"Break",
506
	"Save SPC",
507
	"Mouse Left",
508
	"Mouse Right",
509
	"Scope Turbo",
510
	"Scope Pause",
511
	"Scope Cursor",
512
	"Offscreen",
513
	"Fn Modifier",
514
	"Alt Modifier",
515
	"Turbo Speed Up",
516
	"Turbo Speed Down",
517
	"Turbo Control Modifier"
518
};
519
520
static int	gIconNumber[kNeedCount] =
521
{
522
	0,
523
	1,
524
	2,
525
	3,
526
527
	12,
528
	13,
529
	14,
530
	15,
531
532
	24,
533
	25,
534
	26,
535
	27,
536
537
	36,
538
	37,
539
	38,
540
	39,
541
542
	48,
543
	49,
544
	50,
545
	51,
546
547
	60,
548
	61,
549
	62,
550
	63,
551
552
	72,
553
	73,
554
	74,
555
	75,
556
557
	84,
558
	85,
559
	86,
560
	87,
561
562
	5,
563
	7,
564
	6,
565
	4,
566
	8,
567
	9,
568
	11,
569
	10,
570
571
	17,
572
	19,
573
	18,
574
	16,
575
	20,
576
	21,
577
	23,
578
	22,
579
580
	29,
581
	31,
582
	30,
583
	28,
584
	32,
585
	33,
586
	35,
587
	34,
588
589
	41,
590
	43,
591
	42,
592
	40,
593
	44,
594
	45,
595
	47,
596
	46,
597
598
	53,
599
	55,
600
	54,
601
	52,
602
	56,
603
	57,
604
	59,
605
	58,
606
607
	65,
608
	67,
609
	66,
610
	64,
611
	68,
612
	69,
613
	71,
614
	70,
615
616
	77,
617
	79,
618
	78,
619
	76,
620
	80,
621
	81,
622
	83,
623
	82,
624
625
	89,
626
	91,
627
	90,
628
	88,
629
	92,
630
	93,
631
	95,
632
	94,
633
634
	101,
635
	102,
636
	103,
637
	104,
638
	114,
639
	105,
640
	116,
641
	117,
642
	106,
643
	107,
644
	108,
645
	109,
646
	110,
647
	111,
648
	112,
649
	113,
650
	115
651
};
652
653
static void JoypadSetDirectionInfo (void);
654
static pascal void IdleTimer (EventLoopTimerRef, void *);
655
static pascal OSStatus ControllerEventHandler (EventHandlerCallRef, EventRef, void *);
656
657
658
void SaveControllerSettings (void)
659
{
660
	CFStringRef	keyCFStringRef;
661
 	Boolean		syncFlag;
662
663
	JoypadSetDirectionInfo();
664
665
    for (int a = 0; a < kNeedCount; a++)
666
    {
667
		char	needCStr[64], num[10];
668
669
		strcpy(needCStr, gNeeds[a]);
670
		if (padSetting > 1)
671
		{
672
			sprintf(num, "_%d", padSetting);
673
			strcat(needCStr, num);
674
		}
675
676
		keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s"), needCStr);
677
        if (keyCFStringRef)
678
        {
679
			if (gActionRecs[a].fDevice && gActionRecs[a].fElement)
680
				syncFlag = HIDSaveElementPref(keyCFStringRef, kCFPreferencesCurrentApplication, gActionRecs[a].fDevice, gActionRecs[a].fElement);
681
            else
682
				CFPreferencesSetAppValue(keyCFStringRef, NULL, kCFPreferencesCurrentApplication);
683
684
			CFRelease(keyCFStringRef);
685
        }
686
    }
687
688
	for (int a = 0; a < MAC_MAX_PLAYERS; a++)
689
	{
690
		keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DirectionHint_%d_%d"), a, padSetting);
691
		if (keyCFStringRef)
692
		{
693
			CFNumberRef	numRef;
694
			CFIndex		v;
695
696
			v = (CFIndex) gDirectionHint[a];
697
			numRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &v);
698
			if (numRef)
699
			{
700
				CFPreferencesSetAppValue(keyCFStringRef, numRef, kCFPreferencesCurrentApplication);
701
				CFRelease(numRef);
702
			}
703
704
			CFRelease(keyCFStringRef);
705
		}
706
	}
707
708
	CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
709
}
710
711
void LoadControllerSettings (void)
712
{
713
	CFStringRef	keyCFStringRef;
714
715
    for (int a = 0; a < kNeedCount; a++)
716
    {
717
		pRecDevice	pDevice  = NULL;
718
		pRecElement	pElement = NULL;
719
		Boolean		r = false;
720
		char		needCStr[64], num[10];
721
722
		strcpy(needCStr, gNeeds[a]);
723
		if (padSetting > 1)
724
		{
725
			sprintf(num, "_%d", padSetting);
726
			strcat(needCStr, num);
727
		}
728
729
		keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s"), needCStr);
730
		if (keyCFStringRef)
731
		{
732
			r = HIDRestoreElementPref(keyCFStringRef, kCFPreferencesCurrentApplication, &pDevice, &pElement);
733
			if (r && pDevice && pElement)
734
			{
735
				gActionRecs[a].fDevice  = pDevice;
736
				gActionRecs[a].fElement = pElement;
737
			}
738
			else
739
			{
740
				gActionRecs[a].fDevice  = NULL;
741
				gActionRecs[a].fElement = NULL;
742
			}
743
744
			CFRelease(keyCFStringRef);
745
		}
746
	}
747
748
	for (int a = 0; a < MAC_MAX_PLAYERS; a++)
749
	{
750
		keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DirectionHint_%d_%d"), a, padSetting);
751
		if (keyCFStringRef)
752
		{
753
			Boolean	r;
754
755
			gDirectionHint[a] = (int) CFPreferencesGetAppIntegerValue(keyCFStringRef, kCFPreferencesCurrentApplication, &r);
756
			if (!r)
757
				gDirectionHint[a] = kPadElemTypeNone;
758
759
			CFRelease(keyCFStringRef);
760
		}
761
		else
762
			gDirectionHint[a] = kPadElemTypeNone;
763
	}
764
765
	JoypadSetDirectionInfo();
766
}
767
768
static pascal OSStatus ControllerEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
769
{
770
	OSStatus	err, result = eventNotHandledErr;
771
	WindowRef	tWindowRef;
772
773
	tWindowRef = (WindowRef) inUserData;
774
775
	switch (GetEventClass(inEvent))
776
	{
777
		case kEventClassWindow:
778
			switch (GetEventKind(inEvent))
779
			{
780
				case kEventWindowClose:
781
					QuitAppModalLoopForWindow(tWindowRef);
782
					result = noErr;
783
					break;
784
			}
785
786
			break;
787
788
		case kEventClassCommand:
789
			switch (GetEventKind(inEvent))
790
			{
791
				HICommand	tHICommand;
792
793
				case kEventCommandUpdateStatus:
794
					err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand);
795
					if (err == noErr && tHICommand.commandID == 'clos')
796
					{
797
						UpdateMenuCommandStatus(true);
798
						result = noErr;
799
					}
800
801
					break;
802
803
				case kEventCommandProcess:
804
					err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand);
805
					if (err == noErr)
806
					{
807
						if (tHICommand.commandID == 'CLRa')
808
						{
809
							ClearPadSetting();
810
							result = noErr;
811
						}
812
						else
813
						{
814
							SInt32	command = -1, count;
815
816
							for (count = 0; count < kNeedCount; count++)
817
								if (tHICommand.commandID == gControlIDs[count].signature)
818
									command = count;
819
820
							if (command >= 0)
821
							{
822
								pRecDevice	pDevice;
823
								pRecElement	pElement;
824
825
								FlushEventQueue(GetCurrentEventQueue());
826
827
								if (HIDConfigureAction(&pDevice, &pElement, 2.5f))
828
								{
829
									if (command < MAC_MAX_PLAYERS * 4)	// Direction
830
									{
831
										int		i    = command >> 2;	// Player
832
										long	curv = HIDGetElementValue(pDevice, pElement);
833
834
										if (pElement->usage == kHIDUsage_GD_Hatswitch)	// Hat Switch
835
										{
836
											gActionRecs[kUp(i)].fDevice  = gActionRecs[kDn(i)].fDevice  = gActionRecs[kLf(i)].fDevice  = gActionRecs[kRt(i)].fDevice  = pDevice;
837
											gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = pElement;
838
839
											if (pDevice->vendorID == 1103)	// Thrustmaster
840
												gDirectionInfo[i].type = (pElement->max > 4) ? kPadElemTypeOtherHat8 : kPadElemTypeOtherHat4;
841
											else
842
											{
843
												if (pElement->max > 4)
844
												{
845
													if (((command % 4 == 0) && (curv == 0)) ||	// Up    : 0
846
														((command % 4 == 1) && (curv == 4)) ||	// Down  : 4
847
														((command % 4 == 2) && (curv == 6)) ||	// Left  : 6
848
														((command % 4 == 3) && (curv == 2)))	// Right : 2
849
														gDirectionInfo[i].type = kPadElemTypeOtherHat8;
850
													else
851
														gDirectionInfo[i].type = kPadElemTypeHat8;
852
												}
853
												else
854
												{
855
													if (((command % 4 == 0) && (curv == 0)) ||	// Up    : 0
856
														((command % 4 == 1) && (curv == 2)) ||	// Down  : 2
857
														((command % 4 == 2) && (curv == 3)) ||	// Left  : 3
858
														((command % 4 == 3) && (curv == 1)))	// Right : 1
859
														gDirectionInfo[i].type = kPadElemTypeOtherHat4;
860
													else
861
														gDirectionInfo[i].type = kPadElemTypeHat4;
862
												}
863
											}
864
865
											gDirectionInfo[i].device [kPadHat] = pDevice;
866
											gDirectionInfo[i].element[kPadHat] = pElement;
867
											gDirectionInfo[i].max    [kPadHat] = pElement->max;
868
											gDirectionInfo[i].min    [kPadHat] = pElement->min;
869
										}
870
										else
871
										if (pElement->max - pElement->min > 1)			// Axis (maybe)
872
										{
873
											if ((command % 4 == 0) || (command % 4 == 1))	// Up or Dn
874
											{
875
												gActionRecs[kUp(i)].fDevice  = gActionRecs[kDn(i)].fDevice  = pDevice;
876
												gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = pElement;
877
878
												gDirectionInfo[i].type               = kPadElemTypeAxis;
879
												gDirectionInfo[i].device [kPadYAxis] = pDevice;
880
												gDirectionInfo[i].element[kPadYAxis] = pElement;
881
												gDirectionInfo[i].max    [kPadYAxis] = pElement->max;
882
												gDirectionInfo[i].min    [kPadYAxis] = pElement->min;
883
												gDirectionInfo[i].mid    [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1;
884
												gDirectionInfo[i].maxmid [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].mid[kPadYAxis]) >> 1;
885
												gDirectionInfo[i].midmin [kPadYAxis] = (gDirectionInfo[i].mid[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1;
886
											}
887
											else											// Lf or Rt
888
											{
889
												gActionRecs[kLf(i)].fDevice  = gActionRecs[kRt(i)].fDevice  = pDevice;
890
												gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = pElement;
891
892
												gDirectionInfo[i].type               = kPadElemTypeAxis;
893
												gDirectionInfo[i].device [kPadXAxis] = pDevice;
894
												gDirectionInfo[i].element[kPadXAxis] = pElement;
895
												gDirectionInfo[i].max    [kPadXAxis] = pElement->max;
896
												gDirectionInfo[i].min    [kPadXAxis] = pElement->min;
897
												gDirectionInfo[i].mid    [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1;
898
												gDirectionInfo[i].maxmid [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].mid[kPadXAxis]) >> 1;
899
												gDirectionInfo[i].midmin [kPadXAxis] = (gDirectionInfo[i].mid[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1;
900
											}
901
										}
902
										else											// Button (maybe)
903
										{
904
											gActionRecs[command].fDevice  = pDevice;
905
											gActionRecs[command].fElement = pElement;
906
											gDirectionInfo[i].type = kPadElemTypeButton;
907
										}
908
909
										gDirectionHint[i] = gDirectionInfo[i].type;
910
									}
911
									else
912
									{
913
										gActionRecs[command].fDevice  = pDevice;
914
										gActionRecs[command].fElement = pElement;
915
									}
916
								}
917
								else
918
								{
919
									if (command < MAC_MAX_PLAYERS * 4)	// Direction
920
									{
921
										int	i = command >> 2;	// Player
922
923
										gActionRecs[kUp(i)].fDevice  = gActionRecs[kDn(i)].fDevice  = gActionRecs[kLf(i)].fDevice  = gActionRecs[kRt(i)].fDevice  = NULL;
924
										gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = NULL;
925
926
										gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeNone;
927
										gDirectionInfo[i].device [0] = gDirectionInfo[i].device [1] = NULL;
928
										gDirectionInfo[i].element[0] = gDirectionInfo[i].element[1] = NULL;
929
									}
930
									else
931
									{
932
										gActionRecs[command].fDevice  = NULL;
933
										gActionRecs[command].fElement = NULL;
934
									}
935
								}
936
937
								gActionRecs[command].fValue    = 0;
938
								gActionRecs[command].fOldValue = -2;
939
940
								FlushEventQueue(GetCurrentEventQueue());
941
942
								result = noErr;
943
							}
944
						}
945
					}
946
947
					break;
948
			}
949
950
			break;
951
	}
952
953
	return (result);
954
}
955
956
static pascal void IdleTimer (EventLoopTimerRef inTimer, void *userData)
957
{
958
	static uint32	old[MAC_MAX_PLAYERS] = { ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0 };
959
960
	HIViewRef	ctl, root;
961
	uint32		pad[MAC_MAX_PLAYERS];
962
963
	root = HIViewGetRoot((WindowRef) userData);
964
965
	for (int i = 0; i < MAC_MAX_PLAYERS; i++)
966
	{
967
		pad[i] = 0;
968
		JoypadScanDirection(i, &(pad[i]));
969
970
		if (old[i] != pad[i])
971
		{
972
			old[i]  = pad[i];
973
974
			HIViewFindByID(root, gControlIDs[kUp(i)], &ctl);
975
			SetControl32BitValue(ctl, (pad[i] & kMaskUp) ? 1 : 0);
976
			HIViewFindByID(root, gControlIDs[kDn(i)], &ctl);
977
			SetControl32BitValue(ctl, (pad[i] & kMaskDn) ? 1 : 0);
978
			HIViewFindByID(root, gControlIDs[kLf(i)], &ctl);
979
			SetControl32BitValue(ctl, (pad[i] & kMaskLf) ? 1 : 0);
980
			HIViewFindByID(root, gControlIDs[kRt(i)], &ctl);
981
			SetControl32BitValue(ctl, (pad[i] & kMaskRt) ? 1 : 0);
982
		}
983
	}
984
985
	for (int i = MAC_MAX_PLAYERS * 4; i < kNeedCount; i++)
986
	{
987
		gActionRecs[i].fValue = ISpKeyIsPressed(i);
988
989
		if (gActionRecs[i].fOldValue != gActionRecs[i].fValue)
990
		{
991
			gActionRecs[i].fOldValue  = gActionRecs[i].fValue;
992
993
			HIViewFindByID(root, gControlIDs[i], &ctl);
994
			SetControl32BitValue(ctl, (gActionRecs[i].fValue ? 1 : 0));
995
		}
996
	}
997
}
998
999
void SetUpHID (void)
1000
{
1001
	pRecDevice	device;
1002
1003
	HIDBuildDeviceList(NULL, NULL);
1004
	device = HIDGetFirstDevice();
1005
	if (!device)
1006
	{
1007
		hidExist = false;
1008
		return;
1009
	}
1010
1011
	hidExist = true;
1012
1013
	ClearPadSetting();
1014
1015
	LoadControllerSettings();
1016
}
1017
1018
void ClearPadSetting (void)
1019
{
1020
	for (int i = 0; i < MAC_MAX_PLAYERS; i++)
1021
	{
1022
		gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeNone;
1023
		gDirectionInfo[i].device [0] = gDirectionInfo[i].device [1] = NULL;
1024
		gDirectionInfo[i].element[0] = gDirectionInfo[i].element[1] = NULL;
1025
	}
1026
1027
	for (int i = 0; i < kNeedCount; i++)
1028
	{
1029
		gActionRecs[i].fDevice   = NULL;
1030
		gActionRecs[i].fElement  = NULL;
1031
		gActionRecs[i].fValue    = 0;
1032
		gActionRecs[i].fOldValue = -2;
1033
	}
1034
}
1035
1036
void ReleaseHID (void)
1037
{
1038
	if (hidExist)
1039
		HIDReleaseDeviceList();
1040
}
1041
1042
void ConfigureHID (void)
1043
{
1044
	OSStatus	err;
1045
	IBNibRef	nibRef;
1046
1047
	if (!hidExist)
1048
		return;
1049
1050
	err = CreateNibReference(kMacS9XCFString, &nibRef);
1051
	if (err == noErr)
1052
	{
1053
		WindowRef	tWindowRef;
1054
1055
		err = CreateWindowFromNib(nibRef, CFSTR("Controllers"), &tWindowRef);
1056
		if (err == noErr)
1057
		{
1058
			EventHandlerRef				eref;
1059
			EventLoopTimerRef			tref;
1060
			EventHandlerUPP				eventUPP;
1061
			EventLoopTimerUPP			timerUPP;
1062
			EventTypeSpec				windowEvents[] = { { kEventClassCommand, kEventCommandProcess      },
1063
														   { kEventClassCommand, kEventCommandUpdateStatus },
1064
														   { kEventClassWindow,  kEventWindowClose         } };
1065
			HIViewRef					ctl, root;
1066
			HIViewID					cid;
1067
			CFStringRef					str1, str2;
1068
			ControlButtonContentInfo	info;
1069
1070
			LoadControllerSettings();
1071
1072
			root = HIViewGetRoot(tWindowRef);
1073
			cid.id = 0;
1074
			cid.signature = 'PRES';
1075
			HIViewFindByID(root, cid, &ctl);
1076
			str1 = CFCopyLocalizedString(CFSTR("PresetNum"), "PresetNum");
1077
			str2 = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, str1, padSetting);
1078
			SetStaticTextCFString(ctl, str2, false);
1079
			CFRelease(str2);
1080
			CFRelease(str1);
1081
1082
			if (systemVersion >= 0x1040)
1083
			{
1084
				info.contentType = kControlContentCGImageRef;
1085
				for (int i = 0; i < kNeedCount; i++)
1086
				{
1087
					HIViewFindByID(root, gControlIDs[i], &ctl);
1088
					info.u.imageRef = macIconImage[gIconNumber[i]];
1089
					err = SetBevelButtonContentInfo(ctl, &info);
1090
				}
1091
			}
1092
		#ifdef MAC_PANTHER_SUPPORT
1093
			else
1094
			{
1095
				info.contentType = kControlContentIconRef;
1096
				for (int i = 0; i < kNeedCount; i++)
1097
				{
1098
					HIViewFindByID(root, gControlIDs[i], &ctl);
1099
					info.u.iconRef = macIconRef[gIconNumber[i]];
1100
					err = SetBevelButtonContentInfo(ctl, &info);
1101
				}
1102
			}
1103
		#endif
1104
1105
			eventUPP = NewEventHandlerUPP(ControllerEventHandler);
1106
			err = InstallWindowEventHandler(tWindowRef, eventUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) tWindowRef, &eref);
1107
1108
			timerUPP = NewEventLoopTimerUPP(IdleTimer);
1109
			err = InstallEventLoopTimer(GetCurrentEventLoop(), 0.0f, 0.1f, timerUPP, (void *) tWindowRef, &tref);
1110
1111
			MoveWindowPosition(tWindowRef, kWindowControllers, false);
1112
			ShowWindow(tWindowRef);
1113
			err = RunAppModalLoopForWindow(tWindowRef);
1114
			HideWindow(tWindowRef);
1115
			SaveWindowPosition(tWindowRef, kWindowControllers);
1116
1117
			err = RemoveEventLoopTimer(tref);
1118
			DisposeEventLoopTimerUPP(timerUPP);
1119
1120
			err = RemoveEventHandler(eref);
1121
			DisposeEventHandlerUPP(eventUPP);
1122
1123
			CFRelease(tWindowRef);
1124
1125
			SaveControllerSettings();
1126
		}
1127
1128
		DisposeNibReference(nibRef);
1129
	}
1130
}
1131
1132
long ISpKeyIsPressed (int needID)
1133
{
1134
	return (gActionRecs[needID].fDevice ? HIDGetElementValue(gActionRecs[needID].fDevice, gActionRecs[needID].fElement) : 0);
1135
}
1136
1137
void JoypadScanDirection (int i, uint32 *pad)
1138
{
1139
	long	state;
1140
1141
	switch (gDirectionInfo[i].type)
1142
	{
1143
		case kPadElemTypeAxis:							// Axis (maybe)
1144
			if (gDirectionInfo[i].device[kPadYAxis])	// Y-Axis
1145
			{
1146
				state = HIDGetElementValue(gDirectionInfo[i].device[kPadYAxis], gDirectionInfo[i].element[kPadYAxis]);
1147
				if (state >= gDirectionInfo[i].maxmid[kPadYAxis])
1148
					*pad |= kMaskDn;
1149
				else
1150
				if (state <= gDirectionInfo[i].midmin[kPadYAxis])
1151
					*pad |= kMaskUp;
1152
			}
1153
1154
			if (gDirectionInfo[i].device[kPadXAxis])	// X-Axis
1155
			{
1156
				state = HIDGetElementValue(gDirectionInfo[i].device[kPadXAxis], gDirectionInfo[i].element[kPadXAxis]);
1157
				if (state >= gDirectionInfo[i].maxmid[kPadXAxis])
1158
					*pad |= kMaskRt;
1159
				else
1160
				if (state <= gDirectionInfo[i].midmin[kPadXAxis])
1161
					*pad |= kMaskLf;
1162
			}
1163
1164
			break;
1165
1166
		case kPadElemTypeHat8:							// Hat Switch (8 Directions)
1167
			if (gDirectionInfo[i].device[kPadHat])
1168
			{
1169
				state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]);
1170
				switch (state)
1171
				{
1172
					case 1:	*pad |=  kMaskUp           ;	break;
1173
					case 2:	*pad |= (kMaskUp | kMaskRt);	break;
1174
					case 3:	*pad |=  kMaskRt		   ;	break;
1175
					case 4:	*pad |= (kMaskRt | kMaskDn);	break;
1176
					case 5:	*pad |=  kMaskDn		   ;	break;
1177
					case 6:	*pad |= (kMaskDn | kMaskLf);	break;
1178
					case 7:	*pad |=  kMaskLf		   ;	break;
1179
					case 8:	*pad |= (kMaskLf | kMaskUp);	break;
1180
				}
1181
			}
1182
1183
			break;
1184
1185
		case kPadElemTypeHat4:							// Hat Switch (4 Directions)
1186
			if (gDirectionInfo[i].device[kPadHat])
1187
			{
1188
				state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]);
1189
				switch (state)
1190
				{
1191
					case 1:	*pad |=  kMaskUp;	break;
1192
					case 2:	*pad |=  kMaskRt;	break;
1193
					case 3:	*pad |=  kMaskDn;	break;
1194
					case 4:	*pad |=  kMaskLf;	break;
1195
				}
1196
			}
1197
1198
			break;
1199
1200
		case kPadElemTypeOtherHat8:						// Hat Switch (8 Directions, Start at 0)
1201
			if (gDirectionInfo[i].device[kPadHat])
1202
			{
1203
				state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]);
1204
				switch (state)
1205
				{
1206
					case 0:	*pad |=  kMaskUp		   ;	break;
1207
					case 1:	*pad |= (kMaskUp | kMaskRt);	break;
1208
					case 2:	*pad |=  kMaskRt		   ;	break;
1209
					case 3:	*pad |= (kMaskRt | kMaskDn);	break;
1210
					case 4:	*pad |=  kMaskDn		   ;	break;
1211
					case 5:	*pad |= (kMaskDn | kMaskLf);	break;
1212
					case 6:	*pad |=  kMaskLf		   ;	break;
1213
					case 7:	*pad |= (kMaskLf | kMaskUp);	break;
1214
				}
1215
			}
1216
1217
			break;
1218
1219
		case kPadElemTypeOtherHat4:						// Hat Switch (4 Directions, Start at 0)
1220
			if (gDirectionInfo[i].device[kPadHat])
1221
			{
1222
				state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]);
1223
				switch (state)
1224
				{
1225
					case 0:	*pad |=  kMaskUp;	break;
1226
					case 1:	*pad |=  kMaskRt;	break;
1227
					case 2:	*pad |=  kMaskDn;	break;
1228
					case 3:	*pad |=  kMaskLf;	break;
1229
				}
1230
			}
1231
1232
			break;
1233
1234
		case kPadElemTypeButton:						// Button (maybe)
1235
			if (gActionRecs[kUp(i)].fDevice && HIDGetElementValue(gActionRecs[kUp(i)].fDevice, gActionRecs[kUp(i)].fElement))
1236
				*pad |= kMaskUp;
1237
			if (gActionRecs[kDn(i)].fDevice && HIDGetElementValue(gActionRecs[kDn(i)].fDevice, gActionRecs[kDn(i)].fElement))
1238
				*pad |= kMaskDn;
1239
			if (gActionRecs[kLf(i)].fDevice && HIDGetElementValue(gActionRecs[kLf(i)].fDevice, gActionRecs[kLf(i)].fElement))
1240
				*pad |= kMaskLf;
1241
			if (gActionRecs[kRt(i)].fDevice && HIDGetElementValue(gActionRecs[kRt(i)].fDevice, gActionRecs[kRt(i)].fElement))
1242
				*pad |= kMaskRt;
1243
1244
			break;
1245
	}
1246
}
1247
1248
static void JoypadSetDirectionInfo (void)
1249
{
1250
	for (int i = 0; i < MAC_MAX_PLAYERS; i++)
1251
	{
1252
		if (((gActionRecs[kUp(i)].fDevice) && (gActionRecs[kUp(i)].fElement)) &&
1253
			((gActionRecs[kDn(i)].fDevice) && (gActionRecs[kDn(i)].fElement)) &&
1254
			((gActionRecs[kLf(i)].fDevice) && (gActionRecs[kLf(i)].fElement)) &&
1255
			((gActionRecs[kRt(i)].fDevice) && (gActionRecs[kRt(i)].fElement)))
1256
		{
1257
			if ((gActionRecs[kUp(i)].fDevice  == gActionRecs[kDn(i)].fDevice)  &&
1258
				(gActionRecs[kDn(i)].fDevice  == gActionRecs[kLf(i)].fDevice)  &&
1259
				(gActionRecs[kLf(i)].fDevice  == gActionRecs[kRt(i)].fDevice)  &&
1260
				(gActionRecs[kUp(i)].fElement == gActionRecs[kDn(i)].fElement) &&
1261
				(gActionRecs[kDn(i)].fElement == gActionRecs[kLf(i)].fElement) &&
1262
				(gActionRecs[kLf(i)].fElement == gActionRecs[kRt(i)].fElement) &&
1263
				(gActionRecs[kUp(i)].fElement->usage == kHIDUsage_GD_Hatswitch))				// Hat Switch
1264
			{
1265
				if ((gDirectionHint[i] == kPadElemTypeHat8) || (gDirectionHint[i] == kPadElemTypeOtherHat8) ||
1266
					(gDirectionHint[i] == kPadElemTypeHat4) || (gDirectionHint[i] == kPadElemTypeOtherHat4))
1267
					gDirectionInfo[i].type = gDirectionHint[i];
1268
				else																			// Assuming...
1269
				{
1270
					if ((gActionRecs[kUp(i)].fDevice->vendorID == 1103) || (gActionRecs[kUp(i)].fElement->min == 0))
1271
						gDirectionInfo[i].type = (gActionRecs[kUp(i)].fElement->max > 4) ? kPadElemTypeOtherHat8 : kPadElemTypeOtherHat4;
1272
					else
1273
						gDirectionInfo[i].type = (gActionRecs[kUp(i)].fElement->max > 4) ? kPadElemTypeHat8      : kPadElemTypeHat4;
1274
1275
					gDirectionHint[i] = gDirectionInfo[i].type;
1276
				}
1277
1278
				gDirectionInfo[i].device [kPadHat] =  gActionRecs[kUp(i)].fDevice;
1279
				gDirectionInfo[i].element[kPadHat] =  gActionRecs[kUp(i)].fElement;
1280
				gDirectionInfo[i].max    [kPadHat] =  gActionRecs[kUp(i)].fElement->max;
1281
				gDirectionInfo[i].min    [kPadHat] =  gActionRecs[kUp(i)].fElement->min;
1282
			}
1283
			else
1284
			if ((gActionRecs[kUp(i)].fDevice  == gActionRecs[kDn(i)].fDevice)               &&
1285
				(gActionRecs[kLf(i)].fDevice  == gActionRecs[kRt(i)].fDevice)               &&
1286
				(gActionRecs[kUp(i)].fElement == gActionRecs[kDn(i)].fElement)              &&
1287
				(gActionRecs[kLf(i)].fElement == gActionRecs[kRt(i)].fElement)              &&
1288
				(gActionRecs[kUp(i)].fElement->max - gActionRecs[kUp(i)].fElement->min > 1) &&
1289
				(gActionRecs[kLf(i)].fElement->max - gActionRecs[kLf(i)].fElement->min > 1))	// Axis (maybe)
1290
			{
1291
				gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeAxis;
1292
1293
				gDirectionInfo[i].device [kPadYAxis] = gActionRecs[kUp(i)].fDevice;
1294
				gDirectionInfo[i].element[kPadYAxis] = gActionRecs[kUp(i)].fElement;
1295
				gDirectionInfo[i].max    [kPadYAxis] = gActionRecs[kUp(i)].fElement->max;
1296
				gDirectionInfo[i].min    [kPadYAxis] = gActionRecs[kUp(i)].fElement->min;
1297
				gDirectionInfo[i].mid    [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1;
1298
				gDirectionInfo[i].maxmid [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].mid[kPadYAxis]) >> 1;
1299
				gDirectionInfo[i].midmin [kPadYAxis] = (gDirectionInfo[i].mid[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1;
1300
1301
				gDirectionInfo[i].device [kPadXAxis] = gActionRecs[kLf(i)].fDevice;
1302
				gDirectionInfo[i].element[kPadXAxis] = gActionRecs[kLf(i)].fElement;
1303
				gDirectionInfo[i].max    [kPadXAxis] = gActionRecs[kLf(i)].fElement->max;
1304
				gDirectionInfo[i].min    [kPadXAxis] = gActionRecs[kLf(i)].fElement->min;
1305
				gDirectionInfo[i].mid    [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1;
1306
				gDirectionInfo[i].maxmid [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].mid[kPadXAxis]) >> 1;
1307
				gDirectionInfo[i].midmin [kPadXAxis] = (gDirectionInfo[i].mid[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1;
1308
			}
1309
			else																				// Button (maybe)
1310
				gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeButton;
1311
		}
1312
		else
1313
		{
1314
			gActionRecs[kUp(i)].fDevice  = gActionRecs[kDn(i)].fDevice  = gActionRecs[kLf(i)].fDevice  = gActionRecs[kRt(i)].fDevice  = NULL;
1315
			gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = NULL;
1316
1317
			gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeNone;
1318
			gDirectionInfo[i].device [0] = gDirectionInfo[i].device [1] = NULL;
1319
			gDirectionInfo[i].element[0] = gDirectionInfo[i].element[1] = NULL;
1320
		}
1321
	}
1322
}