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