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

JJ2 File Format Recommendations

Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,983

Violet CLM has disabled reputation

Jan 4, 2012, 10:06 AM
Violet CLM is offline
Reply With Quote
JJ2 File Format Recommendations

This is a thread for public proposals for modifications of the file formats used by JJ2. The ones I'm proposing here would have no effect ingame but are instead to be used for storing data for use in editing programs, but if JJ2+ development resumes or the source code is released, proposals that would affect the game (e.g. ordering layer display by the unused layer z-index properties) would become feasible.


List of Locked Words in Data1 of .j2l files
J2L specification

The section "Unknown4" in the first data stream of level files, located between tile types and animated tiles, is 1024 (or 4096) bytes long. I've looked at over four thousand levels and it's all zeroes in every one of them, and I have seen no effect from modifying it either. I propose filling it in with a list of shorts pointing to words (as defined in Data3) which should be considered "locked" for the purposes of editing and primarily saving.

When saving a level, as described here and at greater length in the Reworder documentation, JCS (and also MLLE and WebJCS) goes through the level layer by layer (starting with 1 and ending at 8) and breaks the layer layout data into "words" of 4x1 tiles each. Two instances of the same four tiles (e.g. blank, blank, blank, blank) will, in the general case, use the same word, potentially lowering the .j2l filesize. If a set of four tiles contains an animated tile with an event on it, JCS/MLLE/WebJCS will automatically record this as a new word. While this allows trigger scenery (and other such events) to affect words used in background layers, it is impossible to affect words used in foreground layers without the use of Reworder.

The proposed "locked" words would be a list of always-identical-to-one-another words which independent (=fanmade) level editors such as MLLE and WebJCS would respect on saving. For instance, in ReworderEx1.j2l, word #64 includes the animated tiles to make the top half of the scarab beetle appear in the foreground. The word appears in layer 2, where it is visible to the player, and in layer 4, where trigger scenery is applied to it. Saving in JCS eradicates this connection and creates two separate words in place of one. If #64 were included in the list of locked words, an independent level editor would override its usual "event on animated tile equals a new word" behavior and bind the instance in layer 4 to the instance in layer 2. (Note that the word number itself might not still be 64 after further edits, and so the list of locked words would have to be number-independent and moreover recalculated on every save.)

This proposal includes recommendations for how to save levels (i.e. overrule the usual word-defining behavior) but not for editing levels. Individual implementations may decide how to handle the case of a user wishing to edit the tiles of a locked word, as well as providing interfaces for locking or unlocking words in the first place.


Smart Flipped Tiles in Data1 of .j2t files
J2T specification

.j2t files include several [MAXTILES]-long (=1024 or 4096) strings of unused bytes, including Unknown2, which is actually 4*MAXTILES long. I've tested it in over one thousand tilesets and it was all zeroes every time. I propose filling the first half of it with shorts pointing for any tile x to the tile y within the tileset that is equivalent (in mask) to tile x flipped and yet tiles properly with nonflipped tiles.

For instance, consider Castle. Flipping tile 2,2 -- the upper-left wall corner piece against a background block -- will result in an upper-right wall corner piece, yet one that does not look right combined with other nonflipped tiles. (In this particular case, the grooves on the floor are in the wrong direction.) The smart flipped tile list would include a pointer to tile 9,2 -- the upper-right wall corner piece. An independent level editor would then provide users with an option of smart flipping a selection tile by tile (as an alternative to actual graphical flipping), resulting in a selection with a mask equivalent to that of the selection flipped the regular way, but one which tiles properly with ordinary tiles. Since many CTF levels have symmetrical layouts, a simple action to automate the laying out of the other half would reduce development time considerably.

To delve briefly into actual values: tile 2,2 corresponds to tile #11, and tile 9,2 to tile #18. The 11th short within the Unknown2 section would thus have a value of 18, and the 18th short would have a value of 11. If a tile with no set smart flipped value (i.e. a value of 0) is smart flipped, it should remain the same tile.

(To the best of my knowledge there are currently no independent tileset editors, largely because there is little pressing need for one. This would be one incentive for the creation of a program. Another is allowing tileset designers finer control over tile-by-tile transparency. For instance, Scorpio Key includes a palette tile. Since the only real use for a palette tile is things like 8-bit textured backgrounds and 8-bit water -- a level designer rarely places a palette tile in their level -- I made the palette tile serve as the typical invisible block tile by specifying in the .j2t that the tile is fully transparent. Unfortunately, I had to do this manually using j2ff and a hex editor, because no independent tileset editor exists.)


Alternate Tiles in Data1 of .j2t files

This is essentially the same idea as the above, with the same sort of implementation, but without specifying that the alternate tile pointed to has to be the flipped equivalent. Instead, tileset designers could decide on a tile-by-tile basis which tile best counts as "alternate." For example, a tileset with cave tiles (e.g. Carrotus, Diamondus) could have caveless tiles include pointers to the caved equivalents, and vice versa. Tile 6,4 in Diamondus would include a pointer to tile 8,6, and so on. However, this needn't only be used for a caved/caveless distinction; a tileset with two different colors of certain tiles, e.g. many of the gems in CrysilisV, could include pointers from one color to another to let the level designer quickly swap individual gems back and forth without having to find all the right tiles manually.

Storagewise, these pointers would occupy the latter half of Unknown2, since it's 4*MAXTILES long and the pointers would all be shorts and thus only 2*MAXTILES long.
__________________

Last edited by Violet CLM; Jan 5, 2012 at 09:51 AM.
Jgke Jgke's Avatar

JCF Member

Joined: Sep 2006

Posts: 974

Jgke is an asset to this forumJgke is an asset to this forum

Jan 4, 2012, 10:43 AM
Jgke is offline
Reply With Quote
On tilesets: How about having data to tell MLLE that what tiles are what, in addition that what are their counterparts. For example, telling MLLE that tile 6,4 in the Diamondus tileset is a corner block, having air on left and bottom parts, and top and right parts would be walls.
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,983

Violet CLM has disabled reputation

Jan 4, 2012, 11:17 AM
Violet CLM is offline
Reply With Quote
You'd want (at minimum) two bytes per tile, I think:
Byte #1: eight bits, each specifying whether a given tile (up-left, up-center, up-right, middle-center, and so on) is part of the same structure or not.
Byte #2: type of structure. Tubelectric, for instance, has multiple wall types; you wouldn't want to create a wall of mixed purple and red tiles by accident.

Although, I wonder if it might not be better to separate such things (i.e. your idea and mine both) from the .j2t files, for two reasons:
  • Levels may potentially need their word data intact for the gameplay to work properly. If you get a level in your cache, ideally you should not be able to break it just by saving it in MLLE/WebJCS. Info about how tiles are related to one another, however, is by no means necessary.
  • Adding such information to old tilesets, including the official ones, would mean a whole lot of recompilation. This is bothersome to do, leads to version control issues, and may in some cases not be permitted by the tilesets' original authors. Setting up separate files (.j2tdata? whatever) means smaller filesizes, no direct modification of the tilesets themselves, and moreover it's easier for multiple people to refine the info of a given tileset, either for general release or for their own purposes.
__________________
djazz djazz's Avatar

JCF Member

Joined: Feb 2009

Posts: 257

djazz is OFF DA CHARTdjazz is OFF DA CHARTdjazz is OFF DA CHART

Jan 4, 2012, 11:35 AM
djazz is offline
Reply With Quote
Quote:
Originally Posted by Violet CLM View Post
To the best of my knowledge there are currently no independent tileset editors, largely because there is little pressing need for one.
Quote:
Originally Posted by Violet CLM View Post
because no independent tileset editor exists.
Haven't seen my signature?
I think it should work, atleast the same way as JCS create tilesets, except that this needs png files and a palette file.
PHP Tileset Compiler
Have been trying to convert it to JS, but failed as JS don't have ImageGD or similar to get/set/edit the palette from images.
__________________
WebJCS 2 (new and in progress)
WebJCS 1 (old but complete)
SGIP Simple Games in Progress list
Level Packer v2 - With a GUI!
PHP Tileset Compiler

Last edited by djazz; Jan 4, 2012 at 11:53 PM. Reason: Type
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,983

Violet CLM has disabled reputation

Jan 4, 2012, 11:44 AM
Violet CLM is offline
Reply With Quote
Oh, yes, my mistake. Sorry. It doesn't look like it allows manual transparency editing, though, does it?
djazz djazz's Avatar

JCF Member

Joined: Feb 2009

Posts: 257

djazz is OFF DA CHARTdjazz is OFF DA CHARTdjazz is OFF DA CHART

Jan 4, 2012, 12:12 PM
djazz is offline
Reply With Quote
Nope, just as JCS does it.
__________________
WebJCS 2 (new and in progress)
WebJCS 1 (old but complete)
SGIP Simple Games in Progress list
Level Packer v2 - With a GUI!
PHP Tileset Compiler
Olsen Olsen's Avatar

JCF Member

Joined: May 2004

Posts: 1,370

Olsen is doing well so far

Jan 4, 2012, 03:46 PM
Olsen is offline
Reply With Quote
Wow, all of this sound incredibly handy! Especially the alternate idea for .j2t.
__________________
some kind of nature
djazz djazz's Avatar

JCF Member

Joined: Feb 2009

Posts: 257

djazz is OFF DA CHARTdjazz is OFF DA CHARTdjazz is OFF DA CHART

Jan 5, 2012, 02:17 AM
djazz is offline
Reply With Quote
Quote:
Originally Posted by Violet CLM View Post
When saving a level, as described here
It's broken y'know
Code:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order by timestamp limit 0' at line 1
Warning: mysql_numrows(): supplied argument is not a valid MySQL result resource in /home/jazzonli/public_html/hosted/jcsref/node.php on line 27

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/jazzonli/public_html/hosted/jcsref/node.php on line 31
__________________
WebJCS 2 (new and in progress)
WebJCS 1 (old but complete)
SGIP Simple Games in Progress list
Level Packer v2 - With a GUI!
PHP Tileset Compiler
Jgke Jgke's Avatar

JCF Member

Joined: Sep 2006

Posts: 974

Jgke is an asset to this forumJgke is an asset to this forum

Jan 5, 2012, 02:25 AM
Jgke is offline
Reply With Quote
Quote:
Originally Posted by Violet CLM View Post
Setting up separate files (.j2tdata? whatever)
Yeah, that would be a possibility too. They should though be in a different folder, my main JJ2 folder has already tons of litter in it.

We could make a repository for the files, so that they could be downloaded directly from MLLE.
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

Jan 13, 2012, 09:07 AM
Jerrythabest is offline
Reply With Quote
Quote:
Originally Posted by Jake View Post
On tilesets: How about having data to tell MLLE that what tiles are what, in addition that what are their counterparts. For example, telling MLLE that tile 6,4 in the Diamondus tileset is a corner block, having air on left and bottom parts, and top and right parts would be walls.
Quote:
Originally Posted by Violet CLM View Post
You'd want (at minimum) two bytes per tile, I think:
Byte #1: eight bits, each specifying whether a given tile (up-left, up-center, up-right, middle-center, and so on) is part of the same structure or not.
Byte #2: type of structure. Tubelectric, for instance, has multiple wall types; you wouldn't want to create a wall of mixed purple and red tiles by accident.
I actually thought of this too. In fact, I've included a description of each tile in Castube's readme file. If tile types can be properly standardized, I think this can be something awesome to quickly switch tilesets.
Also, if I were to ever release Castube 2, it would have its tiles seriously reorganized. If I could supply such tile information about both versions, MLLE/WebJCS could load Castube 2 without trouble into any Castube 1.3-4 levels.

Quote:
Originally Posted by Violet CLM View Post
Although, I wonder if it might not be better to separate such things (i.e. your idea and mine both) from the .j2t files, for two reasons:

(reasons here)
I agree with this. Another important benefit of a seperate file is that you're not limited to 16 bits per tile. This allows for far more flexibility in how tiles are described. A tileset could have 20 different eyecandy objects, each consisting of 1-6 or even more tiles. It would be impossible to tell all those tiles apart in just 16 bits.


The following is just some brainstorming. I enjoy thinking about how to achieve these things
Let's say we've got some eyecandy we want to define. The format should find a way to store:
  • The fact that the tile is eyecandy
  • An eyecandy object identification (could be a number, or a name like 'vase' or 'knight' if you're thinking about Castle)
  • The X and Y positions within this object
Then, the complete object is defined by placing all tiles in that object relative to another. Two or more tiles claiming the same spot in an object doesn't have to be an error: the knight in Castle has one tile with head + shoulders and another one with only the shoulders. Both could go into the same spot.

When switching a level from another tileset to Castle, the level editor may find 1x3-tile objects in the level, where the tile at the bottom is specified as "eyecandy with the special property of including part of the ground". The level editor finds the knight in the Castle tileset, which has exactly those properties. Whether the night will have a head or not can be randomized.

The specification could be extended to include a property that sets the tile's probability. This way, the tile definitions could give for example a 20/80% ratio to the headless and normal tiles. This way, your new Castle level wouldn't miss half the knight's heads


Other things that should be thought of are animations, especially multi-tile animations. And the fact that some tiles can ONLY go, say, immediately right of another specific tile. Just think of all the layer 4 background tiles with shadows on them. The specification has to be VERY specific.
__________________
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,983

Violet CLM has disabled reputation

Jan 21, 2012, 06:54 PM
Violet CLM is offline
Reply With Quote
Whereas, the JCS.exe shipped with 1.10o does not contain a "Battle, Treasure, or CTF MultiPlayer level" checkbox in its Level Properties window;
Whereas, no level shipped with either 1.10o or Battery Check has the byte corresponding to that checkbox as any value other than 0;
Whereas, setting that byte to 1 has no visible effect in-game (it doesn't even alter the horizontal vs. vertical splitscreen stored in the previous byte);
I propose that the multiplayer byte in BC/1.10o-versioned .j2l files (version 0x202 but without a copyright header) be used to specify whether a .j2l is for 1.10o (value 1), Battery Check (value 2), or ambiguous (any other value at all including 0).
__________________
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,983

Violet CLM has disabled reputation

Jan 25, 2012, 09:51 AM
Violet CLM is offline
Reply With Quote
So, let's talk about file formats for these external j2t files. (And extensions too, if people like? I said .j2tdata earlier, but I might prefer .j2tprofile.)

I think it's fair to expect that the files be versioned. Coming up with a good system for metatiles/eyecandy definition could take some work, as Jerry has illustrated, but the stuff I listed in the first post only required two bytes per tile and that's quite straight-forward. Here's what I'm thinking for a first pass:
Code:
struct J2TProfile (version 1)
{
    char Version;
    short NumberOfTiles; // not necessarily redundant from the .j2t, since tilesets may be expanded and people might want to use a single .j2tprofile with multiple .j2t files.
    char Properties[64]; // don't know what would be put here; just allocating some space in case it might be necessary later.
    short NotesLength;
    char Notes[NotesLength]; // any information the profile compiler might think helpful to provide for users. A quick built-in readme, if you will.
    short SmartFlip[NumberOfTiles];
    short Alternate[NumberOfTiles];
}
Additions in later versions, such as a working metatiles system, would go at the end of the files. That way a program that's only familiar with version 1 (for example) but receives a file of version 2 or 3 could still read the data it would understand, since those data would be at the start of the file, and could simply ignore everything after that.
__________________
Jgke Jgke's Avatar

JCF Member

Joined: Sep 2006

Posts: 974

Jgke is an asset to this forumJgke is an asset to this forum

Jan 25, 2012, 10:53 AM
Jgke is offline
Reply With Quote
About the system how to share the .j2tprofile files, I could host a server for them, if someone makes a quick program for sharing. Going to order a Raspberry Pi as soon as I can, and my router is extremely well-behaving so hosting a server shouldn't be a problem. Or alternatively I'm quite confident that J2O can offer a service for it
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,983

Violet CLM has disabled reputation

Jan 29, 2012, 08:22 PM
Violet CLM is offline
Reply With Quote
On further reflection, the Properties section in my last post should probably be scrapped. If subsequent versions of the files add more data on to the end, they can add properties as well as anything else, so there's no point in putting an empty space for them in at the beginning.
__________________
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 09:36 PM.