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 #ifdef HAVE_CONFIG_H
15 #include <conf.h>
16 #endif
17 
18 #ifndef MACINTOSH			// I'm going to totally seperate these routines -- yeeech!!!!
19 							// see end of file for macintosh equivs
20 
21 #ifdef WINDOWS
22 #define WIN32_LEAN_AND_MEAN
23 #include <windows.h>
24 #include "winapp.h"
25 #else
26 #endif
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 
33 #include "pstypes.h"
34 #include "game.h"
35 #include "menu.h"
36 #include "movie.h"
37 #include "digi.h"
38 #include "kconfig.h"
39 #include "palette.h"
40 #include "joy.h"
41 #include "songs.h"
42 #include "args.h"
43 #include "player.h"
44 #include "mission.h"
45 #include "mono.h"
46 #include "pa_enabl.h"
47 
48 
49 
50 #ifdef RCS
51 static char rcsid[] = "$Id: config.c,v 1.6 2003/03/22 04:04:47 btb Exp $";
52 #endif
53 
54 ubyte Config_digi_volume = 8;
55 ubyte Config_midi_volume = 8;
56 ubyte Config_redbook_volume = 8;
57 ubyte Config_control_type = 0;
58 ubyte Config_channels_reversed = 0;
59 ubyte Config_joystick_sensitivity = 8;
60 
61 #ifdef __MSDOS__
62 static char *digi_dev8_str = "DigiDeviceID8";
63 static char *digi_dev16_str = "DigiDeviceID16";
64 static char *digi_port_str = "DigiPort";
65 static char *digi_irq_str = "DigiIrq";
66 static char *digi_dma8_str = "DigiDma8";
67 static char *digi_dma16_str = "DigiDma16";
68 static char *midi_dev_str = "MidiDeviceID";
69 static char *midi_port_str = "MidiPort";
70 
71 #define _CRYSTAL_LAKE_8_ST		0xe201
72 #define _CRYSTAL_LAKE_16_ST	0xe202
73 #define _AWE32_8_ST				0xe208
74 #define _AWE32_16_ST				0xe209
75 #endif
76 static char *digi_volume_str = "DigiVolume";
77 static char *midi_volume_str = "MidiVolume";
78 static char *redbook_enabled_str = "RedbookEnabled";
79 static char *redbook_volume_str = "RedbookVolume";
80 static char *detail_level_str = "DetailLevel";
81 static char *gamma_level_str = "GammaLevel";
82 static char *stereo_rev_str = "StereoReverse";
83 static char *joystick_min_str = "JoystickMin";
84 static char *joystick_max_str = "JoystickMax";
85 static char *joystick_cen_str = "JoystickCen";
86 static char *last_player_str = "LastPlayer";
87 static char *last_mission_str = "LastMission";
88 static char *config_vr_type_str = "VR_type";
89 static char *config_vr_resolution_str = "VR_resolution";
90 static char *config_vr_tracking_str = "VR_tracking";
91 static char *movie_hires_str = "MovieHires";
92 
93 char config_last_player[CALLSIGN_LEN+1] = "";
94 char config_last_mission[MISSION_NAME_LEN+1] = "";
95 
96 int Config_digi_type = 0;
97 int Config_digi_dma = 0;
98 int Config_midi_type = 0;
99 
100 #ifdef WINDOWS
101 int	 DOSJoySaveMin[4];
102 int	 DOSJoySaveCen[4];
103 int	 DOSJoySaveMax[4];
104 
105 char win95_current_joyname[256];
106 #endif
107 
108 
109 
110 int Config_vr_type = 0;
111 int Config_vr_resolution = 0;
112 int Config_vr_tracking = 0;
113 
114 int digi_driver_board_16;
115 int digi_driver_dma_16;
116 
117 extern byte	Object_complexity, Object_detail, Wall_detail, Wall_render_depth, Debris_amount, SoundChannels;
118 
119 void set_custom_detail_vars(void);
120 
121 
122 #define CL_MC0 0xF8F
123 #define CL_MC1 0xF8D
124 /*
125 void CrystalLakeWriteMCP( ushort mc_addr, ubyte mc_data )
126 {
127 	_disable();
128 	outp( CL_MC0, 0xE2 );				// Write password
129 	outp( mc_addr, mc_data );		// Write data
130 	_enable();
131 }
132 
133 ubyte CrystalLakeReadMCP( ushort mc_addr )
134 {
135 	ubyte value;
136 	_disable();
137 	outp( CL_MC0, 0xE2 );		// Write password
138 	value = inp( mc_addr );		// Read data
139 	_enable();
140 	return value;
141 }
142 
143 void CrystalLakeSetSB()
144 {
145 	ubyte tmp;
146 	tmp = CrystalLakeReadMCP( CL_MC1 );
147 	tmp &= 0x7F;
148 	CrystalLakeWriteMCP( CL_MC1, tmp );
149 }
150 
151 void CrystalLakeSetWSS()
152 {
153 	ubyte tmp;
154 	tmp = CrystalLakeReadMCP( CL_MC1 );
155 	tmp |= 0x80;
156 	CrystalLakeWriteMCP( CL_MC1, tmp );
157 }
158 */
159 //MovieHires might be changed by -nohighres, so save a "real" copy of it
160 int SaveMovieHires;
161 int save_redbook_enabled;
162 
163 #ifdef WINDOWS
CheckMovieAttributes()164 void CheckMovieAttributes()
165 {
166 		HKEY hKey;
167 		DWORD len, type, val;
168 		long lres;
169 
170 		lres = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Parallax\\Descent II\\1.1\\INSTALL",
171 							0, KEY_READ, &hKey);
172 		if (lres == ERROR_SUCCESS) {
173 			len = sizeof(val);
174 			lres = RegQueryValueEx(hKey, "HIRES", NULL, &type, &val, &len);
175 			if (lres == ERROR_SUCCESS) {
176 				MovieHires = val;
177 				logentry("HIRES=%d\n", val);
178 			}
179 			RegCloseKey(hKey);
180 		}
181 }
182 #endif
183 
184 
185 
ReadConfigFile()186 int ReadConfigFile()
187 {
188 	FILE *infile;
189 	char line[80], *token, *value, *ptr;
190 	ubyte gamma;
191 	int joy_axis_min[7];
192 	int joy_axis_center[7];
193 	int joy_axis_max[7];
194 	int i;
195 
196 	strcpy( config_last_player, "" );
197 
198 	joy_axis_min[0] = joy_axis_min[1] = joy_axis_min[2] = joy_axis_min[3] = 0;
199 	joy_axis_max[0] = joy_axis_max[1] = joy_axis_max[2] = joy_axis_max[3] = 0;
200 	joy_axis_center[0] = joy_axis_center[1] = joy_axis_center[2] = joy_axis_center[3] = 0;
201 
202 #ifdef WINDOWS
203 	memset(&joy_axis_min[0], 0, sizeof(int)*7);
204 	memset(&joy_axis_max[0], 0, sizeof(int)*7);
205 	memset(&joy_axis_center[0], 0, sizeof(int)*7);
206 //@@	joy_set_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max);
207 #else
208 	joy_set_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max);
209 #endif
210 
211 	/*digi_driver_board = 0;
212 	digi_driver_port = 0;
213 	digi_driver_irq = 0;
214 	digi_driver_dma = 0;
215 
216 	digi_midi_type = 0;
217 	digi_midi_port = 0;*/
218 
219 	Config_digi_volume = 8;
220 	Config_midi_volume = 8;
221 	Config_redbook_volume = 8;
222 	Config_control_type = 0;
223 	Config_channels_reversed = 0;
224 
225 	//set these here in case no cfg file
226 	SaveMovieHires = MovieHires;
227 	save_redbook_enabled = Redbook_enabled;
228 
229 	infile = fopen("descent.cfg", "rt");
230 	if (infile == NULL) {
231 		WIN(CheckMovieAttributes());
232 		return 1;
233 	}
234 	while (!feof(infile)) {
235 		memset(line, 0, 80);
236 		fgets(line, 80, infile);
237 		ptr = &(line[0]);
238 		while (isspace(*ptr))
239 			ptr++;
240 		if (*ptr != '\0') {
241 			token = strtok(ptr, "=");
242 			value = strtok(NULL, "=");
243 			if (value[strlen(value)-1] == '\n')
244 				value[strlen(value)-1] = 0;
245 /*			if (!strcmp(token, digi_dev8_str))
246 				digi_driver_board = strtol(value, NULL, 16);
247 			else if (!strcmp(token, digi_dev16_str))
248 				digi_driver_board_16 = strtol(value, NULL, 16);
249 			else if (!strcmp(token, digi_port_str))
250 				digi_driver_port = strtol(value, NULL, 16);
251 			else if (!strcmp(token, digi_irq_str))
252 				digi_driver_irq = strtol(value, NULL, 10);
253 			else if (!strcmp(token, digi_dma8_str))
254 				digi_driver_dma = strtol(value, NULL, 10);
255 			else if (!strcmp(token, digi_dma16_str))
256 				digi_driver_dma_16 = strtol(value, NULL, 10);
257 			else*/ if (!strcmp(token, digi_volume_str))
258 				Config_digi_volume = strtol(value, NULL, 10);
259 			else/* if (!strcmp(token, midi_dev_str))
260 				digi_midi_type = strtol(value, NULL, 16);
261 			else if (!strcmp(token, midi_port_str))
262 				digi_midi_port = strtol(value, NULL, 16);
263 			else*/ if (!strcmp(token, midi_volume_str))
264 				Config_midi_volume = strtol(value, NULL, 10);
265 			else if (!strcmp(token, redbook_enabled_str))
266 				Redbook_enabled = save_redbook_enabled = strtol(value, NULL, 10);
267 			else if (!strcmp(token, redbook_volume_str))
268 				Config_redbook_volume = strtol(value, NULL, 10);
269 			else if (!strcmp(token, stereo_rev_str))
270 				Config_channels_reversed = strtol(value, NULL, 10);
271 			else if (!strcmp(token, gamma_level_str)) {
272 				gamma = strtol(value, NULL, 10);
273 				gr_palette_set_gamma( gamma );
274 			}
275 			else if (!strcmp(token, detail_level_str)) {
276 				Detail_level = strtol(value, NULL, 10);
277 				if (Detail_level == NUM_DETAIL_LEVELS-1) {
278 					int count,dummy,oc,od,wd,wrd,da,sc;
279 
280 					count = sscanf (value, "%d,%d,%d,%d,%d,%d,%d\n",&dummy,&oc,&od,&wd,&wrd,&da,&sc);
281 
282 					if (count == 7) {
283 						Object_complexity = oc;
284 						Object_detail = od;
285 						Wall_detail = wd;
286 						Wall_render_depth = wrd;
287 						Debris_amount = da;
288 						SoundChannels = sc;
289 						set_custom_detail_vars();
290 					}
291 				  #ifdef PA_3DFX_VOODOO   // Set to highest detail because you can't change em
292 					   Object_complexity=Object_detail=Wall_detail=
293 						Wall_render_depth=Debris_amount=SoundChannels = NUM_DETAIL_LEVELS-1;
294 						Detail_level=NUM_DETAIL_LEVELS-1;
295 						set_custom_detail_vars();
296 					#endif
297 				}
298 			}
299 			else if (!strcmp(token, joystick_min_str))	{
300 				sscanf( value, "%d,%d,%d,%d", &joy_axis_min[0], &joy_axis_min[1], &joy_axis_min[2], &joy_axis_min[3] );
301 			}
302 			else if (!strcmp(token, joystick_max_str))	{
303 				sscanf( value, "%d,%d,%d,%d", &joy_axis_max[0], &joy_axis_max[1], &joy_axis_max[2], &joy_axis_max[3] );
304 			}
305 			else if (!strcmp(token, joystick_cen_str))	{
306 				sscanf( value, "%d,%d,%d,%d", &joy_axis_center[0], &joy_axis_center[1], &joy_axis_center[2], &joy_axis_center[3] );
307 			}
308 			else if (!strcmp(token, last_player_str))	{
309 				char * p;
310 				strncpy( config_last_player, value, CALLSIGN_LEN );
311 				p = strchr( config_last_player, '\n');
312 				if ( p ) *p = 0;
313 			}
314 			else if (!strcmp(token, last_mission_str))	{
315 				char * p;
316 				strncpy( config_last_mission, value, MISSION_NAME_LEN );
317 				p = strchr( config_last_mission, '\n');
318 				if ( p ) *p = 0;
319 			} else if (!strcmp(token, config_vr_type_str)) {
320 				Config_vr_type = strtol(value, NULL, 10);
321 			} else if (!strcmp(token, config_vr_resolution_str)) {
322 				Config_vr_resolution = strtol(value, NULL, 10);
323 			} else if (!strcmp(token, config_vr_tracking_str)) {
324 				Config_vr_tracking = strtol(value, NULL, 10);
325 			} else if (!strcmp(token, movie_hires_str)) {
326 				SaveMovieHires = MovieHires = strtol(value, NULL, 10);
327 			}
328 		}
329 	}
330 
331 	fclose(infile);
332 
333 #ifdef WINDOWS
334 	for (i=0;i<4;i++)
335 	{
336 	 DOSJoySaveMin[i]=joy_axis_min[i];
337 	 DOSJoySaveCen[i]=joy_axis_center[i];
338 	 DOSJoySaveMax[i]=joy_axis_max[i];
339    	}
340 #else
341 	joy_set_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max);
342 #endif
343 
344 	i = FindArg( "-volume" );
345 
346 	if ( i > 0 )	{
347 		i = atoi( Args[i+1] );
348 		if ( i < 0 ) i = 0;
349 		if ( i > 100 ) i = 100;
350 		Config_digi_volume = (i*8)/100;
351 		Config_midi_volume = (i*8)/100;
352 		Config_redbook_volume = (i*8)/100;
353 	}
354 
355 	if ( Config_digi_volume > 8 ) Config_digi_volume = 8;
356 	if ( Config_midi_volume > 8 ) Config_midi_volume = 8;
357 	if ( Config_redbook_volume > 8 ) Config_redbook_volume = 8;
358 
359 	digi_set_volume( (Config_digi_volume*32768)/8, (Config_midi_volume*128)/8 );
360 /*
361 	printf( "DigiDeviceID: 0x%x\n", digi_driver_board );
362 	printf( "DigiPort: 0x%x\n", digi_driver_port		);
363 	printf( "DigiIrq: 0x%x\n",  digi_driver_irq		);
364 	printf( "DigiDma: 0x%x\n",	digi_driver_dma	);
365 	printf( "MidiDeviceID: 0x%x\n", digi_midi_type	);
366 	printf( "MidiPort: 0x%x\n", digi_midi_port		);
367   	key_getch();
368 */
369 
370 	/*Config_midi_type = digi_midi_type;
371 	Config_digi_type = digi_driver_board;
372 	Config_digi_dma = digi_driver_dma;*/
373 
374 #if 0
375 	if (digi_driver_board_16 > 0 && !FindArg("-no16bit") && digi_driver_board_16 != _GUS_16_ST) {
376 		digi_driver_board = digi_driver_board_16;
377 		digi_driver_dma = digi_driver_dma_16;
378 	}
379 
380 	// HACK!!!
381 	//Hack to make some cards look like others, such as
382 	//the Crytal Lake look like Microsoft Sound System
383 	if ( digi_driver_board == _CRYSTAL_LAKE_8_ST )	{
384 		ubyte tmp;
385 		tmp = CrystalLakeReadMCP( CL_MC1 );
386 		if ( !(tmp & 0x80) )
387 			atexit( CrystalLakeSetSB );		// Restore to SB when done.
388 	 	CrystalLakeSetWSS();
389 		digi_driver_board = _MICROSOFT_8_ST;
390 	} else if ( digi_driver_board == _CRYSTAL_LAKE_16_ST )	{
391 		ubyte tmp;
392 		tmp = CrystalLakeReadMCP( CL_MC1 );
393 		if ( !(tmp & 0x80) )
394 			atexit( CrystalLakeSetSB );		// Restore to SB when done.
395 	 	CrystalLakeSetWSS();
396 		digi_driver_board = _MICROSOFT_16_ST;
397 	} else if ( digi_driver_board == _AWE32_8_ST )	{
398 		digi_driver_board = _SB16_8_ST;
399 	} else if ( digi_driver_board == _AWE32_16_ST )	{
400 		digi_driver_board = _SB16_16_ST;
401 	} else
402 		digi_driver_board		= digi_driver_board;
403 #else
404 	infile = fopen("descentw.cfg", "rt");
405 	if (infile) {
406 		while (!feof(infile)) {
407 			memset(line, 0, 80);
408 			fgets(line, 80, infile);
409 			ptr = &(line[0]);
410 			while (isspace(*ptr))
411 				ptr++;
412 			if (*ptr != '\0') {
413 				token = strtok(ptr, "=");
414 				value = strtok(NULL, "=");
415 				if (value[strlen(value)-1] == '\n')
416 					value[strlen(value)-1] = 0;
417 				if (!strcmp(token, joystick_min_str))	{
418 					sscanf( value, "%d,%d,%d,%d,%d,%d,%d", &joy_axis_min[0], &joy_axis_min[1], &joy_axis_min[2], &joy_axis_min[3], &joy_axis_min[4], &joy_axis_min[5], &joy_axis_min[6] );
419 				}
420 				else if (!strcmp(token, joystick_max_str))	{
421 					sscanf( value, "%d,%d,%d,%d,%d,%d,%d", &joy_axis_max[0], &joy_axis_max[1], &joy_axis_max[2], &joy_axis_max[3], &joy_axis_max[4], &joy_axis_max[5], &joy_axis_max[6] );
422 				}
423 				else if (!strcmp(token, joystick_cen_str))	{
424 					sscanf( value, "%d,%d,%d,%d,%d,%d,%d", &joy_axis_center[0], &joy_axis_center[1], &joy_axis_center[2], &joy_axis_center[3], &joy_axis_center[4], &joy_axis_center[5], &joy_axis_center[6] );
425 				}
426 			}
427 		}
428 		fclose(infile);
429 	}
430 #endif
431 
432 	return 0;
433 }
434 
WriteConfigFile()435 int WriteConfigFile()
436 {
437 	FILE *infile;
438 	char str[256];
439 	int joy_axis_min[7];
440 	int joy_axis_center[7];
441 	int joy_axis_max[7];
442 	ubyte gamma = gr_palette_get_gamma();
443 
444 	joy_get_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max);
445 
446 #ifdef WINDOWS
447 	for (i=0;i<4;i++)
448    {
449 	 joy_axis_min[i]=DOSJoySaveMin[i];
450 	 joy_axis_center[i]=DOSJoySaveCen[i];
451 	 joy_axis_max[i]=DOSJoySaveMax[i];
452    }
453 #endif
454 
455 	infile = fopen("descent.cfg", "wt");
456 	if (infile == NULL) {
457 		return 1;
458 	}
459 	/*sprintf (str, "%s=0x%x\n", digi_dev8_str, Config_digi_type);
460 	fputs(str, infile);
461 	sprintf (str, "%s=0x%x\n", digi_dev16_str, digi_driver_board_16);
462 	fputs(str, infile);
463 	sprintf (str, "%s=0x%x\n", digi_port_str, digi_driver_port);
464 	fputs(str, infile);
465 	sprintf (str, "%s=%d\n", digi_irq_str, digi_driver_irq);
466 	fputs(str, infile);
467 	sprintf (str, "%s=%d\n", digi_dma8_str, Config_digi_dma);
468 	fputs(str, infile);
469 	sprintf (str, "%s=%d\n", digi_dma16_str, digi_driver_dma_16);
470 	fputs(str, infile);*/
471 	sprintf (str, "%s=%d\n", digi_volume_str, Config_digi_volume);
472 	fputs(str, infile);
473 	/*sprintf (str, "%s=0x%x\n", midi_dev_str, Config_midi_type);
474 	fputs(str, infile);
475 	sprintf (str, "%s=0x%x\n", midi_port_str, digi_midi_port);
476 	fputs(str, infile);*/
477 	sprintf (str, "%s=%d\n", midi_volume_str, Config_midi_volume);
478 	fputs(str, infile);
479 	sprintf (str, "%s=%d\n", redbook_enabled_str, FindArg("-noredbook")?save_redbook_enabled:Redbook_enabled);
480 	fputs(str, infile);
481 	sprintf (str, "%s=%d\n", redbook_volume_str, Config_redbook_volume);
482 	fputs(str, infile);
483 	sprintf (str, "%s=%d\n", stereo_rev_str, Config_channels_reversed);
484 	fputs(str, infile);
485 	sprintf (str, "%s=%d\n", gamma_level_str, gamma);
486 	fputs(str, infile);
487 	if (Detail_level == NUM_DETAIL_LEVELS-1)
488 		sprintf (str, "%s=%d,%d,%d,%d,%d,%d,%d\n", detail_level_str, Detail_level,
489 				Object_complexity,Object_detail,Wall_detail,Wall_render_depth,Debris_amount,SoundChannels);
490 	else
491 		sprintf (str, "%s=%d\n", detail_level_str, Detail_level);
492 	fputs(str, infile);
493 
494 	sprintf (str, "%s=%d,%d,%d,%d\n", joystick_min_str, joy_axis_min[0], joy_axis_min[1], joy_axis_min[2], joy_axis_min[3] );
495 	fputs(str, infile);
496 	sprintf (str, "%s=%d,%d,%d,%d\n", joystick_cen_str, joy_axis_center[0], joy_axis_center[1], joy_axis_center[2], joy_axis_center[3] );
497 	fputs(str, infile);
498 	sprintf (str, "%s=%d,%d,%d,%d\n", joystick_max_str, joy_axis_max[0], joy_axis_max[1], joy_axis_max[2], joy_axis_max[3] );
499 	fputs(str, infile);
500 
501 	sprintf (str, "%s=%s\n", last_player_str, Players[Player_num].callsign );
502 	fputs(str, infile);
503 	sprintf (str, "%s=%s\n", last_mission_str, config_last_mission );
504 	fputs(str, infile);
505 	sprintf (str, "%s=%d\n", config_vr_type_str, Config_vr_type );
506 	fputs(str, infile);
507 	sprintf (str, "%s=%d\n", config_vr_resolution_str, Config_vr_resolution );
508 	fputs(str, infile);
509 	sprintf (str, "%s=%d\n", config_vr_tracking_str, Config_vr_tracking );
510 	fputs(str, infile);
511 	sprintf (str, "%s=%d\n", movie_hires_str, (FindArg("-nohires") || FindArg("-nohighres") || FindArg("-lowresmovies"))?SaveMovieHires:MovieHires);
512 	fputs(str, infile);
513 
514 	fclose(infile);
515 
516 #ifdef WINDOWS
517 {
518 //	Save Windows Config File
519 	char joyname[256];
520 
521 
522 	joy_get_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max);
523 
524 	infile = fopen("descentw.cfg", "wt");
525 	if (infile == NULL) return 1;
526 
527 	sprintf(str, "%s=%d,%d,%d,%d,%d,%d,%d\n", joystick_min_str,
528 			joy_axis_min[0], joy_axis_min[1], joy_axis_min[2], joy_axis_min[3],
529 			joy_axis_min[4], joy_axis_min[5], joy_axis_min[6]);
530 	fputs(str, infile);
531 	sprintf(str, "%s=%d,%d,%d,%d,%d,%d,%d\n", joystick_cen_str,
532 			joy_axis_center[0], joy_axis_center[1], joy_axis_center[2], joy_axis_center[3],
533 			joy_axis_center[4], joy_axis_center[5], joy_axis_center[6]);
534 	fputs(str, infile);
535 	sprintf(str, "%s=%d,%d,%d,%d,%d,%d,%d\n", joystick_max_str,
536 			joy_axis_max[0], joy_axis_max[1], joy_axis_max[2], joy_axis_max[3],
537 			joy_axis_max[4], joy_axis_max[5], joy_axis_max[6]);
538 	fputs(str, infile);
539 
540 	fclose(infile);
541 }
542 	CheckMovieAttributes();
543 #endif
544 
545 	return 0;
546 }
547 
548 #else		// !defined(MACINTOSH)
549 
550 #include <stdio.h>
551 #include <stdlib.h>
552 #include <string.h>
553 #include <ctype.h>
554 
555 #include <Memory.h>
556 #include <Folders.h>
557 #include <GestaltEqu.h>
558 #include <Errors.h>
559 #include <Processes.h>
560 #include <Resources.h>
561 #include <LowMem.h>
562 
563 #include "pa_enabl.h"		// because some prefs rely on this fact
564 #include "error.h"
565 #include "pstypes.h"
566 #include "game.h"
567 #include "digi.h"
568 #include "kconfig.h"
569 #include "palette.h"
570 #include "joy.h"
571 #include "args.h"
572 #include "player.h"
573 #include "mission.h"
574 #include "prefs.h"			// prefs file for configuration stuff -- from DeSalvo
575 
576 #if defined(POLY_ACC)
577 #include "poly_acc.h"
578 #endif
579 
580 #ifdef RCS
581 static char rcsid[] = "$Id: config.c,v 1.6 2003/03/22 04:04:47 btb Exp $";
582 #endif
583 
584 #define MAX_CTB_LEN	512
585 
586 typedef struct preferences {
587 	ubyte	digi_volume;
588 	ubyte	midi_volume;
589 	ubyte	stereo_reverse;
590 	ubyte	detail_level;
591 	ubyte	oc;					// object complexity
592 	ubyte	od;					// object detail
593 	ubyte	wd;					// wall detail
594 	ubyte	wrd;				// wall render depth
595 	ubyte	da;					// debris amount
596 	ubyte	sc;					// sound channels
597 	ubyte	gamma_level;
598 	ubyte	pixel_double;
599 	int		joy_axis_min[4];
600 	int		joy_axis_max[4];
601 	int		joy_axis_center[4];
602 	char	lastplayer[CALLSIGN_LEN+1];
603 	char	lastmission[MISSION_NAME_LEN+1];
604 	char	ctb_config[MAX_CTB_LEN];
605 	int		ctb_tool;
606 	ubyte	master_volume;
607 	ubyte	display_dialog;
608 	ubyte	change_resolution;
609 	ubyte	nosound;
610 	ubyte	nomidi;
611 	ubyte	sound_11k;
612 	ubyte	no_movies;
613 	ubyte	game_monitor;
614 	ubyte	redbook_volume;
615 	ubyte	enable_rave;
616 	ubyte	enable_input_sprockets;
617 } Preferences;
618 
619 char config_last_player[CALLSIGN_LEN+1] = "";
620 char config_last_mission[MISSION_NAME_LEN+1] = "";
621 char config_last_ctb_cfg[MAX_CTB_LEN] = "";
622 int config_last_ctb_tool;
623 ubyte Config_master_volume = 4;
624 ubyte Config_digi_volume = 8;
625 ubyte Config_midi_volume = 8;
626 ubyte Config_redbook_volume = 8;
627 ubyte Config_control_type = 0;
628 ubyte Config_channels_reversed = 0;
629 ubyte Config_joystick_sensitivity = 8;
630 
631 int Config_vr_type = 0;
632 int Config_vr_resolution = 0;
633 int Config_vr_tracking = 0;
634 
635 extern byte	Object_complexity, Object_detail, Wall_detail, Wall_render_depth, Debris_amount, SoundChannels;
636 extern void digi_set_master_volume( int volume );
637 
638 void set_custom_detail_vars(void);
639 
640 static ubyte have_prefs = 0;
641 
642 //�	------------------------------	Private Definitions
643 //�	------------------------------	Private Types
644 
645 typedef struct
646 {
647 	Str31	fileName;
648 	OSType	creator;
649 	OSType	fileType;
650 	OSType	resType;
651 	short	resID;
652 } PrefsInfo, *PrefsInfoPtr, **PrefsInfoHandle;
653 
654 //�	------------------------------	Private Variables
655 
656 static PrefsInfo		prefsInfo;
657 static Boolean		prefsInited = 0;
658 
659 //�	------------------------------	Private Functions
660 
661 static void Pstrcpy(StringPtr dst, StringPtr src);
662 static void Pstrcat(StringPtr dst, StringPtr src);
663 static Boolean FindPrefsFile(short *prefVRefNum, long *prefDirID);
664 
665 //�	--------------------	Pstrcpy
666 
667 static void
Pstrcpy(StringPtr dst,StringPtr src)668 Pstrcpy(StringPtr dst, StringPtr src)
669 {
670 	BlockMove(src, dst, (*src) + 1);
671 }
672 
673 //�	--------------------	Pstrcat
674 
675 static void
Pstrcat(StringPtr dst,StringPtr src)676 Pstrcat(StringPtr dst, StringPtr src)
677 {
678 	BlockMove(src + 1, dst + (*dst) + 1, *src);
679 	*dst += *src;
680 }
681 
682 //�	--------------------	FindPrefsFile
683 
684 static Boolean
FindPrefsFile(short * prefVRefNum,long * prefDirID)685 FindPrefsFile(short *prefVRefNum, long *prefDirID)
686 {
687 OSErr		theErr;
688 long			response;
689 CInfoPBRec	infoPB;
690 
691 	if (! prefsInited)
692 		return (0);
693 
694 	theErr = Gestalt(gestaltFindFolderAttr, &response);
695 	if (theErr == noErr && ((response >> gestaltFindFolderPresent) & 1))
696 	{
697 		//�	Find (or make) it the easy way...
698 		theErr = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, prefVRefNum, prefDirID);
699 	}
700 	else
701 	{
702 	SysEnvRec	theSysEnv;
703 	StringPtr		prefFolderName = "\pPreferences";
704 
705 		//�	yeachh -- we have to do it all by hand!
706 		theErr = SysEnvirons(1, &theSysEnv);
707 		if (theErr != noErr)
708 			return (0);
709 
710 		*prefVRefNum = theSysEnv.sysVRefNum;
711 
712 		//�	Check whether Preferences folder already exists
713 		infoPB.hFileInfo.ioCompletion	= 0;
714 		infoPB.hFileInfo.ioNamePtr	= prefFolderName;
715 		infoPB.hFileInfo.ioVRefNum	= *prefVRefNum;
716 		infoPB.hFileInfo.ioFDirIndex	= 0;
717 		infoPB.hFileInfo.ioDirID		= 0;
718 
719 		theErr = PBGetCatInfo(&infoPB, 0);
720 		if (theErr == noErr)
721 		{
722 			*prefDirID = infoPB.hFileInfo.ioDirID;
723 		}
724 		else if (theErr == fnfErr)		//�	Preferences doesn't already exist
725 		{
726 		HParamBlockRec	dirPB;
727 
728 			//�	Create "Preferences" folder
729 			dirPB.fileParam.ioCompletion	= 0;
730 			dirPB.fileParam.ioVRefNum	= *prefVRefNum;
731 			dirPB.fileParam.ioNamePtr	= prefFolderName;
732 			dirPB.fileParam.ioDirID		= 0;
733 
734 			theErr = PBDirCreate(&dirPB, 0);
735 			if (theErr == noErr)
736 				*prefDirID = dirPB.fileParam.ioDirID;
737 		}
738 	}
739 
740 	//�	If we make it here OK, create Preferences file if necessary
741 	if (theErr == noErr)
742 	{
743 		infoPB.hFileInfo.ioCompletion	= 0;
744 		infoPB.hFileInfo.ioNamePtr	= prefsInfo.fileName;
745 		infoPB.hFileInfo.ioVRefNum	= *prefVRefNum;
746 		infoPB.hFileInfo.ioFDirIndex	= 0;
747 		infoPB.hFileInfo.ioDirID		= *prefDirID;
748 
749 		theErr = PBGetCatInfo(&infoPB, 0);
750 		if (theErr == fnfErr)
751 		{
752 			theErr = HCreate(*prefVRefNum, *prefDirID, prefsInfo.fileName, prefsInfo.creator, prefsInfo.fileType);
753 			if (theErr == noErr)
754 			{
755 				HCreateResFile(*prefVRefNum, *prefDirID, prefsInfo.fileName);
756 				theErr = ResError();
757 			}
758 		}
759 	}
760 
761 	return (theErr == noErr);
762 }
763 
764 //�	--------------------	InitPrefsFile
765 
766 #define UNKNOWN_TYPE 0x3f3f3f3f
767 
768 void
InitPrefsFile(OSType creator)769 InitPrefsFile(OSType creator)
770 {
771 	OSErr err;
772 PrefsInfoHandle		piHdl;
773 
774 	if ((piHdl = (PrefsInfoHandle) GetResource('PRFI', 0)) == nil)
775 	{
776 	ProcessSerialNumber	thePSN;
777 	ProcessInfoRec			thePIR;
778 	FSSpec				appSpec;
779 	StringPtr			app_string;
780 
781 #if 0
782 		GetCurrentProcess(&thePSN);
783 		thePIR.processName = nil;
784 		thePIR.processAppSpec = &appSpec;
785 
786 		//�	Set default to '�Application� Prefs', PREF 0
787 		err = GetProcessInformation(&thePSN, &thePIR);
788 		if (err)
789 			Int3();
790 #endif
791 		app_string = LMGetCurApName();
792 //		Pstrcpy(prefsInfo.fileName, appSpec.name);
793 		Pstrcpy(prefsInfo.fileName, app_string);
794 		Pstrcat(prefsInfo.fileName, "\p Preferences");
795 
796 		//�	Set creator to calling application's signature (should be able to
797 		//�	Determine this automatically, but unable to for some reason)
798 		prefsInfo.creator = creator;
799 		prefsInfo.fileType = 'pref';
800 		prefsInfo.resType = 'pref';
801 		prefsInfo.resID = 0;
802 	}
803 	else
804 	{
805 		//�	Get Preferences file setup from PRFI 0
806 		BlockMove(*piHdl, &prefsInfo, sizeof (prefsInfo));
807 		ReleaseResource((Handle) piHdl);
808 
809 		if (prefsInfo.creator == UNKNOWN_TYPE)
810 			prefsInfo.creator = creator;
811 	}
812 
813 	prefsInited = 1;
814 }
815 
816 //�	--------------------	LoadPrefsFile
817 
818 OSErr
LoadPrefsFile(Handle prefsHdl)819 LoadPrefsFile(Handle prefsHdl)
820 {
821 short	prefVRefNum, prefRefNum;
822 long		prefDirID;
823 OSErr	theErr = noErr;
824 Handle	origHdl;
825 Size		prefSize, origSize;
826 
827 	if (prefsHdl == nil)
828 		return (nilHandleErr);
829 
830 	prefSize = GetHandleSize(prefsHdl);
831 
832 	if (! FindPrefsFile(&prefVRefNum, &prefDirID))
833 		return (fnfErr);
834 
835 	prefRefNum = HOpenResFile(prefVRefNum, prefDirID, prefsInfo.fileName, fsRdWrPerm);
836 	if (prefRefNum == -1)
837 		return (ResError());
838 
839 	//�	Not finding the resource is not an error -- caller will use default data
840 	if ((origHdl = Get1Resource(prefsInfo.resType, prefsInfo.resID)) != nil)
841 	{
842 		origSize = GetHandleSize(origHdl);
843 		if (origSize > prefSize)			//�	Extend handle for extra stored data
844 			SetHandleSize(prefsHdl, origSize);
845 
846 		BlockMove(*origHdl, *prefsHdl, origSize);
847 		ReleaseResource(origHdl);
848 	}
849 
850 	CloseResFile(prefRefNum);
851 
852 	if (theErr == noErr)
853 		theErr = ResError();
854 
855 	return (theErr);
856 }
857 
858 //�	--------------------	SavePrefsFile
859 
860 OSErr
SavePrefsFile(Handle prefHdl)861 SavePrefsFile(Handle prefHdl)
862 {
863 short	prefVRefNum, prefRefNum;
864 long		prefDirID;
865 Handle	origHdl = nil;
866 Size		origSize, prefSize;
867 OSErr	theErr = noErr;
868 
869 	if (! FindPrefsFile(&prefVRefNum, &prefDirID))
870 		return (fnfErr);
871 
872 	if (prefHdl == nil)
873 		return (nilHandleErr);
874 
875 	prefSize = GetHandleSize(prefHdl);
876 
877 	prefRefNum = HOpenResFile(prefVRefNum, prefDirID, prefsInfo.fileName, fsRdWrPerm);
878 	if (prefRefNum == -1)
879 		return (ResError());
880 
881 	if ((origHdl = Get1Resource(prefsInfo.resType, prefsInfo.resID)) != nil)
882 	{
883 		//�	Overwrite existing preferences
884 		origSize = GetHandleSize(origHdl);
885 		if (prefSize > origSize)
886 			SetHandleSize(origHdl, prefSize);
887 
888 		BlockMove(*prefHdl, *origHdl, prefSize);
889 		ChangedResource(origHdl);
890 		WriteResource(origHdl);
891 		ReleaseResource(origHdl);
892 	}
893 	else
894 	{
895 		//�	Store specified preferences for the first time
896 		AddResource(prefHdl, prefsInfo.resType, prefsInfo.resID, "\p");
897 		WriteResource(prefHdl);
898 		DetachResource(prefHdl);
899 	}
900 
901 	CloseResFile(prefRefNum);
902 
903 	if (theErr == noErr)
904 		theErr = ResError();
905 
906 	return (theErr);
907 }
908 
909 //�	-------------------------------------------------------------------------------------------
910 
911 /*
912 
913 	This module provides the ability to save and load a preferences file in the
914 	Preferences folder in the System Folder.  An optional resource, PRFI 0,
915 	is used to provide specifications for the preferences file (creator, etc.).
916 
917 	Three functions are provided:
918 
919 		void InitPrefsFile(OSType creator)
920 
921 	This function will initialize the preferences file, that is, it will create
922 	it in the appropriate place if it doesn't currently exist.  It should be
923 	called with the creator code for the application.  Note that the creator
924 	code specified in PRFI 0 (if any) will be used only if the creator code
925 	passed to this function is '????'.  Without the PRFI 0 resource, the default
926 	specifications are:
927 
928 	File Name: "{Application} Prefs" (i.e., the name of the app plus " Prefs"
929 	Creator: the creator passed to InitPrefsFile
930 	Type: 'PREF'
931 	Pref Resource Type: 'PREF'
932  	Pref Resource ID: 0
933 
934 	The PRFI 0 resource allows you to specify overrides for each of the above
935 	values.  This is useful for development, since the application name might
936 	go through changes, but the preferences file name is held constant.
937 
938 	 	OSErr LoadPrefsFile(Handle prefsHndl)
939 
940 	This function will attempt to copy the data stored in the preferences
941 	file to the given handle (which must be pre-allocated).  If the handle is too
942 	small, then it will be enlarged.  If it is too large, it will not be resized.
943 	The data in the preferences file (normally in PREF 0) will then be copied
944 	into the handle.  If the preferences file did not exist, the original data
945 	in the handle will not change.
946 
947 		OSErr SavePrefsFile(Handle prefsHndl)
948 
949 	This function will attempt to save the given handle to the preferences
950 	file.  Its contents will completely replace the previous data (normally
951 	the PREF 0 resource).
952 
953 	In typical use, you will use InitPrefsFile once, then allocate a handle large
954 	enough to contain your preferences data, and initialize it with default values.
955 	Throughout the course of your program, the handle will undergo modification as
956 	user preferences change.  You can use SavePrefsFile anytime to update the
957 	preferences file, or wait until program exit to do so.
958 
959 */
960 
ReadConfigFile()961 int ReadConfigFile()
962 {
963 	int i;
964 	OSErr err;
965 	Handle prefs_handle;
966 	Preferences *prefs;
967 	char *p;
968 
969 	if (!have_prefs) {			// not initialized....get a handle to the preferences file
970 		InitPrefsFile('DCT2');
971 		have_prefs = 1;
972 	}
973 
974 	prefs_handle = NewHandleClear(sizeof(Preferences));		// new prefs handle
975 	if (prefs_handle == NULL)
976 		return;
977 
978 	prefs = (Preferences *)(*prefs_handle);
979 	err = LoadPrefsFile(prefs_handle);
980 	if (err) {
981 		DisposeHandle(prefs_handle);
982 		return -1;
983 	}
984 
985 	p = (char *)prefs;
986 	for (i = 0; i < sizeof(Preferences); i++) {
987 		if (*p != 0)
988 			break;
989 		p++;
990 	}
991 	if ( i == sizeof(Preferences) )
992 		return -1;
993 
994 	Config_digi_volume = prefs->digi_volume;
995 	Config_midi_volume = prefs->midi_volume;
996 	Config_master_volume = prefs->master_volume;
997 	Config_redbook_volume = prefs->redbook_volume;
998 	Config_channels_reversed = prefs->stereo_reverse;
999 	gr_palette_set_gamma( (int)(prefs->gamma_level) );
1000 
1001 	Scanline_double = (int)prefs->pixel_double;
1002 	if ( PAEnabled )
1003 		Scanline_double = 0;		// can't double with hardware acceleration
1004 
1005 	Detail_level = prefs->detail_level;
1006 	if (Detail_level == NUM_DETAIL_LEVELS-1) {
1007 		Object_complexity = prefs->oc;
1008 		Object_detail = prefs->od;
1009 		Wall_detail = prefs->wd;
1010 		Wall_render_depth = prefs->wrd;
1011 		Debris_amount = prefs->da;
1012 		SoundChannels = prefs->sc;
1013 		set_custom_detail_vars();
1014 	}
1015   #ifdef PA_3DFX_VOODOO   // Set to highest detail because you can't change em
1016 		   Object_complexity=Object_detail=Wall_detail=
1017 			Wall_render_depth=Debris_amount=SoundChannels = NUM_DETAIL_LEVELS-1;
1018 			Detail_level=NUM_DETAIL_LEVELS-1;
1019 			set_custom_detail_vars();
1020   #endif
1021 
1022 	strncpy( config_last_player, prefs->lastplayer, CALLSIGN_LEN );
1023 	p = strchr(config_last_player, '\n' );
1024 	if (p) *p = 0;
1025 
1026 	strncpy(config_last_mission, prefs->lastmission, MISSION_NAME_LEN);
1027 	p = strchr(config_last_mission, '\n' );
1028 	if (p) *p = 0;
1029 
1030 	strcpy(config_last_ctb_cfg, prefs->ctb_config);
1031 
1032 	if ( Config_digi_volume > 8 ) Config_digi_volume = 8;
1033 
1034 	if ( Config_midi_volume > 8 ) Config_midi_volume = 8;
1035 
1036 	joy_set_cal_vals( prefs->joy_axis_min, prefs->joy_axis_center, prefs->joy_axis_max);
1037 	digi_set_volume( (Config_digi_volume*256)/8, (Config_midi_volume*256)/8 );
1038 	digi_set_master_volume(Config_master_volume);
1039 
1040 	gConfigInfo.mDoNotDisplayOptions = prefs->display_dialog;
1041 	gConfigInfo.mUse11kSounds = prefs->sound_11k;
1042 	gConfigInfo.mDisableSound = prefs->nosound;
1043 	gConfigInfo.mDisableMIDIMusic = prefs->nomidi;
1044 	gConfigInfo.mChangeResolution = prefs->change_resolution;
1045 	gConfigInfo.mDoNotPlayMovies = prefs->no_movies;
1046 	gConfigInfo.mGameMonitor = prefs->game_monitor;
1047 	gConfigInfo.mAcceleration = prefs->enable_rave;
1048 	gConfigInfo.mInputSprockets = prefs->enable_input_sprockets;
1049 
1050 	DisposeHandle(prefs_handle);
1051 	return 0;
1052 }
1053 
WriteConfigFile()1054 int WriteConfigFile()
1055 {
1056 	OSErr err;
1057 	Handle prefs_handle;
1058 	Preferences *prefs;
1059 
1060 	prefs_handle = NewHandleClear(sizeof(Preferences));		// new prefs handle
1061 	if (prefs_handle == NULL)
1062 		return;
1063 
1064 	prefs = (Preferences *)(*prefs_handle);
1065 
1066 	joy_get_cal_vals(prefs->joy_axis_min, prefs->joy_axis_center, prefs->joy_axis_max);
1067 	prefs->digi_volume = Config_digi_volume;
1068 	prefs->midi_volume = Config_midi_volume;
1069 	prefs->stereo_reverse = Config_channels_reversed;
1070 	prefs->detail_level = Detail_level;
1071 	if (Detail_level == NUM_DETAIL_LEVELS-1) {
1072 		prefs->oc = Object_complexity;
1073 		prefs->od = Object_detail;
1074 		prefs->wd = Wall_detail;
1075 		prefs->wrd = Wall_render_depth;
1076 		prefs->da = Debris_amount;
1077 		prefs->sc = SoundChannels;
1078 	}
1079 	prefs->gamma_level = (ubyte)gr_palette_get_gamma();
1080 
1081 	if ( !PAEnabled )
1082 		prefs->pixel_double = (ubyte)Scanline_double;		// hmm..don't write this out if doing hardware accel.
1083 
1084 	strncpy( prefs->lastplayer, Players[Player_num].callsign, CALLSIGN_LEN );
1085 	strncpy( prefs->lastmission, config_last_mission, MISSION_NAME_LEN );
1086 	strcpy( prefs->ctb_config, config_last_ctb_cfg);
1087 	prefs->ctb_tool = config_last_ctb_tool;
1088 	prefs->master_volume = Config_master_volume;
1089 	prefs->display_dialog = gConfigInfo.mDoNotDisplayOptions;
1090 	prefs->change_resolution = gConfigInfo.mChangeResolution;
1091 	prefs->nosound = gConfigInfo.mDisableSound;
1092 	prefs->nomidi = gConfigInfo.mDisableMIDIMusic;
1093 	prefs->sound_11k = gConfigInfo.mUse11kSounds;
1094 	prefs->no_movies = gConfigInfo.mDoNotPlayMovies;
1095 	prefs->game_monitor = gConfigInfo.mGameMonitor;
1096 	prefs->redbook_volume = Config_redbook_volume;
1097 	prefs->enable_rave = gConfigInfo.mAcceleration;
1098 	prefs->enable_input_sprockets = gConfigInfo.mInputSprockets;
1099 
1100 	err = SavePrefsFile(prefs_handle);
1101 	DisposeHandle(prefs_handle);
1102 	return (int)err;
1103 }
1104 
1105 #endif
1106 
1107