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