home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / s1 / sesanim / !SESanim / Sources / c / savesprite < prev    next >
Text File  |  1997-05-11  |  5KB  |  215 lines

  1. /* SaveSprite.c */
  2.  
  3. /* Saving an anim as a RiscOS sprite file
  4.  * (K) All Rites Reversed - Copy What You Like (see file Copying)
  5.  *
  6.  * Authors:
  7.  *      Peter Hartley       <peter@ant.co.uk>
  8.  *
  9.  * History:
  10.  *      23-Oct-96 pdh Started
  11.  *      27-Oct-96 pdh Frob to cope with 3/5/6/7bpp anim's
  12.  *      27-Oct-96 *** Release 4beta1
  13.  *      29-Oct-96 pdh Fix mask code so it expands to whole pixels properly
  14.  *      29-Oct-96 *** Release 4beta2
  15.  *      07-Nov-96 *** Release 4
  16.  *      15-Dec-96 *** Release 5beta1
  17.  *      01-Jan-97 pdh Fix bug in saving 2bpp sprites
  18.  *      27-Jan-97 *** Release 5beta2
  19.  *      29-Jan-97 *** Release 5beta3
  20.  *      03-Feb-97 *** Release 5
  21.  *      07-Feb-97 *** Release 5.01
  22.  *
  23.  */
  24.  
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28.  
  29. #include "DeskLib:Sprite.h"
  30.  
  31. #include "bitmap.h"
  32. #include "count.h"
  33. #include "utils.h"
  34.  
  35. #if 0
  36. #define debugf printf
  37. #define DEBUG 1
  38. #else
  39. #define debugf 1?0:printf
  40. #define DEBUG 0
  41. #endif
  42.  
  43.  
  44. void CompressSpriteLine( char *dest, char *src, int n, int bpp )
  45. {
  46.     int i;
  47.  
  48.     switch ( bpp )
  49.     {
  50.     case 8:
  51.         memcpy( dest, src, n );
  52.         break;
  53.     case 4:
  54.         for ( i=0; i< (n+1)/2; i++ )
  55.             dest[i] = src[i<<1] + ( src[(i<<1)+1] << 4 );
  56.         break;
  57.     case 2:
  58.         memset( dest, 0, (n+3)/4 );
  59.         for ( i=0; i<n; i++ )
  60.             dest[i>>2] |= (src[i]) << ((i&3)*2);
  61.         break;
  62.     case 1:
  63.         memset( dest, 0, (n+7)/8 );
  64.         for ( i=0; i<n; i++ )
  65.             dest[i>>3] |= (src[i]) << (i&7);
  66.         break;
  67.     }
  68. }
  69.  
  70. void CompressMaskLine( char *dest, char *src, int n, int bpp )
  71. {
  72.     int i;
  73.  
  74.     switch ( bpp )
  75.     {
  76.     case 8:
  77.         for ( i=0; i<n; i++ )
  78.             dest[i] = ( src[i] ) ? 0xFF : 0;
  79.         break;
  80.     case 4:
  81.         for ( i=0; i< (n+1)/2; i++ )
  82.             dest[i] =     ( src[i<<1]     ? 0xF : 0 )
  83.                       + ( ( src[(i<<1)+1] ? 0xF : 0 ) << 4 );
  84.         break;
  85.     case 2:
  86.         memset( dest, 0, (n+3)/4 );
  87.         for ( i=0; i<n; i++ )
  88.             dest[i>>2] |= ( src[i] ? 3 : 0 ) << ((i&3)*2);
  89.         break;
  90.     case 1:
  91.         memset( dest, 0, (n+7)/8 );
  92.         for ( i=0; i<n; i++ )
  93.             dest[i>>3] |= (src[i]) << (i&7);
  94.         break;
  95.     }
  96. }
  97.  
  98. /* Sprites are only available in 1, 2, 4, 8 bpp */
  99. const char bppmap[8] = { 1, 2, 4, 4, 8, 8, 8, 8 };
  100.  
  101. BOOL Anim_MakeSprite( anim a, FILE *output )
  102. {
  103.     sprite_areainfo sai;
  104.     sprite_header *psh;
  105.     int nSpriteSize;
  106.     int i,y;
  107.     int newbpp;
  108.     int abw;
  109.     void *data;
  110. /*    unsigned int palette[256];*/
  111.     int newncol;
  112.     frameptr f2 = Anim_OpenFrame( a, 0 );
  113.     int nFrames = a->nFrames;
  114.  
  115.     if ( !f2 )
  116.     {
  117.         /* There was an error */
  118.         return FALSE;
  119.     }
  120.  
  121.     newbpp = bppmap[ MinBpp( f2->nColours ) - 1 ];
  122.     newncol = 1 << newbpp;
  123.     abw = ( ( (a->nWidth*newbpp)+31 ) >> 3 ) & ~3;  /* aligned byte width */
  124.  
  125.     nSpriteSize = abw;
  126.     nSpriteSize *= a->nHeight;
  127.     nSpriteSize *= 2;
  128.     nSpriteSize += 8*newncol;
  129.     nSpriteSize += sizeof( sprite_header );
  130.  
  131.     Anim_CloseFrame( a, &f2 );
  132.  
  133.     /* Write the header */
  134.     sai.numsprites = nFrames;
  135.     sai.firstoffset = 16;
  136.     sai.freeoffset = 16 + nFrames*nSpriteSize;
  137.     fwrite( &sai.numsprites, 1, 12, output );
  138.  
  139.     data = Anim_Allocate( nSpriteSize );
  140.     if ( !data )
  141.     {
  142.         Anim_NoMemory( "savesprite" );
  143.         return FALSE;
  144.     }
  145.  
  146.     psh = (sprite_header*) data;
  147.  
  148.     /* Write the frames */
  149.     psh->offset_next = nSpriteSize;
  150.     psh->width = (abw>>2)-1;
  151.     psh->height = a->nHeight-1;
  152.     psh->leftbit = 0;
  153.     psh->rightbit = (a->nWidth*newbpp - 1 ) & 31;
  154.     psh->imageoffset = sizeof(sprite_header) + 8*newncol;
  155.     psh->maskoffset = psh->imageoffset + abw*a->nHeight;
  156.     switch ( newbpp )
  157.     {
  158.     case 1: psh->screenmode = 18; break;
  159.     case 2: psh->screenmode = 19; break;
  160.     case 4: psh->screenmode = 20; break;
  161.     case 8: psh->screenmode = 21; break;
  162.     }
  163.  
  164.     for ( i=0; i < a->nFrames; i++ )
  165.     {
  166.         frameptr f = Anim_OpenFrame( a, i );
  167.         char *src;
  168.         char *dest;
  169.         unsigned int *pPal = (unsigned int*)(psh+1);
  170.         int delay;
  171.  
  172.         if ( !f )
  173.         {
  174.             Anim_Free( &data );
  175.             return FALSE;
  176.         }
  177.  
  178.         src = f->pImage;
  179.         memset( psh->name, 0, 12 );
  180.         delay = Anim_GetDelay( a, i, -1 );
  181.         if ( delay != -1 )
  182.             sprintf( psh->name, "%03ddelay%d", i, delay );
  183.         else
  184.             sprintf( psh->name, "%03d", i );
  185.  
  186.         for ( y=0; y < f->nColours; y++ )       /* NOT newncol */
  187.         {
  188.             *pPal++ = f->pPalette[y];
  189.             *pPal++ = f->pPalette[y];
  190.         }
  191.  
  192.         src = f->pImage;
  193.         dest = ((char*)(psh+1)) + newncol*8;
  194.         for ( y=0; y < a->nHeight; y++ )
  195.         {
  196.             CompressSpriteLine( dest, src, a->nWidth, newbpp );
  197.             dest += abw;
  198.             src += a->nWidth;
  199.         }
  200.  
  201.         src = f->pMask;
  202.         for ( y=0; y < a->nHeight; y++ )
  203.         {
  204.             CompressMaskLine( dest, src, a->nWidth, newbpp );
  205.             dest += abw;
  206.             src += a->nWidth;
  207.         }
  208.  
  209.         Anim_CloseFrame( a, &f );
  210.         fwrite( data, 1, nSpriteSize, output );
  211.     }
  212.     Anim_Free( &data );
  213.     return TRUE;
  214. }
  215.