Adding modding folder with a hacked build.
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
## Bitmaps
|
||||
|
||||
Bitmaps are images using a palette of colours. System Shock uses bitmaps exclusively for its graphics and uses one byte
|
||||
as index per pixel - thus 256 colours possible. The resources store such bitmaps with content type ```0x02``` and they are always compound, even if only one bitmap is stored.
|
||||
|
||||
Bitmaps are stored with a header, the pixel data (sometimes compressed), and an optional private palette.
|
||||
|
||||
### Header
|
||||
|
||||
**Bitmap Header** (`FrameDesc` struct) (28 bytes)
|
||||
|
||||
0000 [4]byte Unused. Always zero. (used as pointer in the engine)
|
||||
0004 byte Type -- 0x02: Uncompressed; 0x04 Compressed
|
||||
0005 byte Align -- Unused
|
||||
0006 uint16 Flags
|
||||
0008 sint16 Width
|
||||
000A sint16 Height
|
||||
000C uint16 Stride
|
||||
000E byte WidthFactor
|
||||
000F byte HeightFactor
|
||||
0010 [4]int16 HotspotBox: Left, Top, Right, Bottom
|
||||
0018 sint32 Private palette offset
|
||||
|
||||
The ```Flags``` is set to value ```0x0001``` then palette index ```0x00``` should be treated as a transparent pixel instead of painting it black.
|
||||
> Compressed images appear to default to transparency if the resolution of the game is 320x200. Higher resolutions require the flag set to behave identical.
|
||||
>
|
||||
> Other factors may also govern whether the bitmap should be treated with transparency - videos and level textures have their special handling in this regard.
|
||||
|
||||
The ```WidthFactor``` and ```HeightFactor``` specify the index of the highest set bit of ```Width``` and ```Height```
|
||||
respectively. For example, if Width is 320 (0x140), then the WidthFactor is 8 (1<<8 == 0x100).
|
||||
|
||||
`HotspotBox` is a placeholder for different applications. It can define a rectangle, or it only defines a point (using the first two values) for anchoring.
|
||||
|
||||
> For the existing images in the original resource files, all images have a ```Stride``` equal to ```Width```.
|
||||
|
||||
### Pixel Data
|
||||
|
||||
After the header, the pixel data is serialized. If the image is uncompressed (Type ```0x02```),
|
||||
```Height``` x ```Stride``` bytes make up the image. Compressed images (Type ```0x04```) use a simple run-length-encoding (RLE).
|
||||
|
||||
#### Pixel Compression
|
||||
|
||||
The compressed byte-stream contains the following byte sequences:
|
||||
|
||||
00 nn zz write nn bytes of value zz
|
||||
nn .. 0 < nn < 0x80: copy the following nn bytes
|
||||
80 lo hi lo hi are a little-endian uint16 nnnn, to be handled as follows:
|
||||
80 00 00 End of compressed data (Skip to end)
|
||||
80 lo hi 0 < hi < 0x80: skip (nnnn & 0x7FFF) output pixel
|
||||
80 lo hi .. 0x80 <= hi < 0xC0: copy the following (nnnn & 0x3FFF) bytes
|
||||
80 lo C0 hi == 0xC0: undefined (not encountered)
|
||||
80 lo hi zz 0xC0 < hi: write (nnnn & 0x3FFF) bytes of value zz
|
||||
nn 0x80 < nn: skip (nn & 0x7F) output pixel
|
||||
|
||||
Three cases exist to compress pixel data: skip a list of pixel, compress a list of a constant
|
||||
value and copy an arbitrary array of bytes. For each of the three, two encoding variants are used: a short and a long form.
|
||||
If a count is to be serialized that is higher than the long-form can store, the encoder uses the long-form to reduce this number to finalize with the short-form.
|
||||
|
||||
> Skipping output pixel is relevant for compressing video clips. Skipped pixel will retain the colour value from the previous frame.
|
||||
> For still images, initialize the output buffer with 0x00.
|
||||
>
|
||||
> To implement a compressor that creates output closest to the original content, use the following sequence. The term "reference" means either a previous frame bitmap, or a fictual frame with all bytes 0x00.
|
||||
> * From an array of bytes with length X, calculate the count Z of bytes at the end that are identical to reference. Compress only N bytes, where N = X - (Z % 0x7FFF).
|
||||
> The final sequence ```80 00 00``` implies to skip to the end. The encoder
|
||||
> seems to have had a limit of counting only up to 0x7FFF, so there may be further (long) skip entries before.
|
||||
> * Iterate through the pixel data from start to N:
|
||||
> * Count the extent of static value bytes
|
||||
> * Count the number of bytes identical to reference
|
||||
> * Determine encoding method
|
||||
> * If the pixel value shall be retained from the reference, skip the count of bytes
|
||||
> * Otherwise, if the count is more than three, encode the count and the constant value
|
||||
> * Otherwise, count the extent of an arbitrary array; Abort when more than three static or identical values are found in sequence; Encode this array.
|
||||
> * Skip the input bytes that have been serialized and continue with the loop
|
||||
> * Encode end of compressed data sequence.
|
||||
|
||||
|
||||
### Private Palette
|
||||
|
||||
The format also allows for an optional palette, which is specific for the bitmap. If an image has no private palette, then this
|
||||
entry is not present and the resource data ends directly after the pixel data.
|
||||
Without a private palette, the colours of the bitmap are context specific. See [Palettes](Palettes.md) for more information.
|
||||
|
||||
Private palettes are used for the splash screens at the beginning of the game, where nothing else is shown.
|
||||
The ```Private palette offset``` in the bitmap header specifies the absolute offset *from the beginning* of the resource to the private palette entry. This means in case of a compound resource, this offset measures across the previous resource blocks as well.
|
||||
|
||||
**Private Palette** (772 bytes)
|
||||
|
||||
0000 [4]byte Unknown. Always 0x00, 0x00, 0x00, 0x01
|
||||
0004 [256*3]byte RGB values
|
||||
|
||||
> The only working examples for this can be found in ```splash.res```.
|
||||
>
|
||||
> The resource file ```gamescr.res``` also contains three bitmaps with a private palette, but these palettes are not used and are ignored by the engine.
|
||||
> The three bitmaps in question are the help overlay (```ALT+o```), and are shown with the game world in the background. Since in these
|
||||
> cases the world can't change its colour, the screen can't use a private palette. By extension, the side-effects of the "Berserk" patch
|
||||
> also affect the colours of the help overlay.
|
||||
> Furthermore, for these three bitmaps, the values of offset fields are wrong as well.
|
||||
Reference in New Issue
Block a user