Scenes.image: Difference between revisions
Bucky21659 (talk | contribs) mNo edit summary |
|||
Line 1: | Line 1: | ||
<code>scenes/'''scenes.image'''</code> is a binary data blob from which Source 2007 (i.e. The Orange Box engine) loads choreography scenes. It was created to improve performance on consoles: it is loaded into memory its entirety when the engine starts, which eliminates the need for consoles' slow optical media to seek around on a disk for hundreds of loose .VCD files. It helps on PC too however, so has been ported across. | <code>scenes/'''scenes.image'''</code> is a binary data blob from which Source 2007 (i.e. The Orange Box engine) loads choreography scenes. It was created to improve performance on consoles: it is loaded into memory in its entirety when the engine starts, which eliminates the need for consoles' slow optical media to seek around on a disk for hundreds of loose .VCD files. It helps on PC too however, so has been ported across. | ||
'''''To build a scenes.image, load Faceposer and choose <code>File > Rebuild scenes.image...</code>''''' | '''''To build a scenes.image, load Faceposer and choose <code>File > Rebuild scenes.image...</code>''''' |
Revision as of 16:57, 7 January 2014
scenes/scenes.image
is a binary data blob from which Source 2007 (i.e. The Orange Box engine) loads choreography scenes. It was created to improve performance on consoles: it is loaded into memory in its entirety when the engine starts, which eliminates the need for consoles' slow optical media to seek around on a disk for hundreds of loose .VCD files. It helps on PC too however, so has been ported across.
To build a scenes.image, load Faceposer and choose File > Rebuild scenes.image...

scenes/
folder will be built into the image. This means that you will need to extract Valve's scenes from your base game's GCFs before compiling if you want to use them. Remember that a lot of scenes used automatically by NPCs are in the original source engine.gcf
. (Yes, doing all this sucks!) You don't need to distribute the extracted VCD files though.Bypassing
If you are producing your own binaries, the old method of loading loose files can be reinstated:
CChoreoScene *CSceneEntity::LoadScene( const char *filename, IChoreoEventCallback *pCallback )
{
char loadfile[MAX_PATH];
Q_strncpy( loadfile, filename, sizeof( loadfile ) );
Q_SetExtension( loadfile, ".vcd", sizeof( loadfile ) );
Q_FixSlashes( loadfile );
void *pBuffer = 0;
CChoreoScene *pScene;
int fileSize = filesystem->ReadFileEx( loadfile, "MOD", &pBuffer, true );
if (fileSize)
{
g_TokenProcessor.SetBuffer((char*)pBuffer);
pScene = ChoreoLoadScene( loadfile, NULL, &g_TokenProcessor, LocalScene_Printf );
}
else
{
// binary compiled vcd
pScene = new CChoreoScene( NULL );
if ( !CopySceneFileIntoMemory( loadfile, &pBuffer, &fileSize ) )
{
MissingSceneWarning( loadfile );
return NULL;
}
CUtlBuffer buf( pBuffer, fileSize, CUtlBuffer::READ_ONLY );
if ( !pScene->RestoreFromBinaryBuffer( buf, loadfile, &g_ChoreoStringPool ) )
{
Warning( "CSceneEntity::LoadScene: Unable to load scene '%s'\n", loadfile );
delete pScene;
pScene = NULL;
}
}
if(pScene)
{
pScene->SetPrintFunc( LocalScene_Printf );
pScene->SetEventCallbackInterface( pCallback );
}
FreeSceneFileMemory( pBuffer );
return pScene;
}
}
CChoreoScene *C_SceneEntity::LoadScene( const char *filename )
{
char loadfile[MAX_PATH];
Q_strncpy( loadfile, filename, sizeof( loadfile ) );
Q_SetExtension( loadfile, ".vcd", sizeof( loadfile ) );
Q_FixSlashes( loadfile );
void *pBuffer = 0;
CChoreoScene *pScene;
int fileSize = filesystem->ReadFileEx( loadfile, "MOD", &pBuffer, true );
if (fileSize)
{
g_TokenProcessor.SetBuffer((char*)pBuffer);
pScene = ChoreoLoadScene( loadfile, this, &g_TokenProcessor, Scene_Printf );
}
else
{
fileSize = scenefilecache->GetSceneBufferSize( loadfile );
if ( fileSize <= 0 )
return NULL;
pBuffer = new char[ fileSize ];
if ( !scenefilecache->GetSceneData( filename, (byte *)pBuffer, fileSize ) )
{
delete[] pBuffer;
return NULL;
}
if ( IsBufferBinaryVCD( (char*)pBuffer, fileSize ) )
{
pScene = new CChoreoScene( this );
CUtlBuffer buf( pBuffer, fileSize, CUtlBuffer::READ_ONLY );
if ( !pScene->RestoreFromBinaryBuffer( buf, loadfile, &g_ChoreoStringPool ) )
{
Warning( "Unable to restore scene '%s'\n", loadfile );
delete pScene;
pScene = NULL;
}
}
}
if(pScene)
{
pScene->SetPrintFunc( Scene_Printf );
pScene->SetEventCallbackInterface( this );
}
delete[] pBuffer;
return pScene;
}
This code also fixes a bug where the maximum path length for a scene was longer on the server than on the client.
Technical information
Scenes.image files are little-endian on all platforms, with all offsets being absolute to the beginning.
Header
The scenes.image file has the following header:
Type | Meaning | Description |
---|---|---|
UInt32 | ID | 4-byte identified used for file identification. Always big-endian "VSIF". |
UInt32 | Version | scenes.image file version. 2 is used. |
UInt32 | Scenes number | Total number of scene files. |
UInt32 | Strings number | Number of strings in the string pool (explained later). |
UInt32 | Scene entry offset | Offset to the scene entries (explained later). |
String pool
After the header, there are offsets to strings in the string pool.
The string pool stores all strings used in binary VCD (BVCD) files. BVCDs use signed 16-bit integers for string indices, so there cannot be more than 32767 strings in an image.
All strings in the pool are null-terminated.
Scene entries
The scene entries are placed at "Scene entry offset", and have the following structure:
Type | Meaning | Description |
---|---|---|
UInt32 | CRC file name | CRC32 hash of scene file name, in scenes\???.vcd format. All file names are lower-case and have \ as path separator. Valve CRC code should be used for best compatibility. |
UInt32 | Data offset | Offset to the scene file. |
UInt32 | Data length | Size of the scene file as stored in scenes.image (not real size of BVCD and/or LZMA compressed/uncompressed data). |
UInt32 | Scene summary offset | Offset to the scene summary (explained later). |
Scene data
Scenes are stored in either uncompressed or compressed format at the offsets specified in the scene entries.
Uncompressed scenes start with "bvcd" 4-byte ID. Their size is specified in the scene entries.
Compressed scenes have the following header:
Type | Meaning | Description |
---|---|---|
UInt32 | ID | Always "LZMA". |
UInt32 | Actual size | Size of uncompressed data. |
UInt32 | LZMA size | Size of compressed data. |
Byte[5] | Properties | Metadata used internally by LZMA module for uncompressing. |
After the header, there is compressed data, with the size being specified in the "LZMA size" field of the header.
Scenes are stored in Binary VCD format, and must be decompiled (either using CChoreoScene::RestoreFromBinaryBuffer
and CChoreoScene::SaveToFile
functions or a tool such as VSIF2VCD) in order to be viewable in Faceposer.
Scene summary
Scene summary stores scene information used to optimize scene playback.
Scene summaries have the following header:
Type | Meaning | Description |
---|---|---|
UInt32 | Milliseconds | Scene playback length, in milliseconds. |
UInt32 | Sounds number | Number of sounds used in the scene. |
After the header, there are 32-bit indices of strings in the string pool. The strings are sound names. They are used for precaching the scene.