mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@21 3b4a5df2-a311-0410-b5c6-a8a6f20db521
1700 lines
41 KiB
C++
1700 lines
41 KiB
C++
//**************************************************************************
|
|
//
|
|
// Filename : flic.c
|
|
//
|
|
// Purpose : Display System for .flc and .fli Flic Files
|
|
//
|
|
// This program is derived from the program decribed in the article "The
|
|
// Flic File Format" on page 18 of the March 1993 edition of Dr. Dobb's
|
|
// Journal. It was restructured from the top down to meet the
|
|
// requirements of Sir-Tech. The high level routines were designed to
|
|
// provided easy integration with existing applications. Except for a few
|
|
// identifiers, the low level routines were not modified.
|
|
//
|
|
// All of the code for these routines in contained in this file and the
|
|
// file "flic.h".
|
|
//
|
|
// Modification history :
|
|
//
|
|
// 06-09-94:??? - Creation
|
|
// ???:David Smoth - ???
|
|
// ???:Bret Rowdon for RIO/GORGE - added 640x480 SVGA support
|
|
// 05-11jun96:HJH - added routines for bitmap use, and
|
|
// other utilities
|
|
// 08-May-97 ARM Adapted for Win95 Standard Gaming Platform
|
|
//
|
|
//**************************************************************************
|
|
|
|
//**************************************************************************
|
|
//
|
|
// Includes
|
|
//
|
|
//**************************************************************************
|
|
|
|
//#include "stdafx.h"
|
|
#include <conio.h>
|
|
#include "flic.h"
|
|
#include "windows.h"
|
|
#include "types.h"
|
|
#include "wcheck.h"
|
|
|
|
//**************************************************************************
|
|
//
|
|
// Variables
|
|
//
|
|
//**************************************************************************
|
|
|
|
//Flic flic;
|
|
char pcxbuf[(640*480)];
|
|
char FlicPal[768];
|
|
|
|
//extern char buffer[(640*480)];
|
|
//extern char buffer2[(640*480)];
|
|
|
|
//**************************************************************************
|
|
//
|
|
// Function prototypes.
|
|
//
|
|
//**************************************************************************
|
|
|
|
static ErrCode flic_next_frame(Flic *flic, BOOL fDecode);
|
|
|
|
//**************************************************************************
|
|
//
|
|
// Functions
|
|
//
|
|
//**************************************************************************
|
|
|
|
//**************************************************************************
|
|
//
|
|
// Low level Functions
|
|
//
|
|
//**************************************************************************
|
|
|
|
//**************************************************************************
|
|
//
|
|
// screen_put_dot
|
|
//
|
|
// Set one dot.
|
|
//
|
|
// Parameter List :
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void screen_put_dot(FlicScreen *s, int x, int y, Pixel color)
|
|
{
|
|
// First clip it.
|
|
if (x < 0 || y < 0 || x >= s->width || y >= s->height)
|
|
return;
|
|
|
|
// Then set it.
|
|
s->pixels[(unsigned)(s->height-y-1) * s->width + x] = color;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// line_clip
|
|
//
|
|
// Clip a horizontal line segment so that it fits on the screen.
|
|
// Return FALSE if clipped out entirely.
|
|
//
|
|
// Parameter List :
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static Boolean line_clip(FlicScreen *s, int *px, int *py, int *pwidth)
|
|
{
|
|
int x = *px;
|
|
int y = *py;
|
|
int width = *pwidth;
|
|
int xend = x + width;
|
|
|
|
if (y < 0 || y >= s->height || xend < 0 || x >= s->width)
|
|
return FALSE; /* Clipped off screen. */
|
|
if (x < 0)
|
|
{
|
|
*pwidth = width = width + x; /* and shortens width. */
|
|
*px = 0;
|
|
}
|
|
if (xend > s->width)
|
|
{
|
|
*pwidth = width = width - (xend - s->width);
|
|
}
|
|
if (width < 0)
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// oldscreen_copy_seg
|
|
//
|
|
// Copy pixels from memory into screen.
|
|
//
|
|
// Parameter List :
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void oldscreen_copy_seg(FlicScreen *s, int x, int y, Pixel *pixels, int count)
|
|
{
|
|
Pixel *pt;
|
|
//int xend;
|
|
int unclipped_x = x;
|
|
int dx;
|
|
|
|
// First let's do some clipping.
|
|
if (!line_clip(s, &x, &y, &count))
|
|
return;
|
|
|
|
dx = x - unclipped_x; // Clipping change in start position.
|
|
if (dx != 0)
|
|
pixels += dx; // Advance over clipped pixels.
|
|
|
|
// Calculate start screen address.
|
|
//pt = s->pixels + (unsigned)y * (unsigned)s->width + (unsigned)x;
|
|
pt = s->pixels + (unsigned)(s->height-y-1) * (unsigned)s->width + (unsigned)x;
|
|
|
|
// Copy pixels to display.
|
|
while (--count >= 0)
|
|
*pt++ = *pixels++;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// screen_repeat_one
|
|
//
|
|
// Draw a horizontal line of a solid color
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// FlicScreen *s -> screen to write to
|
|
// int x -> x position to write to
|
|
// int y -> y position to write to
|
|
// Pixel color -> colour to write
|
|
// int count -> how many times to write
|
|
//
|
|
// Return Value :
|
|
//
|
|
// Modification history :
|
|
//
|
|
// 01jun96:HJH -> reversed the screen up and down so that the
|
|
// bitmaps wouldn't come out upside down (I put in
|
|
// the "s->height -")
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void screen_repeat_one(FlicScreen *s, int x, int y, Pixel color, int count)
|
|
{
|
|
Pixel *pt;
|
|
|
|
// First let's do some clipping.
|
|
if (!line_clip(s, &x, &y, &count))
|
|
return;
|
|
|
|
// Calculate start screen address.
|
|
pt = s->pixels + (unsigned)(s->height-y-1) * (unsigned)s->width + (unsigned)x;
|
|
|
|
// Repeat pixel on display.
|
|
while (--count >= 0)
|
|
*pt++ = color;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// screen_repeat_two
|
|
//
|
|
// Repeat 2 pixels count times on screen.
|
|
//
|
|
// Parameter List :
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void screen_repeat_two(FlicScreen *s, int x, int y, Pixels2 pixels2, int count)
|
|
{
|
|
Pixels2 *pt;
|
|
int is_odd;
|
|
|
|
// First let's do some clipping.
|
|
count <<= 1; // Convert from word to pixel count.
|
|
if (!line_clip(s, &x, &y, &count))
|
|
return;
|
|
is_odd = (count&1); // Did it turn odd after clipping? Ack!
|
|
count >>= 1; // Convert back to word count.
|
|
|
|
// Calculate start screen address.
|
|
pt = (Pixels2 *)(s->pixels + (unsigned)(s->height-y-1) * (unsigned)s->width + (unsigned)x);
|
|
|
|
while (--count >= 0) // Go set screen 2 pixels at a time.
|
|
*pt++ = pixels2;
|
|
|
|
if (is_odd) // Deal with pixel at end of screen if needed.
|
|
{
|
|
Pixel *end = (Pixel *)pt;
|
|
*end = pixels2.pixels[0];
|
|
}
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// screen_put_colors
|
|
//
|
|
// Set count colors in color map starting at start. RGB values
|
|
// go from 0 to 255.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// FlicScreen *s -> screen data
|
|
// int start -> start position
|
|
// Colour *colors -> the colors, of course
|
|
// int count -> how many
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void screen_put_colors(FlicScreen *s, int start, Colour *colors, int count)
|
|
{
|
|
int end = start + count;
|
|
int ix;
|
|
|
|
for (ix = start; ix < end; ++ix)
|
|
{
|
|
FlicPal[ix*3]=colors->r>>2;
|
|
FlicPal[ix*3+1]=colors->g>>2;
|
|
FlicPal[ix*3+2]=colors->b>>2;
|
|
++colors;
|
|
}
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// screen_put_colors_64
|
|
//
|
|
// Set count colors in color map starting at start. RGB values
|
|
// go from 0 to 64. */
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// FlicScreen *s -> screen data
|
|
// int start -> start position
|
|
// Colour *colors -> the colors, of course
|
|
// int count -> how many
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void screen_put_colors_64(FlicScreen *s, int start, Colour *colors, int count)
|
|
{
|
|
int end = start + count;
|
|
int ix;
|
|
|
|
for (ix = start; ix < end; ++ix)
|
|
{
|
|
FlicPal[ix*3]=colors->r;
|
|
FlicPal[ix*3+1]=colors->g;
|
|
FlicPal[ix*3+2]=colors->b;
|
|
|
|
++colors;
|
|
}
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// decode_byte_run
|
|
//
|
|
// Byte-run-length decompression.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Uchar *data -> data to be decoded
|
|
// Flic *flic -> flic data containing where to decode to
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void decode_byte_run(Uchar *data, Flic *flic)
|
|
{
|
|
int x,y;
|
|
int width = flic->head.width;
|
|
int height = flic->head.height;
|
|
int psize; // was char -> HJH
|
|
Char *cpt = (Char *)data;
|
|
int end;
|
|
|
|
y = flic->yoff;
|
|
end = flic->xoff + width;
|
|
while (--height >= 0)
|
|
{
|
|
x = flic->xoff;
|
|
cpt += 1; /* skip over obsolete opcount byte */
|
|
psize = 0;
|
|
while ((x+=psize) < end)
|
|
{
|
|
psize = (char)(*cpt++);
|
|
if (psize >= 0)
|
|
{
|
|
screen_repeat_one(&flic->screen, x, y, *cpt++, psize);
|
|
}
|
|
else
|
|
{
|
|
psize = -psize;
|
|
oldscreen_copy_seg(&(flic->screen),(long) x,(long) y, (unsigned char *)cpt, (long)psize);
|
|
cpt += psize;
|
|
}
|
|
}
|
|
y++;
|
|
}
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// decode_delta_fli
|
|
//
|
|
// Fli style delta decompression.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Uchar *data -> data to be decoded
|
|
// Flic *flic -> flic data containing where to decode to
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void decode_delta_fli(Uchar *data, Flic *flic)
|
|
{
|
|
int xorg = flic->xoff;
|
|
int yorg = flic->yoff;
|
|
Short *wpt = (Short *)data;
|
|
Uchar *cpt = (Uchar *)(wpt + 2);
|
|
int x,y;
|
|
Short lines;
|
|
Uchar opcount;
|
|
Char psize;
|
|
|
|
y = yorg + *wpt++;
|
|
lines = *wpt;
|
|
while (--lines >= 0)
|
|
{
|
|
x = xorg;
|
|
opcount = *cpt++;
|
|
while (opcount > 0)
|
|
{
|
|
x += *cpt++;
|
|
psize = *cpt++;
|
|
if (psize < 0)
|
|
{
|
|
psize = -psize;
|
|
screen_repeat_one(&flic->screen, x, y, *cpt++, psize);
|
|
x += psize;
|
|
opcount-=1;
|
|
}
|
|
else
|
|
{
|
|
oldscreen_copy_seg(&(flic->screen), (long)x, (long)y, (unsigned char *)cpt,(long) psize);
|
|
cpt += psize;
|
|
x += psize;
|
|
opcount -= 1;
|
|
}
|
|
}
|
|
y++;
|
|
}
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// decode_delta_flc
|
|
//
|
|
// Flc-style delta decompression. The data is word oriented though
|
|
// a lot of the control info (how to skip, how many words to
|
|
// copy) are byte oriented still to save space.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Uchar *data -> data to be decoded
|
|
// Flic *flic -> flic data containing where to decode to
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void decode_delta_flc(Uchar *data, Flic *flic)
|
|
{
|
|
int xorg = flic->xoff;
|
|
int yorg = flic->yoff;
|
|
int width = flic->head.width;
|
|
int x,y;
|
|
Short lp_count;
|
|
Short opcount;
|
|
int psize;
|
|
union {Short *w; Uchar *ub; Char *b; Pixels2 *p2;} wpt;
|
|
int lastx;
|
|
|
|
|
|
lastx = xorg + width - 1;
|
|
wpt.ub = data;
|
|
lp_count = *wpt.w++;
|
|
y = yorg;
|
|
goto LPACK;
|
|
|
|
SKIPLINES: /* Advance over some lines. */
|
|
y -= opcount;
|
|
|
|
LPACK: /* do next line */
|
|
if ((opcount = *wpt.w++) >= 0)
|
|
goto DO_SS2OPS;
|
|
if( ((Ushort)opcount) & 0x4000) /* skip lines */
|
|
goto SKIPLINES;
|
|
screen_put_dot(&flic->screen,(Uchar)opcount,lastx,(Pixel)y); /* put dot at eol with low byte */
|
|
if((opcount = *wpt.w++) == 0)
|
|
{
|
|
++y;
|
|
if (--lp_count > 0)
|
|
goto LPACK;
|
|
goto OUTT;
|
|
}
|
|
DO_SS2OPS:
|
|
x = xorg;
|
|
|
|
PPACK: /* do next packet */
|
|
x += *wpt.ub++;
|
|
psize = *wpt.b++;
|
|
if ((psize += psize) >= 0)
|
|
{
|
|
oldscreen_copy_seg(&(flic->screen), (long)x, (long)y, (unsigned char *)wpt.ub,(long) psize);
|
|
x += psize;
|
|
wpt.ub += psize;
|
|
if (--opcount != 0)
|
|
goto PPACK;
|
|
++y;
|
|
if (--lp_count > 0)
|
|
goto LPACK;
|
|
}
|
|
else
|
|
{
|
|
psize = -psize;
|
|
screen_repeat_two(&flic->screen, x, y, *wpt.p2++, psize>>1);
|
|
x += psize;
|
|
if (--opcount != 0)
|
|
goto PPACK;
|
|
++y;
|
|
if (--lp_count > 0)
|
|
goto LPACK;
|
|
}
|
|
OUTT:
|
|
return;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// decode_black
|
|
//
|
|
// Decode a BLACK chunk. Set frame to solid color 0 one
|
|
// line at a time.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Uchar *data -> data to be decoded
|
|
// Flic *flic -> flic data containing where to decode to
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void decode_black(Uchar *data, Flic *flic)
|
|
{
|
|
Pixels2 black;
|
|
int i;
|
|
int height = flic->head.height;
|
|
int width = flic->head.width;
|
|
int x = flic->xoff;
|
|
int y = flic->yoff;
|
|
|
|
black.pixels[0] = black.pixels[1] = 0;
|
|
for (i=0; i<height; ++i)
|
|
{
|
|
screen_repeat_two(&flic->screen, x, y+i, black, width/2);
|
|
if (width & 1) /* if odd set last pixel */
|
|
screen_put_dot(&flic->screen, x+width-1, y+i, 0);
|
|
}
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// decode_literal
|
|
//
|
|
// Decode a LITERAL chunk. Just copy data to screen one line at
|
|
// a time.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Uchar *data -> data to be decoded
|
|
// Flic *flic -> flic data containing where to decode to
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void decode_literal(Uchar *data, Flic *flic)
|
|
{
|
|
int i;
|
|
int height = flic->head.height;
|
|
int width = flic->head.width;
|
|
int x = flic->xoff;
|
|
int y = flic->yoff;
|
|
|
|
for (i=0; i<height; ++i)
|
|
{
|
|
oldscreen_copy_seg(&(flic->screen),(long) x,(long)(y+i), (unsigned char *)data,(long) width);
|
|
data += width;
|
|
}
|
|
}
|
|
|
|
|
|
typedef void ColorOut(FlicScreen *s, int start, Colour *colors, int count);
|
|
/* This is the type of output parameter to our decode_color below.
|
|
* Not coincedently screen_put_color is of this type. */
|
|
|
|
|
|
//**************************************************************************
|
|
//
|
|
// decode_color
|
|
//
|
|
// Decode color map. Put results into output. The two color
|
|
// compressions are identical except for whether the RGB values
|
|
// are 0-63 or 0-255. Passing in an output that does the appropriate
|
|
// shifting on the way to the real pallete lets us use the same
|
|
// code for both COLOR_64 and COLOR_256 compression.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Uchar *data -> data to decode
|
|
// Flic *flic -> the flic
|
|
// ColorOut *output -> place to put decoded data
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void decode_color(Uchar *data, Flic *flic, ColorOut *output)
|
|
{
|
|
int start = 0;
|
|
Uchar *cbuf = (Uchar *)data;
|
|
Short *wp = (Short *)cbuf;
|
|
Short ops;
|
|
int count;
|
|
|
|
ops = *wp;
|
|
cbuf += sizeof(*wp);
|
|
while (--ops >= 0)
|
|
{
|
|
start += *cbuf++;
|
|
if ((count = *cbuf++) == 0)
|
|
count = 256;
|
|
(*output)(&flic->screen, start, (Colour *)cbuf, count);
|
|
cbuf += 3*count;
|
|
start += count;
|
|
}
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// decode_color_256
|
|
//
|
|
// Decode COLOR_256 chunk.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Uchar *data -> data to decode
|
|
// Flic *flic -> the flic
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void decode_color_256(Uchar *data, Flic *flic)
|
|
{
|
|
decode_color(data, flic, screen_put_colors);
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// decode_color_64
|
|
//
|
|
// Decode COLOR_64 chunk.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Uchar *data -> data to decode
|
|
// Flic *flic -> the flic
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static void decode_color_64(Uchar *data, Flic *flic)
|
|
{
|
|
decode_color(data, flic, screen_put_colors_64);
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// decode_frame
|
|
//
|
|
// Decode a frame that is in memory already into screen.
|
|
// Here we just loop through each chunk calling appropriate
|
|
// chunk decoder.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic
|
|
// FrameHead *frame -> info about the frame
|
|
// Uchar *data -> data to decode
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static ErrCode decode_frame(Flic *flic, FrameHead *frame, Uchar *data)
|
|
{
|
|
int i;
|
|
ChunkHead *chunk;
|
|
|
|
for (i=0; i<frame->chunks; ++i)
|
|
{
|
|
chunk = (ChunkHead *)data;
|
|
data += chunk->size;
|
|
switch (chunk->type)
|
|
{
|
|
case COLOR_256:
|
|
if (flic->screen.change_palette)
|
|
//decode_color_256((Uchar *)(chunk+1), flic);
|
|
decode_color_256( (((Uchar *)chunk) + 4 ), flic);
|
|
break;
|
|
case DELTA_FLC:
|
|
decode_delta_flc((Uchar *)(chunk+1), flic);
|
|
break;
|
|
case COLOR_64:
|
|
if (flic->screen.change_palette)
|
|
decode_color_64((Uchar *)(chunk+1), flic);
|
|
break;
|
|
case DELTA_FLI:
|
|
decode_delta_fli((Uchar *)(chunk+1), flic);
|
|
break;
|
|
case BLACK_FRAME:
|
|
decode_black((Uchar *)(chunk+1), flic);
|
|
break;
|
|
case BYTE_RUN:
|
|
decode_byte_run((Uchar *)(chunk+1), flic);
|
|
break;
|
|
case LITERAL:
|
|
decode_literal((Uchar *)(chunk+1), flic);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static ErrCode file_read_big_block(FILE *file, char *block, Ulong size)
|
|
/* Read in a big block. Could be bigger than 64K. */
|
|
{
|
|
char *pt = block;
|
|
unsigned size1;
|
|
|
|
while (size != 0)
|
|
{
|
|
size1 = ((size > 0xFFF0) ? 0xFFF0 : size);
|
|
if ( fread(pt, size1, 1, file) != 1 )
|
|
return ErrFlicRead;
|
|
pt += size1; // Advance pointer to next batch.
|
|
size -= size1; // Subtract current batch from size to go.
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// fill_in_frame2
|
|
//
|
|
// This figures out where the second frame of the flic is
|
|
// (useful for playing in a loop).
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static ErrCode fill_in_frame2(Flic *flic)
|
|
{
|
|
FrameHead head;
|
|
//ErrCode err;
|
|
|
|
(*flic->seek)(flic, flic->head.oframe1);
|
|
if ( fread(&head, sizeof(head), 1, flic->file) != 1 )
|
|
return ErrFlicRead;
|
|
|
|
if ( fread(&head, sizeof(head), 1, flic->file) != 1 )
|
|
return ErrFlicRead;
|
|
|
|
flic->head.oframe2 = flic->head.oframe1 + head.size;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// flic_next_frame
|
|
//
|
|
// Advance to next frame of flic.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static ErrCode flic_next_frame(Flic *flic, BOOL fDecode)
|
|
{
|
|
FrameHead head;
|
|
ErrCode err = 0;
|
|
long size;
|
|
|
|
if ( fread(&head, sizeof(head), 1, flic->file) != 1 )
|
|
err = ErrFlicRead;
|
|
else
|
|
{
|
|
if (head.type == FRAME_TYPE)
|
|
{
|
|
size = head.size - sizeof(head); /* Don't include head. */
|
|
if (size > 0)
|
|
{
|
|
if (size > 500000)
|
|
{
|
|
//TRACE("FLC chunk too big: %d\n",size);
|
|
//Assert(0);
|
|
FastDebugMsg(String("flic_next_frame: FLC chunk too big: %d", size));
|
|
size = 64000;
|
|
}
|
|
if (!(err = file_read_big_block(flic->file, pcxbuf, size)))
|
|
{
|
|
if ( fDecode )
|
|
err = decode_frame(flic, &head, (unsigned char *)pcxbuf);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
err = ErrFlicBadFrame;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// flic_check_frame
|
|
//
|
|
// A dummy routine to be called for each frame.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
static Boolean flic_check_frame(Flic *flic)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// File io
|
|
//
|
|
//**************************************************************************
|
|
|
|
static ErrCode flic_open(Flic *flic, const char *filename)
|
|
{
|
|
return (flic->file = fopen(filename, "rb")) ? 0 : ErrFlicAccess;
|
|
}
|
|
|
|
static ErrCode flic_seek(Flic *flic, long offset)
|
|
{
|
|
return fseek(flic->file, offset, SEEK_SET) ? ErrFlicSeek : 0;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicInit
|
|
//
|
|
// Initializes a flic object.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
void FlicInit(Flic *flic, unsigned screen_width, unsigned screen_height, char change_palette, char *Buff)
|
|
{
|
|
flic->file = NULL;
|
|
//flic->lib.names = NULL;
|
|
|
|
flic->open = flic_open; /* Set routines for single flick file access */
|
|
flic->seek = flic_seek;
|
|
|
|
flic->check_frame = flic_check_frame; /* Select a dummy routine */
|
|
|
|
/** Info used by low level routines */
|
|
|
|
flic->screen.pixels = (unsigned char *)Buff; // (char *) 0xa0000;
|
|
flic->screen.width = screen_width;
|
|
flic->screen.height = screen_height;
|
|
flic->screen.change_palette = change_palette;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicOpen
|
|
//
|
|
// Opens a flic file or locates a flic file in a library.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic
|
|
// const char *filename -> filename of flic to open
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
ErrCode FlicOpen(Flic *flic, const char *filename)
|
|
{
|
|
ErrCode err;
|
|
|
|
flic->xoff = flic->yoff = 0;
|
|
|
|
if ( !(err = (*flic->open)(flic, filename)) )
|
|
{
|
|
if (fread(&flic->head, sizeof(flic->head), 1, flic->file) != 1)
|
|
err = ErrFlicRead;
|
|
else
|
|
{
|
|
flic->name = filename;
|
|
|
|
if (flic->head.type == FLC_TYPE)
|
|
{
|
|
/* Seek frame 1. */
|
|
(*flic->seek)(flic, flic->head.oframe1);
|
|
return 0;
|
|
}
|
|
if (flic->head.type == FLI_TYPE)
|
|
{
|
|
long i;
|
|
/* Do some conversion work here. */
|
|
flic->head.oframe1 = sizeof(flic->head);
|
|
i=flic->head.speed * 1000L;
|
|
flic->head.speed = i / 70;
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
err = ErrFlicBad;
|
|
printf("flic was bad! \n");
|
|
_getch();
|
|
exit(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
FlicClose(flic); /* Close down and scrub partially opened flic. */
|
|
return err;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicSetOrigin
|
|
//
|
|
// Sets the location of the top left corner of the flic in terms of screen
|
|
// coordinates.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic
|
|
// unsigned x -> x-coord of origin
|
|
// unsigned y -> y-coord of origin
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
void FlicSetOrigin(Flic *flic, unsigned x, unsigned y)
|
|
{
|
|
flic->xoff = x;
|
|
flic->yoff = y;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicClose
|
|
//
|
|
// Closes a flic file if one is open. If a library is open, this function has
|
|
// no effect.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
void FlicClose(Flic *flic)
|
|
{
|
|
if ( flic->file )
|
|
{
|
|
fclose(flic->file);
|
|
flic->file = NULL;
|
|
}
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// flic_play_loop_timer
|
|
//
|
|
// This routine is called at the end of each timer period. The timer is used
|
|
// by the FlicPlay routine. The global variable timer_flag indicates that
|
|
// a time interval has elapsed. FlicPlay resets timer_flag for the next
|
|
// interval.
|
|
//
|
|
// Stack checking must be disabled.
|
|
//
|
|
// Parameter List :
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
#ifdef DEBUG
|
|
#pragma off (check_stack)
|
|
#endif
|
|
|
|
static volatile int timer_flag=1;
|
|
|
|
static void flic_play_loop_timer()
|
|
{
|
|
timer_flag = 1;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
#pragma on (check_stack)
|
|
#endif
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicPlay
|
|
//
|
|
// This is the engine for the flic display system. Call this function to
|
|
// display a flic.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
ErrCode FlicPlay(Flic *flic, Ulong max_loop)
|
|
{
|
|
/*
|
|
ErrCode err;
|
|
HTIMER timer;
|
|
|
|
flic->status.max_loop_count = max_loop;
|
|
flic->status.max_frame_index = flic->head.frames;
|
|
|
|
if (flic->head.oframe2 == 0)
|
|
{
|
|
fill_in_frame2(flic);
|
|
// FastBlitRegionSVGA((char *)(0xa0000),(char *)(flic->screen.pixels),(long)0,(long)640,(long)480,(long)0,(long)640);
|
|
// BlitSVGAPage((char *)(flic->screen.pixels));
|
|
// BlitRegionSVGATst((void *)0xa0000,(void *)(flic->screen.pixels),(long)640,(long)480,(long)640);
|
|
//BlitRegionSVGA((char *)0xa0000,(char *)flic->screen.pixels,(long)0,(long)640,(long)480,(long)0,(long)640);
|
|
}
|
|
|
|
// Seek to first frame.
|
|
(*flic->seek)(flic, flic->head.oframe1);
|
|
// Save time to move on.
|
|
|
|
//videoSetMode(3);
|
|
//printf("speed is %d\n",flic->head.speed);
|
|
//_getch();
|
|
//exit(0);
|
|
|
|
//timer = AIL_register_timer(flic_play_loop_timer);
|
|
//AIL_set_timer_period(timer, flic->head.speed* 1000);
|
|
//timer_flag = 0;
|
|
//AIL_start_timer(timer);
|
|
|
|
// Display first frame.
|
|
if (err = flic_next_frame(flic, TRUE))
|
|
{
|
|
//AIL_release_timer_handle(timer);
|
|
return err;
|
|
}
|
|
|
|
for (flic->status.loop_count = 0; !max_loop || flic->status.loop_count < max_loop;
|
|
++flic->status.loop_count)
|
|
{
|
|
// Seek to second frame
|
|
(*flic->seek)(flic, flic->head.oframe2);
|
|
// Loop from 2nd frame thru ring frame
|
|
for (flic->status.frame_index=0;
|
|
(flic->status.frame_index < (flic->head.frames-1)) ||
|
|
( (flic->status.frame_index < flic->head.frames) &&
|
|
( !max_loop || (flic->status.loop_count < (max_loop - 1))));
|
|
++flic->status.frame_index)
|
|
{
|
|
while (!timer_flag);
|
|
|
|
if (err = flic_next_frame(flic, TRUE))
|
|
return err;
|
|
//else
|
|
// FastBlitRegionSVGA((char *)(0xa0000),(char *)(flic->screen.pixels),(long)0,(long)640,(long)480,(long)0,(long)640);
|
|
// BlitSVGAPage((char *)(flic->screen.pixels));
|
|
// BlitRegionSVGATst((void *)0xa0000,(void *)(flic->screen.pixels),(long)640,(long)480,(long)640);
|
|
// BlitRegionSVGA((char *)0xa0000,(char *)flic->screen.pixels,(long)0,(long)640,(long)480,(long)0,(long)640);
|
|
|
|
timer_flag = 0;
|
|
}
|
|
}
|
|
|
|
//AIL_release_timer_handle(timer);
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
void FlicSeekFirst(Flic *flic)
|
|
{
|
|
// if (flic->head.oframe2 == 0)
|
|
// fill_in_frame2(flic);
|
|
|
|
// Seek to first frame.
|
|
flic_seek(flic, flic->head.oframe1);
|
|
|
|
// Display first frame.
|
|
//flic_next_frame(flic, TRUE); HJH
|
|
flic->status.frame_index=0;//1; HJH
|
|
}
|
|
|
|
int FlicAdvance(Flic *flic, BOOL fDecode)
|
|
{
|
|
// Seek to second frame
|
|
//(*flic->seek)(flic, flic->head.oframe2);
|
|
// Loop from 2nd frame thru ring frame
|
|
|
|
// for (flic->status.frame_index=0;
|
|
// (flic->status.frame_index < (flic->head.frames-1)) ||
|
|
// ( (flic->status.frame_index < flic->head.frames) &&
|
|
// ( !max_loop || (flic->status.loop_count < (max_loop - 1))));
|
|
// ++flic->status.frame_index)
|
|
// {
|
|
|
|
if(flic->status.frame_index < flic->head.frames)
|
|
{
|
|
flic_next_frame(flic, fDecode);
|
|
flic->status.frame_index++;
|
|
//memcpy(buffer, buffer2, (HSIZE*VSIZE));
|
|
return(1);
|
|
}
|
|
else
|
|
return(0);
|
|
|
|
// if (flic->check_frame && !(*flic->check_frame)(flic))
|
|
// return 0;
|
|
}
|
|
|
|
static void center_flic(Flic *flic)
|
|
/* Set flic.xoff and flic.yoff so flic plays centered rather
|
|
* than in upper left corner of display. */
|
|
{
|
|
flic->xoff = (flic->screen.width - (signed)flic->head.width)/2;
|
|
flic->yoff = (flic->screen.height - (signed)flic->head.height)/2;
|
|
}
|
|
|
|
void set_flic_origin(Flic *flic, int x, int y)
|
|
{
|
|
flic->xoff = x;
|
|
flic->yoff = y;
|
|
}
|
|
|
|
int frame_check(Flic *flic)
|
|
{
|
|
/*
|
|
char key;
|
|
|
|
if (Esc())
|
|
{
|
|
//AbortScript = TRUE;
|
|
return 0;
|
|
}
|
|
|
|
if (flic->status.frame_index == FlcSoundFrames[FlcSoundIndex][0])
|
|
{
|
|
// if the "sound" number is less than 100, then it's a VOC buffer
|
|
if (FlcSoundFrames[FlcSoundIndex][1] < 100)
|
|
{
|
|
PlayVoc(FlcSoundFrames[FlcSoundIndex][1],-1);
|
|
}
|
|
else // otherwise a raw sound data file to be streamed off of disk
|
|
{
|
|
if (FlcSoundNameList[FlcSoundNameIndex][0]!='\0')
|
|
{
|
|
retcode = lmLibSeek(SNDLIBINFO,FlcSoundNameList[FlcSoundNameIndex++],&SNDoffset,&SNDlength);
|
|
if (retcode == 0)
|
|
StPlay(glbPlayRate,IGNORE_AUDIO_GAPS);
|
|
}
|
|
}
|
|
|
|
// now that the sound has been triggered, ready the next frame number
|
|
FlcSoundIndex++;
|
|
}
|
|
else
|
|
if (FlcSoundFrames[FlcSoundIndex][0] == 9998) // start music?
|
|
{
|
|
PlayXmi(FlcSoundFrames[FlcSoundIndex++][1],FALSE);
|
|
XmiVolume(1,127,0);
|
|
}
|
|
RefreshSound();
|
|
*/
|
|
return 1;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicStart
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// char *filename -> filename of flic to start processing
|
|
// char *buffer -> screen buffer to put data into
|
|
// Flic *flic -> the flic
|
|
// int usepal -> flag - should we use the palette? (I think)
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
int FlicStart(char *filename, int width, int height, char *buffer, Flic *flic, char usepal)
|
|
{
|
|
FlicInit(flic, width, height, usepal, buffer);
|
|
|
|
if(FlicOpen(flic, filename))
|
|
return(-1);
|
|
|
|
FlicSetOrigin(flic, 0, 0);
|
|
FlicSeekFirst(flic);
|
|
FlicAdvance(flic, TRUE); // HJH - we go to 1st, then go process it
|
|
|
|
//memcpy(buffer, buffer2, (HSIZE*VSIZE));
|
|
|
|
return(0);
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicStop
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic
|
|
//
|
|
// Return Value :
|
|
// Modification history :
|
|
//
|
|
//**************************************************************************
|
|
|
|
void FlicStop(Flic *flic)
|
|
{
|
|
FlicClose(flic);
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicGetStats
|
|
//
|
|
// Gets statistics for the given file.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// char *filename -> the flic filename
|
|
// Flic *flic -> the flic
|
|
// int *piBufferSize -> this function will fill in how large a
|
|
// buffer is needed to store a screen of
|
|
// this flick
|
|
// int *piColourPalSize->this function will fill in how large
|
|
// the colour palette is
|
|
//
|
|
// Return Value :
|
|
//
|
|
// ErrCode -> 0 if successfull, non-zero otherwise
|
|
//
|
|
// Modification history :
|
|
//
|
|
// 05jun96:HJH -> creation
|
|
//
|
|
//**************************************************************************
|
|
|
|
ErrCode FlicGetStats(char *filename, int width, int height, Flic *flic, int *piBufferSize, int *piColourPalSize)
|
|
{
|
|
ErrCode err=0;
|
|
FlicInit(flic, width, height, 1, NULL);
|
|
|
|
flic->xoff = flic->yoff = 0;
|
|
|
|
if ( !(err = (*flic->open)(flic, filename)) )
|
|
{
|
|
if (fread(&flic->head, sizeof(flic->head), 1, flic->file) != 1)
|
|
err = ErrFlicRead;
|
|
}
|
|
|
|
if ( !err && piBufferSize )
|
|
*piBufferSize = flic->head.width * flic->head.height;
|
|
|
|
FlicSeekChunk( flic, 0, COLOR_256, piColourPalSize );
|
|
FlicClose(flic); /* Close down and scrub partially opened flic. */
|
|
|
|
return err;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicGetColourPalette
|
|
//
|
|
// To get the colour palette from the given flic file.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// char *filename -> the flic file to extract the palette from
|
|
// char **ppBuffer -> the place to put the palette
|
|
//
|
|
// Return Value :
|
|
//
|
|
// ErrCode -> 0 if successful, non-zero otherwise
|
|
//
|
|
// Modification history :
|
|
//
|
|
// 10jun96:HJH -> creation
|
|
// 19jun96:HJH -> removed <<2 after colors->r/g/b
|
|
//
|
|
//**************************************************************************
|
|
|
|
ErrCode FlicGetColourPalette(CHAR *filename, int width, int height, CHAR **ppBuffer, INT *piNumColours)
|
|
{
|
|
Flic flic;
|
|
INT iBufferSize;
|
|
INT iColourPaletteSize=0;
|
|
ErrCode err = 0;
|
|
ChunkHead *chunk = NULL;
|
|
CHAR *pcPosition;
|
|
|
|
if ( FlicGetStats( filename, width, height, &flic, &iBufferSize, &iColourPaletteSize ) )
|
|
err = -1;
|
|
|
|
if ( piNumColours )
|
|
*piNumColours = iColourPaletteSize;
|
|
|
|
if ( !err && iColourPaletteSize )
|
|
{
|
|
FlicInit(&flic, flic.head.width, flic.head.height, 1, NULL);
|
|
|
|
if(FlicOpen(&flic, filename))
|
|
return(-1);
|
|
|
|
FlicSetOrigin(&flic, 0, 0);
|
|
|
|
*ppBuffer = (CHAR *)MemAlloc( iColourPaletteSize );
|
|
chunk = (ChunkHead *)FlicSeekChunk( &flic, 0, COLOR_256, NULL );
|
|
pcPosition = (CHAR *)(((BYTE *)chunk)+6);
|
|
|
|
if ( chunk )
|
|
{
|
|
INT ix, end, count, start = 0;
|
|
Uchar *cbuf = (Uchar *)pcPosition;
|
|
Short *wp = (Short *)cbuf;
|
|
Short ops;
|
|
Colour *colors;
|
|
|
|
ops = *wp;
|
|
cbuf += sizeof(*wp);
|
|
while (--ops >= 0)
|
|
{
|
|
start += *cbuf++;
|
|
if ((count = *cbuf++) == 0)
|
|
count = 256;
|
|
{
|
|
colors = (Colour *)cbuf;
|
|
end = start + count;
|
|
|
|
for (ix = start; ix < end; ++ix)
|
|
{
|
|
(*ppBuffer)[ix*3] =colors->r;
|
|
(*ppBuffer)[ix*3+1]=colors->g;
|
|
(*ppBuffer)[ix*3+2]=colors->b;
|
|
++colors;
|
|
}
|
|
}
|
|
cbuf += 3*count;
|
|
start += count;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
err = -1;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicSeekChunk
|
|
//
|
|
// To seek to a particular chunk in the flic file.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic to search
|
|
// INT iFrame -> frame in which to search
|
|
// ChunkTypes eType -> type of chunk to search for
|
|
// INT *piChunkSize-> the function puts the size of the chunk here
|
|
//
|
|
// Return Value :
|
|
//
|
|
// char * -> the returned chunk
|
|
//
|
|
// Modification history :
|
|
//
|
|
// 05jun96:HJH -> creation
|
|
//
|
|
//**************************************************************************
|
|
|
|
CHAR *FlicSeekChunk(Flic *flic, INT iFrame, ChunkTypes eType, INT *piChunkSize)
|
|
{
|
|
FrameHead head;
|
|
LONG lSize;
|
|
BOOL fFound = FALSE;
|
|
ErrCode err=0;
|
|
INT i;
|
|
|
|
FlicSeekFirst(flic);
|
|
|
|
for ( i=0 ; i<iFrame ; i++ )
|
|
FlicAdvance(flic, FALSE);
|
|
|
|
if ( fread(&head, sizeof(head), 1, flic->file) != 1 )
|
|
err = ErrFlicRead;
|
|
else
|
|
{
|
|
if (head.type == FRAME_TYPE)
|
|
{
|
|
lSize = head.size - sizeof(head); /* Don't include head. */
|
|
if (lSize > 0)
|
|
{
|
|
if (lSize > 500000)
|
|
{
|
|
_getch();
|
|
lSize = 64000;
|
|
}
|
|
if (!(err = file_read_big_block(flic->file, pcxbuf, lSize)))
|
|
{
|
|
FrameHead *frame = &head;
|
|
Uchar *data = (unsigned char *)pcxbuf;
|
|
int i;
|
|
ChunkHead *chunk;
|
|
|
|
for (i=0; i<head.chunks; ++i)
|
|
{
|
|
chunk = (ChunkHead *)data;
|
|
data += chunk->size;
|
|
if ( chunk->type == eType )
|
|
{
|
|
if ( piChunkSize )
|
|
*piChunkSize = chunk->size;
|
|
return( ((char *)chunk) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
err = ErrFlicBadFrame;
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicFindByteRunBeforeFrame
|
|
//
|
|
// To find the closest byte run frame before the given frame.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic to extract data from
|
|
// INT iFrame -> the frame number before which to find a
|
|
// byte run
|
|
//
|
|
// Return Value :
|
|
//
|
|
// INT -> frame # if successful, BAD_INDEX otherwise
|
|
//
|
|
// Modification history :
|
|
//
|
|
// 19jun96:HJH -> creation
|
|
//
|
|
//**************************************************************************
|
|
|
|
INT FlicFindByteRunBeforeFrame(Flic *flic, INT iFrame)
|
|
{
|
|
INT iRet = BAD_INDEX;
|
|
INT i;
|
|
|
|
|
|
for ( i=iFrame-1 ; i>=0 ; i-- )
|
|
{
|
|
if ( FlicSeekChunk( flic, i, BYTE_RUN, NULL ) )
|
|
return(i);
|
|
}
|
|
|
|
return( iRet );
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicFillBitmapData
|
|
//
|
|
// To put flic bitmap data for a particular frame into the given bitmap.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic to extract data from
|
|
// INT iPrevFrame -> the previous frame decoded, BAD_INDEX if unknown
|
|
// INT iFrame -> the frame number to extract bitmap data for
|
|
// HBITMAP hBitmap -> place to put the bitmap data
|
|
//
|
|
// Return Value :
|
|
//
|
|
// ErrCode -> 0 if successful, non-zero otherwise
|
|
//
|
|
// Modification history :
|
|
//
|
|
// 10jun96:HJH -> creation
|
|
// 19jun96:HJH -> removed redundancies
|
|
// -> added check for iPrevFrame != (iFrame-1)
|
|
//
|
|
//**************************************************************************
|
|
|
|
ErrCode FlicFillBitmapData( Flic *flic, INT iPrevFrame, INT iFrame, HBITMAP hBitmap )
|
|
{
|
|
ErrCode err = 0;
|
|
ChunkHead *chunk = NULL;
|
|
DIBSECTION dibSection;
|
|
INT i, iStart;
|
|
|
|
GetObject( hBitmap, sizeof(DIBSECTION), &dibSection );
|
|
|
|
flic->screen.pixels = (Pixel *)dibSection.dsBm.bmBits;
|
|
|
|
if ( iPrevFrame == BAD_INDEX || iPrevFrame != (iFrame-1) )
|
|
{
|
|
iStart = FlicFindByteRunBeforeFrame( flic, iFrame );
|
|
if ( iStart == BAD_INDEX )
|
|
iStart = 0;
|
|
}
|
|
else
|
|
iStart = iFrame;
|
|
|
|
for ( i=iStart ; i<=iFrame ; i++ )
|
|
{
|
|
chunk = (ChunkHead *)FlicSeekChunk( flic, i, DELTA_FLC, NULL );
|
|
if ( chunk )
|
|
decode_delta_flc( ((BYTE*)chunk)+6, flic );
|
|
else
|
|
{
|
|
chunk = (ChunkHead *)FlicSeekChunk( flic, i, BYTE_RUN, NULL );
|
|
if ( chunk )
|
|
{
|
|
FlicClearBitmap( hBitmap, 0 );
|
|
decode_byte_run( ((BYTE*)chunk)+6, flic );
|
|
}
|
|
}
|
|
|
|
flic->status.frame_index = i;
|
|
}
|
|
|
|
return( err );
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicFillFrameData
|
|
//
|
|
// To put flic frame data for a particular frame into the given bitmap.
|
|
// This is raw data. Either a byte run or deltas.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// Flic *flic -> the flic to extract data from
|
|
// INT iPrevFrame -> the previous frame decoded, BAD_INDEX if unknown
|
|
// INT iFrame -> the frame number to extract bitmap data for
|
|
// CHAR *pcBuffer -> place to put the frame data
|
|
// INT *piSize -> size of buffer ; we return how many bytes
|
|
// were placed in the buffer
|
|
//
|
|
// Return Value :
|
|
//
|
|
// ErrCode -> 0 if successful, non-zero otherwise
|
|
//
|
|
// Modification history :
|
|
//
|
|
// 03jul96:HJH -> creation
|
|
//
|
|
//**************************************************************************
|
|
|
|
ErrCode FlicFillFrameData(
|
|
Flic *flic,
|
|
INT iPrevFrame,
|
|
INT iFrame,
|
|
CHAR *pcBuffer,
|
|
INT *piNumBytes
|
|
)
|
|
{
|
|
ErrCode err = 0;
|
|
ChunkHead *chunk = NULL;
|
|
INT i, iStart, iNumBytesInBuffer;
|
|
|
|
Assert(piNumBytes);
|
|
//GetObject( hBitmap, sizeof(DIBSECTION), &dibSection );
|
|
|
|
flic->screen.pixels = (Pixel *)pcBuffer;
|
|
iNumBytesInBuffer = *piNumBytes;
|
|
|
|
if ( iPrevFrame == BAD_INDEX || iPrevFrame != (iFrame-1) )
|
|
{
|
|
iStart = FlicFindByteRunBeforeFrame( flic, iFrame );
|
|
if ( iStart == BAD_INDEX )
|
|
iStart = 0;
|
|
}
|
|
else
|
|
iStart = iFrame;
|
|
|
|
for ( i=iStart ; i<=iFrame ; i++ )
|
|
{
|
|
chunk = (ChunkHead *)FlicSeekChunk( flic, i, DELTA_FLC, piNumBytes );
|
|
if ( chunk )
|
|
{
|
|
Assert(*piNumBytes <= iNumBytesInBuffer);
|
|
memcpy( pcBuffer, ((BYTE*)chunk)+6, *piNumBytes );
|
|
//decode_delta_flc( ((BYTE*)chunk)+6, flic );
|
|
}
|
|
else
|
|
{
|
|
chunk = (ChunkHead *)FlicSeekChunk( flic, i, BYTE_RUN, piNumBytes );
|
|
if ( chunk )
|
|
{
|
|
Assert(*piNumBytes <= iNumBytesInBuffer);
|
|
//FlicClearBitmap( hBitmap, 0 );
|
|
memcpy( pcBuffer, ((BYTE*)chunk)+6, *piNumBytes );
|
|
//decode_byte_run( ((BYTE*)chunk)+6, flic );
|
|
}
|
|
}
|
|
|
|
flic->status.frame_index = i;
|
|
}
|
|
|
|
return( err );
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// FlicClearBitmap
|
|
//
|
|
// To clear the given bitmap to a certain colour index value.
|
|
//
|
|
// Parameter List :
|
|
//
|
|
// HBITMAP hBitmap -> bitmap to clear
|
|
// INT iFrame -> the colour index to use in clearing
|
|
//
|
|
// Return Value :
|
|
//
|
|
// none
|
|
//
|
|
// Modification history :
|
|
//
|
|
// 11jun96:HJH -> creation
|
|
//
|
|
//**************************************************************************
|
|
|
|
void FlicClearBitmap( HBITMAP hBitmap, INT iColourIndex )
|
|
{
|
|
DIBSECTION dibSection;
|
|
INT i;
|
|
|
|
CHECKV(hBitmap);
|
|
|
|
CHECKV(GetObject(hBitmap, sizeof(DIBSECTION), &dibSection));
|
|
CHECKV(dibSection.dsBm.bmBits);
|
|
CHECKV(dibSection.dsBm.bmHeight);
|
|
CHECKV(dibSection.dsBm.bmWidth);
|
|
|
|
for ( i=0 ; i<dibSection.dsBm.bmHeight*dibSection.dsBm.bmWidth ; i++ )
|
|
{
|
|
((CHAR *)dibSection.dsBm.bmBits)[i] = iColourIndex;
|
|
}
|
|
}
|
|
|