1
2 /* Copyright 1993 J. Remyn */
3 /* This program is freely distributable, but there is no warranty */
4 /* of any kind. */
5 /* version 0.3 */
6 /* Modified for aaflip version 1.0 by Jan Hubicka*/
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <sys/time.h>
11 #include <unistd.h>
12 #include <aalib.h>
13
14 #include "general.h"
15 #include "fli.h"
16
17 #define NAMELEN 256
18
19 struct OPTIONS {
20 char filename[NAMELEN]; /* filename given on command line */
21 char fast; /* 1 = play without delays */
22 char verbose; /* 1 = show info about flic file */
23 char release; /* 1 = don't keep frames in memory */
24 char firstp; /* 1 = process frames while loading */
25 char blank; /* 1 = keep black screen while loading */
26 char stdinp; /* 1 = take flic file from stdin */
27 int speed; /* speed gotten from command line (-1 if nothing gotten) */
28 int playrep; /* nr of times to play animation */
29 } options;
30
31 struct FLI_FRAMECHUNK {
32 long size; /* Size of chunk data part */
33 long file_offset; /* Offset of chunk data part into flic file */
34 int subchunks; /* Number of subchunks in data part */
35 void *cd; /* Pointer to memory containing data part, */
36 /* is NULL if data not kept in memory */
37 };
38
39 struct FLI {
40 char filename[NAMELEN]; /* filename of fli file */
41 char flc; /* 0 = fli, 1 = flc */
42 int mode; /* vgalib mode number to be used */
43 int scr_width; /* width of screen mode used */
44 int scr_height; /* guess */
45 int current; /* current frame index */
46 long time; /* time of last processed frame in usec */
47 FILE *f; /* file pointer of opened flic file */
48 struct FLI_HEADER h; /* 128 byte fli file header structure */
49 struct FLI_FRAMECHUNK *frame;
50 /* pointer to an allocated 'array' of
51 <frames> FLI_FRAMECHUNK structs */
52 } fli;
53
54
55 static aa_palette pal;
56 static aa_context *context;
57 static aa_renderparams *params;
58 static char *graph_mem;
59
60
dcd_color_64(char * data)61 static void dcd_color_64( char *data ) {
62 uchar start = 0;
63 int ops;
64 int count;
65 int i;
66 /* puts( "color_64" ); */
67 ops = *(short int *)data;
68 data = (void *)(((short int *)data) + 1);
69 while( ops-- > 0 ) {
70 start += *(uchar *)data;
71 data = (void *) ((uchar *)data + 1);
72 if( (count = (int)*(uchar *)data) == 0 )
73 count = 256;
74 data = (void *) ((uchar *)data + 1);
75 for( i=0; i<count; i++ ) {
76 /* (s)vgalib requires a table of ints for setting a group
77 * of colors quickly, but we've got a table of chars :(
78 * so we have to set each color individually (slow) */
79 aa_setpalette(pal, start + i,
80 ((int)*(uchar *)data)*4,
81 ((int)*((uchar *)data+1)*4),
82 ((int)*((uchar *)data+2)*4)
83 );
84 data = (void *)((uchar *)data + 3);
85 }
86 start += count;
87 }
88 }
89
dcd_color_256(char * data)90 static void dcd_color_256( char *data ) {
91 uchar start = 0;
92 int ops;
93 int count;
94 int i;
95 /* puts( "color_256" ); */
96 ops = *(short int *)data;
97 data = (void *)((short int *)data + 1);
98 while( ops-- > 0 ) {
99 start += *(uchar *)data;
100 data = (void *)((uchar *)data + 1);
101 if( (count = (int)*(uchar *)data) == 0 )
102 count = 256;
103 data = (void *)((uchar *)data + 1);
104 for( i=0; i<count; i++ ) {
105 aa_setpalette(pal, start + i,
106 *(uchar *)data >> 2,
107 *((uchar *)data+1) >> 2,
108 *((uchar *)data+2) >> 2
109 );
110 data = (void *)((uchar *)data + 3);
111 }
112 start += count;
113 }
114 }
115
memsetw(unsigned short * target,unsigned short w,int count)116 void *memsetw( unsigned short *target, unsigned short w, int count ) {
117 while( count-->0 ) {
118 *target++ = w;
119 }
120 return( target );
121 }
122
dcd_delta_flc(struct FLI * fli,char * data)123 static void dcd_delta_flc( struct FLI *fli, char *data ) {
124 short int line;
125 short int nrlines;
126 char *index;
127 short packets;
128 short type;
129 int x;
130 uchar lastbyte;
131 char setlastbyte;
132 /* puts( "delta flc" ); */
133 /* get nr of lines in chunk */
134 nrlines = *(short int *)data;
135 data = (void *)((short int *)data + 1);
136 line = 0;
137 setlastbyte = 0;
138 lastbyte = 0; /* this is just to get rid of a compiler warning */
139 index = graph_mem;
140
141 while( nrlines>0 ) { /* don't put nrlines-- here, the continues don't allow it */
142
143 type = *(short *)data;
144 data = (void *)((short *)data + 1);
145 /* the 2 highest bits of type indicate how to interpret it */
146 if( type<0 ) {
147 if( type&0x4000 ) {
148 /* add to the line number and act as if nothing
149 * happened.
150 * documentation says it's all right just to
151 * add the abs. value of the word, which is the
152 * same as subtracting the word as it is always
153 * negative.
154 */
155 line -= type;
156 index += fli->scr_width * (-type);
157 continue;
158 }
159 /* the low byte contains a lastbyte (the last byte
160 * on a line in odd-width resolution flic files),
161 * this word is followed by the packet count
162 */
163 setlastbyte = 1;
164 lastbyte = (uchar)(type & 0x00FF);
165 packets = *(short *)data;
166 data = (void *)((short *)data + 1);
167 /* packets can be 0 now if just the last byte
168 * changes for this line
169 */
170 }
171 if( type>=0 ) {
172 /* the word contains the nr of packets
173 * we can just assign this to packets because the
174 * high bits are zero
175 */
176 packets = type;
177 }
178
179 /* decode packets */
180 x = 0;
181 while( packets-->0 ) {
182 /* get & decode packet */
183 x += *(uchar *)data;
184 data = (void *)((uchar *)data + 1);
185 type = *(char *)data;
186 data = (void *)((uchar *)data + 1);
187 if( (char)type>=0 ) {
188 /* copy ptype words */
189 type <<= 1;
190 memcpy( index + x, data, type );
191 x += type;
192 data = (void *)((uchar *)data + type);
193 continue;
194 }
195 type = -(char)type;
196 memsetw( (ushort *)(index + x), *(ushort *)data, type );
197 x += type<<1;
198 data = (void *)((ushort *)data + 1);
199 }
200 if( !setlastbyte ) {
201 index = (char *)((uchar *)index + fli->scr_width);
202 nrlines--;
203 continue;
204 }
205 /* put lastbyte at end of line */
206 *(uchar *)(index + fli->scr_width - 1) = lastbyte;
207 setlastbyte = 0;
208 index = (char *)((uchar *)index + fli->scr_width);
209 nrlines--;
210 }
211 }
212
213
dcd_delta_fli(struct FLI * fli,char * data)214 static void dcd_delta_fli( struct FLI *fli, char *data ) {
215 short int line;
216 short int nrlines;
217 char *index;
218 uchar packets;
219 int index_x;
220 char type;
221 /* puts( "delta fli" ); */
222 line = *(short int *)data;
223 data = (void *)((short int *)data + 1);
224 index = graph_mem + line * fli->scr_width;
225 nrlines = *(short int *)data;
226 data = (void *)((short int *)data + 1);
227 while( nrlines-- > 0 ) {
228 index_x = 0;
229 packets = *(uchar *)data;
230 data = (void *)((uchar *)data + 1);
231 while( packets > 0 ) {
232 index_x += *(uchar *)data;
233 data = (void *)((uchar *)data + 1);
234 type = *(char *)data;
235 data = (void *)((char *)data + 1);
236 if( type >= 0 ) {
237 memcpy( index + index_x, data, type );
238 index_x += type;
239 data = (void *)((uchar *)data + type);
240 packets--;
241 continue;
242 }
243 memset( index + index_x, *(uchar *)data, -type );
244 index_x -= type;
245 data = (void *)((uchar *)data + 1);
246 packets--;
247 }
248 index += fli->scr_width;
249 }
250 }
251
252
253
dcd_byte_run(struct FLI * fli,char * data)254 static void dcd_byte_run( struct FLI *fli, char *data ) {
255 int lines;
256 int width;
257 char type;
258 int index;
259 int index_x;
260 /* puts( "byte run" ); */
261 lines = fli->h.height;
262 width = fli->h.width;
263 index = 0;
264 while( lines-->0 ) {
265 data = (void *)((uchar *)data + 1); /* skip byte containing number of packets */
266 /* start a loop to decode packets until end of line is reached */
267 index_x = 0;
268 while ( index_x < width ) {
269 type = *((char *)data++);
270 if( type<0 ) {
271 /* type now contains nr of bytes to copy to video */
272 memcpy( graph_mem + index + index_x, (uchar *)data, -type );
273 index_x -= type;
274 data = (void *)((uchar *)data - type);
275 }
276 else {
277 memset( graph_mem + index + index_x, *(uchar *)data++, type );
278 index_x += type;
279 }
280 }
281 index += fli->scr_width;
282 }
283 }
284
285
dcd_black(struct FLI * fli,char * data)286 static void dcd_black( struct FLI *fli, char *data ) {
287 /* puts( "black" ); */
288 int l;
289 uchar *index;
290
291 l = fli->h.height;
292 index = graph_mem;
293 while( l-- > 0 ) {
294 memset( index, 0, fli->h.width );
295 index += fli->scr_width;
296 }
297 }
298
dcd_literal(struct FLI * fli,char * data)299 static void dcd_literal( struct FLI *fli, char *data ) {
300 int l;
301 /* puts( "literal" ); */
302 l = fli->h.height;
303 {
304 /* linear video memory */
305 char *index;
306 index = graph_mem;
307 while( l-- > 0 ) {
308 memcpy( index, data, fli->h.width );
309 data = (void *)((uchar *)data + fli->h.width);
310 index += fli->scr_width;
311 }
312 }
313 }
314
dcd_pstamp(char * data)315 static void dcd_pstamp( char *data ) {
316 /* puts( "pstamp" ); */
317 }
318
showhelp(void)319 static void showhelp( void ) {
320 puts( "FLI Player for Linux (version 0.2a) by John Remyn" );
321 puts( "modified version for aalib by Jan Hubicka" );
322 puts( "Now it is ascii arted FLI Player for text mode" );
323 puts( "Usage:" );
324 puts( " flip [switch] <filename>" );
325 puts( "Valid switches are :" );
326 puts( " -f Switch off clock synchronization." );
327 puts( " -v Show information on flic file." );
328 puts( " -? -h Show help." );
329 puts( " -a Don't keep frames in memory." );
330 puts( " -b Process frames when they are loaded." );
331 puts( " -c Keep a blank screen while frames are being loaded." );
332 puts( " -n <number> Play the animation sequence <n> times." );
333 puts( " -s <delay> Set delay between frames to <delay> miliseconds." );
334 puts( " - Read flic file from standard input." );
335 puts( "also standard aalib options are supported" );
336 puts( " -dim, -bold, -reverse, -normal for enabling attributes");
337 puts( " -nodim, -nobold, -noreverse, -nonormal for disabling");
338 puts( "Press H for help on keys while playing." );
339 }
340
parse_cmdln(int argc,char * argv[],struct OPTIONS * options)341 static void parse_cmdln( int argc, char *argv[], struct OPTIONS *options ) {
342 int i,j;
343
344 options->filename[0] = '\0';
345 options->fast = 0;
346 options->verbose = 0;
347 options->release = 0;
348 options->firstp = 0;
349 options->blank = 0;
350 options->playrep = 1;
351 options->speed = -1;
352 options->stdinp = 0;
353 for( i=1; i<argc; i++ ) {
354 if( *argv[i]=='-' ) {
355 char c;
356 int k;
357 /* argv[i] contains options */
358 if( *(argv[i]+1)=='\0' ) {
359 options->stdinp = 1;
360 }
361 j = 1;
362 k = 0;
363 while( (c = *(argv[i]+j))!='\0' ) {
364 switch( c ) {
365 case 'f' : options->fast = 1; break;
366 case 'v' : options->verbose = 1; break;
367 case 'a' : options->release = 1; break;
368 case 'b' : options->firstp = 1; break;
369 case 'c' : options->blank = 1; break;
370 case '?' :
371 case 'h' : showhelp(); exit( 0 ); break;
372 case 'n' : if( i+k+1<argc ) {
373 k++;
374 options->playrep = abs( atoi( argv[i+k] ) );
375 }
376 break;
377 case 's' : if( i+k+1<argc ) {
378 k++;
379 options->speed = abs( atoi( argv[i+k] ) );
380 /* adjust to some reasonable value */
381 if (options->speed > 1000) options->speed = 1000;
382 /* convert to usec */
383 options->speed *= 1000;
384 }
385 break;
386 default : showhelp();
387 puts( "Unknown option." );
388 exit( -1 );
389 }
390 j++;
391 }
392 i = i+k;
393 }
394 else {
395 if( argv[i]!=NULL ) {
396 /* argv[i] is the filename of the flic file */
397 strncpy( options->filename, argv[i], NAMELEN );
398 }
399 }
400 }
401 if( options->filename[0]=='\0' && options->stdinp==0 ) {
402 showhelp();
403 puts( "No filename given." );
404 exit( -1 );
405 }
406 }
407
open_fli(struct FLI * fli,struct OPTIONS * options)408 static int open_fli( struct FLI *fli, struct OPTIONS *options ) {
409 /* open file and read the header */
410 if( !options->stdinp ) {
411 fli->f = fopen( fli->filename, "rb" );
412 if( !fli->f ) {
413 return 0;
414 }
415 }
416 else {
417 fli->f = stdin;
418 }
419 freadblock( fli->f, sizeof( fli->h.size ), &(fli->h.size) );
420 freadblock( fli->f, sizeof( fli->h.type ), &(fli->h.type) );
421 freadblock( fli->f, sizeof( fli->h.frames ), &(fli->h.frames) );
422 freadblock( fli->f, sizeof( fli->h.width ), &(fli->h.width) );
423 freadblock( fli->f, sizeof( fli->h.height ), &(fli->h.height) );
424 freadblock( fli->f, sizeof( fli->h.depth ), &(fli->h.depth) );
425 freadblock( fli->f, sizeof( fli->h.flags ), &(fli->h.flags) );
426 freadblock( fli->f, sizeof( fli->h.speed ), &(fli->h.speed) );
427 freadblock( fli->f, sizeof( fli->h.reserved0 ), &(fli->h.reserved0) );
428 freadblock( fli->f, sizeof( fli->h.created ), &(fli->h.created) );
429 freadblock( fli->f, sizeof( fli->h.creator ), &(fli->h.creator) );
430 freadblock( fli->f, sizeof( fli->h.updated ), &(fli->h.updated) );
431 freadblock( fli->f, sizeof( fli->h.updater ), &(fli->h.updater) );
432 freadblock( fli->f, sizeof( fli->h.aspectx ), &(fli->h.aspectx) );
433 freadblock( fli->f, sizeof( fli->h.aspecty ), &(fli->h.aspecty) );
434 freadblock( fli->f, sizeof( fli->h.reserved1 ), &(fli->h.reserved1) );
435 freadblock( fli->f, sizeof( fli->h.oframe1 ), &(fli->h.oframe1) );
436 freadblock( fli->f, sizeof( fli->h.oframe2 ), &(fli->h.oframe2) );
437 freadblock( fli->f, sizeof( fli->h.reserved2 ), &(fli->h.reserved2) );
438
439 /* now check if it's a flc or a fli and take necessary precautions */
440 if( (unsigned)fli->h.type==FLITYPE ) {
441 /* it's a fli. convert as much as possible to flc */
442 fli->flc = 0;
443 /* convert frame rate from 1/70 sec to usec */
444 fli->h.speed *= 100;
445 fli->h.speed /= 7;
446 fli->h.speed *= 1000;
447 /* ascpect ratio is ignored, but fix it anyway */
448 fli->h.aspectx = 6;
449 fli->h.aspecty = 5;
450 /* can't convert frame offsets */
451 }
452 else if( (unsigned)fli->h.type==FLCTYPE ) {
453 fli->flc = 1;
454 fli->h.speed *= 1000; /* convert msec to usec */
455 }
456 else {
457 puts( "File type not recognized." );
458 exit( -1 );
459 }
460 return 1;
461 };
462
463
describe_fli(struct FLI * fli)464 static void describe_fli( struct FLI *fli ) {
465 printf( "Filename %s\n", fli->filename );
466 printf( "size %li\n", fli->h.size );
467 printf( "type %x\n", fli->h.type );
468 printf( "frames %i\n", fli->h.frames );
469 printf( "width %i\n", fli->h.width );
470 printf( "height %i\n", fli->h.height );
471 printf( "depth %i\n", fli->h.depth );
472 printf( "flags %x\n", fli->h.flags );
473 printf( "speed %li\n", fli->h.speed );
474 printf( "aspectx %i\n", fli->h.aspectx );
475 printf( "aspecty %i\n", fli->h.aspecty );
476 printf( "oframe1 %li\n", fli->h.oframe1 );
477 printf( "oframe2 %li\n", fli->h.oframe2 );
478 };
479
480
readchunkheader(FILE * f,struct FLI_CHUNK_HEADER * buf)481 static void readchunkheader( FILE *f, struct FLI_CHUNK_HEADER *buf ) {
482 freadblock( f, sizeof( buf->size ), &buf->size );
483 freadblock( f, sizeof( buf->type ), &buf->type );
484 freadblock( f, sizeof( buf->chunks ), &buf->chunks );
485 freadblock( f, sizeof( buf->reserved ), &buf->reserved );
486 }
487
scan_to_frame(struct FLI * fli)488 static void scan_to_frame( struct FLI *fli ) {
489 struct FLI_CHUNK_HEADER buf;
490 struct FLI_FRAMECHUNK *fc;
491 do {
492 readchunkheader( fli->f, &buf );
493 if( buf.type==0xF1FA ) break;
494 fseek( fli->f, buf.size - FLI_CHUNK_HEADERLEN, SEEK_CUR );
495 } while ( buf.type!=0xF1FA );
496 fc = fli->frame + fli->current;
497 fc->size = buf.size - FLI_CHUNK_HEADERLEN;
498 fc->subchunks = buf.chunks;
499 fc->file_offset = ftell( fli->f );
500 fc->cd = NULL;
501 }
502
getframechunkdata(struct FLI * fli)503 static void getframechunkdata( struct FLI *fli ) {
504 struct FLI_FRAMECHUNK *fc;
505 void *data;
506 fc = fli->frame + fli->current;
507 data = fc->cd;
508 if( data )
509 return; /* frame chunk data already loaded */
510 if(fc->size) {
511 data = malloc( fc->size );
512 if( !data ) {
513 printf( "cannot allocate memory for frame data\n" );
514 exit( 1 );
515 }
516 fseek( fli->f, fc->file_offset, SEEK_SET );
517 freadblock( fli->f, fc->size, data );
518 } else data=NULL;
519 fc->cd = data;
520 }
521
releaseframechunkdata(struct FLI * fli)522 static void releaseframechunkdata( struct FLI *fli ) {
523 struct FLI_FRAMECHUNK *fc;
524 fc = fli->frame + fli->current;
525 if( fc->cd ) {
526 free( fc->cd );
527 fc->cd = NULL;
528 }
529 }
530
processframechunk(struct FLI * fli)531 static void processframechunk( struct FLI *fli ) {
532 struct FLI_FRAMECHUNK *fc;
533 void *data;
534 int i;
535 fc = fli->frame + fli->current;
536 data = fc->cd;
537 for( i=0; i<fc->subchunks; i++ ) {
538 /* switch( chunktype ) */
539 switch( *((short int *)((char *)data+4)) ) {
540 case COLOR_256 :
541 dcd_color_256( (char *)data + 6 );
542 break;
543 case DELTA_FLC :
544 dcd_delta_flc( fli, (char *)data + 6 );
545 break;
546 case COLOR_64 :
547 dcd_color_64( (char *)data + 6 );
548 break;
549 case DELTA_FLI :
550 dcd_delta_fli( fli, (char *)data + 6 );
551 break;
552 case BLACK :
553 dcd_black( fli, (char *)data + 6 );
554 break;
555 case BYTE_RUN :
556 dcd_byte_run( fli, (char *)data + 6 );
557 break;
558 case LITERAL :
559 dcd_literal( fli, (char *)data + 6 );
560 break;
561 case PSTAMP :
562 dcd_pstamp( (char *)data + 6 );
563 break;
564 default :
565 puts( "unknown subchunk" );
566 }
567 data = (void *)((char *)data + *(long *)data);
568 }
569 }
570
gettime(void)571 long gettime(void) {
572 struct timeval t;
573 gettimeofday(&t, NULL);
574 return(t.tv_usec);
575 }
576
await()577 int await() {
578 #define T 10000 /* process key every 10ms */
579 int i;
580 long t;
581 t = gettime();
582 if (t < fli.time) t = t + 1E6;
583 t = fli.h.speed - (t - fli.time);
584 if (t > 0) {
585 if (t > T) {
586 for (i = 0; i < (t / T); i++) {
587 usleep(T);
588 if (f_getkey() == 'q') return(1);
589 }
590 usleep(t % T);
591 }
592 else usleep(t);
593 }
594 return(f_getkey() == 'q');
595 }
596
fastscale(char * b1,char * b2,int x1,int x2,int y1,int y2,int width1,int width2)597 static void fastscale(char *b1, char *b2, int x1, int x2, int y1, int y2, int width1, int width2)
598 {
599 int ddx1, ddx, spx = 0, ex;
600 int ddy1, ddy, spy = 0, ey;
601 int x;
602 char *bb1 = b1;
603 width2 -= x2;
604 if (!x1 || !x2 || !y1 || !y2)
605 return;
606 ddx = x1 + x1;
607 ddx1 = x2 + x2;
608 if (ddx1 < ddx)
609 spx = ddx / ddx1, ddx %= ddx1;
610 ddy = y1 + y1;
611 ddy1 = y2 + y2;
612 if (ddy1 < ddy)
613 spy = (ddy / ddy1) * width1, ddy %= ddy1;
614 ey = -ddy1;
615 for (; y2; y2--) {
616 ex = -ddx1;
617 for (x = x2; x; x--) {
618 *b2 = *b1;
619 b2++;
620 b1 += spx;
621 ex += ddx;
622 if (ex > 0) {
623 b1++;
624 ex -= ddx1;
625 }
626 }
627 b2 += width2;
628 bb1 += spy;
629 ey += ddy;
630 if (ey > 0) {
631 bb1 += width1;
632 ey -= ddy1;
633 }
634 b1 = bb1;
635 }
636 }
637 static int resized;
resize(aa_context * c)638 static void resize(aa_context * c)
639 {
640 aa_resize(c);
641 resized = 1;
642 }
643
yesno(int x,int y,char * string)644 static int yesno(int x, int y, char *string)
645 {
646 char c;
647 aa_puts(context, x, y, AA_SPECIAL, string);
648 aa_flush(context);
649 while ((c = tolower(aa_getkey(context, 1))) != 'y' && c != 'n');
650 return (c == 'y');
651 }
getnum(char * string)652 static int getnum(char *string)
653 {
654 unsigned char c;
655 aa_puts(context, 0, 0, AA_SPECIAL, string);
656 aa_flush(context);
657 while ((c = tolower(aa_getkey(context, 1))) < '0' || c > '9');
658 return (c - '0');
659 }
selectfont(aa_context * c)660 static void selectfont(aa_context * c)
661 {
662 int i = 0, i1;
663 char string[255];
664 for (i = 0; aa_fonts[i] != NULL; i++) {
665 sprintf(string, "%i - %-40s", i, aa_fonts[i]->name);
666 aa_puts(context, 0, i, AA_SPECIAL, string);
667 }
668 i1 = getnum("");
669 if (i1 < i)
670 aa_setfont(c, *(aa_fonts + i1));
671 }
672
673 #if AA_LIB_VERSION==1 && AA_LIB_MINNOR==0
674 #define SUPPORTED c->driver->params.supported
675 #else
676 #define SUPPORTED c->driverparams.supported
677 #endif
selectsupported(aa_context * c)678 static void selectsupported(aa_context * c)
679 {
680 int supported = c->params.supported;
681 char text[40];
682 int ch;
683 do {
684 char *texts[]={
685 "Normal characters",
686 "Half bright (dim)",
687 "Double bright (bold)",
688 "Bold font",
689 "Reversed",
690 "8 bit ascii",
691 "Control characters"};
692 int masks[]={AA_NORMAL_MASK,AA_DIM_MASK,AA_BOLD_MASK,AA_BOLDFONT_MASK,AA_REVERSE_MASK,AA_EIGHT,AA_ALL};
693 int i;
694 for(i=0;i<7;i++)
695 {
696 sprintf(text,"%i %-20s:%-12s",i+1,texts[i],(SUPPORTED&masks[i])?((supported&masks[i])?"On":"Off"):"Unsupported");
697 aa_puts(c,0,i,AA_SPECIAL,text);
698 }
699 aa_puts(c,0,i,AA_SPECIAL,"8 Leave this menu");
700 aa_flush(c);
701 while ((ch = tolower(aa_getkey(context, 1))) < '1' || ch > '8');
702 ch-='1';
703 if(ch<7) supported^=masks[ch];
704 } while (ch<7);
705
706 aa_setsupported(c, supported);
707 }
f_getkey(void)708 int f_getkey(void)
709 {
710 int c=aa_getkey(context,0);
711 switch(c) {
712 case 'h':
713 case 'H':
714 aa_puts(context,0,0,AA_SPECIAL," aaflip - an ascii art fli/flc player ");
715 aa_puts(context,0,1,AA_SPECIAL," ");
716 aa_puts(context,0,2,AA_SPECIAL," ';' '\\' - gamma '<' '>' - bright ");
717 aa_puts(context,0,3,AA_SPECIAL," '[' ']' - Random dithering',' '.' - contrast ");
718 aa_puts(context,0,4,AA_SPECIAL," 'I' 'i' - inversion ");
719 aa_puts(context,0,5,AA_SPECIAL," ");
720 aa_puts(context,0,6,AA_SPECIAL," 'm' - Dithering method 'q' - quit ");
721 aa_puts(context,0,7,AA_SPECIAL," 'u' - Select attributes 'g' - font ");
722 aa_flush(context);
723 aa_getkey(context,1);
724 break;
725 case ';':
726 params->gamma /= 1.05;
727 break;
728 case '\'':
729 params->gamma *= 1.05;
730 break;
731 case '<':
732 params->bright -= 4;
733 break;
734 case '>':
735 params->bright += 4;
736 break;
737 case '[':
738 params->randomval -= 4;
739 break;
740 case ']':
741 params->randomval += 4;
742 break;
743 case ',':
744 params->contrast -= 2;
745 break;
746 case '.':
747 params->contrast += 2;
748 break;
749 case 'm':
750 params->dither = (params->dither + 1) % AA_DITHERTYPES;
751 break;
752 case 'i':
753 params->inversion = 1;
754 break;
755 case 'I':
756 params->inversion = 0;
757 break;
758 case 'u':
759 selectsupported(context);
760 break;
761 case 'g':
762 selectfont(context);
763 break;
764 }
765 return(c);
766 }
767
main(int argc,char * argv[])768 int main( int argc, char *argv[] ) {
769 int quit = 0;
770 int playstartframe = 0;
771 int first=1;
772 long t, tdelta;
773 aa_parseoptions(NULL,NULL,&argc,argv);
774 parse_cmdln( argc, argv, &options );
775 strcpy( fli.filename, options.filename );
776
777 /* open flic and get header information */
778 if( !open_fli( &fli, &options ) ) {
779 puts( "cannot open fli file" );
780 exit( 1 );
781 }
782
783 /* show header */
784 if( options.verbose==1 ) {
785 describe_fli( &fli );
786 }
787
788 /* optionally set delays */
789 if( options.speed>=0 ) {
790 fli.h.speed = options.speed;
791 }
792
793 /* optionally reduce delays to 0 (this overrides the set delay option) */
794 if( options.fast==1 ) {
795 fli.h.speed = 0;
796 }
797
798
799 /* silly but might happen */
800 if( options.playrep<=0 ) {
801 exit( 0 );
802 }
803
804 /* determine graphics mode to use */
805 /* set mode */
806 context=aa_autoinit(&aa_defparams);
807 if(context==NULL) {
808 printf("Failed to initialize aalib\n");
809 exit(1);
810 }
811 aa_hidecursor(context);
812 aa_autoinitkbd(context,0);
813 aa_resizehandler(context,resize);
814 params=aa_getrenderparams();
815 fli.scr_width = fli.h.width;
816 fli.scr_height = fli.h.height;
817 graph_mem=malloc(fli.scr_width*fli.scr_height);
818
819 fli.frame = (struct FLI_FRAMECHUNK *)malloc( (fli.h.frames+1) * sizeof( struct FLI_FRAMECHUNK ) );
820 if( fli.frame==NULL ) {
821 puts( "cannot allocate enough memory to store frame information\n" );
822 exit( 1 );
823 }
824
825 fli.current = 0;
826 /* preloading */
827 /* first the 1st frame which is a full screen frame */
828 scan_to_frame( &fli );
829
830 if( !options.blank ) {
831 getframechunkdata( &fli );
832 processframechunk( &fli );
833 releaseframechunkdata( &fli );
834 playstartframe = 1;
835 }
836 else {
837 getframechunkdata( &fli );
838 playstartframe = 0;
839 if( options.release ) {
840 releaseframechunkdata( &fli );
841 }
842 }
843 fli.current++;
844 first=1;
845 while( fli.current<=fli.h.frames && !quit ) {
846 scan_to_frame( &fli );
847 getframechunkdata( &fli );
848 if( options.firstp ) {
849 fli.time = gettime();
850 processframechunk( &fli );
851 }
852 if( options.release ) {
853 releaseframechunkdata( &fli );
854 }
855 if(first||options.firstp) {
856 fastscale(graph_mem,context->imagebuffer,
857 fli.scr_width,aa_imgwidth(context),
858 fli.scr_height,aa_imgheight(context),
859 fli.scr_width,aa_imgwidth(context));
860 aa_renderpalette(context,pal,params,0,0,aa_imgwidth(context),aa_imgheight(context));
861 if(first&&!options.firstp)
862 aa_puts(context,0,0,AA_SPECIAL,"Preloading...");
863 aa_flush(context);
864 }
865 fli.current++;
866 first=0;
867 if( f_getkey()=='q' ) quit = 1;
868 if(options.firstp&&!quit) quit = await();
869 }
870
871 if(!quit) {
872
873 if( options.firstp ) {
874 options.playrep--;
875 if( options.playrep==0 ) {
876 quit = 1;
877 }
878 }
879
880 fli.current = playstartframe;
881 while( !quit ) {
882 fli.time = gettime();
883 getframechunkdata( &fli );
884 processframechunk( &fli );
885 if( options.release ) {
886 releaseframechunkdata( &fli );
887 }
888 fli.current++;
889 fastscale(graph_mem,context->imagebuffer,
890 fli.scr_width,aa_imgwidth(context),
891 fli.scr_height,aa_imgheight(context),
892 fli.scr_width,aa_imgwidth(context));
893 aa_renderpalette(context,pal,params,0,0,aa_imgwidth(context),aa_imgheight(context));
894 aa_flush(context);
895 if( fli.current>fli.h.frames ) {
896 fli.current = 1;
897 options.playrep--;
898 if( options.playrep==0 ) {
899 quit = 1;
900 break;
901 }
902 }
903 quit = await();
904
905 }
906 }
907
908 /* restore textmode */
909 aa_close(context);
910
911 /* close flic */
912 if( !options.stdinp ) {
913 fclose( fli.f );
914 }
915 fli.f = NULL;
916 return 0;
917 };
918
919
920
921