Sprite Cache File Format Question

Started by redspark, Wed 20/02/2013 15:13:12

Previous topic - Next topic

redspark

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?

Code: AGS

    <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.

Crimson Wizard

#1
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

Code: cpp

  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();
  }
[close]

Also, version < 5 files contain palette, which is now unused:
Spoiler
Code: cpp

  if (vers < 5) {
    // skip the palette
      cache_stream->Seek(Common::kSeekCurrent, 256 * 3);
  }
[close]

The version < 4 file have always Index of Last Sprite = 200:
Spoiler
Code: cpp

  if (vers < 4)
    numspri = 200;
[close]

When reading a sprite, only version 5 reads sprite data length, others calculate it from color depth and size:
Spoiler
Code: cpp

    if (vers == 5) {
      spriteDataSize = cache_stream->ReadInt32();
    }
    else {
      spriteDataSize = wdd * coldep * htt;
    }
[close]
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
Code: cpp

    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;
    }
[close]

redspark

Thank you.  That helps clear some things up for me.  I'm glad it led to a bug fix. :)

SMF spam blocked by CleanTalk