This is the format used by levels in Jazz Jackrabbit 2 versions 1.00g and 1.00h. It is not a direct analogue of j2l files in 1.10 and higher, since it also contains the tileset data found in j2t files. The files are also not compressed, resulting in much larger filesizes.
.LEV files contain a number of nestable sections headed by FourCCs. Each section begins with a long encoding the length of that section minus the FourCC and the long. Thus the DDCF section, which contains all the other sections, has a length long that is the length of the file minus eight.
struct EDIT { long SectionLength; byte MLLEFocusedLayer; // the current layer at time of saving string TilesetImageFilename; // the original .anm file long NumberOfTiles; byte unknown = 0; string LayerName[8]; byte Padding[]; // pad the section length out to 196 }
struct EDI2 { long SectionLength = 4108; long One = 1; long TenTwentyFour = 1024; byte Zeroes[4100]; // all zeroes }
struct LINF { long SectionLength; short ChunkVersion = 258; // JJ2 gives error otherwise string LevelName; string BonusLevel; string MusicFile; string NextLevel; // minus the file extension string SecretLevel; long MinLight; // multiply by 1.5625 to get Set Light-compatible value long StartLight; // same long unknown3[8]; byte Padding[]; // pad the section length out to a multiple of four }
struct HSTR { long SectionLength; short MaxLength = 256; // maybe? string HelpString[16]; byte Padding[]; // pad the section length out to a multiple of four }
struct TILE { long SectionLength; long ChunkVersion = 263; // JJ2 gives error otherwise section INFO; section DATA; section EMSK; section MASK; section ANIM; section FLIP; }
struct INFO { long SectionLength; long NumberOfTiles; byte TileType[NumberOfTiles-1]; // starts at tile 1, not 0 byte Padding[]; // pad the section length out to a multiple of four }
struct DATA { long SectionLength; Tile TileType[NumberOfTiles-1]; //tile 0 is always blank //and therefore is not recorded }
struct Tile { byte TrasparencyFlags; // bit4: Part0 is nontransparent // bit5: Part1 is nontransparent // bit6: Part2 is nontransparent // bit7: Part3 is nontransparent Part TilePart[4]; }
struct Part (nontransparent) { byte PaletteColor[16][16]; }
struct Part (transparent) { short Size; //Length of following data short Width = 16; short Height = 16; byte Data[Size-4]; //RLE encoded data }the Data starts with an infobyte of the structure: F00COUNT where the F bit indicates transparency (0 if transparent). the COUNT bits is the amout of pixels with the F attribute. If not transparent then the following COUNT bytes are nontransparent pixel data then comes another infobyte. If transparent, the pixels are not stored of course, and the next byte is another infobyte. If the COUNT bits = 0 (and F=1) then the row is finished and the rest of the line should be filled with transparent pixels.
An additional encoding of the transparency mask of the tileset. Pretty similar in style to the clipping masks in JJ1: each tile is broken down into sixty-four 4×4 sections, and each bit specifies the transparency of that section: 1 if any of the pixels in it are transparent, 0 if the whole section is opaque.
struct EMSK { long SectionLength; byte FourXFour[NumberOfTiles][8]; }
The clipping masks for the various tiles used in the level. However, not every tile has a mask, and trying to touch a tile without a mask assigned crashes JJ2.
Following the standard length long is a series of every masked tile in the level. A tile begins with a short giving its number (zero-indexed). If the sixteenth bit of this short is 0, then the next 128 bytes are the clipping mask of that tile, one bit per pixel, four bytes per row. If the sixteenth bit is 1, then the next two bytes are a short giving the number of another tile with the same mask. So 02 80 01 00 means that the third tile (02 00) has the same mask as the second tile (01 00).
At the end of the section is an 0xFFFF short as an instruction to stop reading, since there is no explicit statement of how many masked tiles there are.
struct ANIM { long SectionLength; long NumberOfAnimations; Animated_Tile Animation[NumberOfAnimations]; }
struct Animated_Tile { short FrameWait; short RandomWait; short PingPongWait; bool PingPong; char Speed; char FrameCount; short Frame[FrameCount] }
struct FLIP { long SectionLength; short FlippedTile[SectionLength/2-2]; short SectionTerminator = 0xFF; }
struct LAYR { long SectionLength; long ChunkVersion = 263; // JJ2 gives error otherwise section INFO; section DATA; section EVNT; }
struct INFO { long SectionLength; LayerInfo LayerProperties[8]; }
struct LayerInfo { long LayerFlags; // bit0: Tile Width // bit1: Tile Height // bit2: Layer has tiles // bit3: Limit Visible Region // bit4: Texture mode short LayerWidth; short LayerHeight; short ZAxis; // nothing happens when you change these byte Type; // No known effect. Name from Michiel. long SpeedSettings; // bit0: include unknown byte // bit1: include X/Y Speeds // bit2: include Auto X/Y Speeds byte DetailLevel; //if SpeedSettings bit0. //Only appears in battle1 and battle3, for //layer 5 only, where it is 02 both times. //No known effect. Name from Michiel. long LayerXSpeed; //if SpeedSettings bit1 long LayerYSpeed; //if SpeedSettings bit1 long LayerAutoXSpeed; //if SpeedSettings bit2 long LayerAutoYSpeed; //if SpeedSettings bit2 }
struct DATA { long SectionLength; short AnimOffset = 1024 - NumberOfAnimations; short NumberOfWords; short unknown = 0; // always zero? short Word[NumberOfWords][16]; short LayerLayout[8][Ceiling(LayerWidth/16)*LayerHeight]; }
struct EVNT { long SectionLength; long Event[Layer4Width*Layer4Height]; }
struct TMAP (without a textured background) { long SectionLength; short ChunkVersion = 257; // JJ2 gives error otherwise byte Zeroes6; //all zeroes } struct TMAP (with a textured background) { long SectionLength; short ChunkVersion = 257; // JJ2 gives error otherwise long One = 1; long Seven = 7; long Zero = 0; byte TexturedBackground65536; //every pixel in layer 8 }
struct CMAP { long SectionLength; long Colorcount = 256; // seems always to be 256? byte unknown = 1; // always one? byte Color[256][3]; // channels are in the order R,G,B byte Padding[]; // pad the section length out to a multiple of four }
Jazz2Online © 1999-INFINITY (Site Credits). We have a Privacy Policy. Jazz Jackrabbit, Jazz Jackrabbit 2, Jazz Jackrabbit Advance and all related trademarks and media are ™ and © Epic Games. Lori Jackrabbit is © Dean Dodrill. J2O development powered by Loops of Fury and Chemical Beats.
Eat your lima beans, Johnny.