.sg2 / .sg3 + .555 Documented

The SG asset pipeline

Every sprite in Caesar III, Pharaoh, Zeus and Emperor comes through this pair of files: an .sg2 or .sg3 index describing images, and one or more .555 files holding their pixels. Getting art out of these games, or new art in, means reading both.

Used by Caesar III Pharaoh Zeus Emperor

An SG file contains no pixels. It is an index: a fixed header, a lookup table, one record per source bitmap, and one record per image. The pixels live in .555 files, and every image record points into one by byte offset.

The split is what makes the format tractable. You can read the whole catalogue of a game's art — names, dimensions, animation frames, which building a sprite belongs to — without decoding a single pixel.

Header

80 bytes, at the start of the file. All integers are little-endian.

OffsetSizeTypeFieldDescription
04int32file_sizeSize of this SG file.
44int32versionFormat version. See the table below.
84unknownPurpose not established.
124int32num_image_recordsTotal image records present.
164int32num_imagesImage records actually in use.
204int32num_bitmap_recordsBitmap records present.
244int32unknownBitmap-related; purpose not established.
284int32total_filesizeTotal size of the image data.
324int32filesize_555Size of the internal .555 file.
364int32filesize_externalCombined size of the external .555 files.
4040unknownPurpose not established.

Version codes

Read from offset 4. The version decides the size of an image record, which makes it the first thing a parser needs.

211
SG2 — Caesar III.
213
SG3 — Pharaoh, Zeus, Emperor.
214
SG3 with an alpha mask. Image records grow from 64 to 72 bytes.

Index

600 bytes, immediately after the header.

OffsetSizeTypeFieldDescription
80600uint16[300]image_idsMaps a stable game-facing group ID to the position of an image record. The indirection is the point: artists could reorder or re-export images without the game code having to change.

Bitmap record

200 bytes each, following the index. One per source bitmap — the artist's original file, which may hold many game images.

OffsetSizeTypeFieldDescription
065char[]filenameNull-terminated source filename, e.g. a .bmp name.
6551char[]commentNull-terminated description.
1164int32widthWidth of the external bitmap.
1204int32heightHeight of the external bitmap.
1244int32num_imagesHow many images come from this bitmap.
1284int32start_indexFirst image index belonging to it.
1324int32end_indexLast image index belonging to it.
13664int32[16]unknownPurpose not established.

Image record

64 bytes below version 214, 72 bytes at 214 and above. Offsets are relative to the start of the record.

OffsetSizeTypeFieldDescription
04int32offset_555Byte offset of this image's pixel data within its .555 file.
44int32lengthLength of the stored data.
84int32uncompressed_lengthLength once expanded.
124zeroAlways zero.
164int32invert_offsetOffset of the image this one mirrors. SG3 only.
202uint16widthImage width in pixels.
222uint16heightImage height in pixels.
246unknownThree shorts; purpose not established.
302uint16num_animation_spritesFrames in this animation.
322uint16unknownPurpose not established.
342int16sprite_offset_xHorizontal animation offset.
362int16sprite_offset_yVertical animation offset.
3810unknownPurpose not established.
481uint8can_reverseWhether the animation plays back and forth.
491unknownPurpose not established.
501uint8typeImage type. See below.
511uint8fully_compressedThe whole image is run-length compressed.
521uint8externalPixels live in an external .555 file rather than the internal one.
531uint8part_compressedIsometric image with a compressed top section.
542unknownPurpose not established.
561uint8bitmap_idWhich bitmap record this image came from.
571unknownPurpose not established.
581uint8animation_speed_idPlayback speed selector.
591unknownPurpose not established.
604zeroAlways zero.
644int32alpha_offsetAlpha mask offset. Version 214 only.
684int32alpha_lengthAlpha mask length. Version 214 only.

Image types

Read from offset 50 of an image record.

0
Plain image that may carry transparency.
1, 10, 12, 13, 20
Plain images.
30
Isometric — a building or terrain tile, stored differently. See below.

How pixels are stored

Three storage modes, chosen per image by the flags at offsets 51 to 53.

Uncompressed images are raw pixels, row by row, top to bottom and left to right.

Compressed images are run-length encoded, and only for transparency. A control byte of 255 means "the next byte is a count of transparent pixels"; any other value is a count of coloured pixels that follow. There is no compression of the colours themselves.

Isometric images come in two parts. The base is a set of uncompressed diamond tiles — 58×30 pixels in Caesar III, Pharaoh and Zeus, and 78×40 in Emperor — laid out row by row for multi-tile buildings. Anything standing above the ground plane follows as a compressed "top" section.

The .555 files and colour

Pixels are two bytes each, little-endian, five bits per channel in R-G-B order. The single value 0xF81F is the transparency key rather than a colour, which is why it never appears as magenta in-game.

Most images live in the internal .555 file, which shares the SG file's name. Some live in external ones, flagged at offset 52 of the image record and named after the bitmap record's filename with the extension changed to .555. Pharaoh in particular spreads its art across several external files.

Sources