GMF Format (Halloween Harry)
Each of the four missions has five levels, and each level is stored in its own file. Filenames are in the form of MxZy.GMF where x is the mission and y is the level. There are a total of 20 GMF files stored in MAPS.-0. Each GMF file contains a header, 256 colors of palette data, two layers of map data and a sprite layer, and some other data that has not been decoded yet.
The file layout is as follows:
|BYTE||signature||0x11 followed by "SubZero Game File"|
|UINT32LE||unknown||Always zero - changing this seems to have no effect|
|UINT16LE||startX||X coordinate of player's starting position|
|UINT16LE||startY||Y coordinate of player's starting position|
|UINT16LE||unknown||Always zero - changing this seems to have no effect|
|BYTE||mapFlags||Map flags - zero = parallax background, nonzero == fixed background|
|BYTE||palette||Standard 6-bit VGA Palette|
|BYTE||tileflags||One byte flag for each of the map tiles (see below)|
|BYTE||unknown||Could be related to tileflags|
|UINT16LE||spriteCount||Number of sprites in the level|
|BYTE[spriteCount * 128]||sprites||Sprite location/behavior data; see below|
|UINT16LE||mapWidth||Width of map, in tiles|
|UINT16LE||mapHeight||Height of map, in tiles|
|BYTE[mapWidth * mapHeight]||background||Background tiles, one byte per tile|
|BYTE[mapWidth * mapHeight]||foreground||Foreground tiles, one byte per tile|
The palette is easy to decode. It is found in the same place in each GMF file: the 768 bytes from offset 0x1D to 0x31D. The first byte is the red value, the second byte is green, and the third is blue. The values are in the range 0-63 (see VGA Palette for details.)
The very first entry is used for transparent pixels.
Each byte in this block of 256 has a value of either 0 or 1. When this value is zero, the corresponding tile is solid. When this value is one, the tile does not block the player. No other values have been spotted.
There is a set of 10 bytes after the tile flags which are of an unknown purpose. It is also possible this block sits before the tile flags instead. Further investigation of the tile flags will confirm which it is.
After the tile flags/unknown block comes a number of 128-byte blocks. There is a UINT16LE at the beginning to indicate how many blocks (sprites) there are. Each sprite is in the following structure:
|BYTE||type||Sprite type (e.g. 0x24 for a floppy disk)|
|UINT16LE||x||X-coordinate of sprite location, in pixels|
|UINT16LE||y||Y-coordinate of sprite location, in pixels|
Plain-text strings are visible in many of these blocks (M3Z1.GMF contains quite a few), and the content of some of these correspond to text spoken by Diane when Harry touches a disk. The first byte before the text determines the length of the string.
After the sprite data the map tiles follow. These begin with two UINT16LE integers (width and height, in 16x16 tiles) followed by the actual map tiles. There is one byte for each tile in the layer, and there are two layers. The background layer is encoded first. Both have the same dimensions. (But note that, because the game uses parallax scrolling, just placing the foreground map image over the background image won't produce an image that exactly matches what you see when playing.)
No encoding or compression is used. Each byte represents one 16x16 tile, indexed by the table from the MISSIONx.CHR file. For example, a value of 0 represents the 1st tile in the CHR file, a value of 0x10 represents the 17th tile in the CHR file, etc.
Progress and Issues
Duckthing has written a program which reads palette data from the GMF file and tile data from the CHR file, and then creates three PNG images: one for the background, one for the foreground, and one with the foreground overlaid on the background. Aside from the parallax issue mentioned above, and the fact that sprites are missing, this program produces the map as it appears in the game. Of course, the sprites are a major issue.
The following tools are able to work with files in this format.
|Name||Platform||View?||Create new?||Modify?||Access hidden data?||Edit metadata?||Notes|
|Camoto||Linux/Windows||Yes, no sprites||No||Yes, no sprites||N/A||N/A|
This file format was reverse engineered by Duckthing. Additional fields and some of the sprite structure was deciphered 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!)