Announcement

Collapse
No announcement yet.

Want CTP sprites in Civ?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Want CTP sprites in Civ?

    Sorry abuot the subject had to get your attention

    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
    
    Last edited by heardie; November 18, 2001, 19:23.

  • #2
    It would be great if someone could figure out how to use the CTP & CTPII sprites.

    Comment


    • #3
      FYI, the sprites consist of (usually) :

      All picture files should be 96*72 *.tif files, with alpha channels containing all non-black pixels.

      Graphic:
      up to 10 movement frames
      up to 10 attack frames
      up to 10 'work' frames (optional) (I think only unconventional units have these)
      up to 10 death frames
      up to 10 victory frames (optional) (non-combat units do not have these)

      Shadow:
      one shadow for every frame of actual graphic.

      Possibly Script. text file script to detail how to encode the sprite. It may or may not get encoded into the sprite, certainly it is neccessary to make the sprite, and detail what the sprite consists of.

      If anyone wants to try this, it would be very cool.

      Also, I suspect heardie's long description is incomplete, so I attatch the full readme for making sprites, with description of C++ encoding in section 5.0
      Attached Files
      Concrete, Abstract, or Squoingy?
      "I don't believe in giving scripting languages because the only additional power they give users is the power to create bugs." - Mike Breitkreutz, Firaxis

      Comment


      • #4
        Originally posted by Immortal Wombat

        Also, I suspect heardie's long description is incomplete, so I attatch the full readme for making sprites, with description of C++ encoding in section 5.0
        Yep, mines only section 5.0

        Comment


        • #5
          Yeah, but it cuts out in the middle of a for{ loop...
          Concrete, Abstract, or Squoingy?
          "I don't believe in giving scripting languages because the only additional power they give users is the power to create bugs." - Mike Breitkreutz, Firaxis

          Comment


          • #6
            That's true, and it won't let m edit in the rest...?

            Comment


            • #7
              Character limit on posts
              Concrete, Abstract, or Squoingy?
              "I don't believe in giving scripting languages because the only additional power they give users is the power to create bugs." - Mike Breitkreutz, Firaxis

              Comment

              Working...
              X