1 /*****************************************************************************\
2      Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3                 This file is licensed under the Snes9x License.
4    For further information, consult the LICENSE file in the root directory.
5 \*****************************************************************************/
6 
7 /***********************************************************************************
8   SNES9X for Mac OS (c) Copyright John Stiles
9 
10   Snes9x for Mac OS X
11 
12   (c) Copyright 2001 - 2011  zones
13   (c) Copyright 2002 - 2005  107
14   (c) Copyright 2002         PB1400c
15   (c) Copyright 2004         Alexander and Sander
16   (c) Copyright 2004 - 2005  Steven Seeger
17   (c) Copyright 2005         Ryan Vogt
18  ***********************************************************************************/
19 
20 
21 #include "port.h"
22 
23 #include <IOKit/hid/IOHIDUsageTables.h>
24 #include "HID_Utilities_External.h"
25 
26 #include "mac-prefix.h"
27 #include "mac-dialog.h"
28 #include "mac-os.h"
29 #include "mac-joypad.h"
30 
31 #define	kUp(i)					(i * 4)
32 #define	kDn(i)					(i * 4 + 1)
33 #define	kLf(i)					(i * 4 + 2)
34 #define	kRt(i)					(i * 4 + 3)
35 
36 #define	kPadElemTypeNone		0
37 #define	kPadElemTypeHat4		1
38 #define	kPadElemTypeHat8		2
39 #define	kPadElemTypeAxis		3
40 #define	kPadElemTypeButton		4
41 #define	kPadElemTypeOtherHat4	5
42 #define	kPadElemTypeOtherHat8	6
43 
44 #define	kPadXAxis				1
45 #define	kPadYAxis				0
46 #define	kPadHat					0
47 
48 #define	kMaskUp					0x0800
49 #define	kMaskDn					0x0400
50 #define	kMaskLf					0x0200
51 #define	kMaskRt					0x0100
52 
53 typedef	hu_device_t		*pRecDevice;
54 typedef	hu_element_t	*pRecElement;
55 
56 typedef struct	actionStruct
57 {
58 	pRecDevice 	fDevice;
59 	pRecElement	fElement;
60 	long		fValue;
61 	long		fOldValue;
62 }	actionRec, *actionPtr;
63 
64 typedef struct	padDirectionInfo
65 {
66 	int			type;
67 	pRecDevice	device [2];
68 	pRecElement	element[2];
69 	long		max    [2];
70 	long		maxmid [2];
71 	long		mid    [2];
72 	long		midmin [2];
73 	long		min    [2];
74 }	directionInfo;
75 
76 static actionRec		gActionRecs[kNeedCount];
77 static directionInfo	gDirectionInfo[MAC_MAX_PLAYERS];
78 static int				gDirectionHint[MAC_MAX_PLAYERS];
79 
80 static const HIViewID	gControlIDs[kNeedCount] =
81 {
82 	{ '1_Up', 0 },
83 	{ '1_Dn', 0 },
84 	{ '1_Lf', 0 },
85 	{ '1_Rt', 0 },
86 
87 	{ '2_Up', 0 },
88 	{ '2_Dn', 0 },
89 	{ '2_Lf', 0 },
90 	{ '2_Rt', 0 },
91 
92 	{ '3_Up', 0 },
93 	{ '3_Dn', 0 },
94 	{ '3_Lf', 0 },
95 	{ '3_Rt', 0 },
96 
97 	{ '4_Up', 0 },
98 	{ '4_Dn', 0 },
99 	{ '4_Lf', 0 },
100 	{ '4_Rt', 0 },
101 
102 	{ '5_Up', 0 },
103 	{ '5_Dn', 0 },
104 	{ '5_Lf', 0 },
105 	{ '5_Rt', 0 },
106 
107 	{ '6_Up', 0 },
108 	{ '6_Dn', 0 },
109 	{ '6_Lf', 0 },
110 	{ '6_Rt', 0 },
111 
112 	{ '7_Up', 0 },
113 	{ '7_Dn', 0 },
114 	{ '7_Lf', 0 },
115 	{ '7_Rt', 0 },
116 
117 	{ '8_Up', 0 },
118 	{ '8_Dn', 0 },
119 	{ '8_Lf', 0 },
120 	{ '8_Rt', 0 },
121 
122 	{ '1__B', 0 },
123 	{ '1__A', 0 },
124 	{ '1__X', 0 },
125 	{ '1__Y', 0 },
126 	{ '1__L', 0 },
127 	{ '1__R', 0 },
128 	{ '1Sel', 0 },
129 	{ '1Srt', 0 },
130 
131 	{ '2__B', 0 },
132 	{ '2__A', 0 },
133 	{ '2__X', 0 },
134 	{ '2__Y', 0 },
135 	{ '2__L', 0 },
136 	{ '2__R', 0 },
137 	{ '2Sel', 0 },
138 	{ '2Srt', 0 },
139 
140 	{ '3__B', 0 },
141 	{ '3__A', 0 },
142 	{ '3__X', 0 },
143 	{ '3__Y', 0 },
144 	{ '3__L', 0 },
145 	{ '3__R', 0 },
146 	{ '3Sel', 0 },
147 	{ '3Srt', 0 },
148 
149 	{ '4__B', 0 },
150 	{ '4__A', 0 },
151 	{ '4__X', 0 },
152 	{ '4__Y', 0 },
153 	{ '4__L', 0 },
154 	{ '4__R', 0 },
155 	{ '4Sel', 0 },
156 	{ '4Srt', 0 },
157 
158 	{ '5__B', 0 },
159 	{ '5__A', 0 },
160 	{ '5__X', 0 },
161 	{ '5__Y', 0 },
162 	{ '5__L', 0 },
163 	{ '5__R', 0 },
164 	{ '5Sel', 0 },
165 	{ '5Srt', 0 },
166 
167 	{ '6__B', 0 },
168 	{ '6__A', 0 },
169 	{ '6__X', 0 },
170 	{ '6__Y', 0 },
171 	{ '6__L', 0 },
172 	{ '6__R', 0 },
173 	{ '6Sel', 0 },
174 	{ '6Srt', 0 },
175 
176 	{ '7__B', 0 },
177 	{ '7__A', 0 },
178 	{ '7__X', 0 },
179 	{ '7__Y', 0 },
180 	{ '7__L', 0 },
181 	{ '7__R', 0 },
182 	{ '7Sel', 0 },
183 	{ '7Srt', 0 },
184 
185 	{ '8__B', 0 },
186 	{ '8__A', 0 },
187 	{ '8__X', 0 },
188 	{ '8__Y', 0 },
189 	{ '8__L', 0 },
190 	{ '8__R', 0 },
191 	{ '8Sel', 0 },
192 	{ '8Srt', 0 },
193 
194 	{ '__FF', 0 },
195 	{ '_Frz', 0 },
196 	{ '_DeF', 0 },
197 	{ '_Snp', 0 },
198 	{ '_Esc', 0 },
199 	{ '_SPC', 0 },
200 	{ 'MouL', 0 },
201 	{ 'MouR', 0 },
202 	{ 'ScoT', 0 },
203 	{ 'ScoP', 0 },
204 	{ 'ScoC', 0 },
205 	{ 'Ofsc', 0 },
206 	{ '__Fn', 0 },
207 	{ '_Alt', 0 },
208 	{ 'FFUp', 0 },
209 	{ 'FFDn', 0 },
210 	{ '__TC', 0 }
211 };
212 
213 static char	gNeeds[kNeedCount][64] =
214 {
215 	"1P Up",
216 	"1P Down",
217 	"1P Left",
218 	"1P Right",
219 
220 	"2P Up",
221 	"2P Down",
222 	"2P Left",
223 	"2P Right",
224 
225 	"3P Up",
226 	"3P Down",
227 	"3P Left",
228 	"3P Right",
229 
230 	"4P Up",
231 	"4P Down",
232 	"4P Left",
233 	"4P Right",
234 
235 	"5P Up",
236 	"5P Down",
237 	"5P Left",
238 	"5P Right",
239 
240 	"6P Up",
241 	"6P Down",
242 	"6P Left",
243 	"6P Right",
244 
245 	"7P Up",
246 	"7P Down",
247 	"7P Left",
248 	"7P Right",
249 
250 	"8P Up",
251 	"8P Down",
252 	"8P Left",
253 	"8P Right",
254 
255 	"1P B Button",
256 	"1P A Button",
257 	"1P X Button",
258 	"1P Y Button",
259 	"1P L Button",
260 	"1P R Button",
261 	"1P Select",
262 	"1P Start",
263 
264 	"2P B Button",
265 	"2P A Button",
266 	"2P X Button",
267 	"2P Y Button",
268 	"2P L Button",
269 	"2P R Button",
270 	"2P Select",
271 	"2P Start",
272 
273 	"3P B Button",
274 	"3P A Button",
275 	"3P X Button",
276 	"3P Y Button",
277 	"3P L Button",
278 	"3P R Button",
279 	"3P Select",
280 	"3P Start",
281 
282 	"4P B Button",
283 	"4P A Button",
284 	"4P X Button",
285 	"4P Y Button",
286 	"4P L Button",
287 	"4P R Button",
288 	"4P Select",
289 	"4P Start",
290 
291 	"5P B Button",
292 	"5P A Button",
293 	"5P X Button",
294 	"5P Y Button",
295 	"5P L Button",
296 	"5P R Button",
297 	"5P Select",
298 	"5P Start",
299 
300 	"6P B Button",
301 	"6P A Button",
302 	"6P X Button",
303 	"6P Y Button",
304 	"6P L Button",
305 	"6P R Button",
306 	"6P Select",
307 	"6P Start",
308 
309 	"7P B Button",
310 	"7P A Button",
311 	"7P X Button",
312 	"7P Y Button",
313 	"7P L Button",
314 	"7P R Button",
315 	"7P Select",
316 	"7P Start",
317 
318 	"8P B Button",
319 	"8P A Button",
320 	"8P X Button",
321 	"8P Y Button",
322 	"8P L Button",
323 	"8P R Button",
324 	"8P Select",
325 	"8P Start",
326 
327 	"Fast Forward",
328 	"Freeze Game",
329 	"Defrost Game",
330 	"Screenshot",
331 	"Break",
332 	"Save SPC",
333 	"Mouse Left",
334 	"Mouse Right",
335 	"Scope Turbo",
336 	"Scope Pause",
337 	"Scope Cursor",
338 	"Offscreen",
339 	"Fn Modifier",
340 	"Alt Modifier",
341 	"Turbo Speed Up",
342 	"Turbo Speed Down",
343 	"Turbo Control Modifier"
344 };
345 
346 static int	gIconNumber[kNeedCount] =
347 {
348 	0,
349 	1,
350 	2,
351 	3,
352 
353 	12,
354 	13,
355 	14,
356 	15,
357 
358 	24,
359 	25,
360 	26,
361 	27,
362 
363 	36,
364 	37,
365 	38,
366 	39,
367 
368 	48,
369 	49,
370 	50,
371 	51,
372 
373 	60,
374 	61,
375 	62,
376 	63,
377 
378 	72,
379 	73,
380 	74,
381 	75,
382 
383 	84,
384 	85,
385 	86,
386 	87,
387 
388 	5,
389 	7,
390 	6,
391 	4,
392 	8,
393 	9,
394 	11,
395 	10,
396 
397 	17,
398 	19,
399 	18,
400 	16,
401 	20,
402 	21,
403 	23,
404 	22,
405 
406 	29,
407 	31,
408 	30,
409 	28,
410 	32,
411 	33,
412 	35,
413 	34,
414 
415 	41,
416 	43,
417 	42,
418 	40,
419 	44,
420 	45,
421 	47,
422 	46,
423 
424 	53,
425 	55,
426 	54,
427 	52,
428 	56,
429 	57,
430 	59,
431 	58,
432 
433 	65,
434 	67,
435 	66,
436 	64,
437 	68,
438 	69,
439 	71,
440 	70,
441 
442 	77,
443 	79,
444 	78,
445 	76,
446 	80,
447 	81,
448 	83,
449 	82,
450 
451 	89,
452 	91,
453 	90,
454 	88,
455 	92,
456 	93,
457 	95,
458 	94,
459 
460 	101,
461 	102,
462 	103,
463 	104,
464 	114,
465 	105,
466 	116,
467 	117,
468 	106,
469 	107,
470 	108,
471 	109,
472 	110,
473 	111,
474 	112,
475 	113,
476 	115
477 };
478 
479 static void JoypadSetDirectionInfo (void);
480 static pascal void IdleTimer (EventLoopTimerRef, void *);
481 static pascal OSStatus ControllerEventHandler (EventHandlerCallRef, EventRef, void *);
482 
483 
SaveControllerSettings(void)484 void SaveControllerSettings (void)
485 {
486 	CFStringRef	keyCFStringRef;
487  	Boolean		syncFlag;
488 
489 	JoypadSetDirectionInfo();
490 
491     for (int a = 0; a < kNeedCount; a++)
492     {
493 		char	needCStr[64], num[10];
494 
495 		strcpy(needCStr, gNeeds[a]);
496 		if (padSetting > 1)
497 		{
498 			sprintf(num, "_%d", padSetting);
499 			strcat(needCStr, num);
500 		}
501 
502 		keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s"), needCStr);
503         if (keyCFStringRef)
504         {
505 			if (gActionRecs[a].fDevice && gActionRecs[a].fElement)
506 				syncFlag = HIDSaveElementPref(keyCFStringRef, kCFPreferencesCurrentApplication, gActionRecs[a].fDevice, gActionRecs[a].fElement);
507             else
508 				CFPreferencesSetAppValue(keyCFStringRef, NULL, kCFPreferencesCurrentApplication);
509 
510 			CFRelease(keyCFStringRef);
511         }
512     }
513 
514 	for (int a = 0; a < MAC_MAX_PLAYERS; a++)
515 	{
516 		keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DirectionHint_%d_%d"), a, padSetting);
517 		if (keyCFStringRef)
518 		{
519 			CFNumberRef	numRef;
520 			CFIndex		v;
521 
522 			v = (CFIndex) gDirectionHint[a];
523 			numRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &v);
524 			if (numRef)
525 			{
526 				CFPreferencesSetAppValue(keyCFStringRef, numRef, kCFPreferencesCurrentApplication);
527 				CFRelease(numRef);
528 			}
529 
530 			CFRelease(keyCFStringRef);
531 		}
532 	}
533 
534 	CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
535 }
536 
LoadControllerSettings(void)537 void LoadControllerSettings (void)
538 {
539 	CFStringRef	keyCFStringRef;
540 
541     for (int a = 0; a < kNeedCount; a++)
542     {
543 		pRecDevice	pDevice  = NULL;
544 		pRecElement	pElement = NULL;
545 		Boolean		r = false;
546 		char		needCStr[64], num[10];
547 
548 		strcpy(needCStr, gNeeds[a]);
549 		if (padSetting > 1)
550 		{
551 			sprintf(num, "_%d", padSetting);
552 			strcat(needCStr, num);
553 		}
554 
555 		keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s"), needCStr);
556 		if (keyCFStringRef)
557 		{
558 			r = HIDRestoreElementPref(keyCFStringRef, kCFPreferencesCurrentApplication, &pDevice, &pElement);
559 			if (r && pDevice && pElement)
560 			{
561 				gActionRecs[a].fDevice  = pDevice;
562 				gActionRecs[a].fElement = pElement;
563 			}
564 			else
565 			{
566 				gActionRecs[a].fDevice  = NULL;
567 				gActionRecs[a].fElement = NULL;
568 			}
569 
570 			CFRelease(keyCFStringRef);
571 		}
572 	}
573 
574 	for (int a = 0; a < MAC_MAX_PLAYERS; a++)
575 	{
576 		keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DirectionHint_%d_%d"), a, padSetting);
577 		if (keyCFStringRef)
578 		{
579 			Boolean	r;
580 
581 			gDirectionHint[a] = (int) CFPreferencesGetAppIntegerValue(keyCFStringRef, kCFPreferencesCurrentApplication, &r);
582 			if (!r)
583 				gDirectionHint[a] = kPadElemTypeNone;
584 
585 			CFRelease(keyCFStringRef);
586 		}
587 		else
588 			gDirectionHint[a] = kPadElemTypeNone;
589 	}
590 
591 	JoypadSetDirectionInfo();
592 }
593 
ControllerEventHandler(EventHandlerCallRef inHandlerCallRef,EventRef inEvent,void * inUserData)594 static pascal OSStatus ControllerEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
595 {
596 	OSStatus	err, result = eventNotHandledErr;
597 	WindowRef	tWindowRef;
598 
599 	tWindowRef = (WindowRef) inUserData;
600 
601 	switch (GetEventClass(inEvent))
602 	{
603 		case kEventClassWindow:
604 			switch (GetEventKind(inEvent))
605 			{
606 				case kEventWindowClose:
607 					QuitAppModalLoopForWindow(tWindowRef);
608 					result = noErr;
609 					break;
610 			}
611 
612 			break;
613 
614 		case kEventClassCommand:
615 			switch (GetEventKind(inEvent))
616 			{
617 				HICommand	tHICommand;
618 
619 				case kEventCommandUpdateStatus:
620 					err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand);
621 					if (err == noErr && tHICommand.commandID == 'clos')
622 					{
623 						UpdateMenuCommandStatus(true);
624 						result = noErr;
625 					}
626 
627 					break;
628 
629 				case kEventCommandProcess:
630 					err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand);
631 					if (err == noErr)
632 					{
633 						if (tHICommand.commandID == 'CLRa')
634 						{
635 							ClearPadSetting();
636 							result = noErr;
637 						}
638 						else
639 						{
640 							SInt32	command = -1, count;
641 
642 							for (count = 0; count < kNeedCount; count++)
643 								if (tHICommand.commandID == gControlIDs[count].signature)
644 									command = count;
645 
646 							if (command >= 0)
647 							{
648 								pRecDevice	pDevice;
649 								pRecElement	pElement;
650 
651 								FlushEventQueue(GetCurrentEventQueue());
652 
653 								if (HIDConfigureAction(&pDevice, &pElement, 2.5f))
654 								{
655 									if (command < MAC_MAX_PLAYERS * 4)	// Direction
656 									{
657 										int		i    = command >> 2;	// Player
658 										long	curv = HIDGetElementValue(pDevice, pElement);
659 
660 										if (pElement->usage == kHIDUsage_GD_Hatswitch)	// Hat Switch
661 										{
662 											gActionRecs[kUp(i)].fDevice  = gActionRecs[kDn(i)].fDevice  = gActionRecs[kLf(i)].fDevice  = gActionRecs[kRt(i)].fDevice  = pDevice;
663 											gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = pElement;
664 
665 											if (pDevice->vendorID == 1103)	// Thrustmaster
666 												gDirectionInfo[i].type = (pElement->max > 4) ? kPadElemTypeOtherHat8 : kPadElemTypeOtherHat4;
667 											else
668 											{
669 												if (pElement->max > 4)
670 												{
671 													if (((command % 4 == 0) && (curv == 0)) ||	// Up    : 0
672 														((command % 4 == 1) && (curv == 4)) ||	// Down  : 4
673 														((command % 4 == 2) && (curv == 6)) ||	// Left  : 6
674 														((command % 4 == 3) && (curv == 2)))	// Right : 2
675 														gDirectionInfo[i].type = kPadElemTypeOtherHat8;
676 													else
677 														gDirectionInfo[i].type = kPadElemTypeHat8;
678 												}
679 												else
680 												{
681 													if (((command % 4 == 0) && (curv == 0)) ||	// Up    : 0
682 														((command % 4 == 1) && (curv == 2)) ||	// Down  : 2
683 														((command % 4 == 2) && (curv == 3)) ||	// Left  : 3
684 														((command % 4 == 3) && (curv == 1)))	// Right : 1
685 														gDirectionInfo[i].type = kPadElemTypeOtherHat4;
686 													else
687 														gDirectionInfo[i].type = kPadElemTypeHat4;
688 												}
689 											}
690 
691 											gDirectionInfo[i].device [kPadHat] = pDevice;
692 											gDirectionInfo[i].element[kPadHat] = pElement;
693 											gDirectionInfo[i].max    [kPadHat] = pElement->max;
694 											gDirectionInfo[i].min    [kPadHat] = pElement->min;
695 										}
696 										else
697 										if (pElement->max - pElement->min > 1)			// Axis (maybe)
698 										{
699 											if ((command % 4 == 0) || (command % 4 == 1))	// Up or Dn
700 											{
701 												gActionRecs[kUp(i)].fDevice  = gActionRecs[kDn(i)].fDevice  = pDevice;
702 												gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = pElement;
703 
704 												gDirectionInfo[i].type               = kPadElemTypeAxis;
705 												gDirectionInfo[i].device [kPadYAxis] = pDevice;
706 												gDirectionInfo[i].element[kPadYAxis] = pElement;
707 												gDirectionInfo[i].max    [kPadYAxis] = pElement->max;
708 												gDirectionInfo[i].min    [kPadYAxis] = pElement->min;
709 												gDirectionInfo[i].mid    [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1;
710 												gDirectionInfo[i].maxmid [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].mid[kPadYAxis]) >> 1;
711 												gDirectionInfo[i].midmin [kPadYAxis] = (gDirectionInfo[i].mid[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1;
712 											}
713 											else											// Lf or Rt
714 											{
715 												gActionRecs[kLf(i)].fDevice  = gActionRecs[kRt(i)].fDevice  = pDevice;
716 												gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = pElement;
717 
718 												gDirectionInfo[i].type               = kPadElemTypeAxis;
719 												gDirectionInfo[i].device [kPadXAxis] = pDevice;
720 												gDirectionInfo[i].element[kPadXAxis] = pElement;
721 												gDirectionInfo[i].max    [kPadXAxis] = pElement->max;
722 												gDirectionInfo[i].min    [kPadXAxis] = pElement->min;
723 												gDirectionInfo[i].mid    [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1;
724 												gDirectionInfo[i].maxmid [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].mid[kPadXAxis]) >> 1;
725 												gDirectionInfo[i].midmin [kPadXAxis] = (gDirectionInfo[i].mid[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1;
726 											}
727 										}
728 										else											// Button (maybe)
729 										{
730 											gActionRecs[command].fDevice  = pDevice;
731 											gActionRecs[command].fElement = pElement;
732 											gDirectionInfo[i].type = kPadElemTypeButton;
733 										}
734 
735 										gDirectionHint[i] = gDirectionInfo[i].type;
736 									}
737 									else
738 									{
739 										gActionRecs[command].fDevice  = pDevice;
740 										gActionRecs[command].fElement = pElement;
741 									}
742 								}
743 								else
744 								{
745 									if (command < MAC_MAX_PLAYERS * 4)	// Direction
746 									{
747 										int	i = command >> 2;	// Player
748 
749 										gActionRecs[kUp(i)].fDevice  = gActionRecs[kDn(i)].fDevice  = gActionRecs[kLf(i)].fDevice  = gActionRecs[kRt(i)].fDevice  = NULL;
750 										gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = NULL;
751 
752 										gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeNone;
753 										gDirectionInfo[i].device [0] = gDirectionInfo[i].device [1] = NULL;
754 										gDirectionInfo[i].element[0] = gDirectionInfo[i].element[1] = NULL;
755 									}
756 									else
757 									{
758 										gActionRecs[command].fDevice  = NULL;
759 										gActionRecs[command].fElement = NULL;
760 									}
761 								}
762 
763 								gActionRecs[command].fValue    = 0;
764 								gActionRecs[command].fOldValue = -2;
765 
766 								FlushEventQueue(GetCurrentEventQueue());
767 
768 								result = noErr;
769 							}
770 						}
771 					}
772 
773 					break;
774 			}
775 
776 			break;
777 	}
778 
779 	return (result);
780 }
781 
IdleTimer(EventLoopTimerRef inTimer,void * userData)782 static pascal void IdleTimer (EventLoopTimerRef inTimer, void *userData)
783 {
784 	static uint32	old[MAC_MAX_PLAYERS] = { ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0 };
785 
786 	HIViewRef	ctl, root;
787 	uint32		pad[MAC_MAX_PLAYERS];
788 
789 	root = HIViewGetRoot((WindowRef) userData);
790 
791 	for (int i = 0; i < MAC_MAX_PLAYERS; i++)
792 	{
793 		pad[i] = 0;
794 		JoypadScanDirection(i, &(pad[i]));
795 
796 		if (old[i] != pad[i])
797 		{
798 			old[i]  = pad[i];
799 
800 			HIViewFindByID(root, gControlIDs[kUp(i)], &ctl);
801 			SetControl32BitValue(ctl, (pad[i] & kMaskUp) ? 1 : 0);
802 			HIViewFindByID(root, gControlIDs[kDn(i)], &ctl);
803 			SetControl32BitValue(ctl, (pad[i] & kMaskDn) ? 1 : 0);
804 			HIViewFindByID(root, gControlIDs[kLf(i)], &ctl);
805 			SetControl32BitValue(ctl, (pad[i] & kMaskLf) ? 1 : 0);
806 			HIViewFindByID(root, gControlIDs[kRt(i)], &ctl);
807 			SetControl32BitValue(ctl, (pad[i] & kMaskRt) ? 1 : 0);
808 		}
809 	}
810 
811 	for (int i = MAC_MAX_PLAYERS * 4; i < kNeedCount; i++)
812 	{
813 		gActionRecs[i].fValue = ISpKeyIsPressed(i);
814 
815 		if (gActionRecs[i].fOldValue != gActionRecs[i].fValue)
816 		{
817 			gActionRecs[i].fOldValue  = gActionRecs[i].fValue;
818 
819 			HIViewFindByID(root, gControlIDs[i], &ctl);
820 			SetControl32BitValue(ctl, (gActionRecs[i].fValue ? 1 : 0));
821 		}
822 	}
823 }
824 
SetUpHID(void)825 void SetUpHID (void)
826 {
827 	pRecDevice	device;
828 
829 	HIDBuildDeviceList(NULL, NULL);
830 	device = HIDGetFirstDevice();
831 	if (!device)
832 	{
833 		hidExist = false;
834 		return;
835 	}
836 
837 	hidExist = true;
838 
839 	ClearPadSetting();
840 
841 	LoadControllerSettings();
842 }
843 
ClearPadSetting(void)844 void ClearPadSetting (void)
845 {
846 	for (int i = 0; i < MAC_MAX_PLAYERS; i++)
847 	{
848 		gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeNone;
849 		gDirectionInfo[i].device [0] = gDirectionInfo[i].device [1] = NULL;
850 		gDirectionInfo[i].element[0] = gDirectionInfo[i].element[1] = NULL;
851 	}
852 
853 	for (int i = 0; i < kNeedCount; i++)
854 	{
855 		gActionRecs[i].fDevice   = NULL;
856 		gActionRecs[i].fElement  = NULL;
857 		gActionRecs[i].fValue    = 0;
858 		gActionRecs[i].fOldValue = -2;
859 	}
860 }
861 
ReleaseHID(void)862 void ReleaseHID (void)
863 {
864 	if (hidExist)
865 		HIDReleaseDeviceList();
866 }
867 
ConfigureHID(void)868 void ConfigureHID (void)
869 {
870 	OSStatus	err;
871 	IBNibRef	nibRef;
872 
873 	if (!hidExist)
874 		return;
875 
876 	err = CreateNibReference(kMacS9XCFString, &nibRef);
877 	if (err == noErr)
878 	{
879 		WindowRef	tWindowRef;
880 
881 		err = CreateWindowFromNib(nibRef, CFSTR("Controllers"), &tWindowRef);
882 		if (err == noErr)
883 		{
884 			EventHandlerRef				eref;
885 			EventLoopTimerRef			tref;
886 			EventHandlerUPP				eventUPP;
887 			EventLoopTimerUPP			timerUPP;
888 			EventTypeSpec				windowEvents[] = { { kEventClassCommand, kEventCommandProcess      },
889 														   { kEventClassCommand, kEventCommandUpdateStatus },
890 														   { kEventClassWindow,  kEventWindowClose         } };
891 			HIViewRef					ctl, root;
892 			HIViewID					cid;
893 			CFStringRef					str1, str2;
894 			ControlButtonContentInfo	info;
895 
896 			LoadControllerSettings();
897 
898 			root = HIViewGetRoot(tWindowRef);
899 			cid.id = 0;
900 			cid.signature = 'PRES';
901 			HIViewFindByID(root, cid, &ctl);
902 			str1 = CFCopyLocalizedString(CFSTR("PresetNum"), "PresetNum");
903 			str2 = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, str1, padSetting);
904 			SetStaticTextCFString(ctl, str2, false);
905 			CFRelease(str2);
906 			CFRelease(str1);
907 
908 			if (systemVersion >= 0x1040)
909 			{
910 				info.contentType = kControlContentCGImageRef;
911 				for (int i = 0; i < kNeedCount; i++)
912 				{
913 					HIViewFindByID(root, gControlIDs[i], &ctl);
914 					info.u.imageRef = macIconImage[gIconNumber[i]];
915 					err = SetBevelButtonContentInfo(ctl, &info);
916 				}
917 			}
918 		#ifdef MAC_PANTHER_SUPPORT
919 			else
920 			{
921 				info.contentType = kControlContentIconRef;
922 				for (int i = 0; i < kNeedCount; i++)
923 				{
924 					HIViewFindByID(root, gControlIDs[i], &ctl);
925 					info.u.iconRef = macIconRef[gIconNumber[i]];
926 					err = SetBevelButtonContentInfo(ctl, &info);
927 				}
928 			}
929 		#endif
930 
931 			eventUPP = NewEventHandlerUPP(ControllerEventHandler);
932 			err = InstallWindowEventHandler(tWindowRef, eventUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) tWindowRef, &eref);
933 
934 			timerUPP = NewEventLoopTimerUPP(IdleTimer);
935 			err = InstallEventLoopTimer(GetCurrentEventLoop(), 0.0f, 0.1f, timerUPP, (void *) tWindowRef, &tref);
936 
937 			MoveWindowPosition(tWindowRef, kWindowControllers, false);
938 			ShowWindow(tWindowRef);
939 			err = RunAppModalLoopForWindow(tWindowRef);
940 			HideWindow(tWindowRef);
941 			SaveWindowPosition(tWindowRef, kWindowControllers);
942 
943 			err = RemoveEventLoopTimer(tref);
944 			DisposeEventLoopTimerUPP(timerUPP);
945 
946 			err = RemoveEventHandler(eref);
947 			DisposeEventHandlerUPP(eventUPP);
948 
949 			CFRelease(tWindowRef);
950 
951 			SaveControllerSettings();
952 		}
953 
954 		DisposeNibReference(nibRef);
955 	}
956 }
957 
ISpKeyIsPressed(int needID)958 long ISpKeyIsPressed (int needID)
959 {
960 	return (gActionRecs[needID].fDevice ? HIDGetElementValue(gActionRecs[needID].fDevice, gActionRecs[needID].fElement) : 0);
961 }
962 
JoypadScanDirection(int i,uint32 * pad)963 void JoypadScanDirection (int i, uint32 *pad)
964 {
965 	long	state;
966 
967 	switch (gDirectionInfo[i].type)
968 	{
969 		case kPadElemTypeAxis:							// Axis (maybe)
970 			if (gDirectionInfo[i].device[kPadYAxis])	// Y-Axis
971 			{
972 				state = HIDGetElementValue(gDirectionInfo[i].device[kPadYAxis], gDirectionInfo[i].element[kPadYAxis]);
973 				if (state >= gDirectionInfo[i].maxmid[kPadYAxis])
974 					*pad |= kMaskDn;
975 				else
976 				if (state <= gDirectionInfo[i].midmin[kPadYAxis])
977 					*pad |= kMaskUp;
978 			}
979 
980 			if (gDirectionInfo[i].device[kPadXAxis])	// X-Axis
981 			{
982 				state = HIDGetElementValue(gDirectionInfo[i].device[kPadXAxis], gDirectionInfo[i].element[kPadXAxis]);
983 				if (state >= gDirectionInfo[i].maxmid[kPadXAxis])
984 					*pad |= kMaskRt;
985 				else
986 				if (state <= gDirectionInfo[i].midmin[kPadXAxis])
987 					*pad |= kMaskLf;
988 			}
989 
990 			break;
991 
992 		case kPadElemTypeHat8:							// Hat Switch (8 Directions)
993 			if (gDirectionInfo[i].device[kPadHat])
994 			{
995 				state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]);
996 				switch (state)
997 				{
998 					case 1:	*pad |=  kMaskUp           ;	break;
999 					case 2:	*pad |= (kMaskUp | kMaskRt);	break;
1000 					case 3:	*pad |=  kMaskRt		   ;	break;
1001 					case 4:	*pad |= (kMaskRt | kMaskDn);	break;
1002 					case 5:	*pad |=  kMaskDn		   ;	break;
1003 					case 6:	*pad |= (kMaskDn | kMaskLf);	break;
1004 					case 7:	*pad |=  kMaskLf		   ;	break;
1005 					case 8:	*pad |= (kMaskLf | kMaskUp);	break;
1006 				}
1007 			}
1008 
1009 			break;
1010 
1011 		case kPadElemTypeHat4:							// Hat Switch (4 Directions)
1012 			if (gDirectionInfo[i].device[kPadHat])
1013 			{
1014 				state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]);
1015 				switch (state)
1016 				{
1017 					case 1:	*pad |=  kMaskUp;	break;
1018 					case 2:	*pad |=  kMaskRt;	break;
1019 					case 3:	*pad |=  kMaskDn;	break;
1020 					case 4:	*pad |=  kMaskLf;	break;
1021 				}
1022 			}
1023 
1024 			break;
1025 
1026 		case kPadElemTypeOtherHat8:						// Hat Switch (8 Directions, Start at 0)
1027 			if (gDirectionInfo[i].device[kPadHat])
1028 			{
1029 				state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]);
1030 				switch (state)
1031 				{
1032 					case 0:	*pad |=  kMaskUp		   ;	break;
1033 					case 1:	*pad |= (kMaskUp | kMaskRt);	break;
1034 					case 2:	*pad |=  kMaskRt		   ;	break;
1035 					case 3:	*pad |= (kMaskRt | kMaskDn);	break;
1036 					case 4:	*pad |=  kMaskDn		   ;	break;
1037 					case 5:	*pad |= (kMaskDn | kMaskLf);	break;
1038 					case 6:	*pad |=  kMaskLf		   ;	break;
1039 					case 7:	*pad |= (kMaskLf | kMaskUp);	break;
1040 				}
1041 			}
1042 
1043 			break;
1044 
1045 		case kPadElemTypeOtherHat4:						// Hat Switch (4 Directions, Start at 0)
1046 			if (gDirectionInfo[i].device[kPadHat])
1047 			{
1048 				state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]);
1049 				switch (state)
1050 				{
1051 					case 0:	*pad |=  kMaskUp;	break;
1052 					case 1:	*pad |=  kMaskRt;	break;
1053 					case 2:	*pad |=  kMaskDn;	break;
1054 					case 3:	*pad |=  kMaskLf;	break;
1055 				}
1056 			}
1057 
1058 			break;
1059 
1060 		case kPadElemTypeButton:						// Button (maybe)
1061 			if (gActionRecs[kUp(i)].fDevice && HIDGetElementValue(gActionRecs[kUp(i)].fDevice, gActionRecs[kUp(i)].fElement))
1062 				*pad |= kMaskUp;
1063 			if (gActionRecs[kDn(i)].fDevice && HIDGetElementValue(gActionRecs[kDn(i)].fDevice, gActionRecs[kDn(i)].fElement))
1064 				*pad |= kMaskDn;
1065 			if (gActionRecs[kLf(i)].fDevice && HIDGetElementValue(gActionRecs[kLf(i)].fDevice, gActionRecs[kLf(i)].fElement))
1066 				*pad |= kMaskLf;
1067 			if (gActionRecs[kRt(i)].fDevice && HIDGetElementValue(gActionRecs[kRt(i)].fDevice, gActionRecs[kRt(i)].fElement))
1068 				*pad |= kMaskRt;
1069 
1070 			break;
1071 	}
1072 }
1073 
JoypadSetDirectionInfo(void)1074 static void JoypadSetDirectionInfo (void)
1075 {
1076 	for (int i = 0; i < MAC_MAX_PLAYERS; i++)
1077 	{
1078 		if (((gActionRecs[kUp(i)].fDevice) && (gActionRecs[kUp(i)].fElement)) &&
1079 			((gActionRecs[kDn(i)].fDevice) && (gActionRecs[kDn(i)].fElement)) &&
1080 			((gActionRecs[kLf(i)].fDevice) && (gActionRecs[kLf(i)].fElement)) &&
1081 			((gActionRecs[kRt(i)].fDevice) && (gActionRecs[kRt(i)].fElement)))
1082 		{
1083 			if ((gActionRecs[kUp(i)].fDevice  == gActionRecs[kDn(i)].fDevice)  &&
1084 				(gActionRecs[kDn(i)].fDevice  == gActionRecs[kLf(i)].fDevice)  &&
1085 				(gActionRecs[kLf(i)].fDevice  == gActionRecs[kRt(i)].fDevice)  &&
1086 				(gActionRecs[kUp(i)].fElement == gActionRecs[kDn(i)].fElement) &&
1087 				(gActionRecs[kDn(i)].fElement == gActionRecs[kLf(i)].fElement) &&
1088 				(gActionRecs[kLf(i)].fElement == gActionRecs[kRt(i)].fElement) &&
1089 				(gActionRecs[kUp(i)].fElement->usage == kHIDUsage_GD_Hatswitch))				// Hat Switch
1090 			{
1091 				if ((gDirectionHint[i] == kPadElemTypeHat8) || (gDirectionHint[i] == kPadElemTypeOtherHat8) ||
1092 					(gDirectionHint[i] == kPadElemTypeHat4) || (gDirectionHint[i] == kPadElemTypeOtherHat4))
1093 					gDirectionInfo[i].type = gDirectionHint[i];
1094 				else																			// Assuming...
1095 				{
1096 					if ((gActionRecs[kUp(i)].fDevice->vendorID == 1103) || (gActionRecs[kUp(i)].fElement->min == 0))
1097 						gDirectionInfo[i].type = (gActionRecs[kUp(i)].fElement->max > 4) ? kPadElemTypeOtherHat8 : kPadElemTypeOtherHat4;
1098 					else
1099 						gDirectionInfo[i].type = (gActionRecs[kUp(i)].fElement->max > 4) ? kPadElemTypeHat8      : kPadElemTypeHat4;
1100 
1101 					gDirectionHint[i] = gDirectionInfo[i].type;
1102 				}
1103 
1104 				gDirectionInfo[i].device [kPadHat] =  gActionRecs[kUp(i)].fDevice;
1105 				gDirectionInfo[i].element[kPadHat] =  gActionRecs[kUp(i)].fElement;
1106 				gDirectionInfo[i].max    [kPadHat] =  gActionRecs[kUp(i)].fElement->max;
1107 				gDirectionInfo[i].min    [kPadHat] =  gActionRecs[kUp(i)].fElement->min;
1108 			}
1109 			else
1110 			if ((gActionRecs[kUp(i)].fDevice  == gActionRecs[kDn(i)].fDevice)               &&
1111 				(gActionRecs[kLf(i)].fDevice  == gActionRecs[kRt(i)].fDevice)               &&
1112 				(gActionRecs[kUp(i)].fElement == gActionRecs[kDn(i)].fElement)              &&
1113 				(gActionRecs[kLf(i)].fElement == gActionRecs[kRt(i)].fElement)              &&
1114 				(gActionRecs[kUp(i)].fElement->max - gActionRecs[kUp(i)].fElement->min > 1) &&
1115 				(gActionRecs[kLf(i)].fElement->max - gActionRecs[kLf(i)].fElement->min > 1))	// Axis (maybe)
1116 			{
1117 				gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeAxis;
1118 
1119 				gDirectionInfo[i].device [kPadYAxis] = gActionRecs[kUp(i)].fDevice;
1120 				gDirectionInfo[i].element[kPadYAxis] = gActionRecs[kUp(i)].fElement;
1121 				gDirectionInfo[i].max    [kPadYAxis] = gActionRecs[kUp(i)].fElement->max;
1122 				gDirectionInfo[i].min    [kPadYAxis] = gActionRecs[kUp(i)].fElement->min;
1123 				gDirectionInfo[i].mid    [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1;
1124 				gDirectionInfo[i].maxmid [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].mid[kPadYAxis]) >> 1;
1125 				gDirectionInfo[i].midmin [kPadYAxis] = (gDirectionInfo[i].mid[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1;
1126 
1127 				gDirectionInfo[i].device [kPadXAxis] = gActionRecs[kLf(i)].fDevice;
1128 				gDirectionInfo[i].element[kPadXAxis] = gActionRecs[kLf(i)].fElement;
1129 				gDirectionInfo[i].max    [kPadXAxis] = gActionRecs[kLf(i)].fElement->max;
1130 				gDirectionInfo[i].min    [kPadXAxis] = gActionRecs[kLf(i)].fElement->min;
1131 				gDirectionInfo[i].mid    [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1;
1132 				gDirectionInfo[i].maxmid [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].mid[kPadXAxis]) >> 1;
1133 				gDirectionInfo[i].midmin [kPadXAxis] = (gDirectionInfo[i].mid[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1;
1134 			}
1135 			else																				// Button (maybe)
1136 				gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeButton;
1137 		}
1138 		else
1139 		{
1140 			gActionRecs[kUp(i)].fDevice  = gActionRecs[kDn(i)].fDevice  = gActionRecs[kLf(i)].fDevice  = gActionRecs[kRt(i)].fDevice  = NULL;
1141 			gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = NULL;
1142 
1143 			gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeNone;
1144 			gDirectionInfo[i].device [0] = gDirectionInfo[i].device [1] = NULL;
1145 			gDirectionInfo[i].element[0] = gDirectionInfo[i].element[1] = NULL;
1146 		}
1147 	}
1148 }
1149