/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Functions to load & save player games * */ #include #include #include #include #include "error.h" #include "gameseq.h" #include "player.h" #include "playsave.h" #include "joy.h" #include "digi.h" #include "newmenu.h" #include "palette.h" #include "menu.h" #include "config.h" #include "text.h" #include "state.h" #include "u_mem.h" #include "strutil.h" #include "strio.h" #include "vers_id.h" #include "byteswap.h" #include "physfsx.h" #include "newdemo.h" #include "gauges.h" //version 5 -> 6: added new highest level information //version 6 -> 7: stripped out the old saved_game array. //version 7 -> 8: readded the old saved_game array since this is needed // for shareware saved games //the shareware is level 4 #define SAVE_FILE_ID 0x44504c52 /* 'DPLR' */ #define SAVED_GAME_VERSION 8 //increment this every time saved_game struct changes #define COMPATIBLE_SAVED_GAME_VERSION 4 #define COMPATIBLE_PLAYER_STRUCT_VERSION 16 struct player_config PlayerCfg; saved_game_sw saved_games[N_SAVE_SLOTS]; extern void InitWeaponOrdering(); int new_player_config() { int i=0; for (i=0;i='a'){ neg=1;I=p[0]-'a'; }else{ neg=0;I=p[0]-'A'; } i=0;*v=0; p++; while (p[i*2] && p[i*2+1] && p[i*2]!=' '){ c=(p[i*2]-33)+((p[i*2+1]-33)<<4); c^=effcode[i+neg]; *v+=c << (i*8); i++; } if (neg) *v *= -1; if (!p[i*2])return NULL; return p+(i*2); } void plyr_read_stats_v(int *k, int *d){ char filename[14]; int k1=-1,k2=0,d1=-1,d2=0; PHYSFS_file *f; *k=0;*d=0;//in case the file doesn't exist. sprintf(filename,GameArg.SysUsePlayersDir?"Players/%s.eff":"%s.eff",Players[Player_num].callsign); f = PHYSFSX_openReadBuffered(filename); if(f) { char line[256],*word; if(!PHYSFS_eof(f)) { cfgets(line,50,f); word=splitword(line,':'); if(!strcmp(word,"kills")) *k=atoi(line); d_free(word); } if(!PHYSFS_eof(f)) { cfgets(line,50,f); word=splitword(line,':'); if(!strcmp(word,"deaths")) *d=atoi(line); d_free(word); } if(!PHYSFS_eof(f)) { cfgets(line,50,f); word=splitword(line,':'); if(!strcmp(word,"key") && strlen(line)>10){ unsigned char *p; if (line[0]=='0' && line[1]=='1'){ if ((p=decode_stat((unsigned char*)line+3,&k1,effcode1))&& (p=decode_stat(p+1,&k2,effcode2))&& (p=decode_stat(p+1,&d1,effcode3))){ decode_stat(p+1,&d2,effcode4); } } } d_free(word); } if (k1!=k2 || k1!=*k || d1!=d2 || d1!=*d) { *k=0;*d=0; } } if(f) PHYSFS_close(f); } void plyr_read_stats() { plyr_read_stats_v(&PlayerCfg.NetlifeKills,&PlayerCfg.NetlifeKilled); } void plyr_save_stats() { int kills = PlayerCfg.NetlifeKills,deaths = PlayerCfg.NetlifeKilled, neg, i; char filename[PATH_MAX]; unsigned char buf[16],buf2[16],a; PHYSFS_file *f; memset(filename, '\0', PATH_MAX); snprintf(filename, PATH_MAX, GameArg.SysUsePlayersDir?"Players/%s.eff":"%s.eff", Players[Player_num].callsign); f = PHYSFSX_openWriteBuffered(filename); if(!f) return; //broken! PHYSFSX_printf(f,"kills:%i\n",kills); PHYSFSX_printf(f,"deaths:%i\n",deaths); PHYSFSX_printf(f,"key:01 "); if (kills<0) { neg=1; kills*=-1; } else neg=0; for (i=0;kills;i++) { a=(kills & 0xFF) ^ effcode1[i+neg]; buf[i*2]=(a&0xF)+33; buf[i*2+1]=(a>>4)+33; a=(kills & 0xFF) ^ effcode2[i+neg]; buf2[i*2]=(a&0xF)+33; buf2[i*2+1]=(a>>4)+33; kills>>=8; } buf[i*2]=0; buf2[i*2]=0; if (neg) i+='a'; else i+='A'; PHYSFSX_printf(f,"%c%s %c%s ",i,buf,i,buf2); if (deaths<0) { neg=1; deaths*=-1; }else neg=0; for (i=0;deaths;i++) { a=(deaths & 0xFF) ^ effcode3[i+neg]; buf[i*2]=(a&0xF)+33; buf[i*2+1]=(a>>4)+33; a=(deaths & 0xFF) ^ effcode4[i+neg]; buf2[i*2]=(a&0xF)+33; buf2[i*2+1]=(a>>4)+33; deaths>>=8; } buf[i*2]=0; buf2[i*2]=0; if (neg) i+='a'; else i+='A'; PHYSFSX_printf(f,"%c%s %c%s\n",i,buf,i,buf2); PHYSFS_close(f); } int write_player_d1x(char *filename) { PHYSFS_file *fout; int rc=0; char tempfile[PATH_MAX]; strcpy(tempfile,filename); tempfile[strlen(tempfile)-4]=0; strcat(tempfile,".pl$"); fout=PHYSFSX_openWriteBuffered(tempfile); if (!fout && GameArg.SysUsePlayersDir) { PHYSFS_mkdir("Players/"); //try making directory fout=PHYSFSX_openWriteBuffered(tempfile); } if(fout) { PHYSFSX_printf(fout,"[D1X Options]\n"); PHYSFSX_printf(fout,"[weapon reorder]\n"); PHYSFSX_printf(fout,"primary=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",PlayerCfg.PrimaryOrder[0], PlayerCfg.PrimaryOrder[1], PlayerCfg.PrimaryOrder[2],PlayerCfg.PrimaryOrder[3], PlayerCfg.PrimaryOrder[4], PlayerCfg.PrimaryOrder[5]); PHYSFSX_printf(fout,"secondary=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",PlayerCfg.SecondaryOrder[0], PlayerCfg.SecondaryOrder[1], PlayerCfg.SecondaryOrder[2],PlayerCfg.SecondaryOrder[3], PlayerCfg.SecondaryOrder[4], PlayerCfg.SecondaryOrder[5]); PHYSFSX_printf(fout,"[end]\n"); PHYSFSX_printf(fout,"[joystick]\n"); PHYSFSX_printf(fout,"sensitivity0=%d\n",PlayerCfg.JoystickSens[0]); PHYSFSX_printf(fout,"sensitivity1=%d\n",PlayerCfg.JoystickSens[1]); PHYSFSX_printf(fout,"sensitivity2=%d\n",PlayerCfg.JoystickSens[2]); PHYSFSX_printf(fout,"sensitivity3=%d\n",PlayerCfg.JoystickSens[3]); PHYSFSX_printf(fout,"sensitivity4=%d\n",PlayerCfg.JoystickSens[4]); PHYSFSX_printf(fout,"deadzone0=%d\n",PlayerCfg.JoystickDead[0]); PHYSFSX_printf(fout,"deadzone1=%d\n",PlayerCfg.JoystickDead[1]); PHYSFSX_printf(fout,"deadzone2=%d\n",PlayerCfg.JoystickDead[2]); PHYSFSX_printf(fout,"deadzone3=%d\n",PlayerCfg.JoystickDead[3]); PHYSFSX_printf(fout,"deadzone4=%d\n",PlayerCfg.JoystickDead[4]); PHYSFSX_printf(fout,"[end]\n"); PHYSFSX_printf(fout,"[mouse]\n"); PHYSFSX_printf(fout,"flightsim=%d\n",PlayerCfg.MouseFlightSim); PHYSFSX_printf(fout,"sensitivity0=%d\n",PlayerCfg.MouseSens[0]); PHYSFSX_printf(fout,"sensitivity1=%d\n",PlayerCfg.MouseSens[1]); PHYSFSX_printf(fout,"sensitivity2=%d\n",PlayerCfg.MouseSens[2]); PHYSFSX_printf(fout,"sensitivity3=%d\n",PlayerCfg.MouseSens[3]); PHYSFSX_printf(fout,"sensitivity4=%d\n",PlayerCfg.MouseSens[4]); PHYSFSX_printf(fout,"fsdead=%d\n",PlayerCfg.MouseFSDead); PHYSFSX_printf(fout,"fsindi=%d\n",PlayerCfg.MouseFSIndicator); PHYSFSX_printf(fout,"filter=%d\n",PlayerCfg.MouseFilter); PHYSFSX_printf(fout,"[end]\n"); PHYSFSX_printf(fout,"[weapon keys v2]\n"); PHYSFSX_printf(fout,"1=0x%x,0x%x,0x%x\n",PlayerCfg.KeySettingsD1X[0],PlayerCfg.KeySettingsD1X[1],PlayerCfg.KeySettingsD1X[2]); PHYSFSX_printf(fout,"2=0x%x,0x%x,0x%x\n",PlayerCfg.KeySettingsD1X[3],PlayerCfg.KeySettingsD1X[4],PlayerCfg.KeySettingsD1X[5]); PHYSFSX_printf(fout,"3=0x%x,0x%x,0x%x\n",PlayerCfg.KeySettingsD1X[6],PlayerCfg.KeySettingsD1X[7],PlayerCfg.KeySettingsD1X[8]); PHYSFSX_printf(fout,"4=0x%x,0x%x,0x%x\n",PlayerCfg.KeySettingsD1X[9],PlayerCfg.KeySettingsD1X[10],PlayerCfg.KeySettingsD1X[11]); PHYSFSX_printf(fout,"5=0x%x,0x%x,0x%x\n",PlayerCfg.KeySettingsD1X[12],PlayerCfg.KeySettingsD1X[13],PlayerCfg.KeySettingsD1X[14]); PHYSFSX_printf(fout,"6=0x%x,0x%x,0x%x\n",PlayerCfg.KeySettingsD1X[15],PlayerCfg.KeySettingsD1X[16],PlayerCfg.KeySettingsD1X[17]); PHYSFSX_printf(fout,"7=0x%x,0x%x,0x%x\n",PlayerCfg.KeySettingsD1X[18],PlayerCfg.KeySettingsD1X[19],PlayerCfg.KeySettingsD1X[20]); PHYSFSX_printf(fout,"8=0x%x,0x%x,0x%x\n",PlayerCfg.KeySettingsD1X[21],PlayerCfg.KeySettingsD1X[22],PlayerCfg.KeySettingsD1X[23]); PHYSFSX_printf(fout,"9=0x%x,0x%x,0x%x\n",PlayerCfg.KeySettingsD1X[24],PlayerCfg.KeySettingsD1X[25],PlayerCfg.KeySettingsD1X[26]); PHYSFSX_printf(fout,"0=0x%x,0x%x,0x%x\n",PlayerCfg.KeySettingsD1X[27],PlayerCfg.KeySettingsD1X[28],PlayerCfg.KeySettingsD1X[29]); PHYSFSX_printf(fout,"[end]\n"); PHYSFSX_printf(fout,"[cockpit]\n"); PHYSFSX_printf(fout,"mode=%i\n",PlayerCfg.CockpitMode[0]); PHYSFSX_printf(fout,"hud=%i\n",PlayerCfg.HudMode); PHYSFSX_printf(fout,"rettype=%i\n",PlayerCfg.ReticleType); PHYSFSX_printf(fout,"retrgba=%i,%i,%i,%i\n",PlayerCfg.ReticleRGBA[0],PlayerCfg.ReticleRGBA[1],PlayerCfg.ReticleRGBA[2],PlayerCfg.ReticleRGBA[3]); PHYSFSX_printf(fout,"retsize=%i\n",PlayerCfg.ReticleSize); PHYSFSX_printf(fout,"[end]\n"); PHYSFSX_printf(fout,"[toggles]\n"); PHYSFSX_printf(fout,"persistentdebris=%i\n",PlayerCfg.PersistentDebris); PHYSFSX_printf(fout,"prshot=%i\n",PlayerCfg.PRShot); PHYSFSX_printf(fout,"noredundancy=%i\n",PlayerCfg.NoRedundancy); PHYSFSX_printf(fout,"multimessages=%i\n",PlayerCfg.MultiMessages); PHYSFSX_printf(fout,"bombgauge=%i\n",PlayerCfg.BombGauge); PHYSFSX_printf(fout,"[end]\n"); PHYSFSX_printf(fout,"[opengl]\n"); PHYSFSX_printf(fout,"oglalphaeffects=%i\n",PlayerCfg.OglAlphaEffects); PHYSFSX_printf(fout,"[end]\n"); PHYSFSX_printf(fout,"[plx version]\n"); PHYSFSX_printf(fout,"plx version=%s\n",VERSION); PHYSFSX_printf(fout,"[end]\n"); PHYSFSX_printf(fout,"[end]\n"); PHYSFS_close(fout); if(rc==0) { PHYSFS_delete(filename); rc = PHYSFSX_rename(tempfile,filename); } return rc; } else return errno; } //read in the player's saved games. returns errno (0 == no error) int read_player_file() { char filename[32]; PHYSFS_file *file; int player_file_size, shareware_file = -1, id = 0; short saved_game_version, player_struct_version; Assert(Player_num>=0 && Player_num PlayerCfg.HighestLevels[i].LevelNum) PlayerCfg.HighestLevels[i].LevelNum = levelnum; write_player_file(); } //gets the player's highest level from the file for this mission int get_highest_level(void) { int i; int highest_saturn_level = 0; read_player_file(); #ifndef SHAREWARE #ifndef SATURN if (strlen(Current_mission_filename)==0 ) { for (i=0;i i ) i = highest_saturn_level; return i; } //write out player's saved games. returns errno (0 == no error) int write_player_file() { char filename[32]; PHYSFS_file *file; int errno_ret, i; if ( Newdemo_state == ND_STATE_PLAYBACK ) return -1; errno_ret = WriteConfigFile(); sprintf(filename, GameArg.SysUsePlayersDir? "Players/%.8s.plx" : "%.8s.plx", Players[Player_num].callsign); write_player_d1x(filename); sprintf(filename, GameArg.SysUsePlayersDir? "Players/%.8s.plr" : "%.8s.plr", Players[Player_num].callsign); file = PHYSFSX_openWriteBuffered(filename); if (!file) return errno; PHYSFS_writeULE32(file, SAVE_FILE_ID); PHYSFS_writeULE16(file, SAVED_GAME_VERSION); PHYSFS_writeULE16(file, PLAYER_STRUCT_VERSION); PHYSFS_writeSLE32(file, PlayerCfg.NHighestLevels); PHYSFS_writeSLE32(file, PlayerCfg.DefaultDifficulty); PHYSFS_writeSLE32(file, PlayerCfg.AutoLeveling); errno_ret = EZERO; //write higest level info if ((PHYSFS_write( file, PlayerCfg.HighestLevels, sizeof(hli), PlayerCfg.NHighestLevels) != PlayerCfg.NHighestLevels)) { errno_ret = errno; PHYSFS_close(file); return errno_ret; } if (PHYSFS_write( file, saved_games,sizeof(saved_games),1) != 1) { errno_ret = errno; PHYSFS_close(file); return errno_ret; } #ifdef NETWORK if ((PHYSFS_write( file, PlayerCfg.NetworkMessageMacro, MAX_MESSAGE_LEN, 4) != 4)) { errno_ret = errno; PHYSFS_close(file); return errno_ret; } #else { //PHYSFS_seek( file, PHYSFS_tell(file)+MAX_MESSAGE_LEN * 4 ); // Seeking is bad for Mac OS 9 char dummy[MAX_MESSAGE_LEN][4]; if ((PHYSFS_write( file, dummy, MAX_MESSAGE_LEN, 4) != 4)) { errno_ret = errno; PHYSFS_close(file); return errno_ret; } } #endif //write kconfig info { if (PHYSFS_write(file, PlayerCfg.KeySettings[0], sizeof(PlayerCfg.KeySettings[0]), 1) != 1) errno_ret=errno; if (PHYSFS_write(file, PlayerCfg.KeySettings[1], sizeof(PlayerCfg.KeySettings[1]), 1) != 1) errno_ret=errno; for (i = 0; i < MAX_CONTROLS*3; i++) if (PHYSFS_write(file, "0", sizeof(ubyte), 1) != 1) // Skip obsolete Flightstick/Thrustmaster/Gravis map fields errno_ret=errno; if (PHYSFS_write(file, PlayerCfg.KeySettings[2], sizeof(PlayerCfg.KeySettings[2]), 1) != 1) errno_ret=errno; for (i = 0; i < MAX_CONTROLS; i++) if (PHYSFS_write(file, "0", sizeof(ubyte), 1) != 1) // Skip obsolete Cyberman map field errno_ret=errno; if(errno_ret == EZERO) { ubyte old_avg_joy_sensitivity = 8; if (PHYSFS_write( file, &PlayerCfg.ControlType, sizeof(ubyte), 1 )!=1) errno_ret=errno; else if (PHYSFS_write( file, &old_avg_joy_sensitivity, sizeof(ubyte), 1 )!=1) errno_ret=errno; } } if (!PHYSFS_close(file)) errno_ret = errno; if (errno_ret != EZERO) { PHYSFS_delete(filename); //delete bogus file nm_messagebox(TXT_ERROR, 1, TXT_OK, "%s\n\n%s",TXT_ERROR_WRITING_PLR, strerror(errno_ret)); } return errno_ret; }