# File formats

## LBD

LBD files in LSD: Dream Emulator are used to store chunks of levels.&#x20;

Sometimes if a level has a large number of LBD files, they will be split into a number of subdirectories called 'N1', 'N2', and so on. I think this is something to do with efficient sector layout on the physical game disc.

Level chunks in LSD are tile-based, and each LBD contains data for a 20x20 tile chunk of the level. Each LBD file has its own tileset, in the form of a TMD file (3D model) with objects for each tile in the chunk's tileset. Notably, different LBD files within the same level do not share a tileset - the tileset is embedded separately into each file. This leads to a lot of repeats and isn't very storage-efficient, but was probably a lot more optimized for disc reads.

Tiles in the chunk are arranged in a regular grid, and each tile can have an 'extra tile' which is simply added in the same position as itself. Note that even extra tiles can have other extra tiles, so you could have long chains of different tiles all in the same place.

Chunks in a level are arranged in a more complicated fashion than tiles in a chunk. There are two ways level chunks can be arranged: *vertically*, and *horizontally*. The horizontal arrangement is used in most levels, with the vertical arrangement being used in only two: Bright Moon Cottage, and Moonlight Tower.

Horizontally arranged levels are tiled in a 'brick wall' pattern, like so:

```
+---+---+---+
| 5 | 6 | 7 |
+-+-+-+-+-+-+
  | 3 | 4 |
+-+-+-+-+-+-+
| 0 | 1 | 2 |
+---+---+---+
```

Where '0' is M000.LBD, '1' is M001.LBD, and so on. The dimension of the levels varies, the diagram above is the arrangement for a level with a dimension of 3. The dimension of each level is listed below:

| Level | Name                | Dimension |
| ----- | ------------------- | --------- |
| STG00 | Bright Moon Cottage | Vertical  |
| STG01 | Pit & Temple        | 3         |
| STG02 | Kyoto               | 6         |
| STG03 | The Natural World   | 16        |
| STG04 | Happytown           | 6         |
| STG05 | Violence District   | 5         |
| STG06 | Moonlight Tower     | Vertical  |
| STG07 | Temple Dojo         | 5         |
| STG08 | Flesh Tunnels       | 1         |
| STG09 | Clockwork Machines  | 1         |
| STG10 | Long Hallway        | 3         |
| STG11 | Sun Faces Heave     | 4         |
| STG12 | Black Space         | 4         |
| STG13 | Monument Park       | 2         |

Vertically tiled levels technically apply no tiling at all—LBD chunks are all placed in the same location. The vertical nature of these levels is actually applied in the tile data, with increasing `TileHeight` values causing the LBD files to span multiple storeys.

There is nothing in the LBD file to distinguish between vertical and horizontal levels, and also nothing in the file that describes the dimension of the level. There's no data in any other game files that could represent this information, therefore this data must be baked into the game executable somewhere.

LBD files also can contain a number of entities. These entities are the 'interactive objects' of LSD. Entities are stored in an MML file, which is a container for multiple MOM files. A MOM file is an entity.

Entities are just a TMD 3D object file with a collection of TOD animation files.

If an LBD file does not contain any entities this will be stated in the header, and the data will simply not be in the file.

### Format

#### `LBDFile`

| Type            | Name       | Description                                                                                                                                                                                 |
| --------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LBDHeader`     | Header     | The header of the file.                                                                                                                                                                     |
| `LBDTile`array  | TileLayout | <p>Length is equal to <code>Header.TileWidth \* Header.TileHeight</code>.</p><p>This is the grid of tiles in this chunk, starting at the bottom left and continuing rightwards along X.</p> |
| `LBDTile` array | ExtraTiles | <p>Length is equal to <code>Header.NumberOfExtraTiles</code>.</p><p>This is the array of extra tile data that tiles index into when they have extra tiles.</p>                              |
| `TMDFile`       | Tiles      | TMD file containing an object for each tile in this chunk's tileset.                                                                                                                        |
| `MMLFile`       | MML        | MML file containing the entities in this level.                                                                                                                                             |

#### `LBDHeader`

| Type       | Name               | Description                                                                                                                                                                                 |
| ---------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `uint16_t` | Version            | This is always `0x1`.                                                                                                                                                                       |
| `uint16_t` | HasMML             | `0x1` if this LBD has an MML file, `0x0` otherwise.                                                                                                                                         |
| `uint32_t` | AddressOffset      | Always `0x18`, this gets added to some other memory offsets.                                                                                                                                |
| `uint32_t` | TilesTMDOffset     | The offset in bytes to the TMD file containing the tiles. This needs to be added to `AddressOffset`.                                                                                        |
| `uint32_t` | TilesTMDLength     | The length of the TMD file containing the tiles in bytes.                                                                                                                                   |
| `uint32_t` | MMLOffset          | The offset in bytes to the MML file containing the entities. This **does not** need to be added to `AddressOffset`. If this LBD does not contain an MML then this will point out of bounds. |
| `uint32_t` | MMLLength          | The length of the MML file in bytes.                                                                                                                                                        |
| `uint16_t` | UnknownValue       | This is `0x4C` in every LBD file. Its purpose is currently unknown.                                                                                                                         |
| `uint16_t` | NumberOfExtraTiles | The length of the array of extra tile data in the LBD file.                                                                                                                                 |
| `uint16_t` | TileWidth          | The width of the LBD file in tiles. It's `0x14` (20) for every LBD.                                                                                                                         |
| `uint16_t` | TileHeight         | The height of the LBD file in tiles. It's `0x14` for every LBD.                                                                                                                             |

#### `LBDTile`

| Type       | Name                      | Description                                                                                                                                 |
| ---------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `uint8_t`  | DrawTile                  | `0x1` if tile is visible, `0x0` otherwise.                                                                                                  |
| `uint8_t`  | UnknownFlag               | `0x0` or `0x1`, but usage is unknown.                                                                                                       |
| `uint16_t` | TileType                  | Essentially the tile ID. It's an index into the objects array of the Tiles TMD. That object will be the tile drawn at this tile's position. |
| `uint8_t`  | FootstepSoundAndCollision | Somehow encodes the footstep sound and collision of this tile. The encoding is currently unknown.                                           |
| `uint8_t`  | TileDirection             | Encodes tile rotation in 90 degree increments. `0x0` is no rotation, `0x1` is 90 degrees, `0x2` is 180 degrees, and `0x3` is 270 degrees.   |
| `int16_t`  | TileHeight                | The height offset in units to apply to this tile.                                                                                           |
| `uint16_t` | ExtraTileOffset           | The offset in the file to the extra tile to draw on this tile. This needs to be added to `AddressOffset` from the `LBDHeader`.              |
| `uint16_t` | AlwaysZero                | This is `0x0` in every LBD file. Its use is currently unknown.                                                                              |

## MML

An MML file is used to store a collection of MOM files. MOM files are the entities and interactive objects that appear in the game. MML files are only found within LBD files, there are none loose in the game files.

### Format

#### `MMLFile`

| Type             | Name         | Description                                                                                                        |
| ---------------- | ------------ | ------------------------------------------------------------------------------------------------------------------ |
| `uint32_t`       | ID           | Magic number and namesake. Always `0x4D4D4C20`, or `"MML "`.                                                       |
| `uint32_t`       | NumberOfMOMs | The number of MOMs in this MML file.                                                                               |
| `uint32_t` array | MOMOffsets   | Length is equal to `NumberOfMOMs`. This is an array of byte offsets to each MOM file from the top of the MML file. |
| `MOMFile`        | MOMs         | Length is equal to `NumberOfMOMs`. This is an array of the MOM files in the file.                                  |

## MOM

A MOM file stores a single entity/interactive object that can appear in the game. For instance, the grey man and unused dog entity are both MOM files. Most of the MOM files in the game are stored in MML files in the LBD files—the two exceptions being listed above.

In practical terms, a MOM file contains a TMD file with a number of objects, and an MOS file—a container for TOD animation files. TOD animations store a number of frames, each containing transformations to apply to objects in a TMD file. Hence, when combined in a MOM file they can represent a 3D object with a number of different animations.

### Format

#### `MOMFile`

| Type       | Name      | Description                                                                |
| ---------- | --------- | -------------------------------------------------------------------------- |
| `uint32_t` | ID        | Magic number and namesake. Always `0x4D4F4D20`, or `"MOM "`.               |
| `uint32_t` | MOMLength | The length of this MOM file in bytes.                                      |
| `uint32_t` | TMDOffset | The offset in bytes to this MOM's TMD file, from the top of this MOM file. |
| `MOSFile`  | MOS       | Container for TOD animation data.                                          |
| `TMDFile`  | TMD       | 3D model object data.                                                      |

## MOS

A MOS file is a container for multiple TOD animation files. MOS files are only found in MOM files, there are none loose in the game files.

### Format

#### `MOSFile`

| Type             | Name         | Description                                                                                              |
| ---------------- | ------------ | -------------------------------------------------------------------------------------------------------- |
| `uint32_t`       | ID           | Magic number and namesake. Always `0x4D4F5320`, or `"MOS "`.                                             |
| `uint32_t`       | NumberOfTODs | The number of TOD animation files in this MOS.                                                           |
| `uint32_t` array | TODOffsets   | Length is equal to `NumberOfTODs`. Contains byte offsets to each TOD file from the top of this MOS file. |
| `TODFile` array  | TODs         | Length is equal to `NumberOfTODs`. This is the animation data.                                           |

## TIX

A TIX file stores texture atlases for each texture set of each level. These texture atlases are stored as a collection of TIM files that get loaded directly into VRAM when a level loads.

You'll see them in level directories (STG00–13) as `TEXA.TIX` through `TEXD.TIX`.

### Format

#### `TIXFile`

| Type             | Name   | Description                                                                             |
| ---------------- | ------ | --------------------------------------------------------------------------------------- |
| `TIXHeader`      | Header | The file header.                                                                        |
| `TIXChunk` array | Chunks | Length is equal to `TIXHeader.NumberOfChunks`. Each chunk can store multiple TIM files. |

#### `TIXHeader`

The TIX header is 2048 bytes long. Remaining space after the fields listed here is empty (zero).

| Type             | Name           | Description                                                                                                                                     |
| ---------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `uint32_t`       | NumberOfChunks | The number of chunks in this TIX file.                                                                                                          |
| `uint32_t` array | ChunkOffsets   | Length is equal to `NumberOfChunks`. Each element in this array is an offset in bytes to a `TIXChunk` from the start of the TIX file.           |
| `uint32_t` array | ChunkLengths   | Length is equal to `NumberOfChunks`. Each element in this array is the length of the `TIXChunk` at the corresponding index into `ChunkOffsets`. |

#### `TIXChunk`

A `TIXChunk` stores multiple TIM files to be loaded into VRAM.

Due to the length of the `TIXHeader`, the first chunk is always at offset 0x800. Chunks are aligned on some form of boundary. There is seemingly no pattern for the length of a `TIXChunk`, and chunks that do not fill their allocated space leave the rest empty. For these reasons, when reading the file it would probably be best to seek to the TIM offset, read the TIM, then seek directly to the next offset and continue in this fashion until the given number of TIMs is reached—finally seeking directly to the next chunk without dealing with any empty data on the end.

| Type             | Name         | Description                                                                                                          |
| ---------------- | ------------ | -------------------------------------------------------------------------------------------------------------------- |
| `uint32_t`       | NumberOfTIMs | The number of TIMs in this chunk.                                                                                    |
| `uint32_t` array | TIMOffsets   | Length is equal to `NumberOfTIMs`. Each element is an offset in bytes from the top of this `TIXChunk` to a TIM file. |
| `TIMFile`        | TIMs         | Length is equal to `NumberOfTIMs`. Each element is a TIM file.                                                       |
