# SLP files

SLP files are stored in the DRS files. They contain all the (animation)
textures. Like the DRS format, it can also be read sequentially.

## SLP file format

#### Header
The SLP file starts with a header:

Length   | Type   | Description      | Example
---------|--------|------------------|--------
4 bytes  | string | Version          | 2.0N
4 bytes  | int32  | Number of frames | 1, 0x00000001
24 bytes | string | Comment          | ArtDesk 1.00 SLP Writer


```cpp
struct slp_header {
  char  version[4];
  int32 num_frames;
  char  comment[24];
};
```
Python format: `Struct("< 4s i 24s")`

#### SLP Frame info
After the header, there are `num_frames` entries of `slp_frame_info`:
Every `slp_frame_info` stores meta-information about a single frame (texture)
within the SLP.

Length   | Type   | Description                | Example
---------|--------|----------------------------|--------
4 bytes  | uint32 | Command table offset       | 2464, 0x000009A0
4 bytes  | uint32 | Outline table offset       | 64, 0x00000040
4 bytes  | uint32 | Palette offset (unused)    | 0, 0x00000000
4 bytes  | uint32 | Properties (likely unused) | 16, 0x00000010
4 bytes  | int32  | Width of image             | 800, 0x00000320
4 bytes  | int32  | Height of image            | 600, 0x00000258
4 bytes  | int32  | Centre of sprite (X coord) | 0, 0x00000000
4 bytes  | int32  | Centre of sprite (Y coord) | 0, 0x00000000

```cpp
struct slp_frame_info {
  uint32 cmd_table_offset;
  uint32 outline_table_offset;
  uint32 palette_offset;
  uint32 properties;
  int32  width;
  int32  height;
  int32  hotspot_x;
  int32  hotspot_y;
};
```
Python format: `Struct("< I I I I i i i i")`

* `palette_offset` is apparently never used.
* `properties` is only used to indicate which palette for the image to use.
  However, these seem to be the same, so can generally be ignored.
    * 0x10 - "default game palette"
    * 0x00 - "global color palette"
* `hotspot_x` & `hotspot_y` tell the engine where the centre of the unit is.

One image of size `width`*`height` has `height` rows, of course.

#### SLP Frame row edge
At `outline_table_offset` (after the `slp_frame_info` structs), an array of
  `slp_frame_row_edge` (of length `height`) structs begins.

Length   | Type   | Description   | Example
---------|--------|---------------|--------
2 bytes  | uint16 | Left spacing  | 20, 0x0014
2 bytes  | uint16 | Right spacing | 3, 0x0003

```cpp
struct slp_frame_row_edge {
  uint16 left_space;
  uint16 right_space;
};
```
Python format: `Struct("< H H")`

For every row, `left_space` and `right_space` specify the number of transparent
pixels, from each side to the center. For example, in a 50 pixels wide row, with
a `slp_frame_row_edge` of `{ .left_space = 20, .right_space = 3 }`, the leftmost
20 pixels will be transparent, the rightmost 3 will be transparent and there
will be 27 pixels of graphical data provided through some number of commands.

If the right or left value is `0x8000`, the row is completely transparent.
Note that there are no command bytes for these rows, so will have to be skipped
"manually".

`width - left_space - right_space` = number of pixels in this line.

After those padding frames, at `slp_frame_info.cmd_table_offset`, an array of
uint32 (of length `height`) begins:

```cpp
struct slp_command_offset {
  uint32 offset;
}
```
Python format: `Struct("< I")`

Each `offset` defines the offset (beginning) of the first command of a row.
The first `offset` in this array is the first drawing command for the image.

These are not actually necessary to use (but obviously are necessary to read),
since the commands can be read sequentially, although they can be used for
validation purposes.

The actual command data starts after the end of the command offsets, or:
`slp_frame_info.cmd_table_offset + 4 * slp_frame_info.height`.


### SLP drawing commands

The image is drawn line by line, a line is finished with the "End of line"
command (0x0F), where a command is a one-byte number (stored in the
least-significant bits of the byte, e.g. `command = data & 0x0F`), followed by
command-specific data with a length varying depending on the command. The next
command immediately follows the previous command's data.

Each command triggers a drawing method for n = "Count" pixels.

All the commands tell you to draw a palette_index, for n pixels.

The *Pixel count* value is stored at these locations: (where `cmd_byte` is the
value of the command byte, and `next_byte` is the value of the next byte)

Value name     | Pixel count
---------------|------------
next           | `next_byte`
`>> 2`         | `cmd_byte >> 2` (i.e., most significant bits used as data value)
`>> n` or next | `pixel_count = cmd_byte >> n; if pixel_count == 0: pixel_count = next_byte`. i.e., the `8 - n` most significant bits of `cmd_byte` if they are `!= 0`, else the next byte.
`<< 4 + next`  | `((cmd_byte & 0xf0) << 4) + next_byte`

Commands where *Count* is `>> i` only reuse the most significant bits of `cmd_byte`.

Command Name             | Byte value | Count          | Description
-------------------------|------------|----------------|------------
Lesser block copy        | `0x00`     | `>> 2`         | An array of length *Count* filled with 1-byte palette indices follows, 1 index per pixel.
Lesser skip              | `0x01`     | `>> 2` or next | *Count* transparent pixels should be drawn from the current position.
Greater block copy       | `0x02`     | `<< 4 + next`  | An array of length *Count* filled with 1-byte palette indices follows, 1 index per pixel.
Greater skip             | `0x03`     | `<< 4 + next`  | *Count* transparent pixels should be drawn from the current position.
Player color block copy | `0x06`     | `>> 4` or next | An array of length "Count" filled with 1-byte player color palette indices follow, 1 index per pixel. The real palette index is `player_color_palette_index + player * 16`, where `player` is the player ID you're drawing for (1-8).
Fill                     | `0x07`     | `>> 4` or next | One palette index byte follows. This color should be drawn `pixel_count` times from the current position.
Fill player color       | `0x0A`     | `>> 4` or next | One player palette index byte follows. This color should be drawn `pixel_count` times. See `player_color_list (0x06)`
Shadow                   | `0x0B`     | `>> 4` or next | Draw *Count* shadow pixels (The pixels to draw when a unit is behind another object).
Extended command         | `0x0E`     | depends        | Get the specific extended command by looking at the most significant bits of the command. (See the table below for details)
End of line              | `0x0F`     | 0              | End of commands for this row. If more commands follow, they are for the next row.

Extended commands, for outlines behind trees/buildings:

Command name        | Byte value | Count | Description
--------------------|------------|-------|------------
render_hint_xflip   | `0x0E`     | 0     | Draw the following command if sprite is not flipped right to left.
render_h_notxflip   | `0x1E`     | 0     | Draw following command if this sprite is x-flipped.
table_use_normal    | `0x2E`     | 0     | Set color transform table to normal.
table_use_alternate | `0x3E`     | 0     | Set color transform table to alternate.
outline_1           | `0x4E`     | 1     | `palette_index = player_index = player * 16`, if obstructed, draw player color, else transparent. This is the player color outline you see when a unit is behind a building. (special color = 1)
outline_span_1      | `0x5E`     | next  | `palette_index = player_index = player * 16`, can be >=1 pixel
outline_2           | `0x6E`     | 1     | `palette_index = 0`, if pixel obstructed, draw a pixel as black outline, else transparent. (special color = 2)
outline_span_2      | `0x7E`     | next  | `palette_index = 0`, same as obstruct_black, >=1 pixel.
dither              | `0x8E`     | ?     | ?
premulti_alpha      | `0x9E`     | ?     | Premultiplied alpha?
orig_alph           | `0xA0`     | ?     | Original alpha?


* "Lesser block copy" (0x00) also takes the values `0x04, 0x08 & 0x0C`
* "Lesser skip" (0x01) also takes the values `0x05, 0x09, 0x0D`.
* "Player color block copy" (0x06) is an index into the palette, in range 0-15.
* "Shadow" (0x0B) destination "pixels" are used as a lookup into a shadow_table.
  This lookup pixel is then used to draw into the buffer. The shadow table is a
  color-tinted variation of the real color table. It's also used to draw things
  like the red-tinted checkerboard when placing buildings at forbidden places.
* "special color" - 2 means black (enhance the outline, cartoonlike), 1 is
  player color.
* When a unit is behind an object (Commands `0x{4,5,6,7}E` used), only the
  outline of the corresponding part of the unit is drawn, the rest of the unit
  is transparent. So, the left outline is one pixel more to the left than the
  first color.

  Usually, these outline pixels should be stored to a second image, which is
  rendered on top of the tree/building by the fragment shader.

For later drawing, a graphics file needs flags for:

* object has outline
* can show objects behind by outline
* both of them

Now the palette indices for all the colors of the unit are known, but a palette
is needed for them to be drawn.

## Palette Files

The drawing palette is stored inside `interfac.drs`. It's basically an array of
`(r, g, b)` tuples.

The file id is `50500+x`, the palettes (color tables) are stored the same way
as .SLPs are. (see [.DRS Files](drs-files.md)) Here `x` is the palette index,
which should be 0, experiment with `[1,10]`...

`interfac.drs` contains many of these files, but the ingame art uses id 50500.

The palette is a (text-based) JASC Paint Shop Pro file, starting with
`JASC-PAL\r\n`. Read this line at the very start of a .BIN file to see if it's a
palette file. The second line stores version information, should be `0100`. The
third line stores the number of entries, as text.

The rest is that many `r g b\r\n` lines. Again, `r`, `g` and `b` are stored as
text (range `0-255`).

They are referenced in the SLP files, so should be indexed. It's simply an
array, so line 3=>index 0, line 4=>index 1 etc.


## SLP types

### SLP files for moving objects

Unit .SLP files contain 5 states:

1. Attacking
2. Standing Ground
3. Dying
4. Rotting
5. Moving

On average, each state has roughly 50 animation frames -> ~250 textures per unit

For each animation, 5 directions of it are stored, the other 3 directions are
generated later by flipping the sprite on the y axis.

Villagers have way more than the 5 animations (for the different resources),
boats have 2 (boat & sail).


### SLP files for static objects

Contain the image of the building. Some static objects have multiple chunks,
like the Town Center, where units can be under one arm and 'in front of' the
main building.


### SLP files for weapons

Dust, arrows, etc.


### SLP files for shadows

Every object in game has a shadow. Moving units have frames for their shadow in
the same SLP file, but buildings and other objects have their shadows in
separate SLPs.

Large numbers of shadow SLPs are difficult to identify, due to the image only
being in a single color.
