Saveconvert - change various settings in save file

the other option is that we write something in python and use the civ engine to change game options. That would work with some things but probably not all things. Would this also give us the ability to extra pbem passwords?
 
Since its in C could you release the source to us?
I would love to see it.

I would transfer it to C# and do some comenting and reworking if I ever get it.
 
for BtS you cant change the values in the savegame like this..
you would need to make something in game (in python or similar).. but such a mod would also prevent it being able to load standard savegames with locked assets (like multiplayer games)... so in BtS you would need to write your own savegame loading code from inside the mod... (or alternatively you could crack the BtS savegame protection mechanism)

here is the source code: (it contains some unused code and variables I think.. didnt study it too much :p )

Code:
/* Written by Peter Pettersen aka Gyathaar */

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include "md5.h"



void input_maxplayers();

enum GameOptions {
	GO_NO_CITY_RAZING,
	GO_NO_CITY_FLIPPING_FROM_CULTURE,
	GO_CITY_FLIPPING_AFTER_CONQUEST,
	GO_NO_BARBARIANS,
	GO_RAGING_BARBARIANS,
	GO_AGGRESSIVE_AI,
	GO_RANDOM_PERSONALITIES,
	GO_NO_TECHNOLOGY_TRADING,
	GO_PERMANENT_ALLIANCES,
	GO_ALWAYS_WAR,
	GO_ALWAYS_PEACE,
	GO_ONE_CITY_CHALLENGE,
	GO_PERMANENT_WAR_OR_PEACE,
	GO_DONT_PRESERVE_RANDOM_SEED,
	GO_NO_CHEATING,
	GO_REQUIRE_COMPLETE_KILLS,
	GO_NO_VASSAL_STATES,
	GO_NO_TRIBAL_VILLAGES,
	GO_COUNT
} ;

int options_meny[GO_COUNT-3] = {\
	GO_NO_CITY_RAZING,\
	GO_NO_CITY_FLIPPING_FROM_CULTURE,\
	GO_CITY_FLIPPING_AFTER_CONQUEST,\
	GO_NO_BARBARIANS,\
	GO_RAGING_BARBARIANS,\
	GO_AGGRESSIVE_AI,\
	GO_NO_TECHNOLOGY_TRADING,\
	GO_PERMANENT_ALLIANCES,\
	GO_ALWAYS_WAR,\
	GO_ALWAYS_PEACE,\
	GO_ONE_CITY_CHALLENGE,\
	GO_PERMANENT_WAR_OR_PEACE,\
	GO_DONT_PRESERVE_RANDOM_SEED,\
	GO_REQUIRE_COMPLETE_KILLS,\
	GO_NO_VASSAL_STATES\
};

char *options_meny_text[GO_COUNT-3] = {\
	"No City Razing",\
	"No City Flipping from Culture",\
	"City Flipping after Conquest",\
	"No Barbarians",\
	"Raging Barbarians",\
	"Aggressive AI",\
	"No Technology Trading",\
	"Permanent Alliances",\
	"Always War",\
	"Always Peace",\
	"One City Challenge",\
	"Permanent War or Peace",\
	"Don\'t Preserve Random Seed",\
	"Require Complete Kills",\
	"No Vassal States"\
};

char *resources[35] = { "aluminium","coal","copper","horse","iron","marble","oil","stone","uranium","banana",\
"clam","corn","cow","crab","deer","fish","pig","rice","sheep","wheat",\
"dye","fur","gems","gold","incense","ivory","silk","silver","spices","sugar",\
"wine","whale","drama","music","movies"};

char *gametypes[16] = {\
    "Singleplayer",\
    "Singleplayer",\
    "Singleplayer",\
    "Multiplayer",\
    "Multiplayer",\
    "Multiplayer",\
    "Hotseat",\
    "Multiplayer",\
    "Play by E-mail",\
    "Play by E-mail ?"\
};

char *timers[6] = {\
    "Static",\
    "Snail",\
    "Slow",\
    "Medium",\
    "Fast",\
    "Blazing!!!"\
};

char *diff_str[9] = {\
	"Settler",\
	"Chieftain",\
	"Warlord",\
	"Noble",\
	"Prince",\
	"Monarch",\
	"Emperor",\
	"Immortal",\
	"Deity"\
};


char* victoryoption_str[7] = {\
	"Score",\
	"Time",\
	"Conquest",\
	"Domination",\
	"Cultural",\
	"Space Race",\
	"Diplomatic"\
};

char *civs[20] = {"America","Arabia","Aztec","China","Egypt","England","France","Germany","Greece","Inca",\
"India","Japan","Mali","Mongol","Persia","Rome","Russia","Spain","Minor civilization","Barbarian civilization"};

char *wcivs[26] = {"America","Arabia","Aztec","Carthage","Celt","China","Egypt","England","France","Germany","Greece","Inca",\
"India","Japan","Korea","Mali","Mongol","Ottoman","Persia","Rome","Russia","Spain","Viking","Zulu","Minor civilization","Barbarian civilization"};

char **civdesc;
char **leadername;
char **civadj;
char **civpasswd;
char **civemail;

int *civid;

int *convert;
int convert_to = 0;

char outfile[256] = "";


unsigned char *conditions;
int *diffs;
int score_vic;

int human_player = -1;
int humans = 0;
int ver;
int lastturn = -1;
int gamespeed;
int time_played;
int start_turn;
int start_year;
int turn_limit;
int gametype;

int max_players = 18;

unsigned char simul,takeover,timer,anonplayers;

int turnt;
int pbturnt;

md5_state_t state;

unsigned CHUNK;

FILE *fp,*outs,*outf;
unsigned long uncompressed_length;
char *uncompr;

char *full_file;
int fsize;
char *fptr;

char *header;
int hsize;
char *hptr;

char *data;
int dsize;
char *dptr;


char *modified_save;
int modified_length;
char *mptr;


char *victory_conditions;
char *score_victory;
char *difficulties;
char *converts;
char *turntimer;
char *pbturntimer;
char *multi;
char *gametype_ptr;
char *options_ptr;

unsigned have;
int err;
// z_stream d_stream; /* decompression stream */


int current_turn;

char out[4096];


unsigned char read_byte(int d){
	unsigned char ret;
	if(!d){
		ret = fgetc(fp);
		*mptr++ = ret;
	}
	else {
		while(d--){
			ret = *dptr++;
		}
	}
	return ret;
}


short read_short(int d){
    short l;
            ;
    l = (((short) (read_byte(d))));
    l |= (((short) (read_byte(d)))) << 8;
    return l;
}


long read_long(int d){
    long l;

    l = (((long) (read_byte(d))));
    l |= (((long) (read_byte(d)))) << 8;
    l |= (((long) (read_byte(d)))) << 16;
    l |= (((long) (read_byte(d)))) << 24;
    return l;
}

int read_asciistring(int d){
    long i;
    long length = read_long(d);

	out[0] = '\0';


    if(length > 0) {
        for(i=0; i<length;i++){
            out[i] = (char)read_byte(d);
        }
        out[i] = '\0';
    }
    return length;
}

int read_ustring(int d){
        long i;
        long length = read_long(d);

	out[0] = '\0';

    if(length > 0) {
        for(i=0; i<length;i++){
            out[i] = read_byte(d);
            read_byte(d);
        }
        out[i] = '\0';
    }
    return length;
}



int init(char *filename){

    long start, stop, i;
    int ret,flen;

    if (NULL == (fp = fopen(filename, "rb"))) {
            fprintf (stderr, "Failed to open file \"%s\" ...\n",filename);
            fsize = 0;

            flen = strlen(filename);
            strcpy(&filename[flen],".Civ4SavedGame");

            fprintf (stderr, "... Trying \"%s\" as filename...\n",filename);
            if (NULL == (fp = fopen(filename, "rb"))) {
                strcpy(&filename[flen],".CivWarlordsSave");

                fprintf (stderr, "... Trying \"%s\" as filename...\n",filename);
                if (NULL == (fp = fopen(filename, "rb"))) {
                    return -1;
                }
            }
            fprintf (stderr, "... Success ...\n\n");
    }

	fseek (fp, 0L, 2);
	modified_length = ftell (fp);
	fseek (fp, 0L, 0);

//	printf("%d\n",modified_length);

	modified_save = malloc(modified_length);
	mptr = modified_save;

    return 0;
}


int parse_header(){

    int i,j;

    int mod,ret;
	int options;

	long stop;
	int len;
	char modpath[256];
	char adminpasswd[33];

    int haspassword = 0;

    char buffer[40],passwd[256];
    char* pos=buffer;
    md5_byte_t digest[16];


    ver = read_long(0);
    mod = read_asciistring(0);
    if(mod)
        strncpy(modpath,out,mod+1);

//	if(out != NULL) printf("%s\n",out);

    i = read_asciistring(0);
    read_long(0);

	if(ver > 100){
        i = read_asciistring(0);
//        if(i > 0) printf("verstring: %s\n",out);
		i=read_asciistring(0);
//        if(i > 0) printf("dllcrc: %s\n",out);
		i=read_asciistring(0);
//        if(i > 0) printf("shadercrc: %s\n",out);
		i=read_asciistring(0);
//        if(i > 0) printf("pythoncrc: %s\n",out);
		i=read_asciistring(0);
//        if(i > 0) printf("xmlcrc: %s\n",out);
	}
    read_long(0);


    gametype_ptr = mptr;
    gametype = read_long(0);

    read_ustring(0);
//	if(out != NULL) printf("%s\n",out);

    read_ustring(0); // clear text game password

    i = read_ustring(0); // admin password

	if(i>0){
	    if(strncmp(out,"d41d8cd98f00b204e9800998ecf8427e",32)){
            haspassword = 1;
            strncpy(adminpasswd,out,32);
            adminpasswd[32] = '\0';
	    }
	}

    read_ustring(0);
    read_byte(0);

    read_long(0);
    read_long(0);
    read_long(0);
    read_long(0);
    gamespeed = read_long(0);
    turntimer = mptr;
    turnt = read_long(0);
    read_long(0);


    i = read_long(0); //map options
    for(j=0;j<i;j++){
        read_long(0);
    }

    if(ver>=200)
        read_long(0);

    i = read_long(0);

    conditions = malloc(i * sizeof(char));

	victory_conditions = mptr;
    for(j=0;j<i;j++){
            conditions[j] = read_byte(0);
    }

	options = (ver < 102 ? 13 : (ver < 103 ? 15 : 16));

    if(ver >= 200){
        options = 18;
    }

    if((ver == 103) && mod && !strncmp(modpath,"Mods\\Fall from Heaven 100\\",26)){
        options = 17;
    }

    options_ptr = mptr;
    for(j=0;j<options;j++){
        i = read_byte(0);
        if((j == GO_NO_CHEATING) && (i == 1)){
            printf("Sorry, this program will not convert a save with the locked assets flag set.\n");
            return -1;
        }
    }

    if(haspassword){

        printf("This save is protected by an admin password...\n");

//            printf("md5: %s\n",out);

        md5_init(&state);

        printf("Input admin password: ");
        fgets(passwd,256,stdin);
        passwd[strlen(passwd)-1] = '\0';

        md5_append(&state, (const md5_byte_t*)passwd, (int)strlen(passwd));

        md5_finish ( &state, digest );
        for (i = 0; i < 16; i++) {
            sprintf(pos,"%02x", digest[i]);
            pos += 2;
        }

//            printf("md5calc: %s\n",buffer);

        if(strncmp(adminpasswd,buffer,32)){
            printf("Incorrect admin password.. exiting program.\n");
            return -1;
        }

    }

    input_maxplayers();

    civdesc = malloc((max_players+1) * sizeof(char *));
    leadername = malloc((max_players+1) * sizeof(char *));
    civadj = malloc((max_players+1) * sizeof(char *));
    civpasswd = malloc((max_players+1) * sizeof(char *));
    civemail = malloc((max_players+1) * sizeof(char *));

    civid = malloc((max_players+1) * sizeof(char *));
    convert = malloc((max_players+1) * sizeof(char *));
    diffs = malloc((max_players+1) * sizeof(char *));

    for(i=0;i<(max_players+1);i++){
        civdesc[i] = NULL;
        leadername[i] = NULL;
        civadj[i] = NULL;
        civpasswd[i] = NULL;
        civemail[i] = NULL;

        civid[i] = -1;
        convert[i] = 0;
        diffs[i] = 0;
    }

    multi = mptr;

    simul = read_byte(0);
    takeover = read_byte(0);

    if(ver >= 200){
        read_byte(0); //shuffleteams
        anonplayers = read_byte(0);
    }
    timer = read_byte(0);

    read_byte(0);

	current_turn = read_long(0);

    read_long(0);

    pbturntimer = mptr;
    pbturnt = read_long(0);

	score_victory = mptr;
	score_vic = read_long(0);
	read_long(0);


    for(i=0;i<(max_players+1);i++){
        len = read_ustring(0);
        if(len >0){
            leadername[i] = malloc(len+1);
            strncpy(leadername[i],out,len+1);
        }
    }
    for(i=0;i<(max_players+1);i++){
        len = read_ustring(0);
		if(len >0){
			civdesc[i] = malloc(len+1);
			strncpy(civdesc[i],out,len+1);
		}
	}
    for(i=0;i<(max_players+1);i++){
		read_ustring(0);
    }
    for(i=0;i<(max_players+1);i++){
        len = read_ustring(0);
		if(len >0){
			civadj[i] = malloc(len+1);
			strncpy(civadj[i],out,len+1);
		}
	}
    for(i=0;i<(max_players+1);i++){
        len = read_ustring(0);
		if(len >0){
			civpasswd[i] = malloc(len+1);
			strncpy(civpasswd[i],out,len+1);
		}
	}
    for(i=0;i<(max_players+1);i++){
        len = read_asciistring(0);

		if(len >0){
			civemail[i] = malloc(len+1);
			strncpy(civemail[i],out,len+1);
		}
	}
    for(i=0;i<(max_players+1);i++){
        read_asciistring(0); // smtpserver
    }
    for(i=0;i<(max_players+1);i++){
        read_byte(0);
    }

    for(i=0;i<(max_players+1);i++){
        read_ustring(0);
    }

	for(i=0;i<(max_players+1);i++){
        civid[i] = read_long(0);
	}
    for(i=0;i<(max_players+1);i++){
        read_long(0);
    }
    for(i=0;i<(max_players+1);i++){
        read_long(0);
    }

	difficulties = mptr;
    for(i=0;i<(max_players+1);i++){
        diffs[i] = read_long(0);
    }
    for(i=0;i<(max_players+1);i++){
        read_long(0);
    }
    for(i=0;i<(max_players+1);i++){
        read_long(0);
    }

    humans = 0;
    converts = mptr;
    for(i=0;i<(max_players+1);i++){
        j = read_long(0);
		if((j == 0) || (j == 3)){
            convert[i] = 1;
            humans++;
		}
        else
            convert[i] = 0;
	}


    for(i=0;i<(max_players+1);i++){
        j = read_byte(0);
    }
	if(ver != 100){
        	for(j=0;j<3;j++){
                	for(i=0;i<(max_players+1);i++){
                        	read_byte(0);
                	}
        	}
	}

        for(i=0;i<(max_players+1);i++){
                read_byte(0);
        }
        for(i=0;i<(max_players+1);i++){
                read_byte(0);
        }
        read_long(0);

	uncompressed_length = read_long(0);




	i = read_long(0);


    hsize = ftell (fp);

	fseek (fp, 0L, 2);
	stop = ftell (fp);
	fsize = stop - hsize + 1;
	fseek (fp, hsize, 0);


	full_file = mptr;

	for (i = 0 ; ret = fread (full_file+i, 1, 1, fp) ; i+= ret)
		;

	fclose(fp);

//	printf("%d\n",full_file + i - modified_save);


	return 0;


}



void convert_type(){
	char input;

	do {
		printf("Convert to: 1=hotseat, 2=pbem, 3=pitboss/network game, 0=leave untouched [0]:");
		input = fgetc(stdin);
		if(input == '\n') {
			convert_to = 0;
			break;
		}
		if(input == '1')
			convert_to = 1;
		else if(input == '2')
			convert_to = 2;
		else if(input == '3')
			convert_to = 3;
		else if(input == '0')
			convert_to = 0;
		do {
			;

		} while (fgetc(stdin) != '\n');

	} while ((convert_to != 0) && (convert_to != 1) && (convert_to != 2) && (convert_to != 3));

    if(convert_to != 0)
        *(gametype_ptr) = (convert_to == 1 ? 6 : (convert_to == 2 ? 8 : 3));
    else
        *(gametype_ptr) = gametype;
}

void out_file(){
    if(ver < 200)
        printf("Output savefile [%s.Civ4SavedGame]:",(convert_to == 1 ? "hotseat" : (convert_to == 2 ? "pbem" : "output")));
    else
        printf("Output savefile [%s.CivWarlordsSave]:",(convert_to == 1 ? "hotseat" : (convert_to == 2 ? "pbem" : "output")));

	fgets(outfile,256,stdin);
	outfile[strlen(outfile)-1] = '\0';

	if(strlen(outfile)==0){
		if(convert_to == 1){
            if(ver < 200)
                strcpy(outfile,"hotseat.Civ4SavedGame");
            else
                strcpy(outfile,"hotseat.CivWarlordsSave");
		}
		else if(convert_to == 2){
            if(ver < 200)
                strcpy(outfile,"pbem.Civ4SavedGame");
            else
                strcpy(outfile,"pbem.CivWarlordsSave");
		}
		else {
            if(ver < 200)
                strcpy(outfile,"output.Civ4SavedGame");
            else
                strcpy(outfile,"output.CivWarlordsSave");
		}
	}

	if(ver < 200 && !strstr(outfile,".Civ4SavedGame")){
        strcpy(&outfile[strlen(outfile)],".Civ4SavedGame");
	}

	if(ver >= 200 && !strstr(outfile,".CivWarlordsSave")){
        strcpy(&outfile[strlen(outfile)],".CivWarlordsSave");
	}

	//printf("%s\n",outfile);
}

void convert_players(){

	char *desc;
	int default_civ;
    int i,id;
	char input_civ[256];

no_humans:

	do {
        for(i=0; i<(max_players+1); i++){
            if(civid[i] != -1) {
                if(civdesc[i] != NULL){
                    desc = civdesc[i];
                }
                else {
				    if(ver >= 200)
                        desc = wcivs[civid[i]];
                    else
                        desc = civs[civid[i]];
                }
                if(i<max_players)
                    printf("%-2d: %s (%s)\n",i,desc,convert[i]?"human":"AI");
                else
                    printf("%-2d: Barbarian civilization\n",i);

            }
        }

        default_civ = -1;

		printf("Input civ number to toggle between human and AI player (-1 to input no more civs) [%d]:",default_civ);

		fgets(input_civ,256,stdin);

		if(input_civ[0] == '\n')
			id = default_civ;
		else
			id = atoi(input_civ);

		if((id > max_players) || (id < -1))
			printf("Civ number %d is outside the valid range.\n",id);
		else if((id != -1)  && (civid[id] == -1))
			printf("Civ number %d is not in this game.\n",id);
		else if(id != -1) {
			convert[id] = !convert[id];
			printf("Converting civ number %d to %s player\n",id,convert[id]?"human":"AI");
			if(convert[id])
                humans++;
            else
                humans--;

		}

	} while (id != -1 );

    if(humans <= 0){
        printf("\nThere has to be atleast one human player in the game!!!\n\n");
        goto no_humans;
    }

    for(i=0;i<(max_players+1);i++){
		if(convert[i])
			*(converts + 4*i) = 0;
		else if(civid[i] != -1 )
			*(converts + 4*i) = 1;

	}
}

void change_victory_conditions(){
    int i,id;
	char input[256];

	do {
		if(conditions[0] && (score_vic > 0)){
			printf("%-2d: %s victory - enabled (Required score: %d)\n",0,victoryoption_str[0],score_vic);
		}
		else {
			printf("%-2d: %s victory - disabled\n",0,victoryoption_str[0]);
		}
		for(i=1; i<7; i++){
			printf("%-2d: %s victory - %s\n",i,victoryoption_str[i],conditions[i]?"enabled":"disabled");

		}

		printf("Input victory condition to enable/disable (-1 to exit) [%d]:",-1);

		fgets(input,256,stdin);

		if(input[0] == '\n')
			id = -1;
		else
			id = atoi(input);

		if((id > 6) || (id < -1))
			printf("Input is outside validrange outside the valid range.\n",id);
		else if(id == 0){
			if(conditions[0] && (score_vic > 0)){
				conditions[0] = 0;
			}
			else {
				conditions[0] = 1;
				printf("Input score victory limit [%d]:",score_vic);

				fgets(input,256,stdin);

				if(input[0] == '\n')
					i = score_vic;
				else
					i = atoi(input);
				score_vic = i;
			}
		}
		else {
			conditions[id] = conditions[id]?0:1;
		}

	} while (id != -1 );


	for(i=0; i<7; i++){
		*(victory_conditions + i) = conditions[i];
	}

	*(score_victory + 0) = (char)(  score_vic & ( (1<<8) - 1) );
	*(score_victory + 1) = (char)( (score_vic & ( (1<<16) - 1) )>>8);
	*(score_victory + 2) = (char)( (score_vic & ( (1<<24) - 1) )>>16);
	*(score_victory + 3) = (char)( (score_vic & ( (1<<32) - 1) )>>24);
}

void change_difficulties(){
    int i,id;
	char input[256];
	char *desc;

	do {
		for(i=0; i<(max_players+1); i++){
			if(civid[i] != -1) {
				if(civdesc[i] != NULL){
					desc = civdesc[i];
				}
				else {
				    if(ver >= 200)
                        desc = wcivs[civid[i]];
                    else
                        desc = civs[civid[i]];
				}
				if(i<max_players)
					printf("%-2d: %s - %s\n",i,desc,diff_str[diffs[i]]);
				else
					printf("%-2d: Barbarian civilization - %s\n",i,diff_str[diffs[i]]);

			}
		}
		printf("Input civ you want to change difficulty level for (-1 to exit) [%d]:",-1);

		fgets(input,256,stdin);

		if(input[0] == '\n')
			id = -1;
		else
			id = atoi(input);

		if((id > max_players) || (id < -1))
			printf("Civ number %d is outside the valid range.\n",id);
		else if((id != -1)  && (civid[id] == -1))
			printf("Civ number %d is not in this game.\n",id);
		else if(id != -1) {
			do {

				for(i=1; i<10; i++){
					printf("%-2d: %s\n",i,diff_str[i-1]);
				}
				printf("Input desired difficulty level for civ %d [%d]:",id,diffs[id] + 1);

				fgets(input,256,stdin);

				if(input[0] == '\n')
					i = diffs[id] + 1;
				else
					i = atoi(input);

			} while ((i < 1) || (i > 9));
			diffs[id] = i - 1;
		}

	} while (id != -1 );

	for(i=0; i<(max_players+1); i++){
		*(difficulties + i*4) = (char)(  diffs[i] & ( (1<<8) - 1) );
	}
}

void change_options(){
    int i,id,options;
	char input[256];


	options = (ver < 102 ? 12 : (ver < 103 ? 13 : 14));

    if(ver >= 200){
        options = 15;
    }

	do {
		for(i=0; i<options; i++){
			printf("%-2d: %s - %s\n",i,options_meny_text[i],*(options_ptr + options_meny[i])?"enabled":"disabled");
		}

		printf("Input game option to enable/disable (-1 to exit) [%d]:",-1);

		fgets(input,256,stdin);

		if(input[0] == '\n')
			id = -1;
		else
			id = atoi(input);

		if((id >= options) || (id < -1))
			printf("Input is outside validrange outside the valid range.\n",id);
		else if(id >= 0){
			*(options_ptr + options_meny[id]) = *(options_ptr + options_meny[id])?0:1;
		}

	} while (id != -1 );
}

void input_timer(){
    int i;
	char input[256];

    for(i=0; i<6; i++){
        printf("%d: %s%s\n",i,timers[i],i==turnt?" (current value)":"");
    }

    printf("Input desired turn timer [%d (%s)]:",turnt,timers[turnt]);

    fgets(input,256,stdin);

    if(input[0] == '\n')
        i = turnt;
    else
        i = atoi(input);

    if((i < 0) || (i > 5))
        i = turnt;

    *(turntimer) = i;
    turnt = i;

}

void input_pbtimer(){
    int i;
	char input[256];

    printf("Input desired pitboss turn timer in hours [%d]:",pbturnt);

    fgets(input,256,stdin);

    if(input[0] == '\n')
        i = pbturnt;
    else
        i = atoi(input);

    if(i < 0)
        i = pbturnt;

	*(pbturntimer + 0) = (char)( i & ( (1<<8) - 1) );
	*(pbturntimer + 1) = (char)( (i & ( (1<<16) - 1) )>>8);
	*(pbturntimer + 2) = (char)( (i & ( (1<<24) - 1) )>>16);
	*(pbturntimer + 3) = (char)( (i & ( (1<<32) - 1) )>>24);

    pbturnt = i;

}

void input_maxplayers(){
    int i;
	char input[256];

    printf("What is the max number of players this game allows? [%d]:\n(Leave at default if you have no idea what this is about) ",max_players);

    fgets(input,256,stdin);

    if(input[0] == '\n')
        i = max_players;
    else
        i = atoi(input);

    if((i < 0))
        i = max_players;

    max_players = i;

}

void menu(){
	char input[256];
    int menuchoice;

    strcpy(outfile,"output.Civ4SavedGame");


    do {

        printf("\nMenu:\n\n");

        printf(" 1: Convert to type (%s%s).\n",(convert_to == 0 ? "unchanged - " :
                (convert_to == 1 ? "hotseat" :
                (convert_to == 2 ? "play by E-mail" : "pitboss / network multiplayer" ))),
            (convert_to == 0 ? (gametype < 9 ? gametypes[gametype] : gametypes[9]): ""));

        printf(" 2: Convert between AI <-> Human (Currently %d human players).\n",humans);

        printf(" 3: Change difficulty levels.\n");

        printf(" 4: Change victory conditions.\n");

        printf(" 5: Change game options.\n");

        if((convert_to != 1) && (convert_to != 2) && !((convert_to == 0) && ((gametype <= 2) || (gametype == 6) || (gametype >= 8)))){
            printf(" 6: Toggle simultaneous turns (%s).\n",simul?"on":"off");

            printf(" 7: Toggle take over AI (%s).\n",takeover?"on":"off");

            printf(" 8: Toggle turn timers (%s).\n",timer?"on":"off");


            if(timer){
                printf(" 9: Change multiplayer timer (%s).\n",timers[turnt]);

                printf("10: Change Pitboss timer (%d hours).\n",pbturnt);

            }
            if(ver >= 200){
                printf("11: Toggle anonymous play (%s).\n",anonplayers?"on":"off");
            }
        }

        printf("\n-1: Finish and write to output file.\n",outfile);

        printf("\nSelect from menu [-1]: ");

		fgets(input,256,stdin);

		if(input[0] == '\n')
			menuchoice = -1;
		else
            menuchoice = atoi(input);

        switch(menuchoice){
            case 1: convert_type();
                    break;
            case 2: convert_players();
                    break;
            case 3: change_difficulties();
                    break;
            case 4: change_victory_conditions();
                    break;
            case 5: change_options();
                    break;
            case 6: simul = !simul;
                    *(multi + 0) = simul;
                    break;
            case 7: takeover = !takeover;
                    *(multi + 1) = takeover;
                    break;
            case 8: timer = !timer;
                    if(ver < 200)
                        *(multi + 2) = timer;
                    else
                        *(multi + 4) = timer;
                    break;
            case 9: input_timer();
                    break;
            case 10: input_pbtimer();
                    break;
            case 11:if(ver >= 200) {
                        anonplayers = !anonplayers;
                        *(multi + 3) = anonplayers;
                    }
                    break;
            default:
                    break;
        }

    } while (menuchoice != -1);
    out_file();
}


void main(int argc, char **argv){

    int ret,i,id;

	char filename[256] = "";

	printf("Saveconvert Version 4.2\n\n");

	if(argc > 1){
		strncpy(filename,argv[1],strlen(argv[1])+1);
	}

	printf("Input savefile [%s]:",filename);
	fgets(filename,256,stdin);

	filename[strlen(filename)-1] = '\0';
	if(strlen(filename)==0){
		if(argc > 1){
			strncpy(filename,argv[1],strlen(argv[1])+1);
		}
		else {
			filename[0] = '\0';
		}
	}

    if(-1 == (ret = init(filename))){
            return;
    }


    if(ret = parse_header()){
            return;
    }


    menu();

	if (NULL == (outf = fopen(outfile, "wb"))) {
        fprintf (stderr, "Failed to open file \"%s\" for writing.\n",outfile);
        return;
	}
	outs = outf;


	fwrite (modified_save, 1, modified_length, outs);
    if(outf) fclose(outf);
    return;
}
 
Thank you, will work on it to see what happens.

I can't make out what is what. What functions are responsible for reading the text from the save file? And where does it convert the text to the individual values?
 
It would be truly wonderful if we could finally have a tool to edit BtS save games. I have two pbem games that need to have tech trading disabled, and we are quite far in and cannot restart them.
 
It would be truly wonderful if we could finally have a tool to edit BtS save games. I have two pbem games that need to have tech trading disabled, and we are quite far in and cannot restart them.
why disabled? Just interested to know.
 
why disabled? Just interested to know.
We're new to pbem with normal victory conditions, and one of the games is a free-for-all with AI's and another is a team-FFA with AI's. I'm just worried that the AI's are going to trade technology with each other and make it too complicated for us humans to win. It seems that most players in the pbem forum disable tech trading as well.
 
fair enough - AIs in the game can be abused.
 
As far as I remember, if you just hexedit the save in BtS to change this, then the save wont load.. (the savegame checksum checks will fail)
But I may be wrong about just this setting..
 
As far as I remember, if you just hexedit the save in BtS to change this, then the save wont load.. (the savegame checksum checks will fail)
But I may be wrong about just this setting..
I see. I guess we'll have to start over again, perhaps with some extra advanced start points. Thanks ruff_hi and Gyathaar.
 
Darn would a save game converter be the only way to disable Time victory mid-game? I really don't want to save my game as a new scenario since I don't want the dates and diplo modifiers reset.
 
I decided to start a new thread since the tool has changed quite a bit from the original tool for playing scenarios in hotseat.

I have a simple wish to be able to swap civs and their playing orders in the original WBSave file, but cannot find the right Utility for that. Say, in scenario Civ 1 starts second and Civ2 starts 4th. Any easy way to alternate this order? :confused:
 
Necro thread!

I have a BtS PBEM game going on with friends. We wish to convert it to a Pittboss game, was this application actually updated to do this since I'm reading it can't handle updated BtS save format? Is there something else that would allow us to do so?
 
Top Bottom