home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
-
- Flick FLI-format Animation Viewer v1.2 19 Feb 1994
- --------------------------------------
-
-
- This program plays FLI/FLC-format bitmapped animation files on any ECS
- or AGA Amiga running OS2.04 or higher. FLI/FLC-format files are
- produced by Autodesk Animator and Autodesk 3D Studio on a PC, as well
- as by other programs.
-
- The files in this archive may be distributed anywhere provided they are
- unmodified and are not sold for profit.
-
- Ownership and copyright of all files remains with the author:
-
- Peter McGavin, 86 Totara Crescent, Lower Hutt, New Zealand.
- e-mail: peterm@maths.grace.cri.nz
-
- *****************************************************************************/
-
- #include "includes.h"
-
- const char version[] = "$VER: Flick 1.2 " __AMIGADATE__ ;
-
- long __oslibversion = 37; /* we require at least OS2.0 */
-
- char __stdiowin[] = "CON:20/50/500/130/Flick";
- char __stdiov37[] = "/AUTO/CLOSE";
-
- void __asm c2p_8 (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __a3 UBYTE *buff0,
- register __a4 UBYTE *buff1,
- register __a5 struct Library *TimerBase,
- register __a6 struct GfxBase *GfxBase,
- register __d0 struct Library *UtilityBase,
- register __d1 ULONG plsiz);
-
- void __asm c2p_6 (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __a3 UBYTE *buff0,
- register __a4 UBYTE *buff1,
- register __a5 struct Library *TimerBase,
- register __a6 struct GfxBase *GfxBase,
- register __d0 struct Library *UtilityBase,
- register __d1 ULONG plsiz);
-
- void __asm c2p_4 (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __a3 UBYTE *buff0,
- register __a4 UBYTE *buff1,
- register __a5 struct Library *TimerBase,
- register __a6 struct GfxBase *GfxBase,
- register __d0 struct Library *UtilityBase,
- register __d1 ULONG plsiz);
-
- void __asm c2p320x200x8 (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __a3 UBYTE *buff0,
- register __a4 UBYTE *buff1,
- register __a5 struct Library *TimerBase,
- register __a6 struct GfxBase *GfxBase,
- register __d0 struct Library *UtilityBase);
-
- void __asm c2p320x200x6 (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __a3 UBYTE *buff0,
- register __a4 UBYTE *buff1,
- register __a5 struct Library *TimerBase,
- register __a6 struct GfxBase *GfxBase,
- register __d0 struct Library *UtilityBase);
-
- void __asm c2p_8_040 (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __d1 ULONG plsiz);
-
- void __asm c2p_6_040 (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __d1 ULONG plsiz);
-
- void __asm c2p_4_040 (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __d1 ULONG plsiz);
-
- void __asm c2p320x200x8_040 (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster);
-
- void __asm c2p320x200x6_040 (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster);
-
- void __asm c2p_8_cmp (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __a2 UBYTE *compare_data,
- register __d1 ULONG plsiz);
-
- void __asm c2p_6_cmp (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __a2 UBYTE *compare_data,
- register __d1 ULONG plsiz);
-
- void __asm c2p_4_cmp (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __a2 UBYTE *compare_data,
- register __d1 ULONG plsiz);
-
- void __asm c2p320x200x8_cmp (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __a2 UBYTE *compare_data);
-
- void __asm c2p320x200x6_cmp (register __a0 UBYTE *chunky_data,
- register __a1 PLANEPTR raster,
- register __a2 UBYTE *compare_data);
-
- #define FLI_256_COLOR 4
- #define FLI_SS2 7
- #define FLI_COLOR 11
- #define FLI_LC 12
- #define FLI_BLACK 13
- #define FLI_BRUN 15
- #define FLI_COPY 16
- #define FLI_PSTAMP 18
-
- struct header {
- ULONG size;
- UWORD magic;
- UWORD frames;
- UWORD width;
- UWORD height;
- UWORD depth;
- UWORD flags;
- ULONG speed;
- UWORD reserved1;
- ULONG created;
- ULONG creator;
- ULONG updated;
- ULONG updater;
- UWORD aspectx;
- UWORD aspecty;
- UBYTE reserved2[38];
- ULONG oframe1;
- ULONG oframe2;
- UBYTE reserved3[40];
- };
-
- struct frameheader {
- ULONG size;
- UWORD magic;
- UWORD chunks;
- UBYTE expand[8];
- };
-
- struct chunkheader {
- ULONG size;
- UWORD type;
- };
-
- struct options {
- BOOL ram;
- enum mode_type mode;
- BOOL once;
- BOOL rom;
- BOOL dbuf;
- BOOL cmp;
- };
-
- #define BITMAP_DEPTH 8
-
- PLANEPTR raster[2] = {NULL, NULL}; /* 8 contiguous bitplanes */
- struct BitMap screen_bm[2]; /* The displayed bitmap (may be less planes) */
- struct BitMap bitmap_bm[2]; /* The full depth-8 bitmap */
- struct RastPort rp[2];
- UBYTE *buff0 = NULL; /* CHIP buffer for chunky2planar */
- UBYTE *buff1 = NULL; /* CHIP buffer for chunky2planar */
-
- UWORD __chip emptypointer[] = {
- 0x0000, 0x0000, /* reserved, must be NULL */
- 0x0000, 0x0000, /* 1 row of image data */
- 0x0000, 0x0000}; /* reserved, must be NULL */
-
- struct NewScreen ns = {
- 0,0,0,0,0,
- 2,1,
- 0 /* HIRES | LACE */,
- CUSTOMSCREEN | CUSTOMBITMAP,
- NULL,
- NULL,
- NULL,
- &screen_bm[0]
- };
-
- struct NewWindow nw = {
- 0,0, /* Starting corner */
- 0,0, /* Width, height */
- 2,1, /* detail, block pens */
- VANILLAKEY, /* IDCMP flags */
- ACTIVATE|BORDERLESS, /* Window flags */
- NULL, /* Pointer to first gadget */
- NULL, /* Pointer to checkmark */
- NULL, /* title */
- NULL, /* screen pointer */
- NULL, /* bitmap pointer */
- 0,0,0,0, /* window not sized */
- CUSTOMSCREEN /* type of screen */
- };
-
- struct Screen *s = NULL;
- struct Window *w = NULL;
- UWORD screen_width;
- UWORD screen_depth;
-
- struct ScreenBuffer *sb[2] = {NULL, NULL};
- struct MsgPort *safeport = NULL;
- struct MsgPort *dispport = NULL;
- BOOL safe = TRUE;
- BOOL disp = TRUE;
-
- struct RastPort temprp; /* for WritePixelArray8() */
- struct BitMap tmp_bm; /* for WritePixelArray8(), Height=1, Depth=8 */
- PLANEPTR tmpras = NULL; /* for WritePixelArray8() */
-
- struct header h;
-
- struct Library *TimerBase = NULL;
- struct timerequest *timerio = NULL;
- ULONG timerclosed = TRUE;
- struct EClockVal *time0 = NULL;
- struct EClockVal *time1 = NULL;
- double micros_per_eclock; /* Length of EClock tick in microseconds */
-
- struct Task *thistask = NULL;
- BOOL v39 = FALSE;
- BOOL m68040 = FALSE;
-
- char programname[20];
- BPTR olddir = NULL;
- struct RDArgs *rdargs = NULL;
-
- struct Library *AslBase = NULL;
- struct FileRequester *fr = NULL;
-
-
- /****************************************************************************/
-
- void swapw (UWORD *w)
- /* Swap the bytes around in a word which may be on an odd byte-boundary */
- {
- UBYTE t;
-
- t = ((UBYTE *)w)[0];
- ((UBYTE *)w)[0] = ((UBYTE *)w)[1];
- ((UBYTE *)w)[1] = t;
- }
-
- void swapl (ULONG *l)
- /* Swap the bytes around in a longword which may be on an odd byte-boundary */
- {
- UBYTE t;
-
- t = ((UBYTE *)l)[0];
- ((UBYTE *)l)[0] = ((UBYTE *)l)[3];
- ((UBYTE *)l)[3] = t;
- t = ((UBYTE *)l)[1];
- ((UBYTE *)l)[1] = ((UBYTE *)l)[2];
- ((UBYTE *)l)[2] = t;
- }
-
- UWORD extractw (UWORD *w)
- /* Get a word which may be on an odd byte-boundary */
- {
- UBYTE t[2];
-
- t[0] = ((UBYTE *)w)[0];
- t[1] = ((UBYTE *)w)[1];
- return *(UWORD *)t;
- }
-
- ULONG extractl (ULONG *l)
- /* Get a longword which may be on an odd byte-boundary */
- {
- UBYTE t[4];
-
- t[0] = ((UBYTE *)l)[0];
- t[1] = ((UBYTE *)l)[1];
- t[2] = ((UBYTE *)l)[2];
- t[3] = ((UBYTE *)l)[3];
- return *(ULONG *)t;
- }
-
- /****************************************************************************/
-
- void _STDcleanup (void)
- /* This get called automatically by SAS/C 6.3 on any sort of exit condition */
- {
- int which;
-
- if (!safe) {
- Wait (1 << safeport->mp_SigBit);
- while (GetMsg (safeport) != NULL) /* clear message queue */
- /* nothing */ ;
- safe = TRUE;
- }
- if (!disp) {
- Wait (1 << dispport->mp_SigBit);
- while (GetMsg (dispport) != NULL) /* clear message queue */
- /* nothing */ ;
- disp = TRUE;
- }
-
- if (w != NULL) {
- CloseWindow (w);
- w = NULL;
- }
- if (sb[1] != NULL) {
- FreeScreenBuffer (s, sb[1]);
- sb[1] = NULL;
- }
- if (sb[0] != NULL) {
- FreeScreenBuffer (s, sb[0]);
- sb[0] = NULL;
- }
- if (s != NULL) {
- CloseScreen (s);
- s = NULL;
- }
- if (tmpras != NULL) {
- FreeRaster (tmpras, screen_width, screen_depth);
- tmpras = NULL;
- }
- if (dispport != NULL) {
- DeletePort (dispport);
- dispport = NULL;
- }
- if (safeport != NULL) {
- DeletePort (safeport);
- safeport = NULL;
- }
- if (buff0 != NULL) {
- FreeMem (buff0, screen_width * (ULONG)h.height);
- buff0 = NULL;
- }
- if (buff1 != NULL) {
- FreeMem (buff1, screen_width * (ULONG)h.height);
- buff1 = NULL;
- }
- for (which = 0; which < 2; which++) {
- if (raster[which] != NULL) {
- FreeRaster (raster[which], screen_width, BITMAP_DEPTH * h.height);
- raster[which] = NULL;
- }
- }
- if (fr != NULL) {
- FreeAslRequest (fr);
- fr = NULL;
- }
- if (AslBase != NULL) {
- CloseLibrary (AslBase);
- AslBase = NULL;
- }
- if (time1 != NULL) {
- FreeMem (time1, sizeof(struct EClockVal));
- time1 = NULL;
- }
- if (time0 != NULL) {
- FreeMem (time0, sizeof(struct EClockVal));
- time0 = NULL;
- }
- if (olddir != NULL) {
- CurrentDir (olddir);
- olddir = NULL;
- }
- if (rdargs != NULL) {
- FreeArgs (rdargs);
- rdargs = NULL;
- }
- if (!timerclosed) {
- CloseDevice ((struct IORequest *)timerio);
- timerclosed = TRUE;
- TimerBase = NULL;
- }
- if (timerio != NULL) {
- FreeMem (timerio, sizeof(struct timerequest));
- timerio = NULL;
- }
- /* standard libraries are auto-closed here by SAS/C */
- }
-
- /****************************************************************************/
-
- void die (char *msg, ...)
- /* Exit program with message, return code 10 */
- {
- va_list arglist;
-
- WBenchToFront ();
- va_start (arglist, msg);
- vfprintf (stderr, msg, arglist);
- va_end (arglist);
- Delay (50); /* give the user time to read the message */
- exit (10);
- /* SAS/C executes _STDcleanup() automatically on exit */
- }
-
- /****************************************************************************/
-
- void *malloc_check (size_t size)
- {
- void *p;
-
- if ((p = malloc (size)) == NULL)
- die ("%s: Out of memory trying to allocate %ld bytes!\n", programname,
- size);
- return (p);
- }
-
- /****************************************************************************/
-
- void animate_file (char *fname, struct options opt)
- {
- FILE *f;
- ULONG size, y, class, totalframes, restartpos, l;
- UWORD i, frame, chunk, code;
- UWORD packets, n, m, c, lines, bsize, depth, which;
- UWORD *viewcolourtable;
- struct IntuiMessage *msg;
- UBYTE *filebuf, *buf, *framebuf, *chunkbuf, *p, *p2, *p3;
- UBYTE *chunky, *compare_chunky[2], *copy_of_chunky;
- UBYTE *restartptr, *xlate;
- UBYTE (*colourtable)[256][3], pattern[2];
- BOOL going, firstloop;
- struct frameheader *fh;
- struct chunkheader *ch;
- ULONG fh_size;
- UWORD fh_magic, fh_chunks, ch_type;
- BOOL palette_changed;
- int oldpri;
-
- /* initialise resources */
- f = NULL;
- viewcolourtable = NULL;
- filebuf = NULL;
- framebuf = NULL;
- chunky = NULL;
- compare_chunky[0] = NULL;
- compare_chunky[1] = NULL;
- copy_of_chunky = NULL;
- xlate = NULL;
- colourtable = NULL;
- fh = NULL;
-
- /* open file and read header struct */
- if ((f = fopen (fname, "rb")) == NULL)
- die ("%s: Can't open %s\n", programname, fname);
- if ((fread (&h, sizeof(struct header), 1, f)) != 1)
- die ("%s: Error reading file\n", programname);
- swapl (&h.size);
- swapw (&h.magic);
- swapw (&h.frames);
- swapw (&h.width);
- swapw (&h.height);
- swapw (&h.depth);
- swapw (&h.flags);
- swapl (&h.speed);
- swapl (&h.creator);
- swapl (&h.updater);
- swapw (&h.aspectx);
- swapw (&h.aspecty);
- swapl (&h.oframe1);
- swapl (&h.oframe2);
-
- printf ("File = %s\n", fname);
- printf ("%lu bytes, %u frames, %ux%ux%u, speed = %u\n", h.size, h.frames,
- h.width, h.height, h.depth, h.speed);
- if (h.magic != 0xaf11 && h.magic != 0xaf12)
- die ("%s: Unrecognised magic number %04x\n", programname, h.magic);
-
- /* allow for AGA modes */
- screen_width = (h.width + 63) & ~63;
-
- /* allocate chunky pixels */
- chunky = malloc_check (screen_width * (ULONG)h.height);
- memset (chunky, 0, screen_width * (ULONG)h.height);
-
- if (opt.rom)
- copy_of_chunky = malloc_check (screen_width * (ULONG)h.height);
-
- /* allocate 2 rasters (for double-buffering) */
- screen_depth = 8;
- for (which = 0; which < (opt.dbuf ? 2 : 1); which++) {
- InitBitMap (&screen_bm[which], screen_depth, screen_width, h.height); /* Displayed bm */
- InitBitMap (&bitmap_bm[which], BITMAP_DEPTH, screen_width, h.height); /* Full depth-8 bm */
- /* Allocate 1 contiguous raster for all 8 planes */
- if ((raster[which] = (PLANEPTR)AllocRaster (screen_width,
- BITMAP_DEPTH * h.height)) == NULL)
- die ("%s: Out of CHIP memory!\n", programname);
- for (depth = 0; depth < screen_depth; depth++)
- screen_bm[which].Planes[depth] = raster[which] +
- depth * RASSIZE (screen_width, h.height);
- for (depth = 0; depth < BITMAP_DEPTH; depth++)
- bitmap_bm[which].Planes[depth] = raster[which] +
- depth * RASSIZE (screen_width, h.height);
- InitRastPort (&rp[which]);
- rp[which].BitMap = &screen_bm[which];
- SetRast (&rp[which], 0);
- /* allocate compare_chunky pixels */
- if (opt.cmp) {
- compare_chunky[which] = malloc_check (screen_width * (ULONG)h.height);
- memset (compare_chunky[which], 0, screen_width * (ULONG)h.height);
- }
- }
-
- /* if using ram then read in the entire file else allocate header buffers */
- if (opt.ram)
- if ((filebuf = malloc (h.size - sizeof(struct header))) == NULL) {
- printf ("%s: Not enough free contiguous memory to load into RAM\n", programname);
- printf (" Playing from disk instead\n");
- opt.ram = FALSE;
- } else {
- if ((fread (filebuf, h.size - sizeof(struct header), 1, f)) != 1)
- die ("%s: Error reading file\n", programname);
- buf = filebuf;
- }
- if (!opt.ram) {
- fh = malloc_check (sizeof(struct frameheader));
- }
-
- /* open screen with custom bitmap */
- ns.Width = screen_width;
- ns.Height = h.height;
- ns.Depth = screen_depth;
- if (screen_width > 384)
- ns.ViewModes |= HIRES;
- else
- ns.ViewModes &= ~HIRES;
- if (h.height > 283)
- ns.ViewModes |= LACE;
- else
- ns.ViewModes &= ~LACE;
- if (opt.mode == MODE_COLOUR)
- if ((!v39) || (s = OpenScreen(&ns)) == NULL) {
- printf ("%s: Can't open 8 bitplane COLOUR screen\n", programname);
- if (ns.ViewModes & HIRES) {
- printf (" Using 4 bitplane COLOUR4 instead\n");
- opt.mode = MODE_COLOUR4;
- } else {
- printf (" Using 6 bitplane EHB instead\n");
- opt.mode = MODE_EHB;
- }
- Delay (100);
- }
- if (opt.mode != MODE_COLOUR) {
- if (opt.mode == MODE_EHB) {
- ns.ViewModes |= EXTRA_HALFBRITE;
- screen_depth = 6;
- } else
- screen_depth = 4;
- ns.Depth = screen_depth;
- for (which = 0; which < (opt.dbuf ? 2 : 1); which++)
- screen_bm[which].Depth = screen_depth;
- if ((s = OpenScreen(&ns)) == NULL)
- die ("%s: Can't open screen!\n", programname);
- }
-
- /* initialise tmp stuff for WritePixelArray8() */
- if (opt.rom) {
- if ((tmpras = (PLANEPTR)AllocRaster (screen_width, screen_depth)) == NULL)
- die ("%s: Out of memory\n", programname);
- InitBitMap (&tmp_bm, screen_depth, screen_width, 1);
- for (depth = 0; depth < screen_depth; depth++)
- tmp_bm.Planes[depth] = tmpras + depth * RASSIZE (screen_width, 1);
- temprp = rp[0];
- temprp.Layer = NULL;
- temprp.BitMap = &tmp_bm;
- } else if ((!opt.cmp) && !m68040) {
- /* allocate scratch buffers in chip ram for blitter in chunky2planar */
- if ((buff0 = AllocMem (screen_width * (ULONG)h.height, MEMF_CHIP)) == NULL)
- die ("%s: Out of CHIP memory trying to allocate %ld bytes!\n",
- programname, screen_width * (ULONG)h.height);
- if ((buff1 = AllocMem (screen_width * (ULONG)h.height, MEMF_CHIP)) == NULL)
- die ("%s: Out of CHIP memory trying to allocate %ld bytes!\n",
- programname, screen_width * (ULONG)h.height);
- }
-
- /* allocate structures for double-buffering (if v39) */
- if (v39 && opt.dbuf) {
- if ((safeport = CreatePort (NULL, 0)) == NULL ||
- (dispport = CreatePort (NULL, 0)) == NULL)
- die ("%s: Can't create port!\n", programname);
- for (which = 0; which < 2; which++) {
- if ((sb[which] = AllocScreenBuffer (s, &screen_bm[which], 0)) == NULL)
- die ("%s: Can't allocate ScreenBuffer!\n", programname);
- sb[which]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = safeport;
- sb[which]->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = dispport;
- }
- }
-
- /* open a backdrop window (for intuition events) */
- nw.Width = screen_width;
- nw.Height = h.height;
- nw.Screen = s;
- nw.MinWidth = screen_width;
- nw.MinHeight = h.height;
- nw.MaxWidth = screen_width;
- nw.MaxHeight = h.height;
- if ((w = OpenWindow(&nw)) == NULL)
- die ("%s: Can't open window!\n", programname);
-
- /* turn the mouse pointer off for this window */
- SetPointer (w, emptypointer, 1, 16, 0, 0);
-
- /* allocate and initialise colour tables and pixel xlate table */
- colourtable = (UBYTE (*)[256][3])malloc_check (sizeof(*colourtable));
- memset (colourtable, 0, sizeof(*colourtable));
- xlate = malloc_check (256);
-
- switch (opt.mode) {
- case MODE_COLOUR4:
- case MODE_EHB:
- viewcolourtable = (UWORD *)malloc_check ((1 << screen_depth) * sizeof(UWORD));
- memset (viewcolourtable, 0, (1 << screen_depth) * sizeof(UWORD));
- break;
- case MODE_GREY:
- viewcolourtable = (UWORD *)malloc_check ((1 << screen_depth) * sizeof(UWORD));
- memset (viewcolourtable, 0, (1 << screen_depth) * sizeof(UWORD));
- for (c = 0; c < 16; c++)
- viewcolourtable[c] = c * 0x0111;
- LoadRGB4 (&s->ViewPort, viewcolourtable, 1 << screen_depth);
- break;
- case MODE_COLOUR:
- viewcolourtable = (UWORD *)malloc_check (2 * sizeof(UWORD) +
- (1 << screen_depth) * 3 * sizeof(ULONG) + sizeof(UWORD));
- memset (viewcolourtable, 0, 2 * sizeof(UWORD) +
- (1 << screen_depth) * 3 * sizeof(ULONG) + sizeof(UWORD));
- viewcolourtable[0] = 1 << screen_depth;
- for (i = 0; i < 256; i++)
- xlate[i] = i;
- break;
- }
-
- /* initialise loop variables */
- which = 0; /* bitmap index --- flips between 0 and 1 with each frame */
- palette_changed = FALSE;
- frame = 0;
- totalframes = 0;
- firstloop = TRUE;
- going = TRUE;
-
- /* read the start time */
- ReadEClock (time0);
-
- /* loop for each frame */
- while (going) {
-
- /* if this is the 2nd frame, save the current file-position for loop */
- if (totalframes == 1)
- if (opt.ram)
- restartptr = buf;
- else
- if ((restartpos = ftell (f)) == -1)
- die ("%s: Error ftelling file\n", programname);
-
- /* read the frame header */
- if (opt.ram) {
- fh = (struct frameheader *)buf;
- buf += sizeof(struct frameheader);
- } else
- if ((fread (fh, sizeof(struct frameheader), 1, f)) != 1)
- die ("%s: Error reading file\n", programname);
- if (firstloop || !opt.ram) {
- swapl (&fh->size);
- swapw (&fh->magic);
- swapw (&fh->chunks);
- }
- fh_size = extractl (&fh->size);
- fh_magic = extractw (&fh->magic);
- fh_chunks = extractw (&fh->chunks);
-
- /* allocate memory for and read the rest of the frame */
- if (opt.ram) {
- framebuf = buf;
- } else {
- size = fh_size - sizeof(struct frameheader);
- if (size == 0)
- framebuf = NULL;
- else {
- framebuf = malloc_check (size);
- if ((fread (framebuf, size, 1, f)) != 1)
- die ("%s: Error reading file\n", programname);
- buf = framebuf;
- }
- }
-
- /* check for and ignore 0xf100 frames */
- if (fh_magic == 0xf100) {
-
- totalframes--; /* don't count this frame */
- frame--;
-
- } else {
-
- /* consistency check */
- if (fh_magic != 0xf1fa)
- die ("%s: Unrecognised magic number in frame %04x %lu\n",
- programname, fh_magic, fh_size);
-
- /* loop for each chunk */
- for (chunk = 0; chunk < fh_chunks; chunk++) {
-
- /* examine the chunk header */
- ch = (struct chunkheader *)buf;
- if (firstloop || !opt.ram) {
- swapl (&ch->size);
- swapw (&ch->type);
- }
- chunkbuf = buf + sizeof(struct chunkheader);
- buf += (extractl (&ch->size) + 1) & ~1;
- ch_type = extractw (&ch->type);
-
- /* uncompress chunk into chunky pixels */
- switch (ch_type) {
-
- case FLI_SS2:
- p = chunkbuf;
- p2 = chunky;
- lines = *p++;
- lines |= (*p++ << 8);
- for ( ; lines > 0; lines--) {
- do {
- packets = *p++;
- packets |= (*p++ << 8);
- if (packets > 32767)
- if (packets > 49151)
- p2 += (65536 - packets) * (ULONG)screen_width;
- else
- *(p2 + screen_width - 1) = (packets & 0xff);
- } while (packets >= 32768);
- p3 = p2;
- for ( ; packets > 0; packets--) {
- p3 += *p++;
- bsize = *p++;
- if (bsize > 127) {
- bsize = 256 - bsize;
- if (opt.mode == MODE_COLOUR) {
- /*
- repmem (p3, p, 2, bsize);
- p3 += (bsize << 1);
- */
- for (i = bsize; i > 0; i--) {
- *p3++ = *p;
- *p3++ = *(p + 1);
- }
- p += 2;
- } else {
- pattern[1] = xlate[*p++];
- pattern[0] = xlate[*p++];
- /*
- repmem (p3, pattern, 2, bsize);
- p3 += (bsize << 1);
- */
- for (i = bsize; i > 0; i--) {
- *p3++ = pattern[1];
- *p3++ = pattern[0];
- }
- }
- } else {
- bsize <<= 1;
- if (opt.mode == MODE_COLOUR) {
- memcpy (p3, p, bsize);
- /*
- CopyMem (p, p3, bsize);
- */
- p += bsize;
- p3 += bsize;
- } else
- for (i = bsize; i > 0; i--)
- *p3++ = xlate[*p++];
- }
- }
- p2 += screen_width;
- }
- break;
-
- case FLI_256_COLOR:
- case FLI_COLOR:
- p = chunkbuf;
- packets = *p++;
- packets |= (*p++ << 8);
- c = 0;
- for ( ; packets > 0; packets--) {
- c += *p++;
- n = *p++;
- if (n == 0)
- n = 256;
- for (m = 0; m < n; m++) {
- if (ch_type == FLI_256_COLOR) {
- (*colourtable)[c][0] = *p++; /* R */
- (*colourtable)[c][1] = *p++; /* G */
- (*colourtable)[c][2] = *p++; /* B */
- } else {
- (*colourtable)[c][0] = *p++ << 2; /* R */
- (*colourtable)[c][1] = *p++ << 2; /* G */
- (*colourtable)[c][2] = *p++ << 2; /* B */
- }
- c++;
- }
- }
- switch (opt.mode) {
- case MODE_COLOUR4:
- case MODE_EHB:
- median_cut (*colourtable, viewcolourtable, xlate, opt.mode);
- break;
- case MODE_GREY:
- for (c = 0; c < 256; c++)
- xlate[c] = ((((UWORD)(*colourtable)[c][0]) +
- ((UWORD)(*colourtable)[c][1]) +
- ((UWORD)(*colourtable)[c][2])) / 3) >> 4;
- break;
- case MODE_COLOUR:
- break;
- }
- palette_changed = TRUE;
- break;
-
- case FLI_LC:
- p = chunkbuf;
- y = *p++;
- y |= (*p++ << 8);
- p2 = &chunky[y * screen_width];
- lines = *p++;
- lines |= (*p++ << 8);
- for ( ; lines > 0; lines--) {
- p3 = p2;
- for (packets = *p++; packets > 0; packets--) {
- p3 += *p++;
- bsize = *p++;
- if (bsize > 127) {
- bsize = 256 - bsize;
- memset (p3, xlate[*p++], bsize);
- p3 += bsize;
- } else {
- if (opt.mode == MODE_COLOUR) {
- memcpy (p3, p, bsize);
- /*
- CopyMem (p, p3, bsize);
- */
- p += bsize;
- p3 += bsize;
- } else
- for (i = bsize; i > 0; i--)
- *p3++ = xlate[*p++];
- }
- }
- p2 += screen_width;
- }
- break;
-
- case FLI_BLACK:
- memset (chunky, xlate[0], screen_width * (ULONG)h.height);
- break;
-
- case FLI_BRUN:
- p = chunkbuf;
- p2 = chunky;
- for (lines = h.height; lines > 0; lines--) {
- p3 = p2 + h.width;
- p++; /* skip packet count */
- while (p2 < p3) {
- bsize = *p++;
- if (bsize <= 127) {
- memset (p2, xlate[*p++], bsize);
- p2 += bsize;
- } else {
- bsize = 256 - bsize;
- if (opt.mode == MODE_COLOUR) {
- memcpy (p2, p, bsize);
- /*
- CopyMem (p, p2, bsize);
- */
- p += bsize;
- p2 += bsize;
- } else
- for (i = bsize; i > 0; i--)
- *p2++ = xlate[*p++];
- }
- }
- p2 += (screen_width - h.width);
- }
- break;
-
- case FLI_COPY:
- if (opt.mode == MODE_COLOUR)
- if (h.width == screen_width) {
- /*
- memcpy (chunky, chunkbuf, h.width * (ULONG)h.height);
- */
- CopyMemQuick (chunkbuf, chunky, screen_width * (ULONG)h.height);
- } else {
- p = chunkbuf;
- p2 = chunky;
- for (lines = h.height; lines > 0; lines--) {
- CopyMemQuick (p, p2, h.width);
- p += h.width;
- p2 += screen_width;
- }
- }
- else {
- if (h.width == screen_width) {
- p2 = chunky;
- for (l = h.width * (ULONG)h.height; l > 0; l--)
- *p2++ = xlate[*p++];
- } else {
- p = chunkbuf;
- p2 = chunky;
- for (lines = h.height; lines > 0; lines--) {
- for (i = h.width; i > 0; i--)
- *p2++ = xlate[*p++];
- p2 += (screen_width - h.width);
- }
- }
- }
- break;
-
- case FLI_PSTAMP:
- break;
-
- default:
- die ("%s: Unrecognised chunk type %04x\n", programname, ch_type);
- break;
- } /* end of switch for each chunk type */
-
- } /* end of loop for each chunk within frame */
-
- /* update amiga's colourtable if palette has changed in this frame */
- if (palette_changed) {
- switch (opt.mode) {
- case MODE_COLOUR4:
- LoadRGB4 (&s->ViewPort, viewcolourtable, 16);
- break;
- case MODE_EHB:
- LoadRGB4 (&s->ViewPort, viewcolourtable, 32);
- break;
- case MODE_GREY:
- break;
- case MODE_COLOUR:
- for (c = 0; c < (1 << screen_depth); c++) {
- ((ULONG *)viewcolourtable)[3*c+1] = (*colourtable)[c][0] << 24;
- ((ULONG *)viewcolourtable)[3*c+2] = (*colourtable)[c][1] << 24;
- ((ULONG *)viewcolourtable)[3*c+3] = (*colourtable)[c][2] << 24;
- }
- LoadRGB32 (&s->ViewPort, (ULONG *)viewcolourtable);
- break;
- }
- palette_changed = FALSE;
- }
-
- /* Wait until it is safe to modify bitmap without flicker (if v39) */
- if (v39 && opt.dbuf) {
- if (!safe) {
- Wait (1 << safeport->mp_SigBit);
- while (GetMsg (safeport) != NULL) /* clear message queue */
- /* nothing */ ;
- safe = TRUE;
- }
- }
-
- /* render into the non-displayed raster (if double-buffering) */
- if (opt.dbuf)
- which = 1 - which;
-
- /* convert from chunky pixels to (hidden) planar raster[which] */
- if (opt.rom) {
- /* WritePixelArray8() destroys original chunky, so make a copy */
- CopyMemQuick (chunky, copy_of_chunky, screen_width * (ULONG)h.height);
- WritePixelArray8 (&rp[which], 0, 0, screen_width-1, h.height-1,
- copy_of_chunky, &temprp);
- } else if (opt.cmp) {
- switch (screen_depth) {
- case 4:
- c2p_4_cmp (chunky, raster[which], compare_chunky[which],
- (screen_width * (ULONG)h.height) >> 3);
- break;
- case 6:
- if (screen_width == 320 && h.height == 200)
- c2p320x200x6_cmp (chunky, raster[which], compare_chunky[which]);
- else
- c2p_6_cmp (chunky, raster[which], compare_chunky[which],
- (screen_width * (ULONG)h.height) >> 3);
- break;
- case 8:
- if (screen_width == 320 && h.height == 200)
- c2p320x200x8_cmp (chunky, raster[which], compare_chunky[which]);
- else
- c2p_8_cmp (chunky, raster[which], compare_chunky[which],
- (screen_width * (ULONG)h.height) >> 3);
- break;
- default:
- die ("%s: Unsupported resolution\n", programname);
- break;
- }
- } else if (m68040) {
- switch (screen_depth) {
- case 4:
- c2p_4_040 (chunky, raster[which],
- (screen_width * (ULONG)h.height) >> 3);
- break;
- case 6:
- if (screen_width == 320 && h.height == 200)
- c2p320x200x6_040 (chunky, raster[which]);
- else
- c2p_6_040 (chunky, raster[which],
- (screen_width * (ULONG)h.height) >> 3);
- break;
- case 8:
- if (screen_width == 320 && h.height == 200)
- c2p320x200x8_040 (chunky, raster[which]);
- else
- c2p_8_040 (chunky, raster[which],
- (screen_width * (ULONG)h.height) >> 3);
- break;
- default:
- die ("%s: Unsupported resolution\n", programname);
- break;
- }
- } else {
- switch (screen_depth) {
- case 4:
- c2p_4 (chunky, raster[which], buff0, buff1,
- TimerBase, GfxBase, UtilityBase,
- (screen_width * (ULONG)h.height) >> 3);
- break;
- case 6:
- if (screen_width == 320 && h.height == 200)
- c2p320x200x6 (chunky, raster[which], buff0, buff1,
- TimerBase, GfxBase, UtilityBase);
- else
- c2p_6 (chunky, raster[which], buff0, buff1,
- TimerBase, GfxBase, UtilityBase,
- (screen_width * (ULONG)h.height) >> 3);
- break;
- case 8:
- if (screen_width == 320 && h.height == 200)
- c2p320x200x8 (chunky, raster[which], buff0, buff1,
- TimerBase, GfxBase, UtilityBase);
- else
- c2p_8 (chunky, raster[which], buff0, buff1,
- TimerBase, GfxBase, UtilityBase,
- (screen_width * (ULONG)h.height) >> 3);
- break;
- default:
- die ("%s: Unsupported resolution\n", programname);
- break;
- }
- }
-
- /* make the new raster visible (if double-buffering) */
- if (opt.dbuf) {
- if (v39) {
- oldpri = SetTaskPri (thistask, 20); /* don't flicker when mouse moves */
- /* Wait until it is safe to swap bitmaps without flicker */
- if (!disp) {
- Wait (1 << dispport->mp_SigBit);
- while (GetMsg (dispport) != NULL) /* clear message queue */
- /* nothing */ ;
- disp = TRUE;
- }
- if (ChangeScreenBuffer (s, sb[which])) {
- disp = FALSE;
- safe = FALSE;
- }
- SetTaskPri (thistask, oldpri); /* restore task priority */
- } else {
- s->ViewPort.RasInfo->BitMap = &screen_bm[which];
- MakeScreen (s);
- RethinkDisplay ();
- }
- }
-
- /* check for CTRL/C or BREAK */
- if (SetSignal (0, 0) & SIGBREAKF_CTRL_C) {
- SetSignal (0, SIGBREAKF_CTRL_C);
- printf ("***Break\n");
- exit (0);
- }
-
- /* check for intuition messages */
- while ((msg = (struct IntuiMessage *)GetMsg (w->UserPort)) != NULL) {
- class = msg->Class;
- code = msg->Code;
- ReplyMsg ((struct Message *)msg);
- if (class == IDCMP_VANILLAKEY)
- switch (code) {
- case 0x03: /* CTRL/C */
- printf ("***Break\n");
- exit (0);
- case 0x1b: /* ESC */
- case 0x51: /* q */
- case 0x71: /* Q */
- going = FALSE;
- break;
- default:
- break;
- }
- }
-
- } /* end of if frame magic != 0xf100 */
-
- /* seek to the beginning of the next frame or deallocate frame ram */
- if (opt.ram)
- buf = framebuf + fh_size - sizeof(struct frameheader);
- else
- if (framebuf != NULL)
- free (framebuf);
- framebuf = NULL;
-
- /* seek back to frame 1 (the 2nd frame) when we get to the last frame */
- if (frame++ == h.frames)
- if (opt.once)
- going = FALSE;
- else {
- firstloop = FALSE;
- frame = 1;
- if (opt.ram)
- buf = restartptr;
- else
- if (fseek (f, restartpos, SEEK_SET) == -1)
- die ("%s: Error seeking file\n", programname);
- }
-
- totalframes++;
-
- } /* end of loop for each frame */
-
- /* cleanup pending messages */
- if (!safe) {
- Wait (1 << safeport->mp_SigBit);
- while (GetMsg (safeport) != NULL) /* clear message queue */
- /* nothing */ ;
- safe = TRUE;
- }
- if (!disp) {
- Wait (1 << dispport->mp_SigBit);
- while (GetMsg (dispport) != NULL) /* clear message queue */
- /* nothing */ ;
- disp = TRUE;
- }
-
- /* find out and display how long it took */
- ReadEClock (time1);
- printf ("%s: Frames per second = %5.2lf\n", programname,
- 1000000.0 * totalframes /
- (((time1->ev_hi - time0->ev_hi) * 4294967296.0
- + (time1->ev_lo - time0->ev_lo)) * micros_per_eclock));
-
- /* close files and free memory */
- if (f != NULL) {
- fclose (f);
- f = NULL;
- }
- if (colourtable != NULL) {
- free (colourtable);
- colourtable = NULL;
- }
- if (viewcolourtable != NULL) {
- free (viewcolourtable);
- viewcolourtable = NULL;
- }
- if (xlate != NULL) {
- free (xlate);
- xlate = NULL;
- }
- if (filebuf != NULL) {
- free (filebuf);
- filebuf = NULL;
- }
- if (!opt.ram) {
- if (fh != NULL) {
- free (fh);
- fh = NULL;
- }
- }
- if (compare_chunky[1] != NULL) {
- free (compare_chunky[1]);
- compare_chunky[1] = NULL;
- }
- if (compare_chunky[0] != NULL) {
- free (compare_chunky[0]);
- compare_chunky[0] = NULL;
- }
- if (chunky != NULL) {
- free (chunky);
- chunky = NULL;
- };
- if (copy_of_chunky != NULL) {
- free (copy_of_chunky);
- copy_of_chunky = NULL;
- }
- if (w != NULL) {
- CloseWindow (w);
- w = NULL;
- }
- if (sb[1] != NULL) {
- FreeScreenBuffer (s, sb[1]);
- sb[1] = NULL;
- }
- if (sb[0] != NULL) {
- FreeScreenBuffer (s, sb[0]);
- sb[0] = NULL;
- }
- if (dispport != NULL) {
- DeletePort (dispport);
- dispport = NULL;
- }
- if (safeport != NULL) {
- DeletePort (safeport);
- safeport = NULL;
- }
- if (s != NULL) {
- CloseScreen (s);
- s = NULL;
- }
- if (tmpras != NULL) {
- FreeRaster (tmpras, screen_width, screen_depth);
- tmpras = NULL;
- }
- if (buff1 != NULL) {
- FreeMem (buff1, screen_width * (ULONG)h.height);
- buff1 = NULL;
- }
- if (buff0 != NULL) {
- FreeMem (buff0, screen_width * (ULONG)h.height);
- buff0 = NULL;
- }
- if (raster[1] != NULL) {
- FreeRaster (raster[1], screen_width, BITMAP_DEPTH * h.height);
- raster[1] = NULL;
- }
- if (raster[0] != NULL) {
- FreeRaster (raster[0], screen_width, BITMAP_DEPTH * h.height);
- raster[0] = NULL;
- }
- }
-
- /****************************************************************************/
-
- struct TagItem frtags[] = {
- {ASL_Hail, 0},
- {ASL_Pattern, (ULONG)"#?.fl[ic]"},
- {ASL_OKText, (ULONG)"Play"},
- {ASL_CancelText, (ULONG)"Cancel"},
- {ASL_FuncFlags, FILF_PATGAD},
- {TAG_DONE, 0}
- };
-
- char resultstring[128];
-
- void filerequestloop (struct options *opt)
- {
- if ((AslBase = OpenLibrary ("asl.library", 37L)) != NULL) {
- frtags[0].ti_Data = (ULONG)programname;
- if (AslBase->lib_Version < 39)
- frtags[1].ti_Data = (ULONG)"#?.fl?";
- if ((fr = (struct FileRequester *)AllocAslRequest
- (ASL_FileRequest, frtags)) != NULL) {
- while (AslRequest (fr, NULL)) {
- strcpy (resultstring, fr->rf_Dir);
- AddPart (resultstring, fr->rf_File, 128);
- animate_file (resultstring, *opt);
- }
- FreeAslRequest (fr);
- fr = NULL;
- }
- CloseLibrary (AslBase);
- AslBase = NULL;
- }
- }
-
- /****************************************************************************/
-
- LONG argarray[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
- int main (int argc, char *argv[])
- {
- struct WBStartup *argmsg;
- struct WBArg *wb_arg;
- char **fnames;
- UWORD ktr;
- struct options opt;
-
-
- /* standard libraries are auto-opened here by SAS/C */
-
- /* find out about ourself */
- thistask = FindTask (NULL);
- GetProgramName (programname, 19);
- v39 = (GfxBase->LibNode.lib_Version >= 39);
- m68040 = (SysBase->AttnFlags & AFF_68040) != 0;
-
- /* timer stuff */
- if ((timerio = (struct timerequest *)AllocMem (sizeof(struct timerequest),
- MEMF_CLEAR | MEMF_PUBLIC)) == NULL)
- die ("%s: Out of memory\n", programname);
- if (timerclosed = OpenDevice (TIMERNAME, UNIT_MICROHZ,
- (struct IORequest *)timerio, 0))
- die ("%s: Can't open timer.device!\n", programname);
- TimerBase = (struct Library *)timerio->tr_node.io_Device;
- if ((time0 = (struct EClockVal *)AllocMem (sizeof(struct EClockVal),
- MEMF_CLEAR | MEMF_PUBLIC)) == NULL)
- die ("%s: Out of memory\n", programname);
- if ((time1 = (struct EClockVal *)AllocMem (sizeof(struct EClockVal),
- MEMF_CLEAR | MEMF_PUBLIC)) == NULL)
- die ("%s: Out of memory\n", programname);
- micros_per_eclock = 1000000.0 / (double)ReadEClock (time0);
-
- /* set default switches */
- opt.ram = TRUE;
- opt.mode = MODE_COLOUR;
- opt.once = FALSE;
- opt.rom = FALSE;
- opt.dbuf = TRUE;
- opt.cmp = TRUE;
-
- /* parse workbench message or commandline */
- if (argc == 0) {
- argmsg = (struct WBStartup *)argv;
- wb_arg = argmsg->sm_ArgList;
- strcpy (programname, wb_arg->wa_Name);
- if (argmsg->sm_NumArgs <= 1)
- filerequestloop (&opt);
- else {
- wb_arg++;
- for (ktr = 1; ktr < argmsg->sm_NumArgs; ktr++, wb_arg++)
- if (wb_arg->wa_Lock != NULL) {
- olddir = CurrentDir (wb_arg->wa_Lock);
- animate_file (wb_arg->wa_Name, opt);
- CurrentDir (olddir);
- olddir = NULL;
- } else
- animate_file (wb_arg->wa_Name, opt);
- }
- } else {
- if ((rdargs = ReadArgs
- ("FILE/M,DISK/S,RAM/S,ONCE/S,COLOUR/S,COLOR/S,EHB/S,COLOUR4/S,COLOR4/S,GREY/S,GRAY/S,ROM/S,NODBUF/S,NOCOMPARE/S",
- argarray, NULL)) != NULL) {
- if (argarray[1])
- opt.ram = FALSE;
- if (argarray[2])
- opt.ram = TRUE;
- if (argarray[3])
- opt.once = TRUE;
- if (argarray[4] || argarray[5])
- opt.mode = MODE_COLOUR;
- if (argarray[6])
- opt.mode = MODE_EHB;
- if (argarray[7] || argarray[8])
- opt.mode = MODE_COLOUR4;
- if (argarray[9] || argarray[10])
- opt.mode = MODE_GREY;
- if (argarray[11])
- opt.rom = TRUE;
- if (argarray[12])
- opt.dbuf = FALSE;
- if (argarray[13])
- opt.cmp = FALSE;
- fnames = (char **)argarray[0];
- if (fnames == NULL || *fnames == NULL)
- filerequestloop (&opt);
- else
- while (*fnames != NULL)
- animate_file (*fnames++, opt);
- FreeArgs (rdargs);
- rdargs = NULL;
- }
- }
-
- /* Let the user see how fast it went before the window closes */
- if (argc == 0)
- Delay (200);
-
- /* exit program with success code */
- return (0);
-
- /* SAS/C executes _STDcleanup() automatically on exit or break */
-
- }
-
- /****************************************************************************/
-