Editing Blood Omen file formats

Jump to: navigation, search

Warning: You are not logged in.

Your IP address will be recorded in this page's edit history.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
{{TOCRIGHT}}
+
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.  
This page is dedicated to the specifications for file formats used in Blood Omen. It encompasses exploring work done by the community since Blood Omen was released.  
+
  
Most simple 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]] development.
+
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.
 +
 
 +
==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:
 +
 
 +
<span style="color:green">// output 32 bytes with value 0xFF</span>
 +
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; <span style="color:green">// <byte> mod 16</span>
 +
* byte 2 : (int)(<byte>/16) <span style="color:green">// <byte> div 16</span>
 +
 
 +
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 [http://www.thelostworlds.net/Software/Blood_Omen_Decompressor.html The Lost Worlds] and [[Blood Pill]] sourcecode.
  
 
==BIG file==
 
==BIG file==
Line 15: Line 43:
 
   '''bytes''' - File contents
 
   '''bytes''' - File contents
  
{{tip|There can be gaps between files}}
+
Tricks:
 +
* There can be gaps between files
  
 
==TIM image==
 
==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 [https://github.com/paulvortex/BloodPill/blob/master/src/timfile.cpp here].
+
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.
  
'''Tips''':
+
Tricks:
 
* Some pill.big entries can contain several TIM's glued together.
 
* Some pill.big entries can contain several TIM's glued together.
 
* Some blood omen TIM files can contain tails with nulls.
 
* Some blood omen TIM files can contain tails with nulls.
Line 27: Line 56:
  
 
===VAG===
 
===VAG===
Playstation's Very-Audio-Good files (4-bit ADPCM variation) used in blood omen playstation version and by blood omen sneak peek preview. Unused in PC version. Reference decoder/encoder can be found [https://github.com/paulvortex/BloodPill/blob/master/src/vagfile.cpp here].
+
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.
  
'''Tips''':
+
Tricks:
 
* Many VAG files are headerless (having mess in the header, even no 'VAGb' fourCC, hence could only be detected by direct parsing).
 
* 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
 
* Normally should be played at 11025hz, but some ones (music and some sounds) at 22050hz
Line 36: Line 65:
 
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.
 
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.
  
{{tip|Files have no header at all}}
+
Tricks:
 +
* Files have no header at all
  
 
===Waveform Audio File===
 
===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.
 
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.
  
{{tip|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}}
+
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
==Video==
+
 
+
===PSX STR===
+
Used in Blood Omen PlayStation version. STR is MJPEG video stream with interleaved audio. [http://kenai.com/projects/jpsxdec/pages/Home jPsxDec] tool could be used to extract and decode this format from playstation CD images.
+
 
+
===JAM Videos===
+
JAM is lossy video compression format developed by Semilogic entertainment and used in Blood Omen PC version. The format uses shared palette for several frames and a form of dynamic compression. JAM spec and decoder was unveiled in 2011 by MisterGrim. JAM can only store video, audio was stored in separate .VAG file (which was for real, raw IMA ADPCM).
+
 
+
JAM videos have much more artifacts than STR, sound track is mono (STR have stereo).
+
 
+
JAM decompressing code can be found [https://github.com/paulvortex/BloodPill/blob/master/src/jamfile.cpp here]
+
  
 
==Sprites==
 
==Sprites==
Line 59: Line 78:
 
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.
 
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===
+
===Sprite type 1===
Always have 1 frame and no compression used.  
+
Item cards. Always have 1 frame and no compression used.  
  
 
  '''uint32''' - always 0x01 0x00 0x00 0x00  
 
  '''uint32''' - always 0x01 0x00 0x00 0x00  
Line 73: Line 92:
 
  '''width*height bytes''' - picture contents (indexes into colormap)
 
  '''width*height bytes''' - picture contents (indexes into colormap)
  
{{tip|Really, it is simplified sprite type 3}}
+
Tricks:
 +
* Really, it is simplified sprite type 3
  
===Sprite type 2 - Images collection===
+
===Sprite type 2===
Multiframe sprite with per-frame palette. Used by interface images collections (such as spell/item pics).
+
Multiframe sprite with per-frame palette. Used by interface images collection.
  
 
  '''uint32''' - number of frames
 
  '''uint32''' - number of frames
Line 91: Line 111:
 
   '''width*height bytes''' - picture contents (indexes into colormap)
 
   '''width*height bytes''' - picture contents (indexes into colormap)
  
{{tip|In some files real width/height may be double of what written in header}}
+
Tricks:
 +
* In some files real width/height may be double of what written in header
  
===Sprite type 3 - Object sprites===
+
===Sprite type 3===
 
Multiframe sprite with shared palette.
 
Multiframe sprite with shared palette.
  
Line 108: Line 129:
 
   '''byte''' - y
 
   '''byte''' - y
 
  <span style="color:green">Array of frame picture data:</span>
 
  <span style="color:green">Array of frame picture data:</span>
   '''bytes''' - compressed picture contents (indexes into colormap) using run-length encodingE, some files using 4-bit color (see [[#Compression methods]])
+
   '''variable bytes''' - compressed picture contents (indexes into colormap) using Index-based RLE, some files using 4-bit color
  
'''Tips''':
+
Tricks:
* It is unknown how to get what compression file do use (RLE on 0x00, or 0xFF or both), it seems engine gives that info when file get loaded
+
* 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 RLE
+
* Some files are using 4-bit color instead of Index-based compression
  
===Sprite type 4 - character sprites===
+
===Sprite type 4===
Multiframe sprite with shared palette, with additional frames headers. Used by characters. Pretty same as type 3.
+
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''' - number of frames
 
  '''uint32''' - file size
 
  '''uint32''' - file size
 
  <span style="color:green">Array of additional frame headers (rounded to the greatest multiplier of 4):</span>
 
  <span style="color:green">Array of additional frame headers (rounded to the greatest multiplier of 4):</span>
     '''byte''' - damage mark. A value of 1 tell the game to deal damage in this frame.
+
     byte - unknown info
 
  '''768 bytes''' - 24-bit colormap data
 
  '''768 bytes''' - 24-bit colormap data
 
  '''int16''' - x offset for all frames
 
  '''int16''' - x offset for all frames
Line 131: Line 152:
 
   '''byte''' - y
 
   '''byte''' - y
 
  <span style="color:green">Array of frame picture data:</span>
 
  <span style="color:green">Array of frame picture data:</span>
   '''bytes''' - compressed picture contents (indexes into colormap) using run-length encoding, some files using 4-bit color (see [[#Compression methods]])
+
   '''variable bytes''' - compressed picture contents (indexes into colormap) using Index-based RLE, some files using 4-bit color
  
'''Tips''':
+
Tricks:
* It is unknown how to get what compression file do use (RLE on 0x00, or 0xFF or both), it seems engine gives that info when file get loaded
+
* 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 RLE
+
* Some files are using 4-bit color instead of Index-based compression
  
 
===Sprite type 5===
 
===Sprite type 5===
Line 150: Line 171:
 
   '''byte''' - y
 
   '''byte''' - y
 
  <span style="color:green">Array of frame picture data:</span>
 
  <span style="color:green">Array of frame picture data:</span>
   '''bytes''' - compressed picture contents (indexes into colormap) using RLE (see [[#Compression methods]])
+
   '''variable bytes''' - compressed picture contents (indexes into colormap) using Index-based RLE
  
'''Tips''':
+
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
 
* 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 (RLE on 0x00, or 0xFF or both), it seems engine gives that info when file get loaded
+
* 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==
Line 163: Line 184:
  
 
=== Tiles ===
 
=== Tiles ===
Tiles are 256-color TIM images compressed with LZ77 (see [[#Compression methods]]).
+
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.
 
Each tile texture has 8x8 = 64 tiles. Engine renders all tile separately, switching current tile texture as needed.
  
 
  '''uint32''' - compressed data size
 
  '''uint32''' - compressed data size
  '''bytes''' - compressed data
+
  '''variable bytes''' - compressed data
  
'''Tips''':
+
Tricks:
* Since all tiles are 8-bit 256x256 TIM, unpacked data size is always same
+
* Since all tiles are 8-bit 256x256 TIM, unpacked data size is always same  
  
 
=== Map file ===
 
=== Map file ===
Line 177: Line 198:
 
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).
  
<span style="color:green">// blood omen map structure</span>
+
// blood omen map structure
<span style="color:#7f0055; font-weight:bold; ">typedef</span> <span style="color:#7f0055; font-weight:bold; ">struct</span>
+
typedef struct  
{
+
{
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> parm1;    <span style="color:green">// first parm, if script is not defined it"s 0xFFFF, 0xFFFE is null value</span>
+
unsigned short parm1;    // first parm, if script is not defined it's 0xFFFF, 0xFFFE is null value
                        <span style="color:green">//  - destination/source map number (TRIGGER_EXIT, TRIGGER_ENTRANCE, TRIGGER_TELEPORT)</span>
+
                        //  - destination/source map number (TRIGGER_EXIT, TRIGGER_ENTRANCE, TRIGGER_TELEPORT)
                        <span style="color:green">//  - speech num (TRIGGER_INFOMARK, TRIGGER_IMAGEMARK)</span>
+
                        //  - speech num (TRIGGER_INFOMARK, TRIGGER_IMAGEMARK)
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> parm2;    <span style="color:green">// second parm:</span>
+
unsigned short parm2;    // second parm:
                        <span style="color:green">//  - button num (TRIGGER_BUTTON)</span>
+
                        //  - button num (TRIGGER_BUTTON)
                        <span style="color:green">//  - pic num (TRIGGER_IMAGEMARK)</span>
+
                        //  - pic num (TRIGGER_IMAGEMARK)
byte          parm3;    <span style="color:green">// destination/source map section (TRIGGER_EXIT, TRIGGER_ENTRANCE, TRIGGER_TELEPORT)</span>
+
byte          parm3;    // destination/source map section (TRIGGER_EXIT, TRIGGER_ENTRANCE, TRIGGER_TELEPORT)
byte          srcx;    <span style="color:green">// sposition</span>
+
byte          srcx;    // sposition
byte          srcy;    <span style="color:green">// sposition</span>
+
byte          srcy;    // sposition
byte          type;    <span style="color:green">// script type, one of TRIGGER_</span>
+
byte          type;    // script type, one of TRIGGER_
byte          u2[3];    <span style="color:green">// ?</span>
+
byte          u2[3];    // ?
byte          x;        <span style="color:green">// position</span>
+
byte          x;        // position
byte          y;        <span style="color:green">// position</span>
+
byte          y;        // position
byte          u3[3];    <span style="color:green">// ?</span>
+
byte          u3[3];    // ?
}bo_trigger_t;
+
}bo_trigger_t;
+
<span style="color:#7f0055; font-weight:bold; ">typedef</span> <span style="color:#7f0055; font-weight:bold; ">struct</span>
+
{
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> savenum;  <span style="color:green">// unique savegame id</span>
+
byte          itemcode; <span style="color:green">// one of MAPITEM_ code</span>
+
byte          x;        <span style="color:green">// position</span>
+
byte          y;        <span style="color:green">// position</span>
+
byte          hidden;  <span style="color:green">// set to 1 if item is spawned by trigger (like barrel destruction)</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> target;  <span style="color:green">// targeted triggergroup</span>
+
byte          u[4];    <span style="color:green">// ?</span>
+
}bo_item_t;
+
+
<span style="color:#7f0055; font-weight:bold; ">typedef</span> <span style="color:#7f0055; font-weight:bold; ">struct</span>
+
{
+
    <span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> targetnum;<span style="color:green">// a triggergroup</span>
+
byte x;                  <span style="color:green">// position</span>
+
byte u1;                <span style="color:green">// ?</span>
+
byte y;                  <span style="color:green">// position</span>
+
byte u2;                <span style="color:green">// ?</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> tile1;    <span style="color:green">// tilenum</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> tile2;    <span style="color:green">// alternate state tilenum</span>
+
byte contents1;          <span style="color:green">// contents, see CONTENTS_ defines for possible content values</span>
+
byte contents2;          <span style="color:green">// alternate state contents</span>
+
byte u3[12];            <span style="color:green">// ?</span>
+
}bo_atile_t;
+
+
<span style="color:#7f0055; font-weight:bold; ">typedef</span> <span style="color:#7f0055; font-weight:bold; ">struct</span>
+
{
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> target;  <span style="color:green">// a triggergroup to call</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> tile1;    <span style="color:green">// tilenum</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> tile2;    <span style="color:green">// alternate state tilenum</span>
+
byte flags;              <span style="color:green">// see BUTTONFLAG_* defs</span>
+
byte u1;                <span style="color:green">// ?</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> savenum;  <span style="color:green">// unique savegame id</span>
+
byte u2;                <span style="color:green">// ?</span>
+
byte u3;                <span style="color:green">// ?</span>
+
}bo_button_t;
+
+
<span style="color:#7f0055; font-weight:bold; ">typedef</span> <span style="color:#7f0055; font-weight:bold; ">struct</span>
+
{
+
byte x;                  <span style="color:green">// position</span>
+
byte y;                  <span style="color:green">// position</span>
+
byte lightposx;          <span style="color:green">// position of lightsource</span>
+
byte lightposy;          <span style="color:green">// position of lightsource</span>
+
byte sprite;            <span style="color:green">// index of sprite from sprites array</span>
+
byte lightheight;        <span style="color:green">// height (for lightsource)</span>
+
byte lightwidth;        <span style="color:green">// width (for lightsource)</span>
+
byte flags;              <span style="color:green">// effect flags</span>
+
byte lightflags;        <span style="color:green">// light flags</span>
+
byte r;                  <span style="color:green">// red color component</span>
+
byte g;                  <span style="color:green">// green color component</span>
+
byte b;                  <span style="color:green">// blue color component</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> targetnum;<span style="color:green">// triggergroup</span>
+
byte start_on;          <span style="color:green">// 1 if effect starts on, 0 if starts off</span>
+
byte u3[5];              <span style="color:green">// ?</span>
+
}bo_effect_t;
+
+
<span style="color:#7f0055; font-weight:bold; ">typedef</span> <span style="color:#7f0055; font-weight:bold; ">struct</span>
+
{
+
byte data[164];
+
}bo_object_t;
+
+
<span style="color:#7f0055; font-weight:bold; ">typedef</span> <span style="color:#7f0055; font-weight:bold; ">struct</span>
+
{
+
byte x;                  <span style="color:green">// start position</span>
+
byte y;                  <span style="color:green">// end position</span>
+
byte w;                  <span style="color:green">// width</span>
+
byte h;                  <span style="color:green">// height</span>
+
byte ofsx;              <span style="color:green">// multiply by 16 to get real offset</span>
+
byte ofsy;              <span style="color:green">// multiply by 16 to get real offset</span>
+
byte u1;
+
byte u2;
+
}bo_grpobject_t;
+
+
<span style="color:#7f0055; font-weight:bold; ">typedef</span> <span style="color:#7f0055; font-weight:bold; ">struct</span>
+
{
+
byte u1;                <span style="color:green">// ?</span>
+
byte u2;                <span style="color:green">// ?</span>
+
byte u3;                <span style="color:green">// ?</span>
+
byte u4;                <span style="color:green">// ?</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> tile1;    <span style="color:green">// base tile (grpobject really, not standart 32x32 tile)</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> tile2;    <span style="color:green">// toggled tile (grpobject)</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> tile3;    <span style="color:green">// destroyed tile (grpobject)</span>
+
byte u5;                <span style="color:green">// ?</span>
+
byte u6;                <span style="color:green">// ?</span>
+
byte pushable;          <span style="color:green">// a strength required to push</span>
+
byte toggled;            <span style="color:green">// trigger can toggle it"s state (means tile2 is there)</span>
+
byte u7;                <span style="color:green">// ?</span>
+
byte spawnitems[3];      <span style="color:green">// item codes to spawn when toggled/destroyed</span>
+
byte u8;                <span style="color:green">// ?</span>
+
byte destructible;      <span style="color:green">// destructible flags</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> savenum;  <span style="color:green">// unique savegame id</span>
+
byte u10;                <span style="color:green">// ?</span>
+
byte x;                  <span style="color:green">// position</span>
+
byte y;                  <span style="color:green">// position</span>
+
byte u11;                <span style="color:green">// ? </span>
+
byte active;            <span style="color:green">// 1 is filled, otherwise 0</span>
+
byte u13;                <span style="color:green">// ? </span>
+
}bo_scenery_t;
+
+
<span style="color:#7f0055; font-weight:bold; ">typedef</span> <span style="color:#7f0055; font-weight:bold; ">struct</span>
+
{
+
byte x;                  <span style="color:green">// position</span>
+
byte y;                  <span style="color:green">// position</span>
+
byte u1;                <span style="color:green">// ?</span>
+
byte u2;                <span style="color:green">// ?</span>
+
}bo_path_t;
+
+
<span style="color:#7f0055; font-weight:bold; ">typedef</span> <span style="color:#7f0055; font-weight:bold; ">struct</span>
+
{
+
bo_path_t paths[4];      <span style="color:green">// patrole paths</span>
+
byte u1[12];            <span style="color:green">// ?</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> savenum;  <span style="color:green">// unique savegame id</span>
+
byte u2[52];            <span style="color:green">// ?</span>
+
byte charnum;            <span style="color:green">// monster class (same as char* sprite)</span>
+
byte u3[10];            <span style="color:green">// ?</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> target;  <span style="color:green">// triggergroup to call once killed</span>
+
byte u4[20];            <span style="color:green">// ?</span>
+
byte lastpath;          <span style="color:green">// ?</span>
+
byte u6[18];            <span style="color:green">// ?</span>
+
byte u7[15];            <span style="color:green">// ?</span>
+
byte x;                  <span style="color:green">// position</span>
+
byte y;                  <span style="color:green">// position</span>
+
byte u8[4];              <span style="color:green">// ?</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span> speechnum;<span style="color:green">// a speech number for disguise talk</span>
+
byte u9[6];              <span style="color:green">// ?</span>
+
}bo_monster_t;
+
+
<span style="color:#7f0055; font-weight:bold; ">typedef</span> <span style="color:#7f0055; font-weight:bold; ">struct</span>
+
{
+
<span style="color:green">// a chain of tilemap numbers used (to make a filenames)</span>
+
<span style="color:green">// each tilemap holds 64 tiles, tiles numbering is linear</span>
+
<span style="color:green">// like, a tile #131 is tile #3 from tilemap #2</span>
+
<span style="color:green">// being 2-byte (unsigned short) tilenum contains some flags (flag are starting from byte 10)</span>
+
<span style="color:green">// see TILEFLAG_ defines for possible tileflags</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span>  tilemaps[40];
+
byte            u1[12]; <span style="color:green">// yet unknown info</span>
+
bo_object_t    objects[10];
+
bo_monster_t    monsters[32];
+
bo_grpobject_t  grpobjects[8][32];
+
<span style="color:green">// animated tiles - a tiles that can be toggled between 2 states and have different contents for each state</span>
+
<span style="color:green">// used on doors, spikes that pops up on the floor etc.</span>
+
<span style="color:green">// animated tiles have triggergroup to be executed by script</span>
+
bo_atile_t      atiles[100];
+
<span style="color:green">// a special buttons array holds all buttons used on level</span>
+
<span style="color:green">// pretty similar to animated tiles</span>
+
<span style="color:green">// buttons have triggergroup to be executed by script</span>
+
bo_button_t    buttons[20];
+
<span style="color:green">// yet unknown info #2</span>
+
byte            u2[8];
+
<span style="color:green">// scenery pushable objects - tables, chairs, stones etc.</span>
+
bo_scenery_t    scenery[256];
+
<span style="color:green">// first tilemap</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span>  backtiles[80][80];
+
<span style="color:green">// second tilemap</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span>  foretiles[80][80];
+
<span style="color:green">// contents map - a contents value for each static tile (in game they get overriden by switchable tiles if presented)</span>
+
<span style="color:green">// see CONTENTS_ defines for possible content values</span>
+
byte            contents[80][80];
+
<span style="color:green">// linear triggers array - all triggers used on map</span>
+
bo_trigger_t    triggers[255];
+
<span style="color:green">// triggers are non-solid interaction points, activated when player stands in them</span>
+
<span style="color:green">// this array golds pointers to triggers</span>
+
byte            triggertiles[80][80];
+
<span style="color:green">// items placed on level</span>
+
<span style="color:green">// itemcodes 0-9 are powerups, codes 10, 11, 12, 13 reserved for unique item codes</span>
+
<span style="color:green">// so there will be not more than 4 unique item type per level</span>
+
<span style="color:green">// unique items are: spells, weapons, forms, artifacts, tokens</span>
+
byte            uniqueitems[4];
+
bo_item_t      items[50];
+
<span style="color:green">// yet unknown data</span>
+
byte            u4[8];
+
byte            u5[8][40];
+
byte            u6[24];
+
<span style="color:green">// effects</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">short</span>  sprites[8];
+
bo_effect_t    effects[64];
+
<span style="color:green">// map general info</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">char</span>  u61;
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">char</span>  environments; <span style="color:green">// 0 is outdoor, 1 is indoor</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">char</span>  ambientcolor[3]; <span style="color:green">// rgb format, 15 15 15 is white, 31 31 31 is double white</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">char</span>  songnum; <span style="color:green">// 0 is oracle caves</span>
+
                        <span style="color:green">// 1 is mausoleum</span>
+
                        <span style="color:green">// 2 is awakening</span>
+
                        <span style="color:green">// 3 is road to vengeance</span>
+
                        <span style="color:green">// 4 is nupraptor</span>
+
                        <span style="color:green">// 5 is maleks bastion</span>
+
                        <span style="color:green">// 6 is voradors mansion</span>
+
                        <span style="color:green">// 7 is dark eden</span>
+
                        <span style="color:green">// 8 is solemn dirge</span>
+
                        <span style="color:green">// 9 is avernus </span>
+
                        <span style="color:green">// 10 is elzevir</span>
+
<span style="color:green">// yet unknown info #7</span>
+
<span style="color:#7f0055; font-weight:bold; ">unsigned</span> <span style="color:#7f0055; font-weight:bold; ">char</span>  u7[930];
+
}bo_map_t;
+
+
<span style="color:green">// things that are not figured out yet:</span>
+
<span style="color:green">// - how lightning is done (variable form lights, day-night light, ambient light)</span>
+
<span style="color:green">// - monster"s paths"s switch (some paths are messed up)</span>
+
<span style="color:green">// - counters and puzzle triggers?</span>
+
+
<span style="color:green">// map environments</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ENVIRONMENTS_OUTDOOR    0</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ENVIRONMENTS_INDOOR    1</span>
+
+
<span style="color:green">// tileflags</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TILEFLAG_UNKNOWN1      1024</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TILEFLAG_NODRAW        2048</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TILEFLAG_ONTOPINFRONT  4096</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TILEFLAG_ALWAYSBELOW    8192</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TILEFLAG_ALWAYSONTOP    16384</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TILEFLAG_UNKNOWN6      32768</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TILEFLAG_MASK          </span><span style="color:#7f0055; ">(</span><span style="color:#7f0055; ">1024 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 2048 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 4096 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 8192 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 16384 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 32768</span><span style="color:#7f0055; ">)</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TILEFLAG_IMASK          </span><span style="color:#7f0055; ">(</span><span style="color:#7f0055; ">1 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 2 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 4 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 8 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 16 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 32 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 64 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 128 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 256 </span><span style="color:#7f0055; ">+</span><span style="color:#7f0055; "> 512</span><span style="color:#7f0055; ">)</span>
+
+
<span style="color:green">// contents</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_NONE          0</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_SOLID          1</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_WATER          2</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_LAVA          3</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_FIRE          4</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_SPIKES        5</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_TRAPTELEPORT  6</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_JUMPWALL      8</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_SWAMP          11</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_JUMPFENCE      10</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_MISTWALK      12</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_SACRIFICE      13</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_ICE            19</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_SAVEGAME      44</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> CONTENTS_BATMARK        45</span>
+
+
<span style="color:green">// triggers</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TRIGGER_EXIT            1</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TRIGGER_ENTRANCE        2</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TRIGGER_SPEECHMARK      3</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TRIGGER_TOUCH          4</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TRIGGER_TELEPORT        6</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> TRIGGER_IMAGEMARK      7</span>
+
+
<span style="color:green">// button flags</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> BUTTONFLAG_TOGGLE 1</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> BUTTONFLAG_SECRET      2</span>
+
+
<span style="color:green">// effect flags</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> LIGHTFLAG_FIRE        2  </span><span style="color:green">// fire damage</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> LIGHTFLAG_THUNDER      4  </span><span style="color:green">// thunder light</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> LIGHTFLAG_X            8</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> LIGHTFLAG_FORWARD      16  </span><span style="color:green">// spot light orientation, vertical lightsize sets number of steps, horizontal size sets starting step size</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> LIGHTFLAG_BACK        32  </span><span style="color:green">// spot light orientation, vertical lightsize sets number of steps, horizontal size sets starting step size</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> LIGHTFLAG_RIGHT        64  </span><span style="color:green">// spot light orientation, vertical lightsize sets number of steps, horizontal size sets starting step size</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> LIGHTFLAG_LEFT        128  </span><span style="color:green">// spot light orientation, vertical lightsize sets number of steps, horizontal size sets starting step size</span>
+
+
<span style="color:green">// light flags (possible light flags - 4 or 6)</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> EFFECTFLAG_DYNAMIC      1  </span><span style="color:green">// dynamic light adds to world light, not replacing it</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> EFFECTFLAG_FLICKER      2  </span><span style="color:green">// flickering light</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> EFFECTFLAG_LIGHT        4  </span><span style="color:green">// has light</span>
+
+
<span style="color:green">// item codes</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_SMALLBLOODFLASK 1</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_BLOODFLASK      2</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_RUNEPYRAMID    3</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_PURPLESPHERE    4</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_BLUESPHERE      5</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_GREENSPHERE    6</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_GOLDSPHERE      7</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_REDSPHERE      8</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_ANCIENTVIAL    9</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_UNIQUE1        10 </span><span style="color:green">// unique item codes</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_UNIQUE2        11 </span><span style="color:green">// unique item codes</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_UNIQUE3        12 </span><span style="color:green">// unique item codes</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> MAPITEM_UNIQUE4        13 </span><span style="color:green">// unique item codes</span>
+
+
<span style="color:green">// real item codes</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_INSPIREHATE  10</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_STUN        11</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_SPIRITWRACK  12</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_BLOODGOUT    13</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_BLOODSHOWER  14</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_SPIRITDEATH  15</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_LIGHT        16</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_LIGHTNING    17</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_REPEL        18</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_ENERGYBOLT  19</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_INCAPACITATE 20</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_CONTROLMIND  21</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_SPELL_SANCTUARY    22</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARTIFACT_FLAY      23</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARTIFACT_PENTALICH 24</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARTIFACT_IMPLODE  25</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARTIFACT_FONT      26</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARTIFACT_BANK      27</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARTIFACT_HEART    28</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARTIFACT_ANTITOXIN 29</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARTIFACT_SLOWTIME  30</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_TOKEN_MOEBIUS      31</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_TOKEN_DEJOULE      32</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_TOKEN_DOLL        33</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_TOKEN_MALEK        34</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_TOKEN_AZIMUTH      35</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_TOKEN_MORTANIUS    36</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_TOKEN_NUPRAPTOR    37</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_TOKEN_BANE        38</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_TOKEN_SIGNETRING  39</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_TOKEN_TIMEDEVICE  40</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_TOKEN_ANACROTHE    41</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_WEAPON_MACE        43</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_WEAPON_AXES        44</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_WEAPON_FLAMESWORD  45</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_WEAPON_SOULREAVER  46</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARMOR_BONE        48</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARMOR_CHAOS        49</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARMOR_FLESH        50</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ARMOR_WRAITH      51</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_FORM_BAT          53</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_FORM_WOLF          54</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_FORM_DISGUISE      55</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_FORM_MIST          56</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ENDING_1          69</span>
+
<span style="color:#7f0055; ">#</span><span style="color:#7f0055; ">define</span><span style="color:#7f0055; "> ITEM_ENDING_2          70</span>
+
  
==Compression methods==
+
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;
  
'''Index-based Run Length Encoding (RLE)'''
+
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;
  
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. Blood Omen RLE only used for values 0x00 or 0xFF.
+
typedef struct
   
+
{
Example:
+
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;
  
<span style="color:green">// output 32 bytes with value 0xFF</span>
+
typedef struct
0xFF 0x20
+
{
 +
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;
  
'''4-bit images'''
+
typedef struct
 +
{
 +
byte data[164];
 +
}bo_object_t;
  
Encode 2 pixels per byte with 256 color palette but with only 16 colors used (other pixels are black).
+
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;
  
For each byte it produces 2 bytes in order:
+
typedef struct
* byte 1 : <byte> - (int)(<byte>/16)*16; <span style="color:green">// <byte> mod 16</span>
+
{
* byte 2 : (int)(<byte>/16) <span style="color:green">// <byte> div 16</span>
+
byte u1;                // ?
 
+
byte u2;                // ?
Example:
+
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;
  
  231 will output 2 pixels with values:
+
typedef struct
  byte 1 : 7
+
{
  byte 2 : 14
+
byte x;                  // position
 +
byte y;                  // position
 +
byte u1;                // ?
 +
byte u2;                // ?
 +
}bo_path_t;
  
'''Variation of LZ77'''
+
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;
  
A variation of the LZ77 (LZ1) data compression algorithms.
+
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
  
Sample decoder can be found at [http://www.thelostworlds.net/Software/Blood_Omen_Decompressor.html The Lost Worlds] and [[Blood Pill]] sourcecode.
+
// 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
  
==Credits==
+
// button flags
* Andrey [Rackot] Grachev - Bigfile specs
+
#define BUTTONFLAG_TOGGLE 1
* Pavel [VorteX] Timofeyev - Map file, sprites
+
#define BUTTONFLAG_SECRET      2
* Ben Lincoln - LZ77 decompressor
+
* JAM decoding specs by MisterGrim
+
* Balder and Zench from XentaX forums (www.xentax.com) - IMA ADPCM
+
  
==See also==
+
// item codes
* [[Blood Pill]]
+
#define MAPITEM_SMALLBLOODFLASK 1
* [http://kenai.com/projects/jpsxdec/pages/Home jPsxDec homepage]
+
#define MAPITEM_BLOODFLASK      2
* [http://wiki.qhimm.com/PSX/TIM_file TIM specifications at QHimmWiki]
+
#define MAPITEM_RUNEPYRAMID    3
* [http://www.thelostworlds.net/Software/Blood_Omen_Decompressor.html Blood Omen Decompressor homepage]
+
#define MAPITEM_PURPLESPHERE    4
* [http://www.thelostworlds.net/BO1/Map_Survey.html Blood Omen Map Survey (TheLostWorlds)]
+
#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
  
__NOEDITSECTION__
+
// real item codes
{{finished}}
+
#define ITEM_SPELL_INSPIREHATE  10
{{grammar}}
+
#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

Please note that all contributions to Blood Wiki are considered to be released under the Creative Commons Attribution Share Alike (see BloodWiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

Cancel | Editing help (opens in new window)

This page is a member of 2 hidden categories:

Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox