1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13 
14 
15 #pragma off (unreferenced)
16 static char rcsid[] = "$Id: joydefsw.c,v 1.1.1.1 2001/01/19 03:30:14 bradleyb Exp $";
17 #pragma on (unreferenced)
18 
19 #include "desw.h"
20 #include <mmsystem.h>
21 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <dos.h>
26 
27 #include "mono.h"
28 #include "key.h"
29 #include "joy.h"
30 #include "timer.h"
31 #include "error.h"
32 
33 #include "inferno.h"
34 #include "game.h"
35 #include "object.h"
36 #include "player.h"
37 
38 #include "controls.h"
39 #include "joydefs.h"
40 #include "victor.h"
41 #include "render.h"
42 #include "palette.h"
43 #include "newmenu.h"
44 #include "args.h"
45 #include "gamefont.h"
46 #include "text.h"
47 #include "kconfig.h"
48 #include "digi.h"
49 #include "playsave.h"
50 #include "screens.h"
51 #include "config.h"
52 
53 //	Extra control stuff
54 
55 // #include "cyberimp.h"
56 
57 
58 //##int joydefs_calibrate_flag = 0;
59 int joydefs_max_joysticks = 0;
60 int joydefs_num_joysticks = 0;
61 int Joystick_calibrating = 0;
62 
63 
64 extern int WriteConfigFile();
65 extern void kconfig_set_fcs_button(int btn, int button);
66 
67 
68 WinJoystickDesc WinJoyDesc;
69 
70 //	Windows 95:
71 //		Calibration and Menus because of automatic joystick detection
72 //		and 6 axis' (XYZ-RUV)
73 
74 extern ubyte default_kconfig_settings[][MAX_CONTROLS];
75 
76 
win95_autodetect_joystick()77 void win95_autodetect_joystick()
78 {
79 	JOYCAPS jc;
80 
81 //	Set default windows joystick settings.
82 //	AUTODETECT !!!
83 	joyGetDevCaps(JOYSTICKID1, &jc, sizeof(jc));
84 
85 //	Do buttons first
86 	default_kconfig_settings[CONTROL_WINJOYSTICK][1] = 0xff;
87 	default_kconfig_settings[CONTROL_WINJOYSTICK][4] = 0xff;
88 	default_kconfig_settings[CONTROL_WINJOYSTICK][26] = 0xff;
89 
90 	default_kconfig_settings[CONTROL_WINJOYSTICK][0] = 0x0;
91 	if (jc.wMaxButtons > 1)
92 		default_kconfig_settings[CONTROL_WINJOYSTICK][1] = 0x1;
93 	if (jc.wMaxButtons > 2)
94 		default_kconfig_settings[CONTROL_WINJOYSTICK][4] = 0x2;
95 	if (jc.wMaxButtons > 3)
96 		default_kconfig_settings[CONTROL_WINJOYSTICK][26] = 0x3;
97 
98 //	Do Hat!
99 	default_kconfig_settings[CONTROL_WINJOYSTICK][6] = 0xff;
100 	default_kconfig_settings[CONTROL_WINJOYSTICK][7] = 0xff;
101 	default_kconfig_settings[CONTROL_WINJOYSTICK][8] = 0xff;
102 	default_kconfig_settings[CONTROL_WINJOYSTICK][9] = 0xff;
103 
104 	if (jc.wCaps & JOYCAPS_HASPOV) {
105 		default_kconfig_settings[CONTROL_WINJOYSTICK][6] = 0x10;
106 		default_kconfig_settings[CONTROL_WINJOYSTICK][7] = 0x12;
107 		default_kconfig_settings[CONTROL_WINJOYSTICK][8] = 0x13;
108 		default_kconfig_settings[CONTROL_WINJOYSTICK][9] = 0x11;
109 	}
110 
111 //	Do Z-Axis (Throttle)
112 
113 //	Do rudder? (R-AXIS)
114 
115 }
116 
117 
win95_controls_init()118 int win95_controls_init()
119 {
120 	//int i = 0;
121 	int spjoy = 0;
122 
123 	if (FindArg("-SpecialDevice")) spjoy = 1;
124 
125 	joydefs_max_joysticks = joy_init(0,spjoy);
126 	if (!joy95_init_stick(1, spjoy)) return 0;
127 
128 //@@	for (i = 2; i <= joydefs_max_joysticks; i++)
129 //@@		if (!joy95_init_stick(i,0)) {
130 //@@			joydefs_max_joysticks = i-1;
131 //@@			break;
132 //@@		}
133 
134 	joy_handler_win(0,0,0,0);
135 	win95_autodetect_joystick();
136 
137 	return 1;
138 }
139 
140 
joy_delay()141 void joy_delay()
142 {
143 	stop_time();
144 	WinDelay(250);
145 	joy_flush();
146 	start_time();
147 }
148 
dump_axis_vals(int * t_vals)149 void dump_axis_vals(int *t_vals)
150 {
151 	mprintf_at((0, 2, 32, "X:%6d\n", t_vals[0]));
152 	mprintf_at((0, 3, 32, "Y:%6d\n", t_vals[1]));
153 	mprintf_at((0, 4, 32, "Z:%6d\n", t_vals[2]));
154 	mprintf_at((0, 5, 32, "R:%6d\n", t_vals[4]));
155 	mprintf_at((0, 6, 32, "U:%6d\n", t_vals[5]));
156 	mprintf_at((0, 7, 32, "V:%6d\n", t_vals[6]));
157 }
158 
159 
160 //	MAIN CALIBRATION ROUTINES
161 //	----------------------------------------------------------------------------
162 
joydefs_calibrate(void)163 void joydefs_calibrate(void)
164 {
165 	DWORD dwval;
166 	BOOL flag;
167 	STARTUPINFO si;
168 	PROCESS_INFORMATION pi;
169 	char name[80];
170 	char oldname[80];
171 	int j;
172 	int old_mode= -1;
173 
174 	Joystick_calibrating = 1;
175 
176 	if (GRMODEINFO(modex)) {
177 		old_mode = Screen_mode;
178 		set_screen_mode(SCREEN_MENU);
179 	}
180 	palette_save();
181 	apply_modified_palette();
182 	reset_palette_add();
183 
184 	gr_palette_load(gr_palette);
185 
186 //	Call calibration Applet
187 	joy95_get_name(JOYSTICKID1, oldname, 79);
188 
189 	logentry("Closing joystick for control panel init.\n");
190 	joy_close();							// Close down joystick polling
191 
192 	memset(&si, 0, sizeof(si));
193 	si.cb = sizeof(si);
194 	si.dwFlags = STARTF_USESHOWWINDOW;
195 	si.wShowWindow = SW_SHOW;
196 
197 	flag = CreateProcess(
198 			NULL,
199 			"rundll32.exe shell32.dll,Control_RunDLL joy.cpl",
200 			NULL, NULL,
201 			FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL,
202 			&si, &pi);
203 	if (!flag) {
204 		nm_messagebox( NULL, 1, TXT_OK, "UNABLE TO INITIATE\nJOYSTICK CONTROL PANEL");
205 	}
206 	else {
207 		dwval = WaitForInputIdle(pi.hProcess, INFINITE);
208 		mprintf((1, "JOY.CPL initiated?\n"));
209 		WinDelayIdle();							// Clear out messages.
210 
211 		while (WaitForSingleObject(pi.hProcess, 0) != WAIT_OBJECT_0)
212 		{
213 			if (multi_menu_poll()==-1)	{
214 				TerminateProcess(pi.hProcess,0);
215 				Sleep(100);
216 				CloseHandle(pi.hThread);
217 				CloseHandle(pi.hProcess);
218 				break;
219 			}
220 		}
221 
222 		mprintf((1, "JOY.CPL process finished?\n"));
223 		ShowWindow(_hAppWnd, SW_MAXIMIZE);
224 		WinDelayIdle();
225 		SetForegroundWindow(_hAppWnd);
226 		WinDelayIdle();
227 		_RedrawScreen = FALSE;
228 	}
229 
230 	if (win95_controls_init())					// Reinitializing joystick polling.
231 		logentry("Reinitialized joystick with new settings.\n");
232 	else
233 		logentry("Failed to reinitialize joystick.\n");
234 
235 //	Set kconfig settings to updated vals.
236 	joy95_get_name(JOYSTICKID1, name, 79);
237 
238 	if (Config_control_type == CONTROL_WINJOYSTICK) {
239 		if (strcmp(name, oldname)) {
240 			for (j=0; j<MAX_CONTROLS; j++ )
241 				kconfig_settings[CONTROL_WINJOYSTICK][j] = default_kconfig_settings[CONTROL_WINJOYSTICK][j];
242 			kc_set_controls();
243 		}
244 	}
245 
246 //@@	joydefs_calibrate2();
247 
248 	reset_cockpit();
249 
250 	palette_restore();
251 
252 	if (old_mode != -1)	{
253 		set_screen_mode(old_mode);
254 	}
255 
256 	Joystick_calibrating = 0;
257 }
258 
259 
260 //@@//	We should make our own windowed calibrator
261 //@@void joydefs_calibrate2()
262 //@@{
263 //@@	ubyte masks;
264 //@@	char calmsg[6][32];
265 //@@
266 //@@	int org_axis_min[7];
267 //@@	int org_axis_center[7];
268 //@@	int org_axis_max[7];
269 //@@
270 //@@	int axis_min[7] = { 0, 0, 0, 0, 0, 0, 0 };
271 //@@	int axis_cen[7] = { 0, 0, 0, 0, 0, 0, 0 };
272 //@@	int axis_max[7] = { 0, 0, 0, 0, 0, 0, 0 };
273 //@@
274 //@@	int t_vals[7];
275 //@@
276 //@@	char title[50];
277 //@@	char text[50];
278 //@@	int res;
279 //@@	int nsticks = 0;
280 //@@
281 //@@//	Get Current Calibration stuff
282 //@@	joydefs_calibrate_flag = 0;
283 //@@
284 //@@	joy_get_cal_vals(org_axis_min, org_axis_center, org_axis_max);
285 //@@
286 //@@	joy_set_cen();
287 //@@
288 //@@	masks = joystick_read_raw_axis( JOY_ALL_AXIS+JOY_EXT_AXIS, t_vals );
289 //@@
290 //@@	if (!joy_present)	{
291 //@@		nm_messagebox( NULL, 1, TXT_OK, TXT_NO_JOYSTICK );
292 //@@		return;
293 //@@	}
294 //@@
295 //@@	masks = joy_get_present_mask();
296 //@@
297 //@@	nsticks = 1;
298 //@@
299 //@@	res = joy_calibrate_xy(&axis_min[0], &axis_cen[0],	&axis_max[0],
300 //@@		  							&axis_min[1], &axis_cen[1], &axis_max[1]);
301 //@@
302 //@@	if (!res) {
303 //@@		joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max);
304 //@@		return;
305 //@@	}
306 //@@
307 //@@	strcpy(calmsg[0], "MOVE JOYSTICK UNTIL BAR REACHES");
308 //@@	strcpy(calmsg[1], "TOP AND PRESS BUTTON");
309 //@@	strcpy(calmsg[2], "MOVE JOYSTICK UNTIL BAR REACHES");
310 //@@	strcpy(calmsg[3], "BOTTOM AND PRESS BUTTON");
311 //@@	strcpy(calmsg[4], "RELEASE JOYSTICK");
312 //@@	strcpy(calmsg[5], "AND PRESS BUTTON");
313 //@@
314 //@@	mprintf((0, "Masks: %x\n", masks));
315 //@@
316 //@@	if (masks&JOY_1_Z_AXIS) {
317 //@@		res = joy_calibrate_bar(2, "CALIBRATE Z-AXIS", calmsg,
318 //@@							&axis_min[2], &axis_cen[2], &axis_max[2]);
319 //@@		if (!res) {
320 //@@			joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max);
321 //@@			return;
322 //@@		}
323 //@@  	}
324 //@@
325 //@@	if (masks&JOY_1_R_AXIS) {
326 //@@		res = joy_calibrate_bar(4, "CALIBRATE RUDDER", calmsg,
327 //@@							&axis_min[4], &axis_cen[4], &axis_max[4]);
328 //@@		if (!res) {
329 //@@			joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max);
330 //@@			return;
331 //@@		}
332 //@@  	}
333 //@@
334 //@@	if (masks&JOY_1_U_AXIS) {
335 //@@		res = joy_calibrate_bar(5, "CALIBRATE U-AXIS", calmsg,
336 //@@							&axis_min[5], &axis_cen[5], &axis_max[5]);
337 //@@		if (!res) {
338 //@@			joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max);
339 //@@			return;
340 //@@		}
341 //@@  	}
342 //@@
343 //@@	if (masks&JOY_1_V_AXIS) {
344 //@@		res = joy_calibrate_bar(6, "CALIBRATE V-AXIS", calmsg,
345 //@@							&axis_min[6], &axis_cen[6], &axis_max[6]);
346 //@@		if (!res) {
347 //@@			joy_set_cal_vals(org_axis_min, org_axis_center, org_axis_max);
348 //@@			return;
349 //@@		}
350 //@@  	}
351 //@@
352 //@@
353 //@@	joy_set_cal_vals(axis_min, axis_cen, axis_max);
354 //@@
355 //@@	WriteConfigFile();
356 //@@}
357 
358 
359 //	Joydefs button detection
360 //		This function will do Windows Joystick Button stuff
361 //		may emulate Thrustmaster FCS, Flightstick Pro, etc.
362 
joydefsw_do_button()363 int joydefsw_do_button()
364 {
365 	int axis[7];
366 	int code=255;
367 	int i;
368 
369 	joystick_read_raw_axis(JOY_ALL_AXIS, axis);
370 
371 	switch (Config_control_type)
372 	{
373 		case CONTROL_WINJOYSTICK:
374 			code = joydefsw_do_winjoybutton(axis);
375 			break;
376 	}
377 
378 //	Get standard buttons
379 	for (i=0; i<16; i++ )	{
380 		if ( joy_get_button_state(i) )
381 			code = i;
382 	}
383 
384 	return code;
385 }
386 
387 
joydefsw_do_winjoybutton(int * axis)388 int joydefsw_do_winjoybutton(int *axis)
389 {
390 //	Do POV detection first.  We should use the same
391 // procedure as the DOS version so that we can emulate the
392 // Thrustmaster selections (to keep Player files the same between
393 //	versions.  (19,15,11,7,0)
394 	int button;
395 
396 	if (axis[3] == JOY_POVBACKWARD)
397 		button = 17;
398 	else if (axis[3] == JOY_POVFORWARD)
399 		button = 19;
400 	else if (axis[3] == JOY_POVLEFT)
401 		button = 16;
402 	else if (axis[3] == JOY_POVRIGHT)
403 		button = 18;
404 	else if (axis[3] == JOY_POVCENTERED)
405 		button = 0;
406 
407 	kconfig_set_fcs_button(19,button);
408 	kconfig_set_fcs_button(18,button);
409 	kconfig_set_fcs_button(17,button);
410 	kconfig_set_fcs_button(16, button);
411 
412 	if (button == 0) button = 255;
413 
414 	return button;
415 }
416 
417 
418 
419 //	Joystick Menu
420 //		We want to keep the config files the same for the Windows/DOS
421 //		versions.  But we also autodetect joystick stuff.
422 //		Find some way to keep this easier than the DOS version without screwing
423 //		up configuration files.
424 
joydef_menuset_1(int nitems,newmenu_item * items,int * last_key,int citem)425 void joydef_menuset_1(int nitems, newmenu_item * items, int *last_key, int citem )
426 {
427 	//int i;
428 	int oc_type = Config_control_type;
429 
430 	nitems = nitems;
431 	last_key = last_key;
432 	citem = citem;
433 
434 	if (items[0].value) Config_control_type = CONTROL_NONE;
435 	else if (items[1].value) Config_control_type = CONTROL_MOUSE;
436 	else if (items[2].value) Config_control_type = CONTROL_WINJOYSTICK;
437 
438 //@@	if ( (oc_type != Config_control_type) && (Config_control_type == CONTROL_THRUSTMASTER_FCS ) )	{
439 //@@			nm_messagebox( TXT_IMPORTANT_NOTE, 1, TXT_OK, TXT_FCS );
440 //@@		}
441 
442 	if (oc_type != Config_control_type) {
443 		//##switch (Config_control_type) {
444 		//##	case 	CONTROL_WINJOYSTICK:
445 		//##		joydefs_calibrate_flag = 1;
446 		//##}
447 		kc_set_controls();
448 	}
449 
450 }
451 
452 extern ubyte kc_use_external_control;
453 extern ubyte kc_enable_external_control;
454 extern ubyte *kc_external_name;
455 
joydefs_config()456 void joydefs_config()
457 {
458 	int i, old_masks, masks,nitems;
459 	newmenu_item m[13];
460 	int i1=11;
461 	char xtext[92];
462 	char joytext[128];
463 	int no_joystick_option = 0;
464 
465 	//##joydefs_calibrate_flag = 0;
466 
467 	joy95_get_name(JOYSTICKID1, xtext, 127);
468 	if (!strcmpi(xtext, "NO JOYSTICK DETECTED") && (Config_control_type == CONTROL_WINJOYSTICK))	{
469 		Config_control_type = CONTROL_NONE;
470 		no_joystick_option = 1;
471 	}
472 	else no_joystick_option = 0;
473 	nm_wrap_text(joytext, xtext, 20);
474 
475 	do {
476 		nitems=10;
477 		m[0].type = NM_TYPE_RADIO; m[0].text = CONTROL_TEXT(0); m[0].value = 0; m[0].group = 0;
478 		m[1].type = NM_TYPE_RADIO; m[1].text = CONTROL_TEXT(5); m[1].value = 0; m[1].group = 0;
479 
480 		if (no_joystick_option) {
481 			m[2].type = NM_TYPE_TEXT; m[2].text = joytext; m[2].value = 0; m[2].group = 0;
482 		} else {
483 			m[2].type = NM_TYPE_RADIO; m[2].text = joytext; m[2].value = 0; m[2].group = 0;
484 		}
485 
486 		m[3].type = NM_TYPE_TEXT;  m[3].text="";
487 		m[4].type = NM_TYPE_MENU; m[4].text=TXT_CUST_ABOVE;
488 		m[5].type = NM_TYPE_TEXT;  m[5].text="";
489 		m[6].type = NM_TYPE_SLIDER; m[6].text=TXT_JOYS_SENSITIVITY; m[6].value=Config_joystick_sensitivity; m[6].min_value =0; m[6].max_value = 8;
490 		m[7].type = NM_TYPE_TEXT;   m[7].text="";
491 		m[8].type = NM_TYPE_TEXT;   m[8].text="";
492 		m[9].type = NM_TYPE_MENU; m[9].text=TXT_CUST_KEYBOARD;
493 
494 		if (Config_control_type == CONTROL_WINJOYSTICK) m[2].value = 1;
495 		else if (Config_control_type == CONTROL_MOUSE) m[1].value = 1;
496 		else if (Config_control_type == CONTROL_NONE) m[0].value = 1;
497 		else m[0].value = 1;
498 
499 		i1 = newmenu_do1( NULL, TXT_CONTROLS, nitems, m, joydef_menuset_1, i1 );
500 		Config_joystick_sensitivity = m[6].value;
501 
502 		switch(i1)	{
503 		case 4: {
504 				old_masks = 0;
505 				for (i=0; i<4; i++ )		{
506 					if (kconfig_is_axes_used(i))
507 						old_masks |= (1<<i);
508 				}
509 				if ( Config_control_type==0 )
510 					Config_control_type=0;
511 				else if ( Config_control_type < CONTROL_MOUSE )
512 					kconfig(1, CONTROL_TEXT(Config_control_type) );
513 				else if ( Config_control_type == CONTROL_WINJOYSTICK)
514 					kconfig(3, CONTROL_TEXT(Config_control_type) );
515 				else
516 					kconfig(2, CONTROL_TEXT(Config_control_type) );
517 
518 				masks = 0;
519 				for (i=0; i<4; i++ )		{
520 					if (kconfig_is_axes_used(i))
521 						masks |= (1<<i);
522 				}
523 
524 				//##switch (Config_control_type) {
525 				//##case 	CONTROL_WINJOYSTICK:
526 				//##	{
527 				//##		for (i=0; i<4; i++ )	{
528 				//##			if ( (masks&(1<<i)) && (!(old_masks&(1<<i))))
529 				//##				joydefs_calibrate_flag = 1;
530 				//##		}
531 				//##	}
532 				//##	break;
533 				//##}
534 			}
535 			break;
536 		case 9:
537 			kconfig(0, TXT_KEYBOARD);
538 			break;
539 		}
540 
541 	} while(i1 > -1);
542 
543 //	No calibration under new system where control panel does this.
544 //	switch (Config_control_type) {
545 //		case 	CONTROL_WINJOYSTICK:
546 //			if ( joydefs_calibrate_flag )
547 //				joydefs_calibrate();
548 //			break;
549 //	}
550 }
551 
552 
553 //	Extended joystick menu
554 //	----------------------------------------------------------------------------
joydefsw_win_joyselect(char * title)555 void joydefsw_win_joyselect(char *title)
556 {
557 	FILE *fp;
558 	char filename[64];
559 	char *token;
560 	ubyte axis;
561 
562 	if (newmenu_filelist("Windows 95 Controls", "*.joy", filename)) {
563 		fp = fopen(filename, "rb");
564 		if (!fp) {
565 			nm_messagebox(TXT_ERROR, 1, TXT_OK, "Unable to find control file");
566 			strcpy(title, "Windows 95 Custom");
567 			return;
568 		}
569 
570 	// Get Axis support.
571 		if (!fread(&axis, sizeof(ubyte), 1, fp)) {
572 			nm_messagebox(TXT_ERROR, 1, TXT_OK, "Illegal or corrupt control file");
573 			strcpy(title, "Windows 95 Custom");
574 			fclose(fp);
575 			return;
576 		}
577 
578 
579 		if (fread(kconfig_settings[CONTROL_WINJOYSTICK],
580 					sizeof(kconfig_settings[CONTROL_WINJOYSTICK]),
581 				1, fp) != 1) {
582 			nm_messagebox(TXT_ERROR, 1, TXT_OK, "Illegal or corrupt control file");
583 			strcpy(title, "Windows 95 Custom");
584 			fclose(fp);
585 			return;
586 		}
587 		fclose(fp);
588 
589 		token = strtok(filename, ".");
590 		strcpy(title, token);
591 	}
592 	else strcpy(title, "Windows 95 Custom");
593 }
594 
595