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