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