This document describes the file formats of Free Hero Mesh. (Most users
will not need this file.)
A Free Hero Mesh puzzle set consists of four files, each with the same
base name, but with a different suffix to identify its type:
.xclass - Class resource file
.class - Class definition file
.level - Level file
.solution - Solution file
A composite puzzle set is a Hamster archive file consisting of these
four files as the lumps stored in it.
The below sections are for the lumps of the .xclass, .level, and .solution
files (which are Hamster archive files).
=== level/*.LVL ===
This lump containts the definition of a single level.
The lump name is the level ID number followed by ".LVL".
The header is six bytes:
* Level version number (small-endian 16-bits).
* Level code number (small-endian 16-bits).
* Width (one byte): The low 6-bits are one less than the playfield width.
(The high 2-bits are reserved for future use.)
* Height (one byte): The low 6-bits are one less than the playfield height.
(The high 2-bits are reserved for future use.)
The null-terminated title follows, and may include formatting codes.
After the title is the objects. Start with X=0 and Y=1 (the coordinates are
1-based). Each one starts by the flag byte:
* If it is 0xFF then there are no more objects.
* If it is 0xFE then start over from the beginning (X=0 and Y=1), but any
further objects will be in the bizarro world.
* The bit6, bit5, bit4 are used to determine the coordinates. If bit6 is
set then advance the X coordinate by 1. If bit5 is set then one byte with
the X coordinate follows. If bit4 is set then one byte with the Y
coordinate follows. (Bit4 and bit6 should not both be set.)
* If bit7 is set then it is MRU. In this case, the low 4-bits are the
run count. There are two MRUs; one of them is stored and retrieved if
any of bit6/bit5/bit4 are set, and the other is used if none of them are.
If the run count is nonzero, then that is the number of further objects
after the first one; each one advances the X coordinate by one (leaving
off for the next command at that object's location), and they always use
the MRU for the bit6/bit5/bit4 set instead of clear.
* If bit7 is clear then it is a single non-MRU object (which will be
stored in the appropriate MRU slot, as mentioned, and will also be
placed in the level playfield). In this case, bit3 is set if any of
the Misc1/Misc2/Misc3 are used or clear if they are all zero, and the
low 3-bits are the Dir variable of this object (0=east).
Objects within a cell should be ordered bottom to top, and otherwise
should be ordered starting from top left and going right.
A non-MRU object has the following data:
* Class number: Only the low 14-bits are used for the class number. If
the high bit is set, then it uses the lowest numbered default image for
this class, otherwise the image number is specified explicitly.
* Image number: One byte; not present if bit15 of the class number is
set. (Zero is the first image number.)
* If the bit3 of the flag byte is set, then the next byte specifies
the types of the Misc values. The high two bits specify how many Misc
values are used; if this is zero, then Misc2 and Misc3 are used but
Misc1 is not used. The low 2-bits are the type of Misc1, the next are
type of Misc2, and then type of Misc3. The types are: 0=number, 1=class,
2=message, 3=string.
* The Misc values follow (according to the Misc type byte); each
one that exists is a small-endian 16-bit number.
After the objects is zero or more level strings, each of which is
null-terminated, and may have formatting codes. The first level string
is numbered zero (for the purpose of referencing by Misc values).
=== level/CLASS.DEF ===
Associates class names and user-defined message names with numbers, which
are used to refer to them in the other "*.LVL" lumps (all classes and
user-defined messages used must be listed here, but there may also be
classes and messages that are used only in the class definition file,
which is OK). This lump is mandatory.
First is the list of classes. Each one is the small-endian 16-bit class
number (which must be at least one), followed by the null-terminated class
name (excluding the $ prefix). This is terminated by a small-endian number
zero (and no name).
Next is the list of messages. Each one is the small-endian 16-bit message
number (which must be at least 256), followed by the null-terminated
message name (excluding the # prefix).
Standard messages are not included in this list.
=== level/DIVISION.IDX ===
Contains the list of level divisions. This lump is optional.
Each record consists of a small-endian 16-bit level order number followed
by the null-terminated title of this division.
=== level/LEVEL.IDX ===
Defines the order of the levels. This lump is mandatory.
Consists of a sequence of small-endian 16-bit level ID numbers.
=== solution/*.SOL ===
This lump contains the recorded solution for a single level.
The name of this lump is the level ID number followed by ".SOL". The data
of this lump has the following format:
* Level version number (16-bits small-endian): If this does not match the
level version number in the .LVL lump, then the solution is considered to
be invalid.
* Flags (8-bits): Specifies which other fields are present.
* Score (signed 32-bits small-endian; only present if flag bit7 is set):
The score of this level. Lower numbers are better.
* Comment (null-terminated; only present if flag bit0 set): Normally
contains a user name, but may be any arbitrary text.
* Timestamp (64-bits small-endian; only present if flag bit1 set): The
UNIX timestamp when the solution was recorded.
* Move list: One byte per turn, being the key codes. (Use of numbers 0-7
here is reserved for future use; they are not valid key codes.)
(Free Hero Mesh currently ignores the comment and time stamp, although
this might change in a future version of Free Hero Mesh.)
Special key codes are:
* 1 = Coordinate input; follow by two more bytes being the X coordinate
and Y coordinate (both in the range 1 to 64).
=== xclass/*.DEP ===
A dependent picture (defined by transforming one or more other pictures);
the part of the name before the dot is the picture name.
It starts with the base picture name (which must be a IMG lump, and cannot
be another DEP lump). Any byte in range 0 to 31 is not considered to be a
part of the name and is considered to be the code of the first filter,
instead. After the base name is zero or more filters.
Each filter starts with one byte indicating the filter type:
* 0 to 7 = Mirror/flip/transpose (zero means no change). No additional
data for this filter follows (but other filters might follow).
* 8 to 10 = Change colours. Follow by one byte being the number of colours
listed, and then one byte colour code per colour. The filter code means
the type of colour changing: 8 means it is a list of pairs, replacing the
first in each pair with the second; 9 means each one in the list is changed
to the next one; 10 means pairs where each one is changed to the other one
in that pair.
* 11 = Overlay. Follow by a picture name (which must be a IMG lump and not
a DEP lump); it is terminated in the same way as the base name is.
* 12 to 15 = Shift. The filter code is the direction: 12=up, 13=down,
14=right, 15=left. Follow by a list of pairs of shift amounts. The first
byte of each pair is the shift amount; the high bit is set if this is the
last pair. The second byte of each pair is the picture size that the shift
amount is based on.
* 16 = Hue/shade. The additional data is two bytes, being the hue adjust
(unsigned) and shade adjust (signed).
=== xclass/*.IMG ===
A picture; the part of the name before the dot is the picture name.
The beginning of this lump data specifies how many variants and their
formats and sizes, as follows:
* The first byte has the number of variants in the low nybble, and the
format of the first variant in the high nybble.
* Next is bytes for variants other than the first. The second variant
has the low nybble, the third variant has the high nybble, etc.
* Next is the sizes (one byte each) for each variant, in order. The
size can be any number from 1 to 255; the width and height of the
picture are both this number.
The format numbers are 0 to 7 for compressed format, where the number
indicates the order of the pixels (horizontally or vertically, up, down,
left, right). If the format number is 15 then it is uncompressed and
the pixels are stored in the usual order (starting from top left).
After that is the data for each picture variant.
A compressed picture is stored by the sequence of bytes as follows:
* 0 to 84 = Homogeneous run (2 or more pixels). Follow by one byte being
the pixel value. If the previous command is also a homogeneous run and
is the same colour, then the run count is 85 times one more than the first
byte, otherwise the run count is two plus the first byte.
* 85 to 169 = Heterogeneous run (1 to 85 pixels). Follow by that many
bytes being the pixel values (palette index).
* 170 to 254 = Copy-above run (1 to 85 pixels). Copies the specified
number of pixels from the previous scanline. (If this crosses multiple
scanlines, it continues copying it.)
=== xclass/*.MUL ===
This lump is a "multidependent" lump. The lump name is ignored except for
the MUL suffix, but it is displayed in the picture editor.
The first four bytes are the number of bases and the number of filters in
each of the three filter lists. All of these bytes have the number in the
low 6-bits, and bit7 is set if it is nullable; bit6 is unused and it must
be clear.
After that is the list of bases, each being a null-terminated string,
which must be the name of a .IMG lump without the .IMG suffix.
After the list of bases is the information for each filter chain; first
all chains in the first list, and then the second, and then the third;
null chains are not listed. These records have the format:
* A small-endian 16-bit number, where bit10-bit0 is the length of this
filter chain in bytes, bit13-bit11 is the length of the name in bytes
(not counting the ._- prefix), and bit15-bit14 is the prefix character
(0 if none, 1 if a hyphen, 2 if a underscore, or 3 if a dot).
* The name, not counting the prefix, with no terminator.
After that will be the list of filters in each chain, in the same format
as for DEP lumps but without the base name.
=== xclass/*.WAV ===
A user-defined sound effect. The part of the lump name before the dot is
the name used to refer to it in a class definition file; the exclamation
mark is not included in the lump name.
The format is a RIFF WAVE file.
=== xclass/PICEDIT.CFG ===
Stores the default picture sizes when adding new pictures to this puzzle
set. Consists of one byte per picture size (up to fifteen sizes). If there
is any null byte, then it and anything after it is ignored (in future, the
extra data may be used for something; currently, it is meaningless).