home *** CD-ROM | disk | FTP | other *** search
- /* SaveSprite.c */
-
- /* Saving an anim as a RiscOS sprite file
- * (K) All Rites Reversed - Copy What You Like (see file Copying)
- *
- * Authors:
- * Peter Hartley <peter@ant.co.uk>
- *
- * History:
- * 23-Oct-96 pdh Started
- * 27-Oct-96 pdh Frob to cope with 3/5/6/7bpp anim's
- * 27-Oct-96 *** Release 4beta1
- * 29-Oct-96 pdh Fix mask code so it expands to whole pixels properly
- * 29-Oct-96 *** Release 4beta2
- * 07-Nov-96 *** Release 4
- * 15-Dec-96 *** Release 5beta1
- * 01-Jan-97 pdh Fix bug in saving 2bpp sprites
- * 27-Jan-97 *** Release 5beta2
- * 29-Jan-97 *** Release 5beta3
- * 03-Feb-97 *** Release 5
- * 07-Feb-97 *** Release 5.01
- *
- */
-
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
-
- #include "DeskLib:Sprite.h"
-
- #include "bitmap.h"
- #include "count.h"
- #include "utils.h"
-
- #if 0
- #define debugf printf
- #define DEBUG 1
- #else
- #define debugf 1?0:printf
- #define DEBUG 0
- #endif
-
-
- void CompressSpriteLine( char *dest, char *src, int n, int bpp )
- {
- int i;
-
- switch ( bpp )
- {
- case 8:
- memcpy( dest, src, n );
- break;
- case 4:
- for ( i=0; i< (n+1)/2; i++ )
- dest[i] = src[i<<1] + ( src[(i<<1)+1] << 4 );
- break;
- case 2:
- memset( dest, 0, (n+3)/4 );
- for ( i=0; i<n; i++ )
- dest[i>>2] |= (src[i]) << ((i&3)*2);
- break;
- case 1:
- memset( dest, 0, (n+7)/8 );
- for ( i=0; i<n; i++ )
- dest[i>>3] |= (src[i]) << (i&7);
- break;
- }
- }
-
- void CompressMaskLine( char *dest, char *src, int n, int bpp )
- {
- int i;
-
- switch ( bpp )
- {
- case 8:
- for ( i=0; i<n; i++ )
- dest[i] = ( src[i] ) ? 0xFF : 0;
- break;
- case 4:
- for ( i=0; i< (n+1)/2; i++ )
- dest[i] = ( src[i<<1] ? 0xF : 0 )
- + ( ( src[(i<<1)+1] ? 0xF : 0 ) << 4 );
- break;
- case 2:
- memset( dest, 0, (n+3)/4 );
- for ( i=0; i<n; i++ )
- dest[i>>2] |= ( src[i] ? 3 : 0 ) << ((i&3)*2);
- break;
- case 1:
- memset( dest, 0, (n+7)/8 );
- for ( i=0; i<n; i++ )
- dest[i>>3] |= (src[i]) << (i&7);
- break;
- }
- }
-
- /* Sprites are only available in 1, 2, 4, 8 bpp */
- const char bppmap[8] = { 1, 2, 4, 4, 8, 8, 8, 8 };
-
- BOOL Anim_MakeSprite( anim a, FILE *output )
- {
- sprite_areainfo sai;
- sprite_header *psh;
- int nSpriteSize;
- int i,y;
- int newbpp;
- int abw;
- void *data;
- /* unsigned int palette[256];*/
- int newncol;
- frameptr f2 = Anim_OpenFrame( a, 0 );
- int nFrames = a->nFrames;
-
- if ( !f2 )
- {
- /* There was an error */
- return FALSE;
- }
-
- newbpp = bppmap[ MinBpp( f2->nColours ) - 1 ];
- newncol = 1 << newbpp;
- abw = ( ( (a->nWidth*newbpp)+31 ) >> 3 ) & ~3; /* aligned byte width */
-
- nSpriteSize = abw;
- nSpriteSize *= a->nHeight;
- nSpriteSize *= 2;
- nSpriteSize += 8*newncol;
- nSpriteSize += sizeof( sprite_header );
-
- Anim_CloseFrame( a, &f2 );
-
- /* Write the header */
- sai.numsprites = nFrames;
- sai.firstoffset = 16;
- sai.freeoffset = 16 + nFrames*nSpriteSize;
- fwrite( &sai.numsprites, 1, 12, output );
-
- data = Anim_Allocate( nSpriteSize );
- if ( !data )
- {
- Anim_NoMemory( "savesprite" );
- return FALSE;
- }
-
- psh = (sprite_header*) data;
-
- /* Write the frames */
- psh->offset_next = nSpriteSize;
- psh->width = (abw>>2)-1;
- psh->height = a->nHeight-1;
- psh->leftbit = 0;
- psh->rightbit = (a->nWidth*newbpp - 1 ) & 31;
- psh->imageoffset = sizeof(sprite_header) + 8*newncol;
- psh->maskoffset = psh->imageoffset + abw*a->nHeight;
- switch ( newbpp )
- {
- case 1: psh->screenmode = 18; break;
- case 2: psh->screenmode = 19; break;
- case 4: psh->screenmode = 20; break;
- case 8: psh->screenmode = 21; break;
- }
-
- for ( i=0; i < a->nFrames; i++ )
- {
- frameptr f = Anim_OpenFrame( a, i );
- char *src;
- char *dest;
- unsigned int *pPal = (unsigned int*)(psh+1);
- int delay;
-
- if ( !f )
- {
- Anim_Free( &data );
- return FALSE;
- }
-
- src = f->pImage;
- memset( psh->name, 0, 12 );
- delay = Anim_GetDelay( a, i, -1 );
- if ( delay != -1 )
- sprintf( psh->name, "%03ddelay%d", i, delay );
- else
- sprintf( psh->name, "%03d", i );
-
- for ( y=0; y < f->nColours; y++ ) /* NOT newncol */
- {
- *pPal++ = f->pPalette[y];
- *pPal++ = f->pPalette[y];
- }
-
- src = f->pImage;
- dest = ((char*)(psh+1)) + newncol*8;
- for ( y=0; y < a->nHeight; y++ )
- {
- CompressSpriteLine( dest, src, a->nWidth, newbpp );
- dest += abw;
- src += a->nWidth;
- }
-
- src = f->pMask;
- for ( y=0; y < a->nHeight; y++ )
- {
- CompressMaskLine( dest, src, a->nWidth, newbpp );
- dest += abw;
- src += a->nWidth;
- }
-
- Anim_CloseFrame( a, &f );
- fwrite( data, 1, nSpriteSize, output );
- }
- Anim_Free( &data );
- return TRUE;
- }
-