Aug 6, 2011, 01:53 PM | |
.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? 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. |
Aug 6, 2011, 02:45 PM | |
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.
Last edited by Violet CLM; Aug 14, 2011 at 10:02 AM. |
Aug 9, 2011, 10:21 AM | |
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. |
Aug 9, 2011, 11:20 AM | |
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 Code:
byte TrasparencyFlags; //This shows which parts the bits represent: 43210000 Part TilePart[4]; 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]; 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 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. |
Aug 9, 2011, 11:50 AM | |
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 |
Aug 9, 2011, 12:31 PM | |
![]() |
Aug 12, 2011, 01:11 PM | |||||||||
Restoring lost posts from old hosting provider
![]() Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
__________________
Last edited by Jerrythabest; Aug 12, 2011 at 01:22 PM. |
Aug 12, 2011, 02:30 PM | |
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
Last edited by Violet CLM; Aug 14, 2011 at 03:58 PM. |
Aug 13, 2011, 09:23 AM | |
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.
__________________
|
Aug 13, 2011, 12:09 PM | |
[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] } 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. |
Aug 14, 2011, 05:37 PM | |
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. |
Aug 16, 2011, 01:51 AM | |
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. |
Aug 17, 2011, 06:37 PM | |
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. |
Aug 20, 2011, 02:22 AM | |
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.
__________________
|
Aug 20, 2011, 05:33 PM | ||||
Quote:
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:
Quote:
![]() (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.) |
Aug 21, 2011, 12:47 AM | |
I'll be looking forward to your visualizations
![]() ![]() 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. |
Aug 21, 2011, 05:33 AM | |
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: 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. |
Aug 21, 2011, 08:31 AM | |
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. |
Aug 21, 2011, 01:16 PM | |||||
Great stuff!
Quote:
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:
Quote:
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:
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 ETA: Here's a list of, as far as I can tell, everything we don't yet understand.
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. |
Aug 21, 2011, 08:26 PM | |
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.) |
Aug 22, 2011, 04:27 AM | ||
Quote:
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 + "]");
__________________
|
Aug 22, 2011, 04:55 AM | |
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 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? ![]()
__________________
|
Aug 22, 2011, 07:02 AM | |
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.) |
Aug 22, 2011, 07:23 AM | |
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?
__________________
Mystic Legends http://www.mysticlegends.org/ The Price of Admission - Hoarfrost Hollow - Sacrosanct - other - stuff |
Aug 22, 2011, 07:41 AM | |
Haha it's awesome!
![]() ![]()
__________________
|
Aug 22, 2011, 07:51 AM | |
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.
|
Aug 22, 2011, 10:15 AM | |
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.
|
![]() |
Violet CLM |
This message has been deleted by Violet CLM.
|
Aug 24, 2011, 11:47 AM | |
![]() |
Aug 26, 2011, 04:13 AM | |
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).
__________________
|
Oct 26, 2011, 07:11 PM | ||
Quote:
(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.) |
![]() |
«
Previous Thread
|
Next Thread
»
Thread Tools | |
|
|
All times are GMT -8. The time now is 02:26 PM.
Jazz2Online © 1999-INFINITY (Site Credits). 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. Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Original site design by Ovi Demetrian. DrJones is the puppet master. Eat your lima beans, Johnny.