Jill of the Jungle Map Format
Format type | Map/level |
---|---|
Map type | 2D tile-based |
Layer count | 2 |
Tile size (pixels) | 16×16 |
Viewport (pixels) | 232×160 |
Games |
The Jill of the Jungle Map Format is the format used to describe the levels played during the game. The maps contain two layers - a background layer and an "object" layer. The background layer is a grid of 16x16 pixel tiles, 128 tiles wide and 64 tiles high. The object layer is made up of an arbitrary list of objects, with X and Y offsets in pixels.
File format
The main map file starts off with the background layer, then immediately following it is the foreground layer, the savegame data block and the string stack.
Background layer
The background layer is quite simple. It is an array of 8,192 16-bit values (128 tiles wide by 64 tiles high == 8192 tiles total.) Each 16-bit value is a code, such as 0xC0D3. The formula ((x * MAP_HEIGHT) + y) * 2 (where MAP_HEIGHT is 64) will provide the offset (in bytes) into the map file where that grid's 16-bit code is located.
Once the code is found, its lower 14 bits are isolated (e.g. code & 0x3FFF) which provides an ID that is listed in the tile mapping table (see below.) The tile mapping table then provides an index into the graphics file for the image that should be displayed at that grid location. The upper two bits are only used during gameplay to record information about which tiles are on screen at any given time.[1] The official games all seem to have these upper two bits set in the map file, so it's probably a good idea to do the same when writing out modified maps.
For example, if the 16-bit code is 0xC0D3, then isolating the lower three nybbles will provide the number 0x00D3. At the entry for ID 0x00D3 in the tile mapping table, the value might be iTileset as 0x12 and iTile as 0x34. This means that in the graphics file, tileset number 0x12 should be accessed, and tile number 0x34 within that tileset should be drawn at the grid coordinate.
It is also important to note that these values are stored little-endian, like the SHA format. This means that for example the value 0xC0D3 is stored as the two bytes D3-C0, not as C0-D3.
Tile mapping table
There is a separate file in the game directory that contains mappings between tile codes in the background layer and the game's graphics. In Jill of the Jungle this is called JILL.DMA and in Xargon it is TILES.XRx.
This file is arranged as an array of entries, one after the other. Each entry is in the following format:
Data type | Description |
---|---|
UINT16LE iMapCode | ID used in map file |
UINT8 iTile | Index into the tileset for the image to use |
UINT8 iTileset | Index of tileset containing this tile's image (ignore upper two bits - see below) |
UINT16LE iFlags | Flags for this tile (can stand on, can hurt player, etc.) |
UINT8 iLength | Length of tile name |
char cName[iLength] | iLength characters for the tile name. This string is not NULL-terminated. |
Note that only the lower six bits of iTileset refer to the tile number. The purpose of the upper unknown bits is unknown. To get a valid tileset index use iTileset & 0x3F
.
iFlags is broken up as follows:
Bit | Hex | Name | Description |
---|---|---|---|
- | 0x0000 | <zero> | Default solid block |
1 | 0x0001 | F_PLAYERTHRU | Blocks you can walk, jump or fall through (background tiles, the path on the overhead map, etc.) |
2 | 0x0002 | F_STAIR, F_NOTSTAIR (Xargon) | Blocks that you can stand on (can also jump up through when combined with F_PLAYERTHRU) |
3 | 0x0004 | F_VINE, F_NOTVINE (Xargon) | Can climb this block - usually combined with F_PLAYERTHRU (giving 0x0005) |
4 | 0x0008 | F_MSGTOUCH | Activates game-specific code when touched |
5 | 0x0010 | F_MSGDRAW | Regular blocks have just one shape, f_msgdraw triggers msg_block(msg_draw) for animated blocks. |
6 | 0x0020 | F_MSGUPDATE | game-specific code (through msg_block(msg_update)) at every frame. For animated blocks. |
7 | 0x0040 | F_INSIDE | This block contains text inside it |
8 | 0x0080 | F_FRONT | object property : Foreground object |
9 | 0x0100 | F_TRIGGER | Unknown |
10 | 0x0200 | F_BACK | object property: Background object (e.g. torches) |
10 | 0x0200 | F_TINYTHRU | (likely PlayerThru when player is in 'mini' mode, unused in Xargon) |
11 | 0x0400 | F_ALWAYS | object property : "Always updates object" |
12 | 0x0800 | F_KILLABLE | object property : monster can be killed with regular weapon. |
13 | 0x1000 | F_FIREBALL | object property : object is a fireball |
14 | 0x2000 | F_WATER | A water tile. regular player will sink, the S.U.B. and aquatic monster can swim through it, but not out of it |
14 | 0x4000 | F_NOT_WATER | (Xargon) Not a water tile. |
15 | 0x4000 | F_WEAPON | object property : object is a regular weapon |
16 | 0x8000 | (unused) | (unused) |
Note that the same "flag set" is used for both blocks and objects. Some properties only apply to blocks, some only apply to objects, some to both (f_msgtouch), and some flags have a different meaning for blocks and tile (e.g. 0x200 and 0x2000).
Object layer
The object layer is drawn in front of the background layer, and contains all the interactive elements of the map, such as points and enemies.
The object data starts straight after the background layer data, so that's at offset 16,384 bytes into the map file (8,192 tiles * two bytes per tile.) The first two bytes in the object layer are a 16-bit integer (UINT16LE) that stores the number of objects in the map, and this is followed by the data for each object, one after the other.
Each object is 31 bytes long, and is stored in the following structure:
Data type | Description |
---|---|
UINT8 iType | Object type (e.g. a "point item", or an enemy.) |
UINT16 iX | X-coordinate of object |
UINT16 iY | Y-coordinate of object |
UINT16 iXD | object horizontal speed |
UINT16 iYD | object vertical speed |
UINT16 iWidth | Width of object |
UINT16 iHeight | Height of object |
UINT16 iState | Object sub-type (e.g. what type of "point item"), or current "State" (running, jumping, etc) |
UINT16 iSubState | object-specific semantic |
UINT16 iStateCount | object-specific semantic, typically a frame counter |
UINT16 iCounter | Various uses. Often used to link doors or switches to obstacles. |
UINT16 iFlags | internally used for rendering. |
UINT32 lPointer | Used internally as a pointer. If this value is 0, there is no entry for this object in the string stack (see below.) Any non-zero value means there is an entry for this object in the string stack. |
UINT16 iInfo1 | Unknown |
UINT16 iZapHold | Unknown |
At the present time it is assumed (perhaps hoped) that objects can be mapped to images in the same way as the tiles in the background layer can be mapped to images, but as yet there is no known way of doing this.
Savegame data
Saved games are "snapshots" of the current level state, which is why some spare room exists in the map format to allow special data to be saved.
Jill In Jill of the Jungle, this section is 70 bytes long.
|
Xargon[2] In Xargon, this section is 97 bytes long.
|
String stack
The Strings Stack is just a bunch of arbitrary strings (can be either text or file references). Each entry starts with an unsigned short integer defining the length of the incoming string. Note that the string is always followed by a null byte (so if "length of next entry" is 12, you only have the string size and should not forget to read an extra byte to reach the next entry). The string stack's entries are used for iType[20] ("write text"), 21 ("write text in big") and 12 ("checkpoints") and can contain music filenames, demo filenames, next level filenames or arbitrary text content.
In Xargon and Jill, the checkpoint type contains a string:
- If the first character of this string is '*' then the rest of the string is taken to be the filename of the music file to play in that level.
- If the first character is '#' then the string is also a music file, but it is only played if there is no song currently playing, or the level number is between 1 and 32 inclusive. This is probably used for the main menu/credits/etc. so as not to interrupt the theme song when displaying those "levels", and it is used for the map level so the theme music keeps playing (rather than starting from the beginning again) when starting a game.
- The first character of the string can also be '&' which, in Xargon, forces the song to be song_33.xr1 and in Jill does not change the song. The rest of the string as a macro filename, to be read and played back as a demo. This is used in the ending sequences.
Object iTypes
Here's a list of objects used in Jill maps. A brief Xargon list is available in the source code.
iXD and iYD defines both speed and direction of items and ennemies. Positive values goes to right and down while values under zero move the object left and up. lPointer referes to a segment of memory and is likely used to store entries from the string stack, that's why the gap between two consecutive pointers equals 65536 (this is the maximum size in byte of a string in the stack) Playable objects must be the first entry in the list to avoid a weird "scroll to first entity" bug in Jill
Functional
- iType[0] (PLAYER) Playable: Jill (level)
- ObjectInfo1 (sometimes '-1'): usage unknown
- iType[23] (TINY) Playable: Jill (map overview in Jill3)
- iType[54] (JILLFISH) Playable: Fish (never used in maps - if player dies, restart as Jill)
- iType[56] (JILLBIRD) Playable: Firebird (never used in maps - if player dies, restart as Jill)
- iType[57] (JILLFROG) Playable: Frog (never used in maps - if player dies, restart as Jill)
- iType[12] (CHECKPT) Trigger: Checkpoint
- iXD ('> 0'): X position of start in new map
- iYD ('> 0'): Y position of start in new map
- iState: If set to 1, the level is reset to it's initial state if player dies. If set to 0, the level's state is unchanged if player dies.
- iCounter ('>= 0'): checkpoint/level number
- iPointer: pointer
- NOTE: Always lock access to previous checkpoint when the player reaches a new checkpoint. This item reads an entry from the string stack: a single-character code and a filename. If the code is "*", it means "load and play this song from the beginning". If the code is "#", it means "keep on playing this song". If the code is "!", then there's no filename and it means "load previous map". If there's no code, then the filename is the next level to load.
- iType[15] (PAD) Trigger: Touch Trigger
- iCounter ('>= 0'): target tag
- iType[32] (SWITCH) Trigger: Switch
- iState (usually '0'): switch position, if target is off, set to '1'
- iXD (usually '0'): set to '0' when triggering two objects with different start states (one bridge 'off' and a wall 'on' for example)
- iType[52] (BUTTON) Trigger: Press Button
- iXD (set to '1' to face right, '-1' to face left): direction
- iState (set to '1' if target is off)
- iSubState: usage unknown, rarely used
- iCounter ('>= 0'): target tag
- iType[24] (DOOR) Misc: Locked Door
- iYD (usually '0', set to '1' for crystal): required key type
- iCounter ('>= 0'): self tag
- iType[25] (FALLDOOR) Misc: Collapsing ceiling
- iCounter ('>= 0'): self tag
- iType[26] (BRIDGER) Misc: Toggle Wall
- iXD (set to 1 for horizontal/floor)
- iYD (set to 1 for vertical/wall)
- iCounter ('>= 0'): self tag
- NOTE: If set as wall, must be placed on top of the wall, if set as floor, must be placed on the far left of the floor. By default, these walls are "off", use "ELEVMID" tiles for wall and "BRIDGE" for floor. Walls and bridges cannot go through two different types of tiles.
- iType[44] (KNIGHT) Misc: Knight
- iState (set to '1' for start on, '0' for start off): initial state
- iStateCount (set to '6' for 'none shall pass')
- iCounter ('>= 0'): self tag (toggle when triggered)
- iType[61] (ELEV) Misc: Lift
- iCounter (usually '0'): if set to '-1', do not return to initial state
- NOTE: When going up, the elevator will travel until the player hits a solid tile. When going down, the elevator will erase "ELEVMID" tiles, replacing them with the tile directly above. "ELEVBOT" tiles look the same as "ELEVMID" tiles, but an elevator will not travel through it.
Items & Bonus
- iType[1] (APPLE) Bonus: Apple
- iType[28] (TOKEN) Bonus: Pickup Item & morphing icons
- iCounter ('>= 0'): item type (can be anything from 0 to 9 and matches the inventory item number)
- iType[2] (KNIFE) Weapon: Knife
- iType[14] (KEY) Key: Old Red Key
- iType[33] (GEM) Key: Crystal
- iCounter (rarely set to '1'): usage unknown
Monsters
- iType[4] (BIGANT) Green bug
- iXD (usually '2'): movement speed
- iType[7] (DEMON) Devil
- iType[8] (BUNNY) Bunny
- iType[9] (INCHWORM) Worm
- iXD (usually '2'): movement speed
- iType[11] (BOBSLUG) Giant Slug
- iXD (usually '2'): movement speed
- iType[17] (FATSO) Lizard Man
- iXD (usually '2'): movement speed
- iType[22] (FROG) Frog
- iType[29] (ANT) Giant Ant
- iXD (usually '3'): movement speed
- iType[30] (PHOENIX) Phoenix
- iXD (usually '3'): movement speed
- iType[39] (SNAKE) Invincible Snake
- iXD (usually '2'): movement speed
- iType[43] (BAT) Giant Bat
- iType[45] (BEENEST) Hive
- iType[46] (BEESWARM) Bees
- iType[47] (CRAB) Crab
- iType[48] (CROC) Gator
- iXD (usually '2'): movement speed
- iType[53] (PAC) Ghost
- iXD (usually '2'): initial direction
- iCounter (usually '2'): movement speed
- NOTE: Ghosts move along the same tile type
- iType[59] (JELLYFISH) Jellyfish
- iType[60] (BADFISH) Eels
Traps
- iType[35] (BOULDER) Rolling Stone
- iType[38] (STALAG) Falling Spike
- iCounter ('>= 0'): self tag (fall when triggered)
- iType[41] (BOLL) Boucing Ball
- iCounter (usually '4'): ball type (0-small, 3-red, 4-green)
- iType[65] (VINECLIMB) Sparks
- iYD (usually '2'): movement speed
- NOTE: Sparks move along the same tile type
Misc
- iType[13] (PAUL) Misc: Prince
- iState (
''
): object animation frame
- iType[19] (CLOUD) Misc: Cloud
- iCounter ('>= 0'): usage unknown
- iXD (
''
): movement speed
- iType[20] (TEXT6) Misc: Write text (small capital letters)
- iXD (
''
): CGA color index number - iYD (usually '-1' for transparent): background color
- lPointer: pointer
- NOTE: This item reads an entry from the string stack
- iType[21] (TEXT8) Misc: Write text (big letters)
- iXD (
''
): CGA color index number - iYD (usually '-1' for transparent): background color
- lPointer: pointer
- NOTE: This item reads an entry from the string stack
- iType[40] (SEAROCK) Misc: Underwater Rock
- iType[42] (MEGA) Misc: Huge letter
- iXD ('>= 0'): letter type (0-M, 1-E, 2-G, 3-A, 4-S)
- iCounter ('>= 0'): self tag (fall when triggered)
- iType[49] (EPIC) Misc: Epic Logo
- iType[51] (SKULL) Misc: Big Skull
- iCounter ('>= 0'): self tag (laugh with red gloomy eyes when triggered)
- iType[64] (EYE) Misc: Eye
- iType[66] (FLAG) Misc: Flag
- iType[67] (MAPDEMO) Misc: "Demo"/"Map" sign
- iXD (sign type, '>= 0'): set to '1' for "map", '0' for "demo"
Untested
- iType[3] ? (buggy/unusable)
- iType[5] ? (buggy/unusable)
- iType[10] ? (buggy/unusable)
- iType[16] ? (buggy/unusable)
- iType[27] ? (buggy/unusable)
- iType[34] ? (buggy/unusable)
- iType[50] ? (buggy/unusable)
- iType[55] ? (buggy/unusable)
- iType[6] Buggy: harmless firebird
- iType[18] Saves: Demon attack
- iSpeedX (
''
): Horizontal speed - iSpeedY (
''
): Vertical speed
- iType[31] Saves: flame attack
- iType[36] Saves: Particle
- iState (
''
): color - iSpeedX (
''
): velocity X - iSpeedY (
''
): velocity Y - iFlag (
'16384'
): Unknow - iCounter (
''
): Unknow
- iType[37] Saves: Pain effect
- iType[58] Saves: Bubbles
- iFlag (
'16384'
): Unknow
- iType[62] Saves: Player attack (fireball)
- iType[63] Saves: Player attack (fish)
References
Credits
This file format was reverse engineered by Malvineous, Ilovemyq3map2 and SaxxonPike. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)