DGRP Resource Format
The following information is not based on any proprietary knowledge or restricted documentation—it was entirely derived from observation, experiment, and public information, thus it may be inaccurate or incomplete.
Analyzed by Greg Noel. Thanks to Lee Reeves for initially figuring out the repeating groups in version 20004. Also, Peter Gould ran specially-modified objects through Transmorgifier to see what would happen.
The DGRP ("draw group") resource combines sprites (SPR# or SPR2 resources) into a composite image. A single DGRP knows how to display one tile of an object from each direction and at each zoom factor. Multi-tile objects have a draw group for each tile. Images in each tile are coordinated so that they tie together seamlessly.
A draw group can be used to represent an object in a particular state, called the graphical state. Changing the state changes the draw group that renders the object. The different states may use completely disjoint sprites ("lamp on" and "lamp off" rarely have much in common) but more often an object image will be built up out of a couple of base pieces plus some unique overlays. For example, the fridge consists of an outside, six positions for the door as it opens, and several variations of the inside, so that the animation can get a salad from the humidor, a TV dinner from the freezer, or a can of beans from the shelf.
The DGRP resource started life as a simple structure, containing only a few short integers. Over time, fields have been eliminated, other fields have been moved within the structure, and some floating point values added. Perhaps the most interesting transformation was the expansion of all the integer fields to four-byte integers. There doesn't seem to have been any need for the expansion (the dynamic range of the values fits easily in short integers or bytes), so perhaps it is an attempt to comply with some standard, since many other game formats also use four-byte integers to contain values with a small dynamic range.
In the description below, integers are in little-endian order (least significant byte first). Also, floats are IEEE short float format with the bytes in little-endian order.
|Size in version||Field|
|. . .|
Four versions have been found identified by a version number in the first two bytes. The versions found (so far) are 20000, 20001, 20003, and 20004. (Presumably, 20002 also exists, but there are no samples.) Other formats tend to have versions around 1000, probably meaning 1.000. It is unlikely that this is already version 20, so the version could represent 2.000x or 2.00.0x; of the two, the latter is more likely.
In the tables, the column headed V.x has the width of the corresponding field in version 2000x. A width of zero says that the field does not exist in that version. The fields are given in order; a field that has been moved will have the same description with a zero size in the unused position.
The count is always exactly 12: four directions with three zoom factors each. No exception has been observed, although the encoding looks like some objects could be described in fewer entries.
Each of the twelve images form a complete image of the object from the specified direction and zoom level.
|Size in version||Field|
|12||16||?||24||32||Sprite info 0|
|. . .|
|12||16||?||24||32||Sprite info N-1|
The header was originally only four bytes; later it was expanded to twelve bytes with no change in the dynamic range of the values. Moreover, the count was moved from the first position of the header to the last position (just before the repeating group). There appears to be no real reason to move the count, except that putting the count just before the repeating group is similar to other game formats, lending credence to the hypothesis that this format was changed to comply with some standard.
The direction is probably a bitmap, although all observed cases have exactly one bit set. It may be that the original intent was to allow symmetric objects (a square table or a round pillar, for example) to be described by a single entry, but it turned out to be easier to generate multiple entries instead. A value of 0x01 is the right rear of the image, 0x04 is the right front, and 0x10 is the left front. 0x40 is the left rear, From the symmetry, one can guess that the values 0x02, 0x08, 0x20, and 0x80 are the right, front, left and rear views, respectively.
The zoom factor is always 1, 2, or 3. The value 1 is the smallest image (furthest out), 2 is the intermediate position, and 3 is the largest image (closest in). The smallest image is half the size of the intemediate image and the intermediate image is half the size of the largest image.
The count is how many sprite info entries are present. Each entry identifies a sprite frame and has information on exactly how to adjust the frame when rendering the image.
|DGRP sprite info|
|Size in version||Field|
|2||2||?||4||4||SPR ID number|
|2||2||?||4||4||SPR frame number|
In earlier versions, there's a field that contains either -3 or -5. This is probably some sort of tag; entries with the -3 value contain sprite information while entries with -5 contain something else (and may well be parsed differently; only the total length of the entry is the same). There are so few instances of -5 that it hasn't proved possible to decode them. It's known that Transmorgifier ignores the -5 entries, so they are probably something that has been eliminated. Only the -3 entries are documented here.
The SPR ID is the ID of either an SPR# or SPR2 resource (the DGRP doesn't specify which one). The frame number is the frame within the SPR resource.
The flags were originally right after the SPR fields. When the format was reorganized, they were moved to last, then later two more fields were added at the end. It doesn't seem like there was much foresight being used here; there doesn't seem to be any real reason why they had to be moved.
Only two flag bits have been observed: Bit 1 (mask 0x01) is the mirror symmetry flag, which causes the displayed image to be flipped. (In practice, this bit is only set on left-side images. We can speculate that it might be ignored on right-side images, which would allow such objects to be described with a fewer entries.) Bit 3 (mask 0x04) seems to be applied to objects that flicker, like fire and twinkling lights. The exact meaning is unknown, but it could be a trigger for the animation or it could cause (a portion of) the animation by rotating the palette.
Sprites are apparently restricted to a 136x384 image (this is the widest and tallest any sprite achieves). Pixel X and Y are adjustments to the start location for a sprite so that the composite image can be larger than this size. As suggested by the names, they are integer values measured in pixels and operate in 2-D screen coordinates.
At the same time, objects live in the Sim world. The X, Y, and Z offsets are floats, measured in grid units (the grid that shows up when in buy or build mode; on this scale, an end table occupies about a 1x1x1 cube). These values operate in 3-D world coordinates: the X axis is across the face of the object, the Y axis is forward and backward, and the Z axis is upward. The X offset is always zero in all samples, so it's not absolutely certain that it's a float. The Y offset is used in a few objects like chairs, so they can be moved away from a table when sitting on them. The Z offset is used to place objects (like the burglar alarm) higher than would otherwise be allowed by the sprite image.
The Sims™ is a trademark of Maxis and Electronic Arts.
This page was last modified Monday, 10-Mar-2003 03:41:28 UTC.