Sorry abuot the subject had to get your attention
Well, here's the gory details about the spr format:
Well, here's the gory details about the spr format:
Code:
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
Comment