The Dink Network

Save games and globals

June 14th 2011, 03:10 PM
wizardb.gif
Kyle
Peasant He/Him Belgium
 
I was wondering how globals are saved inside the save file.

Is it possible in theory to delete globals from a save file and then reuse those variable "slots" in the dmod on that save later on?

Let me give an example:

I use the global &addon1 in the regular savefile. Now ingame I change map files and reset everything, except I want to continue playing on the same savefile so the stats and items are still intact. So, I wish to delete $addon1 and create a new variable $addon2 that is using the same "slot".
June 14th 2011, 03:26 PM
custom_magicman.gif
magicman
Peasant They/Them Netherlands duck
Mmmm, pizza. 
There are no DinkC commands for it, but you could write an external savegame editor that does just that. Variables are saved as an array of 250 items that all look like:

4 bytes (=1 integer) of variable value
20 bytes (=20 characters) of variable name
4 bytes (=1 integer) of "scope" (either global (presumably 0 or -1 or something like that), or a script number)
1 byte (=1 boolean) to indicate if this slot is currently in use.
3 bytes of padding, to make this 32 bytes total.

I'll have to do a bit more math to figure out at which byte offset in the .dat file you can find this structure, but I bet you can open it with a hex editor and look for anything that looks like a variable name.

EDIT<whatever>: I guess this assumes a 32bits architecture, which is the only thing I'm familiar with.

EDIT<whatever+1>: Modified the savegame layout a bit to better reflect how data is saved.

EDIT<whatever+2>: Reading up on 64bits architectures, it looks like an "int" is 4 bytes, no matter which system is used. It is only a "long" that suddenly gets bigger.
June 14th 2011, 03:46 PM
wizardb.gif
Kyle
Peasant He/Him Belgium
 
Thanks, that's exactly what I needed to know I'll look for the offset, shouldn't be too hard.

Any info on how to read/write to a .dat file? I can program just fine, but have never touched trying to read/write to a file that's not just text.
June 14th 2011, 04:01 PM
custom_magicman.gif
magicman
Peasant They/Them Netherlands duck
Mmmm, pizza. 
That depends on the language you use, of course, but three things to be aware of:
1) Open the file in binary mode, instead of text mode.
2) Figure out which of the four bytes that are an integer is the most significant.
3) Seth hates (or used to hate) array index 0, so the savegame may only contain 249 variables, with 32 nonsense bytes in front. I think the best way to discover this is to write a small D-Mod that uses as many variables as you can. If string interpolation works in make_global_int, try:

&crap = 0;
loop:
make_global_int("var&crap",&crap);
&crap += 1;
// Except, of course, some more sensible bound, because you'll still need the required globals.
if (&crap < 250)
{
  goto loop;
}


If your primary language is C, then you can look at this wikipage to figure it out.
June 14th 2011, 04:11 PM
wizardb.gif
Kyle
Peasant He/Him Belgium
 
I mainly program in C# or PHP, obviously the latter is useless for this

I get everything you're saying except: "2) Figure out which of the four bytes that are an integer is the most significant."

Could you elaborate a little please?

And I'll be testing that script to see if the interpolation works (I'm thinking no :/). If not, I'll just copy/paste change a lot

EDIT: I think I get it, you just meant which 4 bytes are the value if I need that, scope if I need that, ... I think I'm fine now, thanks
June 14th 2011, 04:29 PM
custom_magicman.gif
magicman
Peasant They/Them Netherlands duck
Mmmm, pizza. 
Oh, PHP can be used for this. True, it's mostly used for dynamic websites, but you can use it to write scripts just like Perl or Python... Either way, search for "reading/writing binary file PHP" (or C#, though if you're unlucky, google may ignore the #). There's bound to be some tutorials about this.

About significant bytes, the integer value of a variable is saved as 4 bytes:

[byte1][byte2][byte3][byte4]

As you probably know, each byte can store values ranging from 0 (00) up to 255 (FF). How to store the number "1" in four bytes? This can be either:

00 00 00 01 -- most significant byte first
or
01 00 00 00 -- most significant byte last

Depending on which byte is the most significant. Similarly, 256 can be:

00 00 01 00 -- most significant byte first
or
00 01 00 00 -- most significant byte last

Finally, 257:

00 00 01 01 -- most significant byte first
or
01 01 00 00 -- most significant byte last

Oh, and I just checked, the boolean for "active" is stored as only one byte (either 00 or 01), but it's followed by three bytes that are all 00, for byte padding reasons. If you don't know what this means, ignore it. Just be aware that the 4 bytes of "active" look either like "01 00 00 00" or "00 00 00 00", even though the first combination of four bytes, when interpreted as an integer might mean 2^24, in case the most significant byte goes first.

I... hope that makes sense.
June 14th 2011, 04:41 PM
wizardb.gif
Kyle
Peasant He/Him Belgium
 
Excellent! I think I have everything I need to get started on my pet utility now

Couldn't have done it without you Magic