User:Alfwyn/Sandbox8
Arena Hacking[edit]
BSA[edit]
Arena has only one BSA file, "GLOBAL.BSA", which is simply many smaller files packed together. The format is close to Daggerfall's BSA format.
BSA File Format | |
---|---|
uint16 | Number of files |
blob[] | File contents |
index[] | File indices |
The beginning of the file index section can be found at filesize-18*number_of_files
, entries have the following format:
index | |
---|---|
char[12] | 8.3 Filename |
uint16 | unused, always 0 |
uint16 | File size |
uint16 | unused, always 0 |
From there the contents of a file can be found by successively adding file sizes of previous entries (and observing the initial offset of 2).
IMG, COL[edit]
The IMG format for images and COL format for color palettes match that of Daggerfall (IMG and COL), with a few differences:
Some images have no header, in that case the image is uncompressed, but width and height have to be known. All images are in 8-bit indexed color format.
IMG header | |
---|---|
uint16 | X-Offset |
uint16 | Y-Offset |
uint16 | image width |
uint16 | image height |
uint16 | flags |
uint16 | Pixel data length (equals width x height for uncompressed images) |
Following the initial header is the pixel data, after that the optional palette.
Palettes are 256 entries of 3 bytes in order r, g, b, with values 0=black to 63=full color. They are either contained in the image file, or found in one of several COL files.
LZSS compression[edit]
Let outp be the position in the stream of decompressed data written, starting at 0. Compressed data is a sequence of units until the pixel data length is reached:
The first byte encodes the meaning of the next few bytes, from low to high bit:
- 1: next byte is a literal, to be copied as is
- 0: next two bytes encode length and position of already decoded data to copy:
- 12 bit location (8 low bits found in first byte, 4 high bits found in the high bits of second byte)
- 4 bit length (4 low bits in second byte)
- len bytes starting at pos should be copied to the output:
- len = length+3
- pos = outp&~0xfff | (location+18)&0xfff; if (pos>=outp) pos-=4096
- Note that pos+len may span beyond the currently decompressed data, that way run length compression is part of the algorithm
- len bytes starting at pos should be copied to the output: