# The Longest Journey XMG

## XMG

### General conventions and basic definitions

First, let the following be a convention throughout this document:

uint8 {1} - Red
uint8 {1} - Green
uint8 {1} - Blue

shall be called the RGB type.

The XMG format is based on the YCbCr colour scheme, which makes a conversion to RGB necessary, should one decide to save the image as a standard bitmap. Therefore, conversion tables have to be set up according to the following matrix/vector multiplication scheme (a rounded variant of the standard set in CCIR 601 without signal head- or footroom; quite similar to image data encoded according to the JFIF 1.02 standard ):

```| R |   |  1.000000  0.000000  1.402000 |   | Y        |
| G | = |  1.000000 -0.344136 -0.714136 | * | Cb - 128 |
| B |   |  1.000000  1.772000  0.000000 |   | Cr - 128 |
```

Or put differently:

```R = Y + 1.402 * (Cr - 128)
G = Y - 0.344136 * (Cb - 128) - 0.714136 * (Cr - 128)
B = Y + 1.772 * (Cb - 128)
```

• all result values have to be clamped to byte values, i.e. integers in the range of 0..255 and
• depending on how this conversion is implemented, small differences (due to rounding) in comparison to the pictures generated by the game engine are possible. However, if done right, these differences are usually unnoticable by the human eye.

Thus, in the course of this document it is assumed that the following tables have been set up:

YCbB[i]  --  given the Cb value i, output its contribution to B
YCrR[i]  --  given the Cr value i, output its contribution to R
YCbG[i]  --  given the Cb value i, output its contribution to G
YCrG[i]  --  given the Cr value i, output its contribution to G

Now, the conversion from YCbCr to RGB can be done simply by:

```R = Y + YCrR[Cr]
G = Y + YCbG[Cb] + YCrG[Cr]
B = Y + YCbB[Cb]
```

### Format Specifications

An XMG file starts with a general header:

uint32 {4} - Unknown (probably version number, usually 3)
RGB {3}    - Transparency colour
uint8 {1}  - Unknown
uint32 {4} - Image width
uint32 {4} - Image height
uint32 {4} - Scanline length
uint32 {4} - Unknown
uint32 {4} - Unknown

The scanline length value determines the memory consumption of one image line when expressed in RGB values.

After this header, the image data follows. It describes the image line-wise (from the top left to the bottom right) in terms of tiles (2x2 pixels in size) and can contain different types of colour entries: RGB, YCbCr or transparency. To cope with this differentiation, the basic data structure builds on reading byte opcodes. Such an opcode is interpreted as a bitfield of the format xxyyzzzz, where xx denotes the color mode (00 for YCbCr, 01 for transparency, 10 for RGB) and yyzzzz denotes the number of tiles to be processed. In case xx equals 11, yy is the color mode and a second opcode aaaaaaaa has to be read. The number of tiles is then zzzzaaaaaaaa.

Colour entries of the defined type are read until the requested number of tiles has been filled. Then, the next opcode can be read.

#### YCbCr colour mode

In this mode, colour entries of the type

uint8 {1} - Y0
uint8 {1} - Y1
uint8 {1} - Y2
uint8 {1} - Y3
uint8 {1} - Cr
uint8 {1} - Cb

have to be read. The Cr- and Cb-values are valid for the complete tile, while the Yx-values have to be applied to the four pixels of the tile in the following manner:

```+----+----+
| Y0 | Y1 |
+----+----+
| Y2 | Y3 |
+----+----+
```

The conversion to RGB can be done as specified above.

#### Transparency colour mode

Here, the requested number of tiles is simply flood-filled with the transperency colour specified in the XMG header.

#### RGB colour mode

In this mode, four structures of the type RGB have to be read per requested tile. The colours are applied to the tile just like the Yx values in the YCbCr mode are distributed.

Not written yet

Unknown