VGFM Tileset Format
Format type | Tileset |
---|---|
Hardware | VGA |
Max tile count | 65535 |
Palette | External |
Tile names? | No |
Minimum tile size (pixels) | 16×16 |
Maximum tile size (pixels) | 16×16 |
Plane count | 1 |
Plane arrangement | Linear |
Transparent pixels? | Yes |
Hitmap pixels? | No |
Metadata? | None |
Supports sub-tilesets? | No |
Compressed tiles? | No |
Hidden data? | No |
Games |
The VGFM Tileset Format is used by Vinyl Goddess From Mars to store the graphics used to draw game levels.
Signature
There is no signature, but careful parsing of the fields to ensure they have expected values can allow files to be detected. There is no data trailing the pixelData field, so if this field ends right at the end of the file, it is highly probable the file is in this format.
File format
The file begins with pixel data for each tile, stored in the form of lookup codes. After the last tile's data, there is a list of which lookup codes map to which pixels. The lookup codes are each two bytes long, while the pixels they map to are four bytes long.
Data type | Name | Description |
---|---|---|
UINT16LE | count | Number of tiles in the tileset |
TILE[count] | tile | Variable length data for all tiles (see below) |
UINT16LE | lenPixel | Length of pixel data |
UINT8[lenPixel] | pixelData | Pixel data, lenPixel bytes long |
The TILE structure is as follows:
Data type | Name | Description |
---|---|---|
UINT16LE | lenTile | Number of bytes in the tile data |
UINT16LE[lenTile / 2] | codes | List of codes, lenTile bytes long (see below) |
Each tile is fixed at 16×16 in size.
Where lenTile is 0x80, the tile is composed of 64 UINT16LE values (to make up a length of 0x80 bytes.) Each value is a code that needs to be decoded as described below. There is no mask/transparency in this tile.
Where lenTile is 0xC0 instead, there is additional information for the transparency. The tile is treated as before, but with an additional UINT8 value inserted before each UINT16LE. The lower four bits of the UINT8 control the mask for the corresponding four pixels represented by the UINT16LE code value.
Some examples: (split over multiple lines for readability)
80 00 # Length, here 0x80 00 00 # Code 0x0000 05 00 # Code 0x0005 ... C0 00 # Next tile, length is 0xC0 so this has a mask 0f # Mask byte for first four pixels on the first line 00 00 # Code 0x0000 again 03 # Mask byte for second four pixels on the first line 06 00 # Code 0x0006 ...
Only the lower four bits of the mask byte are used, and these are in opposite order - i.e. the LSB (value 1) is the pixel at x=0, the next bit (value 2) is x=1, bit value 4 is x=2, and bit value 8 is x=3. The bit is set to 1 if the pixel is opaque and 0 if it is transparent.
Decoding tiles
The tiles are stored as a list of UINT16LE values (here called "codes".) Each value is a lookup code, representing four pixels. To find the actual pixel values, this code must be looked up in the pixelData table and those values used.
For example, if the first code in a tile has a value of 0x0000, then the first four pixels in the tile are the first four bytes (0..3) in pixelData. A code of 0x0001 would represent the second lot of four bytes (4..7) in pixelData.
If the second code (target pixels y=0, x=4..7) has a value of 0x0005, then bytes 20..23 in pixelData would be copied into y=0, x=4..7 in the final image.
In the example above, the two tiles start with the same code (0x0000). This means the first four pixels of both tiles will be the same.
Credits
This file format was reverse engineered by Malvineous. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)