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