Adding modding folder with a hacked build.

This commit is contained in:
ml
2026-09-26 08:53:08 +02:00
parent cdb960dc71
commit c91080aba7
755 changed files with 50424 additions and 0 deletions
+97
View File
@@ -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.