DO/PRJ

From Dark Omen Wiki

(Difference between revisions)
Jump to: navigation, search
(PRJ Format with converter (not corrected!))
Line 1: Line 1:
 +
__TOC__
 +
 +
----
 +
 +
Titelblatt
 +
 +
----
 +
Conventions and definitions:
Conventions and definitions:
-
“Byte” signifies a 1-byte (8-bit) integer
 
-
“Long” signifies a Big-endian 4-byte (32-bit) integer (i.e. stored as “n¤¤¤”)
 
-
“Array” denotes a literal sequence of characters
 
-
“String” denotes a  sequence of characters ended with a NULL (0x00)
 
-
“¤” signifies a NULL (0x00)
 
-
“•” signifies a space (0x20)
 
 +
"Byte" signifies a 1-byte (8-bit) integer
-
The entry point of Dark Omen’s battle description is the .PRJ-file in each battle’s folder. It is a reasonable hypothesis that “.prj” stands for project, and just as reasonable that the name comes from an experimental phase or structure that happened to become the actual core, or that nobody could bother change the names to something more appropriate. Before delving into it, it is worth noting and keeping in mind that the PRJ format is really more or less a hack and is structurally and internally inconsistent, and contains several unconventional (not to say outright stupid) solutions.
+
"Long" signifies a Big-endian 4-byte (32-bit) integer (i.e. stored as "n¤¤¤")
-
Anyway, Dark Omen battles principally consist of a general description of the level (scene and battle) in the .prj-file, a .BTB-file (“BaTtle Boundaries”?) that specifies the deployment zone, a number of .M3D (“Model 3D”?) model files (the special format used in Dark Omen), and 8-bit 128x128 .BMP textures used by and specified in the M3D models.
+
"Array" denotes a literal sequence of characters
-
The .PRJ-file is structured into a file format identification header and then into ten specialised blocks of binary data. The design of these blocks seems inspired by ignorance-friendly nested-block layouts (such as f.i. the .3DS file format) in that each block is systematically begun with a unique block ID header and block size value, thus apparently allowing blind/ignorant parsing, but since the implementation of the block size value is inconsistent the original Dark Omen code probably employs vanilla forward-parsing.
+
"String" denotes a sequence of characters ended with a NULL (0x00)
-
== Project file general layout ==
+
"¤" signifies a NULL (0x00)
-
{|class="wikitable"
+
"'''•'''" signifies a space (0x20)
 +
 
 +
==The .PRJ Battle Project File Layout==
 +
The entry point of Dark Omen<nowiki>’</nowiki>s battle description is the .PRJ-file in each battle<nowiki>’</nowiki>s folder. It is a reasonable hypothesis that ".prj" stands for project, and just as reasonable that the name comes from an experimental phase or structure that happened to become the actual core, or that nobody could bother change the names to something more appropriate. Before delving into it, it is worth noting and keeping in mind that the PRJ format is really more or less a hack and is structurally and internally inconsistent, and contains several unconventional (not to say outright stupid) solutions.
 +
 
 +
Anyway, Dark Omen battles principally consist of a general description of the level (scene and battle) in the .prj-file, a .BTB-file ("BaTtle Boundaries"?) that specifies the deployment zone, a number of .M3D ("Model 3D"?) model files (the special format used in Dark Omen), and 8-bit 128x128 .BMP textures used by and specified in the M3D models.
 +
 
 +
The .PRJ-file is structured into a file format identification header and then into ten specialised blocks of binary data. The design of these blocks seems inspired by ignorance-friendly nested-block layouts (such as f.i. the .3DS file format) in that each block is systematically begun with a unique block ID header and block size value, thus apparently allowing blind/ignorant parsing, but since ''the implementation of the block size value is inconsistent'' the original Dark Omen code probably employs vanilla forward-parsing.
 +
 
 +
===Project file general layout===
 +
 
 +
{|border="2" cellspacing="0" cellpadding="4" width="100%"
|'''Section'''
|'''Section'''
-
|
+
|&nbsp;
|'''Notes'''
|'''Notes'''
 +
|-
|-
|1
|1
-
|“Dark·Omen·Battle·file·1.10······”
+
|"Dark'''•'''Omen'''•'''Battle'''•'''file'''•'''1.10'''••••••'''"
|32-byte file ID header
|32-byte file ID header
 +
|-
|-
|2
|2
-
|“BASE”-block
+
|"BASE"-block
|Map socket base and terrain block
|Map socket base and terrain block
 +
|-
|-
|3
|3
-
|“WATR”-block
+
|"WATR"-block
|Water mesh block
|Water mesh block
 +
|-
|-
|4
|4
-
|“FURN”-block
+
|"FURN"-block
-
|Meshes used (“furniture”) block
+
|Meshes used ("furniture") block
 +
 
|-
|-
|5
|5
-
|“INST”-block
+
|"INST"-block
|Furniture instances block
|Furniture instances block
 +
|-
|-
|6
|6
-
|“TERR”-block
+
|"TERR"-block
|Terrain data entries block
|Terrain data entries block
 +
|-
|-
|7
|7
-
|“ATTR”-block
+
|"ATTR"-block
|Block - Terrain attributes?
|Block - Terrain attributes?
 +
|-
|-
|8
|8
-
|“EXCL”-block
+
|"EXCL"-block
|Block - Exclusions???
|Block - Exclusions???
 +
|-
|-
|9
|9
-
|“MUSC”-block
+
|"MUSC"-block
|Block - Music?
|Block - Music?
 +
|-
|-
|10
|10
-
|“TRAC”-block
+
|"TRAC"-block
|Block -???
|Block -???
 +
|-
|-
|11
|11
-
|“EDIT”-block
+
|"EDIT"-block
|Block -???
|Block -???
-
|-
+
 
|}
|}
 +
==Data layout of subsections.==
-
== Data layout of subsections ==
+
General block layout
-
General block layout:
+
{|border="2" cellspacing="0" cellpadding="4" width="77%"
-
{|class="wikitable"
+
|'''Offset'''
|'''Offset'''
|'''Size'''
|'''Size'''
|'''Type'''
|'''Type'''
|'''Description'''
|'''Description'''
 +
|-
|-
|0
|0
|4
|4
|Array
|Array
-
|Data block type identifier (“ID”)
+
|Data block type identifier ("ID")
 +
 
|-
|-
|4
|4
|4
|4
|Long
|Long
-
|Size of data block (“BSIZE”, never less than 1)
+
|Size of data block ("BSIZE", never less than 1)
 +
 
|-
|-
|8
|8
Line 91: Line 119:
|…
|…
|Block data
|Block data
 +
|}
|}
-
ID is one of these 4-character literals:
+
ID is one of these 4-character literals
-
* “BASE” – Map socket (“base”, map cut-away edges)
+
* "BASE" – Map socket ("base", map cut-away edges)
-
* “WATR” – Waterline?
+
* "WATR" – Waterline?
-
* “FURN” – 3D object on map (“Furniture”)  
+
* "FURN" – 3D object on map ("Furniture")
-
* “INST” - ??
+
* "INST" - ??
-
* “TERR” - ?? Terrain data ??
+
* "TERR" - ?? Terrain data ??
* ATTR
* ATTR
* EXCL
* EXCL
Line 106: Line 135:
* EDIT
* EDIT
-
=== ID “BASE” block data layout ===
+
====ID "BASE" block data layout====
 +
The BASE block layout is minimal with only a string as data. The "base" in a Dark Omen map is the terrain and the socket surrounding it. These are saved in two separate flies with identical names but different extensions.
-
The BASE block layout is minimal with only a string as data. The “base” in a Dark Omen map is the terrain and the socket surrounding it. These are saved in two separate flies with identical names but different extensions.
+
{|border="2" cellspacing="0" cellpadding="4" width="80%"
 +
|'''Offset'''
 +
|'''Size'''
 +
|'''Type'''
 +
|'''Description'''
-
'''TODO: Add Wiki Syntax'''
+
|-
 +
|0
 +
|4
 +
|"BASE"
 +
|Base data block identifier
-
Offset Size Type Description
+
|-
-
0 4 “BASE” Base data block identifier
+
|4
-
4 4 Long Size of data block (“BSIZE”, never less than 1)
+
|4
-
8 BSIZE String Filename of socket mesh (generally “base.m3d”)
+
|Long
 +
|Size of data block ("BSIZE", never less than 1)
-
The socket has the filename as written in the data (“base.m3d”), while the terrain filename is obtained by replacing the extension with “m3x” (“base.m3x”).
+
|-
-
2.2 ID: “WATR” block data layout
+
|8
-
Offset Size Type Description
+
|BSIZE
-
0 4 “WATR” Water mesh data block identifier
+
|String
-
4 4 Long Size of data block (“BSIZE”, never less than 1)
+
|Filename of socket mesh (generally "base.m3d")
-
8 BSIZE String Filename of water mesh
+
 +
|}
 +
The socket has the filename as written in the data ("base.m3d"), while the terrain filename is obtained by replacing the extension with "m3x" ("base.m3x").
 +
====ID: "WATR" block data layout====
-
2.3 ID: “FURN” block data layout
+
{|border="2" cellspacing="0" cellpadding="4" width="79%"
-
The “FURN” (probably “FURNiture”) block contains the file name of all 3D models used in the scene. These models are then referenced by number (1-based, where “0” indicated NO model is used) in INST entries (next section).
+
|'''Offset'''
 +
|'''Size'''
 +
|'''Type'''
 +
|'''Description'''
-
Offset Size Type Description
+
|-
-
0 4 “FURN” Water mesh data block identifier
+
|0
-
4 4 Long Size of data block less 4×F
+
|4
-
8 4 Long Number of furniture objects (“F”)
+
|"WATR"
-
12 BSIZE Spec. List of filenames of furniture for map
+
|Water mesh data block identifier
-
Offset Size Type Description
+
|-
-
0 4 Long Size of string data
+
|4
-
4 String size String Filename of furniture object
+
|4
-
Repeat F times
+
|Long
 +
|Size of data block ("BSIZE", never less than 1)
-
Notice that the BSIZE element of the FURN block is short by 4 × F bytes. The block size was calculated using only the length of the strings, and the size of the string length element was omitted.
+
|-
 +
|8
 +
|BSIZE
 +
|String
 +
|Filename of water mesh
-
2.4 ID: “INST” block data layout
+
|}
-
The INST (probably “INSTances”) block details the objects to be instantiated in the scene and their attributes. Instantiated scene entities seems to be called “furniture” in the Dark Omen source code.
+
-
Offset Size Type Description
+
====ID: "FURN" block data layout====
-
0 4 “INST” Furniture instances data block identifier
+
The "FURN" (probably "FURNiture") block contains the file name of all 3D models used in the scene. These models are then referenced by number (1-based, where "0" indicated NO model is used) in INST entries (next section).
-
4 4 Long Size of data block less 8 (“BSIZE”, never less than 1)
+
-
8 4 Long Number of furniture object instances (“I”)
+
-
12 4 Long Size of each furniture instance (“FSIZE”, always 152)
+
-
I×FSIZE bytes: “Furniture” composite data records. See separate description below.
+
-
Notice that the BSIZE element of the INST block is short by 8 bytes. The block size was calculated using only the data area of the furniture records, and number of objects and record size elements were omitted.
+
{|border="2" cellspacing="0" cellpadding="4" width="81%"
 +
|'''Offset'''
 +
|'''Size'''
 +
|'''Type'''
 +
|'''Description'''
-
Furniture record layout and description
+
|-
-
The furniture record seems to contain a mixture of data of relevance for game as well as of relevance only for a graphical level editor.  
+
|0
 +
|4
 +
|"FURN"
 +
|Water mesh data block identifier
 +
 
 +
|-
 +
|4
 +
|4
 +
|Long
 +
|Size of data block less 4×'''''F'''''
 +
 
 +
|-
 +
|8
 +
|4
 +
|Long
 +
|Number of furniture objects ("'''''F'''''")
 +
 
 +
|-
 +
|12
 +
|BSIZE
 +
|Spec.
 +
|List of filenames of furniture for map
 +
 
 +
|-
 +
|colspan = "4"
 +
 
 +
{|border="2" cellspacing="0" cellpadding="4" width="82%"
 +
|'''Offset'''
 +
|&nbsp;
 +
|'''Size'''
 +
|'''Type'''
 +
|'''Description'''
 +
 
 +
|-
 +
|0
 +
|&nbsp;
 +
|4
 +
|Long
 +
|Size of string data
 +
 
 +
|-
 +
|4
 +
|&nbsp;
 +
|String size
 +
|String
 +
|Filename of furniture object
 +
 
 +
|}
 +
Repeat '''''F''''' times
 +
 
 +
|}
 +
 
 +
'''Notice''' that the BSIZE element of the FURN block is short by 4 × '''''F''''' bytes. The block size was calculated using only the length of the strings, and the size of the string length element was omitted.
 +
 
 +
====ID: "INST" block data layout====
 +
The INST (probably "INSTances") block details the objects to be instantiated in the scene and their attributes. Instantiated scene entities seems to be called "furniture" in the Dark Omen source code.
 +
 
 +
{|border="2" cellspacing="0" cellpadding="4" width="100%"
 +
|'''Offset'''
 +
|'''Size'''
 +
|'''Type'''
 +
|'''Description'''
 +
 
 +
|-
 +
|0
 +
|4
 +
|"INST"
 +
|Furniture instances data block identifier
 +
 
 +
|-
 +
|4
 +
|4
 +
|Long
 +
|Size of data block less 8 ("BSIZE", never less than 1)
 +
 
 +
|-
 +
|8
 +
|4
 +
|Long
 +
|Number of furniture object instances ("'''''I'''''")
 +
 
 +
|-
 +
|12
 +
|4
 +
|Long
 +
|Size of each furniture instance ("FSIZE", always 152)
 +
 
 +
|-
 +
|colspan = "4"|'''''I'''''×FSIZE'' bytes: "Furniture" composite data records. See separate description below.''
 +
 
 +
|}
 +
 
 +
'''Notice''' that the BSIZE element of the INST block is short by 8 bytes. The block size was calculated using only the data area of the furniture records, and number of objects and record size elements were omitted.
 +
 
 +
'''Furniture record layout and description'''
 +
 
 +
The furniture record seems to contain a mixture of data of relevance for game as well as of relevance only for a graphical level editor.
 +
 
 +
'''Notes:'''
 +
 
 +
* The ''position'' and ''extents'' vector items have been transformed into and stored as longs. To obtain the float values, divide each element in orientation by 1024.0f. Further note that the vector described in ''orientation'' has not been normalised, and can also be of 0 magnitude.
 +
* The ''orientation'' vector item has been transformed into and stored as longs. To obtain the float values, divide each element in orientation by 4096.0f (divide again by 2∏ to obtain rotation in radians). Watch for
 +
* The ''orientation'' vector is not normalised
 +
* The ''orientation'' vector magnitude can be 0.
 +
* The ''mesh_slot'' and ''dead_mesh_slot'' items refer to the filename specified in the FURN block, but "1" indicated the first model and "0" signifies that NO mesh is used.
 +
 
 +
{|border="2" cellspacing="0" cellpadding="4" width="100%"
 +
|'''<nowiki>#</nowiki>'''<br>
 +
|'''Offset'''
 +
|'''Size'''
 +
|'''Type'''
 +
|'''Description'''
 +
 
 +
|-
 +
|'''0'''
 +
|0
 +
|4
 +
|long
 +
|ID_prev; //void *
 +
 
 +
|-
 +
|'''1'''
 +
|4
 +
|4
 +
|long
 +
|ID_next; //void *
 +
 
 +
|-
 +
|'''2'''
 +
|8
 +
|4
 +
|long
 +
|selected;
 +
 
 +
|-
 +
|'''3'''
 +
|12
 +
|4
 +
|long
 +
|exclude_from_terrain;
 +
 
 +
|-
 +
|'''4 6'''
 +
|16
 +
|12
 +
|long<nowiki>[</nowiki>3<nowiki>]</nowiki>
 +
|Position (stored as longs: divide each element by 1024.0f)
 +
 
 +
|-
 +
|'''7 9'''
 +
|28
 +
|12
 +
|long<nowiki>[</nowiki>3<nowiki>]</nowiki>
 +
|Orientation (stored as longs: divide each element by 4096.0f)
 +
 
 +
|-
 +
|'''10 12'''
 +
|40
 +
|12
 +
|long<nowiki>[</nowiki>3<nowiki>]</nowiki>
 +
|Min extent (stored as longs: divide each element by 1024.0f)
 +
 
 +
|-
 +
|'''13 15'''
 +
|52
 +
|12
 +
|long<nowiki>[</nowiki>3<nowiki>]</nowiki>
 +
|Max extent (stored as longs: divide each element by 1024.0f)
 +
 
 +
|-
 +
|'''16'''
 +
|64
 +
|4
 +
|long
 +
|mesh_slot;// used to store a mesh slot number in the SAVED project
 +
 
 +
|-
 +
|'''17'''
 +
|68
 +
|4
 +
|long
 +
|Mesh *pMesh;  //long ID_mesh; //void *
 +
 
 +
|-
 +
|'''18'''
 +
|72
 +
|4
 +
|long
 +
|make_attackable;
 +
 
 +
|-
 +
|'''19'''
 +
|76
 +
|4
 +
|long
 +
|toughness;// used if the furniture is to be attackable
 +
 
 +
|-
 +
|'''20'''
 +
|80
 +
|4
 +
|long
 +
|wounds;
 +
 
 +
|-
 +
|'''21'''
 +
|84
 +
|4
 +
|long
 +
|''Padding''
 +
 
 +
|-
 +
|'''22'''
 +
|88
 +
|4
 +
|long
 +
|owner_unit_index;
 +
 
 +
|-
 +
|'''23'''
 +
|92
 +
|4
 +
|long
 +
|is_burning;
 +
 
 +
|-
 +
|'''24'''
 +
|96
 +
|4
 +
|long
 +
|SFX_code;
 +
 
 +
|-
 +
|'''25'''
 +
|100
 +
|4
 +
|long
 +
|GFX_code;
 +
 
 +
|-
 +
|'''26'''
 +
|104
 +
|4
 +
|long
 +
|is_locked;// cannot be dragged while locked
 +
 
 +
|-
 +
|'''27'''
 +
|108
 +
|4
 +
|long
 +
|exclude_from_terrain_shadow;
 +
 
 +
|-
 +
|'''28'''
 +
|112
 +
|4
 +
|long
 +
|exclude_from_walk;
 +
 
 +
|-
 +
|'''29'''
 +
|116
 +
|4
 +
|long
 +
|magic_item_code;
 +
 
 +
|-
 +
|'''30'''
 +
|120
 +
|4
 +
|long
 +
|particle_effect_code;
 +
 
 +
|-
 +
|'''31'''
 +
|124
 +
|4
 +
|long
 +
|dead_mesh_slot;// used to store a mesh slot number in the SAVED project
 +
 
 +
|-
 +
|'''32'''
 +
|128
 +
|4
 +
|long
 +
|Mesh *pDeadMesh; //long dead_mesh; //void *
 +
 
 +
|-
 +
|'''33'''
 +
|132
 +
|4
 +
|long
 +
|light;
 +
 
 +
|-
 +
|'''34'''
 +
|136
 +
|4
 +
|long
 +
|light_radius;
 +
 
 +
|-
 +
|'''35'''
 +
|140
 +
|4
 +
|long
 +
|light_ambient;
 +
 
 +
|-
 +
|'''36'''
 +
|144
 +
|4
 +
|long
 +
|''Padding''
 +
 
 +
|-
 +
|'''37'''
 +
|148
 +
|4
 +
|long
 +
|''Padding''
 +
 
 +
|}
 +
 
 +
====ID: "TERR" data block layout====
 +
 
 +
{|border="2" cellspacing="0" cellpadding="4" width="87%"
 +
|'''Offset'''
 +
|'''Size'''
 +
|'''Type'''
 +
|'''Description'''
 +
 
 +
|-
 +
|0
 +
|4
 +
|"TERR"
 +
|TERR (terrain?) data block identifier
 +
 
 +
|-
 +
|4
 +
|4
 +
|Long
 +
|Size of data block ("BSIZE", never less than 1)
 +
 
 +
|-
 +
|8
 +
|4
 +
|Long
 +
|Number of TERR data entries ("'''''T'''''")
 +
 
 +
|-
 +
|12
 +
|4
 +
|Long
 +
|Size of each TERR data entry ("TSIZE", always 200?)
 +
 
 +
|-
 +
|colspan = "4"|'''''T'''''×TSIZE'' bytes: composite data records. See separate description below.''
 +
 
 +
|}
 +
 
 +
'''''TERR Data record format not yet mapped!'''''
 +
 
 +
====ID: "ATTR" block data layout====
 +
 
 +
"Rob" from http://darkomenworld.freeforums.org/looking-at-the-data-files-t33-15.html
 +
 
 +
{|cellspacing="0" cellpadding = "10" style="border-style:solid; border-color:black; border-width:1px;" width="100%"
 +
|I figured out a bit of the ATTR block: <br><br>ATTR <br><nowiki>{</nowiki> <br>char<nowiki>[</nowiki>4<nowiki>]</nowiki> <nowiki>’</nowiki>ATTR<nowiki>’</nowiki> <br>long BLOCK_SIZE <br>long WIDTH_OF_MAP <br>long HEIGHT_OF_MAP <br><nowiki>}</nowiki> <br><br>Then follows (width*height/2) bytes. Each tile has 4 bits of attributes and these are packed 2 to a byte. <br><br>Then there are 64 bytes, of which I can<nowiki>’</nowiki>t make out much. <br><br>It looks like this is line-of-sight / accessibility information. attributes are 0 for <nowiki>’</nowiki>ordinary<nowiki>’</nowiki> tiles, 2 for blocked ( i.e. unit can<nowiki>’</nowiki>t move there ), 8 for passable water (such as fords), 10 (8<nowiki>|</nowiki>2) for impassible water. <br><br>There are probably more attribute values, its just a matter of looking at all the maps. I made a program which spits out the data as a bitmap, so I can just compare to the minimaps.
 +
 
 +
|}
 +
 
 +
==The M3D 3D Object File Layout==
 +
The M3D format used by Dark Omen is a raw-data binary format to save a model consisting of a non-hierarchal array of meshes. It is intended for forward-parsing and do not contain block meta-data.
 +
 
 +
===Render flags===
 +
M3D stored basic instructions on how the model is intended to be rendered in its filename.
 +
 
 +
<font color="#DFDFBF"><font size = "4">  </font></font><font color="#688468">//=====================================================================
 +
 
 +
// Render flags
 +
 
 +
// ------------
 +
 
 +
//
 +
 
 +
// Render flags for a model are provided, believe it or not, in
 +
 
 +
// the model<nowiki>’</nowiki>s filename. If the leading character is an underline
 +
 
 +
// then the following is a hash for a binary attribute map where
 +
 
 +
//
 +
 
 +
//  00000 ( 0) = no flags
 +
 
 +
//  00001 ( 1) = translucency (colour blending?)
 +
 
 +
//  00010 ( 2) = animate texture UV coordinates
 +
 
 +
//  00100 ( 4) = transparency (alpha blending?)
 +
 
 +
//  10000 (16) = colour key transparency
 +
 
 +
//
 +
 
 +
// The hash depends on character
 +
 
 +
//
 +
 
 +
//  <nowiki>’</nowiki>0<nowiki>’</nowiki>..<nowiki>’</nowiki>9<nowiki>’</nowiki>: flag <nowiki>|</nowiki>= char - 48 (==<nowiki>></nowiki> 0 .. 9)
 +
 
 +
//  <nowiki>’</nowiki>A<nowiki>’</nowiki>..<nowiki>’</nowiki>Z<nowiki>’</nowiki>: flag <nowiki>|</nowiki>= char - 55 (==<nowiki>></nowiki> 10 .. 35)
 +
 
 +
//  <nowiki>’</nowiki>a<nowiki>’</nowiki>..<nowiki>’</nowiki>z<nowiki>’</nowiki>: flag <nowiki>|</nowiki>= char - 87 (==<nowiki>></nowiki> 10 .. 35)
 +
 
 +
//
 +
 
 +
// The most common filename prefixes (actually, the only ones
 +
 
 +
// present in Dark Omen) are:
 +
 
 +
//
 +
 
 +
//  "_4": 00000100 (transparency)
 +
 
 +
//  "_6": 00000110 (transparecy and animated texture coordinates)
 +
 
 +
//  "_7": 00000111 (translucency, animated texture coordinates, and transparency)
 +
 
 +
//  "_K": 00010100 (transparency and colour keying)
 +
 
 +
//
 +
 
 +
//===============================================================
 +
 
 +
</font>
 +
 
 +
===General layout===
 +
 
 +
{|border="2" cellspacing="0" cellpadding="4" width="100%"
 +
|0
 +
|24
 +
|&nbsp;
 +
|File header
 +
 
 +
|-
 +
|24
 +
|96 * n
 +
|&nbsp;
 +
|Texture description
 +
 
 +
|-
 +
|&nbsp;
 +
|&nbsp;
 +
|&nbsp;
 +
|Sub-object description
 +
 
 +
|}
 +
 
 +
File header:
 +
 
 +
{|border="2" cellspacing="0" cellpadding="4" width="100%"
 +
|0
 +
|4
 +
|Long
 +
|File ID
 +
 
 +
|-
 +
|4
 +
|4
 +
|Long
 +
|Magic
 +
 
 +
|-
 +
|8
 +
|4
 +
|Long
 +
|Version
 +
 
 +
|-
 +
|12
 +
|4
 +
|Long
 +
|CRC
 +
 
 +
|-
 +
|16
 +
|4
 +
|Long
 +
|NOT CRC
 +
 
 +
|-
 +
|20
 +
|2
 +
|Short
 +
|<nowiki>#</nowiki> textures<br>
 +
 
 +
|-
 +
|22
 +
|2
 +
|Short
 +
|<nowiki>#</nowiki> sub-objects<br>
 +
 
 +
|}
 +
 
 +
Texture description entry
 +
 
 +
{|border="2" cellspacing="0" cellpadding="4" width="100%"
 +
|0
 +
|64
 +
|Char<nowiki>[</nowiki>64<nowiki>]</nowiki>
 +
|Filepath (ignored)
 +
 
 +
|-
 +
|64
 +
|32
 +
|Char<nowiki>[</nowiki>32<nowiki>]</nowiki>
 +
|Texture filename
 +
 
 +
|}
 +
 
 +
3D Sub-object Description
 +
 
 +
{|border="0" cellspacing="2" width="100%"
 +
|<font color="#DFDFBF"><font size = "4">
 +
|</font><font color="#EAEAAC">'''char'''</font><font color="#DFDFBF">
 +
|&nbsp;
 +
|</font></font><font color="#E5DFC5"><font size = "4">name</font></font><font color="#C7C792"><font size = "4"><nowiki>[</nowiki></font></font><font color="#8FC9A0"><font size = "4">32</font></font><font color="#C7C792"><font size = "4"><nowiki>]</nowiki>;</font><font color="#DFDFBF">
 +
|colspan = "2"|</font</font><font color="#DFDFBF">></font><font color="#688468"><font size = "4">// object name</font>
 +
 
 +
|-
 +
|</font><font color="#DFDFBF"><font size = "4">
 +
|</font><font color="#EAEAAC">'''short'''</font><font color="#DFDFBF">
 +
|&nbsp;
 +
|</font</font><font color="#DFDFBF">></font><font color="#E5DFC5"><font size = "4">parent</font></font><font color="#C7C792"><font size = "4">;</font><font color="#DFDFBF">
 +
|&nbsp;
 +
|</font</font><font color="#DFDFBF">></font><font color="#688468"><font size = "4">// parent index</font>
 +
 
 +
|-
 +
|</font><font color="#DFDFBF"><font size = "4">
 +
|</font><font color="#E5DFC5">M3DPOINT</font><font color="#DFDFBF">
 +
|</font><font color="#E5DFC5">pivot</font</font><font color="#E5DFC5">></font><font color="#C7C792"><font size = "4">;</font><font color="#DFDFBF">
 +
|&nbsp;
 +
|colspan = "2"|</font</font><font color="#DFDFBF">></font><font color="#688468"><font size = "4">// origin for heirarchy</font>
 +
 
 +
|-
 +
|</font><font color="#DFDFBF"><font size = "4">
 +
|</font><font color="#EAEAAC">'''short'''</font><font color="#DFDFBF">
 +
|&nbsp;
 +
|</font</font><font color="#DFDFBF">></font><font color="#E5DFC5"><font size = "4">vertices</font></font><font color="#C7C792"><font size = "4">;</font><font color="#DFDFBF">
 +
|colspan = "2"|</font</font><font color="#DFDFBF">></font><font color="#688468"><font size = "4">// number of verts.</font>
 +
 
 +
|-
 +
|</font><font color="#DFDFBF"><font size = "4">
 +
|</font><font color="#EAEAAC">'''short'''</font><font color="#DFDFBF">
 +
|&nbsp;
 +
|</font</font><font color="#DFDFBF">></font><font color="#E5DFC5"><font size = "4">faces</font></font><font color="#C7C792"><font size = "4">;</font><font color="#DFDFBF">
 +
|&nbsp;
 +
|</font</font><font color="#DFDFBF">></font><font color="#688468"><font size = "4">// number of faces</font>
 +
 
 +
|-
 +
|colspan = "3"|</font><font color="#DFDFBF"><font size = "4">
 +
|</font><font color="#EAEAAC">'''long'''</font><font color="#DFDFBF">
 +
|&nbsp;
 +
|</font</font><font color="#DFDFBF">></font><font color="#E5DFC5"><font size = "4">flags</font></font><font color="#C7C792"><font size = "4">;</font>
 +
 
 +
|-
 +
|colspan = "3"|</font><font color="#DFDFBF"><font size = "4">
 +
|</font><font color="#EAEAAC">'''long'''</font><font color="#DFDFBF">
 +
|&nbsp;
 +
|</font</font><font color="#DFDFBF">></font><font color="#E5DFC5"><font size = "4">spare1</font></font><font color="#C7C792"><font size = "4">;</font>
 +
 
 +
|-
 +
|colspan = "3"|</font><font color="#DFDFBF"><font size = "4">
 +
|</font><font color="#EAEAAC">'''long'''</font><font color="#DFDFBF">
 +
|&nbsp;
 +
|</font</font><font color="#DFDFBF">></font><font color="#E5DFC5"><font size = "4">spare2</font></font><font color="#C7C792"><font size = "4">;</font>
 +
 
 +
|}
-
Notes:
+
</font>
-
• The position and extents vector items have been transformed into and stored as longs. To obtain the float values, divide each element in orientation by 1024.0f. Further note that the vector described in orientation has not been normalised, and can also be of 0 magnitude.
+
-
• The orientation vector item has been transformed into and stored as longs. To obtain the float values, divide each element in orientation by 4096.0f (divide again by 2∏ to obtain rotation in radians). Watch for
+
-
o The orientation vector is not normalised
+
-
o The orientation vector magnitude can be 0.
+
-
• The mesh_slot and dead_mesh_slot items refer to the filename specified in the FURN block, but “1” indicated the first model and “0” signifies that NO mesh is used.
+
-
# Offset Size Type Description
+
Geometry
-
0 0 4 long ID_prev; //void *
+
-
1 4 4 long ID_next; //void *
+
-
2 8 4 long selected;
+
-
3 12 4 long exclude_from_terrain;
+
-
4 6 16 12 long[3] Position (stored as longs: divide each element by 1024.0f)
+
-
7 9 28 12 long[3] Orientation (stored as longs: divide each element by 4096.0f)
+
-
10 12 40 12 long[3] Min extent (stored as longs: divide each element by 1024.0f)
+
-
13 15 52 12 long[3] Max extent (stored as longs: divide each element by 1024.0f)
+
-
16 64 4 long mesh_slot; // used to store a mesh slot number in the SAVED project
+
-
17 68 4 long Mesh *pMesh;  //long ID_mesh; //void *
+
-
18 72 4 long make_attackable;
+
-
19 76 4 long toughness; // used if the furniture is to be attackable
+
-
20 80 4 long wounds;
+
-
21 84 4 long Padding
+
-
22 88 4 long owner_unit_index;
+
-
23 92 4 long is_burning;
+
-
24 96 4 long SFX_code;
+
-
25 100 4 long GFX_code;
+
-
26 104 4 long is_locked; // cannot be dragged while locked
+
-
27 108 4 long exclude_from_terrain_shadow;
+
-
28 112 4 long exclude_from_walk;
+
-
29 116 4 long magic_item_code;
+
-
30 120 4 long particle_effect_code;
+
-
31 124 4 long dead_mesh_slot; // used to store a mesh slot number in the SAVED project
+
-
32 128 4 long Mesh *pDeadMesh; //long dead_mesh; //void *
+
-
33 132 4 long light;
+
-
34 136 4 long light_radius;
+
-
35 140 4 long light_ambient;
+
-
36 144 4 long Padding
+
-
37 148 4 long Padding
+
 +
Geometry header
-
2.5 ID: “TERR” data block layout
+
List of faces
-
Offset Size Type Description
+
-
0 4 “TERR” TERR (terrain?) data block identifier
+
-
4 4 Long Size of data block (“BSIZE”, never less than 1)
+
-
8 4 Long Number of TERR data entries (“T”)
+
-
12 4 Long Size of each TERR data entry (“TSIZE”, always 200?)
+
-
T×TSIZE bytes: composite data records. See separate description below.
+
 +
List of vertices
-
TERR Data record format not yet mapped!
+
==Graphical effects==
-
2.6 ID: “ATTR” block data layout
+
From filenames
-
“Rob” from http://darkomenworld.freeforums.org/looking-at-the-data-files-t33-15.html
+
Water movement, etc: animated texture coordinates
-
I figured out a bit of the ATTR block:  
+
-
ATTR
+
Transparency
-
{
+
-
char[4] 'ATTR'
+
-
long BLOCK_SIZE
+
-
long WIDTH_OF_MAP
+
-
long HEIGHT_OF_MAP
+
-
}
+
-
Then follows (width*height/2) bytes. Each tile has 4 bits of attributes and these are packed 2 to a byte.
+
Particle effects from settings in the INST block
-
Then there are 64 bytes, of which I can't make out much.
+
Water vapour (waterfalls etc)
-
It looks like this is line-of-sight / accessibility information. attributes are 0 for 'ordinary' tiles, 2 for blocked ( i.e. unit can't move there ), 8 for passable water (such as fords), 10 (8|2) for impassible water.
+
Dust
-
There are probably more attribute values, its just a matter of looking at all the maps. I made a program which spits out the data as a bitmap, so I can just compare to the minimaps.
+
Fire
-
[[Category:Modifications]]
+
Explosions

Revision as of 18:39, 26 April 2008

Contents



Titelblatt


Conventions and definitions:

"Byte" signifies a 1-byte (8-bit) integer

"Long" signifies a Big-endian 4-byte (32-bit) integer (i.e. stored as "n¤¤¤")

"Array" denotes a literal sequence of characters

"String" denotes a sequence of characters ended with a NULL (0x00)

"¤" signifies a NULL (0x00)

"" signifies a space (0x20)

The .PRJ Battle Project File Layout

The entry point of Dark Omen’s battle description is the .PRJ-file in each battle’s folder. It is a reasonable hypothesis that ".prj" stands for project, and just as reasonable that the name comes from an experimental phase or structure that happened to become the actual core, or that nobody could bother change the names to something more appropriate. Before delving into it, it is worth noting and keeping in mind that the PRJ format is really more or less a hack and is structurally and internally inconsistent, and contains several unconventional (not to say outright stupid) solutions.

Anyway, Dark Omen battles principally consist of a general description of the level (scene and battle) in the .prj-file, a .BTB-file ("BaTtle Boundaries"?) that specifies the deployment zone, a number of .M3D ("Model 3D"?) model files (the special format used in Dark Omen), and 8-bit 128x128 .BMP textures used by and specified in the M3D models.

The .PRJ-file is structured into a file format identification header and then into ten specialised blocks of binary data. The design of these blocks seems inspired by ignorance-friendly nested-block layouts (such as f.i. the .3DS file format) in that each block is systematically begun with a unique block ID header and block size value, thus apparently allowing blind/ignorant parsing, but since the implementation of the block size value is inconsistent the original Dark Omen code probably employs vanilla forward-parsing.

Project file general layout

Section   Notes
1 "DarkOmenBattlefile1.10••••••" 32-byte file ID header
2 "BASE"-block Map socket base and terrain block
3 "WATR"-block Water mesh block
4 "FURN"-block Meshes used ("furniture") block
5 "INST"-block Furniture instances block
6 "TERR"-block Terrain data entries block
7 "ATTR"-block Block - Terrain attributes?
8 "EXCL"-block Block - Exclusions???
9 "MUSC"-block Block - Music?
10 "TRAC"-block Block -???
11 "EDIT"-block Block -???

Data layout of subsections.

General block layout

Offset Size Type Description
0 4 Array Data block type identifier ("ID")
4 4 Long Size of data block ("BSIZE", never less than 1)
8 BSIZE Block data

ID is one of these 4-character literals

  • "BASE" – Map socket ("base", map cut-away edges)
  • "WATR" – Waterline?
  • "FURN" – 3D object on map ("Furniture")
  • "INST" - ??
  • "TERR" - ?? Terrain data ??
  • ATTR
  • EXCL
  • MUSC
  • TRAC
  • EDIT

ID "BASE" block data layout

The BASE block layout is minimal with only a string as data. The "base" in a Dark Omen map is the terrain and the socket surrounding it. These are saved in two separate flies with identical names but different extensions.

Offset Size Type Description
0 4 "BASE" Base data block identifier
4 4 Long Size of data block ("BSIZE", never less than 1)
8 BSIZE String Filename of socket mesh (generally "base.m3d")

The socket has the filename as written in the data ("base.m3d"), while the terrain filename is obtained by replacing the extension with "m3x" ("base.m3x").

ID: "WATR" block data layout

Offset Size Type Description
0 4 "WATR" Water mesh data block identifier
4 4 Long Size of data block ("BSIZE", never less than 1)
8 BSIZE String Filename of water mesh

ID: "FURN" block data layout

The "FURN" (probably "FURNiture") block contains the file name of all 3D models used in the scene. These models are then referenced by number (1-based, where "0" indicated NO model is used) in INST entries (next section).

Offset Size Type Description
0 4 "FURN" Water mesh data block identifier
4 4 Long Size of data block less 4×F
8 4 Long Number of furniture objects ("F")
12 BSIZE Spec. List of filenames of furniture for map
colspan = "4"
Offset   Size Type Description
0   4 Long Size of string data
4   String size String Filename of furniture object

Repeat F times

Notice that the BSIZE element of the FURN block is short by 4 × F bytes. The block size was calculated using only the length of the strings, and the size of the string length element was omitted.

ID: "INST" block data layout

The INST (probably "INSTances") block details the objects to be instantiated in the scene and their attributes. Instantiated scene entities seems to be called "furniture" in the Dark Omen source code.

Offset Size Type Description
0 4 "INST" Furniture instances data block identifier
4 4 Long Size of data block less 8 ("BSIZE", never less than 1)
8 4 Long Number of furniture object instances ("I")
12 4 Long Size of each furniture instance ("FSIZE", always 152)
I×FSIZE bytes: "Furniture" composite data records. See separate description below.

Notice that the BSIZE element of the INST block is short by 8 bytes. The block size was calculated using only the data area of the furniture records, and number of objects and record size elements were omitted.

Furniture record layout and description

The furniture record seems to contain a mixture of data of relevance for game as well as of relevance only for a graphical level editor.

Notes:

  • The position and extents vector items have been transformed into and stored as longs. To obtain the float values, divide each element in orientation by 1024.0f. Further note that the vector described in orientation has not been normalised, and can also be of 0 magnitude.
  • The orientation vector item has been transformed into and stored as longs. To obtain the float values, divide each element in orientation by 4096.0f (divide again by 2∏ to obtain rotation in radians). Watch for
  • The orientation vector is not normalised
  • The orientation vector magnitude can be 0.
  • The mesh_slot and dead_mesh_slot items refer to the filename specified in the FURN block, but "1" indicated the first model and "0" signifies that NO mesh is used.
#
Offset Size Type Description
0 0 4 long ID_prev; //void *
1 4 4 long ID_next; //void *
2 8 4 long selected;
3 12 4 long exclude_from_terrain;
4 6 16 12 long[3] Position (stored as longs: divide each element by 1024.0f)
7 9 28 12 long[3] Orientation (stored as longs: divide each element by 4096.0f)
10 12 40 12 long[3] Min extent (stored as longs: divide each element by 1024.0f)
13 15 52 12 long[3] Max extent (stored as longs: divide each element by 1024.0f)
16 64 4 long mesh_slot;// used to store a mesh slot number in the SAVED project
17 68 4 long Mesh *pMesh; //long ID_mesh; //void *
18 72 4 long make_attackable;
19 76 4 long toughness;// used if the furniture is to be attackable
20 80 4 long wounds;
21 84 4 long Padding
22 88 4 long owner_unit_index;
23 92 4 long is_burning;
24 96 4 long SFX_code;
25 100 4 long GFX_code;
26 104 4 long is_locked;// cannot be dragged while locked
27 108 4 long exclude_from_terrain_shadow;
28 112 4 long exclude_from_walk;
29 116 4 long magic_item_code;
30 120 4 long particle_effect_code;
31 124 4 long dead_mesh_slot;// used to store a mesh slot number in the SAVED project
32 128 4 long Mesh *pDeadMesh; //long dead_mesh; //void *
33 132 4 long light;
34 136 4 long light_radius;
35 140 4 long light_ambient;
36 144 4 long Padding
37 148 4 long Padding

ID: "TERR" data block layout

Offset Size Type Description
0 4 "TERR" TERR (terrain?) data block identifier
4 4 Long Size of data block ("BSIZE", never less than 1)
8 4 Long Number of TERR data entries ("T")
12 4 Long Size of each TERR data entry ("TSIZE", always 200?)
T×TSIZE bytes: composite data records. See separate description below.

TERR Data record format not yet mapped!

ID: "ATTR" block data layout

"Rob" from http://darkomenworld.freeforums.org/looking-at-the-data-files-t33-15.html

I figured out a bit of the ATTR block:

ATTR
{
char[4] ’ATTR’
long BLOCK_SIZE
long WIDTH_OF_MAP
long HEIGHT_OF_MAP
}

Then follows (width*height/2) bytes. Each tile has 4 bits of attributes and these are packed 2 to a byte.

Then there are 64 bytes, of which I can’t make out much.

It looks like this is line-of-sight / accessibility information. attributes are 0 for ’ordinary’ tiles, 2 for blocked ( i.e. unit can’t move there ), 8 for passable water (such as fords), 10 (8|2) for impassible water.

There are probably more attribute values, its just a matter of looking at all the maps. I made a program which spits out the data as a bitmap, so I can just compare to the minimaps.

The M3D 3D Object File Layout

The M3D format used by Dark Omen is a raw-data binary format to save a model consisting of a non-hierarchal array of meshes. It is intended for forward-parsing and do not contain block meta-data.

Render flags

M3D stored basic instructions on how the model is intended to be rendered in its filename.

//=====================================================================

// Render flags

// ------------

//

// Render flags for a model are provided, believe it or not, in

// the model’s filename. If the leading character is an underline

// then the following is a hash for a binary attribute map where

//

// 00000 ( 0) = no flags

// 00001 ( 1) = translucency (colour blending?)

// 00010 ( 2) = animate texture UV coordinates

// 00100 ( 4) = transparency (alpha blending?)

// 10000 (16) = colour key transparency

//

// The hash depends on character

//

// ’0’..’9’: flag |= char - 48 (==> 0 .. 9)

// ’A’..’Z’: flag |= char - 55 (==> 10 .. 35)

// ’a’..’z’: flag |= char - 87 (==> 10 .. 35)

//

// The most common filename prefixes (actually, the only ones

// present in Dark Omen) are:

//

// "_4": 00000100 (transparency)

// "_6": 00000110 (transparecy and animated texture coordinates)

// "_7": 00000111 (translucency, animated texture coordinates, and transparency)

// "_K": 00010100 (transparency and colour keying)

//

//===============================================================

General layout

0 24   File header
24 96 * n   Texture description
      Sub-object description

File header:

0 4 Long File ID
4 4 Long Magic
8 4 Long Version
12 4 Long CRC
16 4 Long NOT CRC
20 2 Short # textures
22 2 Short # sub-objects

Texture description entry

0 64 Char[64] Filepath (ignored)
64 32 Char[32] Texture filename

3D Sub-object Description

char   name[32]; </font>// object name
short   </font>parent;   </font>// parent index
M3DPOINT pivot</font>;   </font>// origin for heirarchy
short   </font>vertices; </font>// number of verts.
short   </font>faces;   </font>// number of faces
long   </font>flags;
long   </font>spare1;
long   </font>spare2;

Geometry

Geometry header

List of faces

List of vertices

Graphical effects

From filenames

Water movement, etc: animated texture coordinates

Transparency

Particle effects from settings in the INST block

Water vapour (waterfalls etc)

Dust

Fire

Explosions

Personal tools
communication