I'm working on a utility to read in some of the AGS files. I've started with the Sprite Cache. I downloaded the source code for the engine and tried to decipher the file format from that. However, I'm not sure it is correct. Would anyone be able to confirm that the follow is accurate and if not, what is wrong with it?
<Header>
word version (6)
string SpriteFileSig (" Sprite File ")
byte Compressed (1 or 0)
long SpriteFileIDCheck
word Index of Last Sprite (Number of Sprites -1)
<Sprite Header>
word bpss (Bytes per Color)
word Sprite Width
word Sprite Height
<Compressed>
long Length
byte Array of bytes of Length in size
<Uncompressed>
byte Array of bytes of bpss * Sprite Width * Sprite Height (Could be word or long depending on Color depth)
Thanks.
I am guessing you used "save" function as a reference? It is not always correct, because data format may have changed over time, and "save" function includes only the latest one. Here's what we may learn from "load" function.
Depending on file version, the compressed flag and spriteFileID may not be there.
Spoiler
if (vers == 4)
this->spritesAreCompressed = false;
else if (vers == 5)
this->spritesAreCompressed = true;
else if (vers >= 6)
{
this->spritesAreCompressed = (cache_stream->ReadInt8() == 1);
spriteFileID = cache_stream->ReadInt32();
}
Also, version < 5 files contain palette, which is now unused:
Spoiler
if (vers < 5) {
// skip the palette
cache_stream->Seek(Common::kSeekCurrent, 256 * 3);
}
The version < 4 file have always Index of Last Sprite = 200:
Spoiler
if (vers < 4)
numspri = 200;
When reading a sprite, only version 5 reads sprite data length, others calculate it from color depth and size:
Spoiler
if (vers == 5) {
spriteDataSize = cache_stream->ReadInt32();
}
else {
spriteDataSize = wdd * coldep * htt;
}
As yu may see, the "compressed" flag is not checked here at all.
Also, it is a bit strange that version 6 does not read sprite data size... I would expect it to do so. But frankly, I never paid attention to what this file version is in the game I tested.
Other than that, it seems correct.
Also, may I suggest not to use "long" and "word", but "int" and "short" instead (or maybe even better - int32 and int16)? The "long" type has different meanings on 32-bit and 64-bit platforms, therefore it does not define exact value size. "Word" too may be different.
//--------------------------------------------------
UPDATE: It looks like we found a bug in the engine here :)
QuoteAlso, it is a bit strange that version 6 does not read sprite data size...
Exactly, and that's wrong, because it should. The only reason it works is that Editor includes sprites index file to the game, and sprites are not loaded raw, but instead are being picked out using offsets provided by index table.
There's indeed must be an "if compressed" check in the loading code for file version >= 6. I am going to fix that in our development branch :).
//--------------------------------------------------
UPDATE 2: Fixed n tested.
This is how the reading of sprite size should look like:
Spoiler
if (vers == 5) {
spriteDataSize = cache_stream->ReadInt32();
}
else if (vers >= 6)
{
spriteDataSize = this->spritesAreCompressed ? cache_stream->ReadInt32() :
wdd * coldep * htt;
}
else {
spriteDataSize = wdd * coldep * htt;
}
Thank you. That helps clear some things up for me. I'm glad it led to a bug fix. :)