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