/* Original code by zoombapup/zen. * Reworked by Sol/Trauma, adding FLC support and other functionality. * (Also cleaned up, but remember, obfuscation is in the eye of the beholder =)) * * ** public domain ** * * Version=1.2 * * Revision history * 1.2 - Further cleanup, separated textmode stuff to different file. * 1.1 - Added FLC support. Released. * 1.0 - Cleaned up zoombapup's source, nuking lots of irrelevant stuff. * - Added FLIDATA structure to gain re-entrancy. */ #include #include #include #include #include #pragma pack(1); /* Pack structure members to 1 byte boundaries */ typedef struct { /* fli header */ int fli_size; /* Should be same as file size. */ short int fli_magic; /* 0AF12h */ short int fli_frames; /* Frames in flic, 4000 max */ short int width; /* x size */ short int height;/* y size */ short int depth; /* bits per pixel, always 8 in fli/flc */ short int flags; /* Bitmapped flags. 0=ring frame, 1=header updated */ short int speed; /* Delay between frames in ms (or retraces :)) */ short int reserved1; int created; /* MS-dos date of creation */ int creator; /* SerNo of animator, 0464c4942h for FlicLib */ int updated; /* MS-dos date of last modify */ int updater; /* .. */ short int aspectx; /* x-axis aspect ratio (320x200: 6)*/ short int aspecty; /* y-axis aspect ratio (320x200: 5)*/ char reserved2[38]; int oframe1; /* offset to frame 1 */ int oframe2; /* offset to frame 2 - for looping, jump here */ char reserved3[42]; } FLIHEADER; typedef struct { /* frame header */ int framesize; unsigned short int magic; short int chunks; unsigned char reserved[8]; } FRAMEHEADER; typedef struct { /* chunk header */ int size; short int type; } CHUNKHEADER; typedef struct { /* FLI player interface structure */ char * framebuffer; /* Picture buffer. */ char * flicdata; /* Pointer to the (raw) fli data. */ char * palette; /* Pointer to 768 byte palette buffer. */ int palette_change; /* changes to 1 if palette changes */ int x_size; /* x-size of framebuffer */ int y_size; /* y-size of framebuffer */ int curframe; /* Current frame */ int maxframe; /* max. frame */ int looped; /* changes to 1 if we're looped. */ char * nextframe; /* Pointer to next frame in flicdata */ char * loopframe; /* Pointer to loop frame in flicdata */ } FLIDATA; #pragma pack(); /************************************************************************ ** FLI/FLC decoder functions. Part 1: chunk decoders ** *************************************************************************/ static void fli_black(FLIDATA * flidata) { /* "Set whole frame to index 0" -chunk */ memset(flidata->framebuffer,0,flidata->x_size*flidata->y_size); } static void fli_copy(unsigned char *data,FLIDATA * flidata) { /* Uncompressed frame (extremely rare) */ memcpy(flidata->framebuffer,data,flidata->x_size*flidata->y_size); } static void fli_colour(unsigned char *cdata,FLIDATA * flidata) { /* 64 - level palette chunk */ short int *pktaddress; unsigned char skip; unsigned char set; short int numberpk; short int packetcount; int a; pktaddress=(short int *)cdata; cdata+=2; numberpk=*pktaddress; for (packetcount=0;packetcountpalette+a)=*(cdata+a); flidata->palette_change=1; } else { for (a=0;apalette+skip*3+a)=*(cdata+a); flidata->palette_change=1; cdata+=(set*3); } } } static void fli_colour256(unsigned char *cdata, FLIDATA * flidata) { /* 256 - level palette chunk */ short int *pktaddress; unsigned char skip; int set; short int numberpk; short int packetcount; int a; pktaddress=(short int *)cdata; cdata+=2; numberpk=*pktaddress; for (packetcount=0;packetcountpalette+a)=*(cdata+a)/4; flidata->palette_change=1; } else { for (a=0;a<(set*3);a++) *(flidata->palette+a+skip*3)=*(cdata+a)/4; flidata->palette_change=1; cdata+=(set*3); } } } static void fli_rc(unsigned char*lcdata, FLIDATA * flidata) { /* 8b-based delta */ short int *addlines; short int numlines; unsigned char *vbuffptr; short int linecount; unsigned char pktcount,skip,numpkt,sizecount,databyte; signed char size; unsigned char *linestart; vbuffptr=flidata->framebuffer; addlines=(short int *) lcdata; numlines=*addlines; lcdata+=4; addlines+=1; vbuffptr+=numlines*flidata->x_size; numlines=*addlines; linestart=vbuffptr; for (linecount=0;linecount=0) { for (sizecount=0;sizecountx_size; } } static void fli_ss2(unsigned char*lcdata, FLIDATA * flidata) { /* 16b-based delta (FLC only) */ short int numlines; unsigned char *vbuffptr; short int linecount; char skip; int pktcount,sizecount,databyte; short int numpkt; signed char size; unsigned char *linestart; vbuffptr=flidata->framebuffer; numlines=*(short int *)lcdata; lcdata+=2; linestart=vbuffptr; for (linecount=0;linecountx_size; } else for (pktcount=0;pktcount=0) { for (sizecount=0;sizecountx_size; } } static void fli_brun(unsigned char*brundata, FLIDATA * flidata) { /* RLE full frame */ short int numlines; unsigned char *vbuffptr; unsigned char pktcount,numpkt,sizecount; signed char size; vbuffptr=flidata->framebuffer; for (numlines=0;numlinesy_size;numlines++) { numpkt=*brundata; brundata++; for (pktcount=0;pktcount=0) { for (sizecount=0;sizecountsize; chunkdata=thischunk+6; switch (chunkhead->type) { case 4: /* 256-level palette (FLC only) */ fli_colour256(chunkdata,flidata); break; case 7: /* 16b-based delta (FLC only) */ fli_ss2(chunkdata,flidata); break; case 11: /* 64-level palette */ fli_colour(chunkdata,flidata); break; case 12: /* 8b-based delta */ fli_rc(chunkdata,flidata); break; case 13: /* full black frame */ fli_black(flidata); break; case 15: /* RLE full frame */ fli_brun(chunkdata,flidata); break; case 16: /* full frame, no compression */ fli_copy(chunkdata,flidata); break; case 18: /* postage stamp sized image - out of this routine's scope */ break; default: /* unknown/irrelevant */ break; } return(nextchunk); } static unsigned char *fli_frame(FLIDATA * flidata) { FRAMEHEADER *thisframe; unsigned char *nextframe; short int numchunks; unsigned char *thischunk; thisframe=(FRAMEHEADER *) flidata->nextframe; nextframe=flidata->nextframe; nextframe+=thisframe->framesize; thischunk=(flidata->nextframe+sizeof(FRAMEHEADER)); if (thisframe->magic==0xf1fa) for (numchunks=1;numchunks<=thisframe->chunks;numchunks++) { thischunk=decode_chunk(thischunk,flidata); } return(nextframe); } /************************************************************************ ** FLI/FLC decoder functions. Part 3: "high level" functions ** *************************************************************************/ /* This is an example only.. you can do similar fli_open functions for your own filesystem. This one works with my CompressedFileLibrary. FLIDATA * fli_open_cfl(char * filename) { FLIDATA * flidata; FLIHEADER * header; flidata=malloc(sizeof(FLIDATA)); flidata->flicdata=CFL_GetFile(filename); if (flidata->flicdata==0) { cprintf("File open error.\r\n"); exit(5); } header=(void *)flidata->flicdata; flidata->framebuffer=malloc(header->width*header->height); flidata->x_size=header->width; flidata->y_size=header->height; flidata->palette=malloc(768); flidata->palette_change=0; flidata->curframe=0; flidata->looped=0; flidata->maxframe=header->fli_frames; flidata->nextframe=flidata->flicdata+sizeof(FLIHEADER); flidata->loopframe=flidata->nextframe; memset(flidata->framebuffer,0,header->width*header->height); return(flidata); } */ FLIDATA * fli_open(char * filename,int offset) { FILE * fli_file; FLIHEADER header; FLIDATA * flidata; flidata=malloc(sizeof(FLIDATA)); fli_file=fopen(filename,"rb"); if (fli_file==0) { cprintf("File open error.\r\n"); exit(2); } fseek(fli_file,offset,SEEK_SET); fread(&header,1,sizeof(header),fli_file); flidata->framebuffer=malloc(header.width*header.height); flidata->x_size=header.width; flidata->y_size=header.height; flidata->palette=malloc(768); flidata->palette_change=0; flidata->curframe=0; flidata->looped=0; flidata->maxframe=header.fli_frames; flidata->flicdata=malloc(header.fli_size-sizeof(header)); fread(flidata->flicdata,1,header.fli_size-sizeof(header),fli_file); flidata->nextframe=flidata->flicdata; flidata->loopframe=flidata->nextframe; fclose(fli_file); memset(flidata->framebuffer,0,header.width*header.height); return(flidata); } void fli_zap(FLIDATA * flidata) { free(flidata->flicdata); free(flidata->palette); free(flidata->framebuffer); free(flidata); } void fli_renderframe(FLIDATA * flidata) { flidata->nextframe=fli_frame(flidata); flidata->curframe++; if (flidata->curframe==flidata->maxframe) { flidata->curframe=0; flidata->nextframe=flidata->loopframe; flidata->looped=1; } }