Difference between revisions of "ELVL Format"

From ASSS Wiki
Jump to: navigation, search
m (updated source link)
Line 1: Line 1:
ELVL Format now superecedes the [[RGN Format]].
+
apple cows
 
 
The latest version can always be found at http://sscx.net/asss/extended-lvl-format.txt
 
 
 
<pre>
 
extended level file format
 
version 0.4
 
grelminar@yahoo.com
 
------------------------
 
 
 
0. note
 
 
 
this document is a work in progress. it often speaks about things being
 
implemented in asss. it's often wrong: implementation of the features
 
described in this document is still ongoing, and many features described
 
here are not yet implemented.
 
 
 
 
 
1. background
 
 
 
the basic level format, in use for many years, supports two main pieces
 
of data: a bitmapped tileset for the map, and the tile data. the tileset
 
bitmap is optional. the file layout is relatively simple: the bitmap
 
comes first, if it's present, followed by tile data to the end of the
 
file. if the bitmap signature isn't present, applications assume the
 
whole file contains tile data.
 
 
 
to support advanced features that are already, or will soon be, possible
 
in asss, i'd like to propose a backwards-compatible extension of the
 
basic level format.
 
 
 
 
 
2. goals
 
 
 
the primary goal is to make it possible to embed more metadata in level
 
files. this includes descriptive information about the creator of the
 
file and its intended use, but also some functional information.
 
 
 
the most important, and complicated, type of metadata that i'd like to
 
embed are regions. a region is just a set of tiles, usually but not
 
necessarily contiguous, plus some information describing how the server
 
(and maybe eventually the client) should treat that set of tiles.
 
 
 
 
 
3. file format
 
 
 
3.1. embedding metadata in lvl files
 
 
 
currently, level files have one of two formats:
 
 
 
    <bitmapfileheader>
 
    <bitmapinfoheader>
 
    <color table>
 
    <bitmap data>
 
    <tile data>
 
 
 
or just:
 
 
 
    <tile data>
 
 
 
for now, i'm just going to talk about level files that contain tilesets.
 
tileset-less files will be discussed later.
 
 
 
to preserve backwards compatibility with all the programs that read or
 
write level files (subspace, continuum, ssme, ssled, facts, subgame,
 
etc.), the beginning of the file will have to remain the same. the tile
 
data will also have to remain the last item in the file, since all the
 
level-file-reading code assumes that all the data from a specific point
 
to the end of the file is tile data. thus, the new data will have to be
 
inserted in the middle of the file, making it look like this:
 
 
 
    <bitmapfileheader>
 
    <bitmapinfoheader>
 
    <color table>
 
    <bitmap data>
 
    <metadata/regions>    <-- new stuff
 
    <tile data>
 
 
 
the trick that makes this work is the fact that the bitmapfileheader
 
contains a field that specifies the total file size, which programs use
 
to locate the start of the tile data. (at least i hope they do. if any
 
program assumes the tile data directly follows the bitmap data, these
 
extended files will break it.) another nice feature is that header also
 
contains 4 bytes of reserved space, which we will use to point to the
 
metadata section.
 
 
 
for reference, the windows BITMAPFILEHEADER struct looks like this:
 
 
 
struct BITMAPFILEHEADER {
 
    u16 bfType;        // == 0x4D42 ("BM")
 
    u32 bfSize;        // the total size of the file, which is also
 
                        // the offset of the tile data
 
    u16 bfReserved1;    // previously reserved, but we're going to
 
                        // use this for our format
 
    u16 bfReserved2;    // this one is still unused, should be 0
 
    u32 bfOffBits;      // the offset to the bitmap data
 
};
 
 
 
so, to make an extended level file, lay out your two bitmap headers,
 
color table, and bitmap data as before, then the metadata section, and
 
finally the tile data. the metadata section should be aligned to start
 
at a multiple of 4 bytes from the start of the file, so you might need
 
0-3 bytes of padding between the end of the bitmap data and the start of
 
the metadata. the metadata section will always be a multiple of 4 bytes
 
long, so the tile data will also always start on a multiple of 4 bytes.
 
 
 
set the bfReserved1 field to the byte position of the start of the
 
metadata section. typically, this will be 49720 bytes. also, the bfSize
 
value, which was previously almost always 49718, will now point to the
 
tile data, which will be located right after the extended metadata. so
 
for a file containing 4000 bytes of metadata, bfSize will be 53720.
 
 
 
note that this means from the perspective of a program that only
 
understands bmp files, or one that only understands plain lvl files, the
 
metadata is part of the bitmap. it just happens that the bitmap contains
 
more bits than is necessary for its dimensions and color depth.
 
 
 
to make an extended level file without a tileset, you simply start off
 
the file with the metadata chunk, followed by the tile data. WARNING:
 
currently no programs except asss understand extended level files
 
without tilesets.
 
 
 
 
 
3.2. metadata format
 
 
 
now, the format of the metadata section itself. this is designed to be
 
extensible, so new features can get added to lvl files without
 
redefining the whole format. it's somewhat inspired by the png file
 
format, which was inspired by iff, etc.
 
 
 
first, there's a header:
 
 
 
struct metadata_header {
 
    u32 magic;          // == 0x6c766c65 ("elvl", for "extended lvl")
 
    u32 totalsize;      // the number of bytes in the whole metadata section
 
    u32 reserved;      // reserved, should be 0
 
};
 
 
 
magic should always be equal to 0x6c766c65. if it isn't, the file is
 
incorrect or corrupted. incidentally, the magic value is how extended
 
level files without tilesets can be identified. (that is, an initial
 
"BM" means an initial tileset, which may or may not contain extended
 
data, an initial "elvl" means an extended level file without a tileset,
 
and anything else is a plain level file without a tileset.) also note
 
that the magic value is an illegal value for tile data.
 
 
 
totalsize is the number of bytes in the whole metadata section,
 
including the header. note that the tile data will start at an offset of
 
totalsize bytes from the start of the metadata_header.
 
 
 
directly following the header is a series of "chunks". there is no limit
 
to the number of chunks. each chunk contains a chunk header:
 
 
 
struct chunk_header {
 
    u32 type;  // describes what this chunk represents
 
    u32 size;  // the number of bytes in the data portion of this
 
                // chunk, _not_ including the header.
 
};
 
 
 
the header is followed by arbitrary data whose interpretation is
 
determined by the chunk type. the data portion of a chunk may be of any
 
length, including 0 bytes and odd numbers of bytes. if a chunk isn't a
 
multiple of 4 bytes long, it should be padded up to a multiple of 4
 
bytes so that the next chunk starts on a 4-byte boundary (but the
 
padding isn't counted in the size field, it's just understood to be
 
there).
 
 
 
an application can ignore chunk types that it doesn't know about. if
 
it's an editor that's loading and saving elvl files, it should probably
 
save the extra chunks and write them back to the file when it gets
 
saved.
 
 
 
there are several chunk types defined so far:
 
 
 
"ATTR" - defines a textual attribute
 
"REGN" - defines a region
 
"TSET" - defines a tileset
 
"TILE" - defines tile data
 
 
 
i'll describe their function and format one by one:
 
 
 
3.2.1. "ATTR" chunks
 
 
 
these define miscelaneous textual attributes. the format is ascii text,
 
not null terminated, in this form: "<key>=<value>". each "ATTR" chunk
 
should contain just one key/value pair. multiple chunks of this type may
 
be present in one file.
 
 
 
some keys that might be typically found in a level file are:
 
 
 
"NAME" - a descriptive name for this map
 
"VERSION" - a version number for this map
 
"ZONE" - the zone this file is intended to be used with
 
"MAPCREATOR" - the person who created this map (the format of the value
 
              should be "name <email>")
 
"TILESETCREATOR" - the person who created the tileset
 
"PROGRAM" - the name of the program that was used to create this level
 
            file
 
 
 
3.2.2. "REGN" chunks
 
 
 
these chunks define regions. to recap, a region is a set of tiles,
 
usually but not always contiguous, with certain properties. asss
 
understands regions and can implement some advanced features using them.
 
currently continuum doesn't understand regions, but it would be nice if
 
it did, and we'll be able to do even cooler things when it does.
 
 
 
there's a lot of stuff that you might want to say about a region, so to
 
support all the varied uses, and also future uses, we'll use the chunk
 
model again: each region gets its own set of "subchunks" describing its
 
function. to avoid confusion, all sub-chunk types that go inside the
 
"REGN" superchunk start with "r". the data of the big "REGN" chunk is
 
simply a series of subchunks.
 
 
 
here are some defined sub-chunk types:
 
 
 
"rNAM" - a descriptive name for the region
 
"rTIL" - tile data, the definition of the region
 
"rBSE" - whether the region represents a base in a flag game
 
"rNAW" - no antiwarp
 
"rNWP" - no weapons
 
"rNFL" - no flag drops
 
"rAWP" - auto-warp
 
"rPYC" - code to be executed when a player enters or leaves this region
 
 
 
3.2.2.1. "rNAM" chunks
 
 
 
this is just a plain ascii string, not null terminated. every chunk
 
should have exactly one of these.
 
 
 
3.2.2.2. "rTIL" chunks
 
 
 
this subchunk describes the tiles that make up the region. it's stored
 
in a compact rle-ish representation.
 
 
 
conceptually, a region is some subset of the 1024x1024 tiles in the map.
 
to encode a region, encode it row by row, left to right, top to bottom.
 
 
 
for each row, split it into runs of empty tiles and present tiles. for
 
each run, output one of these bit sequences:
 
 
 
    000nnnnn          - n+1 (1-32) empty tiles in a row
 
    001000nn nnnnnnnn - n+1 (1-1024) empty tiles in a row
 
    010nnnnn          - n+1 (1-32) present tiles in a row
 
    011000nn nnnnnnnn - n+1 (1-1024) present tiles in a row
 
 
 
for the two-byte sequences, the bits in the second byte are the low
 
bits, and the two bits at the end of the first byte are the high bits.
 
 
 
for example, if you have a run of 10 present tiles, you'd output the
 
byte 01001001, or 73 decimal. if you have a run of 300 empty tiles,
 
you'd output 00100001 00101011, or 33 43.
 
 
 
for each row, you must output a sequence of runs that sum to exactly
 
1024 tiles. anything else (missing tiles at the end of a row, or a run
 
that extends past the end of the line) is an error.
 
 
 
there are two exceptions to the above rule: first, rows that contain no
 
tiles at all can (optionally) be encoded specially:
 
 
 
    100nnnnn          - n+1 (1-32) rows of all empty
 
    101000nn nnnnnnnn - n+1 (1-1024) rows of all empty
 
 
 
second, if the same pattern of tiles appears in more than one
 
consecutive row, you can use these special codes to save more space:
 
 
 
    110nnnnn          - repeat last row n+1 (1-32) times
 
    111000nn nnnnnnnn - repeat last row n+1 (1-1024) times
 
 
 
the rTIL chunk must describe exactly 1024 rows. this might require only
 
two bytes (163 255 for the totally empty region), or it might require
 
much more.
 
 
 
note: several bit patterns don't correspond to any of the above codings.
 
that's deliberate. don't use them.
 
 
 
3.2.2.3. "rBSE" chunks
 
 
 
this is a 0-byte chunk. its presence signifies that this region should
 
be considered a "base".
 
 
 
3.2.2.4. "rNAW" chunks
 
 
 
this is a 0-byte chunk. if present, antiwarp should be disabled for
 
ships in this region. currently, this disabling happens on the server,
 
and players whose antiwarp is being disabled aren't necessarily aware of
 
it. it would be nice if in the future continuum understood this feature
 
so that it could inform the player that antiwarp is unavailable in this
 
location.
 
 
 
3.2.2.5. "rNWP" chunks
 
 
 
this is a 0-byte chunk. if present, all weapons are non-functional in
 
this region. the same notes apply to this feature as to the no antiwarp
 
feature.
 
 
 
3.2.2.6. "rNFL" chunks
 
 
 
this is a 0-byte chunk. if present, any flags dropped in this region are
 
respawned as neutral flags in the center of the map (or wherever the
 
settings indicate they should be spawned).
 
 
 
3.2.2.7. "rAWP" chunks
 
 
 
this chunk, if present, turns on the auto-warping feature. any player
 
entering this region will be immediately warped to the specified
 
destination.
 
 
 
the data for this chunk specifies the destination, in this format:
 
 
 
struct autowarp_destination {
 
    i16 x;          // the destination x coordinate, 1-1023, 0 for the
 
                    // default, or -1 for the player's current x coordinate.
 
    i16 y;          // the destination y coordinate.
 
    char arena[16];  // the destination arena name. null if the warp
 
                    // does not cross arenas.
 
};
 
 
 
as a simple space optimization, if the warp does not cross arenas, you
 
can leave out the 16 bytes of arena name, so that the whole chunk data
 
is 4 bytes long.
 
 
 
3.2.2.8. "rPYC" chunks
 
 
 
this chunk lets you embed code in level files. the exact semantics of
 
this data haven't yet been determined, but it'll probably go something
 
like this:
 
 
 
this chunk should contain ascii data representing some python code. the
 
code will be executed when the map is loaded, and it may define several
 
functions: a function named "enter", if it exists, will be call each
 
time a player enters this region. it will be called with one argument,
 
which is the player who entered the region. a function named "exit"
 
works similarly, except of course it gets called when someone leaves.
 
 
 
 
 
3.2.3. "TSET" and "TILE" chunks
 
 
 
these chunk types are intented to be used only in the far future, when
 
all lvl files use the extended format, and the backwards-compatible
 
format described so far doesn't have to be used. such files will start
 
with the "elvl" metadata header described above, and they will contain
 
the tileset bitmap and tile data as chunks.
 
 
 
the format of a "TSET" chunk is a windows format bitmap, _without_ the
 
bitmapfileheader stuff (because its function is taken care of by the
 
chunk header). that is, it starts with a bitmapinfoheader, which is
 
followed directly by the color table, which is followed directly by the
 
bitmap data. the bitmap data should be in 8-bit format with no
 
compression.
 
 
 
the format of a "TILE" chunk is just tile data, in the same format it's
 
always been in:
 
 
 
struct tile {
 
    unsigned x : 12;  // range 0-1023, upper two bits should be 0
 
    unsigned y : 12;
 
    unsigned tile : 8;
 
};
 
 
 
there should be no more than one of each of these chunks in a file. one
 
file should not contain both an ETST and a TSET chunk. if a file
 
contains neither of those two types, the default tileset should be used.
 
 
 
 
 
4. comments
 
 
 
if you have an suggestions for improving the file format or this
 
document, email them to grelminar@yahoo.com, or post them on the forums
 
at http://forums.minegoboom.com/
 
 
 
 
 
5. history
 
 
 
version 0.3:
 
  - removed ETST chunks, since cont basically supports this
 
    functionality already through tiles.bm2
 
 
 
version 0.2:
 
  - better format for region tile data
 
 
 
version 0.1:
 
  - initial version
 
</pre>
 
 
 
[[Category: Formats]]
 
[[Category: Map]]
 

Revision as of 03:37, 30 November 2005

apple cows