EDIT: I was digging around in the ToA files, and am now thoroughly terrified of timmeh. Those save functions are crazy. I have no idea.
The code was a bit of a mess, but it's functional, and if I can explain it it might make a little more sense...
Let's see...
ofstream savefile("data\\save.dat", ios::out | ios::binary);
savefile.write(reinterpret_cast<char *>(&Game.plyr_x), sizeof(int) );
savefile.write(reinterpret_cast<char *>(&Game.plyr_y), sizeof(int) );
savefile.write(reinterpret_cast<char *>(&Game.current_map), sizeof(dungeon_map) );
int logvecsize = Game.longlog.size();
savefile.write(reinterpret_cast<char *>(&logvecsize), sizeof(int) );
for(int i=0; i<logvecsize; i++)
{
int length = Game.longlog[i].length();
savefile.write(reinterpret_cast<char *>(&length), sizeof(int) );
for(int j=0; j<length; j++)
{
savefile.write(reinterpret_cast<char *>(&Game.longlog[i].at(j)), sizeof(char) );
}
}
savefile.close();
The first line opens the file for output in binary mode. The next two save the player's x and y positions. The fourth is just to show that you can save a class/structure just as easily as an integer, with some limitations I'll mention in a minute.
The next bit is a little more complicated. I'm trying to save the vector of strings I use to store the message log, but neither vectors nor strings can be saved the same way integers can, because they're dynamic (can change size). First I get and save the size of the vector, just like I would a normal integer. Next I loop through the vector, saving the strings one at a time. It works almost just like the vector, first I write the length of the string to the file, then each character in the string.
The last line saves and closes the file.
ifstream loadfile("data\\save.dat", ios::in | ios::binary);
loadfile.read(reinterpret_cast<char *>(&Game.plyr_x), sizeof(int) );
loadfile.read(reinterpret_cast<char *>(&Game.plyr_y), sizeof(int) );
dungeon_map newmap;
loadfile.read(reinterpret_cast<char *>(&newmap), sizeof(dungeon_map) );
memcpy(&Game.current_map, &newmap, sizeof(dungeon_map));
Game.current_map = newmap;
Game.longlog.clear();
int logvecsize;
loadfile.read(reinterpret_cast<char *>(&logvecsize), sizeof(int) );
for(int i=0; i<logvecsize; i++)
{
int length;
loadfile.read(reinterpret_cast<char *>(&length), sizeof(int));
char log[length+1];
for(int j=0; j<length; j++)
{
loadfile.read(reinterpret_cast<char *>(&log[j]), sizeof(char));
}
log[length] = '\0';
Game.longlog.push_back(string(log));
}
loadfile.close();
I know, this one looks even worse... in all honesty though it's not too bad. The first line opens the file for input in binary mode. The next two load the player's position. The next block is a little weird, but only because it's different. Basically, for a reason I can't remember at the moment, I couldn't load the map directly into the 'Game' structure's 'current_map' member. So I create a blank map, load the one from the file into it instead, then copy the information from it into the Game.current_map one. I can't really remember why it works quite like that, with the memcpy call, but it works.
The next thing I do is clear the log vector, in case the player is loading in the middle of a game. Then I load the size of the saved vector, and load the strings. The string loading is a little weird too, but basically, I load the length, make a c-string thats one character longer (so I can terminate it after putting the rest of the letters in), and then load the letters into it one at a time. Once I'm done, I convert the c-string into a normal string and push it onto the vector.
As you've probably (hopefully...) guessed, the last line closes the file.
The limitation I mentioned earlier: Just like you have to save strings, vectors and other dynamic data types manually, any class or structure with a dynamic data type member has to be saved manually. This is made a lot easier if you're using classes, cause you can create save and load functions that take the file variable as an argument, and break it down further.
See? Or did I just make it worse?
[EDIT]: Here's an example of loading with a class function...
for(int i=0; i<EQUIPMENTSLOTS; i++)
{
Game.plyr_equipment[i] = EmptySlot;
if(Game.plyr_equipped[i]==true)
{
Game.plyr_equipment[i].load(loadfile);
}
}
void item::load(ifstream &File)
{
File.read(reinterpret_cast<char *>(&name), sizeof(char[10]) );
File.read(reinterpret_cast<char *>(&symbol), sizeof(char) );
File.read(reinterpret_cast<char *>(&type), sizeof(int) );
File.read(reinterpret_cast<char *>(&ammo_type), sizeof(int) );
File.read(reinterpret_cast<char *>(&equip_slot), sizeof(int) );
File.read(reinterpret_cast<char *>(&effects), sizeof( int[EFFECTTYPES]) );
item_spell.load(File);
File.read(reinterpret_cast<char *>(&uses), sizeof(int) );
File.read(reinterpret_cast<char *>(&x), sizeof(int) );
File.read(reinterpret_cast<char *>(&y), sizeof(int) );
File.read(reinterpret_cast<char *>(&value), sizeof(int) );
File.read(reinterpret_cast<char *>(&weight), sizeof(int) );
}
Actually, there's a second tier here, cause the item load the spell that's tied to it with the spell class' load function. Anyways, just figured I'd post this in case you wanted an example.