/* * FLI playing code originally by zoombapup/zen * Greatly cleaned up and improved by Sol/hsa (it might actually work now) * Lots of stupid irrelevant stuff nuked. FLC compatibility added as well. * Converted to textmode. */ /*************************************************************************/ /* Includes */ /*************************************************************************/ #include #include #include #include #include #include "textfx.h" /*************************************************************************/ /* Typedefs (structures) */ /*************************************************************************/ #pragma pack(1); typedef struct { /* fli header */ int fli_size; short int fli_magic; short int fli_frames; short int width; short int height; short int depth; short int flags; /* if 3, last frame should be same as first frame */ short int speed; short int reserved1; int created; int creator; int updated; int updater; short int aspectx; short int aspecty; 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; char * flicdata; char * palette; int palette_change; /* changes to 1 if palette changes */ int x_size; int y_size; int curframe; int maxframe; int looped; char * nextframe; char * loopframe; } FLIDATA; #pragma pack(); /*************************************************************************/ /* FLI decoder functions (relevant) */ /*************************************************************************/ unsigned char *decode_chunk(unsigned char *thischunk, FLIDATA * flidata) { CHUNKHEADER *chunkhead; unsigned char *nextchunk; unsigned char *chunkdata; chunkhead=(CHUNKHEADER *)thischunk; nextchunk=thischunk+chunkhead->size; chunkdata=thischunk+6; switch (chunkhead->type) { case 4: /* 256-level palette */ fli_colour256(chunkdata,flidata); break; case 7: /* 16b-based delta */ 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 */ break; default: /* unknown/irrelevant */ break; } return(nextchunk); } 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); } void fli_black(FLIDATA * flidata) { memset(flidata->framebuffer,0,flidata->x_size*flidata->y_size); } void fli_copy(unsigned char *data,FLIDATA * flidata) { memcpy(flidata->framebuffer,data,flidata->x_size*flidata->y_size); } void fli_colour(unsigned char *cdata,FLIDATA * flidata) { short int *pktaddress; unsigned char skip; unsigned char set; short int numberpk; short int packetcount; int a; pktaddress=(short int *)cdata; cdata++; cdata++; 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); } } } void fli_colour256(unsigned char *cdata, FLIDATA * flidata) { short int *pktaddress; unsigned char skip; int set; short int numberpk; short int packetcount; int a; pktaddress=(short int *)cdata; cdata++; cdata++; 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); } } } void fli_rc(unsigned char*lcdata, FLIDATA * flidata) { 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; } } void fli_ss2(unsigned char*lcdata, FLIDATA * flidata) { 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; } } void fli_brun(unsigned char*brundata, FLIDATA * flidata) { 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;sizecountflicdata=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; } } /*****************************************************************/ /* Other functions (Not required by FLI decoder itself) */ /*****************************************************************/ void waitframes(int numframes) { for (;numframes;numframes--) { waitVR(); } } void waitVR(void) { while (inp(0x3da) & 8); while (!(inp(0x3da) & 8)); } void vga_setmode(int mode) { union REGS r; r.h.ah = 0x00; r.h.al = mode; int386(0x10,&r,&r); } void vga_setpal(char *pal) { int i; outp(0x3c8,0x00); for (i = 0; i < 768; i++) outp(0x3c9,pal[i]); } short int textpalette[256]; void fli_frame2text(FLIDATA *flidata) { int x,y; for (y=0;y<43;y++) for (x=0;x<80;x++) *(short int *)(0xb8000+y*160+x*2)=textpalette[*(flidata->framebuffer+y*flidata->x_size+x)]; } void main(int argc,char **argv) { FLIDATA * flikki; int a; int speed; if (argc<2) { cprintf("------------------------------------------------------------------------------\r\n" "TXTFLI - 80x43 Textmode Fli/Flc player by Sol_HSA aka Sol of Hysteria and DEE.\r\n" "\r\n" "Usage: TXTFLI <.fli/flc file of any size> \r\n" "(speed = retraces to wait before next frame)\r\n" "------------------------------------------------------------------------------\r\n"); } else { flikki=fli_open(argv[1],0); /* can be changed to load from lib for instance */ speed=5; if (argc>2) speed=strtol(argv[2],0,10); set80x43(); memset(textpalette,0,256*2); while (!kbhit()) { fli_renderframe(flikki); /* renders a frame into framebuffer */ if (!flikki->looped) if (flikki->palette_change) { /* as renderframe doesn't touch palette, */ for (a=0;a<256;a++) /* we have to do it here. */ textpalette[a]=calcpal(*(flikki->palette+a*3+0), *(flikki->palette+a*3+1), *(flikki->palette+a*3+2)); flikki->palette_change=0; } fli_frame2text(flikki); waitframes(speed); /* screen, and handle delay. */ } fli_zap(flikki); /* this deallocates framebuffer etc */ set80x25(); cprintf("Remember: EVERYTHING looks good while viewed from 20 meters in free fall.\r\n"); } }