Blood Omen file formats

From Blood Wiki
(Difference between revisions)
Jump to: navigation, search
(Created page with "This page is dedicated to file formats used to store resources fo Blood Omen. It encompasses exploring work done by the community since Blood Omen was released. Most basic f...")
 
m (Map file)
Line 197: Line 197:
  
 
Map file is fixed-length structure which holds tiles placement (80x80), enemies, lights, buttons and other objects to form Blood Omen level. Because of it's fixed nature, there are many limits, and each map file have exactly same size (so it can just be copied into memory).
 
Map file is fixed-length structure which holds tiles placement (80x80), enemies, lights, buttons and other objects to form Blood Omen level. Because of it's fixed nature, there are many limits, and each map file have exactly same size (so it can just be copied into memory).
 
// blood omen map structure
 
typedef struct
 
{
 
unsigned short parm1;    // first parm, if script is not defined it's 0xFFFF, 0xFFFE is null value
 
                        //  - destination/source map number (TRIGGER_EXIT, TRIGGER_ENTRANCE, TRIGGER_TELEPORT)
 
                        //  - speech num (TRIGGER_INFOMARK, TRIGGER_IMAGEMARK)
 
unsigned short parm2;    // second parm:
 
                        //  - button num (TRIGGER_BUTTON)
 
                        //  - pic num (TRIGGER_IMAGEMARK)
 
byte          parm3;    // destination/source map section (TRIGGER_EXIT, TRIGGER_ENTRANCE, TRIGGER_TELEPORT)
 
byte          srcx;    // sposition
 
byte          srcy;    // sposition
 
byte          type;    // script type, one of TRIGGER_
 
byte          u2[3];    // ?
 
byte          x;        // position
 
byte          y;        // position
 
byte          u3[3];    // ?
 
}bo_trigger_t;
 
 
typedef struct
 
{
 
unsigned short savenum;  // unique savegame id
 
byte          itemcode; // one of MAPITEM_ code
 
byte          x;        // position
 
byte          y;        // position
 
byte          hidden;  // set to 1 if item is spawned by trigger (like barrel destruction)
 
unsigned short target;  // targeted triggergroup
 
byte          u[4];    // ?
 
}bo_item_t;
 
 
typedef struct
 
{
 
    unsigned short targetnum;// a triggergroup
 
byte x;                  // position
 
byte u1;                // ?
 
byte y;                  // position
 
byte u2;                // ?
 
unsigned short tile1;    // tilenum
 
unsigned short tile2;    // alternate state tilenum
 
byte contents1;          // contents, see CONTENTS_ defines for possible content values
 
byte contents2;          // alternate state contents
 
byte u3[12];            // ?
 
}bo_atile_t;
 
 
typedef struct
 
{
 
unsigned short target;  // a triggergroup to call
 
unsigned short tile1;    // tilenum
 
unsigned short tile2;    // alternate state tilenum
 
byte flags;              // see BUTTONFLAG_* defs
 
byte u1;                // ?
 
unsigned short savenum;  // unique savegame id
 
byte u2;                // ?
 
byte u3;                // ?
 
}bo_button_t;
 
 
typedef struct
 
{
 
byte x;                  // position
 
byte y;                  // position
 
byte lightposx;          // position of lightsource
 
byte lightposy;          // position of lightsource
 
byte sprite;            // index of sprite from sprites array
 
byte lightsizex;        // size of light polygons
 
byte lightsizey;        // size of light polygons
 
byte u1;                // ?
 
byte lightform;          // light form flags
 
byte r;                  // red color component
 
byte g;                  // green color component
 
byte b;                  // blue color component
 
unsigned short targetnum;// triggergroup
 
byte start_on;          // 1 if effect starts on, 0 if starts off
 
byte u3[5];              // ?
 
}bo_effect_t;
 
 
typedef struct
 
{
 
byte data[164];
 
}bo_object_t;
 
 
typedef struct
 
{
 
byte x;                  // start position
 
byte y;                  // end position
 
byte w;                  // width
 
byte h;                  // height
 
byte ofsx;              // multiply by 16 to get real offset
 
byte ofsy;              // multiply by 16 to get real offset
 
byte u1;
 
byte u2;
 
}bo_grpobject_t;
 
 
typedef struct
 
{
 
byte u1;                // ?
 
byte u2;                // ?
 
byte u3;                // ?
 
byte u4;                // ?
 
unsigned short tile1;    // base tile (grpobject really, not standart 32x32 tile)
 
unsigned short tile2;    // toggled tile (grpobject)
 
unsigned short tile3;    // destroyed tilee (grpobject)
 
byte u5;                // ?
 
byte u6;                // ?
 
byte pushable;          // a strength required to push
 
byte toggled;            // trigger can toggle it's state (means tile2 is there)
 
byte u7;                // ?
 
byte spawnitems[3];      // item codes to spawn when toggled/destroyed
 
byte u8;                // ?
 
byte destructible;      // destructible flags
 
unsigned short savenum;  // unique savegame id
 
byte u10;                // ?
 
byte x;                  // position
 
byte y;                  // position
 
byte u11;                // ?
 
byte active;            // 1 is filled, otherwise 0
 
byte u13;                // ?
 
}bo_scenery_t;
 
 
typedef struct
 
{
 
byte x;                  // position
 
byte y;                  // position
 
byte u1;                // ?
 
byte u2;                // ?
 
}bo_path_t;
 
 
typedef struct
 
{
 
bo_path_t paths[4];      // patrole paths
 
byte u1[12];            // ?
 
unsigned short savenum;  // unique savegame id
 
byte u2[52];            // ?
 
byte charnum;            // monster class (same as char* sprite)
 
byte u3[10];            // ?
 
unsigned short target;  // triggergroup to call once killed
 
byte u4[20];            // ?
 
byte lastpath;          // ?
 
byte u6[18];            // ?
 
byte u7[15];            // ?
 
byte x;                  // position
 
byte y;                  // position
 
byte u8[4];              // ?
 
unsigned short speechnum;// a speech number for disguise talk
 
byte u9[6];              // ?
 
}bo_monster_t;
 
 
typedef struct
 
{
 
// a chain of tilemap numbers used (to make a filenames)
 
// each tilemap holds 64 tiles, tiles numbering is linear
 
// like, a tile #131 is tile #3 from tilemap #2
 
// being 2-byte (unsigned short) tilenum contains some flags (flag are starting from byte 10)
 
// see TILEFLAG_ defines for possible tileflags
 
unsigned short  tilemaps[40];
 
// yet unknown info
 
byte            u1[12];
 
bo_object_t    objects[10];
 
bo_monster_t    monsters[32];
 
bo_grpobject_t  grpobjects[8][32];
 
// animated tiles - a tiles that can be toggled between 2 states and have different contents for each state
 
// used on doors, spikes that pops up on the floor etc.
 
// animated tiles have triggergroup to be executed by script
 
bo_atile_t      atiles[100];
 
// a special buttons array holds all buttons used on level
 
// pretty similar to animated tiles
 
// buttons have triggergroup to be executed by script
 
bo_button_t    buttons[20];
 
// yet unknown info #2
 
byte            u2[8];
 
// scenery pushable objects - tables, chairs, stones etc.
 
bo_scenery_t    scenery[256];
 
// first tilemap
 
unsigned short  backtiles[80][80];
 
// second tilemap
 
unsigned short  foretiles[80][80];
 
// contents map - a contents value for each static tile (in game they get overriden by switchable tiles if presented)
 
// see CONTENTS_ defines for possible content values
 
byte            contents[80][80];
 
// linear triggers array - all triggers used on map
 
bo_trigger_t    triggers[255];
 
// triggers are non-solid interaction points, activated when player stands in them
 
// this array golds pointers to triggers
 
byte            triggertiles[80][80];
 
// items placed on level
 
// itemcodes 0-9 are powerups, codes 10, 11, 12, 13 reserved for unique item codes
 
// so there will be not more than 4 unique item type per level
 
// unique items are: spells, weapons, forms, artifacts, tokens
 
byte            uniqueitems[4];
 
bo_item_t      items[50];
 
// yet unknown data
 
byte            u4[8];
 
byte            u5[8][40];
 
byte            u6[24];
 
// effects
 
unsigned short  sprites[8];
 
bo_effect_t    effects[64];
 
// yet unknown data
 
unsigned char  u7[936];
 
}bo_map_t;
 
 
// things that are not figured out yet:
 
// - how lightning is done (variable form lights, day-night light, ambient light)
 
// - monster's paths's switch (some paths are messed up)
 
// - counters and puzzle triggers?
 
 
// tileflags
 
#define TILEFLAG_UNKNOWN1      1024
 
#define TILEFLAG_NODRAW        2048
 
#define TILEFLAG_UNKNOWN3      4096
 
#define TILEFLAG_UNKNOWN4      8192
 
#define TILEFLAG_ALWAYSONTOP    16384
 
#define TILEFLAG_UNKNOWN6      32768
 
#define TILEFLAG_MASK          (1024 + 2048 + 4096 + 8192 + 16384 + 32768)
 
#define TILEFLAG_IMASK          (1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 + 256 + 512)
 
 
// contents
 
#define CONTENTS_SOLID          1
 
#define CONTENTS_WATER          2
 
#define CONTENTS_LAVA          3
 
#define CONTENTS_FIRE          4
 
#define CONTENTS_SPIKES        5
 
#define CONTENTS_TRAPTELEPORT  6
 
#define CONTENTS_JUMPWALL      8
 
#define CONTENTS_SWAMP          11
 
#define CONTENTS_JUMPFENCE      10
 
#define CONTENTS_MISTWALK      12
 
#define CONTENTS_SACRIFICE      13
 
#define CONTENTS_ICE            19
 
#define CONTENTS_SAVEGAME      44
 
#define CONTENTS_BATMARK        45
 
 
// triggers
 
#define TRIGGER_EXIT            1
 
#define TRIGGER_ENTRANCE        2
 
#define TRIGGER_SPEECHMARK      3
 
#define TRIGGER_TOUCH          4
 
#define TRIGGER_TELEPORT        6
 
#define TRIGGER_IMAGEMARK      7
 
 
// button flags
 
#define BUTTONFLAG_TOGGLE 1
 
#define BUTTONFLAG_SECRET      2
 
 
// item codes
 
#define MAPITEM_SMALLBLOODFLASK 1
 
#define MAPITEM_BLOODFLASK      2
 
#define MAPITEM_RUNEPYRAMID    3
 
#define MAPITEM_PURPLESPHERE    4
 
#define MAPITEM_BLUESPHERE      5
 
#define MAPITEM_GREENSPHERE    6
 
#define MAPITEM_GOLDSPHERE      7
 
#define MAPITEM_REDSPHERE      8
 
#define MAPITEM_ANCIENTVIAL    9
 
#define MAPITEM_UNIQUE1        10 // unique item codes
 
#define MAPITEM_UNIQUE2        11 // unique item codes
 
#define MAPITEM_UNIQUE3        12 // unique item codes
 
#define MAPITEM_UNIQUE4        13 // unique item codes
 
 
// real item codes
 
#define ITEM_SPELL_INSPIREHATE  10
 
#define ITEM_SPELL_STUN        11
 
#define ITEM_SPELL_SPIRITWRACK  12
 
#define ITEM_SPELL_BLOODGOUT    13
 
#define ITEM_SPELL_BLOODSHOWER  14
 
#define ITEM_SPELL_SPIRITDEATH  15
 
#define ITEM_SPELL_LIGHT        16
 
#define ITEM_SPELL_LIGHTNING    17
 
#define ITEM_SPELL_REPEL        18
 
#define ITEM_SPELL_ENERGYBOLT  19
 
#define ITEM_SPELL_INCAPACITATE 20
 
#define ITEM_SPELL_CONTROLMIND  21
 
#define ITEM_SPELL_SANCTUARY    22
 
#define ITEM_ARTIFACT_FLAY      23
 
#define ITEM_ARTIFACT_PENTALICH 24
 
#define ITEM_ARTIFACT_IMPLODE  25
 
#define ITEM_ARTIFACT_FONT      26
 
#define ITEM_ARTIFACT_BANK      27
 
#define ITEM_ARTIFACT_HEART    28
 
#define ITEM_ARTIFACT_ANTITOXIN 29
 
#define ITEM_ARTIFACT_SLOWTIME  30
 
#define ITEM_TOKEN_MOEBIUS      31
 
#define ITEM_TOKEN_DEJOULE      32
 
#define ITEM_TOKEN_DOLL        33
 
#define ITEM_TOKEN_MALEK        34
 
#define ITEM_TOKEN_AZIMUTH      35
 
#define ITEM_TOKEN_MORTANIUS    36
 
#define ITEM_TOKEN_NUPRAPTOR    37
 
#define ITEM_TOKEN_BANE        38
 
#define ITEM_TOKEN_SIGNETRING  39
 
#define ITEM_TOKEN_TIMEDEVICE  40
 
#define ITEM_TOKEN_ANACROTHE    41
 
#define ITEM_WEAPON_MACE        43
 
#define ITEM_WEAPON_AXES        44
 
#define ITEM_WEAPON_FLAMESWORD  45
 
#define ITEM_WEAPON_SOULREAVER  46
 
#define ITEM_ARMOR_BONE        48
 
#define ITEM_ARMOR_CHAOS        49
 
#define ITEM_ARMOR_FLESH        50
 
#define ITEM_ARMOR_WRAITH      51
 
#define ITEM_FORM_BAT          53
 
#define ITEM_FORM_WOLF          54
 
#define ITEM_FORM_DISGUISE      55
 
#define ITEM_FORM_MIST          56
 
#define ITEM_ENDING_1          69
 
#define ITEM_ENDING_2          70
 

Revision as of 11:42, 22 November 2012

This page is dedicated to file formats used to store resources fo Blood Omen. It encompasses exploring work done by the community since Blood Omen was released.

Most basic formats - such as .BIG file structure, TIM specs, were unveiled long time ago, but some ones (map format, sprites) was unveiled lately during Blood Pill utility development.

Contents

Compression methods

Index-based RLE

Used on sprite data to compress black areas which is normally transparent. This technique alters reading process of byte 0x0 and 0xFF. If got this byte when reading picture data, should read 1 byte more which will be times to repeat this byte.

Example:

// output 32 bytes with value 0xFF
0xFF 0x20

4-bit images

Encode 2 pixels per byte with 256 color palette but with only 16 colors used (other pixels are black).

For each byte it produces 2 bytes in order:

  • byte 1 : <byte> - (int)(<byte>/16)*16; // <byte> mod 16
  • byte 2 : (int)(<byte>/16) // <byte> div 16

Example:

 231 will output 2 pixels with values:
 byte 1 : 7
 byte 2 : 14

Variation of LZ77

A variation of the LZ77 (LZ1) data compression algorithms.

Example decoder can be found at The Lost Worlds and Blood Pill sourcecode.

BIG file

This is general file storing all game resources. It's structure is quite simple:

uint32 - number of entries
Array of entries:
  uint32 - Hashed name of file
  uint32 - File size
  uint32 - File offset
Array of entry data:
  bytes - File contents

Tricks:

  • There can be gaps between files

TIM image

Playstation images. Used to store graphics and tiles. TIM specs are widely known, so it will be not listed here. Reference decoder/encoder can be found at Blood Pill sourcecode.

Tricks:

  • Some pill.big entries can contain several TIM's glued together.
  • Some blood omen TIM files can contain tails with nulls.

Sounds

VAG

Playstation's 4bit Very-Audio-Good files (ADPCM variation) used in blood omen playstation version and by blood omen sneak peek preview. In PC versino they are unused. Reference decoder/encoder can be found at Blood Pill sourcecode.

Tricks:

  • Many VAG files are headerless (having mess in the header, even no 'VAGb' fourCC, hence could only be detected by direct parsing).
  • Normally should be played at 11025hz, but some ones (music and some sounds) at 22050hz

RAW IMA ADPCM

Headerless files containing raw IMA ADPCM stream to replaces VAG files in PC version. They are using exactly same file names as VAG files in playstation version.

Tricks:

  • Files have no header at all

Waveform Audio File

Blood Omen PC version have some sounds in .WAV format (playstation have them in .VAG). This format is widely known and does not need to be explained.

Tricks:

  • It seems game doesnt use WAV headers, some file have bogus play rate and should be tweaked manually to play with correct rate thay listened in game

Sprites

Sprites are images of characters and animated stuff. There are 3 extensions as of filenames: SHA, SDR, SHD. However, when Blood Pill was developed, there were no knowledge of real file names, so this spec will define "Sprite types" which covers unpacking of all sprites, including unused ones.

Sprite type 1

Item cards. Always have 1 frame and no compression used.

uint32 - always 0x01 0x00 0x00 0x00 
uint32 - file size
768 bytes - 24-bit colormap data (256 colors)
int16 - x position
int16 - y position
byte - width
byte - height
byte - x
byte - y
width*height bytes - picture contents (indexes into colormap)

Tricks:

  • Really, it is simplified sprite type 3

Sprite type 2

Multiframe sprite with per-frame palette. Used by interface images collection.

uint32 - number of frames
uint32 - file size
768 bytes - 24-bit colormap data (unused)
Array of frame headers:
  768 bytes - 24-bit colormap data
  uint32 - offset to the picture data from the end of headers
  ubyte - width
  ubyte - height
  byte - x
  byte - y
Array of frame picture data:
  width*height bytes - picture contents (indexes into colormap)

Tricks:

  • In some files real width/height may be double of what written in header

Sprite type 3

Multiframe sprite with shared palette.

uint32 - number of frames
uint32 - file size
768 bytes - 24-bit colormap data
int16 - x offset for all frames
int16 - y offset for all frames
Array of frame headers:
  uint32 - offset to the picture data from the end of headers
  ubyte - width
  ubyte - height
  byte - x
  byte - y
Array of frame picture data:
  variable bytes - compressed picture contents (indexes into colormap) using Index-based RLE, some files using 4-bit color

Tricks:

  • It is unknown how to get what compression file do use (Index-based in 0x00, or 0xFF or both), it seems engine gives that info when file get loaded
  • Some files are using 4-bit color instead of Index-based compression

Sprite type 4

Multiframe sprite with shared palette, with additional frames headers. Used by actor sprites and effects. Pretty same as type 3.

uint32 - number of frames
uint32 - file size
Array of additional frame headers (rounded to the greatest multiplier of 4):
   byte - unknown info
768 bytes - 24-bit colormap data
int16 - x offset for all frames
int16 - y offset for all frames
Array of frame headers:
  uint32 - offset to the picture data from the end of headers
  ubyte - width
  ubyte - height
  byte - x
  byte - y
Array of frame picture data:
  variable bytes - compressed picture contents (indexes into colormap) using Index-based RLE, some files using 4-bit color

Tricks:

  • It is unknown how to get what compression file do use (Index-based in 0x00, or 0xFF or both), it seems engine gives that info when file get loaded
  • Some files are using 4-bit color instead of Index-based compression

Sprite type 5

Another variation of type 3 with no offset info and (sometimes) broken width/height, which should be fixed with special trick.

uint32 - number of frames
uint32 - file size
768 bytes - 24-bit colormap data
Array of frame headers:
  uint32 - offset to the picture data from the end of headers
  ubyte - width
  ubyte - height
  byte - x
  byte - y
Array of frame picture data:
  variable bytes - compressed picture contents (indexes into colormap) using Index-based RLE

Tricks:

  • Some frames have broken width/height because they width is above 255 and format uses 1 byte to encode it, 255 + [width] should be used to correct this
  • It is unknown how to get what compression file do use (Index-based in 0x00, or 0xFF or both), it seems engine gives that info when file get loaded

Maps

Maps are central thing which brings all resources (images, sounds, tiles, sprites) together. There is about 80% of map structure revealed, allowing to extract general amount of things from it, including: textures used, a map image, monster/effect/item placement, triggers, info marks, doors and buttons etc.

Each map has a mapnum and section that is included in filename. That info is used to place map in a global adventure map (see TheLost Worlds - May survey for complete info about level naming).

Tiles

Tiles are 256-color TIM images compressed with LZ77 (see #Compression methods)).

Each tile texture has 8x8 = 64 tiles. Engine renders all tile separately, switching current tile texture as needed.

uint32 - compressed data size
variable bytes - compressed data

Tricks:

  • Since all tiles are 8-bit 256x256 TIM, unpacked data size is always same

Map file

Map file is fixed-length structure which holds tiles placement (80x80), enemies, lights, buttons and other objects to form Blood Omen level. Because of it's fixed nature, there are many limits, and each map file have exactly same size (so it can just be copied into memory).

Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox