# Kula Level Format **TODO:** Document that in demos, the 9th attribute automatically makes the level hidden. --- Kula World uses a custom binary format for stroring level data. This format does not have its own extension, and is mostly the same across all versions of the game. :::warning Some demos of the game contain slight differences! ::: **Things to Note:** - This format uses [**little endian**](https://en.wikipedia.org/wiki/Endianness). - Most values in this format are read as 2 byte signed integers. ``(int16_t)`` **General Structure** ``` 00000h 13310h Block Data 13310h 2 Block Count 13312h 2 Unused 13314h 2 Property Count ...... ...... Property List ``` ## Position Systems There are 2 main types of positioning used in game, **block coordinates** and **entity coordinates.** Here's an example of the different coordinates: - `11 00 10 00 11 00` - Block Coordinate - `00 22 00 20 9C 20` - Entity Coordinate The block coordinate system is mainly used for positioning block properties and block positioning in general. Objects and entities in game that need to use finer position values use the entity coordinate system, such as the ball and the current moving block position. An entity coordinate value is **double** the amount of a block coordinate value, and the bytes are swapped, with the first byte as fine tune. In the example above, we have a block with an item using the block coordinate and a ball on top of the same block using the entity coordinate, and we can see that the X and Z values are the same, while the Y coordinate is slightly above the block. Here are two different structures that will be used throughout this document to define position values: ```c struct BLOCK_POSITION { uint16_t x; uint16_t z; uint16_t y; } struct ENTITY_POSITION { uint16_t x; uint16_t z; uint16_t y; } ``` ## Block Data Section Every level in the game is essentially a **34x34x34** grid of blocks, with some that contain custom properties. The first block starts at the top, left, forward corner of the level, which is at coordinate **0, 0, 0** (X Y Z) The last block ends at the bottom, right, back corner of the level, which is at coordinate **33, 33, 33**. - X indicates left and right. - Y indicates up and down. - Z indicates forward and backward (depth). The first **0x13310** bytes of the file represent the block data, and indicate which block in the grid is what. Every 2 bytes indicate a single block, with each time incrementing the Y position. This continues until the Y position reaches 33, which is when the Z position is incremented, and Y is set back to 0. Once the Z position reaches 33, the X position is incremented and Y and Z are set back to 0. These blocks are read until the position of the file reaches the end of the **block data section**, which is at offset **0x13310**. Knowing that every block is represented as 2 bytes, and it's position in the level is determined by where it appears in the block data section, let's look into the 2 bytes themselves, which is a signed integer: - `FF FF` indicates an air block, or nothing. Nothing at all is placed there, and it completely ignored. - `00 00` indicates a block with no special properties at all, such as containing items. - `01 00` indicates a fire block, which is just a regular block but with fire patches on all sides with no items or any other properties. - `02 00` indicates an ice block, the same as above. - `03 00` indicates an invisible block, the same as above. - `04 00` indicates an acid block, the same as above. - `05 00` or above (ex. `06 00`, `07 00`, etc.) indicates a block with special properties, such as a laser block, a moving block, or one that contains items / objects. The first block of this type must start at **5**, and is incremented for every next special block. (ex. `05 00`, `06 00`, `07 00`, all the way up until the near 2 byte integer limit of `FD FF`). - `FE FF` is **reserved** and is automatically placed in the game's memory for representing laser block segments, so it is not really that important. ## Property List Section As stated above, there are a lot of different types of special blocks used in the game, and each one needs additional data defined below at the end of the file, right after the block data section (**0x13310**). You can think of every property as a chunk of **256 bytes** of data. Let's look at the first property in HIRO's first level as an example: ``` 013310h 14 00 00 00 06 00 00 00 07 00 00 00 00 00 02 00 013320h FF FF FF FF FF FF 00 00 F4 01 01 00 FF FF FF FF 013330h FF FF 1E 00 FF FF FF FF 00 00 FF FF FF FF 00 00 013340h FF FF FF FF FF FF 00 00 FF FF FF FF FF FF FF FF 013350h FF FF FF FF FF FF FF FF 00 00 FF FF FF FF 00 00 013360h FF FF FF FF FF FF 00 00 FF FF FF FF FF FF FF FF 013370h FF FF FF FF FF FF FF FF 00 00 FF FF FF FF 00 00 013380h FF FF FF FF FF FF 00 00 FF FF FF FF FF FF FF FF 013390h FF FF FF FF FF FF FF FF 00 00 FF FF FF FF 00 00 0133A0h FF FF FF FF FF FF 00 00 FF FF FF FF FF FF FF FF 0133B0h FF FF FF FF FF FF FF FF 00 00 FF FF FF FF 00 00 0133C0h FF FF FF FF FF FF 00 00 FF FF FF FF FF FF FF FF 0133D0h FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 0133E0h FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 0133F0h FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 013400h FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ``` Each property follows this structure below: ```c struct PROPERTY { BLOCK_POSITION previousPropertyPosition; uint16_t blockType; char data[248]; } ``` The first 6 bytes indicate the X, Z, and Y position of the previous property respectively. So, if we look at the next attribute's 6 bytes, in this example: `11 00 0C 00 11 00`, the position of this property is **17, 12, 17** (X Z Y). **However**, since this is the first property in this section, there is **no previous property.** So, for only the first property in the section, it follows a slightly different structure below: ```c struct PROPERTY_FIRST { uint16_t blockCount; uint16_t unused; // Usually null (00 00) uint16_t propertyCount; uint16_t blockType; char data[248]; } ``` So the first 2 bytes indicate the total block count in the level, which in this case is **20**, as there are **20** blocks in the level. However, very strangely, this value does not seem to have an affect on the level at all, and in some cases is set to an absurdly high value like `FD FF` (as seen in **LEVEL 94**. For more information, see the oddities section.) This value might have been used as metadata for their level editor, or was used in a way earlier version of the game. The next to bytes aren't used as well, and is usually `00 00` in 99% of cases, as some levels have this value set **differently**. Thankfully, the next 2 bytes are always accurate and used, and specify the amount of attributes in the level, in this case **6**. This value must be set correctly, and might indicate how much memory to allocate for the property section. Lastly, the next 2 bytes specify the block's type, and must be in the range of 0 and 9, inclusive. Here's a list of all of the different block types: - `00 00` indicates a regular block, that may contain items and other objects. This will be the case most of the time. - `01 00` indicates a fire block, but may also contain items and other objects as well. **This is how blocks with fire and items work**, as the block is set to type of fire, and an item is placed on the desired side(s). - `02 00` indicates the same as above, but as an ice block. - `03 00` indicates the same as above, but as an invisible block. - `04 00` indicates the same as above, but as an acid block. - `05 00` indicates a moving block. - `06 00` indicates a crumble block. - `07 00` indicates a flashing block. - `08 00` indicates a laser block. - `09 00` indicates the level flag property. - `9A 02` indicates the level information property. Depending on the block's type, the property's data will differ between them. Below are different sections that pertain to each block type. --- ### Object Block - 0:4 The following structure below applies to a block that contains **objects** (items / gizmos). **Moving blocks, crumble blocks, flashing blocks, and laser blocks** follow a different structure, and can be seen in their dedicated sections respectively below. Here is the structure of an object block: ```c struct PROPERTY_DATA { char[32] topObjectData; char[32] rightObjectData; char[32] frontObjectData; char[32] backObjectData; char[32] leftObjectData; char[32] bottomObjectData; char[56] padding; // Always FF } ``` Most item data **except for transports and button**, which are slightly different, follow a structure like so: ```c struct { int16_t id; int16_t orientation; int16_t variant; int16_t state; int16_t objectIndex; int16_t targetProperty1; int16_t targetProperty2; int16_t unknown; // Always 0, changes model int16_t animation; //?? int16_t relativeYPosition; int16_t animationType; int16_t animationValue1; // FF, memory only int16_t animationValue2; // FF, memory only int16_t animationValue3; // FF, memory only int16_t animationSpeed; int16_t animationCounter; // FF, memory only int16_t animationState; // FF, memory only } ``` Each object in game has a completely unique **ID**, that indicates what item to put there. In combination, some items can have different **variants** as well. Take a coin for example, which has an ID of `0x25`, you can switch between a bronze coin, blue, and gold coin depending on its variant, instead of each one having its own ID. Some objects have different **states** as well, which is used to signify the current state the object is in, such as a transporter being powered on or off, or an item being uncollected or collected. Only some objects however, have different **orientations**, which is used to specify the direction for the object. For an example, arrows use the orientation value to determine which direction to face in, and the player spawn uses this value to determine which way to look when you're spawned into the level. Some objects have an **objectIndex**, which is incremented starting from 0 in every object. This value is not required to be set in the level file itself, as it's automatically set in memory. In the first two demos, the **relativeYPosition**, **animationType**, and **animationSpeed** fields are required to be set correctly, as they determine how far above an object is above its block, and how it is spun / animated. In the main games, these fields are **ignored**, and therefore are also not required and modifiable. The **spinValue**, **shakeValue**, **floatValue**, **lightCounter**, and **light** fields are not set in the level file itself, and are automatically populated in memory. Lastly, let's talk about the **targetProperty1** and **targetProperty2** fields, which are only used by transporters and buttons. These two fields specify what object(s) to toggle when the transporter / button is powered / unpowered (toggled), and where the transporter will send the player to, respectively. They both act as positions, and follow this principle: ```c uint8_t propertyIndex; uint8_t side; uint16_t position = (propertyIndex * 16) + side; ``` For example, let's look at some location data, `D0 01` and `72 01`. The first location is at index **29**, as the maximum value for the first byte is `F0` (16), and the second byte is incremented due to 29 > 16, which leaves 13, and translates to `D0` in hex. Since only the first digit in the byte represents the index, it would be `D0 01`. Additionally, the second digit in the first byte is 0, which targets the top side of the block. Using this knowledge, the index of the second location is **23**, which is `70 01`. Since the side we want to target in the second location is 2, the second digit is the first byte is set as such, leaving us with `72 01` as a result. So both of these locations target the 29th attribute block in the level, on the top side and the **23rd attribute block** on the **right** side, respectively. With the positions aside, it's worth nothing that in the first demo, but button powers itself when pressed, but in all later versions of the game it **does not**. The button also only uses **targetProperty1** in the demo, so it only has one slot. In all of the other versions of the games, the button has **2 slots**, and does not power itself when pressed. This means that the button needs power itself, so often times, one of the slots are used to power itself. However, it's worth noting that **only the targetProperty2 can power the button itself!** --- ### Moving Block - 5 ```c struct MOVING_BLOCK { uint16_t direction; uint16_t orientation; uint16_t unknown; // Usually 1 BLOCK_POSITION fromPosition; BLOCK_POSITION toPosition; char padding[12]; uint16_t unknown; // Changes between 00 and FF uint16_t length; uint16_t speed; char padding[2]; uint16_t blockID; char padding[196]; ENTITY_POSITION currentPosition; char unknown[6]; // Always 00 01 00 01 00 01 } ``` A single block is placed in the starting position, which is known as the **origin**. Based on the length, that many blocks including the origin will be placed in the direction depending on the direction type: - `00`, `05` - Positive Y - `01`, `04` - Positive X - `02`, `03` - Positive Z The direction specifies what direction the moving block needs to travel in order to reach its **toPosition**: - `00 00` indicates up. - `01 00` indicates right. - `02 00` indicates forward. - `03 00` indicates back. - `04 00` indicates left. - `05 00` indicates down. - Any other value causes the moving block to not move at all. For example, if the block length is **1**, no other blocks will be placed as the origin is counted as **1**. If the length is **3** however and the direction is set to **1**, **2 blocks** will be placed in the **Positive X** direction. The moving block starts off at the starting position (which is the **currentPosition**), moves to the **toPosition**, and then moves between the **fromPosition** and **toPosition**. The maximum length a moving block can be is **4**, as the texture data the block stores in memory inside its property overwrites other information about the moving block, as well as the next property. The **orientation** of the moving block indicates its orientation, meaning the texture is wrapped onto the moving block. If this value is not set correctly, the block's collision will not work properly and will often crash the game. - `00 00` indicates up and down. - `01 00` indicates left and right. - `02 00` indicates forward and backward. - Any other value defaults to up and down. The **speed** indicates how many times the current position is incremented / decremented per frame. So if the speed is set to 10, the block will move 10 in the current direction per frame. The **from and to positions** dictate the two spots the moving block will move between in game. The **currentPosition** dictates what position the moving block will start in, and is updated every frame in game. Lastly, the **blockID** is set to the block ID that represents this property in the block data section. --- ### Crumbling Block - 6 ```c struct CRUMBLE_BLOCK { uint16_t state; ENTITY_POSITION position; char padding[240]; // FF } ``` As we can see, the crumble block follows one of the easiest structurs in the entire game. The first 2 bytes indicate the crumble block's state, which should always be set to `01 00` in the game's file. - `00 00` indicates the crumble block is gone. - `01 00` indicates the crumble block is active. - `02 00` indicates the crumble block is crumbling, but is not used. - `03 00` indicates the crumble block is crumbling. - Any other value causes the crumble block to still be active, but will not make a sound when touched. Strangely enough, in no versions of the game are the **X, Y, and Z** positions of the crumble block used. They are set in the file, but when changed, don't seem to have an affect on the game. The crumble block uses entity positioning, and are set as the exact block coordinate of the crumble block. The 240 bytes of padding are usually `FF`, but strangely enough, some crumble blocks have object block data or other weird structures. Although they have no effect, it's still interesting to see that maybe some crumble blocks were inteded to also have items as well. --- ### Flashing Block - 7 ```c struct FLASHING_BLOCK { uint16_t index; // Memory only, always FF uint16_t timing; uint16_t state; // Memory only, always FF uint16_t counter; // Memory only, always FF char padding[240]; // FF } ``` Similar to the moving spikes, the flashing block also contains a **timing** value, which specifies in what order of timing the flashing block will appear. Occasionally, just like the crumble block, the **240** bytes of padding may contain weird structures, but have no affect at all. --- ### Laser Block - 8 ```c struct LASER_BLOCK { uint16_t unknown; uint16_t direction; uint16_t enabled; BLOCK_POSITION fromPosition; BLOCK_POSITION toPosition; char[14] padding; uint16_t unknown; // Usually 1 char[4] padding; int16_t blockID; char[2] padding; uint16_t color; uint16_t toggleObject1; }; ``` The direction specifies what direction the laser block needs to look in to reach its **toPosition**: - `00 00` indicates up. - `01 00` indicates right. - `02 00` indicates forward. - `03 00` indicates back. - `04 00` indicates left. - `05 00` indicates down. Changing the **color** property to values other than the 4 color values can actually change the laser texture itself, however upon the laser turning on, that game will crash. --- ### Level Flag Property - 9 The flag property is optional, always behind the level information property (if set), and is used for setting flags for the level and does not tie to any block at all: ```c struct FLAG_PROPERTY { uint16_t hidden; uint16_t reverseInvisible; char[244] padding; } ``` As you can see, this property is very simple and only has two flags, which are set to true are false depending if they're to set to 1 and 0 respectively. This first flag specifies if the current level is a **hidden level**, and the second flag specifies if the current level uses **reverse-invisible blocks**. Similar to the crumble and flashing blocks, this property usually contains **a lot** of weird structures in its padding, and sometimes this property is added to a level that doesn't even use its flags. ``` 014010h 11 00 11 00 11 00 09 00 00 00 00 00 00 00 00 00 014020h 00 00 00 00 FF FF 00 00 FF FF FF FF FF FF FF FF 014030h FF FF FF FF FF FF FF FF 00 00 FF FF FF FF 00 00 014040h FF FF FF FF FF FF 00 00 FF FF FF FF FF FF FF FF 014050h FF FF FF FF FF FF FF FF 00 00 FF FF FF FF 00 00 014060h FF FF FF FF FF FF 00 00 FF FF FF FF FF FF FF FF 014070h FF FF FF FF FF FF FF FF 00 00 FF FF FF FF 00 00 014080h FF FF FF FF FF FF 00 00 FF FF FF FF FF FF FF FF 014090h FF FF FF FF FF FF FF FF 00 00 FF FF FF FF 00 00 0140A0h FF FF FF FF FF FF 00 00 FF FF FF FF FF FF FF FF 0140B0h FF FF FF FF FF FF FF FF 0A 00 00 00 00 00 01 00 0140C0h FF FF FF FF FF FF 00 00 00 01 03 00 FF FF FF FF 0140D0h FF FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF 0140E0h FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 0140F0h FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 014100h FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 014110h 11 00 13 00 11 00 9A 02 0D 00 11 00 11 00 FB FF ``` Take this property from **LEVEL 31** as an example. We can see that it's definitely a flag property, but doesn't have any of its flags set. Even stranger however, we can see that it contains data for a bounce pad on the underside of the block, and even has a block position set for it in the next property. It is unknown why this occurs, but it does not have an affect on the level at all. --- ### Level Information Property - 666 At the end of most levels, there is an extra property that contains basic information about the level itself. Although, most of these values are unknown, they do not seem to have an affect on the level at all. This property has a block type of **666**, but is not tied to any block. :::warning As previously stated, some levels do not contain this property, notably the first Kula Quest demo. This property is not required, and the game will default to values if this property does not exist. ::: ```c struct LEVEL_PROPERTY { char[10] unknown; uint16_t startingTime; char[236] padding; // FF } ``` The only known value in this property is **startingTime**, which specifies the amount of time the level starts with in seconds. The game calculates the amount of time by multiplying this value by **50**, which is the PAL's game framerate. For reference, the game decrements currentTime every frame of gameplay, and ends the level if it is equal to 0, meaning you ran out of time. In Kula World and Roll Away, the time is calculated by multiplying this value by **50**, which is the PAL's game framerate: ```c // SLUS_007.24: 0x35F5C // currentTime: 0xA573C // Check if the block's type is 666, meaning the level info property exists // If so, set currentTime to the property's 6th index (startingTime) * 50; if (*propertyData == 0x29a) { currentTime = propertyData[6] * 0x32; } // If the level info property doesn't exist, default to 4950 else { currentTime = 0x1356; } ``` *Note: Kula World and Roll Away function the same here, so Roll Away is used as an example.* <br> In Kula Quest, the time is calculated by multiplying this value by **60**, which is the NTSC's game framerate, and then checking if the value is **5940**, which is the maximum time value (99), and setting it to **7140** if so: ```c // SCPS_100.64: 0x362C4 // currentTime: 0xA12EC // Check if the block's type is 666, meaning the level info property exists // If so, set currentTime to the property's 6th index (startingTime) * 60; if (*propertyData == 0x29a) { currentTime = propertyData[6] * 0x3c; } // If the level info property doesn't exist, default to 7140 else { currentTime = 0x1be4; } // If the currentTime was set to 5940, default to 7140 if (currentTime == 0x1734) { currentTime = 0x1be4; } ``` ---