whitespace
[btb/d2x.git] / main / config.c
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.5 2001-11-14 10:31:40 bradleyb 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
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
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
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, SaveMovieHires );
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.5 2001-11-14 10:31:40 bradleyb 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
668 Pstrcpy(StringPtr dst, StringPtr src)
669 {
670         BlockMove(src, dst, (*src) + 1);
671 }
672
673 //¥     --------------------    Pstrcat
674
675 static void
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
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
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
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
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
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
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