1 /*
2   Hatari - dlgJoystick.c
3 
4   This file is distributed under the GNU General Public License, version 2
5   or at your option any later version. Read the file gpl.txt for details.
6 */
7 const char DlgJoystick_fileid[] = "Hatari dlgJoystick.c : " __DATE__ " " __TIME__;
8 
9 #include "main.h"
10 #include "configuration.h"
11 #include "dialog.h"
12 #include "sdlgui.h"
13 #include "joy.h"
14 
15 #define DLGJOY_STJOYNAME   3
16 #define DLGJOY_PREVSTJOY   4
17 #define DLGJOY_NEXTSTJOY   5
18 #define DLGJOY_DEFINEKEYS  7
19 #define DLGJOY_DISABLED    8
20 #define DLGJOY_USEKEYS     9
21 #define DLGJOY_USEREALJOY 10
22 #define DLGJOY_SDLJOYNAME 12
23 #define DLGJOY_PREVSDLJOY 13
24 #define DLGJOY_NEXTSDLJOY 14
25 #define DLGJOY_AUTOFIRE   15
26 #define DLGJOY_EXIT       16
27 
28 /* The joysticks dialog: */
29 
30 static char sSdlStickName[20];
31 
32 static SGOBJ joydlg[] =
33 {
34 	{ SGBOX, 0, 0, 0,0, 32,18, NULL },
35 	{ SGTEXT, 0, 0, 8,1, 15,1, "Joysticks setup" },
36 
37 	{ SGBOX, 0, 0, 4,3, 24,1, NULL },
38 	{ SGTEXT, 0, 0, 5,3, 22,1, NULL },
39 	{ SGBUTTON, 0, 0,  1,3, 3,1, "\x04", SG_SHORTCUT_LEFT },
40 	{ SGBUTTON, 0, 0, 28,3, 3,1, "\x03", SG_SHORTCUT_RIGHT },
41 
42 	{ SGBOX, 0, 0, 1,4, 30,11, NULL },
43 	{ SGBUTTON,   0, 0, 19,7, 11,1, "D_efine keys" },
44 
45 	{ SGRADIOBUT, 0, 0, 2,5, 10,1, "_disabled" },
46 	{ SGRADIOBUT, 0, 0, 2,7, 14,1, "use _keyboard" },
47 	{ SGRADIOBUT, 0, 0, 2,9, 20,1, "use real _joystick:" },
48 
49 	{ SGBOX, 0, 0, 5,11, 22,1, NULL },
50 	{ SGTEXT, 0, 0, 6,11, 20,1, sSdlStickName },
51 	{ SGBUTTON, 0, 0,  4,11, 1,1, "\x04", SG_SHORTCUT_UP },
52 	{ SGBUTTON, 0, 0, 27,11, 1,1, "\x03", SG_SHORTCUT_DOWN },
53 
54 	{ SGCHECKBOX, 0, 0, 2,13, 17,1, "Enable _autofire" },
55 
56 	{ SGBUTTON, SG_DEFAULT, 0, 6,16, 20,1, "Back to main menu" },
57 	{ -1, 0, 0, 0,0, 0,0, NULL }
58 };
59 
60 
61 /* The joystick keys setup dialog: */
62 
63 static char sKeyInstruction[24];
64 static char sKeyName[24];
65 
66 static SGOBJ joykeysdlg[] =
67 {
68 	{ SGBOX, 0, 0, 0,0, 28,5, NULL },
69 	{ SGTEXT, 0, 0, 2,1, 24,1, sKeyInstruction },
70 	{ SGTEXT, 0, 0, 2,3, 24,1, sKeyName },
71 	{ -1, 0, 0, 0,0, 0,0, NULL }
72 };
73 
74 
75 static char *sJoystickNames[JOYSTICK_COUNT] =
76 {
77 	"ST Joystick 0",
78 	"ST Joystick 1",
79 	"STE Joypad A",
80 	"STE Joypad B",
81 	"Parallel port stick 1",
82 	"Parallel port stick 2"
83 };
84 
85 
86 /*-----------------------------------------------------------------------*/
87 /**
88  * Show dialogs for defining joystick keys and wait for a key press.
89  */
DlgJoystick_DefineOneKey(char * pType,int * pKey)90 static void DlgJoystick_DefineOneKey(char *pType, int *pKey)
91 {
92 	SDL_Event sdlEvent;
93 
94 	if (bQuitProgram)
95 		return;
96 
97 	snprintf(sKeyInstruction, sizeof(sKeyInstruction), "Press key for '%s'...", pType);
98 	snprintf(sKeyName, sizeof(sKeyName), "(was: '%s')", SDL_GetKeyName(*pKey));
99 
100 	SDLGui_DrawDialog(joykeysdlg);
101 
102 	/* drain buffered key events */
103 	SDL_Delay(200);
104 	while (SDL_PollEvent(&sdlEvent))
105 	{
106 		if (sdlEvent.type == SDL_KEYUP || sdlEvent.type == SDL_KEYDOWN)
107 			break;
108 	}
109 
110 	/* get the real key */
111 	do
112 	{
113 		SDL_WaitEvent(&sdlEvent);
114 		if (sdlEvent.type == SDL_KEYDOWN)
115 		{
116 			*pKey = sdlEvent.key.keysym.sym;
117 			snprintf(sKeyName, sizeof(sKeyName), "(now: '%s')", SDL_GetKeyName(*pKey));
118 			SDLGui_DrawDialog(joykeysdlg);
119 		}
120 		else if (sdlEvent.type == SDL_QUIT)
121 		{
122 			bQuitProgram = true;
123 			return;
124 		}
125 	} while (sdlEvent.type != SDL_KEYUP);
126 }
127 
128 
129 /*-----------------------------------------------------------------------*/
130 /**
131  * Let the user define joystick keys.
132  */
DlgJoystick_DefineKeys(int nActJoy)133 static void DlgJoystick_DefineKeys(int nActJoy)
134 {
135 
136 	SDLGui_CenterDlg(joykeysdlg);
137 	DlgJoystick_DefineOneKey("up", &ConfigureParams.Joysticks.Joy[nActJoy].nKeyCodeUp);
138 	DlgJoystick_DefineOneKey("down", &ConfigureParams.Joysticks.Joy[nActJoy].nKeyCodeDown);
139 	DlgJoystick_DefineOneKey("left", &ConfigureParams.Joysticks.Joy[nActJoy].nKeyCodeLeft);
140 	DlgJoystick_DefineOneKey("right", &ConfigureParams.Joysticks.Joy[nActJoy].nKeyCodeRight);
141 	DlgJoystick_DefineOneKey("fire", &ConfigureParams.Joysticks.Joy[nActJoy].nKeyCodeFire);
142 }
143 
144 
145 /*-----------------------------------------------------------------------*/
146 /**
147  * Adapt dialog using the values from the configration structure.
148  */
DlgJoystick_ReadValuesFromConf(int nActJoy,int nMaxId)149 static void DlgJoystick_ReadValuesFromConf(int nActJoy, int nMaxId)
150 {
151 	int i;
152 
153 	/* Check if joystick ID is available */
154 	if (SDL_NumJoysticks() == 0)
155 	{
156 		strcpy(sSdlStickName, "0: (none available)");
157 	}
158 	else if (ConfigureParams.Joysticks.Joy[nActJoy].nJoyId <= nMaxId)
159 	{
160 		snprintf(sSdlStickName, 20, "%i: %s", ConfigureParams.Joysticks.Joy[nActJoy].nJoyId,
161 		         Joy_GetName(ConfigureParams.Joysticks.Joy[nActJoy].nJoyId));
162 	}
163 	else
164 	{
165 		snprintf(sSdlStickName, 20, "0: %s", Joy_GetName(0));
166 		/* Unavailable joystick ID -> disable it if necessary*/
167 		if (ConfigureParams.Joysticks.Joy[nActJoy].nJoystickMode == JOYSTICK_REALSTICK)
168 			ConfigureParams.Joysticks.Joy[nActJoy].nJoystickMode = JOYSTICK_DISABLED;
169 	}
170 
171 	for (i = DLGJOY_DISABLED; i <= DLGJOY_USEREALJOY; i++)
172 		joydlg[i].state &= ~SG_SELECTED;
173 	switch (ConfigureParams.Joysticks.Joy[nActJoy].nJoystickMode)
174 	{
175 	 case JOYSTICK_DISABLED:
176 		joydlg[DLGJOY_DISABLED].state |= SG_SELECTED;
177 		break;
178 	 case JOYSTICK_KEYBOARD:
179 		joydlg[DLGJOY_USEKEYS].state |= SG_SELECTED;
180 		break;
181 	 case JOYSTICK_REALSTICK:
182 		joydlg[DLGJOY_USEREALJOY].state |= SG_SELECTED;
183 		break;
184 	}
185 
186 	if (ConfigureParams.Joysticks.Joy[nActJoy].bEnableAutoFire)
187 		joydlg[DLGJOY_AUTOFIRE].state |= SG_SELECTED;
188 	else
189 		joydlg[DLGJOY_AUTOFIRE].state &= ~SG_SELECTED;
190 }
191 
192 
193 /*-----------------------------------------------------------------------*/
194 /**
195  * Read values from dialog and write them to the configuration structure.
196  */
DlgJoystick_WriteValuesToConf(int nActJoy)197 static void DlgJoystick_WriteValuesToConf(int nActJoy)
198 {
199 	if (joydlg[DLGJOY_DISABLED].state & SG_SELECTED)
200 		ConfigureParams.Joysticks.Joy[nActJoy].nJoystickMode = JOYSTICK_DISABLED;
201 	else if (joydlg[DLGJOY_USEKEYS].state & SG_SELECTED)
202 		ConfigureParams.Joysticks.Joy[nActJoy].nJoystickMode = JOYSTICK_KEYBOARD;
203 	else
204 		ConfigureParams.Joysticks.Joy[nActJoy].nJoystickMode = JOYSTICK_REALSTICK;
205 
206 	ConfigureParams.Joysticks.Joy[nActJoy].bEnableAutoFire = (joydlg[DLGJOY_AUTOFIRE].state & SG_SELECTED);
207 	ConfigureParams.Joysticks.Joy[nActJoy].nJoyId = joydlg[DLGJOY_SDLJOYNAME].txt[0] - '0';
208 }
209 
210 
211 /*-----------------------------------------------------------------------*/
212 /**
213  * Show and process the joystick dialog.
214  */
Dialog_JoyDlg(void)215 void Dialog_JoyDlg(void)
216 {
217 	int but;
218 	static int nActJoy = 1;
219 	int nMaxJoyId;
220 
221 	SDLGui_CenterDlg(joydlg);
222 
223 	joydlg[DLGJOY_STJOYNAME].txt = sJoystickNames[nActJoy];
224 
225 	nMaxJoyId = SDL_NumJoysticks() - 1;
226 	if (nMaxJoyId > 5)
227 		nMaxJoyId = 5;
228 
229 	/* Set up dialog from actual values: */
230 	DlgJoystick_ReadValuesFromConf(nActJoy, nMaxJoyId);
231 
232 	do
233 	{
234     	but = SDLGui_DoDialog(joydlg, NULL);
235 		switch (but)
236 		{
237 		 case DLGJOY_PREVSDLJOY:        // Select the previous SDL joystick
238 			if (ConfigureParams.Joysticks.Joy[nActJoy].nJoyId > 0)
239 			{
240 				ConfigureParams.Joysticks.Joy[nActJoy].nJoyId -= 1;
241 				snprintf(sSdlStickName, 20, "%i: %s", ConfigureParams.Joysticks.Joy[nActJoy].nJoyId,
242 				         Joy_GetName(ConfigureParams.Joysticks.Joy[nActJoy].nJoyId));
243 			}
244 			break;
245 		 case DLGJOY_NEXTSDLJOY:        // Select the next SDL joystick
246 			if (ConfigureParams.Joysticks.Joy[nActJoy].nJoyId < nMaxJoyId)
247 			{
248 				ConfigureParams.Joysticks.Joy[nActJoy].nJoyId += 1;
249 				snprintf(sSdlStickName, 20, "%i: %s", ConfigureParams.Joysticks.Joy[nActJoy].nJoyId,
250 				         Joy_GetName(ConfigureParams.Joysticks.Joy[nActJoy].nJoyId));
251 			}
252 			break;
253 		 case DLGJOY_DEFINEKEYS:        // Define new keys for keyboard emulation
254 			DlgJoystick_DefineKeys(nActJoy);
255 			break;
256 		 case DLGJOY_PREVSTJOY:         // Switch to the previous ST joystick setup tab
257 			if (nActJoy > 0)
258 			{
259 				DlgJoystick_WriteValuesToConf(nActJoy);
260 				nActJoy -= 1;
261 				DlgJoystick_ReadValuesFromConf(nActJoy, nMaxJoyId);
262 				joydlg[DLGJOY_STJOYNAME].txt = sJoystickNames[nActJoy];
263 			}
264 			break;
265 		 case DLGJOY_NEXTSTJOY:         // Switch to the next ST joystick setup tab
266 			if (nActJoy < 5)
267 			{
268 				DlgJoystick_WriteValuesToConf(nActJoy);
269 				nActJoy += 1;
270 				DlgJoystick_ReadValuesFromConf(nActJoy, nMaxJoyId);
271 				joydlg[DLGJOY_STJOYNAME].txt = sJoystickNames[nActJoy];
272 			}
273 			break;
274 		}
275 	}
276 	while (but != DLGJOY_EXIT && but != SDLGUI_QUIT
277 	       && but != SDLGUI_ERROR && !bQuitProgram);
278 
279 	DlgJoystick_WriteValuesToConf(nActJoy);
280 }
281