Win shapes

From AlephWiki

Jump to: navigation, search

Shapes File Format


Return to History

Loren Petrich


Shapes File Format

The M2/Moo shapes file is all data form, while the M1 shapes file is all resource fork. The M2/Moo shapes file starts with 32 directory records, which have this format:

struct collection_header /* 32 bytes on disk */
{
int16 status;
uint16 flags;

// For 8-bit mode
int32 offset, length;

// For 16-bit mode and higher bit depths
// (use the 8-bit one if this one is absent)
int32 offset16, length16;

int16 unused[6];
};

"offset" is the number of bytes into the file, while "length" is the number of bytes of a shapes chunk. And offset of -1 means no chunk.

However, the shapes chunks are stored as individual resources, starting with index value 128, in M1.

The chunks have this overall format:

Header (shapes_header) [contains offsets to the color and to offset tables for the other data]

Colors (color_entry) (#: color_count*palette_count)

Sequences offsets in chunk (long) (#: high_level_shapes_count)

Sequences (#: high_level_shapes_count)

Header: (high_level_shape)

Frames: (short) (NumViews*number_of_frames + 1) [the last one is zero]

Here is view_count -> NumViews (true number):

1 -> 1
3 -> 4
4 -> 4
5 -> 8
8 -> 8
9 -> 5
10 -> 1

Frames offsets in chunk (long) (#: low_level_shapes_count)

Frames (low_level_shape) (#: low_level_shapes_count)

Image offsets in chunk (long) (#: image_count)

Images (#: image_count)

Header: (image_header)

Scan Starts: (long) (#: NumScanStarts + 1) [address of scanlines; used internally; don't need to keep track of this; just leave room for it]

Image data, as color-index bytes.

The image data is uncompressed for the walls and interface elements (what one sees in the HUD), but is compressed for sprite data. The compression differs between M1 and M2/oo. Furthermore, the scanlines differ, being rows for interface elements (NumScanStarts is the height), and columns for the others (NumScanStarts is the width). Thus, these others will have to be have horizontal and vertical directions interchanged to view them properly.

Here are the two types of data compression used on each scanline:

M1: Repeat the following:

  • Read in a short as value P.
  • If it is positive, then read in the next P values as pixels.
  • If it is negative, then skip over (-P) pixels in the final image.
  • If it is zero, stop

M2/oo:

  • Read in two shorts, P0, P1.
  • Skip over P0 pixels in the final image.
  • Read in the next (P1-P0) values as pixels.

All of this data is packed, without any padding, and, of course, is big-endian.

Big-endian and little-endian are different digit order. Big-endian is most-significant first, little-endian is least-significant first. Numbers written for human consumption are almost always written in big-endian form.

On the computer side of things, however, Macintoshes, Sparcs, and others use big-endian order and PeeCees and Alphas uses little-endian order.

And beyond that, there are alignment problems. The more recent CPU chips prefer n-byte numbers to be aligned on n-byte address boundaries. However, the older CPU chips have generally been less picky, and the Marathon series' data is all 2-byte aligned. Which means that some 4-byte integers are misaligned.

My preferred solution had been to have the compiler put in workarounds for misaligned 4-byte values, but CB dislikes the idea, so I've decided to handle this matter myself, so as to create a version that I know will work with each endianness and level of alignment strictness.

Personal tools