1 // Burner Game Input
2 #include "burner.h"
3 
4 // Player Default Controls
5 INT32 nPlayerDefaultControls[8] = {0, 1, 2, 3, 8, 8, 8, 8};
6 TCHAR szPlayerDefaultIni[5][MAX_PATH] = { _T(""), _T(""), _T(""), _T(""), _T("") };
7 
8 // Mapping of PC inputs to game inputs
9 struct GameInp* GameInp = NULL;
10 UINT32 nGameInpCount = 0;
11 UINT32 nMacroCount = 0;
12 UINT32 nMaxMacro = 0;
13 
14 INT32 nAnalogSpeed;
15 
16 INT32 nFireButtons = 0;
17 
18 bool bStreetFighterLayout = false;
19 bool bLeftAltkeyMapped = false;
20 
21 // These are mappable global macros for mapping Pause/FFWD etc to controls in the input mapping dialogue. -dink
22 UINT8 macroSystemPause = 0;
23 UINT8 macroSystemFFWD = 0;
24 UINT8 macroSystemFrame = 0;
25 UINT8 macroSystemSaveState = 0;
26 UINT8 macroSystemLoadState = 0;
27 UINT8 macroSystemUNDOState = 0;
28 UINT8 macroSystemLuaHotkey1 = 0;
29 UINT8 macroSystemLuaHotkey2 = 0;
30 UINT8 macroSystemLuaHotkey3 = 0;
31 UINT8 macroSystemLuaHotkey4 = 0;
32 UINT8 macroSystemLuaHotkey5 = 0;
33 UINT8 macroSystemLuaHotkey6 = 0;
34 UINT8 macroSystemLuaHotkey7 = 0;
35 UINT8 macroSystemLuaHotkey8 = 0;
36 UINT8 macroSystemLuaHotkey9 = 0;
37 
38 UINT8 *lua_hotkeys[] = {
39 	&macroSystemLuaHotkey1,
40 	&macroSystemLuaHotkey2,
41 	&macroSystemLuaHotkey3,
42 	&macroSystemLuaHotkey4,
43 	&macroSystemLuaHotkey5,
44 	&macroSystemLuaHotkey6,
45 	&macroSystemLuaHotkey7,
46 	&macroSystemLuaHotkey8,
47 	&macroSystemLuaHotkey9,
48 	NULL
49 };
50 
51 
52 #define HW_NEOGEO ( ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOGEO) || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOCD) )
53 #define HW_NES ( ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_NES) || ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_FDS) )
54 #define HW_MISC ( (! HW_NEOGEO) && (! HW_NES) && ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) != HARDWARE_SEGA_MEGADRIVE) )
55 #define SETS_VS ( (BurnDrvGetGenreFlags() & GBF_VSFIGHT) && ((BurnDrvGetFamilyFlags() & FBF_SF) || (BurnDrvGetFamilyFlags() & FBF_DSTLK) || (BurnDrvGetFamilyFlags() &FBF_PWRINST) || HW_NEOGEO) )
56 
57 #ifdef BUILD_MACOS
58 int MacOSinpInitControls(struct GameInp *pgi, const char *szi);
59 #endif
60 
61 // ---------------------------------------------------------------------------
62 
63 // Check if the left alt (menu) key is mapped
64 #ifndef __LIBRETRO__
GameInpCheckLeftAlt()65 void GameInpCheckLeftAlt()
66 {
67 	struct GameInp* pgi;
68 	UINT32 i;
69 
70 	bLeftAltkeyMapped = false;
71 
72 	for (i = 0, pgi = GameInp; i < (nGameInpCount + nMacroCount); i++, pgi++) {
73 
74 		if (bLeftAltkeyMapped) {
75 			break;
76 		}
77 
78 		switch (pgi->nInput) {
79 			case GIT_SWITCH:
80 				if (pgi->Input.Switch.nCode == FBK_LALT) {
81 					bLeftAltkeyMapped = true;
82 				}
83 				break;
84 			case GIT_MACRO_AUTO:
85 			case GIT_MACRO_CUSTOM:
86 				if (pgi->Macro.nMode) {
87 					if (pgi->Macro.Switch.nCode == FBK_LALT) {
88 						bLeftAltkeyMapped = true;
89 					}
90 				}
91 				break;
92 
93 			default:
94 				continue;
95 		}
96 	}
97 }
98 
99 // Check if the sytem mouse is mapped and set the cooperative level apropriately
GameInpCheckMouse()100 void GameInpCheckMouse()
101 {
102 	bool bMouseMapped = false;
103 	struct GameInp* pgi;
104 	UINT32 i;
105 
106 	for (i = 0, pgi = GameInp; i < (nGameInpCount + nMacroCount); i++, pgi++) {
107 
108 		if (bMouseMapped) {
109 			break;
110 		}
111 
112 		switch (pgi->nInput) {
113 			case GIT_SWITCH:
114 				if ((pgi->Input.Switch.nCode & 0xFF00) == 0x8000) {
115 					bMouseMapped = true;
116 				}
117 				break;
118 			case GIT_MOUSEAXIS:
119 				if (pgi->Input.MouseAxis.nMouse == 0) {
120 					bMouseMapped = true;
121 				}
122 				break;
123 			case GIT_MACRO_AUTO:
124 			case GIT_MACRO_CUSTOM:
125 				if (pgi->Macro.nMode) {
126 					if ((pgi->Macro.Switch.nCode & 0xFF00) == 0x8000) {
127 						bMouseMapped = true;
128 					}
129 				}
130 				break;
131 
132 			default:
133 				continue;
134 		}
135 	}
136 
137 	if (bDrvOkay) {
138 		if (!bRunPause) {
139 			InputSetCooperativeLevel(bMouseMapped, bAlwaysProcessKeyboardInput);
140 		} else {
141 			InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput);
142 		}
143 	} else {
144 		InputSetCooperativeLevel(false, false);
145 	}
146 }
147 #endif
148 
149 // ---------------------------------------------------------------------------
150 
GameInpBlank(INT32 bDipSwitch)151 INT32 GameInpBlank(INT32 bDipSwitch)
152 {
153 	UINT32 i = 0;
154 	struct GameInp* pgi = NULL;
155 
156 	// Reset all inputs to undefined (even dip switches, if bDipSwitch==1)
157 	if (GameInp == NULL) {
158 		return 1;
159 	}
160 
161 	// Get the targets in the library for the Input Values
162 	for (i = 0, pgi = GameInp; i < nGameInpCount; i++, pgi++) {
163 		struct BurnInputInfo bii;
164 		memset(&bii, 0, sizeof(bii));
165 		BurnDrvGetInputInfo(&bii, i);
166 		if (bDipSwitch == 0 && (bii.nType & BIT_GROUP_CONSTANT)) {		// Don't blank the dip switches
167 			continue;
168 		}
169 
170 		memset(pgi, 0, sizeof(*pgi));									// Clear input
171 
172 		pgi->nType = bii.nType;											// store input type
173 		pgi->Input.pVal = bii.pVal; 									// store input pointer to value
174 
175 		if (bii.nType & BIT_GROUP_CONSTANT) {							// Further initialisation for constants/DIPs
176 			pgi->nInput = GIT_CONSTANT;
177 			pgi->Input.Constant.nConst = *bii.pVal;
178 		}
179 	}
180 
181 	for (i = 0; i < nMacroCount; i++, pgi++) {
182 		pgi->Macro.nMode = 0;
183 		if (pgi->nInput == GIT_MACRO_CUSTOM) {
184 			pgi->nInput = 0;
185 		}
186 	}
187 
188 	bLeftAltkeyMapped = false;
189 
190 	return 0;
191 }
192 
GameInpInitMacros()193 static void GameInpInitMacros()
194 {
195 	struct GameInp* pgi;
196 	struct BurnInputInfo bii;
197 
198 	INT32 nPunchx3[5] = {0, 0, 0, 0, 0};
199 	INT32 nPunchInputs[5][3];
200 	INT32 nKickx3[5] = {0, 0, 0, 0, 0};
201 	INT32 nKickInputs[5][3];
202 
203 	INT32 nNeogeoButtons[5][4];
204 	INT32 nPgmButtons[10][16];
205 
206 	bStreetFighterLayout = false;
207 	nMacroCount = 0;
208 
209 	nFireButtons = 0;
210 
211 	memset(&nNeogeoButtons, 0, sizeof(nNeogeoButtons));
212 	memset(&nPgmButtons, 0, sizeof(nPgmButtons));
213 
214 	for (UINT32 i = 0; i < nGameInpCount; i++) {
215 		bii.szName = NULL;
216 		BurnDrvGetInputInfo(&bii, i);
217 		if (bii.szName == NULL) {
218 			bii.szName = "";
219 		}
220 
221 		// Fix for 6 players (xmen6p ...)
222 		bool bPlayerInInfo = (toupper(bii.szInfo[0]) == 'P' && bii.szInfo[1] >= '1' && bii.szInfo[1] <= '6'); // Because some of the older drivers don't use the standard input naming.
223 		bool bPlayerInName = (bii.szName[0] == 'P' && bii.szName[1] >= '1' && bii.szName[1] <= '6');
224 
225 		if (bPlayerInInfo || bPlayerInName) {
226 			INT32 nPlayer = 0;
227 
228 			if (bPlayerInName)
229 				nPlayer = bii.szName[1] - '1';
230 			if (bPlayerInInfo && nPlayer == 0)
231 				nPlayer = bii.szInfo[1] - '1';
232 
233 			if (nPlayer == 0) {
234 				if (strncmp(" fire", bii.szInfo + 2, 5) == 0) {
235 					nFireButtons++;
236 				}
237 			}
238 
239 			if (_stricmp(" Weak Punch", bii.szName + 2) == 0) {
240 				nPunchx3[nPlayer] |= 1;
241 				nPunchInputs[nPlayer][0] = i;
242 			}
243 			if (_stricmp(" Medium Punch", bii.szName + 2) == 0) {
244 				nPunchx3[nPlayer] |= 2;
245 				nPunchInputs[nPlayer][1] = i;
246 			}
247 			if (_stricmp(" Strong Punch", bii.szName + 2) == 0) {
248 				nPunchx3[nPlayer] |= 4;
249 				nPunchInputs[nPlayer][2] = i;
250 			}
251 			if (_stricmp(" Weak Kick", bii.szName + 2) == 0) {
252 				nKickx3[nPlayer] |= 1;
253 				nKickInputs[nPlayer][0] = i;
254 			}
255 			if (_stricmp(" Medium Kick", bii.szName + 2) == 0) {
256 				nKickx3[nPlayer] |= 2;
257 				nKickInputs[nPlayer][1] = i;
258 			}
259 			if (_stricmp(" Strong Kick", bii.szName + 2) == 0) {
260 				nKickx3[nPlayer] |= 4;
261 				nKickInputs[nPlayer][2] = i;
262 			}
263 
264 			if (HW_NEOGEO) {
265 				if (_stricmp(" Button A", bii.szName + 2) == 0) {
266 					nNeogeoButtons[nPlayer][0] = i;
267 				}
268 				if (_stricmp(" Button B", bii.szName + 2) == 0) {
269 					nNeogeoButtons[nPlayer][1] = i;
270 				}
271 				if (_stricmp(" Button C", bii.szName + 2) == 0) {
272 					nNeogeoButtons[nPlayer][2] = i;
273 				}
274 				if (_stricmp(" Button D", bii.szName + 2) == 0) {
275 					nNeogeoButtons[nPlayer][3] = i;
276 				}
277 			}
278 
279 			//if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_IGS_PGM) {
280 			{ // Use nPgmButtons for Autofire too -dink
281 				if ((_stricmp(" Button 1", bii.szName + 2) == 0) || (_stricmp(" fire 1", bii.szInfo + 2) == 0)) {
282 					nPgmButtons[nPlayer][0] = i;
283 				}
284 				if ((_stricmp(" Button 2", bii.szName + 2) == 0) || (_stricmp(" fire 2", bii.szInfo + 2) == 0)) {
285 					nPgmButtons[nPlayer][1] = i;
286 				}
287 				if ((_stricmp(" Button 3", bii.szName + 2) == 0) || (_stricmp(" fire 3", bii.szInfo + 2) == 0)) {
288 					nPgmButtons[nPlayer][2] = i;
289 				}
290 				if ((_stricmp(" Button 4", bii.szName + 2) == 0) || (_stricmp(" fire 4", bii.szInfo + 2) == 0)) {
291 					nPgmButtons[nPlayer][3] = i;
292 				}
293 				if ((_stricmp(" Button 5", bii.szName + 2) == 0) || (_stricmp(" fire 5", bii.szInfo + 2) == 0)) {
294 					nPgmButtons[nPlayer][4] = i;
295 				}
296 				if ((_stricmp(" Button 6", bii.szName + 2) == 0) || (_stricmp(" fire 6", bii.szInfo + 2) == 0)) {
297 					nPgmButtons[nPlayer][5] = i;
298 				}
299 			}
300 		}
301 	}
302 
303 	pgi = GameInp + nGameInpCount;
304 
305 	{ // Mappable system macros -dink
306 			pgi->nInput = GIT_MACRO_AUTO;
307 			pgi->nType = BIT_DIGITAL;
308 			pgi->Macro.nMode = 0;
309 			pgi->Macro.nSysMacro = 1;
310 			sprintf(pgi->Macro.szName, "System Pause");
311 			pgi->Macro.pVal[0] = &macroSystemPause;
312 			pgi->Macro.nVal[0] = 1;
313 			nMacroCount++;
314 			pgi++;
315 
316 			pgi->nInput = GIT_MACRO_AUTO;
317 			pgi->nType = BIT_DIGITAL;
318 			pgi->Macro.nMode = 0;
319 			pgi->Macro.nSysMacro = 1;
320 			sprintf(pgi->Macro.szName, "System FFWD");
321 			pgi->Macro.pVal[0] = &macroSystemFFWD;
322 			pgi->Macro.nVal[0] = 1;
323 			nMacroCount++;
324 			pgi++;
325 
326 			pgi->nInput = GIT_MACRO_AUTO;
327 			pgi->nType = BIT_DIGITAL;
328 			pgi->Macro.nMode = 0;
329 			pgi->Macro.nSysMacro = 1;
330 			sprintf(pgi->Macro.szName, "System Frame");
331 			pgi->Macro.pVal[0] = &macroSystemFrame;
332 			pgi->Macro.nVal[0] = 1;
333 			nMacroCount++;
334 			pgi++;
335 
336 			pgi->nInput = GIT_MACRO_AUTO;
337 			pgi->nType = BIT_DIGITAL;
338 			pgi->Macro.nMode = 0;
339 			pgi->Macro.nSysMacro = 1;
340 			sprintf(pgi->Macro.szName, "System Load State");
341 			pgi->Macro.pVal[0] = &macroSystemLoadState;
342 			pgi->Macro.nVal[0] = 1;
343 			nMacroCount++;
344 			pgi++;
345 
346 			pgi->nInput = GIT_MACRO_AUTO;
347 			pgi->nType = BIT_DIGITAL;
348 			pgi->Macro.nMode = 0;
349 			pgi->Macro.nSysMacro = 1;
350 			sprintf(pgi->Macro.szName, "System Save State");
351 			pgi->Macro.pVal[0] = &macroSystemSaveState;
352 			pgi->Macro.nVal[0] = 1;
353 			nMacroCount++;
354 			pgi++;
355 
356 			pgi->nInput = GIT_MACRO_AUTO;
357 			pgi->nType = BIT_DIGITAL;
358 			pgi->Macro.nMode = 0;
359 			pgi->Macro.nSysMacro = 1;
360 			sprintf(pgi->Macro.szName, "System UNDO State");
361 			pgi->Macro.pVal[0] = &macroSystemUNDOState;
362 			pgi->Macro.nVal[0] = 1;
363 			nMacroCount++;
364 			pgi++;
365 	}
366 
367 	// Remove two keys for volume adjustment of cps2
368 	INT32 nRealButtons = ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_CAPCOM_CPS2) ? nFireButtons - 2 : nFireButtons;
369 	INT32 nIndex = 0;
370 
371 	for (UINT32 nPlayer = 0; nPlayer < nMaxPlayers; nPlayer++) {
372 		UINT8* pArrow[4] = { 0, 0, 0, 0 };  // { up, down, left, right }
373 
374 		// Some games may require these buttons to have autofire as well
375 		for (INT32 i = nIndex; i < nGameInpCount; i++, nIndex++)
376 		{
377 			bii.szName = NULL;
378 			BurnDrvGetInputInfo(&bii, i);
379 
380 			if (bii.szName == NULL) {
381 				bii.szName = "";
382 			}
383 			if (_stricmp(" Up", bii.szName + 2) == 0 ||
384 				_stricmp(" Down", bii.szName + 2) == 0 ||
385 				_stricmp(" Left", bii.szName + 2) == 0 ||
386 				_stricmp(" Right", bii.szName + 2) == 0)
387 			{
388 				sprintf(pgi->Macro.szName, "%s", bii.szName);
389 
390 				pgi->nInput = GIT_MACRO_AUTO;
391 				pgi->nType = BIT_DIGITAL;
392 				pgi->Macro.nMode = 0;
393 				pgi->Macro.pVal[0] = bii.pVal;
394 				pgi->Macro.nVal[0] = 1;
395 
396 				nMacroCount++;
397 				pgi++;
398 
399 				if (_stricmp(" Up", bii.szName + 2) == 0) pArrow[0] = bii.pVal;
400 				if (_stricmp(" Down", bii.szName + 2) == 0) pArrow[1] = bii.pVal;
401 				if (_stricmp(" Left", bii.szName + 2) == 0) pArrow[2] = bii.pVal;
402 				if (_stricmp(" Right", bii.szName + 2) == 0) pArrow[3] = bii.pVal;
403 
404 				if ((SETS_VS) && pArrow[0] && pArrow[1] && pArrow[2] && pArrow[3]) {
405 					sprintf(pgi->Macro.szName, "P%d %s", nPlayer + 1, "�I");
406 					pgi->nInput = GIT_MACRO_AUTO;
407 					pgi->nType = BIT_DIGITAL;
408 					pgi->Macro.nMode = 0;
409 					pgi->Macro.pVal[0] = pArrow[0];
410 					pgi->Macro.nVal[0] = 1;
411 					pgi->Macro.pVal[1] = pArrow[2];
412 					pgi->Macro.nVal[1] = 1;
413 					nMacroCount++;
414 					pgi++;
415 
416 					sprintf(pgi->Macro.szName, "P%d %s", nPlayer + 1, "�J");
417 					pgi->nInput = GIT_MACRO_AUTO;
418 					pgi->nType = BIT_DIGITAL;
419 					pgi->Macro.nMode = 0;
420 					pgi->Macro.pVal[0] = pArrow[0];
421 					pgi->Macro.nVal[0] = 1;
422 					pgi->Macro.pVal[1] = pArrow[3];
423 					pgi->Macro.nVal[1] = 1;
424 					nMacroCount++;
425 					pgi++;
426 
427 					sprintf(pgi->Macro.szName, "P%d %s", nPlayer + 1, "�L");
428 					pgi->nInput = GIT_MACRO_AUTO;
429 					pgi->nType = BIT_DIGITAL;
430 					pgi->Macro.nMode = 0;
431 					pgi->Macro.pVal[0] = pArrow[1];
432 					pgi->Macro.nVal[0] = 1;
433 					pgi->Macro.pVal[1] = pArrow[2];
434 					pgi->Macro.nVal[1] = 1;
435 					nMacroCount++;
436 					pgi++;
437 
438 					sprintf(pgi->Macro.szName, "P%d %s", nPlayer + 1, "�K");
439 					pgi->nInput = GIT_MACRO_AUTO;
440 					pgi->nType = BIT_DIGITAL;
441 					pgi->Macro.nMode = 0;
442 					pgi->Macro.pVal[0] = pArrow[1];
443 					pgi->Macro.nVal[0] = 1;
444 					pgi->Macro.pVal[1] = pArrow[3];
445 					pgi->Macro.nVal[1] = 1;
446 					nMacroCount++;
447 					pgi++;
448 				}
449 				if (_stricmp(" Right", bii.szName + 2) == 0) {  // The last key value is ...
450 					nIndex++;
451 					break;
452 				}
453 			}
454 		}
455 		for (INT32 i = 0; i < nRealButtons; i++) {
456 			BurnDrvGetInputInfo(&bii, (HW_NEOGEO) ? nNeogeoButtons[nPlayer][i] : nPgmButtons[nPlayer][i]);
457 
458 			// The appearance of "Px coin" caused by the asymmetric bond of shielding P1 --> Pn (no "Boom" button on P3 of jurassic99 ...)
459 			if (_stricmp(" Coin", bii.szName + 2) != 0) {
460 				pgi->nInput = GIT_MACRO_AUTO;
461 				pgi->nType = BIT_DIGITAL;
462 				pgi->Macro.nMode = 0;
463 				sprintf(pgi->Macro.szName, "%s", bii.szName);
464 
465 				pgi->Macro.pVal[0] = bii.pVal;
466 				pgi->Macro.nVal[0] = 1;
467 				nMacroCount++;
468 				pgi++;
469 			}
470 		}
471 		if (nPunchx3[nPlayer] == 7) {		// Create a 3x punch macro
472 			pgi->nInput = GIT_MACRO_AUTO;
473 			pgi->nType = BIT_DIGITAL;
474 			pgi->Macro.nMode = 0;
475 
476 			sprintf(pgi->Macro.szName, "P%i Buttons 3x Punch", nPlayer + 1);
477 			for (INT32 j = 0; j < 3; j++) {
478 				BurnDrvGetInputInfo(&bii, nPunchInputs[nPlayer][j]);
479 				pgi->Macro.pVal[j] = bii.pVal;
480 				pgi->Macro.nVal[j] = 1;
481 			}
482 
483 			nMacroCount++;
484 			pgi++;
485 		}
486 		if (nKickx3[nPlayer] == 7) {		// Create a 3x kick macro
487 			pgi->nInput = GIT_MACRO_AUTO;
488 			pgi->nType = BIT_DIGITAL;
489 			pgi->Macro.nMode = 0;
490 
491 			sprintf(pgi->Macro.szName, "P%i Buttons 3x Kick", nPlayer + 1);
492 			for (INT32 j = 0; j < 3; j++) {
493 				BurnDrvGetInputInfo(&bii, nKickInputs[nPlayer][j]);
494 				pgi->Macro.pVal[j] = bii.pVal;
495 				pgi->Macro.nVal[j] = 1;
496 			}
497 
498 			nMacroCount++;
499 			pgi++;
500 		}
501 		if (nPunchx3[nPlayer] == 7 && nKickx3[nPlayer] == 7) {		// Create a Weak Punch + Weak Kick macro, Combination keys in the sfa3 series
502 			pgi->nInput = GIT_MACRO_AUTO;
503 			pgi->nType = BIT_DIGITAL;
504 			pgi->Macro.nMode = 0;
505 
506 			sprintf(pgi->Macro.szName, "P%i Buttons Weak PK", nPlayer + 1);
507 			BurnDrvGetInputInfo(&bii, nPunchInputs[nPlayer][0]);
508 			pgi->Macro.pVal[0] = bii.pVal;
509 			pgi->Macro.nVal[0] = 1;
510 			BurnDrvGetInputInfo(&bii, nKickInputs[nPlayer][0]);
511 			pgi->Macro.pVal[1] = bii.pVal;
512 			pgi->Macro.nVal[1] = 1;
513 
514 			nMacroCount++;
515 			pgi++;
516 		}
517 		if (nPunchx3[nPlayer] == 7 && nKickx3[nPlayer] == 7) {		// Create a Medium Punch + Medium Kick macro, Combination keys in the sfa3 series
518 			pgi->nInput = GIT_MACRO_AUTO;
519 			pgi->nType = BIT_DIGITAL;
520 			pgi->Macro.nMode = 0;
521 
522 			sprintf(pgi->Macro.szName, "P%i Buttons Medium PK", nPlayer + 1);
523 			BurnDrvGetInputInfo(&bii, nPunchInputs[nPlayer][1]);
524 			pgi->Macro.pVal[0] = bii.pVal;
525 			pgi->Macro.nVal[0] = 1;
526 			BurnDrvGetInputInfo(&bii, nKickInputs[nPlayer][1]);
527 			pgi->Macro.pVal[1] = bii.pVal;
528 			pgi->Macro.nVal[1] = 1;
529 
530 			nMacroCount++;
531 			pgi++;
532 		}
533 		if (nPunchx3[nPlayer] == 7 && nKickx3[nPlayer] == 7) {		// Create a Strong Punch + Strong Kick macro, Combination keys in the sfa3 series
534 			pgi->nInput = GIT_MACRO_AUTO;
535 			pgi->nType = BIT_DIGITAL;
536 			pgi->Macro.nMode = 0;
537 
538 			sprintf(pgi->Macro.szName, "P%i Buttons Strong PK", nPlayer + 1);
539 			BurnDrvGetInputInfo(&bii, nPunchInputs[nPlayer][2]);
540 			pgi->Macro.pVal[0] = bii.pVal;
541 			pgi->Macro.nVal[0] = 1;
542 			BurnDrvGetInputInfo(&bii, nKickInputs[nPlayer][2]);
543 			pgi->Macro.pVal[1] = bii.pVal;
544 			pgi->Macro.nVal[1] = 1;
545 
546 			nMacroCount++;
547 			pgi++;
548 		}
549 		if (nPunchx3[nPlayer] == 7 && nKickx3[nPlayer] == 7) {		// Create a Strong Punch + Weak Kick macro, Quick cancel technique in sf2ce series
550 			pgi->nInput = GIT_MACRO_AUTO;
551 			pgi->nType = BIT_DIGITAL;
552 			pgi->Macro.nMode = 0;
553 
554 			sprintf(pgi->Macro.szName, "P%i Buttons SP + WK", nPlayer + 1);
555 			BurnDrvGetInputInfo(&bii, nPunchInputs[nPlayer][2]);
556 			pgi->Macro.pVal[0] = bii.pVal;
557 			pgi->Macro.nVal[0] = 1;
558 			BurnDrvGetInputInfo(&bii, nKickInputs[nPlayer][0]);
559 			pgi->Macro.pVal[1] = bii.pVal;
560 			pgi->Macro.nVal[1] = 1;
561 
562 			nMacroCount++;
563 			pgi++;
564 		}
565 		if (nRealButtons == 4 && HW_NEOGEO) {  // NeoGeo & NeoGeo cd
566 			pgi->nInput = GIT_MACRO_AUTO;
567 			pgi->nType = BIT_DIGITAL;
568 			pgi->Macro.nMode = 0;
569 			sprintf(pgi->Macro.szName, "P%i Buttons AB", nPlayer + 1);
570 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]);
571 			pgi->Macro.pVal[0] = bii.pVal;
572 			pgi->Macro.nVal[0] = 1;
573 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]);
574 			pgi->Macro.pVal[1] = bii.pVal;
575 			pgi->Macro.nVal[1] = 1;
576 			nMacroCount++;
577 			pgi++;
578 
579 			pgi->nInput = GIT_MACRO_AUTO;
580 			pgi->nType = BIT_DIGITAL;
581 			pgi->Macro.nMode = 0;
582 			sprintf(pgi->Macro.szName, "P%i Buttons AC", nPlayer + 1);
583 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]);
584 			pgi->Macro.pVal[0] = bii.pVal;
585 			pgi->Macro.nVal[0] = 1;
586 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]);
587 			pgi->Macro.pVal[1] = bii.pVal;
588 			pgi->Macro.nVal[1] = 1;
589 			nMacroCount++;
590 			pgi++;
591 
592 			pgi->nInput = GIT_MACRO_AUTO;
593 			pgi->nType = BIT_DIGITAL;
594 			pgi->Macro.nMode = 0;
595 			sprintf(pgi->Macro.szName, "P%i Buttons AD", nPlayer + 1);
596 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]);
597 			pgi->Macro.pVal[0] = bii.pVal;
598 			pgi->Macro.nVal[0] = 1;
599 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]);
600 			pgi->Macro.pVal[1] = bii.pVal;
601 			pgi->Macro.nVal[1] = 1;
602 			nMacroCount++;
603 			pgi++;
604 
605 			pgi->nInput = GIT_MACRO_AUTO;
606 			pgi->nType = BIT_DIGITAL;
607 			pgi->Macro.nMode = 0;
608 			sprintf(pgi->Macro.szName, "P%i Buttons BC", nPlayer + 1);
609 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]);
610 			pgi->Macro.pVal[0] = bii.pVal;
611 			pgi->Macro.nVal[0] = 1;
612 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]);
613 			pgi->Macro.pVal[1] = bii.pVal;
614 			pgi->Macro.nVal[1] = 1;
615 			nMacroCount++;
616 			pgi++;
617 
618 			pgi->nInput = GIT_MACRO_AUTO;
619 			pgi->nType = BIT_DIGITAL;
620 			pgi->Macro.nMode = 0;
621 			sprintf(pgi->Macro.szName, "P%i Buttons BD", nPlayer + 1);
622 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]);
623 			pgi->Macro.pVal[0] = bii.pVal;
624 			pgi->Macro.nVal[0] = 1;
625 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]);
626 			pgi->Macro.pVal[1] = bii.pVal;
627 			pgi->Macro.nVal[1] = 1;
628 			nMacroCount++;
629 			pgi++;
630 
631 			pgi->nInput = GIT_MACRO_AUTO;
632 			pgi->nType = BIT_DIGITAL;
633 			pgi->Macro.nMode = 0;
634 			sprintf(pgi->Macro.szName, "P%i Buttons CD", nPlayer + 1);
635 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]);
636 			pgi->Macro.pVal[0] = bii.pVal;
637 			pgi->Macro.nVal[0] = 1;
638 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]);
639 			pgi->Macro.pVal[1] = bii.pVal;
640 			pgi->Macro.nVal[1] = 1;
641 			nMacroCount++;
642 			pgi++;
643 
644 			pgi->nInput = GIT_MACRO_AUTO;
645 			pgi->nType = BIT_DIGITAL;
646 			pgi->Macro.nMode = 0;
647 			sprintf(pgi->Macro.szName, "P%i Buttons ABC", nPlayer + 1);
648 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]);
649 			pgi->Macro.pVal[0] = bii.pVal;
650 			pgi->Macro.nVal[0] = 1;
651 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]);
652 			pgi->Macro.pVal[1] = bii.pVal;
653 			pgi->Macro.nVal[1] = 1;
654 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]);
655 			pgi->Macro.pVal[2] = bii.pVal;
656 			pgi->Macro.nVal[2] = 1;
657 			nMacroCount++;
658 			pgi++;
659 
660 			pgi->nInput = GIT_MACRO_AUTO;
661 			pgi->nType = BIT_DIGITAL;
662 			pgi->Macro.nMode = 0;
663 			sprintf(pgi->Macro.szName, "P%i Buttons ABD", nPlayer + 1);
664 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]);
665 			pgi->Macro.pVal[0] = bii.pVal;
666 			pgi->Macro.nVal[0] = 1;
667 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]);
668 			pgi->Macro.pVal[1] = bii.pVal;
669 			pgi->Macro.nVal[1] = 1;
670 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]);
671 			pgi->Macro.pVal[2] = bii.pVal;
672 			pgi->Macro.nVal[2] = 1;
673 			nMacroCount++;
674 			pgi++;
675 
676 			pgi->nInput = GIT_MACRO_AUTO;
677 			pgi->nType = BIT_DIGITAL;
678 			pgi->Macro.nMode = 0;
679 			sprintf(pgi->Macro.szName, "P%i Buttons ACD", nPlayer + 1);
680 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]);
681 			pgi->Macro.pVal[0] = bii.pVal;
682 			pgi->Macro.nVal[0] = 1;
683 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]);
684 			pgi->Macro.pVal[1] = bii.pVal;
685 			pgi->Macro.nVal[1] = 1;
686 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]);
687 			pgi->Macro.pVal[2] = bii.pVal;
688 			pgi->Macro.nVal[2] = 1;
689 			nMacroCount++;
690 			pgi++;
691 
692 			pgi->nInput = GIT_MACRO_AUTO;
693 			pgi->nType = BIT_DIGITAL;
694 			pgi->Macro.nMode = 0;
695 			sprintf(pgi->Macro.szName, "P%i Buttons BCD", nPlayer + 1);
696 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]);
697 			pgi->Macro.pVal[0] = bii.pVal;
698 			pgi->Macro.nVal[0] = 1;
699 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]);
700 			pgi->Macro.pVal[1] = bii.pVal;
701 			pgi->Macro.nVal[1] = 1;
702 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]);
703 			pgi->Macro.pVal[2] = bii.pVal;
704 			pgi->Macro.nVal[2] = 1;
705 			nMacroCount++;
706 			pgi++;
707 
708 			pgi->nInput = GIT_MACRO_AUTO;
709 			pgi->nType = BIT_DIGITAL;
710 			pgi->Macro.nMode = 0;
711 			sprintf(pgi->Macro.szName, "P%i Buttons ABCD", nPlayer + 1);
712 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]);
713 			pgi->Macro.pVal[0] = bii.pVal;
714 			pgi->Macro.nVal[0] = 1;
715 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]);
716 			pgi->Macro.pVal[1] = bii.pVal;
717 			pgi->Macro.nVal[1] = 1;
718 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]);
719 			pgi->Macro.pVal[2] = bii.pVal;
720 			pgi->Macro.nVal[2] = 1;
721 			BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]);
722 			pgi->Macro.pVal[3] = bii.pVal;
723 			pgi->Macro.nVal[3] = 1;
724 			nMacroCount++;
725 			pgi++;
726 		}
727 		if (nRealButtons == 4 && HW_MISC) {  // PGM & Other 4 key games;
728 			pgi->nInput = GIT_MACRO_AUTO;
729 			pgi->nType = BIT_DIGITAL;
730 			pgi->Macro.nMode = 0;
731 			sprintf(pgi->Macro.szName, "P%i Buttons 12", nPlayer + 1);
732 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]);
733 			pgi->Macro.pVal[0] = bii.pVal;
734 			pgi->Macro.nVal[0] = 1;
735 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]);
736 			pgi->Macro.pVal[1] = bii.pVal;
737 			pgi->Macro.nVal[1] = 1;
738 			nMacroCount++;
739 			pgi++;
740 
741 			pgi->nInput = GIT_MACRO_AUTO;
742 			pgi->nType = BIT_DIGITAL;
743 			pgi->Macro.nMode = 0;
744 			sprintf(pgi->Macro.szName, "P%i Buttons 13", nPlayer + 1);
745 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]);
746 			pgi->Macro.pVal[0] = bii.pVal;
747 			pgi->Macro.nVal[0] = 1;
748 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]);
749 			pgi->Macro.pVal[1] = bii.pVal;
750 			pgi->Macro.nVal[1] = 1;
751 			nMacroCount++;
752 			pgi++;
753 
754 			pgi->nInput = GIT_MACRO_AUTO;
755 			pgi->nType = BIT_DIGITAL;
756 			pgi->Macro.nMode = 0;
757 			sprintf(pgi->Macro.szName, "P%i Buttons 14", nPlayer + 1);
758 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]);
759 			pgi->Macro.pVal[0] = bii.pVal;
760 			pgi->Macro.nVal[0] = 1;
761 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]);
762 			pgi->Macro.pVal[1] = bii.pVal;
763 			pgi->Macro.nVal[1] = 1;
764 			nMacroCount++;
765 			pgi++;
766 
767 			pgi->nInput = GIT_MACRO_AUTO;
768 			pgi->nType = BIT_DIGITAL;
769 			pgi->Macro.nMode = 0;
770 			sprintf(pgi->Macro.szName, "P%i Buttons 23", nPlayer + 1);
771 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]);
772 			pgi->Macro.pVal[0] = bii.pVal;
773 			pgi->Macro.nVal[0] = 1;
774 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]);
775 			pgi->Macro.pVal[1] = bii.pVal;
776 			pgi->Macro.nVal[1] = 1;
777 			nMacroCount++;
778 			pgi++;
779 
780 			pgi->nInput = GIT_MACRO_AUTO;
781 			pgi->nType = BIT_DIGITAL;
782 			pgi->Macro.nMode = 0;
783 			sprintf(pgi->Macro.szName, "P%i Buttons 24", nPlayer + 1);
784 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]);
785 			pgi->Macro.pVal[0] = bii.pVal;
786 			pgi->Macro.nVal[0] = 1;
787 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]);
788 			pgi->Macro.pVal[1] = bii.pVal;
789 			pgi->Macro.nVal[1] = 1;
790 			nMacroCount++;
791 			pgi++;
792 
793 			pgi->nInput = GIT_MACRO_AUTO;
794 			pgi->nType = BIT_DIGITAL;
795 			pgi->Macro.nMode = 0;
796 			sprintf(pgi->Macro.szName, "P%i Buttons 34", nPlayer + 1);
797 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]);
798 			pgi->Macro.pVal[0] = bii.pVal;
799 			pgi->Macro.nVal[0] = 1;
800 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]);
801 			pgi->Macro.pVal[1] = bii.pVal;
802 			pgi->Macro.nVal[1] = 1;
803 			nMacroCount++;
804 			pgi++;
805 
806 			pgi->nInput = GIT_MACRO_AUTO;
807 			pgi->nType = BIT_DIGITAL;
808 			pgi->Macro.nMode = 0;
809 			sprintf(pgi->Macro.szName, "P%i Buttons 123", nPlayer + 1);
810 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]);
811 			pgi->Macro.pVal[0] = bii.pVal;
812 			pgi->Macro.nVal[0] = 1;
813 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]);
814 			pgi->Macro.pVal[1] = bii.pVal;
815 			pgi->Macro.nVal[1] = 1;
816 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]);
817 			pgi->Macro.pVal[2] = bii.pVal;
818 			pgi->Macro.nVal[2] = 1;
819 			nMacroCount++;
820 			pgi++;
821 
822 			pgi->nInput = GIT_MACRO_AUTO;
823 			pgi->nType = BIT_DIGITAL;
824 			pgi->Macro.nMode = 0;
825 			sprintf(pgi->Macro.szName, "P%i Buttons 124", nPlayer + 1);
826 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]);
827 			pgi->Macro.pVal[0] = bii.pVal;
828 			pgi->Macro.nVal[0] = 1;
829 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]);
830 			pgi->Macro.pVal[1] = bii.pVal;
831 			pgi->Macro.nVal[1] = 1;
832 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]);
833 			pgi->Macro.pVal[2] = bii.pVal;
834 			pgi->Macro.nVal[2] = 1;
835 			nMacroCount++;
836 			pgi++;
837 
838 			pgi->nInput = GIT_MACRO_AUTO;
839 			pgi->nType = BIT_DIGITAL;
840 			pgi->Macro.nMode = 0;
841 			sprintf(pgi->Macro.szName, "P%i Buttons 134", nPlayer + 1);
842 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]);
843 			pgi->Macro.pVal[0] = bii.pVal;
844 			pgi->Macro.nVal[0] = 1;
845 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]);
846 			pgi->Macro.pVal[1] = bii.pVal;
847 			pgi->Macro.nVal[1] = 1;
848 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]);
849 			pgi->Macro.pVal[2] = bii.pVal;
850 			pgi->Macro.nVal[2] = 1;
851 			nMacroCount++;
852 			pgi++;
853 
854 			pgi->nInput = GIT_MACRO_AUTO;
855 			pgi->nType = BIT_DIGITAL;
856 			pgi->Macro.nMode = 0;
857 			sprintf(pgi->Macro.szName, "P%i Buttons 234", nPlayer + 1);
858 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]);
859 			pgi->Macro.pVal[0] = bii.pVal;
860 			pgi->Macro.nVal[0] = 1;
861 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]);
862 			pgi->Macro.pVal[1] = bii.pVal;
863 			pgi->Macro.nVal[1] = 1;
864 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]);
865 			pgi->Macro.pVal[2] = bii.pVal;
866 			pgi->Macro.nVal[2] = 1;
867 			nMacroCount++;
868 			pgi++;
869 
870 			pgi->nInput = GIT_MACRO_AUTO;
871 			pgi->nType = BIT_DIGITAL;
872 			pgi->Macro.nMode = 0;
873 			sprintf(pgi->Macro.szName, "P%i Buttons 1234", nPlayer + 1);
874 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]);
875 			pgi->Macro.pVal[0] = bii.pVal;
876 			pgi->Macro.nVal[0] = 1;
877 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]);
878 			pgi->Macro.pVal[1] = bii.pVal;
879 			pgi->Macro.nVal[1] = 1;
880 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]);
881 			pgi->Macro.pVal[2] = bii.pVal;
882 			pgi->Macro.nVal[2] = 1;
883 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]);
884 			pgi->Macro.pVal[3] = bii.pVal;
885 			pgi->Macro.nVal[3] = 1;
886 			nMacroCount++;
887 			pgi++;
888 		}
889 		if (nRealButtons == 3 && HW_MISC) {
890 			pgi->nInput = GIT_MACRO_AUTO;
891 			pgi->nType = BIT_DIGITAL;
892 			pgi->Macro.nMode = 0;
893 			sprintf(pgi->Macro.szName, "P%i Buttons 12", nPlayer + 1);
894 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]);
895 			pgi->Macro.pVal[0] = bii.pVal;
896 			pgi->Macro.nVal[0] = 1;
897 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]);
898 			pgi->Macro.pVal[1] = bii.pVal;
899 			pgi->Macro.nVal[1] = 1;
900 			nMacroCount++;
901 			pgi++;
902 
903 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]); // If it's like jurassic99 ...
904 			if (_stricmp(" Coin", bii.szName + 2) != 0) {
905 				pgi->nInput = GIT_MACRO_AUTO;
906 				pgi->nType = BIT_DIGITAL;
907 				pgi->Macro.nMode = 0;
908 				sprintf(pgi->Macro.szName, "P%i Buttons 13", nPlayer + 1);
909 				pgi->Macro.pVal[1] = bii.pVal;
910 				pgi->Macro.nVal[1] = 1;
911 				BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]);
912 				pgi->Macro.pVal[0] = bii.pVal;
913 				pgi->Macro.nVal[0] = 1;
914 				nMacroCount++;
915 				pgi++;
916 			}
917 
918 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]); // If it's like jurassic99 ...
919 			if (_stricmp(" Coin", bii.szName + 2) != 0) {
920 				pgi->nInput = GIT_MACRO_AUTO;
921 				pgi->nType = BIT_DIGITAL;
922 				pgi->Macro.nMode = 0;
923 				sprintf(pgi->Macro.szName, "P%i Buttons 23", nPlayer + 1);
924 				pgi->Macro.pVal[1] = bii.pVal;
925 				pgi->Macro.nVal[1] = 1;
926 				BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]);
927 				pgi->Macro.pVal[0] = bii.pVal;
928 				pgi->Macro.nVal[0] = 1;
929 				nMacroCount++;
930 				pgi++;
931 			}
932 
933 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]); // If it's like jurassic99 ...
934 			if (_stricmp(" Coin", bii.szName + 2) != 0) {
935 				pgi->nInput = GIT_MACRO_AUTO;
936 				pgi->nType = BIT_DIGITAL;
937 				pgi->Macro.nMode = 0;
938 				sprintf(pgi->Macro.szName, "P%i Buttons 123", nPlayer + 1);
939 				pgi->Macro.pVal[2] = bii.pVal;
940 				pgi->Macro.nVal[2] = 1;
941 				BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]);
942 				pgi->Macro.pVal[0] = bii.pVal;
943 				pgi->Macro.nVal[0] = 1;
944 				BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]);
945 				pgi->Macro.pVal[1] = bii.pVal;
946 				pgi->Macro.nVal[1] = 1;
947 				nMacroCount++;
948 				pgi++;
949 			}
950 		}
951 		if (nRealButtons == 2 && (HW_MISC || HW_NES)) {
952 			const char* pChar = HW_NES ? "BA" : "12";
953 			pgi->nInput = GIT_MACRO_AUTO;
954 			pgi->nType = BIT_DIGITAL;
955 			pgi->Macro.nMode = 0;
956 			sprintf(pgi->Macro.szName, "P%i Buttons %s", nPlayer + 1, pChar);
957 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]);
958 			pgi->Macro.pVal[0] = bii.pVal;
959 			pgi->Macro.nVal[0] = 1;
960 			BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]);
961 			pgi->Macro.pVal[1] = bii.pVal;
962 			pgi->Macro.nVal[1] = 1;
963 			nMacroCount++;
964 			pgi++;
965 		}
966 		if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_MEGADRIVE) {
967 			pgi->nInput = GIT_MACRO_AUTO;
968 			pgi->nType = BIT_DIGITAL;
969 			pgi->Macro.nMode = 0;
970 
971 			sprintf(pgi->Macro.szName, "P%i Buttons ABC", nPlayer + 1);
972 			for (INT32 j = 0; j < 3; j++) {
973 				BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][j]);
974 				pgi->Macro.pVal[j] = bii.pVal;
975 				pgi->Macro.nVal[j] = 1;
976 			}
977 			nMacroCount++;
978 			pgi++;
979 
980 			if (nFireButtons == 6) {
981 				pgi->nInput = GIT_MACRO_AUTO;
982 				pgi->nType = BIT_DIGITAL;
983 				pgi->Macro.nMode = 0;
984 
985 				sprintf(pgi->Macro.szName, "P%i Buttons XYZ", nPlayer + 1);
986 				for (INT32 j = 0; j < 3; j++) {
987 					BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][j+3]);
988 					pgi->Macro.pVal[j] = bii.pVal;
989 					pgi->Macro.nVal[j] = 1;
990 				}
991 				nMacroCount++;
992 				pgi++;
993 			}
994 		}
995 	}
996 
997 	// LUA Hotkeys
998 	for (int hotkey_num = 0; lua_hotkeys[hotkey_num] != NULL; hotkey_num++) {
999 		char hotkey_name[40];
1000 		sprintf(hotkey_name, "Lua Hotkey %d", (hotkey_num + 1));
1001 		pgi->nInput = GIT_MACRO_AUTO;
1002 		pgi->nType = BIT_DIGITAL;
1003 		pgi->Macro.nMode = 0;
1004 		pgi->Macro.nSysMacro = 1;
1005 		sprintf(pgi->Macro.szName, hotkey_name);
1006 		pgi->Macro.pVal[0] = lua_hotkeys[hotkey_num];
1007 		pgi->Macro.nVal[0] = 1;
1008 		nMacroCount++;
1009 		pgi++;
1010 	}
1011 
1012 	if ((nPunchx3[0] == 7) && (nKickx3[0] == 7)) {
1013 		bStreetFighterLayout = true;
1014 	}
1015 	if (nFireButtons >= 7 && (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_CAPCOM_CPS2) {
1016 		// used to be 5 buttons in the above check - now we have volume buttons it is 7
1017 		bStreetFighterLayout = true;
1018 	}
1019 }
1020 
GameInpInit()1021 INT32 GameInpInit()
1022 {
1023 	INT32 nRet = 0;
1024 	// Count the number of inputs
1025 	nGameInpCount = 0;
1026 	nMacroCount = 0;
1027 	nMaxMacro = nMaxPlayers * 52;
1028 
1029 	for (UINT32 i = 0; i < 0x1000; i++) {
1030 		nRet = BurnDrvGetInputInfo(NULL,i);
1031 		if (nRet) {														// end of input list
1032 			nGameInpCount = i;
1033 			break;
1034 		}
1035 	}
1036 
1037 	// Allocate space for all the inputs
1038 	INT32 nSize = (nGameInpCount + nMaxMacro) * sizeof(struct GameInp);
1039 	GameInp = (struct GameInp*)malloc(nSize);
1040 	if (GameInp == NULL) {
1041 		return 1;
1042 	}
1043 	memset(GameInp, 0, nSize);
1044 
1045 	GameInpBlank(1);
1046 
1047 	InpDIPSWResetDIPs();
1048 
1049 	GameInpInitMacros();
1050 
1051 	nAnalogSpeed = 0x0100;
1052 
1053 	return 0;
1054 }
1055 
GameInpExit()1056 INT32 GameInpExit()
1057 {
1058 	if (GameInp) {
1059 		free(GameInp);
1060 		GameInp = NULL;
1061 	}
1062 
1063 	nGameInpCount = 0;
1064 	nMacroCount = 0;
1065 
1066 	nFireButtons = 0;
1067 
1068 	bStreetFighterLayout = false;
1069 	bLeftAltkeyMapped = false;
1070 
1071 	return 0;
1072 }
1073 
1074 // ---------------------------------------------------------------------------
1075 // Convert a string from a config file to an input
1076 
SliderInfo(struct GameInp * pgi,TCHAR * s)1077 static TCHAR* SliderInfo(struct GameInp* pgi, TCHAR* s)
1078 {
1079 	TCHAR* szRet = NULL;
1080 	pgi->Input.Slider.nSliderSpeed = 0x700;				// defaults
1081 	pgi->Input.Slider.nSliderCenter = 0;
1082 	pgi->Input.Slider.nSliderValue = 0x8000;
1083 
1084 	szRet = LabelCheck(s, _T("speed"));
1085 	s = szRet;
1086 	if (s == NULL) {
1087 		return s;
1088 	}
1089 	pgi->Input.Slider.nSliderSpeed = (INT16)_tcstol(s, &szRet, 0);
1090 	s = szRet;
1091 	if (s==NULL) {
1092 		return s;
1093 	}
1094 	szRet = LabelCheck(s, _T("center"));
1095 	s = szRet;
1096 	if (s == NULL) {
1097 		return s;
1098 	}
1099 	pgi->Input.Slider.nSliderCenter = (INT16)_tcstol(s, &szRet, 0);
1100 	s = szRet;
1101 	if (s == NULL) {
1102 		return s;
1103 	}
1104 
1105 	return szRet;
1106 }
1107 
StringToJoyAxis(struct GameInp * pgi,TCHAR * s)1108 static INT32 StringToJoyAxis(struct GameInp* pgi, TCHAR* s)
1109 {
1110 	TCHAR* szRet = s;
1111 
1112 	pgi->Input.JoyAxis.nJoy = (UINT8)_tcstol(s, &szRet, 0);
1113 	if (szRet == NULL) {
1114 		return 1;
1115 	}
1116 	s = szRet;
1117 	pgi->Input.JoyAxis.nAxis = (UINT8)_tcstol(s, &szRet, 0);
1118 	if (szRet == NULL) {
1119 		return 1;
1120 	}
1121 
1122 	return 0;
1123 }
1124 
StringToMouseAxis(struct GameInp * pgi,TCHAR * s)1125 static INT32 StringToMouseAxis(struct GameInp* pgi, TCHAR* s)
1126 {
1127 	TCHAR* szRet = s;
1128 
1129 	pgi->Input.MouseAxis.nAxis = (UINT8)_tcstol(s, &szRet, 0);
1130 	if (szRet == NULL) {
1131 		return 1;
1132 	}
1133 
1134 	return 0;
1135 }
1136 
StringToMacro(struct GameInp * pgi,TCHAR * s)1137 static INT32 StringToMacro(struct GameInp* pgi, TCHAR* s)
1138 {
1139 	TCHAR* szRet = NULL;
1140 
1141 	szRet = LabelCheck(s, _T("switch"));
1142 	if (szRet) {
1143 		s = szRet;
1144 		pgi->Macro.nMode = 0x01;
1145 		pgi->Macro.Switch.nCode = (UINT16)_tcstol(s, &szRet, 0);
1146 		return 0;
1147 	}
1148 
1149 	return 1;
1150 }
1151 
StringToInp(struct GameInp * pgi,TCHAR * s)1152 static INT32 StringToInp(struct GameInp* pgi, TCHAR* s)
1153 {
1154 	TCHAR* szRet = NULL;
1155 
1156 	SKIP_WS(s);											// skip whitespace
1157 	szRet = LabelCheck(s, _T("undefined"));
1158 	if (szRet) {
1159 		pgi->nInput = 0;
1160 		return 0;
1161 	}
1162 
1163 	szRet = LabelCheck(s, _T("constant"));
1164 	if (szRet) {
1165 		pgi->nInput = GIT_CONSTANT;
1166 		s = szRet;
1167 		pgi->Input.Constant.nConst=(UINT8)_tcstol(s, &szRet, 0);
1168 		*(pgi->Input.pVal) = pgi->Input.Constant.nConst;
1169 		return 0;
1170 	}
1171 
1172 	szRet = LabelCheck(s, _T("switch"));
1173 	if (szRet) {
1174 		pgi->nInput = GIT_SWITCH;
1175 		s = szRet;
1176 		pgi->Input.Switch.nCode = (UINT16)_tcstol(s, &szRet, 0);
1177 		return 0;
1178 	}
1179 
1180 	// Analog using mouse axis:
1181 	szRet = LabelCheck(s, _T("mouseaxis"));
1182 	if (szRet) {
1183 		pgi->nInput = GIT_MOUSEAXIS;
1184 		return StringToMouseAxis(pgi, szRet);
1185 	}
1186 	// Analog using joystick axis:
1187 	szRet = LabelCheck(s, _T("joyaxis-neg"));
1188 	if (szRet) {
1189 		pgi->nInput = GIT_JOYAXIS_NEG;
1190 		return StringToJoyAxis(pgi, szRet);
1191 	}
1192 	szRet = LabelCheck(s, _T("joyaxis-pos"));
1193 	if (szRet) {
1194 		pgi->nInput = GIT_JOYAXIS_POS;
1195 		return StringToJoyAxis(pgi, szRet);
1196 	}
1197 	szRet = LabelCheck(s, _T("joyaxis"));
1198 	if (szRet) {
1199 		pgi->nInput = GIT_JOYAXIS_FULL;
1200 		return StringToJoyAxis(pgi, szRet);
1201 	}
1202 
1203 	// Analog using keyboard slider
1204 	szRet = LabelCheck(s, _T("slider"));
1205 	if (szRet) {
1206 		s = szRet;
1207 		pgi->nInput = GIT_KEYSLIDER;
1208 		pgi->Input.Slider.SliderAxis.nSlider[0] = 0;	// defaults
1209 		pgi->Input.Slider.SliderAxis.nSlider[1] = 0;	//
1210 
1211 		pgi->Input.Slider.SliderAxis.nSlider[0] = (UINT16)_tcstol(s, &szRet, 0);
1212 		s = szRet;
1213 		if (s == NULL) {
1214 			return 1;
1215 		}
1216 		pgi->Input.Slider.SliderAxis.nSlider[1] = (UINT16)_tcstol(s, &szRet, 0);
1217 		s = szRet;
1218 		if (s == NULL) {
1219 			return 1;
1220 		}
1221 		szRet = SliderInfo(pgi, s);
1222 		s = szRet;
1223 		if (s == NULL) {								// Get remaining slider info
1224 			return 1;
1225 		}
1226 		return 0;
1227 	}
1228 
1229 	// Analog using joystick slider
1230 	szRet = LabelCheck(s, _T("joyslider"));
1231 	if (szRet) {
1232 		s = szRet;
1233 		pgi->nInput = GIT_JOYSLIDER;
1234 		pgi->Input.Slider.JoyAxis.nJoy = 0;				// defaults
1235 		pgi->Input.Slider.JoyAxis.nAxis = 0;			//
1236 
1237 		pgi->Input.Slider.JoyAxis.nJoy = (UINT8)_tcstol(s, &szRet, 0);
1238 		s = szRet;
1239 		if (s == NULL) {
1240 			return 1;
1241 		}
1242 		pgi->Input.Slider.JoyAxis.nAxis = (UINT8)_tcstol(s, &szRet, 0);
1243 		s = szRet;
1244 		if (s == NULL) {
1245 			return 1;
1246 		}
1247 		szRet = SliderInfo(pgi, s);						// Get remaining slider info
1248 		s = szRet;
1249 		if (s == NULL) {
1250 			return 1;
1251 		}
1252 		return 0;
1253 	}
1254 
1255 	return 1;
1256 }
1257 
1258 // ---------------------------------------------------------------------------
1259 // Convert an input to a string for config files
1260 
InpToString(struct GameInp * pgi)1261 TCHAR* InpToString(struct GameInp* pgi)
1262 {
1263 	static TCHAR szString[80];
1264 
1265 	if (pgi->nInput == 0) {
1266 		return _T("undefined");
1267 	}
1268 	if (pgi->nInput == GIT_CONSTANT) {
1269 		_stprintf(szString, _T("constant 0x%.2X"), pgi->Input.Constant.nConst);
1270 		return szString;
1271 	}
1272 	if (pgi->nInput == GIT_SWITCH) {
1273 		_stprintf(szString, _T("switch 0x%.2X"), pgi->Input.Switch.nCode);
1274 		return szString;
1275 	}
1276 	if (pgi->nInput == GIT_KEYSLIDER) {
1277 		_stprintf(szString, _T("slider 0x%.2x 0x%.2x speed 0x%x center %d"), pgi->Input.Slider.SliderAxis.nSlider[0], pgi->Input.Slider.SliderAxis.nSlider[1], pgi->Input.Slider.nSliderSpeed, pgi->Input.Slider.nSliderCenter);
1278 		return szString;
1279 	}
1280 	if (pgi->nInput == GIT_JOYSLIDER) {
1281 		_stprintf(szString, _T("joyslider %d %d speed 0x%x center %d"), pgi->Input.Slider.JoyAxis.nJoy, pgi->Input.Slider.JoyAxis.nAxis, pgi->Input.Slider.nSliderSpeed, pgi->Input.Slider.nSliderCenter);
1282 		return szString;
1283 	}
1284 	if (pgi->nInput == GIT_MOUSEAXIS) {
1285 		_stprintf(szString, _T("mouseaxis %d"), pgi->Input.MouseAxis.nAxis);
1286 		return szString;
1287 	}
1288 	if (pgi->nInput == GIT_JOYAXIS_FULL) {
1289 		_stprintf(szString, _T("joyaxis %d %d"), pgi->Input.JoyAxis.nJoy, pgi->Input.JoyAxis.nAxis);
1290 		return szString;
1291 	}
1292 	if (pgi->nInput == GIT_JOYAXIS_NEG) {
1293 		_stprintf(szString, _T("joyaxis-neg %d %d"), pgi->Input.JoyAxis.nJoy, pgi->Input.JoyAxis.nAxis);
1294 		return szString;
1295 	}
1296 	if (pgi->nInput == GIT_JOYAXIS_POS) {
1297 		_stprintf(szString, _T("joyaxis-pos %d %d"), pgi->Input.JoyAxis.nJoy, pgi->Input.JoyAxis.nAxis);
1298 		return szString;
1299 	}
1300 
1301 	return _T("unknown");
1302 }
1303 
InpMacroToString(struct GameInp * pgi)1304 TCHAR* InpMacroToString(struct GameInp* pgi)
1305 {
1306 	static TCHAR szString[256];
1307 
1308 	if (pgi->nInput == GIT_MACRO_AUTO) {
1309 		if (pgi->Macro.nMode) {
1310 			_stprintf(szString, _T("switch 0x%.2X"), pgi->Macro.Switch.nCode);
1311 			return szString;
1312 		}
1313 	}
1314 
1315 	if (pgi->nInput == GIT_MACRO_CUSTOM) {
1316 		struct BurnInputInfo bii;
1317 
1318 		if (pgi->Macro.nMode) {
1319 			_stprintf(szString, _T("switch 0x%.2X"), pgi->Macro.Switch.nCode);
1320 		} else {
1321 			_stprintf(szString, _T("undefined"));
1322 		}
1323 
1324 		for (INT32 i = 0; i < 4; i++) {
1325 			if (pgi->Macro.pVal[i]) {
1326 				BurnDrvGetInputInfo(&bii, pgi->Macro.nInput[i]);
1327 				_stprintf(szString + _tcslen(szString), _T(" \"%hs\" 0x%02X"), bii.szName, pgi->Macro.nVal[i]);
1328 			}
1329 		}
1330 
1331 		return szString;
1332 	}
1333 
1334 	return _T("undefined");
1335 }
1336 
1337 // ---------------------------------------------------------------------------
1338 // Generate a user-friendly name for a control (PC-side)
1339 
1340 static struct { INT32 nCode; TCHAR* szName; } KeyNames[] = {
1341 
1342 #define FBK_DEFNAME(k) k, _T(#k)
1343 
1344 	{ FBK_ESCAPE,				_T("ESCAPE") },
1345 	{ FBK_1,					_T("1") },
1346 	{ FBK_2,					_T("2") },
1347 	{ FBK_3,					_T("3") },
1348 	{ FBK_4,					_T("4") },
1349 	{ FBK_5,					_T("5") },
1350 	{ FBK_6,					_T("6") },
1351 	{ FBK_7,					_T("7") },
1352 	{ FBK_8,					_T("8") },
1353 	{ FBK_9,					_T("9") },
1354 	{ FBK_0,					_T("0") },
1355 	{ FBK_MINUS,				_T("MINUS") },
1356 	{ FBK_EQUALS,				_T("EQUALS") },
1357 	{ FBK_BACK,					_T("BACKSPACE") },
1358 	{ FBK_TAB,					_T("TAB") },
1359 	{ FBK_Q,					_T("Q") },
1360 	{ FBK_W,					_T("W") },
1361 	{ FBK_E,					_T("E") },
1362 	{ FBK_R,					_T("R") },
1363 	{ FBK_T,					_T("T") },
1364 	{ FBK_Y,					_T("Y") },
1365 	{ FBK_U,					_T("U") },
1366 	{ FBK_I,					_T("I") },
1367 	{ FBK_O,					_T("O") },
1368 	{ FBK_P,					_T("P") },
1369 	{ FBK_LBRACKET,				_T("OPENING BRACKET") },
1370 	{ FBK_RBRACKET,				_T("CLOSING BRACKET") },
1371 	{ FBK_RETURN,				_T("ENTER") },
1372 	{ FBK_LCONTROL,				_T("LEFT CONTROL") },
1373 	{ FBK_A,					_T("A") },
1374 	{ FBK_S,					_T("S") },
1375 	{ FBK_D,					_T("D") },
1376 	{ FBK_F,					_T("F") },
1377 	{ FBK_G,					_T("G") },
1378 	{ FBK_H,					_T("H") },
1379 	{ FBK_J,					_T("J") },
1380 	{ FBK_K,					_T("K") },
1381 	{ FBK_L,					_T("L") },
1382 	{ FBK_SEMICOLON,			_T("SEMICOLON") },
1383 	{ FBK_APOSTROPHE,			_T("APOSTROPHE") },
1384 	{ FBK_GRAVE,				_T("ACCENT GRAVE") },
1385 	{ FBK_LSHIFT,				_T("LEFT SHIFT") },
1386 	{ FBK_BACKSLASH,			_T("BACKSLASH") },
1387 	{ FBK_Z,					_T("Z") },
1388 	{ FBK_X,					_T("X") },
1389 	{ FBK_C,					_T("C") },
1390 	{ FBK_V,					_T("V") },
1391 	{ FBK_B,					_T("B") },
1392 	{ FBK_N,					_T("N") },
1393 	{ FBK_M,					_T("M") },
1394 	{ FBK_COMMA,				_T("COMMA") },
1395 	{ FBK_PERIOD,				_T("PERIOD") },
1396 	{ FBK_SLASH,				_T("SLASH") },
1397 	{ FBK_RSHIFT,				_T("RIGHT SHIFT") },
1398 	{ FBK_MULTIPLY,				_T("NUMPAD MULTIPLY") },
1399 	{ FBK_LALT,					_T("LEFT MENU") },
1400 	{ FBK_SPACE,				_T("SPACE") },
1401 	{ FBK_CAPITAL,				_T("CAPSLOCK") },
1402 	{ FBK_F1,					_T("F1") },
1403 	{ FBK_F2,					_T("F2") },
1404 	{ FBK_F3,					_T("F3") },
1405 	{ FBK_F4,					_T("F4") },
1406 	{ FBK_F5,					_T("F5") },
1407 	{ FBK_F6,					_T("F6") },
1408 	{ FBK_F7,					_T("F7") },
1409 	{ FBK_F8,					_T("F8") },
1410 	{ FBK_F9,					_T("F9") },
1411 	{ FBK_F10,					_T("F10") },
1412 	{ FBK_NUMLOCK,				_T("NUMLOCK") },
1413 	{ FBK_SCROLL,				_T("SCROLLLOCK") },
1414 	{ FBK_NUMPAD7,				_T("NUMPAD 7") },
1415 	{ FBK_NUMPAD8,				_T("NUMPAD 8") },
1416 	{ FBK_NUMPAD9,				_T("NUMPAD 9") },
1417 	{ FBK_SUBTRACT,				_T("NUMPAD SUBTRACT") },
1418 	{ FBK_NUMPAD4,				_T("NUMPAD 4") },
1419 	{ FBK_NUMPAD5,				_T("NUMPAD 5") },
1420 	{ FBK_NUMPAD6,				_T("NUMPAD 6") },
1421 	{ FBK_ADD,					_T("NUMPAD ADD") },
1422 	{ FBK_NUMPAD1,				_T("NUMPAD 1") },
1423 	{ FBK_NUMPAD2,				_T("NUMPAD 2") },
1424 	{ FBK_NUMPAD3,				_T("NUMPAD 3") },
1425 	{ FBK_NUMPAD0,				_T("NUMPAD 0") },
1426 	{ FBK_DECIMAL,				_T("NUMPAD DECIMAL POINT") },
1427 	{ FBK_DEFNAME(FBK_OEM_102) },
1428 	{ FBK_F11,					_T("F11") },
1429 	{ FBK_F12,					_T("F12") },
1430 	{ FBK_F13,					_T("F13") },
1431 	{ FBK_F14,					_T("F14") },
1432 	{ FBK_F15,					_T("F15") },
1433 	{ FBK_DEFNAME(FBK_KANA) },
1434 	{ FBK_DEFNAME(FBK_ABNT_C1) },
1435 	{ FBK_DEFNAME(FBK_CONVERT) },
1436 	{ FBK_DEFNAME(FBK_NOCONVERT) },
1437 	{ FBK_DEFNAME(FBK_YEN) },
1438 	{ FBK_DEFNAME(FBK_ABNT_C2) },
1439 	{ FBK_NUMPADEQUALS,			_T("NUMPAD EQUALS") },
1440 	{ FBK_DEFNAME(FBK_PREVTRACK) },
1441 	{ FBK_DEFNAME(FBK_AT) },
1442 	{ FBK_COLON,				_T("COLON") },
1443 	{ FBK_UNDERLINE,			_T("UNDERSCORE") },
1444 	{ FBK_DEFNAME(FBK_KANJI) },
1445 	{ FBK_DEFNAME(FBK_STOP) },
1446 	{ FBK_DEFNAME(FBK_AX) },
1447 	{ FBK_DEFNAME(FBK_UNLABELED) },
1448 	{ FBK_DEFNAME(FBK_NEXTTRACK) },
1449 	{ FBK_NUMPADENTER,			_T("NUMPAD ENTER") },
1450 	{ FBK_RCONTROL,				_T("RIGHT CONTROL") },
1451 	{ FBK_DEFNAME(FBK_MUTE) },
1452 	{ FBK_DEFNAME(FBK_CALCULATOR) },
1453 	{ FBK_DEFNAME(FBK_PLAYPAUSE) },
1454 	{ FBK_DEFNAME(FBK_MEDIASTOP) },
1455 	{ FBK_DEFNAME(FBK_VOLUMEDOWN) },
1456 	{ FBK_DEFNAME(FBK_VOLUMEUP) },
1457 	{ FBK_DEFNAME(FBK_WEBHOME) },
1458 	{ FBK_DEFNAME(FBK_NUMPADCOMMA) },
1459 	{ FBK_DIVIDE,				_T("NUMPAD DIVIDE") },
1460 	{ FBK_SYSRQ,				_T("PRINTSCREEN") },
1461 	{ FBK_RALT,					_T("RIGHT MENU") },
1462 	{ FBK_PAUSE,				_T("PAUSE") },
1463 	{ FBK_HOME,					_T("HOME") },
1464 	{ FBK_UPARROW,				_T("ARROW UP") },
1465 	{ FBK_PRIOR,				_T("PAGE UP") },
1466 	{ FBK_LEFTARROW,			_T("ARROW LEFT") },
1467 	{ FBK_RIGHTARROW,			_T("ARROW RIGHT") },
1468 	{ FBK_END,					_T("END") },
1469 	{ FBK_DOWNARROW,			_T("ARROW DOWN") },
1470 	{ FBK_NEXT,					_T("PAGE DOWN") },
1471 	{ FBK_INSERT,				_T("INSERT") },
1472 	{ FBK_DELETE,				_T("DELETE") },
1473 	{ FBK_LWIN,					_T("LEFT WINDOWS") },
1474 	{ FBK_RWIN,					_T("RIGHT WINDOWS") },
1475 	{ FBK_DEFNAME(FBK_APPS) },
1476 	{ FBK_DEFNAME(FBK_POWER) },
1477 	{ FBK_DEFNAME(FBK_SLEEP) },
1478 	{ FBK_DEFNAME(FBK_WAKE) },
1479 	{ FBK_DEFNAME(FBK_WEBSEARCH) },
1480 	{ FBK_DEFNAME(FBK_WEBFAVORITES) },
1481 	{ FBK_DEFNAME(FBK_WEBREFRESH) },
1482 	{ FBK_DEFNAME(FBK_WEBSTOP) },
1483 	{ FBK_DEFNAME(FBK_WEBFORWARD) },
1484 	{ FBK_DEFNAME(FBK_WEBBACK) },
1485 	{ FBK_DEFNAME(FBK_MYCOMPUTER) },
1486 	{ FBK_DEFNAME(FBK_MAIL) },
1487 	{ FBK_DEFNAME(FBK_MEDIASELECT) },
1488 
1489 #undef FBK_DEFNAME
1490 
1491 	{ 0,				NULL }
1492 };
1493 
InputCodeDesc(INT32 c)1494 TCHAR* InputCodeDesc(INT32 c)
1495 {
1496 	static TCHAR szString[64];
1497 	TCHAR* szName = _T("");
1498 
1499 	// Mouse
1500 	if (c >= 0x8000) {
1501 		INT32 nMouse = (c >> 8) & 0x3F;
1502 		INT32 nCode = c & 0xFF;
1503 		if (nCode >= 0x80) {
1504 			_stprintf(szString, _T("Mouse %d Button %d"), nMouse, nCode & 0x7F);
1505 			return szString;
1506 		}
1507 		if (nCode < 0x06) {
1508 			TCHAR szAxis[3][3] = { _T("X"), _T("Y"), _T("Z") };
1509 			TCHAR szDir[6][16] = { _T("negative"), _T("positive"), _T("Left"), _T("Right"), _T("Up"), _T("Down") };
1510 			if (nCode < 4) {
1511 				_stprintf(szString, _T("Mouse %d %s (%s %s)"), nMouse, szDir[nCode + 2], szAxis[nCode >> 1], szDir[nCode & 1]);
1512 			} else {
1513 				_stprintf(szString, _T("Mouse %d %s %s"), nMouse, szAxis[nCode >> 1], szDir[nCode & 1]);
1514 			}
1515 			return szString;
1516 		}
1517 	}
1518 
1519 	// Joystick
1520 	if (c >= 0x4000 && c < 0x8000) {
1521 		INT32 nJoy = (c >> 8) & 0x3F;
1522 		INT32 nCode = c & 0xFF;
1523 		if (nCode >= 0x80) {
1524 			_stprintf(szString, _T("Joy %d Button %d"), nJoy, nCode & 0x7F);
1525 			return szString;
1526 		}
1527 		if (nCode < 0x10) {
1528 			TCHAR szAxis[8][3] = { _T("X"), _T("Y"), _T("Z"), _T("rX"), _T("rY"), _T("rZ"), _T("s0"), _T("s1") };
1529 			TCHAR szDir[6][16] = { _T("negative"), _T("positive"), _T("Left"), _T("Right"), _T("Up"), _T("Down") };
1530 			if (nCode < 4) {
1531 				_stprintf(szString, _T("Joy %d %s (%s %s)"), nJoy, szDir[nCode + 2], szAxis[nCode >> 1], szDir[nCode & 1]);
1532 			} else {
1533 				_stprintf(szString, _T("Joy %d %s %s"), nJoy, szAxis[nCode >> 1], szDir[nCode & 1]);
1534 			}
1535 			return szString;
1536 		}
1537 		if (nCode < 0x20) {
1538 			TCHAR szDir[4][16] = { _T("Left"), _T("Right"), _T("Up"), _T("Down") };
1539 			_stprintf(szString, _T("Joy %d POV-hat %d %s"), nJoy, (nCode & 0x0F) >> 2, szDir[nCode & 3]);
1540 			return szString;
1541 		}
1542 	}
1543 
1544 	for (INT32 i = 0; KeyNames[i].nCode; i++) {
1545 		if (c == KeyNames[i].nCode) {
1546 			if (KeyNames[i].szName) {
1547 				szName = KeyNames[i].szName;
1548 			}
1549 			break;
1550 		}
1551 	}
1552 
1553 	if (szName[0]) {
1554 		_stprintf(szString, _T("%s"), szName);
1555 	} else {
1556 		_stprintf(szString, _T("code 0x%.2X"), c);
1557 	}
1558 
1559 	return szString;
1560 }
1561 
InpToDesc(struct GameInp * pgi)1562 TCHAR* InpToDesc(struct GameInp* pgi)
1563 {
1564 	static TCHAR szInputName[64] = _T("");
1565 
1566 	if (pgi->nInput == 0) {
1567 		return _T("");
1568 	}
1569 	if (pgi->nInput == GIT_CONSTANT) {
1570 		if (pgi->nType & BIT_GROUP_CONSTANT) {
1571 			for (INT32 i = 0; i < 8; i++) {
1572 				szInputName[7 - i] = pgi->Input.Constant.nConst & (1 << i) ? _T('1') : _T('0');
1573 			}
1574 			szInputName[8] = 0;
1575 
1576 			return szInputName;
1577 		}
1578 
1579 		if (pgi->Input.Constant.nConst == 0) {
1580 			return _T("-");
1581 		}
1582 	}
1583 	if (pgi->nInput == GIT_SWITCH) {
1584 		return InputCodeDesc(pgi->Input.Switch.nCode);
1585 	}
1586 	if (pgi->nInput == GIT_MOUSEAXIS) {
1587 		TCHAR nAxis = _T('?');
1588 		switch (pgi->Input.MouseAxis.nAxis) {
1589 			case 0:
1590 				nAxis = _T('X');
1591 				break;
1592 			case 1:
1593 				nAxis = _T('Y');
1594 				break;
1595 			case 2:
1596 				nAxis = _T('Z');
1597 				break;
1598 		}
1599 		_stprintf(szInputName, _T("Mouse %i %c axis"), pgi->Input.MouseAxis.nMouse, nAxis);
1600 		return szInputName;
1601 	}
1602 	if (pgi->nInput & GIT_GROUP_JOYSTICK) {
1603 		TCHAR szAxis[8][3] = { _T("X"), _T("Y"), _T("Z"), _T("rX"), _T("rY"), _T("rZ"), _T("s0"), _T("s1") };
1604 		TCHAR szRange[4][16] = { _T("unknown"), _T("full"), _T("negative"), _T("positive") };
1605 		INT32 nRange = 0;
1606 		switch (pgi->nInput) {
1607 			case GIT_JOYAXIS_FULL:
1608 				nRange = 1;
1609 				break;
1610 			case GIT_JOYAXIS_NEG:
1611 				nRange = 2;
1612 				break;
1613 			case GIT_JOYAXIS_POS:
1614 				nRange = 3;
1615 				break;
1616 		}
1617 
1618 		_stprintf(szInputName, _T("Joy %d %s axis (%s range)"), pgi->Input.JoyAxis.nJoy, szAxis[pgi->Input.JoyAxis.nAxis], szRange[nRange]);
1619 		return szInputName;
1620 	}
1621 
1622 	return InpToString(pgi);							// Just do the rest as they are in the config file
1623 }
1624 
InpMacroToDesc(struct GameInp * pgi)1625 TCHAR* InpMacroToDesc(struct GameInp* pgi)
1626 {
1627 	if (pgi->nInput & GIT_GROUP_MACRO) {
1628 		if (pgi->Macro.nMode) {
1629 			return InputCodeDesc(pgi->Macro.Switch.nCode);
1630 		}
1631 	}
1632 
1633 	return _T("");
1634 }
1635 
1636 // ---------------------------------------------------------------------------
1637 
1638 // Find the input number by info
InputInfoToNum(TCHAR * szName)1639 static UINT32 InputInfoToNum(TCHAR* szName)
1640 {
1641 	for (UINT32 i = 0; i < nGameInpCount; i++) {
1642 		struct BurnInputInfo bii;
1643 		BurnDrvGetInputInfo(&bii, i);
1644 		if (bii.pVal == NULL) {
1645 			continue;
1646 		}
1647 
1648 		if (_tcsicmp(szName, ANSIToTCHAR(bii.szInfo, NULL, 0)) == 0) {
1649 			return i;
1650 		}
1651 	}
1652 	return ~0U;
1653 }
1654 
1655 // Find the input number by name
InputNameToNum(TCHAR * szName)1656 static UINT32 InputNameToNum(TCHAR* szName)
1657 {
1658 	for (UINT32 i = 0; i < nGameInpCount; i++) {
1659 		struct BurnInputInfo bii;
1660 		BurnDrvGetInputInfo(&bii, i);
1661 		if (bii.pVal == NULL) {
1662 			continue;
1663 		}
1664 
1665 		if (_tcsicmp(szName, ANSIToTCHAR(bii.szName, NULL, 0)) == 0) {
1666 			return i;
1667 		}
1668 	}
1669 	return ~0U;
1670 }
1671 
InputNumToName(UINT32 i)1672 TCHAR* InputNumToName(UINT32 i)
1673 {
1674 	struct BurnInputInfo bii;
1675 	bii.szName = NULL;
1676 	BurnDrvGetInputInfo(&bii, i);
1677 	if (bii.szName == NULL) {
1678 		return _T("unknown");
1679 	}
1680 	return ANSIToTCHAR(bii.szName, NULL, 0);
1681 }
1682 
MacroNameToNum(TCHAR * szName)1683 static UINT32 MacroNameToNum(TCHAR* szName)
1684 {
1685 	struct GameInp* pgi = GameInp + nGameInpCount;
1686 	for (UINT32 i = 0; i < nMacroCount; i++, pgi++) {
1687 		if (pgi->nInput & GIT_GROUP_MACRO) {
1688 			if (_tcsicmp(szName, ANSIToTCHAR(pgi->Macro.szName, NULL, 0)) == 0) {
1689 				return i;
1690 			}
1691 		}
1692 	}
1693 	return ~0U;
1694 }
1695 
1696 // ---------------------------------------------------------------------------
1697 
GameInpAutoOne(struct GameInp * pgi,char * szi)1698 static INT32 GameInpAutoOne(struct GameInp* pgi, char* szi)
1699 {
1700 	for (INT32 i = 0; i < nMaxPlayers; i++) {
1701 		INT32 nSlide = nPlayerDefaultControls[i] >> 4;
1702 		switch (nPlayerDefaultControls[i] & 0x0F) {
1703 			case 0:										// Keyboard
1704 				GamcAnalogKey(pgi, szi, i, nSlide);
1705 				GamcPlayer(pgi, szi, i, -1);
1706 				GamcMisc(pgi, szi, i);
1707 				break;
1708 			case 1:										// Joystick 1
1709 				GamcAnalogJoy(pgi, szi, i, 0, nSlide);
1710 				GamcPlayer(pgi, szi, i, 0);
1711 				GamcMisc(pgi, szi, i);
1712 				break;
1713 			case 2:										// Joystick 2
1714 				GamcAnalogJoy(pgi, szi, i, 1, nSlide);
1715 				GamcPlayer(pgi, szi, i, 1);
1716 				GamcMisc(pgi, szi, i);
1717 				break;
1718 			case 3:										// Joystick 3
1719 				GamcAnalogJoy(pgi, szi, i, 2, nSlide);
1720 				GamcPlayer(pgi, szi, i, 2);
1721 				GamcMisc(pgi, szi, i);
1722 				break;
1723 			case 4:										// X-Arcade left side
1724 				GamcMisc(pgi, szi, i);
1725 				GamcPlayerHotRod(pgi, szi, i, 0x10, nSlide);
1726 				break;
1727 			case 5:										// X-Arcade right side
1728 				GamcMisc(pgi, szi, i);
1729 				GamcPlayerHotRod(pgi, szi, i, 0x11, nSlide);
1730 				break;
1731 			case 6:										// Hot Rod left side
1732 				GamcMisc(pgi, szi, i);
1733 				GamcPlayerHotRod(pgi, szi, i, 0x00, nSlide);
1734 				break;
1735 			case 7:										// Hot Rod right side
1736 				GamcMisc(pgi, szi, i);
1737 				GamcPlayerHotRod(pgi, szi, i, 0x01, nSlide);
1738 				break;
1739 			default:
1740 				GamcMisc(pgi, szi, i);
1741 		}
1742 	}
1743 
1744 	return 0;
1745 }
1746 
AddCustomMacro(TCHAR * szValue,bool bOverWrite)1747 static INT32 AddCustomMacro(TCHAR* szValue, bool bOverWrite)
1748 {
1749 	TCHAR* szQuote = NULL;
1750 	TCHAR* szEnd = NULL;
1751 
1752 	if (QuoteRead(&szQuote, &szEnd, szValue)) {
1753 		return 1;
1754 	}
1755 
1756 	INT32 nMode = -1;
1757 	INT32 nInput = -1;
1758 	bool bCreateNew = false;
1759 	struct BurnInputInfo bii;
1760 
1761 	for (UINT32 j = nGameInpCount; j < nGameInpCount + nMacroCount; j++) {
1762 		if (GameInp[j].nInput == GIT_MACRO_CUSTOM) {
1763 			if (LabelCheck(szQuote, ANSIToTCHAR(GameInp[j].Macro.szName, NULL, 0))) {
1764 				nInput = j;
1765 				break;
1766 			}
1767 		}
1768 	}
1769 
1770 	if (nInput == -1) {
1771 		if (nMacroCount + 1 == nMaxMacro) {
1772 			return 1;
1773 		}
1774 		nInput = nGameInpCount + nMacroCount;
1775 		bCreateNew = true;
1776 	}
1777 
1778 	_tcscpy(szQuote, ANSIToTCHAR(GameInp[nInput].Macro.szName, NULL, 0));
1779 
1780 	if ((szValue = LabelCheck(szEnd, _T("undefined"))) != NULL) {
1781 		nMode = 0;
1782 	} else {
1783 		if ((szValue = LabelCheck(szEnd, _T("switch"))) != NULL) {
1784 
1785 			if (bOverWrite || GameInp[nInput].Macro.nMode == 0) {
1786 				GameInp[nInput].Macro.Switch.nCode = (UINT16)_tcstol(szValue, &szValue, 0);
1787 			}
1788 
1789 			nMode = 1;
1790 		}
1791 	}
1792 
1793 	if (nMode >= 0) {
1794 		INT32 nFound = 0;
1795 
1796 		for (INT32 i = 0; i < 4; i++) {
1797 			GameInp[nInput].Macro.pVal[i] = NULL;
1798 			GameInp[nInput].Macro.nVal[i] = 0;
1799 			GameInp[nInput].Macro.nInput[i] = 0;
1800 
1801 			if (szValue == NULL) {
1802 				break;
1803 			}
1804 
1805 			if (QuoteRead(&szQuote, &szEnd, szValue)) {
1806 				break;
1807 			}
1808 
1809 			for (UINT32 j = 0; j < nGameInpCount; j++) {
1810 				bii.szName = NULL;
1811 				BurnDrvGetInputInfo(&bii, j);
1812 				if (bii.pVal == NULL) {
1813 					continue;
1814 				}
1815 
1816 				TCHAR* szString = LabelCheck(szQuote, ANSIToTCHAR(bii.szName, NULL, 0));
1817 				if (szString && szEnd) {
1818 					GameInp[nInput].Macro.pVal[i] = bii.pVal;
1819 					GameInp[nInput].Macro.nInput[i] = j;
1820 
1821 					GameInp[nInput].Macro.nVal[i] = (UINT8)_tcstol(szEnd, &szValue, 0);
1822 
1823 					nFound++;
1824 
1825 					break;
1826 				}
1827 			}
1828 		}
1829 
1830 		if (nFound) {
1831 			if (GameInp[nInput].Macro.pVal[nFound - 1]) {
1832 				GameInp[nInput].nInput = GIT_MACRO_CUSTOM;
1833 				GameInp[nInput].Macro.nMode = nMode;
1834 				if (bCreateNew) {
1835 					nMacroCount++;
1836 				}
1837 				return 0;
1838 			}
1839 		}
1840 	}
1841 
1842 	return 1;
1843 }
1844 
GameInputAutoIni(INT32 nPlayer,TCHAR * lpszFile,bool bOverWrite)1845 INT32 GameInputAutoIni(INT32 nPlayer, TCHAR* lpszFile, bool bOverWrite)
1846 {
1847 	TCHAR szLine[1024];
1848 	INT32 nFileVersion = 0;
1849 	UINT32 i;
1850 
1851 	//nAnalogSpeed = 0x0100; /* this clobbers the setting read at the beginning of the file. */
1852 
1853 	FILE* h = _tfopen(lpszFile, _T("rt"));
1854 	if (h == NULL) {
1855 		return 1;
1856 	}
1857 
1858 	// Go through each line of the config file and process inputs
1859 	while (_fgetts(szLine, sizeof(szLine), h)) {
1860 		TCHAR* szValue;
1861 		INT32 nLen = _tcslen(szLine);
1862 
1863 		// Get rid of the linefeed at the end
1864 		if (szLine[nLen - 1] == 10) {
1865 			szLine[nLen - 1] = 0;
1866 			nLen--;
1867 		}
1868 
1869 		szValue = LabelCheck(szLine, _T("version"));
1870 		if (szValue) {
1871 			nFileVersion = _tcstol(szValue, NULL, 0);
1872 		}
1873 		szValue = LabelCheck(szLine, _T("analog"));
1874 		if (szValue) {
1875 			nAnalogSpeed = _tcstol(szValue, NULL, 0);
1876 		}
1877 
1878 		if (nConfigMinVersion <= nFileVersion && nFileVersion <= nBurnVer) {
1879 			szValue = LabelCheck(szLine, _T("input"));
1880 			if (szValue) {
1881 				TCHAR* szQuote = NULL;
1882 				TCHAR* szEnd = NULL;
1883 				if (QuoteRead(&szQuote, &szEnd, szValue)) {
1884 					continue;
1885 				}
1886 
1887 				if ((szQuote[0] == _T('p') || szQuote[0] == _T('P')) && szQuote[1] >= _T('1') && szQuote[1] <= _T('0') + nMaxPlayers && szQuote[2] == _T(' ')) {
1888 					if (szQuote[1] != _T('1') + nPlayer) {
1889 						continue;
1890 					}
1891 				} else {
1892 					if (nPlayer != 0) {
1893 						continue;
1894 					}
1895 				}
1896 
1897 				// Find which input number this refers to
1898 				i = InputNameToNum(szQuote);
1899 				if (i == ~0U) {
1900 					i = InputInfoToNum(szQuote);
1901 					if (i == ~0U) {
1902 						continue;
1903 					}
1904 				}
1905 
1906 				if (GameInp[i].nInput == 0 || bOverWrite) {				// Undefined - assign mapping
1907 					StringToInp(GameInp + i, szEnd);
1908 				}
1909 			}
1910 
1911 			szValue = LabelCheck(szLine, _T("macro"));
1912 			if (szValue) {
1913 				TCHAR* szQuote = NULL;
1914 				TCHAR* szEnd = NULL;
1915 				if (QuoteRead(&szQuote, &szEnd, szValue)) {
1916 					continue;
1917 				}
1918 
1919 				i = MacroNameToNum(szQuote);
1920 				if (i != ~0U) {
1921 					i += nGameInpCount;
1922 					if (GameInp[i].Macro.nMode == 0 || bOverWrite) {	// Undefined - assign mapping
1923 						StringToMacro(GameInp + i, szEnd);
1924 					}
1925 				}
1926 			}
1927 
1928 			szValue = LabelCheck(szLine, _T("afire"));  // Hardware Default Preset - load autofire
1929 			if (szValue) {
1930 				TCHAR* szQuote = NULL;
1931 				TCHAR* szEnd = NULL;
1932 
1933 				if (QuoteRead(&szQuote, &szEnd, szValue)) continue;
1934 
1935 				i = MacroNameToNum(szQuote);
1936 				if (i != ~0U) {
1937 					i += nGameInpCount;
1938 					if (GameInp[i].Macro.nMode == 0 || bOverWrite) {
1939 						(GameInp + i)->Macro.nSysMacro = 15;
1940 					}
1941 				}
1942 			}
1943 
1944 			szValue = LabelCheck(szLine, _T("custom"));
1945 			if (szValue) {
1946 				AddCustomMacro(szValue, bOverWrite);
1947 			}
1948 		}
1949 	}
1950 
1951 	fclose(h);
1952 
1953 	return 0;
1954 }
1955 
1956 // Hardware description, preset file, {hardware, codes}, history.dat token
1957 tIniStruct gamehw_cfg[] = {
1958 	{_T("CPS-1/CPS-2/CPS-3 hardware"),	_T("config/presets/cps.ini"),		{ HARDWARE_CAPCOM_CPS1, HARDWARE_CAPCOM_CPS1_QSOUND, HARDWARE_CAPCOM_CPS1_GENERIC, HARDWARE_CAPCOM_CPSCHANGER, HARDWARE_CAPCOM_CPS2, HARDWARE_CAPCOM_CPS3, 0 }, "$info=" },
1959 	{_T("Neo-Geo hardware"),			_T("config/presets/neogeo.ini"),	{ HARDWARE_SNK_NEOGEO, 0 }, 		"$info="		},
1960 	{_T("Neo-Geo hardware"),			_T("config/presets/neogeo.ini"),	{ HARDWARE_SNK_NEOCD, 0 },			"$neocd="		},
1961 	{_T("Neo Geo Pocket hardware"),     _T("config/presets/ngp.ini"),       { HARDWARE_SNK_NGP, 0 },			"$ngp="			},
1962 	{_T("Neo Geo Pocket hardware"),		_T("config/presets/ngp.ini"),		{ HARDWARE_SNK_NGPC, 0 },			"$ngpc="		},
1963 	{_T("NES hardware"),				_T("config/presets/nes.ini"),		{ HARDWARE_NES, 0 },				"$nes="			},
1964 	{_T("FDS hardware"),				_T("config/presets/fds.ini"),		{ HARDWARE_FDS, 0 },				"$famicom_flop="},
1965 	{_T("PGM hardware"),				_T("config/presets/pgm.ini"),		{ HARDWARE_IGS_PGM, 0 },			"$info="        },
1966 	{_T("MegaDrive hardware"),			_T("config/presets/megadrive.ini"),	{ HARDWARE_SEGA_MEGADRIVE, 0 },		"$megadriv="	},
1967 	{_T("PCE/SGX hardware"),			_T("config/presets/pce.ini"),		{ HARDWARE_PCENGINE_PCENGINE, 0 },	"$pce="			},
1968 	{_T("TG16 hardware"),				_T("config/presets/pce.ini"),		{ HARDWARE_PCENGINE_TG16, 0 },		"$tg16="		},
1969 	{_T("MSX1 hardware"),				_T("config/presets/msx.ini"),		{ HARDWARE_MSX, 0 },				"$msx1_cart="	},
1970 	{_T("Coleco hardware"),				_T("config/presets/coleco.ini"),	{ HARDWARE_COLECO, 0 },				"$coleco="		},
1971 	{_T("SG1000 hardware"),				_T("config/presets/sg1000.ini"),	{ HARDWARE_SEGA_SG1000, 0 },		"$sg1000="		},
1972 	{_T("Sega Master System hardware"),	_T("config/presets/sms.ini"),		{ HARDWARE_SEGA_MASTER_SYSTEM, 0 },	"$sms="			},
1973 	{_T("Sega Game Gear hardware"),		_T("config/presets/gg.ini"),		{ HARDWARE_SEGA_GAME_GEAR, 0 },		"$gamegear="	},
1974 	{_T("Sinclair Spectrum hardware"),	_T("config/presets/spectrum.ini"),	{ HARDWARE_SPECTRUM, 0 },			"$spectrum_cass=" },
1975 	{_T("Fairchild Channel F hardware"),_T("config/presets/channelf.ini"),	{ HARDWARE_CHANNELF, 0 },			"$channelf="	},
1976 	{_T("\0"), _T("\0"), { 0 }, "" } // END of list
1977 };
1978 
GetHistoryDatHardwareToken(char * to_string)1979 void GetHistoryDatHardwareToken(char *to_string)
1980 {
1981 	INT32 nHardwareFlag = (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK);
1982 
1983 	// See if nHardwareFlag belongs to any systems in gamehw_config
1984 	for (INT32 i = 0; gamehw_cfg[i].ini[0] != '\0'; i++) {
1985 		for (INT32 hw = 0; gamehw_cfg[i].hw[hw] != 0; hw++) {
1986 			if (gamehw_cfg[i].hw[hw] == nHardwareFlag)
1987 			{
1988 				strcpy(to_string, gamehw_cfg[i].gameinfotoken);
1989 				return;
1990 			}
1991 		}
1992 	}
1993 
1994 	// HW not found, default to "$info=" (arcade game)
1995 	strcpy(to_string, "$info=");
1996 }
1997 
ConfigGameLoadHardwareDefaults()1998 INT32 ConfigGameLoadHardwareDefaults()
1999 {
2000 	TCHAR *szFileName = _T("");
2001 	INT32 nApplyHardwareDefaults = 0;
2002 
2003 	INT32 nHardwareFlag = (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK);
2004 
2005 	// See if nHardwareFlag belongs to any systems in gamehw_config
2006 	for (INT32 i = 0; gamehw_cfg[i].ini[0] != '\0'; i++) {
2007 		for (INT32 hw = 0; gamehw_cfg[i].hw[hw] != 0; hw++) {
2008 			if (gamehw_cfg[i].hw[hw] == nHardwareFlag)
2009 			{
2010 				szFileName = gamehw_cfg[i].ini;
2011 				nApplyHardwareDefaults = 1;
2012 				break;
2013 			}
2014 		}
2015 	}
2016 
2017 	if (nApplyHardwareDefaults) {
2018 		for (INT32 nPlayer = 0; nPlayer < nMaxPlayers; nPlayer++) {
2019 			GameInputAutoIni(nPlayer, szFileName, true);
2020 		}
2021 	}
2022 
2023 	return 0;
2024 }
2025 
2026 // Auto-configure any undefined inputs to defaults
GameInpDefault()2027 INT32 GameInpDefault()
2028 {
2029 	struct GameInp* pgi;
2030 	struct BurnInputInfo bii;
2031 	UINT32 i;
2032 
2033 	for (INT32 nPlayer = 0; nPlayer < nMaxPlayers; nPlayer++) {
2034 
2035 		if ((nPlayerDefaultControls[nPlayer] & 0x0F) != 0x0F) {
2036 			continue;
2037 		}
2038 
2039 		GameInputAutoIni(nPlayer, szPlayerDefaultIni[nPlayer], false);
2040 	}
2041 
2042 	// Fill all inputs still undefined
2043 	for (i = 0, pgi = GameInp; i < nGameInpCount; i++, pgi++) {
2044 		if (pgi->nInput) {											// Already defined - leave it alone
2045 			continue;
2046 		}
2047 
2048 		// Get the extra info about the input
2049 		bii.szInfo = NULL;
2050 		BurnDrvGetInputInfo(&bii, i);
2051 		if (bii.pVal == NULL) {
2052 			continue;
2053 		}
2054 		if (bii.szInfo == NULL) {
2055 			bii.szInfo = "";
2056 		}
2057 
2058 		// Dip switches - set to constant
2059 		if (bii.nType & BIT_GROUP_CONSTANT) {
2060 			pgi->nInput = GIT_CONSTANT;
2061 			continue;
2062 		}
2063 #ifdef BUILD_MACOS
2064         if (MacOSinpInitControls(pgi, bii.szInfo) == 0) {
2065             continue; // NOTE: prevents 'GameInpAutoOne' from being called
2066         }
2067 #endif
2068 		GameInpAutoOne(pgi, bii.szInfo);
2069 	}
2070 
2071 #ifndef BUILD_MACOS
2072 	// Fill in macros still undefined
2073 	for (i = 0; i < nMacroCount; i++, pgi++) {
2074 		if (pgi->nInput != GIT_MACRO_AUTO || pgi->Macro.nMode) {	// Already defined - leave it alone
2075 			continue;
2076 		}
2077 
2078 		GameInpAutoOne(pgi, pgi->Macro.szName);
2079 	}
2080 #endif
2081 
2082 	return 0;
2083 }
2084 
2085 // ---------------------------------------------------------------------------
2086 // Write all the GameInps out to config file 'h'
2087 
GameInpWrite(FILE * h)2088 INT32 GameInpWrite(FILE* h)
2089 {
2090 	// Write input types
2091 	for (UINT32 i = 0; i < nGameInpCount; i++) {
2092 		TCHAR* szName = NULL;
2093 		INT32 nPad = 0;
2094 		szName = InputNumToName(i);
2095 		_ftprintf(h, _T("input  \"%s\" "), szName);
2096 		nPad = 16 - _tcslen(szName);
2097 		for (INT32 j = 0; j < nPad; j++) {
2098 			_ftprintf(h, _T(" "));
2099 		}
2100 		_ftprintf(h, _T("%s\n"), InpToString(GameInp + i));
2101 	}
2102 
2103 	_ftprintf(h, _T("\n"));
2104 
2105 	struct GameInp* pgi = GameInp + nGameInpCount;
2106 	for (UINT32 i = 0; i < nMacroCount; i++, pgi++) {
2107 		INT32 nPad = 0;
2108 
2109 		if (pgi->nInput & GIT_GROUP_MACRO) {
2110 			switch (pgi->nInput) {
2111 				case GIT_MACRO_AUTO:									// Auto-assigned macros
2112 					if (pgi->Macro.nSysMacro == 15) _ftprintf(h, _T("afire  \"%hs\"\n"), pgi->Macro.szName);  // Create autofire (afire) tag
2113 					_ftprintf(h, _T("macro  \"%hs\" "), pgi->Macro.szName);
2114 					break;
2115 				case GIT_MACRO_CUSTOM:									// Custom macros
2116 					_ftprintf(h, _T("custom \"%hs\" "), pgi->Macro.szName);
2117 					break;
2118 				default:												// Unknown -- ignore
2119 					continue;
2120 			}
2121 
2122 			nPad = 16 - strlen(pgi->Macro.szName);
2123 			for (INT32 j = 0; j < nPad; j++) {
2124 				_ftprintf(h, _T(" "));
2125 			}
2126 			_ftprintf(h, _T("%s\n"), InpMacroToString(pgi));
2127 		}
2128 	}
2129 
2130 	return 0;
2131 }
2132 
2133 // ---------------------------------------------------------------------------
2134 
2135 // Read a GameInp in
GameInpRead(TCHAR * szVal,bool bOverWrite)2136 INT32 GameInpRead(TCHAR* szVal, bool bOverWrite)
2137 {
2138 	INT32 nRet;
2139 	TCHAR* szQuote = NULL;
2140 	TCHAR* szEnd = NULL;
2141 	UINT32 i = 0;
2142 
2143 	nRet = QuoteRead(&szQuote, &szEnd, szVal);
2144 	if (nRet) {
2145 		return 1;
2146 	}
2147 
2148 	// Find which input number this refers to
2149 	i = InputNameToNum(szQuote);
2150 	if (i == ~0U) {
2151 		return 1;
2152 	}
2153 
2154 	if (bOverWrite || GameInp[i].nInput == 0) {
2155 		// Parse the input description into the GameInp structure
2156 		StringToInp(GameInp + i, szEnd);
2157 	}
2158 
2159 	return 0;
2160 }
2161 
GameInpMacroRead(TCHAR * szVal,bool bOverWrite)2162 INT32 GameInpMacroRead(TCHAR* szVal, bool bOverWrite)
2163 {
2164 	INT32 nRet;
2165 	TCHAR* szQuote = NULL;
2166 	TCHAR* szEnd = NULL;
2167 	UINT32 i = 0;
2168 
2169 	nRet = QuoteRead(&szQuote, &szEnd, szVal);
2170 	if (nRet) {
2171 		return 1;
2172 	}
2173 
2174 	i = MacroNameToNum(szQuote);
2175 	if (i != ~0U) {
2176 		i += nGameInpCount;
2177 		if (GameInp[i].Macro.nMode == 0 || bOverWrite) {
2178 			StringToMacro(GameInp + i, szEnd);
2179 		}
2180 	}
2181 
2182 	return 0;
2183 }
2184 
GameMacroAutofireRead(TCHAR * szVal,bool bOverWrite)2185 INT32 GameMacroAutofireRead(TCHAR* szVal, bool bOverWrite)
2186 {
2187 	INT32 nRet;
2188 	TCHAR* szQuote = NULL;
2189 	TCHAR* szEnd = NULL;
2190 	UINT32 i = 0;
2191 
2192 	nRet = QuoteRead(&szQuote, &szEnd, szVal);
2193 	if (nRet) {
2194 		return 1;
2195 	}
2196 
2197 	i = MacroNameToNum(szQuote);
2198 	if (i != ~0U) {
2199 		i += nGameInpCount;
2200 		if (GameInp[i].Macro.nMode == 0 || bOverWrite) {
2201 			(GameInp + i)->Macro.nSysMacro = 15;
2202 		}
2203 	}
2204 
2205 	return 0;
2206 }
2207 
GameInpCustomRead(TCHAR * szVal,bool bOverWrite)2208 INT32 GameInpCustomRead(TCHAR* szVal, bool bOverWrite)
2209 {
2210 	return AddCustomMacro(szVal, bOverWrite);
2211 }
2212