Register FAQ Search Today's Posts Mark Forums Read
Go Back   JazzJackrabbit Community Forums » Open Forums » General Jazz Jackrabbit Talk

.lev file format research thread

Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 6, 2011, 01:53 PM
Violet CLM is offline
Reply With Quote
.lev file format research thread

This thread is to be used to coordinate research into the structure of the LEV files used by Jazz 2 versions 1.00g and 1.00h. You can find and download them easily enough on your own if you don't have them already. Helpful links:
Start of the file:
Code:
char Signature[4] = "DDCF";
long FileLength; // actually length minus eight
char Section1[4] = "EDIT";
long Unknown; // always 196?
char LengthOfTilesetFilename;
char TilesetFilename[LengthOfTilesetFilename];
char Unknown;
long Unknown; // always 2?
Then follow names for all eight layers, each preceded by single chars specifying their string lengths, then a series of null bytes padding until the size reaches 212. Next is the "EDI2" label, signalling the start of another section containing... what?

The "EVNT" section near the end contains the event map, and seems by all indications to have the same structure as Data2 in J2L files. (As far as I was able to discover some years back, Springcord is the only event that works in 1.00 but not 1.23.) The "CMAP" section is the tileset palette, and does not include alpha values.

The "HSTR" (Hint String) section near the top is pretty simple, although different from the .j2l equivalent. First is a long that gives the length of the whole section, minus four. Then a short that looks always to be 256, which I'm guessing is the maximum length of a hint string. Finally (at least) sixteen sets of length char + string, just like for the layer names. Unused hint strings are simply a single null byte, indicating that the length of the string is 0. It looks like there's a little padding going on, since the number of null bytes at the end is not always 16-number of other hint strings.

The "TILE" section appears to begin the tileset section of the file (minus the palette). It consists of two longs, and the first is the distance to the LAYR section.

The first "INFO" section is the "tile types," which in 1.00 basically just means translucent or not. There's a long encoding the remaining length of the section (minus that long), and then ANOTHER long encoding the remaining length of the section (so, minus both longs), and then one byte per tile. Interestingly, while Castle1 uses the full 660-tile version of the tileset, Race1, Trainer, and Battle1 all contain the original 540-tile version.
__________________

Last edited by Violet CLM; Aug 14, 2011 at 07:24 PM.
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 6, 2011, 02:45 PM
Violet CLM is offline
Reply With Quote
This post is dedicated to listing the various sections within a .lev file, and as time goes on, hopefully giving their function and linking to posts about them. Might have missed some, of course.
  • DDCF: Length of whole file
    • EDIT: Tileset filename and layer names
    • EDI2: Same in every file; probably originally used for saving or editing or something
    • LINF: Level Information (level name, next level, music, some other stuff?)
    • HSTR: Hint Strings (text)
    • TILE: Length of tileset section, plus another long of unknown purpose
      • INFO: Tile types (translucent or not)
      • DATA: Tileset image data
      • EMSK: (bunch of longs)
      • MASK:
      • ANIM: Probably the animated tiles
      • FLIP: List of all tiles appearing flipped in the level
    • LAYR: Length of layers section, plus another long of unknown purpose
      • INFO: Layer properties (size, speeds, etc.)
      • DATA: Level layout
      • EVNT: Event map (data2 in .j2l)
    • TMAP: Whether layer 8 is textured or not
    • CMAP: Color Map (palette)
__________________

Last edited by Violet CLM; Aug 14, 2011 at 10:02 AM.
zapS zapS's Avatar

JCF Member

Joined: Jan 2005

Posts: 84

zapS is doing well so far

Aug 9, 2011, 10:21 AM
zapS is offline
Reply With Quote
The fourcc's identifying a section are (afaik) always followed by a 4-byte length-value representing the size of the section minus the fourcc and the length value(8 bytes total).

So this:
long Unknown; // always 196?
is the size of the "EDIT"-section.
zapS zapS's Avatar

JCF Member

Joined: Jan 2005

Posts: 84

zapS is doing well so far

Aug 9, 2011, 11:20 AM
zapS is offline
Reply With Quote
Here follows the structure of the DATA section in the TILE section.
It contains the image data of the tileset.

The DATA section:
Code:
char	Head[4] = "DATA";
int32	Size;			//Size of following data chunk (minus head & size)
Tile	Tiles[tilecount];	//The tilecount is probably in the TILE or INFO sections
The "Tile" structure:
Code:
byte	TrasparencyFlags;    //This shows which parts the bits represent: 43210000
Part	TilePart[4];
Each tile is divided into four 16x16 images, appearing in the order:
topleft, topright, bottomleft, bottomright.
These parts use RLE if they contain transparency.
The most significant half of the TransparencyFlags byte contains flags for each part.
Flags are set if the part is nontransparent, and unset if transparent(RLE encoded).

The "Part" structure:
if the part is nontransparent then it's really simple
Code:
byte data[16][16];
a transparent one is more complicated though
Code:
int16	Size;  //Length of following data
int16	W = 16;  //Probably width and height since they're always 16
int16	H = 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.
zapS zapS's Avatar

JCF Member

Joined: Jan 2005

Posts: 84

zapS is doing well so far

Aug 9, 2011, 11:50 AM
zapS is offline
Reply With Quote
The CMAP section is alot simpler.
Code:
char  CMAP[4] = "CMAP"; 
int32 Length = 776;
int32 Colorcount = 256; //not sure about this but it's always 256 so i guess its the colorcount
byte  Unknown = 1;  // always 1 afaik
byte  Colors[256][3]; // channels are in the order r,g,b
byte  padding[3]={0,0,0}; // probably to make it finish on a 4-byte boundary
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 9, 2011, 12:31 PM
Violet CLM is offline
Reply With Quote
__________________
Jerrythabest Jerrythabest's Avatar

JCF Member

Joined: Apr 2005

Posts: 2,602

Jerrythabest is a forum legendJerrythabest is a forum legendJerrythabest is a forum legend

Aug 12, 2011, 01:11 PM
Jerrythabest is offline
Reply With Quote
Restoring lost posts from old hosting provider
Quote:
Originally Posted by Jerrythabest View Post
Quote:
Originally Posted by zapS View Post
The fourcc's identifying a section are (afaik) always followed by a 4-byte length-value representing the size of the section minus the fourcc and the length value(8 bytes total).

So this:
long Unknown; // always 196?
is the size of the "EDIT"-section.
This appears to be true, except for the first (DDCF) block in the file, which is always 8 bytes ("DDCF" + a long).

The file can be quickly skipped through by:

Code:
skipBytes(8);
while(bytesLeft()){
  skipBytes(4);
  skipBytes(readLong());
}
And thus, a particular block can be reached easily by:

Code:
skipBytes(8);
while(bytesLeft()){
  if(readBytes(4) == "TMAP")  //To reach the TMAP block
    break;
  skipBytes(readLong());
}

Also, I'm missing something in UR's EDIT block. (A char is a one-byte value, right?)

Code:
char Section1[4] = "EDIT";
long SectionLength;
char Unknown; // I see this byte in my Battle1.lev file?
char LengthOfTilesetFilename;
char TilesetFilename[LengthOfTilesetFilename];
char Unknown;
long Unknown; // always 2?
Quote:
Originally Posted by Unknown Rabbit View Post
Just to reply quickly without considering the rest of your post, the DDCF section actually contains all the other sections within it, so the long is the length of the whole file minus eight. It's something like this:
  • DDCF
    • EDIT
    • EDI2
    • LINF
    • HSTR
    • TILE
      • INFO
      • DATA
      • EMSK
    • FLIP
    • LAYR
    • INFO
    • DATA
    • EVNT
    • TMAP
    • CMAP
Quote:
Originally Posted by Jerrythabest View Post
Ah, that's indeed a better way to put it. Also, the LAYR block contains the second INFO/DATA blocks... so it's actually like this:

  • DDCF
    • EDIT
    • EDI2
    • LINF
    • HSTR
    • TILE
      • INFO
      • DATA
      • EMSK
      • FLIP
    • LAYR
      • INFO
      • DATA
      • EVNT
    • TMAP
    • CMAP
Quote:
Originally Posted by Jerrythabest View Post
I've began working on the LAYR blocks.

Code:
char       BlockHeader[4] = "LAYR";
long       BlockLength; // Total length of the following INFO, DATA and EVNT blocks + 4
long       Unknown;

char       InfoHeader[4] = "INFO";
long       InfoLength; // Length of this block, excluding InfoHeader and InfoLength (as usual)
LayerInfo  LayerProperties[8]; // As specified below

char       DataHeader[4] = "DATA";
long       DataLength;
(layer data follows, I haven't figured it out yet)
The LayerInfo structure mentioned above (assuming you're using the name 'short' for a 2-byte value?):
Code:
long  LayerFlags; // Only the lower 5 or so bits appear to be in use:
                  //   bit0: Tile X
                  //   bit1: Tile Y
                  //   bit2: ? (either 2 or 3 is Limit
                  //   bit3: ?   Visible Region)
                  //   bit4: Texture mode
short LayerWidth;
short LayerHeight;
char  Unknown[7]; // Still need to look into these bytes
short LayerXSpeedMarginal; // See discussion below!
short LayerXSpeed;
short LayerYSpeedMarginal;
short LayerYSpeed;
Some notes about the layer speeds:
-They appear to be missing entirely for Layer 8 (so the LayerInfo structure is actually 8 bytes shorter for the last layer!)
-The LayerXSpeed/LayerYSpeed fields seem to be the 'integer' part of the layer speeds ('1' syncs with player movement, '2' goes twice as fast etc.), whereas the LayerXSpeedMarginal/LayerYSpeedMarginal values seem to be fractional (even set to the maximum value it's very slightly less than 1). I'm not an expert in floating point representations, so if this is in complience with any standards feel free to teach me about it
Quote:
Originally Posted by Unknown Rabbit View Post
What you're calling LayerFlags looks to have the same structure as LayerMiscProperties on the wiki, which... isn't documented. Whoops. Assuming they are the same, though, the bits are in order Tile Width, Tile Height, Limit Visible Region, Texture Mode, and Parallax Stars. The same goes for the X and Y speeds: just like in .j2l files they're stored in longs as multiples of 65536.
(So layer 8 in .lev files is completely incapable of having its speeds even set, let alone used? That's brilliant.)
Quote:
Originally Posted by Jerrythabest View Post
Ah, multiples of 65536, that's a funny way of describing it JCS simply divides by 65536 when reading the values into those Layer Properties boxes and multiplies by 65536 again upon saving... so that's how.

I'm not sure about Parallax Stars being bit4, if I turn it off in Carrot1 the texured background returns to a plain one? Or have I been screwing up some bits here?


About Layer 8's immobility:

This image is a screenshot of Castle1's LAYR-INFO block, with one layer on each row.


EDIT: Another thing I noticed and that might be interesting... many of these layer properties are stored in .j2l on a per-property basis (as opposed to the per-layer basis in .lev files). But after scanning for, for example, layer speeds in the game's memory I actually found them listed one after the other in memory. Just like they are in .j2l files.
I don't know much about the differences between 1.00g and 1.00h, but for the record: I've seen this in 1.00h.
Quote:
Originally Posted by Unknown Rabbit View Post
Okay, did some actual tinkering instead of just looking at the wiki, and you're right. Limit Visible Region is bit3, and bit2 is HasTiles, that is, whether or not the layer is drawn at all. Parallax stars hadn't been implemented yet in 1.00g; if you turn off texture mode in the levels that do seem to have it, you see that the dots are simply drawn on the textured background manually.

I would be hesitant at best about paying too much attention to the memory layout for anything but save files.

Concerning your mystery bytes, the fourth controls the (storage of the) layer speeds. If the second bit(2) is set, then the seven unknown bytes are followed by two longs storing X Speed and Y Speed. If the third bit (4) is set, then there are two longs storing Auto X Speed and Auto Y Speed. (If both are set, speed precedes auto speed.) Haven't found any examples of the first bit (1) being set yet, but it definitely has some effect, unlike the fourth (8).

Since the last three of the mystery bytes seem always to be zero and don't seem to change anything, I'm guessing that layer speed byte is actually a long, similar to the LayerFlags long. The first two bytes of the seven are a short indicating what the wiki calls Z-Axis (-300, -200, -100, 0, 100, 200, 300, 400), but just like in 1.23, altering them has no effect. Not sure about the third byte yet...
Quote:
Originally Posted by Jerrythabest View Post
Aha, so that's why I couldn't find any auto speed settings in the levels I looked at

Layer 8 can be made to move automatically, but it won't obey 'normal' speed settings.
__________________

Last edited by Jerrythabest; Aug 12, 2011 at 01:22 PM.
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 12, 2011, 02:30 PM
Violet CLM is offline
Reply With Quote
Early thoughts on [LAYR]DATA: there doesn't seem to be any equivalent of the dictionary/words found in .j2l files. Instead, the layers (the ones that have tiles, at least -- just like in .j2l files, it looks like layers without tiles do not have their empty contents saved at all) are laid out pretty much short by short, but with some data missing. In the only level I've looked at in any detail (TREASUR1, chosen because it has no foreground layers) instances of sixteen consecutive blank tiles are not included. So far I haven't figured out where in the file it indicates where those blocks of sixteen need to be inserted. Also it looks like layers with Tile Width whose widths are not multiples of 4 16 may get some padding, but that's a very tentative result so far. Haven't run across any flipped or animated tiles yet.
__________________

Last edited by Violet CLM; Aug 14, 2011 at 03:58 PM.
Jerrythabest Jerrythabest's Avatar

JCF Member

Joined: Apr 2005

Posts: 2,602

Jerrythabest is a forum legendJerrythabest is a forum legendJerrythabest is a forum legend

Aug 13, 2011, 09:23 AM
Jerrythabest is offline
Reply With Quote
Maybe we should look into [TILE]INFO, [TILE]EMSK and [TILE]FLIP so we better understand how flipped tiles and (possibly, hopefully) animations are stored.

It shouldn't be too difficult to find them in layers though, so we know how they're referenced.
__________________
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 13, 2011, 12:09 PM
Violet CLM is offline
Reply With Quote
[TILE]INFO I describe in the opening post. It's the "Tile Types," which just means Translucent here because 1.00g only runs in full screen. Also I just noticed two additional sections between EMSK and FLIP: MASK and ANIM.

FLIP is really simple: it's a list of every tile (referenced by shorts, of course) that appears flipped somewhere in the level. Then I guess it ends in 0xFFFF, which is strictly unnecessary because the number of tiles could be deduced from the length long at the beginning, but whatever. ETA: Found some flipped tiles in [LAYR]DATA, and it's just the same as in .j2l files, the eleventh bit (1024) is set to 1.

ANIM is also simple. First there's the obligatory long giving the remaining length of the section, then a long specifying how many animations are present in the level, and then those animations. As far as I can tell, the only difference between them here vs. in .j2l files is that in .j2l, there are sixty-four frame shorts regardless of how many frames the animation actually uses, whereas in .lev, there are only as many as necessary.
Code:
struct Animated_Tile
{
    short FrameWait;
    short RandomWait;
    short PingPongWait;
    bool PingPong;
    char Speed;
    char FrameCount;
    short Frame[FrameCount]
}
(Note: I didn't actually make sure that the first seven bytes are as given, but since everything else lines up, I saw no reason to doubt it.)

TMAP, as far as I can tell, has only two different contents and appears to indicate whether the background is textured or not? Yeah, I dunno. Maybe it's an instruction to JJ2 to create the appropriate texture resources. In any case, that does appear to be the pattern:

0101000000000000:
BATTLE1, BATTLE2, BATTLE3, BATTLE4, BEACH, BEACH2, CASTLE1, CASTLE1N, COLON1, COLON2, DAMN, DAMN2, HELL, HELL2, LABRAT1, LABRAT2, LABRAT3, MEDIVO1, MEDIVO2, RACE1, RACE2, RACE3, RACE4, SHARE1, TRAINER, TREASUR1, TREASUR2, TREASUR3, TUBE1, TUBE2, TUBE3

0101010000000700:
CARROT1, CARROT1N, DIAM1, DIAM3, JUNG1, JUNG2, PSYCH1, PSYCH2, PSYCH3, SHARE2, SHARE3

Similarly, I checked programmatically, and EDI2's contents are exactly the same in every single .LEV file, so I don't think it's worth worrying about.
__________________

Last edited by Violet CLM; Aug 14, 2011 at 03:51 PM.
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 14, 2011, 05:37 PM
Violet CLM is offline
Reply With Quote
Got it! [LAYR]DATA makes sense now. It's data3 and data4 from .j2l files in a single section with no break between them, except instead of four tiles long, the words are sixteen tiles long. That's why I thought the sections of sixteen blank tiles were missing -- it wasn't the layer I was looking at, it was the pieces of the layer. The frontmatter of the section is a length long, a short (MAXTILES-AnimCount), another short (number of words), and then another short that may always be zero. Now all that's left is EMSK, MASK, and a few miscellaneous shorts and longs here and there.

ETA: I've put what we've figured out so far up on the ERE.
__________________

Last edited by Violet CLM; Aug 14, 2011 at 07:25 PM.
Sievn

JCF Member

Joined: Jun 2011

Posts: 1

Sievn is doing well so far

Aug 16, 2011, 01:23 AM
Sievn is offline
Reply With Quote
I wonder if its possible to open the 32X32 Templates Files that are inside the data file to change the title screen. So far I haven't found a program does open those template files.
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 16, 2011, 01:51 AM
Violet CLM is offline
Reply With Quote
I would suggest using this thread, or heck maybe this one. This is all .lev all the time.

ETA: Concerning the SpeedSettings byte in [LAYR]INFO: if the first bit is set, then there's another byte between the SpeedSettings byte and the (potential) X/Y speeds. This byte appears only in battle1 and battle3, where both times it appears only for layer 5 and has the value of 02. It corresponds to the unknown2 bytes in .j2l files, which are also 02 for layer 5 in those levels only and 00 everywhere else. The values of the unknown2 bytes are read and saved intact by JCS, but I can't get them to do anything when changed, so... mystery "solved."
__________________

Last edited by Violet CLM; Aug 17, 2011 at 04:51 PM.
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 17, 2011, 06:37 PM
Violet CLM is offline
Reply With Quote
All right, I'm pretty sure I understand what's going on with the MASK section. It's the clipping mask (EMSK is the transparency mask), and each tile within it begins with a short giving that tile number. If the sixteenth bit is 0, then the following 128 bytes give the clipping mask for that tile, one bit per pixel, four bytes per row. If the sixteenth bit is 1, then instead that short is followed by another short giving the id of another (previously listed) tile whose mask this current tile shares. So 02 80 01 00 means that the third tile (02 00) has the same mask as the second tile (01 00).
However, not all the tiles actually have masks. At a guess, I'd say only the ones that are used somewhere in the level (or in layer 4?), but that could be wrong. In any case, if a tile doesn't have a mask it's just not listed in the file at all, which works fine because every tile specifies its id. Maskless tiles display fine in-game, but if you try to touch one, the game crashes.
__________________
Jerrythabest Jerrythabest's Avatar

JCF Member

Joined: Apr 2005

Posts: 2,602

Jerrythabest is a forum legendJerrythabest is a forum legendJerrythabest is a forum legend

Aug 20, 2011, 02:22 AM
Jerrythabest is offline
Reply With Quote
I've been away for a few days and I see a lot is revealed in the past week, awesome work! Are there any sections left you'd like me to look into? Otherwise I could possibly run though them all once more to see if I can say anything about the unknown bits and pieces.


What you've found out about the MASK section is very interesting. Apparently, a single tile in the tileset could have a different mask in different levels. But even more interestingly, I'd expect there should have been some sort of tileset file back then, containing the clipping mask of all its tiles. MLLE would then copy the relevant ones, plus the complete tileset image, into the .lev files.
__________________
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 20, 2011, 05:33 PM
Violet CLM is offline
Reply With Quote
Quote:
Originally Posted by Jerrythabest View Post
I've been away for a few days and I see a lot is revealed in the past week, awesome work! Are there any sections left you'd like me to look into? Otherwise I could possibly run though them all once more to see if I can say anything about the unknown bits and pieces.
EMSK is the big mystery, at least as far as format goes. It's an additional encoding of the transparency mask, so it's absolutely useless for loading (all that already being found in [TILE]DATA) but still necessary for saving. I think all that's left besides that is a bit bytes and shorts here and there which mostly seem to have constant values anyway.

Also, visualizing [TILE]DATA reveals I was simplifying [TILE]INFO. Translucent tiles in .lev files are fully opaque in terms of [TILE]DATA transparency, with a special dedicated transparent color. It's strange. Screenshot later.

Quote:
What you've found out about the MASK section is very interesting. Apparently, a single tile in the tileset could have a different mask in different levels.
Well, that much was apparent just looking at the contents of the folder, since there are no tileset files. It's a step between JJ1, which included mask in the level file and graphics in a separate file, and 1.10+, which includes mask and graphics in the same file. Of course, since the tileset itself is included in the level file, and may potentially vary across levels (e.g. Trainer vs. Castle1), the extent to which it's literally the same tileset that has the two different masks is somewhat limited.

Quote:
But even more interestingly, I'd expect there should have been some sort of tileset file back then, containing the clipping mask of all its tiles. MLLE would then copy the relevant ones, plus the complete tileset image, into the .lev files.
This would make perfect sense for them to have done, but I'm not totally sure it's accurate as framed. The EDIT section includes the tile graphics filename, that is, the original .anm file, but nothing about a tileset file that would also have included clipping and transparency masks. It's possible that there was a third masking file separate from the level file and the tileset graphics, which they loaded up each and every time they wanted to edit a level and wasn't necessarily bound to any individual tileset graphics file, but I think it's more likely that they just made one level with a tileset (/tileset group, in the case of day/night versions) and then copied it for later levels, so that the mask work that they'd already done would be intact. They did this a lot for JJ1, particularly copying LEVEL0.001 for creating boss levels, so it makes sense that they'd do it again for JJ2.

(Of course, that's all rampant speculation based almost exclusively on a .anm extension. It should hopefully be possible to say more once I get around to visualizing the masks. If tiles are masked in a level that aren't used in that level, but are used in a different, perhaps earlier level, that's a clue that they weren't imported automatically from a separate dedicated masking file. On the other hand, if each level has masks for all and only those tiles used (in layer 4), then you may well be right.)
__________________
Jerrythabest Jerrythabest's Avatar

JCF Member

Joined: Apr 2005

Posts: 2,602

Jerrythabest is a forum legendJerrythabest is a forum legendJerrythabest is a forum legend

Aug 21, 2011, 12:47 AM
Jerrythabest is offline
Reply With Quote
I'll be looking forward to your visualizations I think this is a fun piece of 'JJ paleontology'

I'll look into EMSK to see if I can figure it out.


EDIT: Something just popped into my mind. JCS also saves which layer you're looking at. In the J2L format specification in the ERE, I can't find where this is stored (though there are JCS Focus positions). I think this is known but just not documented, just like the layer properties flag bits? Anyway, I suspect the 'char Unknown' I found missing in UR's EDIT block is actually the layer number that MLLE was focussed on upon saving, 0-based. It's 3 in many levels (which means they were editing the Sprite Layer). This is just a random thought though, I don't have any proof. Also, if this is correct, we should probably also find some MLLE Focus positions somewhere.
__________________

Last edited by Jerrythabest; Aug 21, 2011 at 06:18 AM.
Jerrythabest Jerrythabest's Avatar

JCF Member

Joined: Apr 2005

Posts: 2,602

Jerrythabest is a forum legendJerrythabest is a forum legendJerrythabest is a forum legend

Aug 21, 2011, 05:33 AM
Jerrythabest is offline
Reply With Quote
The size of EMSK is 8 * tileCount. So each tile in the tileset has 8 bytes, or 64 bits.
The tiles are split up into 64 blocks (8 rows, 8 columns, each covering 4x4 pixels).
Each of the 64 bits flags for one of the 64 blocks of the tile, beginning in the upper left corner, row by row. The bit is set if any of the 16 pixels in the block is transparent. The bit is not set if the whole block is opaque.

EDIT #1: tiles with their INFO byte set to 5 have all bits set.

EDIT #2: (EDI2 haha) About the INFO block: on the ERE it is stated that it contains no byte for the first tile since it's always blank. However, this does not seem to be the case: the length of the block (excluding the fourCC and the two longs in the beginning) is always [numberOfTiles]; it's even always a multiple of 10.

EDIT #3: I've uploaded program output about Castle1, Battle1 and Labrat1. Output begins with "TILE INFO", then all tiles with nonzero INFO bytes (tile# : value) are listed, then "EMSK", followed by a black-and-white visualisation of the EMSK block. Black parts are unset bits, white are set. (NOTE: it's not really an image, but actually a rather large (~4 MB) HTML table. It renders cleanly in Firefox but it's anything but standards complient so it may look buggy in other browsers.)

EDIT #4: JJ2 somehow uses the data in EMSK to determine which parts of the background layers (including layer 4) need to be drawn. Setting all bytes in EMSK to zeroes makes layers 4-8 completely invisible. I couldn't find out how exactly JJ2 uses EMSK to determine this.
__________________

Last edited by Jerrythabest; Aug 21, 2011 at 09:41 AM.
Jerrythabest Jerrythabest's Avatar

JCF Member

Joined: Apr 2005

Posts: 2,602

Jerrythabest is a forum legendJerrythabest is a forum legendJerrythabest is a forum legend

Aug 21, 2011, 08:31 AM
Jerrythabest is offline
Reply With Quote
I just tried something in TMAP: changing the 01 01 bytes into 00 00 in the beginning of Castle1's TMAP gives me a very informative crash: "TMAP section version unrecognised". So if those shorts that are defnied 'Version; //maybe?' on the ERE are really section version numbers it shouldn't be difficult to have JJ2 confirm this!
__________________

Last edited by Jerrythabest; Aug 21, 2011 at 09:38 AM.
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 21, 2011, 01:16 PM
Violet CLM is offline
Reply With Quote
Great stuff!

Quote:
Originally Posted by Jerrythabest View Post
EDIT: Something just popped into my mind. JCS also saves which layer you're looking at. In the J2L format specification in the ERE, I can't find where this is stored (though there are JCS Focus positions). I think this is known but just not documented, just like the layer properties flag bits? Anyway, I suspect the 'char Unknown' I found missing in UR's EDIT block is actually the layer number that MLLE was focussed on upon saving, 0-based. It's 3 in many levels (which means they were editing the Sprite Layer). This is just a random thought though, I don't have any proof. Also, if this is correct, we should probably also find some MLLE Focus positions somewhere.
The current layer in .j2l is something I've never personally gone looking for, so it's not on the ERE even though it is probably "known" to some other people. I can't imagine it would be at all hard to find.

Anyway, that makes a lot of sense for that byte, given that it's in the EDIT section. Here's something a fair bit closer to proof: it's 03 in most places, but it's 02 in TUBE3, and when you open tube3.j2l in JCS then it's viewing layer 3 there as well. I guess they cleared layer 4 before clearing layer 3, and that was all they ever did with it before converting it to .j2l and then never touching it again. Looks like you're right. Certainly I don't notice any effect ingame of changing that byte, not that I'd expect one from anything in the EDIT section.
(I didn't check every single .LEV; there might be others, but TUBE3 struck me as a pretty likely candidate.)

Quote:
Originally Posted by Jerrythabest View Post
EDIT #2: (EDI2 haha) About the INFO block: on the ERE it is stated that it contains no byte for the first tile since it's always blank. However, this does not seem to be the case: the length of the block (excluding the fourCC and the two longs in the beginning) is always [numberOfTiles]; it's even always a multiple of 10.
Oooh, whoops, my bad. That was supposed to be about DATA, not INFO.

Quote:
EDIT #3: I've uploaded program output about Castle1, Battle1 and Labrat1. Output begins with "TILE INFO", then all tiles with nonzero INFO bytes (tile# : value) are listed, then "EMSK", followed by a black-and-white visualisation of the EMSK block. Black parts are unset bits, white are set. (NOTE: it's not really an image, but actually a rather large (~4 MB) HTML table. It renders cleanly in Firefox but it's anything but standards complient so it may look buggy in other browsers.)
Cool! I think you have an off by one error in your INFO tile#s, though. I looked into COLON1 and LABRAT1, and it looks like the transparent color used for translucent tiles is always the second color in the palette. Here's the effects of various values for INFO before I lost interest:
00: normal tile
01: Transparent, used in COLON1
02: Transparent, used in LABRAT1
03: Transparent
04: Access Violation
05: Caption (in the .j2l version of the level), and tile does not display ingame. This explains why in so many levels the caption tiles are copies of other tiles and placed near the bottom of the tileset.
06: Access Violation
07: Access Violation

Quote:
Originally Posted by Jerrythabest View Post
I just tried something in TMAP: changing the 01 01 bytes into 00 00 in the beginning of Castle1's TMAP gives me a very informative crash: "TMAP section version unrecognised". So if those shorts that are defnied 'Version; //maybe?' on the ERE are really section version numbers it shouldn't be difficult to have JJ2 confirm this!
The relevant text from JAZZ2.EXE:
Code:
LINF Chunk version unrecognised by GetLevelName LINF    TMAP Chunk version unrecognised TMAP    CMAP    EVNT    LAYR Chunk version unrecognised LAYR    HSTR    LINF Chunk version unrecognised FLIP    Too many animating tiles    ANIM    MASK    EMSK    DATA    Too many tiles in level INFO    TILE Chunk version unrecognised TILE
It looks like you're right. LINF, LAYR, and TILE are the three sections with those constant version-looking shorts, and that is the constant section of TMAP, whatever the rest is for. Good thinking!


ETA: Here's a list of, as far as I can tell, everything we don't yet understand.
  • An unknown byte in EDIT
  • Two unknown strings in LINF (probably Secret Level and Bonus Level, though which is which?)
  • An unknown byte per layer in [LAYR]INFO
  • Another unknown byte per layer, created by bit0 in the SpeedSettings long and only used in one layer in two levels
  • An unknown short in [LAYR]DATA
  • An unknown byte in CMAP
Other than that, as far as I can tell, we have arrived at a complete specification for .lev files in just over two weeks time. High fives!
or more like a decade's time, depending on how you want to look at it.
__________________

Last edited by Violet CLM; Aug 21, 2011 at 01:57 PM.
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 21, 2011, 08:26 PM
Violet CLM is offline
Reply With Quote
Okay, you win on the MASK front. Here's the first 100 tiles of TRAINER:


And here's RACE3:

Essentially the same tileset, neither likely to have been the first level built with that tileset either, but definitely a different spread of masked tiles. What's more, in every level I've looked at the tiles that have masks are those and only those that appear in layer 4. However, the same masking error on the bottom right tile of the window appears in both levels (and persists in castle1.j2t), so they certainly weren't constructed independently. There must have been some external file after all.
(to forestall questioning, I had MLLE add the checkerboards, they're not part of the original files.)
__________________
Jerrythabest Jerrythabest's Avatar

JCF Member

Joined: Apr 2005

Posts: 2,602

Jerrythabest is a forum legendJerrythabest is a forum legendJerrythabest is a forum legend

Aug 22, 2011, 04:27 AM
Jerrythabest is offline
Reply With Quote
Quote:
Originally Posted by Unknown Rabbit View Post
Cool! I think you have an off by one error in your INFO tile#s, though.
All tile numers are 0-based. In fact I just read the numberOfTiles long and then ran a for-loop like this:
Code:
//Somewhat simplified code
for(int i = 0; i < numberOfTiles; i++){
  byte b = nextByte();
  if(b != 0)
    print("[i:b]");
}

//Actual Java-code (just for the record)
for(int lengte = buf.getInt(), b = 0, i = 0; i < lengte; i++)
  if((b = buf.get()) != 0)
    out.println("[" + i + ":" + b + "]");
Also it's interesting to see they have marked tiles as 'Caption' even though there was no windowed mode back then.
__________________
Jerrythabest Jerrythabest's Avatar

JCF Member

Joined: Apr 2005

Posts: 2,602

Jerrythabest is a forum legendJerrythabest is a forum legendJerrythabest is a forum legend

Aug 22, 2011, 04:55 AM
Jerrythabest is offline
Reply With Quote
After looking at Labrat1.lev's LINF section I come to the following conclusion:
Code:
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; // same
    long MinLight; // multiply by 1.5625 to get Set Light-compatible value
    long StartLight; // same
    byte Padding[]; // pad the section length out (to 80 in most levels, to 88 in labrat 1 & 3)
}
-The field after NextLevel (labrat2) is the SecretLevel field (labrat3).
-The field after Levelname is the only string field left, and thus is the BonusLevel field
-The padding is not always up to 80 bytes, as in labrat 1 and 3 it's actually 88! Why?
__________________
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 22, 2011, 07:02 AM
Violet CLM is offline
Reply With Quote
Soooooooo...
The first custom .lev file.

(The crate is from my attempting to set up a tile cache effect, but it doesn't appear to work in 1.00.)


(LINF: from what I can tell, all sections are padded out to a multiple of four bytes, whatever their contents. That means that LINF doesn't just have a lot of padding; instead, it has eight (layer-related?) longs, all of which seem always to be zero, prior to the padding.)
__________________
cooba cooba's Avatar

JCF Veteran

Joined: Jan 2004

Posts: 7,812

cooba is a glorious beacon of lightcooba is a glorious beacon of lightcooba is a glorious beacon of lightcooba is a glorious beacon of lightcooba is a glorious beacon of lightcooba is a glorious beacon of light

Aug 22, 2011, 07:23 AM
cooba is offline
Reply With Quote
Great job, everyone! Never before has it felt so novel to see Mez01.

Have you yet checked if the alternate textured background effects exist in 1.00?
Jerrythabest Jerrythabest's Avatar

JCF Member

Joined: Apr 2005

Posts: 2,602

Jerrythabest is a forum legendJerrythabest is a forum legendJerrythabest is a forum legend

Aug 22, 2011, 07:41 AM
Jerrythabest is offline
Reply With Quote
Haha it's awesome! About the tile cache.. God knows what's possible in 1.00 that we didn't have in 1.2x
__________________
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 22, 2011, 07:51 AM
Violet CLM is offline
Reply With Quote
As far as we've noticed, there aren't any textured background settings at all, not even fade color. The eight bytes in TMAP immediately preceding the textured background itself would be a likely candidate, but they can be edited freely without seemingly having any effect. Besides that, it's not clear where to look, since by its nature any mode setting is going to be set to 0 and there are a lot of zeroes floating around. In any case, given that there's no fade color, I'd say the chances are pretty low.
__________________
Stijn Stijn's Avatar

Administrator

Joined: Mar 2001

Posts: 6,964

Stijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to behold

Aug 22, 2011, 10:15 AM
Stijn is offline
Reply With Quote
This reminded me that a while ago I had done most of the work on a retooling of the J2O wiki. The actual article view page was mostly finished so I made that one go live (it does look a lot better), I'll see if I can finish up the rest in the next few days.
Old Aug 22, 2011, 03:33 PM
Violet CLM
This message has been deleted by Violet CLM.
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Aug 24, 2011, 11:47 AM
Violet CLM is offline
Reply With Quote
MCEs work in 1.00g.
__________________
Jerrythabest Jerrythabest's Avatar

JCF Member

Joined: Apr 2005

Posts: 2,602

Jerrythabest is a forum legendJerrythabest is a forum legendJerrythabest is a forum legend

Aug 26, 2011, 04:13 AM
Jerrythabest is offline
Reply With Quote
Cool!

Have you tried to load MCE sprites with Ambient Sound yet? If that works too, it might be possible to see Springcord with its real sprites (though only if those sprites exist of course).
__________________
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,991

Violet CLM has disabled reputation

Oct 26, 2011, 07:11 PM
Violet CLM is offline
Reply With Quote
Quote:
Originally Posted by Unknown Rabbit View Post
Soooooooo...
The first custom .lev file.

(The crate is from my attempting to set up a tile cache effect, but it doesn't appear to work in 1.00.)
Minor update: tile cache does work in 1.00, although the words have to be 16 tiles wide instead of 4. The reason the earlier test failed was that I assumed trigger scenery was programmed the same way in 1.00 as it is in 1.23, which turned out to be a mistake. Adding a third frame to the animation made everything work out right. The zip has been updated, in case you're curious.


(And no, I haven't tried ambient sounds, but you're welcome to -- the MLLE test release should be able to handle that, although you'll have to start the level in JCS and convert it if you want any tiles. I strongly doubt they'll have any effect on the springcord, though.)
__________________
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On

Forum Jump

All times are GMT -8. The time now is 12:13 AM.