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.
15 * $Source: /cvs/cvsroot/d2x/main/playsave.c,v $
18 * $Date: 2002-07-29 02:32:32 $
20 * Functions to load & save player games
22 * $Log: not supported by cvs2svn $
23 * Revision 1.4 2001/11/12 00:59:07 bradleyb
24 * load player files regardless of byte order of sig
26 * Revision 1.3 2001/11/11 23:39:22 bradleyb
27 * Created header for MAKE_SIG macro
73 #define SAVE_FILE_ID MAKE_SIG('D','P','L','R')
77 #include <Errors.h> // mac doesn't have "normal" error numbers -- must use mac equivs
87 int get_lifetime_checksum (int a,int b);
96 hli highest_levels[MAX_MISSIONS];
98 #define PLAYER_FILE_VERSION 24 //increment this every time the player file changes
100 //version 5 -> 6: added new highest level information
101 //version 6 -> 7: stripped out the old saved_game array.
102 //version 7 -> 8: added reticle flag, & window size
103 //version 8 -> 9: removed player_struct_version
104 //version 9 -> 10: added default display mode
105 //version 10 -> 11: added all toggles in toggle menu
106 //version 11 -> 12: added weapon ordering
107 //version 12 -> 13: added more keys
108 //version 13 -> 14: took out marker key
109 //version 14 -> 15: added guided in big window
110 //version 15 -> 16: added small windows in cockpit
111 //version 16 -> 17: ??
112 //version 17 -> 18: save guidebot name
113 //version 18 -> 19: added automap-highres flag
114 //version 19 -> 20: added kconfig data for windows joysticks
115 //version 20 -> 21: save seperate config types for DOS & Windows
116 //version 21 -> 22: save lifetime netstats
117 //version 22 -> 23: ??
118 //version 23 -> 24: add name of joystick for windows version.
120 #define COMPATIBLE_PLAYER_FILE_VERSION 17
123 int Default_leveling_on=1;
124 extern ubyte SecondaryOrder[],PrimaryOrder[];
125 extern void InitWeaponOrdering();
128 extern ubyte default_firebird_settings[];
129 extern ubyte default_mousestick_settings[];
132 int new_player_config()
135 int i,j,control_choice;
137 int mct=CONTROL_MAX_TYPES;
143 InitWeaponOrdering (); //setup default weapon priorities
145 #if defined(MACINTOSH) && defined(USE_ISP)
150 #if !defined(MACINTOSH) && !defined(WINDOWS)
151 for (i=0; i<mct; i++ ) {
152 m[i].type = NM_TYPE_MENU; m[i].text = CONTROL_TEXT(i);
154 #elif defined(WINDOWS)
155 m[0].type = NM_TYPE_MENU; m[0].text = CONTROL_TEXT(0);
156 m[1].type = NM_TYPE_MENU; m[1].text = CONTROL_TEXT(5);
157 m[2].type = NM_TYPE_MENU; m[2].text = CONTROL_TEXT(7);
160 for (i = 0; i < 6; i++) {
161 m[i].type = NM_TYPE_MENU; m[i].text = CONTROL_TEXT(i);
163 m[4].text = "Gravis Firebird/Mousetick II";
164 m[3].text = "Thrustmaster";
168 m[0].text = TXT_CONTROL_KEYBOARD;
171 if (Config_control_type==CONTROL_NONE) control_choice = 0;
172 else if (Config_control_type == CONTROL_MOUSE) control_choice = 1;
173 else if (Config_control_type == CONTROL_WINJOYSTICK) control_choice = 2;
174 else control_choice = 0;
176 control_choice = Config_control_type; // Assume keyboard
180 control_choice = newmenu_do1( NULL, TXT_CHOOSE_INPUT, i, m, NULL, control_choice );
185 if ( control_choice < 0 )
188 #if defined(MACINTOSH) && defined(USE_ISP)
190 else // !!!!NOTE ... link to above if (!ISpEnabled()), this is a really crappy function
196 for (i=0;i<CONTROL_MAX_TYPES; i++ )
197 for (j=0;j<MAX_CONTROLS; j++ )
198 kconfig_settings[i][j] = default_kconfig_settings[i][j];
201 Config_control_type = control_choice;
204 if (control_choice == 1) Config_control_type = CONTROL_MOUSE;
205 else if (control_choice == 2) Config_control_type = CONTROL_WINJOYSTICK;
207 // if (Config_control_type == CONTROL_WINJOYSTICK)
208 // joydefs_calibrate();
211 if ( Config_control_type==CONTROL_THRUSTMASTER_FCS) {
212 i = nm_messagebox( TXT_IMPORTANT_NOTE, 2, "Choose another", TXT_OK, TXT_FCS );
213 if (i==0) goto RetrySelection;
216 if ( (Config_control_type>0) && (Config_control_type<5)) {
219 #else // some macintosh only stuff here
220 if ( Config_control_type==CONTROL_THRUSTMASTER_FCS) {
221 extern char *tm_warning;
223 i = nm_messagebox( TXT_IMPORTANT_NOTE, 2, "Choose another", TXT_OK, tm_warning );
224 if (i==0) goto RetrySelection;
225 } else if ( Config_control_type==CONTROL_FLIGHTSTICK_PRO ) {
226 extern char *ch_warning;
228 i = nm_messagebox( TXT_IMPORTANT_NOTE, 2, "Choose another", TXT_OK, ch_warning );
229 if (i==0) goto RetrySelection;
230 } else if ( Config_control_type==CONTROL_GRAVIS_GAMEPAD ) {
231 extern char *ms_warning;
233 i = nm_messagebox( TXT_IMPORTANT_NOTE, 2, "Choose another", TXT_OK, ms_warning );
234 if (i==0) goto RetrySelection;
235 // stupid me -- get real default setting for either mousestick or firebird
236 joydefs_set_type( Config_control_type );
237 if (joy_have_firebird())
238 for (i=0; i<NUM_OTHER_CONTROLS; i++ )
239 kconfig_settings[Config_control_type][i] = default_firebird_settings[i];
241 for (i=0; i<NUM_OTHER_CONTROLS; i++ )
242 kconfig_settings[Config_control_type][i] = default_mousestick_settings[i];
243 kc_set_controls(); // reset the joystick control
245 if ( (Config_control_type>0) && (Config_control_type<5) ) {
246 joydefs_set_type( Config_control_type );
253 Player_default_difficulty = 1;
254 Auto_leveling_on = Default_leveling_on = 1;
255 n_highest_levels = 1;
256 highest_levels[0].shortname[0] = 0; //no name for mission 0
257 highest_levels[0].level_num = 1; //was highest level in old struct
258 Config_joystick_sensitivity = 8;
259 Cockpit_3d_view[0]=CV_NONE;
260 Cockpit_3d_view[1]=CV_NONE;
262 // Default taunt macros
264 strcpy(Network_message_macro[0], "Why can't we all just get along?");
265 strcpy(Network_message_macro[1], "Hey, I got a present for ya");
266 strcpy(Network_message_macro[2], "I got a hankerin' for a spankerin'");
267 strcpy(Network_message_macro[3], "This one's headed for Uranus");
268 Netlife_kills=0; Netlife_killed=0;
275 Scanline_double = 0; // no pixel doubling for poly_acc
279 Scanline_double = 1; // should be default for new player
282 Scanline_double = 1; // should be default for new player
289 extern int Guided_in_big_window,Automap_always_hires;
291 //this length must match the value in escort.c
292 #define GUIDEBOT_NAME_LEN 9
293 extern char guidebot_name[];
294 extern char real_guidebot_name[];
296 WIN(extern char win95_current_joyname[]);
298 ubyte control_type_dos,control_type_win;
300 //read in the player's saved games. returns errno (0 == no error)
301 int read_player_file()
304 char filename[FILENAME_LEN+15];
306 char filename[FILENAME_LEN];
309 int errno_ret = EZERO;
310 int id,player_file_version,i;
313 Assert(Player_num>=0 && Player_num<MAX_PLAYERS);
316 sprintf(filename,"%.8s.plr",Players[Player_num].callsign);
318 sprintf(filename, ":Players:%.8s.plr",Players[Player_num].callsign);
320 file = fopen(filename,"rb");
324 if (file && isatty(fileno(file))) {
325 //if the callsign is the name of a tty device, prepend a char
327 sprintf(filename,"$%.7s.plr",Players[Player_num].callsign);
328 file = fopen(filename,"rb");
336 id = file_read_int(file);
338 // SWAPINT added here because old versions of d2x
339 // used the wrong byte order.
340 if (id!=SAVE_FILE_ID && id!=SWAPINT(SAVE_FILE_ID)) {
341 nm_messagebox(TXT_ERROR, 1, TXT_OK, "Invalid player file");
346 player_file_version = file_read_short(file);
348 if (player_file_version<COMPATIBLE_PLAYER_FILE_VERSION) {
349 nm_messagebox(TXT_ERROR, 1, TXT_OK, TXT_ERROR_PLR_VERSION);
354 Game_window_w = file_read_short(file);
355 Game_window_h = file_read_short(file);
357 Player_default_difficulty = file_read_byte(file);
358 Default_leveling_on = file_read_byte(file);
359 Reticle_on = file_read_byte(file);
360 Cockpit_mode = file_read_byte(file);
362 #ifdef PA_3DFX_VOODOO
372 Default_display_mode = file_read_byte(file);
373 Missile_view_enabled = file_read_byte(file);
374 Headlight_active_default = file_read_byte(file);
375 Guided_in_big_window = file_read_byte(file);
377 if (player_file_version >= 19)
378 Automap_always_hires = file_read_byte(file);
380 Auto_leveling_on = Default_leveling_on;
382 //read new highest level info
384 n_highest_levels = file_read_short(file);
385 if (fread(highest_levels,sizeof(hli),n_highest_levels,file) != n_highest_levels) {
396 len = MAX_MESSAGE_LEN;
398 for (i = 0; i < 4; i++)
399 if (fread(Network_message_macro[i], len, 1, file) != 1)
400 {errno_ret = errno; break;}
402 char dummy[4][MAX_MESSAGE_LEN];
403 fread(dummy, MAX_MESSAGE_LEN, 4, file);
410 int n_control_types = (player_file_version<20)?7:CONTROL_MAX_TYPES;
412 if (fread( kconfig_settings, MAX_CONTROLS*n_control_types, 1, file )!=1)
414 else if (fread((ubyte *)&control_type_dos, sizeof(ubyte), 1, file )!=1)
416 else if (player_file_version >= 21 && fread((ubyte *)&control_type_win, sizeof(ubyte), 1, file )!=1)
418 else if (fread(&Config_joystick_sensitivity, sizeof(ubyte), 1, file )!=1)
422 Config_control_type = control_type_win;
424 Config_control_type = control_type_dos;
428 joydefs_set_type(Config_control_type);
433 PrimaryOrder[i]=file_read_byte (file);
434 SecondaryOrder[i]=file_read_byte(file);
437 if (player_file_version>=16)
439 Cockpit_3d_view[0]=file_read_int(file);
440 Cockpit_3d_view[1]=file_read_int(file);
444 if (errno_ret==EZERO) {
450 if (player_file_version>=22)
453 Netlife_kills=file_read_int (file);
454 Netlife_killed=file_read_int (file);
456 file_read_int(file); file_read_int(file);
462 Netlife_kills=0; Netlife_killed=0;
466 if (player_file_version>=23)
468 i=file_read_int (file);
470 mprintf ((0,"Reading: lifetime checksum is %d\n",i));
471 if (i!=get_lifetime_checksum (Netlife_kills,Netlife_killed))
473 Netlife_kills=0; Netlife_killed=0;
474 nm_messagebox(NULL, 1, "Shame on me", "Trying to cheat eh?");
481 if (player_file_version >= 18)
482 file_read_string(guidebot_name,file);
484 strcpy(guidebot_name,"GUIDE-BOT");
486 strcpy(real_guidebot_name,guidebot_name);
492 joy95_get_name(JOYSTICKID1, buf, 127);
493 if (player_file_version >= 24)
494 file_read_string(win95_current_joyname, file);
496 strcpy(win95_current_joyname, "Old Player File");
498 mprintf((0, "Detected joystick: %s\n", buf));
499 mprintf((0, "Player's joystick: %s\n", win95_current_joyname));
501 if (strcmp(win95_current_joyname, buf)) {
502 for (i = 0; i < MAX_CONTROLS; i++)
503 kconfig_settings[CONTROL_WINJOYSTICK][i] =
504 default_kconfig_settings[CONTROL_WINJOYSTICK][i];
507 if (player_file_version >= 24)
508 file_read_string(buf, file); // Just read it in fpr DPS.
512 if (fclose(file) && errno_ret==EZERO)
523 //finds entry for this level in table. if not found, returns ptr to
524 //empty entry. If no empty entries, takes over last one
529 for (i=0;i<n_highest_levels;i++)
530 if (!stricmp(highest_levels[i].shortname,Mission_list[Current_mission_num].filename))
533 if (i==n_highest_levels) { //not found. create entry
536 i--; //take last entry
540 strcpy(highest_levels[i].shortname,Mission_list[Current_mission_num].filename);
541 highest_levels[i].level_num = 0;
547 //set a new highest level for player for this mission
548 void set_highest_level(int levelnum)
552 if ((ret=read_player_file()) != EZERO)
553 if (ret != ENOENT) //if file doesn't exist, that's ok
556 i = find_hli_entry();
558 if (levelnum > highest_levels[i].level_num)
559 highest_levels[i].level_num = levelnum;
564 //gets the player's highest level from the file for this mission
565 int get_highest_level(void)
568 int highest_saturn_level = 0;
571 if (strlen(Mission_list[Current_mission_num].filename)==0 ) {
572 for (i=0;i<n_highest_levels;i++)
573 if (!stricmp(highest_levels[i].shortname, "DESTSAT")) // Destination Saturn.
574 highest_saturn_level = highest_levels[i].level_num;
577 i = highest_levels[find_hli_entry()].level_num;
578 if ( highest_saturn_level > i )
579 i = highest_saturn_level;
583 extern int Cockpit_mode_save;
585 //write out player's saved games. returns errno (0 == no error)
586 int write_player_file()
589 char filename[FILENAME_LEN+15];
591 char filename[FILENAME_LEN]; // because of ":Players:" path
596 // #ifdef APPLE_DEMO // no saving of player files in Apple OEM version
600 errno_ret = WriteConfigFile();
603 sprintf(filename,"%s.plr",Players[Player_num].callsign);
605 sprintf(filename, ":Players:%.8s.plr",Players[Player_num].callsign);
607 file = fopen(filename,"wb");
611 if (file && isatty(fileno(file))) {
613 //if the callsign is the name of a tty device, prepend a char
616 sprintf(filename,"$%.7s.plr",Players[Player_num].callsign);
617 file = fopen(filename,"wb");
626 //Write out player's info
627 file_write_int(SAVE_FILE_ID,file);
628 file_write_short(PLAYER_FILE_VERSION,file);
630 file_write_short(Game_window_w,file);
631 file_write_short(Game_window_h,file);
633 file_write_byte(Player_default_difficulty,file);
634 file_write_byte(Auto_leveling_on,file);
635 file_write_byte(Reticle_on,file);
636 file_write_byte((Cockpit_mode_save!=-1)?Cockpit_mode_save:Cockpit_mode,file); //if have saved mode, write it instead of letterbox/rear view
637 file_write_byte(Default_display_mode,file);
638 file_write_byte(Missile_view_enabled,file);
639 file_write_byte(Headlight_active_default,file);
640 file_write_byte(Guided_in_big_window,file);
641 file_write_byte(Automap_always_hires,file);
643 //write higest level info
644 file_write_short(n_highest_levels,file);
645 if ((fwrite(highest_levels, sizeof(hli), n_highest_levels, file) != n_highest_levels)) {
652 if ((fwrite(Network_message_macro, MAX_MESSAGE_LEN, 4, file) != 4)) {
658 fseek( file, MAX_MESSAGE_LEN * 4, SEEK_CUR );
665 control_type_win = Config_control_type;
667 control_type_dos = Config_control_type;
670 if (fwrite( kconfig_settings, MAX_CONTROLS*CONTROL_MAX_TYPES, 1, file )!=1)
672 else if (fwrite( &control_type_dos, sizeof(ubyte), 1, file )!=1)
674 else if (fwrite( &control_type_win, sizeof(ubyte), 1, file )!=1)
676 else if (fwrite( &Config_joystick_sensitivity, sizeof(ubyte), 1, file )!=1)
681 fwrite (&PrimaryOrder[i],sizeof(ubyte),1,file);
682 fwrite (&SecondaryOrder[i],sizeof(ubyte),1,file);
684 file_write_int (Cockpit_3d_view[0],file);
685 file_write_int (Cockpit_3d_view[1],file);
688 file_write_int (Netlife_kills,file);
689 file_write_int (Netlife_killed,file);
690 i=get_lifetime_checksum (Netlife_kills,Netlife_killed);
691 mprintf ((0,"Writing: Lifetime checksum is %d\n",i));
693 file_write_int(0, file);
694 file_write_int(0, file);
695 i = get_lifetime_checksum (0, 0);
697 file_write_int (i,file);
700 //write guidebot name
701 file_write_string(real_guidebot_name,file);
706 joy95_get_name(JOYSTICKID1, buf, 127);
708 strcpy(buf, "DOS joystick");
710 file_write_string(buf, file); // Write out current joystick for player.
716 if (errno_ret != EZERO) {
717 remove(filename); //delete bogus file
718 nm_messagebox(TXT_ERROR, 1, TXT_OK, "%s\n\n%s",TXT_ERROR_WRITING_PLR, strerror(errno_ret));
721 #ifdef MACINTOSH // set filetype and creator for playerfile
727 strcpy(pfilename, filename);
729 err = HGetFInfo(0, 0, pfilename, &finfo);
730 finfo.fdType = 'PLYR';
731 finfo.fdCreator = 'DCT2';
732 err = HSetFInfo(0, 0, pfilename, &finfo);
740 //update the player's highest level. returns errno (0 == no error)
741 int update_player_file()
745 if ((ret=read_player_file()) != EZERO)
746 if (ret != ENOENT) //if file doesn't exist, that's ok
749 return write_player_file();
752 int get_lifetime_checksum (int a,int b)
756 // confusing enough to beat amateur disassemblers? Lets hope so