movie.binltl Movie file format

NB. This is a description of the in-game BINARY file format for movies. You are advised not to use this format, but to contribute to the discussion on an XML format for these files.

This is some sketchy information about the movie.binltl file format. These contain animated movies used for the loading screen, cut-scenes and credits. They consist of a number of actors, each of which is animated according to a BinImageAnimation.

File format

The file is unencrypted binary data, roughly corresponding to the C structs used in the game. Pointers are stored as offsets from the start of the file.

Simple types

float - 32-bit floating point in IEEE 754 floating-point "single format" bit layout
int - 32-bit little endian integer
char * - stored in files as a sequential list of null-terminated strings
enum = stored in the file as ints

enum ActorType
{
       eActorType_Image = 0,
       eActorType_Text = 1
};
 
enum AlignmentH
{
       ALIGN_LEFT = 0,
       ALIGN_CENTER = 1,
       ALIGN_RIGHT = 2
};
 
enum AlignmentV
{
       ALIGN_TOP = 0,
       ALIGN_MIDDLE = 1,
       ALIGN_BOTTOM = 2
};

Complex types

struct BinActor
{
+0x00:       ActorType mType;
+0x04:       int mImageStrIdx;
+0x08:       int mLabelTextStrIdx;
+0x0c:       int mFontStrIdx;
+0x10:       float mLabelMaxWidth;
+0x14:       float mLabelWrapWidth;
+0x18:       AlignmentH mLabelJustification;
+0x1c:       float mDepth;
};
 
struct BinMovie
{
+0x00:       float length;
+0x04:       int numActors;
+0x08:       BinActor *pActors;
+0x0c:       BinImageAnimation **ppAnims;
+0x10:       const char *pStringTable;
};

Note that pActors is a pointer to the array of BinActors
ppAnims has an extra indirection which is strictly superfluous, however it allows the BinImageAnimation structure and associated animation data to be stored as a single contiguous block. Which is the format 2DBoy used for the original files.

File order

There is a single BinMovie at the start of the file. All other items are referenced by "pointers" within this structure (offsets from the start of the file).

A BinActor is an animated scene element. All BinActor string indexes reference the BinMovie string table. There is exactly one BinImageAnimation per BinActor.

Example

Some complete dumps (large files!) of movies, including their actors and BinImageAnimations can be found here: Chapter5End and credits

Here are just the actors from res\movie\credits\credits.movie.binltl:

length = 63.0
numActors = 34
actorsOffset = 20
animsOffset = 1108
stringsOffset = 1244
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_BLACK32', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=0.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_GIRL3', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=1.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_GIRL2', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=2.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_GIRL1', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=3.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_GIRL0', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=4.0}
actor = BinActor{actorType=TEXT, imageStr='', labelStr='$MOVIE_CREDITS_DATE', fontStr='FONT_BIGWHITE_52', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=5.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_2DBOY', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=6.0}
actor = BinActor{actorType=TEXT, imageStr='', labelStr='$MOVIE_CREDITS_SPECIALFRIENDS', fontStr='FONT_BIGWHITE_52', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=7.0}
actor = BinActor{actorType=TEXT, imageStr='', labelStr='$MOVIE_CREDITS_D9', fontStr='FONT_BIGWHITE_52', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=8.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_PAULHUBANS', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=9.0}
actor = BinActor{actorType=TEXT, imageStr='', labelStr='$MOVIE_CREDITS_D8', fontStr='FONT_BIGWHITE_52', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=10.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_ALLANBLOMQUIST', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=11.0}
actor = BinActor{actorType=TEXT, imageStr='', labelStr='$MOVIE_CREDITS_D7', fontStr='FONT_BIGWHITE_52', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=12.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_RONCARMEL', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=13.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_AND', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=14.0}
actor = BinActor{actorType=TEXT, imageStr='', labelStr='$MOVIE_CREDITS_D6', fontStr='FONT_BIGWHITE_52', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=15.0}
actor = BinActor{actorType=TEXT, imageStr='', labelStr='$MOVIE_CREDITS_D5', fontStr='FONT_BIGWHITE_52', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=16.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_GEAR', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=17.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_GEAR', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=18.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_GEAR', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=19.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_KYLEGABLER', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=20.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_AND', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=21.0}
actor = BinActor{actorType=TEXT, imageStr='', labelStr='$MOVIE_CREDITS_D4', fontStr='FONT_BIGWHITE_52', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=22.0}
actor = BinActor{actorType=TEXT, imageStr='', labelStr='$MOVIE_CREDITS_D3', fontStr='FONT_BIGWHITE_52', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=23.0}
actor = BinActor{actorType=TEXT, imageStr='', labelStr='$MOVIE_CREDITS_D2', fontStr='FONT_BIGWHITE_52', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=24.0}
actor = BinActor{actorType=TEXT, imageStr='', labelStr='$MOVIE_CREDITS_D1', fontStr='FONT_BIGWHITE_52', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=25.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_TREE', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=26.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_TREE', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=27.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_TREE', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=28.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_TREE', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=29.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_TREE', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=30.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_TREE', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=31.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_WOGLOGO01', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=32.0}
actor = BinActor{actorType=IMAGE, imageStr='IMAGE_MOVIE_CREDITS_LENSFLARE', labelStr='', fontStr='', labelMaxWidth=-1.0, labelWrapWidth=-1.0, labelJustification=1, depth=33.0}