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