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