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.
16 * contains routine(s) to read in the configuration file which contains
17 * game configuration stuff like detail level, sound card, etc
25 #ifndef MACINTOSH // I'm going to totally seperate these routines -- yeeech!!!!
26 // see end of file for macintosh equivs
29 #define WIN32_LEAN_AND_MEAN
60 cvar_t Config_digi_type = { "DigiDeviceID8", "0", 1 };
61 cvar_t digi_driver_board_16 = { "DigiDeviceID16", "0", 1 };
62 //cvar_t digi_driver_port = { "DigiPort", "0", 1 };
63 //cvar_t digi_driver_irq = { "DigiIrq", "0", 1 };
64 cvar_t Config_digi_dma = { "DigiDma8", "0", 1 };
65 cvar_t digi_driver_dma_16 = { "DigiDma16", "0", 1 };
66 cvar_t Config_midi_type = { "MidiDeviceID", "0", 1 };
67 //cvar_t digi_midi_port = { "MidiPort", "0", 1 };
69 cvar_t Config_digi_volume = { "DigiVolume", "8", 1 };
70 cvar_t Config_midi_volume = { "MidiVolume", "8", 1 };
71 cvar_t Config_redbook_volume = { "RedbookVolume", "8", 1 };
72 cvar_t Config_detail_level = { "DetailLevel", "4", 1 };
73 cvar_t Config_gamma_level = { "GammaLevel", "0", 1 };
74 cvar_t Config_control_joystick = { "Joystick", "0", 1 };
75 cvar_t Config_control_mouse = { "Mouse", "0", 1 };
76 cvar_t Config_channels_reversed = { "StereoReverse", "0", 1 };
77 cvar_t Config_joystick_sensitivity = { "JoystickSensitivity", "8", 1 };
78 cvar_t Config_joystick_min = { "JoystickMin", "0,0,0,0", 1 };
79 cvar_t Config_joystick_max = { "JoystickMax", "0,0,0,0", 1 };
80 cvar_t Config_joystick_cen = { "JoystickCen", "0,0,0,0", 1 };
81 cvar_t config_last_player = { "LastPlayer", "", 1 };
82 cvar_t config_last_mission = { "LastMission", "", 1 };
83 cvar_t Config_vr_type = { "VR_type", "0", 1 };
84 cvar_t Config_vr_resolution = { "VR_resolution", "0", 1 };
85 cvar_t Config_vr_tracking = { "VR_tracking", "0", 1 };
86 cvar_t Config_primary_order = { "PrimaryOrder", "", 1 };
87 cvar_t Config_secondary_order = { "SecondaryOrder", "", 1 };
88 cvar_t Config_lifetime_kills = { "LifetimeKills", "0", 1 };
89 cvar_t Config_lifetime_killed = { "LifetimeKilled", "0", 1 };
90 cvar_t Config_lifetime_checksum = { "LifetimeChecksum", "0", 1 };
91 cvar_t Config_display_mode = { "vid_mode", "0", 1 };
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
100 extern sbyte Object_complexity, Object_detail, Wall_detail, Wall_render_depth, Debris_amount, SoundChannels;
102 void set_custom_detail_vars(void);
104 uint32_t legacy_display_mode[] = { SM(320,200), SM(640,480), SM(320,400), SM(640,400), SM(800,600), SM(1024,768), SM(1280,1024) };
110 void CrystalLakeWriteMCP( ushort mc_addr, ubyte mc_data )
113 outp( CL_MC0, 0xE2 ); // Write password
114 outp( mc_addr, mc_data ); // Write data
118 ubyte CrystalLakeReadMCP( ushort mc_addr )
122 outp( CL_MC0, 0xE2 ); // Write password
123 value = inp( mc_addr ); // Read data
128 void CrystalLakeSetSB()
131 tmp = CrystalLakeReadMCP( CL_MC1 );
133 CrystalLakeWriteMCP( CL_MC1, tmp );
136 void CrystalLakeSetWSS()
139 tmp = CrystalLakeReadMCP( CL_MC1 );
141 CrystalLakeWriteMCP( CL_MC1, tmp );
144 //MovieHires might be changed by -nohighres, so save a "real" copy of it
146 int save_redbook_enabled;
149 void CheckMovieAttributes()
152 DWORD len, type, val;
155 lres = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Parallax\\Descent II\\1.1\\INSTALL",
157 if (lres == ERROR_SUCCESS) {
159 lres = RegQueryValueEx(hKey, "HIRES", NULL, &type, &val, &len);
160 if (lres == ERROR_SUCCESS) {
161 cvar_setint( &MovieHires, val );
162 logentry("HIRES=%d\n", val);
170 static int config_initialized;
172 static void config_init(void)
174 /* make sure our cvars are registered */
175 cvar_registervariable(&Config_digi_volume);
176 cvar_registervariable(&Config_midi_volume);
177 cvar_registervariable(&Redbook_enabled);
178 cvar_registervariable(&Config_redbook_volume);
179 cvar_registervariable(&Config_channels_reversed);
180 cvar_registervariable(&Config_gamma_level);
181 cvar_registervariable(&Config_detail_level);
182 cvar_registervariable(&Config_control_joystick);
183 cvar_registervariable(&Config_control_mouse);
184 cvar_registervariable(&Config_joystick_sensitivity);
185 cvar_registervariable(&Config_joystick_min);
186 cvar_registervariable(&Config_joystick_cen);
187 cvar_registervariable(&Config_joystick_max);
188 cvar_registervariable(&config_last_player);
189 cvar_registervariable(&config_last_mission);
190 cvar_registervariable(&Config_vr_type);
191 cvar_registervariable(&Config_vr_resolution);
192 cvar_registervariable(&Config_vr_tracking);
193 cvar_registervariable(&MovieHires);
194 cvar_registervariable(&real_guidebot_name);
195 cvar_registervariable(&Config_primary_order);
196 cvar_registervariable(&Config_secondary_order);
197 cvar_registervariable(&Cockpit_3d_view[0]);
198 cvar_registervariable(&Cockpit_3d_view[1]);
199 cvar_registervariable(&Config_lifetime_kills);
200 cvar_registervariable(&Config_lifetime_killed);
201 cvar_registervariable(&Config_lifetime_checksum);
203 cvar_registervariable(&Network_message_macro[0]);
204 cvar_registervariable(&Network_message_macro[1]);
205 cvar_registervariable(&Network_message_macro[2]);
206 cvar_registervariable(&Network_message_macro[3]);
208 cvar_registervariable(&Game_window_w);
209 cvar_registervariable(&Game_window_h);
210 cvar_registervariable(&Player_default_difficulty);
211 cvar_registervariable(&Auto_leveling_on);
212 cvar_registervariable(&Reticle_on);
213 cvar_registervariable(&Cockpit_mode);
214 cvar_registervariable(&Config_display_mode);
215 cvar_registervariable(&Missile_view_enabled);
216 cvar_registervariable(&Headlight_active_default);
217 cvar_registervariable(&Guided_in_big_window);
218 cvar_registervariable(&Automap_always_hires);
220 config_initialized = 1;
224 static int get_lifetime_checksum (int a,int b)
228 // confusing enough to beat amateur disassemblers? Lets hope so
237 void LoadConfigDefaults(void)
239 cmd_append("bind UP +lookdown; bind PAD8 +lookdown");
240 cmd_append("bind DOWN +lookup; bind PAD2 +lookup");
241 cmd_append("bind LEFT +left; bind PAD4 +left");
242 cmd_append("bind RIGHT +right; bind PAD6 +right");
244 cmd_append("bind LALT +strafe");
245 cmd_append("bind PAD1 +moveleft");
246 cmd_append("bind PAD3 +moveright");
247 cmd_append("bind PAD- +moveup");
248 cmd_append("bind PAD+ +movedown");
250 cmd_append("bind Q +bankleft; bind PAD7 +bankleft");
251 cmd_append("bind E +bankright; bind PAD9 +bankright");
253 cmd_append("bind , +cycle");
254 cmd_append("bind . +cycle2");
256 cmd_append("bind LCTRL +attack; bind RCTRL +attack");
257 cmd_append("bind SPC +attack2");
258 cmd_append("bind F +flare");
259 cmd_append("bind B +bomb");
261 cmd_append("bind R +rearview");
262 cmd_append("bind TAB +automap");
264 cmd_append("bind A +forward");
265 cmd_append("bind Z +back");
266 cmd_append("bind S +afterburner");
268 cmd_append("bind H +headlight");
269 cmd_append("bind T +nrgshield");
271 cmd_append("bind J1B1 +attack");
272 cmd_append("bind J1B2 +attack2");
274 cmd_append("bind MB1 +attack");
275 cmd_append("bind MB2 +attack2");
277 cmd_append("bind 1 weapon 1");
278 cmd_append("bind 2 weapon 2");
279 cmd_append("bind 3 weapon 3");
280 cmd_append("bind 4 weapon 4");
281 cmd_append("bind 5 weapon 5");
282 cmd_append("bind 6 weapon 6");
283 cmd_append("bind 7 weapon 7");
284 cmd_append("bind 8 weapon 8");
285 cmd_append("bind 9 weapon 9");
286 cmd_append("bind 0 weapon 0");
293 int joy_axis_center[7];
297 if (!config_initialized)
300 cvar_set_cvar( &config_last_player, "" );
302 joy_axis_min[0] = joy_axis_min[1] = joy_axis_min[2] = joy_axis_min[3] = 0;
303 joy_axis_max[0] = joy_axis_max[1] = joy_axis_max[2] = joy_axis_max[3] = 0;
304 joy_axis_center[0] = joy_axis_center[1] = joy_axis_center[2] = joy_axis_center[3] = 0;
306 joy_set_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max);
309 cvar_setint(&digi_driver_board, 0);
310 cvar_setint(&digi_driver_port, 0);
311 cvar_setint(&digi_driver_irq, 0);
312 cvar_setint(&digi_driver_dma, 0);
313 cvar_setint(&digi_midi_type, 0);
314 cvar_setint(&digi_midi_port, 0);
317 cvar_setint( &Config_digi_volume, 8 );
318 cvar_setint( &Config_midi_volume, 8 );
319 cvar_setint( &Config_redbook_volume, 8 );
320 cvar_setint( &Config_control_joystick, 0 );
321 cvar_setint( &Config_control_mouse, 0 );
322 cvar_setint( &Config_channels_reversed, 0);
323 cvar_setint( &Config_joystick_sensitivity, 8 );
325 //set these here in case no cfg file
326 SaveMovieHires = MovieHires.intval;
327 save_redbook_enabled = Redbook_enabled.intval;
329 InitWeaponOrdering(); // setup default weapon priorities
330 cvar_set_cvarf(&Config_primary_order, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
331 PrimaryOrder[0], PrimaryOrder[1], PrimaryOrder[2], PrimaryOrder[3],
332 PrimaryOrder[4], PrimaryOrder[5], PrimaryOrder[6], PrimaryOrder[7],
333 PrimaryOrder[8], PrimaryOrder[9], PrimaryOrder[10]);
334 cvar_set_cvarf(&Config_secondary_order, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
335 SecondaryOrder[0], SecondaryOrder[1], SecondaryOrder[2], SecondaryOrder[3],
336 SecondaryOrder[4], SecondaryOrder[5], SecondaryOrder[6], SecondaryOrder[7],
337 SecondaryOrder[8], SecondaryOrder[9], SecondaryOrder[10]);
339 cvar_setint( &Cockpit_3d_view[0], CV_NONE );
340 cvar_setint( &Cockpit_3d_view[1], CV_NONE );
342 cvar_setint( &Config_lifetime_kills, 0 );
343 cvar_setint( &Config_lifetime_killed, 0 );
344 cvar_setint( &Config_lifetime_checksum, 0 );
346 // Default taunt macros
348 cvar_set_cvar(&Network_message_macro[0], "Why can't we all just get along?");
349 cvar_set_cvar(&Network_message_macro[1], "Hey, I got a present for ya");
350 cvar_set_cvar(&Network_message_macro[2], "I got a hankerin' for a spankerin'");
351 cvar_set_cvar(&Network_message_macro[3], "This one's headed for Uranus");
354 cvar_setint(&Player_default_difficulty, 1);
355 cvar_setint(&Auto_leveling_on, 1);
357 if (cfexist("descent.cfg"))
358 cmd_append("exec descent.cfg");
360 LoadConfigDefaults();
364 /* TODO: allow cvars to define a callback that will carry out these initialization things on change. */
366 gr_palette_set_gamma( Config_gamma_level.intval );
368 Detail_level = strtol(Config_detail_level.string, NULL, 10);
369 if (Detail_level == NUM_DETAIL_LEVELS - 1) {
370 int count,dummy,oc,od,wd,wrd,da,sc;
372 count = sscanf (Config_detail_level.string, "%d,%d,%d,%d,%d,%d,%d\n",&dummy,&oc,&od,&wd,&wrd,&da,&sc);
375 Object_complexity = oc;
378 Wall_render_depth = wrd;
381 set_custom_detail_vars();
385 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] );
386 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] );
387 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] );
389 joy_set_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max);
391 i = FindArg( "-volume" );
394 i = atoi( Args[i+1] );
396 if ( i > 100 ) i = 100;
397 cvar_setint( &Config_digi_volume, (i * 8) / 100 );
398 cvar_setint( &Config_midi_volume, (i * 8) / 100 );
399 cvar_setint( &Config_redbook_volume, (i * 8) / 100 );
402 if ( Config_digi_volume.intval > 8 ) cvar_setint( &Config_digi_volume, 8 );
403 if ( Config_midi_volume.intval > 8 ) cvar_setint( &Config_midi_volume, 8 );
404 if ( Config_redbook_volume.intval > 8 ) cvar_setint( &Config_redbook_volume, 8 );
406 digi_set_volume( (Config_digi_volume.intval * 32768) / 8, (Config_midi_volume.intval * 128) / 8 );
410 strncpy(guidebot_name, real_guidebot_name.string, GUIDEBOT_NAME_LEN);
411 guidebot_name[GUIDEBOT_NAME_LEN] = 0;
413 sscanf(Config_primary_order.string, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
414 (int *)&PrimaryOrder[0], (int *)&PrimaryOrder[1], (int *)&PrimaryOrder[2], (int *)&PrimaryOrder[3],
415 (int *)&PrimaryOrder[4], (int *)&PrimaryOrder[5], (int *)&PrimaryOrder[6], (int *)&PrimaryOrder[7],
416 (int *)&PrimaryOrder[8], (int *)&PrimaryOrder[9], (int *)&PrimaryOrder[10]);
417 sscanf(Config_secondary_order.string, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
418 (int *)&SecondaryOrder[0], (int *)&SecondaryOrder[1], (int *)&SecondaryOrder[2], (int *)&SecondaryOrder[3],
419 (int *)&SecondaryOrder[4], (int *)&SecondaryOrder[5], (int *)&SecondaryOrder[6], (int *)&SecondaryOrder[7],
420 (int *)&SecondaryOrder[8], (int *)&SecondaryOrder[9], (int *)&SecondaryOrder[10]);
423 Netlife_kills = Config_lifetime_kills.intval;
424 Netlife_killed = Config_lifetime_killed.intval;
426 con_printf(CON_DEBUG, "Reading: lifetime checksum is %d\n", Config_lifetime_checksum.intval);
427 if (Config_lifetime_checksum.intval != get_lifetime_checksum(Netlife_kills, Netlife_killed)) {
428 Netlife_kills = Netlife_killed = 0;
429 Warning("Shame on me\nTrying to cheat eh?");
433 Default_display_mode = legacy_display_mode[Config_display_mode.intval];
436 printf( "DigiDeviceID: 0x%x\n", digi_driver_board );
437 printf( "DigiPort: 0x%x\n", digi_driver_port.intval );
438 printf( "DigiIrq: 0x%x\n", digi_driver_irq.intval );
439 printf( "DigiDma: 0x%x\n", digi_driver_dma.intval );
440 printf( "MidiDeviceID: 0x%x\n", digi_midi_type.intval );
441 printf( "MidiPort: 0x%x\n", digi_midi_port.intval );
444 cvar_setint( &Config_midi_type, digi_midi_type );
445 cvar_setint( &Config_digi_type, digi_driver_board );
446 cvar_setint( &Config_digi_dma, digi_driver_dma );
450 if (digi_driver_board_16.intval > 0 && !FindArg("-no16bit") && digi_driver_board_16.intval != _GUS_16_ST) {
451 digi_driver_board = digi_driver_board_16.intval;
452 digi_driver_dma = digi_driver_dma_16.intval;
456 //Hack to make some cards look like others, such as
457 //the Crytal Lake look like Microsoft Sound System
458 if ( digi_driver_board == _CRYSTAL_LAKE_8_ST ) {
460 tmp = CrystalLakeReadMCP( CL_MC1 );
462 atexit( CrystalLakeSetSB ); // Restore to SB when done.
464 digi_driver_board = _MICROSOFT_8_ST;
465 } else if ( digi_driver_board == _CRYSTAL_LAKE_16_ST ) {
467 tmp = CrystalLakeReadMCP( CL_MC1 );
469 atexit( CrystalLakeSetSB ); // Restore to SB when done.
471 digi_driver_board = _MICROSOFT_16_ST;
472 } else if ( digi_driver_board == _AWE32_8_ST ) {
473 digi_driver_board = _SB16_8_ST;
474 } else if ( digi_driver_board == _AWE32_16_ST ) {
475 digi_driver_board = _SB16_16_ST;
477 digi_driver_board = digi_driver_board;
480 if (cfexist("descentw.cfg")) {
481 cmd_append("exec descentw.cfg");
484 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] );
485 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] );
486 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] );
493 int WriteConfigFile()
495 PHYSFS_file *outfile;
497 int joy_axis_center[7];
501 joy_get_cal_vals(joy_axis_min, joy_axis_center, joy_axis_max);
503 if (FindArg("-noredbook"))
504 cvar_setint( &Redbook_enabled, save_redbook_enabled );
506 cvar_setint( &Config_gamma_level, gr_palette_get_gamma() );
508 if (Detail_level == NUM_DETAIL_LEVELS-1)
509 cvar_set_cvarf( &Config_detail_level, "%d,%d,%d,%d,%d,%d,%d", Detail_level,
510 Object_complexity,Object_detail,Wall_detail,Wall_render_depth,Debris_amount,SoundChannels );
512 cvar_setint( &Config_detail_level, Detail_level );
514 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] );
515 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] );
516 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] );
518 cvar_set_cvar( &config_last_player, Players[Player_num].callsign );
520 cvar_setint( &MovieHires, SaveMovieHires );
522 cvar_set_cvarf(&Config_primary_order, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
523 PrimaryOrder[0], PrimaryOrder[1], PrimaryOrder[2], PrimaryOrder[3],
524 PrimaryOrder[4], PrimaryOrder[5], PrimaryOrder[6], PrimaryOrder[7],
525 PrimaryOrder[8], PrimaryOrder[9], PrimaryOrder[10]);
526 cvar_set_cvarf(&Config_secondary_order, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
527 SecondaryOrder[0], SecondaryOrder[1], SecondaryOrder[2], SecondaryOrder[3],
528 SecondaryOrder[4], SecondaryOrder[5], SecondaryOrder[6], SecondaryOrder[7],
529 SecondaryOrder[8], SecondaryOrder[9], SecondaryOrder[10]);
532 cvar_setint(&Config_lifetime_kills, Netlife_kills);
533 cvar_setint(&Config_lifetime_killed, Netlife_killed);
534 cvar_setint(&Config_lifetime_checksum, get_lifetime_checksum(Netlife_kills, Netlife_killed));
535 con_printf(CON_DEBUG, "Writing: Lifetime checksum is %d\n", Config_lifetime_checksum.intval);
538 cvar_setint(&Cockpit_mode, (Cockpit_mode_save != -1)?Cockpit_mode_save:Cockpit_mode.intval); //if have saved mode, write it instead of letterbox/rear view
540 for (i = 0; i < (sizeof(legacy_display_mode) / sizeof(uint32_t)); i++) {
541 if (legacy_display_mode[i] == Current_display_mode)
542 cvar_setint(&Config_display_mode, i);
545 outfile = PHYSFSX_openWriteBuffered("descent.cfg");
549 key_write_bindings(outfile);
550 PHYSFS_close(outfile);
552 if (FindArg("-nohires") || FindArg("-nohighres") || FindArg("-lowresmovies"))
553 cvar_setint( &MovieHires, 0 );
556 CheckMovieAttributes();
562 #else // !defined(MACINTOSH)
571 #include <GestaltEqu.h>
573 #include <Processes.h>
574 #include <Resources.h>
587 #include "prefs.h" // prefs file for configuration stuff -- from DeSalvo
589 #define MAX_CTB_LEN 512
591 typedef struct preferences {
594 ubyte stereo_reverse;
596 ubyte oc; // object complexity
597 ubyte od; // object detail
598 ubyte wd; // wall detail
599 ubyte wrd; // wall render depth
600 ubyte da; // debris amount
601 ubyte sc; // sound channels
606 int joy_axis_center[4];
607 char lastplayer[CALLSIGN_LEN+1];
608 char lastmission[MISSION_NAME_LEN+1];
609 char ctb_config[MAX_CTB_LEN];
612 ubyte display_dialog;
613 ubyte change_resolution;
619 ubyte redbook_volume;
621 ubyte enable_input_sprockets;
624 char config_last_player[CALLSIGN_LEN+1] = "";
625 char config_last_mission[MISSION_NAME_LEN+1] = "";
626 char config_last_ctb_cfg[MAX_CTB_LEN] = "";
627 int config_last_ctb_tool;
628 ubyte Config_master_volume = 4;
629 ubyte Config_digi_volume = 8;
630 ubyte Config_midi_volume = 8;
631 ubyte Config_redbook_volume = 8;
632 ubyte Config_control_type = 0;
633 ubyte Config_channels_reversed = 0;
634 ubyte Config_joystick_sensitivity = 8;
636 int Config_vr_type = 0;
637 int Config_vr_resolution = 0;
638 int Config_vr_tracking = 0;
640 extern sbyte Object_complexity, Object_detail, Wall_detail, Wall_render_depth, Debris_amount, SoundChannels;
641 extern void digi_set_master_volume( int volume );
643 void set_custom_detail_vars(void);
645 static ubyte have_prefs = 0;
647 //¥ ------------------------------ Private Definitions
648 //¥ ------------------------------ Private Types
657 } PrefsInfo, *PrefsInfoPtr, **PrefsInfoHandle;
659 //¥ ------------------------------ Private Variables
661 static PrefsInfo prefsInfo;
662 static Boolean prefsInited = 0;
664 //¥ ------------------------------ Private Functions
666 static void Pstrcpy(StringPtr dst, StringPtr src);
667 static void Pstrcat(StringPtr dst, StringPtr src);
668 static Boolean FindPrefsFile(short *prefVRefNum, long *prefDirID);
670 //¥ -------------------- Pstrcpy
673 Pstrcpy(StringPtr dst, StringPtr src)
675 BlockMove(src, dst, (*src) + 1);
678 //¥ -------------------- Pstrcat
681 Pstrcat(StringPtr dst, StringPtr src)
683 BlockMove(src + 1, dst + (*dst) + 1, *src);
687 //¥ -------------------- FindPrefsFile
690 FindPrefsFile(short *prefVRefNum, long *prefDirID)
699 theErr = Gestalt(gestaltFindFolderAttr, &response);
700 if (theErr == noErr && ((response >> gestaltFindFolderPresent) & 1))
702 //¥ Find (or make) it the easy way...
703 theErr = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, prefVRefNum, prefDirID);
708 StringPtr prefFolderName = "\pPreferences";
710 //¥ yeachh -- we have to do it all by hand!
711 theErr = SysEnvirons(1, &theSysEnv);
715 *prefVRefNum = theSysEnv.sysVRefNum;
717 //¥ Check whether Preferences folder already exists
718 infoPB.hFileInfo.ioCompletion = 0;
719 infoPB.hFileInfo.ioNamePtr = prefFolderName;
720 infoPB.hFileInfo.ioVRefNum = *prefVRefNum;
721 infoPB.hFileInfo.ioFDirIndex = 0;
722 infoPB.hFileInfo.ioDirID = 0;
724 theErr = PBGetCatInfo(&infoPB, 0);
727 *prefDirID = infoPB.hFileInfo.ioDirID;
729 else if (theErr == fnfErr) //¥ Preferences doesn't already exist
731 HParamBlockRec dirPB;
733 //¥ Create "Preferences" folder
734 dirPB.fileParam.ioCompletion = 0;
735 dirPB.fileParam.ioVRefNum = *prefVRefNum;
736 dirPB.fileParam.ioNamePtr = prefFolderName;
737 dirPB.fileParam.ioDirID = 0;
739 theErr = PBDirCreate(&dirPB, 0);
741 *prefDirID = dirPB.fileParam.ioDirID;
745 //¥ If we make it here OK, create Preferences file if necessary
748 infoPB.hFileInfo.ioCompletion = 0;
749 infoPB.hFileInfo.ioNamePtr = prefsInfo.fileName;
750 infoPB.hFileInfo.ioVRefNum = *prefVRefNum;
751 infoPB.hFileInfo.ioFDirIndex = 0;
752 infoPB.hFileInfo.ioDirID = *prefDirID;
754 theErr = PBGetCatInfo(&infoPB, 0);
755 if (theErr == fnfErr)
757 theErr = HCreate(*prefVRefNum, *prefDirID, prefsInfo.fileName, prefsInfo.creator, prefsInfo.fileType);
760 HCreateResFile(*prefVRefNum, *prefDirID, prefsInfo.fileName);
766 return (theErr == noErr);
769 //¥ -------------------- InitPrefsFile
771 #define UNKNOWN_TYPE 0x3f3f3f3f
774 InitPrefsFile(OSType creator)
777 PrefsInfoHandle piHdl;
779 if ((piHdl = (PrefsInfoHandle) GetResource('PRFI', 0)) == nil)
781 ProcessSerialNumber thePSN;
782 ProcessInfoRec thePIR;
784 StringPtr app_string;
787 GetCurrentProcess(&thePSN);
788 thePIR.processName = nil;
789 thePIR.processAppSpec = &appSpec;
791 //¥ Set default to 'ÇApplicationÈ Prefs', PREF 0
792 err = GetProcessInformation(&thePSN, &thePIR);
796 app_string = LMGetCurApName();
797 // Pstrcpy(prefsInfo.fileName, appSpec.name);
798 Pstrcpy(prefsInfo.fileName, app_string);
799 Pstrcat(prefsInfo.fileName, "\p Preferences");
801 //¥ Set creator to calling application's signature (should be able to
802 //¥ Determine this automatically, but unable to for some reason)
803 prefsInfo.creator = creator;
804 prefsInfo.fileType = 'pref';
805 prefsInfo.resType = 'pref';
810 //¥ Get Preferences file setup from PRFI 0
811 BlockMove(*piHdl, &prefsInfo, sizeof (prefsInfo));
812 ReleaseResource((Handle) piHdl);
814 if (prefsInfo.creator == UNKNOWN_TYPE)
815 prefsInfo.creator = creator;
821 //¥ -------------------- LoadPrefsFile
824 LoadPrefsFile(Handle prefsHdl)
826 short prefVRefNum, prefRefNum;
828 OSErr theErr = noErr;
830 Size prefSize, origSize;
833 return (nilHandleErr);
835 prefSize = GetHandleSize(prefsHdl);
837 if (! FindPrefsFile(&prefVRefNum, &prefDirID))
840 prefRefNum = HOpenResFile(prefVRefNum, prefDirID, prefsInfo.fileName, fsRdWrPerm);
841 if (prefRefNum == -1)
844 //¥ Not finding the resource is not an error -- caller will use default data
845 if ((origHdl = Get1Resource(prefsInfo.resType, prefsInfo.resID)) != nil)
847 origSize = GetHandleSize(origHdl);
848 if (origSize > prefSize) //¥ Extend handle for extra stored data
849 SetHandleSize(prefsHdl, origSize);
851 BlockMove(*origHdl, *prefsHdl, origSize);
852 ReleaseResource(origHdl);
855 CloseResFile(prefRefNum);
863 //¥ -------------------- SavePrefsFile
866 SavePrefsFile(Handle prefHdl)
868 short prefVRefNum, prefRefNum;
870 Handle origHdl = nil;
871 Size origSize, prefSize;
872 OSErr theErr = noErr;
874 if (! FindPrefsFile(&prefVRefNum, &prefDirID))
878 return (nilHandleErr);
880 prefSize = GetHandleSize(prefHdl);
882 prefRefNum = HOpenResFile(prefVRefNum, prefDirID, prefsInfo.fileName, fsRdWrPerm);
883 if (prefRefNum == -1)
886 if ((origHdl = Get1Resource(prefsInfo.resType, prefsInfo.resID)) != nil)
888 //¥ Overwrite existing preferences
889 origSize = GetHandleSize(origHdl);
890 if (prefSize > origSize)
891 SetHandleSize(origHdl, prefSize);
893 BlockMove(*prefHdl, *origHdl, prefSize);
894 ChangedResource(origHdl);
895 WriteResource(origHdl);
896 ReleaseResource(origHdl);
900 //¥ Store specified preferences for the first time
901 AddResource(prefHdl, prefsInfo.resType, prefsInfo.resID, "\p");
902 WriteResource(prefHdl);
903 DetachResource(prefHdl);
906 CloseResFile(prefRefNum);
914 //¥ -------------------------------------------------------------------------------------------
918 This module provides the ability to save and load a preferences file in the
919 Preferences folder in the System Folder. An optional resource, PRFI 0,
920 is used to provide specifications for the preferences file (creator, etc.).
922 Three functions are provided:
924 void InitPrefsFile(OSType creator)
926 This function will initialize the preferences file, that is, it will create
927 it in the appropriate place if it doesn't currently exist. It should be
928 called with the creator code for the application. Note that the creator
929 code specified in PRFI 0 (if any) will be used only if the creator code
930 passed to this function is '????'. Without the PRFI 0 resource, the default
933 File Name: "{Application} Prefs" (i.e., the name of the app plus " Prefs"
934 Creator: the creator passed to InitPrefsFile
936 Pref Resource Type: 'PREF'
939 The PRFI 0 resource allows you to specify overrides for each of the above
940 values. This is useful for development, since the application name might
941 go through changes, but the preferences file name is held constant.
943 OSErr LoadPrefsFile(Handle prefsHndl)
945 This function will attempt to copy the data stored in the preferences
946 file to the given handle (which must be pre-allocated). If the handle is too
947 small, then it will be enlarged. If it is too large, it will not be resized.
948 The data in the preferences file (normally in PREF 0) will then be copied
949 into the handle. If the preferences file did not exist, the original data
950 in the handle will not change.
952 OSErr SavePrefsFile(Handle prefsHndl)
954 This function will attempt to save the given handle to the preferences
955 file. Its contents will completely replace the previous data (normally
956 the PREF 0 resource).
958 In typical use, you will use InitPrefsFile once, then allocate a handle large
959 enough to contain your preferences data, and initialize it with default values.
960 Throughout the course of your program, the handle will undergo modification as
961 user preferences change. You can use SavePrefsFile anytime to update the
962 preferences file, or wait until program exit to do so.
974 if (!have_prefs) { // not initialized....get a handle to the preferences file
975 InitPrefsFile('DCT2');
979 prefs_handle = NewHandleClear(sizeof(Preferences)); // new prefs handle
980 if (prefs_handle == NULL)
983 prefs = (Preferences *)(*prefs_handle);
984 err = LoadPrefsFile(prefs_handle);
986 DisposeHandle(prefs_handle);
991 for (i = 0; i < sizeof(Preferences); i++) {
996 if ( i == sizeof(Preferences) )
999 Config_digi_volume = prefs->digi_volume;
1000 Config_midi_volume = prefs->midi_volume;
1001 Config_master_volume = prefs->master_volume;
1002 Config_redbook_volume = prefs->redbook_volume;
1003 Config_channels_reversed = prefs->stereo_reverse;
1004 gr_palette_set_gamma( (int)(prefs->gamma_level) );
1006 Scanline_double = (int)prefs->pixel_double;
1008 Scanline_double = 0; // can't double with hardware acceleration
1010 Detail_level = prefs->detail_level;
1011 if (Detail_level == NUM_DETAIL_LEVELS-1) {
1012 Object_complexity = prefs->oc;
1013 Object_detail = prefs->od;
1014 Wall_detail = prefs->wd;
1015 Wall_render_depth = prefs->wrd;
1016 Debris_amount = prefs->da;
1017 SoundChannels = prefs->sc;
1018 set_custom_detail_vars();
1021 strncpy( config_last_player, prefs->lastplayer, CALLSIGN_LEN );
1022 p = strchr(config_last_player, '\n' );
1025 strncpy(config_last_mission, prefs->lastmission, MISSION_NAME_LEN);
1026 p = strchr(config_last_mission, '\n' );
1029 strcpy(config_last_ctb_cfg, prefs->ctb_config);
1031 if ( Config_digi_volume > 8 ) Config_digi_volume = 8;
1033 if ( Config_midi_volume > 8 ) Config_midi_volume = 8;
1035 joy_set_cal_vals( prefs->joy_axis_min, prefs->joy_axis_center, prefs->joy_axis_max);
1036 digi_set_volume( (Config_digi_volume*256)/8, (Config_midi_volume*256)/8 );
1037 digi_set_master_volume(Config_master_volume);
1039 gConfigInfo.mDoNotDisplayOptions = prefs->display_dialog;
1040 gConfigInfo.mUse11kSounds = prefs->sound_11k;
1041 gConfigInfo.mDisableSound = prefs->nosound;
1042 gConfigInfo.mDisableMIDIMusic = prefs->nomidi;
1043 gConfigInfo.mChangeResolution = prefs->change_resolution;
1044 gConfigInfo.mDoNotPlayMovies = prefs->no_movies;
1045 gConfigInfo.mGameMonitor = prefs->game_monitor;
1046 gConfigInfo.mAcceleration = prefs->enable_rave;
1047 gConfigInfo.mInputSprockets = prefs->enable_input_sprockets;
1049 DisposeHandle(prefs_handle);
1053 int WriteConfigFile()
1056 Handle prefs_handle;
1059 prefs_handle = NewHandleClear(sizeof(Preferences)); // new prefs handle
1060 if (prefs_handle == NULL)
1063 prefs = (Preferences *)(*prefs_handle);
1065 joy_get_cal_vals(prefs->joy_axis_min, prefs->joy_axis_center, prefs->joy_axis_max);
1066 prefs->digi_volume = Config_digi_volume;
1067 prefs->midi_volume = Config_midi_volume;
1068 prefs->stereo_reverse = Config_channels_reversed;
1069 prefs->detail_level = Detail_level;
1070 if (Detail_level == NUM_DETAIL_LEVELS-1) {
1071 prefs->oc = Object_complexity;
1072 prefs->od = Object_detail;
1073 prefs->wd = Wall_detail;
1074 prefs->wrd = Wall_render_depth;
1075 prefs->da = Debris_amount;
1076 prefs->sc = SoundChannels;
1078 prefs->gamma_level = (ubyte)gr_palette_get_gamma();
1081 prefs->pixel_double = (ubyte)Scanline_double; // hmm..don't write this out if doing hardware accel.
1083 strncpy( prefs->lastplayer, Players[Player_num].callsign, CALLSIGN_LEN );
1084 strncpy( prefs->lastmission, config_last_mission, MISSION_NAME_LEN );
1085 strcpy( prefs->ctb_config, config_last_ctb_cfg);
1086 prefs->ctb_tool = config_last_ctb_tool;
1087 prefs->master_volume = Config_master_volume;
1088 prefs->display_dialog = gConfigInfo.mDoNotDisplayOptions;
1089 prefs->change_resolution = gConfigInfo.mChangeResolution;
1090 prefs->nosound = gConfigInfo.mDisableSound;
1091 prefs->nomidi = gConfigInfo.mDisableMIDIMusic;
1092 prefs->sound_11k = gConfigInfo.mUse11kSounds;
1093 prefs->no_movies = gConfigInfo.mDoNotPlayMovies;
1094 prefs->game_monitor = gConfigInfo.mGameMonitor;
1095 prefs->redbook_volume = Config_redbook_volume;
1096 prefs->enable_rave = gConfigInfo.mAcceleration;
1097 prefs->enable_input_sprockets = gConfigInfo.mInputSprockets;
1099 err = SavePrefsFile(prefs_handle);
1100 DisposeHandle(prefs_handle);