If I could get details on how to repeat this, I'd be much interested. No experience with zlib but I learn very, very quickly when I need to.
I used the
python implementation of zlib, as it's simple to use and easy to write ad-hoc stuff.
I hope you are familiar with the Python interpreter.
An important note: To load the file in the interpreter, you must specify it as binary, like this (note the 'b' in the file mode):
Code:
savedgamefile = open(path, 'r[B]b[/B]')
data = savedgamefile.read()
savedgamefile.close()
I'm not on the same PC in which I did this, but from memory:
First, the compressed stream inside the save file starts with the hex bytes 0x789C, which is the header of the 'deflate' algorithm (see
RFC1950).
There are chunks of data before that stream. The exact location could be different in different save files (probably dependent on world size, which mod and other factors). On the specific file I worked on it was @ 0x5f6, and I saw it in another save file.
Then the stream continues almost until the end, I don't know exactly where.
I started by using the following:
Code:
uncomp_data = zlib.decompress(data[0x5f6:])
Which gave an exception on incorrect block lengths or something.
I then tried a shorter stream, something like:
Code:
uncomp_data = zlib.decompress(data[0x5f6:0x5f6+100])
Which gave an error of incomplete stream (again, not exact phrasing).
So I did a binary search on the exact position where it breaks, and found the point in which the error changed from 'incomplete' to 'incorrect'.
It still didn't work properly, so what I did was to use a decompression object which can do this in parts:
Code:
# 'end' is the location I found with the binary search
decomp_obj = zlib.decompressobj()
uncomp_data = decomp_obj.decompress(data[0x5f6:end])
And then uncomp_data contained the data written by the game's DLL.
I'm not completely sure it was complete, and I don't know what else it contained, but I added markers (I hardcoded script data members in the code so I can identify both the positions in the stream and the fact that the stream is indeed decompressed), so it was definitely the raw data.
The decompressed data was something like 500KB (from a 9KB compressed buffer), but I assume that's because it was a game start and most data was zeros.
To save the data to a file, I used:
Code:
uncomp_savedgamefile = open(out_path, 'w[B]b[/B]')
uncomp_savedgamefile.write(uncomp_data)
uncomp_savedgamefile.close()
It requires more research, but it's a start. Let me know if it's working.
If you can uncompress it, then one needs to be able to modify, and then return it to a format that can be used.
Yes, but there appears to be a checksum at the end of the save file. I have yet to check this, but I'm guessing you'll need to update this if you modify the data. In addition, I think there's some kind of a header which contains data length, so this would need to be updated as well.
EDIT: You should add 'import zlib' in the beginning. This package should come with the Python standard installation.