Donkey Kong Land/Notes: Difference between revisions

From Data Crystal
Jump to navigation Jump to search
 
Line 1,848: Line 1,848:
===Huffman Coding Derivative===
===Huffman Coding Derivative===


Most background graphics are compressed using the same Huffman coding derivative found in [[Donkey Kong Land 2]], [[Donkey Kong Land III]], [[Battletoads (Game Boy)]], [[Battletoads in Ragnarok's World]], and [[Battletoads & Double Dragon (Game Boy)|Battletoads & Double Dragon]].
Most background graphics are compressed using the same Huffman coding derivative found in [[Donkey Kong Land 2]], [[Donkey Kong Land III]], [[Battletoads (Game Boy)]], [[Battletoads in Ragnarok's World]], and [[Battletoads/Double Dragon (Game Boy)]].


The game's decompressor for this format has a special behavior depending on where data is being decompressed to. After each decompressed byte is written, the game checks whether the destination address is in the range <tt>0x9800-98FF</tt> and, if so, subtracts <tt>0x1000</tt> from it— effectively making the destination address wrap around when it is in the range <tt>0x8800-97FF</tt>. This behavior allows compressed tile graphics that were originally in unsigned order to be decompressed to VRAM in signed order.
The game's decompressor for this format has a special behavior depending on where data is being decompressed to. After each decompressed byte is written, the game checks whether the destination address is in the range <tt>0x9800-98FF</tt> and, if so, subtracts <tt>0x1000</tt> from it— effectively making the destination address wrap around when it is in the range <tt>0x8800-97FF</tt>. This behavior allows compressed tile graphics that were originally in unsigned order to be decompressed to VRAM in signed order.

Revision as of 04:35, 17 September 2020

Chip tiny.png The following article is a Notes Page for Donkey Kong Land.

Maps

All three Donkey Kong Land games use the same LZ derivative to compress their maps. The main differences with the next two games are that the map's width and height are stored before the compressed data starts and any tiles that contain sprites are initialized to the 8-bit value 0x80. Additionally, the uncompressed map data is stored at a different location in RAM.

In DKL, the uncompressed map data starts at 0xCC00 in RAM.

Map IDs

Valid map IDs range from 0x00-49.

0x00: Freezing Fun
0x01: Jungle Jaunt
0x02: Congo Carnage
0x03: Tricky Temple
0x04: Reef Rampage
0x05: Riggin' Rumble
0x06: Nautilus Chase
0x07: Snake Charmer's Challenge
0x08: Swirlwind Storm
0x09: Simian Swing
0x0A: Rope Ravine
0x0B: Deck Trek
0x0C: Button Barrel Blast bonus #2
0x0D: Tyre Trail
0x0E: File select menu
0x0F: Kong Krazy
0x10: Kremlantis
0x11: Balloon Barrage (mislabeled "Construction Site Fight" in the manual)
0x12: Pot Hole Panic
0x13: Mountain Mayhem
0x14: Skyscraper Caper
0x15: Construction Site Fight (mislabeled "Balloon Barrage" in the manual)
0x16: Track Attack
0x17: Sky High Caper
0x18: Arctic Barrel Arsenal
0x19: Fast Barrel Blast
0x1A: Collapsing Clouds
0x1B: Oil Drum Slum
0x1C: Landslide Leap
0x1D: Chomp's Coliseum
0x1E: Button Barrel Blast
0x1F: Spiky Tyre Trail
0x20: Mad Mole Holes
0x21: Freezing Fun bonus
0x22: Fast Barrel Blast bonus #2
0x23: Deck Trek bonus #2
0x24: Riggin' Rumble bonus #2
0x25: Tyre Trail bonus #2
0x26: Simian Swing bonus #1
0x27: Tyre Trail bonus #3
0x28: Jungle Jaunt bonus #1
0x29: Congo Carnage bonus #1
0x2A: Mountain Mayhem bonus #1
0x2B: Wild Sting Fling
0x2C: Tricky Temple bonus #1
0x2D: Swirlwind Storm bonus #1
0x2E: Arctic Barrel Arsenal bonus #2
0x2F: Deck Trek bonus #1
0x30: Balloon Barrage bonus #2
0x31: Snake Charmer's Challenge bonus #1
0x32: Balloon Barrage bonus #1
0x33: Jungle Jaunt bonus #2
0x34: Rope Ravine bonus #2
0x35: Oil Drum Slum bonus #1
0x36: Sky High Caper bonus #1
0x37: Seabed Showdown
0x38: Kong Token bonuses (shared by multiple levels):
        * Simian Swing bonus #2
        * Rope Ravine bonus #1
        * Tyre Trail bonus #1
        * Congo Carnage bonus #2
        * Arctic Barrel Arsenal bonus #1
        * Spiky Tyre Trail bonus #2
        * Collapsing Clouds bonus #2
        * Fast Barrel Blast bonus #1
0x39: K. Rool's Kingdom
0x3A: Pot Hole Panic bonus #1
0x3B: Track Attack bonus #2
0x3C: Landslide Leap bonus #2
0x3D: Riggin' Rumble bonus #1
0x3E: Construction Site Fight bonus #2
0x3F: Spiky Tyre Trail bonus #1
0x40: Track Attack bonus #1
0x41: Pot Hole Panic bonus #2
0x42: Kong Krazy bonus
0x43: Skyscraper Caper bonus
0x44: Mountain Mayhem bonus #2
0x45: Construction Site Fight bonus #1
0x46: Collapsing Clouds bonus #1
0x47: Oil Drum Slum bonus #2
0x48: Button Barrel Blast bonus #1
0x49: Landslide Leap bonus #1

Map Data

0x3247A: A list of MapInfo structures— one for each map. It's indexed using a map ID.

0x32886: A list of 16-bit map initialization function pointers to the same bank. A function pointed to by this list gets called when a map gets loaded. It's indexed using a map ID.

0x31EB2: A list of 8-bit map theme IDs— one for each map. It's indexed using a map ID.

A map's theme determines various map properties, including which tile animations are played on it.

Map Metatiles

0x34001: A list of 24-bit pointers (bank last) to metatile maps that are compressed using an LZ derivative. It's indexed using a map ID. If the address part of a pointer in this list is 0, then that map has no metatile map.

The height of each metatile map is not explicitly stated but one can reasonably guess it by comparing the size of the uncompressed data with the metatile map's width. Also keep in mind that some maps have a metatile map whose last row of metatiles is incomplete.

0x31DD4: A list of the 8-bit widths, in metatiles, of each map's metatile map. It's indexed using a map ID.

0x31D8A: A list of 8-bit values that, for each map, determine both the MSB of a pointer to its MetatileIndexTable and which ROM bank it is in. It's indexed using a map ID.

Possible values:
* Bit 6 of the MSB of the pointer to the MetatileIndexTable is always 1.

0x31EFC: A list of 8-bit values that, for each map, determine the LSB of a pointer to its MetatileIndexTable. It's indexed using a map ID.

See also: Metatiles

Map Layouts

0x32196: A list of 16-bit pointers to Layout structures— one for each map. It's indexed using a map ID.
0x32024: A list of 8-bit ROM bank indices where Layout structures may be found— one for each map. It's indexed using a map ID.

The type of Layout used by a map is determined by its MapInfo structure.

See also: Layouts

Map Bananas

0x3291A: A list of 16-bit pointers to BananaLayout structures in ROM bank 4— one for each map. A pointer to 0 indicates that no BananaLayout has been assigned to that map.

Map 0x39 is set to never load banana layout data, presumably so that the RAM used by the banana system can be used for other purposes.

See also: Bananas

Map Start Points

0x3250E: A list of 16-bit x coordinates for the player character's start point— one for each map. It's indexed using a map ID.

0x325A2: A list of 16-bit y coordinates for the player character's start point— one for each map. It's indexed using a map ID.

0x31F46: A list of 8-bit character state IDs for the player character to start with— one for each map. It's indexed using a map ID.

The direction that the player character starts with is determined by the map's MapInfo structure.

Map Audio

0x31FDA: A list of 8-bit music track IDs that determine which music track to play on each map. It's indexed using a map ID.

Map Data Sets

Usually, when a map gets loaded, these data sets get loaded in the following order:

  • The data set with the same ID as the map's ID.
  • Data set 0x58.

See also: Data Sets

Map Hidden Ropes

The following maps contain hidden ropes: 0x01, 0x05, 0x09, 0x0D, 0x0F, 0x13, 0x19, and 0x1C.

0x31E1E: A list of 8-bit metatile IDs that represent the metatile ID used by closed rope holes. It's indexed using a map ID.

Metatiles with this ID will reveal a hidden rope when stomped on. Maps without rope holes use a metatile ID that does not appear on the map.

0x31E68: A list of 8-bit Metatiles IDs that represent the metatile ID used by opened rope holes. It's indexed using a map ID.

When a rope hole gets opened, its metatile gets replaced by one from this list.

0x32636: A list of 16-bit function pointers to ROM bank 2. It's indexed using a map ID.

When a hidden rope gets revealed, a function from this list gets called. The function being called can be used to determine which hidden rope is assigned to each map.
Function pointers present in this list and their meanings:
  • 0xD25: Does nothing
  • 0x7AA7: Spawns hidden rope 0x00
  • 0x7AAB: Spawns hidden rope 0x01
  • 0x7AAF: Spawns hidden rope 0x02
  • 0x7AB3: Spawns hidden rope 0x03
  • 0x7AB7: Spawns hidden rope 0x04
  • 0x7ABB: Spawns hidden rope 0x05
  • 0x7ABF: Spawns hidden rope 0x06
  • 0x7AC3: Spawns hidden rope 0x07

See also: Hidden Ropes

Map Hidden Caves

The following maps contain hidden caves: 0x01, 0x02, and 0x1F.

These MapPatchHotspotSets are used to reveal hidden caves:

See also: Hidden Caves

MapInfo Structure

  • 0x00:
  • Bits 0-1: ?
  • Bit 2: The type of Layout used by the map.
  • Bits 3-7: ?
  • 0x01:
  • Bits 0-1: ?
  • Bit 2: Whether the map is a bonus map.
  • Bit 3: The direction that the player character starts with.
  • Bits 4-5: ?
  • Bit 6:
Determines which base address to use for non-player metasprite tile pattern pointers (see MetaspriteInfo).
Possible values:
  • 0: base = 0x4000
  • 1: base = 0xC000
A base of 0xC000 appears only on boss maps because boss graphics are loaded to RAM (presumably to allow them to be decompressed). Using it on maps with non-boss objects will result in those objects having messed up graphics.
  • Bit 7: ?

Map Theme IDs

0x00: Snow
0x01: Jungle
0x02: Temple
0x03: Coral
0x04: Ship
0x05: Kong token bonus minigame
0x06: File select menu
0x07: Underwater ruins
0x08: Blimp
0x09: Cave
0x0A: Clouds
0x0B: Skyscraper
0x0C: Construction site
0x0D: Mountain

Metatiles

A metatile is a collection of two or more tiles that forms a larger graphic.

Donkey Kong Land uses 4 x 4 tile metatiles which means that each one is a 32 x 32 pixel square.

See also: Map Metatiles

Metatile Maps

A metatile map is a 2D array of 8-bit metatile IDs that defines how the background of a map looks and behaves.

Metatile maps have their origin at (32,32), meaning it's drawn down and to the right that many pixels.

Metatile Tables

Metatile tables are used to describe the various properties of individual metatiles.

MetatileIndexTable Structure

Describes which tile indices are used by a set of metatiles.

  • 0x0000-00FF: A list of 8-bit tile indices for each metatile's tile (0,0), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0100-01FF: A list of 8-bit tile indices for each metatile's tile (1,0), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0200-02FF: A list of 8-bit tile indices for each metatile's tile (2,0), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0300-03FF: A list of 8-bit tile indices for each metatile's tile (3,0), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0400-04FF: A list of 8-bit tile indices for each metatile's tile (0,1), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0500-05FF: A list of 8-bit tile indices for each metatile's tile (1,1), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0600-06FF: A list of 8-bit tile indices for each metatile's tile (2,1), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0700-07FF: A list of 8-bit tile indices for each metatile's tile (3,1), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0800-08FF: A list of 8-bit tile indices for each metatile's tile (0,2), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0900-09FF: A list of 8-bit tile indices for each metatile's tile (1,2), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0A00-0AFF: A list of 8-bit tile indices for each metatile's tile (2,2), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0B00-0BFF: A list of 8-bit tile indices for each metatile's tile (3,2), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0C00-0CFF: A list of 8-bit tile indices for each metatile's tile (0,3), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0D00-0DFF: A list of 8-bit tile indices for each metatile's tile (1,3), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0E00-0EFF: A list of 8-bit tile indices for each metatile's tile (2,3), padded to 0x100 bytes. It's indexed using a metatile ID.
  • 0x0F00+: A list of 8-bit tile indices for each metatile's tile (3,3). It's indexed using a metatile ID.

Each list in this structure, ignoring padding, may not cross a 0x100 byte page boundary.

Layouts

Layouts determine where most things, including objects, are placed on a map. Bananas are a notable exception since they're placed using a different kind of layout.

The layout data is notably different from the format used by Donkey Kong Land 2 and Donkey Kong Land III. For one, it's much more complicated. Additionally, bananas are placed using a different kind of layout.

See also: Map Layouts

Layout Types

This layout type organizes Placements along the x axis. When using this layout type, only a Placement's x coordinate is used to determine if it has entered the view. Due to this, it is suitable only for maps with few Placements in the same horizontal space.
This layout type has the unique ability to use FunctionPlacements and CameraCuePlacements.
This layout type partitions Placements in a regular grid. It is suitable for situations where there are many Placements in the same vertical space. Compared to 1D layouts it's more versatile but lacks some features and uses more memory.

Layout Structure

  • A Layout must have, at minimum, a list of Placements that determine where things are placed on the map. The list may contain up to 0x80 items. Each list item has an ID that is the same as its index in the list.
  • There are two different types of Layout structures: Layout1D and Layout2D.

See also: Layout1D, Layout2D, Placement

Layout1D Structure

1D layouts store Placements in a list that is sorted based on ascending x coordinate.

  • 0x00+: A list of Placement structures that is sorted based on ascending x coordinate. Its end point isn't clearly defined, but one can reasonably assume one after encountering a list item whose x coordinate is too far right to ever enter the view.

A quirk of 1D layouts is that the last item in the Placement list must have an x coordinate that is far enough right that it will never enter the view. Due to that, only 0x7F out of the maximum 0x80 Placements are available for regular use.

See also: Layout, Placement

Layout2DHeader Structure

  • 0x00-01: A pointer to the first valid item in the partition array in the same ROM bank.
  • 0x02-03: A pointer to the byte after the last valid item in the partition array in the same ROM bank. It's also a pointer to the Layout's Placement list in the same ROM bank.

See also: Layout2D

Layout2D Structure

2D layouts partition Placements into a regular grid of 0x80 x 0x80 pixel cells. The structure itself consists of a 2D array, row pointers to that array, and a Placement list that is sorted based on partition.

  • Immediately preceding this structure is a Layout2DHeader structure.
  • 0x00+: A list of 16-bit pointers to rows of a continuous 2D array in the same ROM bank. The array, called the partition array, is indexed using a location, in partitions.
  • Unless a partition is empty, its associated array item points to an item in the Layout's Placement list that is the first Placement in said partition.
  • A partition is empty if its associated array item points to 0.
  • A partition is also empty if its associated array item is located outside of the range defined in the Layout2DHeader that precedes this structure.
  • Since the array is continuous, its width can be calculated like so:
SIZE_OF_PTR_16 = 2
sizeOfRow = (rowPointers[1] - rowPointers[0]) / SIZE_OF_PTR_16
  • The array's height is undefined, but one can reasonably guess it by utilizing the pointers in the Layout2DHeader.

The origin for this layout type is located at (-0x80,-0x80), in pixels.

A quirk of 2D layouts is that the last item in the Placement list must not be located in any partition. Due to that, only 0x7F out of the maximum 0x80 Placements are available for regular use.

See also: Layout, Layout2DHeader, Placement

Placement Structure

A structure that describes something that is placed on a map.

See also: ObjectPlacement1D, ObjectPlacement2D, FunctionPlacement, CameraCuePlacement, DataBlockPlacement

ObjectPlacement1D Structure

A Placement that describes where an object is placed. They can only be used by 1D layouts.

  • 0x00:
  • Bits 0-5: The type of object that is placed
  • Bit 6: The direction that the object faces
  • Bit 7: Must be 0
  • 0x01: LSB of x coordinate
  • 0x02:
  • Bits 0-4: MSB of x coordinate
  • Bits 5-7: MSB of y coordinate
  • 0x03: LSB of y coordinate

See also: Placement

ObjectPlacement2D Structure

A Placement that describes where an object is placed. They can only be used by 2D layouts.

  • 0x00:
  • Bits 0-5: The type of object that is placed
  • Bit 6: The direction that the object faces
  • Bit 7: Must be 0
  • 0x01:
  • Bits 0-6: The object's x coordinate (partition-relative).
  • Bit 7: If set, then this indicates that this Placement is in a different partition than the one that precedes it.
  • 0x02:
  • Bits 0-6: The object's y coordinate (partition-relative).
  • Bit 7: Unused?
  • 0x03: This Placement's ID represented as a bit index (big endian) and a byte index.
  • Bits 0-2: A bit index (big endian).
  • Bits 3-7: A byte index.
It's formatted this way because it makes it easier to extract bits from bit lists.
It can be converted to a regular Placement ID like so:
SIZE_OF_BYTE_IN_BITS = 8
placementId = byteIndex * SIZE_OF_BYTE_IN_BITS + ((SIZE_OF_BYTE_IN_BITS - 1) - bitIndex)

See also: Placement

FunctionPlacement Structure

A Placement that describes where to call a function. The function may get called multiple times. They can only be used by 1D layouts.

The function must have this signature:

@in hl - A pointer to the byte following the FunctionPlacement structure that
    is being executed and to any DataBlockPlacement structures that may follow it.
  • 0x00:
  • Bits 0-4: MSB of x coordinate
  • Bit 5: Must be 0
  • Bit 6: Must be 0
  • Bit 7: Must be 1
  • 0x01: LSB of x coordinate
  • 0x02-03:
  • Bits 0x0-E: A pointer to the function to call. The bank being pointed to is the one containing this structure.
  • Bit 0xF: Unused?

See also: Placement

CameraCuePlacement Structure

A non-functional Placement type that may have at one point been used to affect the camera's behavior. They don't appear on any maps. They can only be used by 1D layouts.

When it enters the view, either the upper or lower camera bound gets set. However, since those get overwritten again quickly afterward, it has no visible effect. It may have at some point been a functional way to influence the camera— a role that OBJ_CAMERA_CUE now fulfills.

  • 0x00:
  • Bits 0-4: MSB of x coordinate
  • Bit 5: Must be 1
  • Bit 6: Must be 0
  • Bit 7: Must be 1
  • 0x01: LSB of x coordinate
  • 0x02:
  • Bits 0-4: The MSB of the value to set a variable to.
  • Bits 5-7: Determines which variable to set.
Possible values:
  • 0: Set the upper camera bound. However, since it gets overwritten again quickly afterward, this has no visible effect.
  • 1-7: Set the lower camera bound. However, since it gets overwritten again quickly afterward, this has no visible effect.
  • 0x03: The LSB of the value to set a variable to.

See also: Placement

DataBlockPlacement Structure

Contains additional data for the (non-data-block) Placement structure that precedes it. One or more of these may optionally follow any Placement structure.

While these don't actually have a presence on the map, they're important for passing data to functions for object initialization and FunctionPlacement structures.

  • 0x00:
  • Bits 0-4: Field 0
  • Bit 5: Unused?
  • Bit 6: Must be 1
  • Bit 7: Must be 1
  • 0x01: Field 1
  • 0x02: Field 2
  • 0x03: Field 3

See also: Placement, ObjectPlacement1D, ObjectPlacement2D

Objects

Objects are placed on maps by using layouts.

Object Type Configuration Data

0x10001: A list of 16-bit pointers to ObjectTypeConfig structures in the same ROM bank. It's indexed using an object type ID.

Each type of object is given an initial state based on its corresponding item in this list. Therefore, changing items in this list will affect all objects of a given type.

ObjectTypeConfig Structure

Contains values that define part of the initial state for a type of object.

  • Bits 0x0-E: A 16-bit function pointer to ROM bank 4 for the object type's default update function.
  • Bit 0xF: ?
  • 0x06: ?
  • 0x07: ?
  • 0x08: ?
  • 0x09: ?

Object Configuration Data

Object configuration data makes it possible to have variations of the same object type beyond just location and direction. Not all object types have configuration data but, when present, it can be provided in any of the following ways:

  • Location
The configuration data is stored in the object's location.
Unless otherwise noted, location bits used in this way are subsequently set to zero. For example: if bits 0-1 of an x coordinate are used to store configuration data, then those bits would get set to 0— effectively flooring the x coordinate to a multiple of 4.
  • Direction
The configuration data is stored in the object's direction.
Unless otherwise noted, an object's direction determines its initial movement direction and whether its graphic is flipped horizontally.
  • Data blocks
The configuration data is stored in one or more DataBlockPlacement structures that follow the object's associated ObjectPlacement1D or ObjectPlacement2D structure.

Object State

0xC000-C7FF: A list of 8 ObjectState structures in RAM that describe which objects are currently in existence.

ObjectState Structure

Describes an object's state.

  • 0xB4-B6: x coordinate, in 1/0x100 pixels.
  • 0xB7-B9: y coordinate, in 1/0x100 pixels.
  • 0xBA-CE: Often used for data that is specific to a type of object.
  • 0xCF: Invulnerability timer
  • 0xD0-D2: A 24-bit pointer (bank last) to tile patterns for the object's metasprite.
  • 0xD3-D4: A 16-bit pointer to the first tile pattern allocated for this object in VRAM.
  • 0xD5: The number of tile patterns for this object's graphics that need to be uploaded to VRAM.
  • 0xD6:
  • Bit 2: Whether the object's graphics need to be updated.
  • 0xD7-D8: A 16-bit pointer to the MetaspriteLayout used by the object's metasprite in ROM bank 0x06. If the MSB of this pointer is 0, then it means that none has been assigned.
  • 0xD9: The index of the first tile pattern allocated for this object's graphics.
  • 0xDA-DB: The next value of ObjectState+0xD7.
  • 0xDC: The next value of ObjectState+0xD9.
  • 0xDD: ?
  • 0xDE: ?
  • 0xDF: ? The previous value of ObjectState+0xDE.
  • 0xE0: ?
  • 0xE1: ? The previous value of ObjectState+0xE0.
  • ...
  • 0xE8: ?
  • ...
  • 0xEA: ?
  • 0xEB: ?
  • 0xEC-ED: A pointer to the MetaspriteSet in ROM bank 6 that contains the MetaspriteInfo for the object's metasprite.
  • 0xEE-EF:
  • Bits 0x0-E: A 16-bit pointer to the object's update function in ROM bank 4.
  • Bit 0xF: ?
  • 0xF0: ?
  • 0xF1: ?
  • ...
  • 0xF3: ?
  • 0xF4: ?
  • 0xF5: ?
  • 0xF6: ?
  • 0xF7: ?
  • 0xF8: ?
  • 0xF9: ?
  • 0xFA-FB: ?
  • 0xFC-FD: ?
  • ...?

Object Directions

  • 0: Right
  • 1: Left

Object Types

Valid object type IDs range from 0x00-3E.

0x00 (OBJ_NULL)

A special object type that represents "no object". While it can be spawned, doing so restarts the game.

0x01 (OBJ_EXPLOSION)

An explosion, like what appears when you destroy a buddy barrel or an animal crate.

0x02 (OBJ_ANIMAL_CRATE)

An animal crate containing an animal friend.

Configuration
  • x bits 0-1: The type of animal crate this is
ObjectState Variables
  • 0xB2: The type of animal crate this is.
Graphics

The animal crate's type is used as a metasprite set index.

Animal Crate Types
  • 0: Rambi
  • 1: Expresso
  • 2-3: Empty (the crate self-destructs)

0x03 (OBJ_BURIED_TIRE)

A half-buried tire

See also: OBJ_TIRE

0x04 (OBJ_SWIRLWIND)

Swirlwind

0x05 (OBJ_ZINGER)

Zinger

Configuration
  • x bits 0-1: Movement pattern type
The type of movement pattern to use.
  • Direction: Affects its graphic, but does not affect its movement pattern.
ObjectState Variables
  • 0xBA-BB: Affects the movement pattern
  • 0xBD-BE: Affects the movement pattern
  • 0xC2: The type of movement pattern being used.
Zinger Movement Pattern Types
  • 0: Vertical (short)
  • 1: Circular / diagonal
  • 2: Vertical (long)

0x06 (OBJ_KRITTER)

Kritter

Configuration
  • Data Block 0:
  • 0x00:
  • 0x01: LSB of movement range minimum
  • 0x02: MSB of movement range minimum
  • 0x03: LSB of movement range maximum
ObjectState Variables
  • 0xBB: ?
  • 0xC0-C1: Movement range minimum
  • 0xC2-C3: Movement range maximum

See also: OBJ_JUMPING_KRITTER

0x07 (OBJ_ARMY)

Army

ObjectState Variables
  • 0xC2: ?

0x08 (OBJ_SLIPPA)

Slippa

Configuration
  • Data Block 0:
  • 0x00:
  • 0x01: LSB of movement range minimum
  • 0x02: MSB of movement range minimum
  • 0x03: LSB of movement range maximum
ObjectState Variables
  • 0xC0-C1: Movement range minimum
  • 0xC2-C3: Movement range maximum

See also: OBJ_CLIMBING_SLIPPA, OBJ_SLIPPA_JAR

0x09 (OBJ_VINE)

A vine that may be swung on

Configuration
  • x bits 0-1: The vine's ID
A vine's ID is used to determine whether the vine will automatically start swinging when it spawns. If a vine with the preceding ID is in view when this vine spawns, then this vine will start out swinging and with its animation frame automatically synchronized.
Vine IDs wrap around from 0 to 3, therefore the ID that precedes 0 is 3. The same ID may be used by multiple vines.
  • Direction: Only affects the vine's graphics. There is no way to make a left-swinging vine.
ObjectState Variables
  • 0xB1: ?
  • 0xC2: The vine's ID
  • 0xC3: Whether the vine is NOT swinging
Graphics
  • Unless a vine starts out swinging, it starts with metasprite set index 0x12.
  • Unlike most objects, sprite palette 1 is used for its graphic.

0x0A (OBJ_KONG_LETTER)

A K-O-N-G letter.

Configuration
  • x bits 0-1: The type of K-O-N-G letter this is.
ObjectState Variables
  • 0xC0: The type of K-O-N-G letter this is.
Graphics
  • Its graphic isn't flipped according to it's direction.
  • The tile pattern indices used for the object's graphic are offset based on which type of K-O-N-G letter this is, like so:
tilePatternIndexOffset = type * 4
K-O-N-G Letter Types
  • 0: K
  • 1: O
  • 2: N
  • 3: G

See also: OBJ_KONG_LETTER_PLATFORM, OBJ_KONG_LETTER_PLATFORM_MACHINE

0x0B (OBJ_BUDDY_BARREL)

Buddy barrel

See also: OBJ_TOUCH_ACTIVATED_BUDDY_BARREL

0x0C (OBJ_NECKY)

Necky

See also: OBJ_COCONUT_PROJECTILE

0x0D (OBJ_KONG_TOKEN_COUNTER)

Kong token counter (used for bonus stage minigames)

See also: OBJ_KONG_TOKEN

0x0E (OBJ_TIRE)

Tire

See also: OBJ_BURIED_TIRE

0x0F (OBJ_BANANA_BUNCH)

Banana bunch

0x10 (OBJ_OIL_DRUM)

Oil drum

Configuration
ObjectState Variables
Oil Drum Behavior Types
  • 0: On fire permanently
  • 1: Alternates between on fire and extinguished
  • 2: Extinguished permanently

0x11 (OBJ_EXTRA_LIFE_BALLOON)

Extra life balloon

0x12 (OBJ_MINCER)

Mincer

Configuration
  • Data Block 0: ?

0x13 (OBJ_TNT_BARREL)

TNT barrel

See also: OBJ_WOODEN_BARREL, OBJ_METALLIC_BARREL

0x14 (OBJ_METALLIC_BARREL)

Metallic barrel

See also: OBJ_WOODEN_BARREL, OBJ_TNT_BARREL

0x15 (OBJ_EXPRESSO)

Expresso

See also: OBJ_ANIMAL_CRATE

0x16 (OBJ_RAMBI)

Rambi

See also: OBJ_ANIMAL_CRATE

0x17 (OBJ_MINI_NECKY)

Mini-necky

See also: OBJ_COCONUT_PROJECTILE

0x18 (OBJ_NEMO)

Nemo

Configuration
  • Data Block 0: ?

0x19 (OBJ_BUTTON)

Button

0x1A (OBJ_JUMPING_KRITTER)

Kritter (jumping)

Configuration
  • Data Block 0: ?

See also: OBJ_KRITTER

0x1B (OBJ_GNAWTY)

Gnawty

Configuration
  • Data Block 0:
  • 0x00:
  • 0x01: LSB of movement range minimum
  • 0x02: MSB of movement range minimum
  • 0x03: LSB of movement range maximum
ObjectState Variables
  • 0xC0-C1: Movement range minimum
  • 0xC2-C3: Movement range maximum

0x1C (OBJ_COCONUT_PROJECTILE)

The coconut thrown by neckies and mini-neckies

See also: OBJ_NECKY, OBJ_MINI_NECKY

0x1D (OBJ_EXPLOSIVES_BARREL)

A barrel of explosives

0x1E (OBJ_ROPE)

A climbable rope

Configuration
  • x bits 0-1: The type of rope this is.
  • Direction: Has no effect. The rope's initial movement direction is always to the right.
  • Data Block 0:
This data block is only used if the rope's type is 0.
This data block must be present if the rope's type is 0.
  • 0x00:
  • 0x01: LSB of movement range minimum
  • 0x02: MSB of movement range minimum
  • 0x03: LSB of movement range maximum
ObjectState Variables
  • 0xC0-C1: Movement range minimum
  • 0xC2-C3: Movement range maximum
  • 0xC4: The type of rope this is.
  • 0xC5: Current length
  • 0xC6: Target length
  • 0xC9: (Hidden ropes only) The ID of the bonus map that the rope leads to. It must be a bonus map.
Graphics
  • Ropes are drawn in segments.
    • Each segment is drawn using a single 8 x 16 sprite.
    • A segment's sprite must not overlap with any other segment's sprite.
    • Graphics are available for 3 segment lengths: 0x10, 0x08, and 0x04 with tile pattern index offsets of 0x00, 0x02, and 0x04 respectively.
      • Many of the segment length graphics are shorter than a sprite. In those cases, the graphic is aligned to the topmost edge of the sprite.
    • Because the segments do not have per-pixel precision, one end of the rope is unable to smoothly adjust as the rope's length changes. The bottom end of the rope is always the one to do this.
  • Its graphics do not flip according to its direction.
  • Ropes are drawn with an offset of (-10,2).
Rope Types
  • 0: Fixed-length
  • Length: 0x78
  • Motion: Stationary until climbed. Afterward it ping-pongs horizontally within its movement range with an initial direction of right.
  • 1: Hidden
  • Length: 0x00 increasing to 0x78
  • Motion: Moves upward until it disappears
  • Notes: This kind of rope warps you to another map if you climb it. Since there's no way to specify a destination map in the configuration, this rope can only be used properly when spawned programmatically which only happens when a hidden rope gets revealed.

0x1F (OBJ_KLAPTRAP)

Klaptrap

Configuration
  • Data Block 0:
  • 0x00:
  • 0x01: LSB of movement range minimum
  • 0x02: MSB of movement range minimum
  • 0x03: LSB of movement range maximum
ObjectState Variables
  • 0xC0-C1: Movement range minimum
  • 0xC2-C3: Movement range maximum

0x20 (OBJ_KONG_LETTER_PLATFORM_MACHINE)

Transforms K-O-N-G letters into platforms

See also: OBJ_KONG_LETTER, OBJ_KONG_LETTER_PLATFORM

0x21 (OBJ_CHOMPS_JR)

Chomps Jr.

Configuration
  • Data Block 0:
  • 0x00:
  • 0x01: Movement range minimum x
If this value is non-zero, then it gets negated and made object-relative.
  • 0x02: Movement range maximum x
If this value is non-zero, then it gets made object-relative. Otherwise, 0x4000 is used instead.
  • 0x03: (Wave movement type only) The height of the movement track.
ObjectState Variables
  • 0xC0: Whether the custom movement range minimum y is enabled
  • 0xC1-C2: Movement range minimum x
  • 0xC3-C4: Movement range maximum x
  • 0xC6-C7: ?
  • 0xC8: ? (Wave movement type only) The height of the movement track.
Fish Movement Types
  • 0: Wander
The object will wander around in its movement area.
Movement range minimum y: -0x80 (object-relative)
Movement range maximum y: 0 (object-relative)
  • 1: Wave
The object will move as if it's on a track shaped like a series of sine waves.
The track's width is the same as the movement range's width. The track's height is set manually.
Movement range minimum y: The height of the movement track (negated and made object-relative)
Movement range maximum y: 0 (object-relative)

0x22 (OBJ_CLAMBO)

Clambo

0x23 (OBJ_KONG_LETTER_PLATFORM)

A platform that looks like a K-O-N-G letter

Configuration
  • x bits 0-1: The type of K-O-N-G letter this is.
  • y bits 0-1: Group ID
The ID of the group of K-O-N-G letter platforms that this belongs to.
When K-O-N-G letters are fed into a K-O-N-G letter platform machine, only K-O-N-G letters in the same group get revealed.
ObjectState Variables
  • 0xC0: The type of K-O-N-G letter this is.
  • 0xC1: Group ID
Graphics

It gets drawn in the same way as OBJ_KONG_LETTER.

See also: OBJ_KONG_LETTER, OBJ_KONG_LETTER_PLATFORM_MACHINE

0x24 (OBJ_FANGFISH)

Fangfish

Configuration
  • Data Block 0:
  • 0x00:
  • 0x01: Movement range minimum x
If this value is non-zero, then it gets negated and made object-relative.
  • 0x02: Movement range maximum x
If this value is non-zero, then it gets made object-relative. Otherwise, 0x4000 is used instead.
  • 0x03: (Wave movement type only) The height of the movement track.
ObjectState Variables
  • 0xC0: Whether the custom movement range minimum y is enabled
  • 0xC1-C2: Movement range minimum x
  • 0xC3-C4: Movement range maximum x
  • 0xC6-C7: ?
  • 0xC8: ? (Wave movement type only) The height of the movement track.

0x25 (OBJ_KRUSHA)

Krusha

Configuration
  • Data Block 0:
  • 0x00:
  • 0x01: LSB of movement range minimum
  • 0x02: MSB of movement range minimum
  • 0x03: LSB of movement range maximum
ObjectState Variables
  • 0xBB: ?
  • 0xC0-C1: Movement range minimum
  • 0xC2-C3: Movement range maximum

0x26 (OBJ_GLOOP)

Gloop

Configuration
  • Data Block 0:
  • 0x00:
  • 0x01: LSB of movement range minimum
  • 0x02: MSB of movement range minimum
  • 0x03: LSB of movement range maximum
ObjectState Variables
  • 0xC0-C1: Movement range minimum
  • 0xC2-C3: Movement range maximum

0x27 (OBJ_WOODEN_BARREL)

Wooden barrel

See also: OBJ_TNT_BARREL, OBJ_METALLIC_BARREL

0x28 (OBJ_WILD_STING)

Wild sting

ObjectState Variables
  • 0xC2: ?
  • 0xC3: ?
Graphics

Data set 0x2B must be loaded for objects of this type to appear correctly. Additionally, the map must be set to load metasprite graphics from RAM (see MapInfo). As a result, objects of this type will only appear correctly on map 0x2B (Wild Sting Fling).

0x29 (OBJ_HARD_HAT)

Hard Hat

Graphics

Data set 0x20 must be loaded for objects of this type to appear correctly. Additionally, the map must be set to load metasprite graphics from RAM (see MapInfo). As a result, objects of this type will only appear correctly on map 0x20 (Mad Mole Holes).

See also: OBJ_HARD_HAT_PROJECTILE

0x2A (OBJ_CHECKPOINT)

Checkpoint

ObjectState Variables
  • 0xC0: ?

0x2B (OBJ_GOAL)

Goal

0x2C (OBJ_HOGWASH)

Hogwash

Configuration
  • Data Block 0:
  • 0x00:
  • 0x01: LSB of movement range minimum
  • 0x02: MSB of movement range minimum
  • 0x03: LSB of movement range maximum
ObjectState Variables
  • 0xC0-C1: Movement range minimum
  • 0xC2-C3: Movement range maximum

0x2D (OBJ_SLIPPA_JAR)

A jar that spawns slippas

Configuration
  • x bit 0: Determines which directions to spawn slippas in
Possible values:
  • 0: Spawns slippas to the left
  • 1: Spawns slippas to the left and right
  • x bit 1: The slippa jar's initial state
  • y bit 0: Slippa spawn delay
Determines the delay between when a slippa dies and when the slippa jar spawns more of them.
Possible values:
  • 0: Short delay
  • 1: Long delay
  • Direction: (while stationary only) Affects the jar's graphic only. The slippas that it spawns are not affected.
  • Data Block 0:
  • 0x00:
  • Bits 0-4: MSB of slippa movement range maximum
  • Bits 5-7: Reserved (see DataBlockPlacement).
  • 0x01: LSB of slippa movement range minimum
  • 0x02: MSB of slippa movement range minimum
  • 0x03: LSB of slippa movement range maximum
ObjectState Variables
  • 0xBA-BC: The horizontal movement speed to use while rolling, in 1/0x100 pixels.
  • 0xC0-C1: Slippa movement range minimum
  • 0xC2-C3: Slippa movement range maximum
  • 0xC4:
  • Bit 5: Related to the direction that slippas are spawned in
  • 0xC5:
  • Bit 5: Related to the direction that slippas are spawned in
  • 0xC7: Slippa spawn delay
Graphics
Slippa Jar States
  • 0: Stationary
The slippa jar remains stationary and spawns slippas.
  • 1: Rolling
The slippa jar rolls around, presumably powered by any slippas that are inside it. If it runs into a wall, then it rights itself and becomes Stationary.

See also: OBJ_SLIPPA

0x2E (OBJ_TOUCH_ACTIVATED_BUDDY_BARREL)

A touch-activated buddy barrel

See also: OBJ_BUDDY_BARREL

0x2F (OBJ_KONG_TOKEN)

Kong token

0x30 (OBJ_CLOUD_PLATFORM)

Cloud platform

Configuration
  • Direction: Whether to focus the camera on the platform. The object's direction gets set to 0.
ObjectState Variables
  • 0xBC: ?
  • 0xC1:
  • Bit 5: Whether to focus the camera on the platform.

0x31 (OBJ_BARREL_CANNON)

Barrel cannon

Configuration
  • Direction: Only affects the object's graphic
  • Data Block 0:
  • 0x00:
  • Bits 0-4: Movement speed, in increments of 0x20.
It determines the speed at which to move along the movement track.
  • 0x01:
  • Bit 0: No discernible effect. Every barrel cannon in the game has this bit set to 0.
  • Bit 1: Whether to move while full.
  • Bit 2: Whether to move while empty.
  • Bits 3-7: The length of the movement track along the movement track's forward axis, in increments of 8.
  • 0x02:
  • Bit 0: (Delayed barrel cannons only) Whether to allow shooting while rotating.
  • Bits 1-2: The movement track's forward axis.
When a barrel begins moving along its track, it always starts along the backward axis. For example: if the forward axis is north, then it will initially move south, stop, then move north.
  • Bits 3-7: The length of the movement track along the movement track's backward axis, in increments of 8.
  • 0x03:
The relative direction that the barrel rotates in to meet its target rotation.
  • Bits 4-6: Target rotation, in increments of 2.
The barrel cannon must reach this rotation before it can shoot.
  • Bit 7: Barrel cannon type.
The type of barrel cannon this is.
  • Data Block 1:
  • 0x00:
  • Bits 0-4: Physics delay
The number of frames to disable character physics for after shooting, in increments of 8.
  • 0x01:
  • Bits 0-2: Unused
  • Bits 3-7: Input delay
The number of frames to disable character input for after shooting, in increments of 8.
  • 0x02: The amount of force to shoot with.
0x40 is a little force and 0x90 is a lot. Shooting upward requires much more force than shooting in other directions.
  • 0x03:
  • Bit 0: Unused
  • Bit 1: Rotation mode
  • Bit 2: Whether to enable "rotate while empty" when entered.
This is the only way to enable "rotate while empty".
  • Bit 3: Whether to enable "move while empty" when entered.
This could be used to, for example, allow the barrel cannon to move out of reach after it has been fired.
  • Bits 4-7: The rotation speed, in increments of 0x10.
A rotation speed of 0x100 will turn the barrel cannon by one secondary-intercardinal direction (i.e. 22.5 degrees) per frame.
ObjectState Variables
  • Bits 0-3: The barrel cannon's current direction.
  • Bit 4: The type of barrel cannon this is.
  • Bits 5-7: Must be 0.
  • 0xBA-BB: Movement speed.
  • 0xBC: ?
  • 0xC0:
  • Bit 0: ?
  • Bit 1: Whether to move while full.
  • Bit 2: Whether to move while empty.
  • Bit 3: (Delayed barrel cannons only) Whether to allow shooting while rotating.
  • Bit 4-5: The movement track's forward axis.
  • Bit 6: Whether to enable "rotate while empty" when entered.
  • Bit 7: Whether to enable "move while empty" when entered.
  • 0xC1-C2: The minimum x or y coordinate of the movement track's extents. A y coordinate is used unless the movement track's forward axis is 1.
  • 0xC3-C4: The maximum x or y coordinate of the movement track's extents. A y coordinate is used unless the movement track's forward axis is 1.
  • 0xC5: Initial rotation
  • 0xC6: Target rotation
  • 0xC7: The value that gets added to the rotation when a full rotation step has been made. Its value depends on the barrel cannon's relative rotation direction. This should be either -1 (rotate Left) or 1 (rotate Right)).
  • 0xC8: Physics delay, in frames.
  • 0xC9: Input delay, in frames.
  • 0xCA: Shooting force.
  • 0xCB: Rotation speed.
  • 0xCC:
  • Bit 0: The barrel cannon's rotation mode.
  • Bits 1-5: ?
  • Bit 6: Whether to rotate while empty.
  • Bit 7: Whether to shoot now.
  • 0xCE: ?
Graphics

The metasprite set index used can be calculated like so:

metaspriteSetIndex = type * 0x10 + rotation
Barrel Cannon Types
  • 0: Delayed
The barrel cannon shoots only after user input. It has no emblem.
Note that, unless its option to shoot while rotating is enabled, this type of barrel cannon must reach its target rotation before it can be fired. This can be a problem if its rotation speed is set to zero or if its rotation mode is set to Forever. In either situation, the character would become stuck inside the barrel cannon if they were to use it.
  • 1: Auto-fire
The barrel cannon shoots after it finishes rotating, without user input. It has an explosion emblem.
Barrel Cannon Rotation Modes
  • 0: Once
When entered, the barrel cannon will rotate to its target rotation and then stop. After being fired it will rotate back to its initial rotation.
  • 1: Forever
The barrel cannon repeatedly rotates to its target rotation and then back. If the initial and target rotations are the same, then this results in the barrel cannon spinning in one direction forever.
Barrel Cannon Directions

Barrel cannon directions start at north and turn clockwise in increments of secondary-intercardinal directions (i.e. 22.5 degrees).

  • 0x0: N
  • 0x1: NNE
  • 0x2: NE
  • 0x3: ENE
  • 0x4: E
  • 0x5: ESE
  • 0x6: SE
  • 0x7: SSE
  • 0x8: S
  • 0x9: SSW
  • 0xA: SW
  • 0xB: WSW
  • 0xC: W
  • 0xD: WNW
  • 0xE: NW
  • 0xF: NNW
Barrel Cannon Relative Directions
  • 0: Left
  • 1: Right
Barrel Cannon Movement Track Forward Axes
  • 0: N
  • 1: W
  • 2: NW
  • 3: NE

0x32 (OBJ_MOVING_PLATFORM)

Moving platform

Configuration
  • x bits 0-1: The type of moving platform that this is.
  • y bits 0-1: ?
  • Direction: ? The object's direction gets overwritten with 0.
  • Data Block 0:
?
This data block is only used if the platform's type is in the range 0-1.
This data block must be present if the platform's type is in the range 0-1.
Graphics

The first metasprite set index used is based on the moving platform's type and can be calculated like so:

firstMetaspriteSetIndex = type * 4
Moving Platform Types

Valid moving platform types range from 0-2.

  • 0: Conveyor
Animation length: 4
  • 1: Directional
Animation length: 1 (4 subimages— one for each direction)
  • 2: Rock
Animation length: 1

0x33 (OBJ_HARD_HAT_PROJECTILE)

The hard hat thrown by Hard Hat.

Graphics

Data set 0x20 must be loaded for objects of this type to appear correctly. Additionally, the map must be set to load metasprite graphics from RAM (see MapInfo). As a result, objects of this type will only appear correctly on map 0x20 (Mad Mole Holes).

See also: OBJ_HARD_HAT

0x34 (OBJ_SNAPPER)

Snapper

Configuration
  • Data Block 0:
  • 0x00:
  • 0x01: LSB of movement range minimum
  • 0x02: MSB of movement range minimum
  • 0x03: LSB of movement range maximum
ObjectState Variables
  • 0xC0-C1: Movement range minimum
  • 0xC2-C3: Movement range maximum

0x35 (OBJ_CLIMBING_SLIPPA)

A slippa that climbs downward. Once it reaches the end of its climbing range it falls to its demise.

Configuration
  • Data Block 0:
  • 0x00:
  • 0x01: LSB of climbing range minimum
  • 0x02: MSB of climbing range minimum
  • 0x03: LSB of climbing range maximum
ObjectState Variables
  • 0xC0-C1: Climbing range minimum
  • 0xC2-C3: Climbing range maximum

See also: OBJ_SLIPPA

0x36 (OBJ_BOULDER)

Boulder

See also: OBJ_BOULDER_SPAWNER

0x37 (OBJ_BOULDER_SPAWNER)

An invisible object that spawns boulders

Configuration
  • x bits 0-1: Bits 0-1 of the boulder spawn rate.
The rate at which to spawn boulders.
Example values:
  • 0x00: Never spawn boulders.
  • 0x03: Spawn a boulder approximately every half a second.
  • 0x15: Spawn an impenetrable cascade of boulders.
  • y bits 0-1: Bits 1-2 of the boulder spawn rate.
  • y bit 2: Boulder spawn type.
Possible values:
  • 0: In-place
Spawn boulders at the boulder spawner's location.
  • 1: From above
Spawn boulders at the top of the screen.
ObjectState Variables
  • 0xC0: Boulder spawn rate.
  • 0xC1: Boulder spawn timer. A boulder gets spawned when it overflows.
  • 0xC2: ?

See also: OBJ_BOULDER

0x38 (OBJ_CAMERA_CUE)

Camera cue. It's an invisible object that affects the camera's behavior while it's in view.

0x39 (OBJ_WARP_POINT)

A warp point— an invisible object that moves you to another location when you touch it.

Configuration

Data block 0:

If the map containing the warp point is a bonus map, then this data block gets ignored and the game returns to the previous map.
  • 0x00:
  • 0x01: Destination
The ID of the bonus map to warp to. The destination must be a bonus map.
  • 0x02: Return spawn point
The ID of the spawn point to return to. It's used to index in the list of SpawnInfo structures at 0x4BED3 that describe where to spawn the player character after they exit the bonus map.
  • 0x03: Unused
ObjectState Variables
  • 0xC9: (Non-bonus maps only) Destination map ID

0x3A (OBJ_CROWN_PROJECTILE)

The crown thrown by King K. Rool.

Graphics

Data set 0x39 must be loaded for objects of this type to appear correctly. Additionally, the map must be set to load metasprite graphics from RAM (see MapInfo). As a result, objects of this type will only appear correctly on map 0x39 (K. Rool's Kingdom).

See also: OBJ_KING_K_ROOL

0x3B (OBJ_KING_K_ROOL)

King K. Rool

Graphics

Data set 0x39 must be loaded for objects of this type to appear correctly. Additionally, the map must be set to load metasprite graphics from RAM (see MapInfo). As a result, objects of this type will only appear correctly on map 0x39 (K. Rool's Kingdom).

See also: OBJ_CROWN_PROJECTILE

0x3C (OBJ_BALLOON_PLATFORM)

Balloon platform

0x3D (OBJ_COLOSSAL_CLAMBO)

Colossal Clambo

Configuration
  • x bits 0-1: Which part of Colossal Clambo this represents.
ObjectState Variables
  • 0xC0: Which part of Colossal Clambo this represents.
Graphics

Data set 0x37 must be loaded for objects of this type to appear correctly. Additionally, the map must be set to load metasprite graphics from RAM (see MapInfo). As a result, objects of this type will only appear correctly on map 0x37 (Seabed Showdown).

Colossal Clambo Part Types
  • 0: Colossal Clambo
  • 1: Clam
  • 2: Pearl projectile

0x3E (OBJ_UNKNOWN_3E)

It doesn't show up when spawned. The code treats it a lot like K-O-N-G letters and K-O-N-G letter platforms.

Metasprites

A metasprite is a collection of one or more sprites drawn together to form a complete graphic.

MetaspriteSet Structure

  • 0x00+: A list of MetaspriteInfo structures. It's indexed using a metasprite set index. It has no clearly defined end point.

MetaspriteInfo Structure

Describes how to draw a metasprite.

  • 0x00-03:
  • Bits 0x00-0D: A 16-bit pointer to the metasprite's MetaspriteLayout is this value + 0x4000. If this value is 0, then the metasprite has no layout and must be drawn programmatically.
To determine which bank is being pointed to, consider the type of metasprite this is:
  • Is it a player character metasprite? Use ROM bank 5
  • Is it some other kind of metasprite? Use ROM bank 6
Alternatively, one can assume that it points to the same ROM bank as the MetaspriteInfo structure since that seems to always be the case.
  • Bits 0x0E-12: The ROM bank containing the metasprite's tile patterns.
  • Bits 0x13-16: The number of tile patterns used by this metasprite is this value * 2.
  • Bits 0x17-1F:
The address of the metasprite's tile patterns can be derived from this value like so:
base = ? (see below)
address = base + value*0x20
If the metasprite in question is a player character metasprite, then base has a value of 0x4000. Otherwise, the value of base can be determined by looking at the map's MapInfo.

MetaspriteLayout Structure

Describes the metasprite-relative locations of the sprites that compose a metasprite.

  • 0x00: The number of items in the following list is this value / 4.
  • 0x01+: A list of SignedPoints that describe metasprite-relative offsets for each sprite that composes the metasprite.

This structure must never cross a 0x100 byte page boundary.

SignedPoint Structure

  • 0x0: y coordinate (signed)
  • 0x1: x coordinate (signed)

Drawing Metasprites

  • Each sprite forming a metasprite is drawn relative to the metasprite based on an offset from in the metasprite's MetaspriteLayout structure. An additional offset of (-8,-16) is added as well.
  • Only 8 x 16 sprites are used when drawing metasprites.
  • Tile pattern indices increase by 2 for every consecutively drawn sprite.
  • Sprite palette 0 is used for most metasprites. Some objects, such as OBJ_VINE, use sprite palette 1 instead.
  • When flipping the metasprite horizontally, negate the x offset from the MetaspriteLayout structure before adding it. Additionally, the metasprite should be drawn 8 pixels to the left.

Bananas

Unlike in Donkey Kong Land 2 and Donkey Kong Land III, banana layout data is stored separately from other layout data. Up to 0x80 bananas may be placed per map.

See also: Map Bananas

BananaLayout Structure

BananaGroupPlacement Structure

This structure defines zero or more group-relative banana placements.

  • 0x00-01:
Bit 0x0: Must be 0.
Bits 0x1-C: The group's x coordinate is this value * 2.
Bits 0xD-F: The most significant byte of the group's y coordinate*.
  • 0x02: The least significant byte of the group's y coordinate*.
  • 0x03+: A list of BananaGroupMember structures. It's terminated with the 8-bit value 0.

* The group's y coordinate should get multiplied by 4.

BananaGroupMember Structure

  • 0x00: Must not be 0.
Bits 0-3*: The banana's group-relative y coordinate is this value * 8.
Bits 4-7*: The banana's group-relative x coordinate is this value * 8.
* Subtract 1 from the byte's value before extracting these bits.

DummyBananaPlacement Structure

This structure describes the placement of a special kind of banana whose x coordinate is always set to 0xFF00. They are probably used to partition regular bananas.

  • 0x00-01:
Bit 0x0: Must be 1.
Bits 0x1-F: The banana's y coordinate.

Drawing Bananas

  • The 8 tile patterns for the banana animation can be found in data set 0x58. They get loaded to 0x8780-87FF in VRAM (tile pattern indices 0x78-7F).
  • Each banana is drawn using a single 8 x 16 sprite.
  • The tile pattern used and whether x flipping is enabled depends on the animation frame.
  • Sprite palette 0 is always used.
  • Bananas are drawn offset from their actual locations by (-12,-24) pixels.

Characters

Character States

0x16792: A list of 16-bit pointers to MetaspriteSet structures in ROM bank 5 that determine the default MetaspriteSet for each of Donkey Kong's character states. It's indexed using a character state ID.

Some of the items in this list seem to point to invalid data— possibly because some character states are incompatible with Donkey Kong.

0x161CC: A list of 16-bit pointers to MetaspriteSet structures in ROM bank 5 that determine the default MetaspriteSet for each of Diddy Kong's character states. It's indexed using a character state ID.

Some of the items in this list seem to point to invalid data— possibly because some character states are incompatible with Diddy Kong.

Character State IDs

...
0x15: File select menu cursor
0x16: Riding Expresso
0x17: Riding Rambi
...
0x1E: Finishing a level
0x1F: Spawning at a checkpoint
...
0x21: Switching characters
0x22: Swimming
...
0x25: Dying
0x26: Crouching
0x27: Rolling
0x28: Standing / walking / running
0x29: Jumping
...?

Data Sets

Data sets are used to load related data all at once.

0x31C4E: A list of DataSet structures. It's indexed using a data set ID.

0x31D58: A list of UncompressedDataTransfer structures. It's indexed using an uncompressed data transfer ID + 1.

0x1C001: A list of CompressedDataTransfer structures. It's indexed using a compressed data transfer ID.

See also: Map Data Sets

DataSet Structure

Describes a list of data transfers to execute.

DataTransferReference Structure

Describes a data transfer to execute.

  • Bits 0-6: A compressed or uncompressed data transfer ID (see below).
  • Bit 7: Whether the data transfer ID above is a compressed or uncompressed data transfer ID.
Possible values:
  • 0: Compressed
  • 1: Uncompressed

UncompressedDataTransfer Structure

Describes where uncompressed data is located and where to copy it to.

  • 0x00: The size of the source data, in bytes, is this value * 0x10. If this value is 0, then its uncompressed size is 0x1000 bytes instead.
  • 0x01-02: Source address (big endian). The source ROM bank is always 0xC.
  • 0x03-04: Destination address (big endian).

CompressedDataTransfer Structure

Describes where compressed data is located and where to decompress it to.

  • 0x00: Compression format / uncompressed size
Possible values:
  • 0x00: Indicates that the source data is compressed using the RLE derivative. Its uncompressed size is not specified.
  • 0x01+: Indicates that the source is compressed using the Huffman coding derivative. Its uncompressed size, in bytes, is this value * 0x10.
  • 0x01-02: Source address
The address of the compressed data to decompress.
  • 0x03-04:
  • Bits 0-3: Source ROM bank
The ROM bank containing the compressed source data. If this is 0, then 0x12 gets used instead.
  • Bits 4-F: Destination address
The address to decompress the source data to is this value * 0x10.

Data Set IDs

  • 0x00-49: The primary data set for the map with the same ID. It usually loads graphics and a metatile collision map.
  • ...
  • 0x58: Loads tile patterns for bananas and hearts.
  • ...?

Tile Animations

The tile animation that plays depends on the current map's map theme ID.

0x1C181: A list of TileTransfer structures that are used for tile animations. It's indexed using a tile transfer ID.

TileTransfer Structure

Describes where tile patterns are located and where to copy them to.

  • 0x00-01:
  • Bits 0-3: Source ROM bank
The ROM bank containing the tile patterns to copy can be derived from this value like so:
romBank = 0x10 + max(1, value)
  • Bits 4-F: Source address
A pointer to the tile patterns to copy is this value * 0x10.
  • 0x02-03: Destination address
A pointer to where to copy the tile patterns to.
  • 0x04: Tile pattern count
The number of tile patterns to copy.

Map Theme Tile Animations

Maps with these map theme IDs play tile animations:

  • 0x02: Animates torch flames by loading tile transfer IDs 0x00-03 in sequence.
  • 0x08: Animates a background of scrolling blocks. The logic involved in doing so is more complicated than for other tile animations.
  • 0x0A: Animates arrow paths by loading tile transfer IDs 0x08-0B in sequence.
  • 0x0B: Animates conveyor ropes by loading tile transfer IDs 0x0C-0F in sequence.

Tile Transfer IDs

  • 0x00-03: Torch flame animation
  • ...
  • 0x08-0B: Arrow path animation
  • 0x0C-0F: Conveyor rope animation
  • ...?

Hidden Ropes

There are 8 hidden ropes in the game. They can be revealed by stomping on weak terrain found at various locales. Doing so will reveal a hole that the hidden rope then rises from. Climbing the hidden rope will warp the player character to a bonus map.

Hidden ropes are spawned programmatically and behave a little differently from regularly-spawned ropes:

  • They don't have configuration data.
  • The rope's type is set to Hidden, but their target length gets overwritten with 0x60.

0xBB0F: A list of HiddenRopeInfo structures. It's indexed using a hidden rope ID.

See also: Map Hidden Ropes

HiddenRopeInfo Structure

  • 0x00-01: x
The hidden rope's x coordinate.
  • 0x02-03: y
The hidden rope's y coordinate
  • 0x04: Destination
The ID of the bonus map that the hidden rope leads to. It must be a bonus map.
  • 0x05-09: Return point
A SpawnInfo structure describing where to return to after exiting the bonus map.

Hidden Rope IDs

  • 0x00: The hidden rope used by map 0x09.
  • 0x01: The hidden rope used by map 0x05.
  • 0x02: The hidden rope used by map 0x0D.
  • 0x03: The hidden rope used by map 0x13.
  • 0x04: The hidden rope used by map 0x1C.
  • 0x05: The hidden rope used by map 0x0F.
  • 0x06: The hidden rope used by map 0x19.
  • 0x07: The hidden rope used by map 0x01.

Hidden Caves

There are 3 hidden caves in the game disguised as regular stone walls. They become revealed when their entrances are touched by either Rambi or a rolling metallic barrel.

The way this works is that each map with a hidden cave is assigned a MapPatchHotspotSet. A MapPatchHotspot from the set gets triggered if either Rambi or a rolling metallic barrel enter its hotspot area.

Linking caves to other areas isn't done in any special way. Instead, it is done by using warp point objects.

See also: Map Hidden Caves

MapPatchHotspotSet Structure

A set of MapPatchHotspot structures.

  • 0x00-01: A 16-bit pointer to the same ROM bank. Pointed to is the next item in the set or the 16-bit value 0 if there is no next item.
  • Following that is a MapPatchHotspot structure that is part of the set. There is always at least one item in the set.

See also: MapPatchHotspot

MapPatchHotspot Structure

Describes a map patch and the area in which it can be triggered.

  • 0x00: ID
An ID that's used to check whether the patch has been applied.
  • 0x01-02: x
The x coordinate of the hotspot area.
  • 0x03: Width
The width of the hotspot area (extends rightward).
  • 0x04-05: y
The y coordinate of the hotspot area.
  • 0x06: Height
The height of the hotspot area (extends downward).
  • Following that is a 1-byte list length* followed by a list of ByteTransfer structures to execute when the hotspot is triggered. They are used primarily to update the metatile map.
  • Following that is 1-byte list length* followed by a list of MetatileDrawInfo structures to draw when the hotspot is triggered. They are used to make changes to the metatile map visible immediately. Keep in mind that, since the metatiles are drawn at absolute locations, the camera must be at a very specific location for it to work properly.

* A list length of 0 gets interpreted as 0x100.

See also: MapPatchHotspotSet, ByteTransfer, MetatileDrawInfo

ByteTransfer Structure

Describes an 8-bit value and where it should be written to. To execute a ByteTransfer, write its value to its destination.

  • 0x00-01: Destination
The address to write to the value to.
  • 0x02: Value
The value to write to the destination.

MetatileDrawInfo Structure

Describes where to draw a metatile on a VRAM tile map.

  • 0x00: The ID of the metatile to draw.
  • 0x01-02: A pointer to a tile of a VRAM tile map where the top-left corner of the metatile will be drawn.

Compression

Donkey Kong Land uses several different compression schemes— most of which are also used by its sequels Donkey Kong Land 2 and Donkey Kong Land III.

LZ Derivative

The metatile maps are compressed using the same LZ derivative found in Donkey Kong Land 2 and Donkey Kong Land III.

Format

  • Four bits (a half of a byte, or one nibble) are read at a time. If the game finds the following hexadecimal sequences: BE, BF, C, D, E, or F, it is treated as separate compression cases. If it finds any other type of 8-bit hexadecimal sequence, it is treated as an uncompressed byte.
  • Case BE:
    • Format: BE xx y
      • xx: Initial tile, increased by 0x01 each time
      • y: Length-3. Resulting length can range from 0x3 to 0x12.
      • Examples:
        • BE 00 3 -- Initial tile is 00, and length is 3+3=6. The resulting decompressed data: 00 01 02 03 04 05.
        • BE 48 F -- Initial tile is 48, and length is 3+F=12. The resulting decompressed data: 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59.
  • Case BF:
    • Format: BF xx yy z
      • xx yy: Two tiles (useful for repeated 64x32-pixel structures)
      • z: Length-2. Resulting length can range from 0x2 to 0x11.
      • Examples:
        • BF 30 31 5 -- Tiles are 30 31, and length is 5+2=7. The resulting decompressed data: 30 31 30 31 30 31 30 31 30 31 30 31 30 31.
        • BF 24 29 9 -- Tiles are 24 29, and length is 9+2=B. The resulting decompressed data: 24 29 24 29 24 29 24 29 24 29 24 29 24 29 24 29 24 29 24 29 24 29.
  • Case C:
    • Format:
      • C xx y F zz (if xx is odd)
        • Copies a previously written area in RAM -- it reads int(xx/2) + y*0x80 bytes backwards.
        • zz: Length-4. Resulting length can range from 0x4 to 0x103.
      • C xx y z (if xx is odd and z < F)
        • Copies a previously written area in RAM -- it reads int(xx/2) + y*0x80 bytes backwards.
        • z: Length-4. Resulting length can range from 0x4 to 0x12.
      • C xx F yy (if xx is even)
        • Copies a previously written area in RAM -- it reads int(xx/2) bytes backwards.
        • yy: Length-4. Resulting length can range from 0x4 to 0x103.
      • C xx y (if xx is even and y < F)
        • Copies a previously written area in RAM -- it reads int(xx/2) bytes backwards.
        • y: Length-4. Resulting length can range from 0x4 to 0x12.
      • Examples:
        • C 41 2 3 -- Suppose the current RAM address to be written to is 0xCF00. We must subtract this by int(41/2) + 2*80 = 120 to get 0xCDE0. Length is 3+4=7, so data from 0xCDE0 to 0xCDE6 must be read, and copied into 0xCF00 to 0xCF06. Suppose the data starting at 0xCDE0 contains: 10 11 12 13 28 29 40. Therefore, the data at 0xCF00 to 0xCF06 will also contain this same data: 10 11 12 13 28 29 40.
        • C 41 2 F 13 -- Suppose the current RAM address to be written to is 0xCF00. We must subtract this by int(41/2) + 2*80 = 120 to get 0xCDE0. Length is 13+4=17, so data from 0xCDE0 to 0xCDF6 must be read, and copied into 0xCF00 to 0xCF16. Suppose the data starting at 0xCDE0 contains: 10 11 12 13 28 29 40 50 50 50 50 50 50 50 50 50 40 40 40 40 40 40 40 40. Therefore, the data at 0xCF00 to 0xCF06 will also contain this same data: 10 11 12 13 28 29 40 50 50 50 50 50 50 50 50 50 40 40 40 40 40 40 40 40.
        • C 40 3 -- Suppose the current RAM address to be written to is 0xCF00. We must subtract this by int(40/2) = 20 to get 0xCEE0. Length is 3+4=7, so data from 0xCEE0 to 0xCEE6 must be read, and copied into 0xCF00 to 0xCF06. Suppose the data starting at 0xCEE0 contains: 10 11 12 13 28 29 40. Therefore, the data at 0xCF00 to 0xCF06 will also contain this same data: 10 11 12 13 28 29 40.
        • C 40 F 13 -- Suppose the current RAM address to be written to is 0xCF00. We must subtract this by int(40/2) = 20 to get 0xCEE0. Length is 13+4=17, so data from 0xCEE0 to 0xCEF6 must be read, and copied into 0xCF00 to 0xCF16. Suppose the data starting at 0xCEE0 contains: 10 11 12 13 28 29 40 50 50 50 50 50 50 50 50 50 40 40 40 40 40 40 40 40. Therefore, the data at 0xCF00 to 0xCF06 will also contain this same data: 10 11 12 13 28 29 40 50 50 50 50 50 50 50 50 50 40 40 40 40 40 40 40 40.
  • Case D:
    • Format: D x yy z...
      • x: Constant high nibble
      • yy: Length-0x14. Resulting length can range from 0x14 to 0x113.
      • z: Depending on the length, the game then reads 4-bit sequences, and this ends up being the low nibble.
      • Example:
        • D 5 0C -- 5 is the upper nibble. Length is 0x0C+0x14=0x20. 0x20 4-bit sequences will be read. Suppose the data here contains: 01 23 45 67 89 AB CD EF 00 44 88 CC 76 54 32 10. These are all low nibbles, so the resulting decompressed data will be: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 50 50 54 54 58 58 5C 5C 57 56 55 54 53 52 51 50.
  • Case E:
    • Format:
      • E E
        • End map decompression sequence!
      • E x y z... (if x != E)
        • x: Constant high nibble
        • y: Length-0x4. Resulting length can range from 0x4 to 0x13. This is the difference between cases D and E.
        • z: Depending on the length, the game then reads 4-bit sequences, and this ends up being the low nibble.
      • Example:
        • E 5 C -- 5 is the upper nibble. Length is 0xC+0x4=0x10. 0x10 4-bit sequences will be read. Suppose the data here contains: 01 23 45 67 00 88 32 10. These are all low nibbles, so the resulting decompressed data will be: 50 51 52 53 54 55 56 57 50 50 58 58 53 52 51 50.
  • Case F:
    • Format:
      • F xx y z (if y >= 8)
        • xx: Tile
        • Length: (y mod 8) * 0x10 + z + 0xB. Resulting length can range from 0xB to 0x8A.
      • F xx y (if y < 8)
        • xx: Tile
        • Length: y+3. Resulting length can range from 0x3 to 0xA.
        • Examples:
          • F 48 5 -- Tile is 48, and length is 5+3=8. The resulting decompressed data: 48 48 48 48 48 48 48 48.
          • F 48 D 2 -- Tile is 48, and length is (D mod 8)*0x10+2+B = 0x5D. The resulting decompressed data: 48 being repeated 0x5D times.

Decompressor

A decompressor, implemented in Python 2.7.9:

"""
Decompresses data compressed using the LZ derivative.

@param input - A stream of compressed data.
@return The uncompressed data.
"""
def decompress(stream):
    bitReader = BitReader(stream)
    output = bytearray()
    
    while True:
        nibble = bitReader.readNibble()
        if nibble == 0xC:
            # C xx F yy where xx is even - Write yy+4 bytes from ((int)xx)/2+1 bytes earlier
            # C xx y F zz where xx is odd - Write zz+4 bytes from ((int)(xx+y*0x100))/2+1 bytes earlier
            # C xx y where xx is even - Write y+4 bytes from ((int)xx)/2+1 bytes earlier
            # C xx y z where xx is odd - Write z+4 bytes from ((int)(xx+y*0x100))/2+1 bytes earlier
            
            distance = bitReader.readByte()
            if distance % 2 == 1:
                # Distance is odd.
                distance += bitReader.readNibble() * 0x100
            distance = distance//2 + 1
            
            length = bitReader.readNibble()
            if length == 0xF:
                length = bitReader.readByte()
            length += 4
            
            def reiterate(length, distance):
                source = len(output) - distance
                for i in range(length):
                    output.append(output[source + i])
            
            reiterate(length, distance)
        elif nibble == 0xD:
            # D x yy z[...] - Write xz[i] yy+0x14 times
            constantHighNibble = bitReader.readNibble() << 4
            length = bitReader.readByte() + 0x14
            
            for i in range(length):
                output.append(constantHighNibble | bitReader.readNibble())
        elif nibble == 0xE:
            nibble = bitReader.readNibble()
            if nibble == 0xE:
                # EE - End of stream
                break
            
            # E x y z[...] - Write xz[i] y+4 times
            constantHighNibble = nibble << 4
            length = bitReader.readNibble() + 4
            
            for i in range(length):
                output.append(constantHighNibble | bitReader.readNibble())
        elif nibble == 0xF:
            value = bitReader.readByte()
            length = bitReader.readNibble()
            
            if length >= 0x8:
                # F xx y z where y >= 8 - Write xx n times where n = (y % 8) * 0x10 + z + 0xB
                length = (length % 8) * 0x10 + bitReader.readNibble() + 0xB
            else:
                # F xx y where y < 8 - Write xx y+3 times
                length += 3
            
            for i in range(length):
                output.append(value)
        else:
            byte = (nibble << 4) | bitReader.readNibble()
            if byte == 0xBE:
                # BE xx y - Write xx+i y+3 times
                value = bitReader.readByte()
                length = bitReader.readNibble() + 3
                
                for i in range(length):
                    output.append((value+i) & 0xFF)
            elif byte == 0xBF:
                # BF xxxx y - Write xxxx y+2 times
                byte0 = bitReader.readByte()
                byte1 = bitReader.readByte()
                length = bitReader.readNibble() + 2
                
                for i in range(length):
                    output.append(byte0)
                    output.append(byte1)
            else:
                # xx - Write xx
                output.append(byte)
    
    return output

class BitReader:
    def __init__(self, stream):
        self.stream = stream
        self.currentByte = 0
        self.bitPosition = 7
    
    def readBit(self):
        if self.bitPosition == 7:
            self.currentByte, = unpack("<B", self.stream)
        
        result = getBit(self.bitPosition, self.currentByte)
        
        self.bitPosition -= 1
        if self.bitPosition == -1:
            self.bitPosition = 7
        
        return result

    def readBits(self, bitCount):
        result = 0
        
        for i in range(bitCount):
            result <<= 1
            result |= self.readBit()
        
        return result
    
    def readByte(self):
        return self.readBits(8)
    
    def readNibble(self):
        return self.readBits(4)

def getBit(b, n):
    if b < 0: raise Exception("b must be positive.")
    return (n >> b) & 1

def unpack(fmt, file):
    import struct
    return struct.unpack(fmt, buffer(file.read(struct.calcsize(fmt))))

Huffman Coding Derivative

Most background graphics are compressed using the same Huffman coding derivative found in Donkey Kong Land 2, Donkey Kong Land III, Battletoads (Game Boy), Battletoads in Ragnarok's World, and Battletoads/Double Dragon (Game Boy).

The game's decompressor for this format has a special behavior depending on where data is being decompressed to. After each decompressed byte is written, the game checks whether the destination address is in the range 0x9800-98FF and, if so, subtracts 0x1000 from it— effectively making the destination address wrap around when it is in the range 0x8800-97FF. This behavior allows compressed tile graphics that were originally in unsigned order to be decompressed to VRAM in signed order.

Format

Data compressed in this way takes the form of a bitstream of variable-bit-length code words. Each code word describes a path through a binary tree which starts at branch 0xFE and ends at a leaf node. Each leaf node has an associated literal which gets written to the output. Once enough bytes have been written, the decompression stops.

  • A bitstream value of 0 indicates that a left turn should be made.
  • A bitstream value of 1 indicates that a right turn should be made.
  • The bitstream is read starting from the most significant bit of every byte.

The binary tree is split into three tables:

  • 0x3D00-3DFF: Table LT
Contains 8-bit values for the left-side nodes in the binary tree. It's indexed using a branch ID.
  • 0x3E00-3EFF: Table RT
Contains 8-bit values for the right-side nodes in the binary tree. It's indexed using a branch ID.
  • 0x3F00-3FFF: Table TT
Contains 8-bit values describing the type of each node in tables LT and RT. It's indexed using a branch ID.
Each byte follows this format:
  • Bits 0-2: Unused
  • Bit 3: The type of the node in table LT with the same branch ID.
  • Bits 4-6: Unused
  • Bit 7: The type of the node in table RT with the same branch ID.
Node types:
  • 0: A leaf node whose value is a literal
  • 1: A branch node whose value is the branch ID of its children

The same binary tree is shared by all data compressed in this way.

Decompressor

A decompressor, implemented in Python 2.7.9:

"""
Decompresses data compressed using the Huffman derivative.

@param tables - A tuple containing the 3 decompression tables (left, right, and type).
@param uncompressedSize - The size of the uncompressed data.
@param input - A stream of compressed data.

@return The uncompressed data.
"""
def decompress(tables, uncompressedSize, input):
    bitReader = BitReader(input)
    output = bytearray()
    leftTable, rightTable, typeTable = tables
    
    # The ID of the binary tree's root branch.
    ROOT_BRANCH_ID = 0xFE
    
    currentBranchId = ROOT_BRANCH_ID
    
    while len(output) < uncompressedSize:
        if bitReader.readBit() == 0:
            # Take a left branch.
            nodeValue = leftTable[currentBranchId]
            nodeType = getBit(3, typeTable[currentBranchId])
        else:
            # Take a right branch.
            nodeValue = rightTable[currentBranchId]
            nodeType = getBit(7, typeTable[currentBranchId])
        
        if nodeType == NodeType.LEAF:
            # Write the leaf's value to the output and start over from the root branch.
            output.append(nodeValue)
            currentBranchId = ROOT_BRANCH_ID
        elif nodeType == NodeType.BRANCH:
            # Follow the branch.
            currentBranchId = nodeValue
        else:
            raise Exception("Unknown node type.")
    
    return output

class NodeType:
    LEAF = 0
    BRANCH = 1

class BitReader:
    def __init__(self, stream):
        self.stream = stream
        self.currentByte = 0
        self.bitPosition = 7
    
    def readBit(self):
        if self.bitPosition == 7:
            self.currentByte, = unpack("<B", self.stream)
        
        result = getBit(self.bitPosition, self.currentByte)
        
        self.bitPosition -= 1
        if self.bitPosition == -1:
            self.bitPosition = 7
        
        return result

def getBit(b, n):
    if b < 0: raise Exception("b must be positive.")
    return (n >> b) & 1

def unpack(fmt, file):
    import struct
    return struct.unpack(fmt, buffer(file.read(struct.calcsize(fmt))))

RLE Derivative

Metatile collision maps and some sprite graphics are compressed using an RLE derivative.

Format

Data compressed in this way takes the form of a 2-byte header followed by a byte stream of literal values and sentinel value + run length pairs. When a sentinel value is encountered, a number of zero bytes are written to the output based on the run length. This makes it suitable for compressing data with many continuous zeroes.

Note that a run length of 0x00 is interpreted as 0x100.

Header

  • 0x00: The sentinel value
  • 0x01: The number of compressed blocks that follow. Each uncompressed block is 0x10 bytes.
  • 0x02+: A stream of compressed data

Decompressor

A decompressor, implemented in Python 2.7.9:

"""
Decompresses data compressed using the RLE derivative.

@param input - A stream containing the compressed data.
@return The uncompressed data.
"""
def decompress(input):
    output = bytearray()
    
    # Read the header.
    sentinelValue, blockCount = unpack("<BB", input)
    
    # The size of an uncompressed block, in bytes.
    BLOCK_SIZE = 0x10
    # The size of the uncompressed data, in bytes.
    uncompressedSize = blockCount * BLOCK_SIZE
    
    while len(output) < uncompressedSize:
        value, = unpack("<B", input)
        if value == sentinelValue:
            runLength, = unpack("<B", input)
            if runLength == 0: runLength = 0x100
            
            for i in range(runLength):
                output.append(0)
        else:
            output.append(value)
    
    return output

def unpack(fmt, file):
    import struct
    return struct.unpack(fmt, buffer(file.read(struct.calcsize(fmt))))

Miscellaneous

Information that doesn't fit anywhere else goes here.

SpawnInfo Structure

Describes where and how to spawn a character.

  • 0x00-01: x
  • 0x02-03: y
  • 0x04:
Bits 0-6: Character state ID
Bit 7: Direction