`makespr 0.3`
For Civilization: Call to Power
5/21/99

## Contents:

> 1.0 - The Distribution

> 2.0 - Using the Utility
> 2.1 - Scripts
> 2.1.1 - Unit Sprite Scripts
> 2.1.2 - Good Sprite Scripts
> 2.1.3 - City Sprite Scripts
> 2.1.4 - Effect Sprite Scripts
> 2.2 - TIFF Folders and the Source Images

> 3.0 - Graphics Format

> 4.0 - File Names
> 4.1 - Graphics File Names
> 4.2 - Script File Names

> 5.0 - For the Not-So-Faint-Of-Heart

##

1.0 - The Distribution

> `README.TXT`
> `LEGAL.TXT`
> `makespr.exe`
> `Units`
> `1`
> `gu01.txt`
> `Goods`
> `4`
> `gg04.txt`
> `Cities`
> `2`
> `gc002.txt`
> `Effects`
> `21`
> `gx21.txt`

## 2.0 - Using the Utility

This section describes how you might go about using the makespr utility to generate a sprite file (*.SPR file) for use in Call to Power.

To use the utility you'll need:

1. A collection of TIFF images for the sprite you want to make
2. A script file describing the sprite, and the images involved.
3. The makespr.exe utility

Depending on what type of sprite you're making, you'll need different image files. See each section below for details on how to make each type of sprite.

Here's the usage for the utility:

`makespr 0.3: turns a bunch o' tifs into an '.SPR'`

`Usage: makespr [-u] [-c] [-g] [-x] [sprite id]`

`-u Convert a Unit sprite`
`-c Convert a City sprite`
`-g Convert a Good sprite`
`-x Convert an Effect sprite`

`[id] Must be between 0 and 99.`

Copy the makespr.exe to the directory where you have your script file. The script filename must follow the script file naming convention as detailed below. In this example, it's a Unit Sprite script file. The EXE, the script file, and the directory full of images must be in the same directory:

> `Units`
> `1`
> `gu01.txt`
> `makespr.exe`

The name of the directory with the image files is the id number of the sprite you're making, with any leading zeroes removed. Thus, gu01.txt refers to sprite 01, or 1, the directory must be called "1"

From the command line, issue:

`makespr -u 1`

and a `GU01.SPR` will be generated and placed in the same directory as the script file.

### 2.1 - Scripts

To create a sprite, you need to write a script. The script describes the attributes of the sprite, and indicates what the makespr utility can expect to find on disk. Depending on the type of sprite, the script has varying requirements, but some features are common to all.

Scripts are made up of tags and values. Most tags have a corresponding value, others just signify a block of other tags and values. Blocks associated with tags have a boolean value for that tag. That is, 0 or 1, indicating whether the block is supposed to be defined in the script.

#### 2.1.1 - Unit Sprite Scripts

Unit sprites are made up of 5 different animations. These are:

1. Move - displayed when the unit is moving
2. Attack - displayed when the unit attacks another unit, or is attacked by another unit
3. Idle - displayed periodically while the unit is standing still and doing nothing
4. Victory/Death - Displayed when the unit wins/loses a battle
5. Special Action - Displayed for special attacks or things like launch or re-entry from space.

Every Unit MUST have at least one frame (frame zero) of the Move animation. If you want to make single-frame Unit sprites, this is what you want. You'll define only frame zero of the Move animation for each of the 5 facings, and you'll be in business.

A Unit can face 8 directions:

`1`
`8 | 2`
`\|/`
`7---+---3`
`/|\`
`6 | 4`
`5`

To save memory and disk space, we removed facings 6, 7, and 8, and simply mirror the 2, 3, and 4 facings horizontally to simulate a full 8 facings of graphics using only 5 total facings. Like this:

`1`
`2* | 2`
`\|/`
`3*--+---3`
`/|\`
`4* | 4`
`5`

So, to make graphics for a sprite, you only need to create images for facings 1-5, and the other 3 facings will be generated by the code. This lightens the graphics burden a little bit as well. The facings are referred to as 1-5, and they are the directions indicated above. Some unit animations need the full 5 facings (Move, Attack, Special Action) and some only require 1 facing (Idle, Victory/Death.)

Move - requires 5 facings
Attack - requires 5 facings
Idle - requires 1 facing
Victory/Death - requires 1 facing
Special Action - requires 5 facings

Here's a sample Unit Sprite script, commented heavily. It's a script for the Cow sprite, which has a Move and a Death animation only.

> `##############################################################`
> `# This is a sample Unit Sprite script.`
> `##############################################################`

> `0 # this leading zero is required (it can be any number. A number`
> `# here is required, but ignored currently`

> `#`
> `# The UNIT_SPRITE keyword indicates that this is a sprite for units`
> `#`
> `UNIT_SPRITE`
> `{`
> `# The UNIT_SPRITE_MOVE tag specifies whether this sprite has`
> `# a Move action. It has a value of either 0 or 1. If it's 0,`
> `# no sprite action definition block is required. Since it's 1,`
> `# this block is required.`
> `#`
> `UNIT_SPRITE_MOVE 1`
> `{`
> `# This is the sprite action definition block. All sprite`
> `# actions require this block if the sprite action is defined.`
> `#`
> `SPRITE_NUM_FRAMES 11 # number of frames of animation`
> `SPRITE_FIRST_FRAME 0 # the index of the first frame`
> `SPRITE_WIDTH 96 # the width of each sprite image`
> `SPRITE_HEIGHT 72 # the height of each sprite image`
> `SPRITE_HOT_POINTS # the hot points (center points) of`
> `# the sprite for each of the 5 facings`
> `49 54 # facing 1`
> `43 51 # facing 2`
> `50 48 # facing 3`
> `58 38 # facing 4`
> `74 53 # facing 5`
> `}`

> `# The ANIM block is required for each UNIT_SPRITE_* action block`
> `# that is defined (set to 1, and has a sprite action definition`
> `# block.) It describes the animation that will pay, given the`
> `# sprite frames described in the UNIT_SPRITE_* block.`
> `#`
> `ANIM 1`
> `{`
> `ANIM_TYPE 1 # what type of animation is this?`
> `# 0 = sequential (play through from`
> `# the first frame to the last`
> `# defined frame`
> `# 1 = looped (starts over at the`
> `# first frame when it's gone`
> `# through all of the frames`
> `# 2 = back-n-forth (reverses`
> `# direction of playback when`
> `# it reaches the last frame,`
> `# and playes back to the first`
> `# before reversing direction`
> `# again.`
> `ANIM_NUM_FRAMES 10 # How many frames of animation?`
> `ANIM_PLAYBACK_TIME 1000 # How much time does it take to play`
> `# back the animation (in ms.) This`
> `# is not currently supported.`
> `ANIM_DELAY 0 # amount of time to repeat the very`
> `# last frame of the animation before`
> `# continuing (when playing looped`
> `# or Back 'n Forth animations)`
> `ANIM_FRAME_DATA # the list of the sprite frames to`
> `1 2 3 4 5 # to play (must be the same number`
> `6 7 8 9 10 # as defined in ANIM_NUM_FRAMES)`

> `#`
> `# The ANIM_MOVE_DELTAS are nudges applied to each frame of`
> `# animation which bump the draw location the specified offset.`
> `# They allow an single static frame to be moved around a fixed`
> `# location, for instance.`
> `#`
> `# There's one per frame of animation as defined in`
> `# ANIM_NUM_FRAMES`
> `#`
> `ANIM_MOVE_DELTAS 1`
> `{`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`

> `}`

> `#`
> `# This is a 4 bit transparency value, ranged from 0-15, to be`
> `# applied to each frame. This allows the sprite to fade in or`
> `# out over the course of animation, or whatever transparency`
> `# might be used for. 0 is invisible, 15 is opaque`
> `#`
> `ANIM_TRANSPARENCIES 1`
> `{`
> `15 15 15 15 15`
> `15 15 15 15 15`
> `}`

> `}`

> `#`
> `# The Attack animation for this sprite. As you can see, this`
> `# unit doesn't have an Attack animation, so the tag's value is zero.`
> `# Because this tag's value is zero, there's no sprite action`
> `# definition block, and no ANIM {} block associated with this action.`
> `#`
> `UNIT_SPRITE_ATTACK 0`

> `#`
> `# The Idle animation for this unit. There's no Idle animation`
> `# either.`
> `#`
> `# If this sprite had an idle animation, the format of the sprite`
> `# action definition block would be exactly the same as the format`
> `# of the Move block above`
> `#`
> `UNIT_SPRITE_IDLE 0`

> `#`
> `# This Unit DOES have a victory/death animation. For this sprite`
> `# action definition block, and this one only (Victory) there's`
> `# an additional flag field immediately following the`
> `# UNIT_SPRITE_VICTORY tag, and that's UNIT_SPRITE_IS_DEATH, which`
> `# is set to either 0 (indicating that this animation specifies`
> `# a Victory animation--an animation to play when this unit wins`
> `# a battle) or 1 (indicating that this is a death animation, which`
> `# will play when the unit is killed.)`
> `#`
> `UNIT_SPRITE_VICTORY 1`
> `UNIT_SPRITE_IS_DEATH 1`
> `{`
> `SPRITE_NUM_FRAMES 17`
> `SPRITE_FIRST_FRAME 1`
> `SPRITE_WIDTH 96`
> `SPRITE_HEIGHT 72`
> `SPRITE_HOT_POINT 58 38`
> `}`

> `ANIM 1`
> `{`
> `ANIM_TYPE 0`
> `ANIM_NUM_FRAMES 33`
> `ANIM_PLAYBACK_TIME 3300`
> `ANIM_DELAY 0`
> `ANIM_FRAME_DATA`
> `0 1 2 3 4`
> `5 5 5 5 5`
> `6 6 7 7 8`
> `8 9 9 10 10`
> `11 11 12 12 13`
> `13 14 14 15 15`
> `16 16 0`

> `ANIM_MOVE_DELTAS 1`
> `{`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`

> `}`
> `ANIM_TRANSPARENCIES 1`
> `{`
> `15 15 15 15 15`
> `15 15 15 15 15`
> `15 15 15 15 15`
> `15 15 15 15 15`
> `15 15 15 15 15`
> `15 15 15 15 15`
> `15 15 15`
> `}`

> `}`

> `#`
> `# This is the Unit Sprite's Work animation (Special Animation)`
> `# to be used when doing special attacks or special movement.`
> `#`
> `# As you can see, it's not defined.`
> `#`
> `UNIT_SPRITE_WORK 0`

> `#`
> `# Unit Sprite Attributes Section`
> `#`
> `#`
> `# This section specifies a bunch of unit sprite attributes`
> `#`

> `#`
> `# Firepoints`
> `#`
> `# This block indicates where on the sprite that ammunition should`
> `# originate when the unit attacks. This is currently ignored.`
> `#`
> `UNIT_SPRITE_FIREPOINTS 0`

> `# Work Firepoints`
> `#`
> `# This block indicates where on the sprite that the ammunition`
> `# should originate when the unit special attacks. This is also`
> `# currently ignored.`
> `#`
> `UNIT_SPRITE_FIREPOINTS_WORK 0`

> `# UNIT_SPRITE_MOVEOFFSETS`
> `#`
> `# These are sprite nudges to be applied when the unit is moving.`
> `# They are an alternate way of specifying how many pixels in each`
> `# direction that unit should move. There's one pair of offsets`
> `# (x,y) for each facing (1-5).`
> `#`
> `# These are not currently used in the engine.`
> `#`
> `UNIT_SPRITE_MOVEOFFSETS 1`
> `{`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `}`

> `# UNIT_SPRITE_SHIELDPOINTS`
> `#`
> `# This tag's block, when defined, allows you specify where the`
> `# unit's herald shield will appear in the sprite for each of the`
> `# 5 facings, for each of the 5 actions that the unit will perform.`
> `#`
> `# Often a fixed shield position wouldn't always work, as the shield`
> `# might cover up an important part of the sprite. This block`
> `# allows specific points to be used.`
> `#`
> `UNIT_SPRITE_SHIELDPOINTS 1`
> `{`
> `UNIT_SPRITE_SHIELDPOINTS_MOVE`
> `82 9`
> `82 9`
> `82 9`
> `82 9`
> `82 9`
> `UNIT_SPRITE_SHIELDPOINTS_ATTACK`
> `48 36`
> `48 36`
> `48 36`
> `48 36`
> `48 36`
> `UNIT_SPRITE_SHIELDPOINTS_IDLE`
> `48 36`
> `48 36`
> `48 36`
> `48 36`
> `48 36`
> `UNIT_SPRITE_SHIELDPOINTS_VICTORY`
> `82 9`
> `48 36`
> `48 36`
> `48 36`
> `48 36`
> `UNIT_SPRITE_SHIELDPOINTS_WORK`
> `48 36`
> `48 36`
> `48 36`
> `48 36`
> `48 36`
> `}`

> `}`

#### 2.1.2 - Good Sprite Scripts

> `##############################################################`
> `# Sample Good Sprite Script`
> `##############################################################`
> `#`

> `0 # Required 0 here`

> `#`
> `# The TAG for this sprite is GOOD_SPRITE`
> `#`

> `GOOD_SPRITE`
> `{`
> `#`
> `# Goods only have one Action, and that's Idle.`
> `#`
> `# This is a single-facing sprite, not a multiple facing one.`
> `#`
> `GOOD_SPRITE_IDLE 1`
> `{`
> `SPRITE_NUM_FRAMES 16`
> `SPRITE_FIRST_FRAME 1`
> `SPRITE_WIDTH 96`
> `SPRITE_HEIGHT 72`
> `SPRITE_HOT_POINT 53 47`
> `}`

> `#`
> `# Every Action must have an ANIM block`
> `#`
> `ANIM 1`
> `{`
> `ANIM_TYPE 1`
> `ANIM_NUM_FRAMES 32`
> `ANIM_PLAYBACK_TIME 6400`
> `ANIM_DELAY 5000`
> `ANIM_FRAME_DATA`
> `0 1 2 3 2`
> `3 2 3 2 3`
> `4 5 6 7 8`
> `7 8 7 7 7`
> `8 7 8 7 8`
> `9 10 11 12 13`
> `14 15`

> `#`
> `# This block is expanded for illustration purposes`
> `# it could just as easily be replaced with:`
> `# ANIM_MOVE_DELTAS 0`
> `# to achieve the same effect`
> `#`

> `ANIM_MOVE_DELTAS 1`
> `{`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`
> `0 0`

> `}`

> `ANIM_TRANSPARENCIES 1`
> `{`
> `15 15 15 15 15`
> `15 15 15 15 15`
> `15 15 15 15 15`
> `15 15 15 15 15`
> `15 15 15 15 15`
> `15 15 15 15 15`
> `15 15`
> `}`
> `}`
> `}`

#### 2.1.3 - City Sprite Scripts

> `##############################################################`
> `# This is a sample City Sprite script.`
> `##############################################################`

> `0 # Required 0`

> `#`
> `# For reasons that don't bear explanation, a city is the same`
> `# thing as a unit. City sprites, however, aren't used like units`
> `# in the game engine. It's assumed that city sprites (GC*.SPR)`
> `# have only an IDLE action, and nothing else.`
> `#`
> `# So a city sprite's script looks just like a unit sprite's`
> `# script, except that the only action defined is Idle. Here's`
> `# an example:`
> `#`

> `UNIT_SPRITE`
> `{`
> `UNIT_SPRITE_MOVE 0`

> `UNIT_SPRITE_ATTACK 0`

> `UNIT_SPRITE_IDLE 1`
> `{`
> `SPRITE_NUM_FRAMES 1`
> `SPRITE_FIRST_FRAME 1`
> `SPRITE_WIDTH 96`
> `SPRITE_HEIGHT 76`
> `SPRITE_HOT_POINT 49 54`
> `}`

> `ANIM 1`
> `{`
> `ANIM_TYPE 1`
> `ANIM_NUM_FRAMES 1`
> `ANIM_PLAYBACK_TIME 1000`
> `ANIM_DELAY 10000`
> `ANIM_FRAME_DATA`
> `0`

> `ANIM_MOVE_DELTAS 0`
> `ANIM_TRANSPARENCIES 0`

> `}`

> `UNIT_SPRITE_VICTORY 0`

> `UNIT_SPRITE_WORK 0`

> `UNIT_SPRITE_FIREPOINTS 0`

> `UNIT_SPRITE_FIREPOINTS_WORK 0`

> `UNIT_SPRITE_MOVEOFFSETS 0`

> `UNIT_SPRITE_SHIELDPOINTS 0`
> `}`

#### 2.1.4 - Effect Sprite Scripts

> `##############################################################`
> `# This is a sample Effect Sprite script.`
> `##############################################################`

> `21 # a number is required here. It can be any number.`

> `#`
> `# An Effect Sprite is much like a good sprite, except that the`
> `# tag EFFECT_SPRITE implies that the script will define`
> `# EFFECT_SPRITE_PLAY and EFFECT_SPRITE_FLASH. The sprite must`
> `# have an EFFECT_SPRITE_PLAY block, and may optionally have`
> `# an EFFECT_SPRITE_FLASH block.`
> `#`
> `# The *_PLAY block defines the animation for the effect, and`
> `# the *_FLASH block defines a special effect flash that can`
> `# be drawn in the frame as well. The graphics in the *_FLASH`
> `# block are drawn in an additive mode, rather than a standard`
> `# pixel copy mode, to allow for some lighting effects.`
> `#`
> `# The *_FLASH was originally designed to let us light up the`
> `# terrain around the sprite being drawn.`
> `#`

> `EFFECT_SPRITE`
> `{`
> `#`
> `# The Play block is required, and looks much like a normal`
> `# sprite definition block (See the Unit Sprite Script's`
> `# Idle block.)`
> `#`
> `# Note that an ANIM block is required whenever a sprite`
> `# action block is defined.`
> `#`
> `EFFECT_SPRITE_PLAY 1`
> `{`
> `SPRITE_NUM_FRAMES 12`
> `SPRITE_FIRST_FRAME 1`
> `SPRITE_WIDTH 96`
> `SPRITE_HEIGHT 72`
> `SPRITE_HOT_POINT`
> `58 58 # facing 1`
> `}`

> `ANIM 1`
> `{`
> `ANIM_TYPE 0 # 0 = Seq 1 = looped 2 = bnf`
> `ANIM_NUM_FRAMES 24`
> `ANIM_PLAYBACK_TIME 4800 # 1 second`
> `ANIM_DELAY 0 # no delay`
> `ANIM_FRAME_DATA`
> `0 1 2 3 4`
> `5 6 7 8 9`
> `10 11 0 1 2`
> `3 4 5 6 7`
> `8 9 10 11`
> `ANIM_MOVE_DELTAS 0`
> `ANIM_TRANSPARENCIES 0`
> `}`

> `#`
> `# Flash is not currently defined for this sprite, but if it were,`
> `# it would take the form of the EFFECT_SPRITE_PLAY block exactly.`
> `#`
> `EFFECT_SPRITE_FLASH 0`
> `}`

#### 2.2 - TIFF Folders and the Source Images

When you want to compile a sprite, you place all of the appropriately constructed and appropriately named TIFF images into a folder named by the number of the sprite you want to create. For instance, if you wanted to make sprite 25, you'd put them all in a folder called '25'

See Section 4.0 of this document for the naming convention for sprite source images. This naming convention must be observed religiously, or the makespr.exe program won't function.

## 3.0 - Graphics Format

In general, the source graphics for sprites must be 32 bit TIFF's. The R, G, and B channels of the image (8 bits each) comprise the graphic to be drawn on the screen. The alpha channel (A channel, 8 bits) tells makespr.exe what pixels on the image are "on" and should be drawn in the game. The alpha channel is used as a mask for the image. Additionally, since the alpha channel is an 8 bit channel, there are 256 gray levels (0..255) that are used to perform alpha blending when the sprite is drawn. This allows you to make portions of the sprite translucent by providing an alpha value that's less than 255 in the alpha channel of the source image.

Here's an example. These are all from the same 32 bit TIFF file, GU01MA3.3.TIF:

Here's the RGB image of the cow:

Here's the alpha channel for that image. Black (0) means no alpha, and white (255) means full alpha. Gray levels in between apply a fractional alpha.

Also associated with this TIFF is a shadow file, which contains information about the shadow that this sprite casts. The shadow file is optional. makespr.exe will look for a shadow file that corresponds to each 32 bit image TIFF that it loads, and it'll use it if it finds it. Otherwise, shadows are ignored.

The shadow is in a separate file, in this case, GU01MS3.3.TIF:

The shadow image is a 24 bit TIFF (no alpha channel). makespr.exe looks for black pixels or white pixels. White pixels mean no shadow, black pixels mean shadow. This image is 1 bit (black or white, no gray.)

All of these images must be of the size 96x72 pixels.

As makespr.exe processes each sprite, it takes the information in the 32 bit (ARGB) TIFF and the 24 bit (RGB) shadow file (if it exists) and combines them to make each frame of the sprite.

## 4.0 - File Names:

### 4.1 Graphics File Names

> ### Units:

> `GU` | `01` | `M` | `A` | `1` | `.` | `0` | `.` | `TIF`
> Type (Graphics, Units) | Number (must be between 00 and 99) | Action: M - move A - attack I - idle V-victory/death W-specialAttack | Anim or Shadow (A or S) | Facing (1-5 |  | Frame # (0-99) |  | Must be TIF

> > `Move:`

> > `GU01MA1.0.TIF`
> > `GU01MS1.0.TIF (optional)`

> > `Attack:`

> > `GU01AA1.0.TIF`
> > `GU01AS1.0.TIF (optional)`

> > `Idle:`

> > `GU01IA1.0.TIF`
> > `GU01IS1.0.TIF (optional)`

> > `Victory/Death:`

> > `GU01VA1.0.TIF`
> > `GU01VS1.0.TIF (optional)`

> > `Special Action:`

> > `GU01WA1.0.TIF`
> > `GU01WS1.0.TIF (optional)`

> ### Goods:

> `GG` | `04` | `A` | `.` | `1` | `.` | `TIF`
> Type (Graphics, Goods) | Number (must be between 00 and 99) | Anim or Shadow (A or S) |  | Frame # (1-99) |  | Must be TIF

> `GG04A.1.TIF`
> `GG04S.1.TIF (optional)`

> ### Cities:

> `GC` | `002` | `A` | `.` | `1` | `.` | `TIF`
> Type (Graphics, Cities) | Number (must be between 000 and 999) | Anim or Shadow (A or S) |  | Frame # (1-99) |  | Must be TIF

> `GC002A.1.TIF`
> `GC002S.1.TIF (optional)`

> ### Effects:

> `GX` | `21` | `E` | `A` | `.` | `1` | `.` | `TIF`
> Type (Graphics, fX) | Number (must be between 00 and 99) | Effect or Flash (E or F) | Anim or Shadow (A or S) |  | Frame # (1-99) |  | Must be TIF

> `GX21EA.1.TIF`
> `GX21ES.1.TIF (optional)`

> `GX21FA.1.TIF (optional)`

### 4.2 Script File Names

> #### Units

> `GU01.TXT - where the number 01 is valid between 00 and 99.`

> #### Goods

> `GG01.TXT - where the number 01 is valid between 00 and 99.`

> #### Cities

> `GC001.TXT - where the number 001 is valid between 000 and 999.`

> #### Effects

> `GX01.TXT - where the number 01 is valid between 00 and 99.`

##

5.0 - For the Not So Faint of Heart

This section describes the data format of the encoded sprites. This information can be used to create code to interpret, draw, or export sprites in the hands of someone who knows C/C++.

Activision provides no guarantees, and will not be held responsible for any damages that result from the use of this stuff. It won't compile as it is right here, and is provided only as a framework to work from for those interested in writing code to handle the Civ:CTP sprite format.

Activision also won't provide any sort of tech support for questions regarding this stuff. You're on your own.

Caveat Emptor. Have fun.

> `#pragma once`
> `#ifndef __SPRITEUTILS_H__`
> `#define __SPRITEUTILS_H__```

> `// 16 bit pixels of interest`
> `#define k_CHROMAKEY_PIXEL 0x0000`
> `#define k_SHADOW_PIXEL_565 0xF81F`
> `#define k_SHADOW_PIXEL_555 0x7C1F`
> `#define k_SHADOWBACKGD_PIXEL 0xFFFF`
> `// IDs in the RLE sprite stream`
> `#define k_CHROMAKEY_RUN_ID 0x0A`
> `#define k_COPY_RUN_ID 0x0C`
> `#define k_SHADOW_RUN_ID 0x0E`
> `#define k_FEATHERED_RUN_ID 0x0F```

> `// EOLN mask for tag`
> `#define k_EOLN_ID 0xF0```

> `// Alpha values`
> `#define k_NO_ALPHA 0x00`
> `#define k_ALL_ALPHA 0xFF```

> `// Flag for empty row in sprite table`
> `#define k_EMPTY_TABLE_ENTRY 0xFFFF```

> `void spriteutils_MergeShadowMap(Pixel32 *buf, Pixel32 *shadowBuf, uint16 width, uint16 height);```

> `// Sprite Encoding`
> `void spriteutils_EncodeShadowRun(Pixel32 **inBuf, sint32 *pos, sint32 width, Pixel16 **outBufPtr);`
> `void spriteutils_EncodeCopyRun(Pixel32 **inBuf, sint32 *pos, sint32 width, Pixel16 **outBufPtr);`
> `char spriteutils_EncodeChromakeyRun(Pixel32 **inBuf, sint32 *pos, sint32 width, Pixel16 **outBufPtr);`
> `void spriteutils_EncodeFeatheredRun(Pixel32 **inBuf, sint32 *pos, sint32 width, Pixel16 **outBufPtr);`
> `char spriteutils_EncodeScanline(Pixel32 *scanline, sint32 width, Pixel16 **outBufPtr);`
> `Pixel16 *spriteutils_RGB32ToEncoded(Pixel32 *buf, Pixel32 *shadowBuf, uint16 width, uint16 height);`
> `Pixel16 *spriteutils_RGB32ToEncoded(Pixel32 *buf, uint16 width, uint16 height);```

> `#endif//__SPRITEUTILS_H__`

> `//////////////////////////////////////////////////////////////////////////////`

> `void spriteutils_EncodeShadowRun(Pixel32 **inBuf, sint32 *pos, sint32 width, Pixel16 **outBufPtr)`
> `{`
> `Pixel16 pix16;`
> `uint8 alpha;`
> `sint32 runLen = 0;`
> `Pixel16 footer=0;`
> `Pixel16 shadowPixel;```

> `if (g_is565Format) shadowPixel = k_SHADOW_PIXEL_565;`
> `else shadowPixel = k_SHADOW_PIXEL_555;```

> `RGB32Info(**inBuf, &pix16, &alpha);`
> `while (pix16 == shadowPixel && (*pos < width)) {`
> `// Increment input buffer`
> `(*inBuf)++;```

> `// Increment position counter`
> `(*pos)++;```

> `// Increment run length`
> `runLen++;```

> `RGB32Info(**inBuf, &pix16, &alpha);`
> `}```

> `// Build header/footer ID`
> `footer = (Pixel16)(k_SHADOW_RUN_ID << 8 | runLen);```

> `// Set the high nybble of the tag if it's an EOLN condition`
> `if (*pos >= width) footer |= k_EOLN_ID << 8;`
> ``
> `// Append header/footer ID to output buffer`
> `**outBufPtr = footer;`
> `(*outBufPtr)++;`
> `}```

> `//////////////////////////////////////////////////////////////////////////////`
> `void spriteutils_EncodeCopyRun(Pixel32 **inBuf, sint32 *pos, sint32 width, Pixel16 **outBufPtr)`
> `{`
> `Pixel16 pix16;`
> `uint8 alpha;`
> `sint32 runLen = 0;`
> `Pixel16 footer=0;`
> `Pixel16 *headerPtr;`
> `Pixel16 shadowPixel;```

> `if (g_is565Format) {`
> `shadowPixel = k_SHADOW_PIXEL_565;`
> `} else {`
> `shadowPixel = k_SHADOW_PIXEL_555;`
> `}```

> `headerPtr = *outBufPtr;`
> `(*outBufPtr)++;```

> `RGB32Info(**inBuf, &pix16, &alpha);`
> `while (pix16 != shadowPixel && alpha == k_ALL_ALPHA && (*pos < width)) {```

> `// Filter pure-black`
> `if (pix16 == 0x0000) pix16 = 0x0001;```

> `// Write pixel to output buffer`
> `**outBufPtr = pix16;```

> `// Increment output buffer`
> `(*outBufPtr)++;`
> ``
> `// Increment input buffer`
> `(*inBuf)++;```

> `// Increment position counter`
> `(*pos)++;```

> `// Increment run length`
> `runLen++;```

> `RGB32Info(**inBuf, &pix16, &alpha);`
> `}`
> ``
> `// Build the tag with the ID and length`
> `footer = (Pixel16) (k_COPY_RUN_ID << 8 | runLen);```

> `// Set the high nybble of the tag if it's an EOLN condition`
> `if (*pos >= width) footer |= k_EOLN_ID << 8;```

> `*headerPtr = footer;`
> `}```

> `//////////////////////////////////////////////////////////////////////////////`
> `char spriteutils_EncodeChromakeyRun(Pixel32 **inBuf, sint32 *pos, sint32 width, Pixel16 **outBufPtr)`
> `{`
> `Pixel16 pix16;`
> `uint8 alpha;`
> `sint32 runLen = 0;`
> `Pixel16 footer=0;```

> `RGB32Info(**inBuf, &pix16, &alpha);`
> `while (pix16 == k_CHROMAKEY_PIXEL && alpha == k_NO_ALPHA && (*pos < width)) {`
> `// Increment input buffer`
> `(*inBuf)++;```

> `// Increment position counter`
> `(*pos)++;```

> `// Increment run length`
> `runLen++;```

> `RGB32Info(**inBuf, &pix16, &alpha);`
> `}```

> `// If it's a full-row transparent run, it's a skipped row`
> `if (runLen < width) {`
> `// Build header/footer ID`
> `footer = (Pixel16)(k_CHROMAKEY_RUN_ID << 8 | runLen);```

> `// Set the high nybble of the tag if it's an EOLN condition`
> `if (*pos >= width) footer |= k_EOLN_ID << 8;`
> ``
> `// Append header/footer ID to output buffer`
> `**outBufPtr = footer;`
> `(*outBufPtr)++;`
> `} else {`
> `// return TRUE that it's an empty row`
> `return TRUE;`
> `}```

> `return FALSE;`
> `}```

> `//////////////////////////////////////////////////////////////////////////////`
> `char spriteutils_EncodeChromakeyWshadowRun(Pixel32 **inBuf, sint32 *pos, sint32 width, Pixel16 **outBufPtr)`
> `{`
> `Pixel16 pix16;`
> `uint8 alpha;`
> `sint32 runLen = 0;`
> `Pixel16 footer=0;```

> `RGB32Info(**inBuf, &pix16, &alpha);`
> `while ( ((pix16 == k_CHROMAKEY_PIXEL && alpha == k_NO_ALPHA) || (pix16 == k_SHADOWBACKGD_PIXEL)) && (*pos < width) ) {`
> `// Increment input buffer`
> `(*inBuf)++;```

> `// Increment position counter`
> `(*pos)++;```

> `// Increment run length`
> `runLen++;```

> `RGB32Info(**inBuf, &pix16, &alpha);`
> `}```

> `// If it's a full-row transparent run, it's a skipped row`
> `if (runLen < width) {`
> `// Build header/footer ID`
> `footer = (Pixel16)(k_CHROMAKEY_RUN_ID << 8 | runLen);```

> `// Set the high nybble of the tag if it's an EOLN condition`
> `if (*pos >= width) footer |= k_EOLN_ID << 8;`
> ``
> `// Append header/footer ID to output buffer`
> `**outBufPtr = footer;`
> `(*outBufPtr)++;`
> `} else {`
> `// return TRUE that it's an empty row`
> `return TRUE;`
> `}```

> `return FALSE;`
> `}```

> `//////////////////////////////////////////////////////////////////////////////`
> `void spriteutils_EncodeFeatheredRun(Pixel32 **inBuf, sint32 *pos, sint32 width, Pixel16 **outBufPtr)`
> `{`
> `Pixel16 pix16;`
> `Pixel16 footer=0;`
> `uint8 alpha;```

> `RGB32Info(**inBuf, &pix16, &alpha);```

> `(*inBuf)++;`
> `(*pos)++;```

> `footer = (k_FEATHERED_RUN_ID << 8) | alpha;```

> `// Set the high nybble of the tag if it's an EOLN condition`
> `if (*pos >= width)`
> `footer |= k_EOLN_ID << 8;```

> `// Write leading footer tag`
> `**outBufPtr = footer;`
> `(*outBufPtr)++;```

> `// Write pixel value`
> `**outBufPtr = pix16;`
> `(*outBufPtr)++;```

> `}```

> `//////////////////////////////////////////////////////////////////////////////`
> `// this will encode a normal image with shadow merged into it.`
> `char spriteutils_EncodeScanline(Pixel32 *scanline, sint32 width, Pixel16 **outBufPtr)`
> `{`
> `Pixel16 pix16;`
> `Pixel32 pix32;`
> `Pixel32 *scanPtr = scanline;`
> `uint8 alpha;`
> `sint32 pos;`
> `Pixel16 *startPtr;`
> `BOOL empty;`
> `Pixel16 shadowPixel;```

> `if (g_is565Format) {`
> `shadowPixel = k_SHADOW_PIXEL_565;`
> `} else {`
> `shadowPixel = k_SHADOW_PIXEL_555;`
> `}`
> `` ``

> `pos = 0;```

> `// Save starting position of the scanline's data stream`
> `startPtr = *outBufPtr;```

> `// EOLN needs to be at both ends```

> `while (scanPtr < (scanline + width)) {`
> `pix32 = *scanPtr;`
> ``
> `empty = FALSE;```

> `RGB32Info(pix32, &pix16, &alpha);```

> `if (pix16 == k_CHROMAKEY_PIXEL && alpha == k_NO_ALPHA)`
> `{`
> `// Whitespace Run`
> `empty = spriteutils_EncodeChromakeyRun(&scanPtr, &pos, width, outBufPtr);`
> `}`
> `else`
> `if (pix16 == shadowPixel) {`
> `// Shadow Run`
> `spriteutils_EncodeShadowRun(&scanPtr, &pos, width, outBufPtr);`
> `}`
> `else`
> `if (alpha != k_NO_ALPHA && alpha != k_ALL_ALPHA) {`
> `// Feathered pixel`
> `spriteutils_EncodeFeatheredRun(&scanPtr, &pos, width, outBufPtr);`
> `}`
> `else {`
> `// Jus' a plain ol' pixel. This is a copy run.`
> `if (alpha == k_ALL_ALPHA)`
> `spriteutils_EncodeCopyRun(&scanPtr, &pos, width, outBufPtr);`
> `else {`
> `printf("\nError in bitmap data. Pixel with no associated alpha.\n");`
> `exit(-1);`
> `}`
> `}`
> `}```

> `return empty;`
> `}```

> `//////////////////////////////////////////////////////////////////////////////`
> `// this will encode a shadow just like a regular image, taking into account shadow's with white backgrounds`
> `char spriteutils_EncodeScanlineWshadow(Pixel32 *scanline, sint32 width, Pixel16 **outBufPtr)`
> `{`
> `Pixel16 pix16;`
> `Pixel32 pix32;`
> `Pixel32 *scanPtr = scanline;`
> `uint8 alpha;`
> `sint32 pos;`
> `Pixel16 *startPtr;`
> `BOOL empty;`
> `Pixel16 shadowPixel;```

> `if (g_is565Format) {`
> `shadowPixel = k_SHADOW_PIXEL_565;`
> `} else {`
> `shadowPixel = k_SHADOW_PIXEL_555;`
> `}`
> `` ``

> `pos = 0;```

> `// Save starting position of the scanline's data stream`
> `startPtr = *outBufPtr;```

> `// EOLN needs to be at both ends```

> `while (scanPtr < (scanline + width)) {`
> `pix32 = *scanPtr;`
> ``
> `empty = FALSE;```

> `RGB32Info(pix32, &pix16, &alpha);```

> `if ( (pix16 == k_CHROMAKEY_PIXEL && alpha == k_NO_ALPHA) || (pix16 == k_SHADOWBACKGD_PIXEL) )`
> `{`
> `// Whitespace Run`
> `empty = spriteutils_EncodeChromakeyWshadowRun(&scanPtr, &pos, width, outBufPtr);`
> `}`
> `else`
> `if (pix16 == shadowPixel) {`
> `// Shadow Run`
> `spriteutils_EncodeShadowRun(&scanPtr, &pos, width, outBufPtr);`
> `}`
> `else`
> `if (alpha != k_NO_ALPHA && alpha != k_ALL_ALPHA) {`
> `// Feathered pixel`
> `spriteutils_EncodeFeatheredRun(&scanPtr, &pos, width, outBufPtr);`
> `}`
> `else {`
> `// Jus' a plain ol' pixel. This is a copy run.`
> `if (alpha == k_ALL_ALPHA)`
> `spriteutils_EncodeCopyRun(&scanPtr, &pos, width, outBufPtr);`
> `else {`
> `printf("\nError in bitmap data. Pixel with no associated alpha.\n");`
> `exit(-1);`
> `}`
> `}`
> `}```

> `return empty;`
> `}```

> `//////////////////////////////////////////////////////////////////////////////`
> `void spriteutils_MergeShadowMap(Pixel32 *buf, Pixel32 *shadowBuf, uint16 width, uint16 height)`
> `{`
> `Pixel32 *pixPtr, pix;`
> `Pixel32 *shadowPixPtr, shadowPix;```

> `// if the upper-left pixel is pure white, assume this is a white background with a black shadow on it`
> `// otherwise, it's a black background with a pure-magenta shadow on it`
> `BOOL whiteBackground = FALSE;`
> `if ((*shadowBuf & 0x00FFFFFF) == 0x00FFFFFF) {`
> `whiteBackground = TRUE;`
> `} else {`
> `if ((*shadowBuf & 0x00FFFFFF) != 0x00000000) {`
> `printf("\nShadow file is in invalid format.\n");`
> `exit(-1);`
> `}`
> `}```

> `for (sint32 j=0; j<height; j++) {`
> `for (sint32 i=0; i<width; i++) {`
> `pixPtr = buf + j*width + i;`
> `shadowPixPtr = shadowBuf + j*width + i;```

> `pix = *pixPtr;`
> `shadowPix = *shadowPixPtr;`
> `shadowPix = shadowPix & 0x00FFFFFF;```

> `if (whiteBackground) {`
> `// See if there's shadow information there`
> `if (shadowPix != 0x00FFFFFF) {`
> `// There's a shadow pixel, copy it over to the source image's bitmap`
> `// only if there's null alpha`
> `Pixel16 r, g, b, a;```

> `RGB32Components(pix, &r, &g, &b, &a);```

> `// check against empty and full alpha`
> `if (a != 0xFF) {`
> `*pixPtr = 0x00FF00FF;`
> `}`
> `}`
> `} else {`
> `// See if there's shadow information there`
> `if (shadowPix) {`
> `// There's a shadow pixel, copy it over to the source image's bitmap`
> `// only if there's null alpha`
> `Pixel16 r, g, b, a;```

> `RGB32Components(pix, &r, &g, &b, &a);```

> `// check against empty and full alpha`
> `if (a != 0xFF) {`
> `*pixPtr = shadowPix;`
> `}`
> `}`
> `}`
> `}`
> `}`
> `}```

> `//////////////////////////////////////////////////////////////////////////////`
> `// this takes an image and a shadow and makes one image with them`
> `Pixel16 *spriteutils_RGB32ToEncoded(Pixel32 *buf, Pixel32 *shadowBuf, uint16 width, uint16 height)`
> `{`
> `Pixel32 *srcPixel = buf;`
> `Pixel16 *outBuf = new Pixel16[(1+height+width*height)*8];`
> `Pixel16 *returnBuf = NULL;`
> `uint16 *table = (uint16 *)outBuf;`
> `Pixel16 *startOfData;`
> `Pixel16 *dataPtr, *startDataPtr;`
> `BOOL empty;`
> `` ``

> `// One solution to the shadow encoding problem is to merge the shadow information sint32o the source bitmap`
> `if (shadowBuf != NULL)`
> `spriteutils_MergeShadowMap(buf, shadowBuf, width, height);```

> `// Write the height of the sprite as the first 16 bits of the table data`
> `*table++ = (uint16)height;```

> `startOfData = outBuf + 1 + height;`
> `dataPtr = startOfData;```

> `for(sint32 y=0; y<height; y++) {`
> `// Start at the beginning of the scanline`
> `srcPixel = buf + width * y;```

> `startDataPtr = dataPtr;```

> `// Encode runs for this line`
> `empty = spriteutils_EncodeScanline(srcPixel, width, &dataPtr);`
> `if (empty) {`
> `*table++ = k_EMPTY_TABLE_ENTRY;`
> `} else {`
> `// Write the line start sint32o the table`
> `*table++ = startDataPtr - startOfData;`
> `}`
> `}```

> `sint32 resultSize = (dataPtr - outBuf);```

> `returnBuf = new Pixel16[resultSize];```

> `memcpy(returnBuf, outBuf, resultSize * sizeof(Pixel16));```

> `return (Pixel16 *)returnBuf;`
> `}```

> `//////////////////////////////////////////////////////////////////////////////`
> `// this takes any buffer and encodes it as it's own image; Including shadows treated as seperate images`
> `Pixel16 *spriteutils_RGB32ToEncoded(Pixel32 *buf, uint16 width, uint16 height)`
> `{`
> `Pixel32 *srcPixel = buf;`
> `Pixel16 *outBuf = new Pixel16[(1+height+width*height)*8];`
> `Pixel16 *returnBuf = NULL;`
> `uint16 *table = (uint16 *)outBuf;`
> `Pixel16 *startOfData;`
> `Pixel16 *dataPtr, *startDataPtr;`
> `BOOL empty;`
> `` ``

> `// Write the height of the sprite as the first 16 bits of the table data`
> `*table++ = (uint16)height;```

> `startOfData = outBuf + 1 + height;`
> `dataPtr = startOfData;```

> `for(sint32 y=0; y<height; y++) {`
> `// Start at the beginning of the scanline`
> `srcPixel = buf + width * y;```

> `startDataPtr = dataPtr;```

> `// Encode runs for this line`
> `empty = spriteutils_EncodeScanlineWshadow(srcPixel, width, &dataPtr);`
> `if (empty) {`
> `*table++ = k_EMPTY_TABLE_ENTRY;`
> `} else {`
> `// Write the line start sint32o the table`
> `*table++ = startDataPtr - startOfData;`
> `}`
> `}```

> `sint32 resultSize = (dataPtr - outBuf);```

> `returnBuf = new Pixel16[resultSize];```

> `memcpy(returnBuf, outBuf, resultSize * sizeof(Pixel16));```

> `return (Pixel16 *)returnBuf;`
> `}```

> `//////////////////////////////////////////////////////////////////////////////`
> `void spriteutils_CreateQuarterSize(Pixel32 *srcBuf, sint32 srcWidth, sint32 srcHeight, Pixel32 **destBuf, BOOL aa)`
> `{`
> `sint32 destWidth = srcWidth / 2;`
> `sint32 destHeight = srcHeight / 2;`
> `sint32 i,j;`
> `Pixel32 pixel, pixel1, pixel2, pixel3, pixel4;`
> `Pixel32 *outBuf;```

> `outBuf = (Pixel32 *)malloc(destWidth * destHeight * sizeof(Pixel32) );`
> ``
> `for (i=0; i<destHeight; i++) {`
> `for (j=0; j<destWidth; j++) {`
> `pixel1 = srcBuf[(i * 2) * srcWidth + (j * 2)];```

> `if (aa) {`
> `pixel2 = srcBuf[(i * 2) * srcWidth + (j * 2) + 1];`
> `pixel3 = srcBuf[((i * 2) + 1) * srcWidth + (j * 2)];`
> `pixel4 = srcBuf[((i * 2) + 1) * srcWidth + (j * 2) + 1];```

> `pixel = spriteutils_AveragePixel32(pixel1, pixel2, pixel3, pixel4);`
> `} else {`
> `pixel = pixel1;`
> `}```

> `outBuf[i*destWidth + j] = pixel;`
> `}`
> `}`
> ``
> `*destBuf = outBuf;`
> `}`