ftp.nice.ch/pub/next/graphics/movie/Movie.3.0.NIHS.bs.tar.gz#/Movie3.0/Source/xanim/xanim_pfx.c

This is xanim_pfx.c in view mode; [Download] [Up]

/*
 * xanim_pfx.c
 *
 * Copyright (C) 1992,1993,1994 by Mark Podlipec.
 * All rights reserved.
 *
 * This software may be freely copied, modified and redistributed without
 * fee for non-commerical purposes provided that this copyright notice is
 * preserved intact on all copies and modified copies.
 *
 * There is no warranty or other guarantee of fitness of this software.
 * It is provided solely "as is". The author(s) disclaim(s) all
 * responsibility and liability with respect to this software's usage
 * or its effect upon hardware or computer systems.
 *
 */
#include "xanim_pfx.h"
#include "xanim_iff.h"

LONG Is_PFX_File();
ULONG PFX_Read_File();
void PFX_Setup_CMAP();
void PFX_Extract_Images();
ULONG UTIL_Get_MSB_Long();
ULONG UTIL_Get_MSB_UShort();
XA_CHDR *ACT_Get_CMAP();
XA_ACTION *ACT_Get_Action();
void ACT_Setup_Mapped();
void ACT_Add_CHDR_To_Action();


static PFX_PLAY_HDR *pfx_play_stack,*pfx_play_start,*pfx_play_lcur;

static XA_CHDR *pfx_chdr;
static ColorReg pfx_cmap[256];

#define PFX_DEFAULT_TIME 17
static LONG pfx_time;
static PFX_RCHG_HDR *pfx_images;

static ULONG pfx_imagex,pfx_imagey,pfx_imagec,pfx_imaged;

/*
 *
 */
LONG Is_PFX_File(filename)
char *filename;
{
  FILE *fin;
  ULONG data;

  if ( (fin=fopen(filename,XA_OPEN_MODE)) == 0) return(XA_NOFILE);

  data = UTIL_Get_MSB_Long(fin);  /* read past size */
  data = UTIL_Get_MSB_Long(fin); /* read magic */
  fclose(fin);
  if (data == pfx_RCHG) return(TRUE);
  return(FALSE);
}

void PFX_PUSH_PLAY_HDR(p)
PFX_PLAY_HDR *p;
{
  PFX_PLAY_HDR *temp;

  temp = (PFX_PLAY_HDR *) malloc(sizeof(PFX_PLAY_HDR));
  if (temp == 0) TheEnd1("PFX_PUSH_PLAY_HDR: malloc failed\n");
  temp->type = p->type;
  temp->data = p->data;
  temp->count = 0;
  temp->next = 0;
  temp->loop = 0;
  if (pfx_play_start == 0) pfx_play_start = temp;
  else pfx_play_lcur->next = temp;
  pfx_play_lcur = temp;

 DEBUG_LEVEL2 fprintf(stderr,"PUSHING %c%c%c%c", ((p->type >> 24) & 0xff),
    ((p->type >> 16) & 0xff), ((p->type >> 8) & 0xff), ((p->type) & 0xff) );
 DEBUG_LEVEL2 fprintf(stderr," data=%lx ptr=%lx\n",
					p->data,(ULONG)pfx_play_lcur);

	/* stack knows where it's duplicate is on play list */
  p->loop = pfx_play_lcur;  
  p->next = pfx_play_stack;
  pfx_play_stack = p;
}

PFX_PLAY_HDR *PFX_POP_PLAY_HDR()
{
  PFX_PLAY_HDR *p;
  p = pfx_play_stack;
  if (p != 0) pfx_play_stack = pfx_play_stack->next;
  return(p);
}

PFX_RCHG_HDR *PFX_Alloc_RCHG()
{
  PFX_RCHG_HDR *temp;

  temp = (PFX_RCHG_HDR *)malloc(sizeof(PFX_RCHG_HDR));
  if (temp == 0) TheEnd1("PFX_Alloc_RCHG malloc error\n");
  temp->orig = 0;
  temp->dest = 0;
  temp->len  = 0;
  temp->data = 0;
  temp->next = 0;
  return(temp);
}

PFX_FRAM_HDR *PFX_Alloc_FRAM()
{
  PFX_FRAM_HDR *temp;
  temp = (PFX_FRAM_HDR *)malloc(sizeof(PFX_FRAM_HDR));
  if (temp == 0) TheEnd1("PFX_Alloc_FRAM malloc error\n");
  temp->frame = 0;
  temp->time  = 0;
  temp->next = 0;
  return(temp);
}


ULONG PFX_Read_File(fname,anim_hdr)
char *fname;
XA_ANIM_HDR *anim_hdr;
{
  FILE *fin;
  PFX_RCHG_HDR  *first_rchg,*cur_rchg;
  PFX_RCHG_HDR  *first_parm,*cur_parm;
  PFX_FRAM_HDR *first_fram,*cur_fram;
  ULONG pfx_max_rchg;
  ULONG pfx_xflag,pfx_yflag,pfx_cflag,pfx_rchg_flag;
  ULONG d,chid,chlen;
  ULONG frame_count;
  PFX_PLAY_HDR *pfx_play_temp;


  pfx_play_stack = 0;
  pfx_play_start = 0;
  pfx_play_lcur  = 0;

  pfx_chdr = 0;
  pfx_time = PFX_DEFAULT_TIME;
  pfx_images = 0;
  pfx_imagex = 0;
  pfx_imagey = 0;
  pfx_imagec = 0;
  pfx_imaged = 0;

  first_rchg = cur_rchg = 0;
  first_parm = cur_parm = 0;
  pfx_max_rchg = 0;
  pfx_xflag = FALSE;
  pfx_yflag = FALSE;
  pfx_cflag = FALSE;

  if ( (fin=fopen(fname,XA_OPEN_MODE)) == 0)
  {
    fprintf(stderr,"Can't open PFX File %s for reading\n",fname);
    return(FALSE);
  }

  d = UTIL_Get_MSB_Long(fin);   /* probably version number */
  chid = UTIL_Get_MSB_Long(fin); /* get chunk id */
  chlen = UTIL_Get_MSB_Long(fin); /* get chunk length */
  while(chid == pfx_RCHG)
  {
    LONG ret;
    ULONG orig,dest,garb;
    PFX_RCHG_HDR  *tmp_rchg;
    UBYTE *data;

    orig = UTIL_Get_MSB_UShort(fin);
    dest = UTIL_Get_MSB_UShort(fin);
    garb = UTIL_Get_MSB_Long(fin);  /* orig ptr or id or ?? */
    garb = UTIL_Get_MSB_Long(fin);  /* dest ptr or id or ?? */
    garb = UTIL_Get_MSB_UShort(fin); /* always 0xffff */
    DEBUG_LEVEL1 fprintf(stderr,"RCHG %lx  <%ld %ld>\n",chlen,orig,dest);
    chlen -= 14;

    data = (UBYTE *)malloc(chlen);
    if (data == 0) TheEnd1("PFX: rchg data malloc failed\n");
    ret = fread((char *)(data),1,chlen,fin);
    if (ret != chlen) TheEnd1("PFX: rchg data read failed\n");

    tmp_rchg = PFX_Alloc_RCHG();
    tmp_rchg->orig = orig;    
    tmp_rchg->dest = dest;    
    tmp_rchg->len = chlen;    
    tmp_rchg->data = data;

    if (first_rchg == 0) first_rchg = cur_rchg = tmp_rchg;
    else
    {
      cur_rchg->next = tmp_rchg;
      cur_rchg = tmp_rchg;
    }
    if (orig > pfx_max_rchg) pfx_max_rchg = orig;
    if (dest > pfx_max_rchg) pfx_max_rchg = dest;

    chid = UTIL_Get_MSB_Long(fin); /* get chunk id */
    chlen = UTIL_Get_MSB_Long(fin); /* get chunk length */
  }

  while(chid == pfx_PARM)
  {
    LONG ret;
    ULONG pnum,res1,res2;
    PFX_RCHG_HDR  *tmp_parm;
    UBYTE *data;

    pnum = UTIL_Get_MSB_UShort(fin);  /* parm number */
    res1 = UTIL_Get_MSB_UShort(fin);  /* ??? */
    res2 = UTIL_Get_MSB_UShort(fin);   /* ??? */
    chlen -= 6;

    data = (UBYTE *)malloc(chlen);
    if (data == 0) TheEnd1("PFX: parm data malloc failed\n");
    ret = fread((char *)(data),1,chlen,fin);
    if (ret != chlen) TheEnd1("PFX: parm data read failed\n");

    DEBUG_LEVEL1 fprintf(stderr,"PARM %lx\n",chlen);
    DEBUG_LEVEL2 fprintf(stderr,"     %s\n",data);
     
    tmp_parm = PFX_Alloc_RCHG();
    tmp_parm->orig = pnum;
    tmp_parm->dest = res1;
    tmp_parm->len = chlen;
    tmp_parm->data = data;

    if (first_parm == 0) first_parm = cur_parm = tmp_parm;
    else
    {
      cur_parm->next = tmp_parm;
      cur_parm = tmp_parm;
    }

    chid = UTIL_Get_MSB_Long(fin); /* get chunk id */
    chlen = UTIL_Get_MSB_Long(fin); /* get chunk length */
  }

  if (chid != pfx_STMT)
  { 
    fprintf(stderr,"PFX: confused\n");
    return(FALSE);
  }


  first_fram = cur_fram = 0;
  frame_count = 0;

  pfx_rchg_flag = FALSE;
  while(chlen && !feof(fin) )
  {
    chid = UTIL_Get_MSB_Long(fin);  chlen-=4; /* get script id */

    if (chid == pfx_A_B)
    {
      PFX_PLAY_HDR *p;
      p = PFX_POP_PLAY_HDR();
      if (p == 0) TheEnd1("PFX Play List: stack empty err1\n");
      if (pfx_play_temp == 0) TheEnd1("PFX Play List: stack empty err2\n");
      DEBUG_LEVEL1 fprintf(stderr,"POP %c%c%c%c\n", 
	((p->type >> 24) & 0xff), ((p->type >> 16) & 0xff), 
	((p->type >> 8) & 0xff), ((p->type) & 0xff) );
      if (p->type == pfx_REPE) /* point back to just after REPE */
      {
        if (p->loop->next != 0) pfx_play_temp->loop = p->loop->next;
        else TheEnd1("PFX_Loop: hosed\n");
        DEBUG_LEVEL1 fprintf(stderr,"   loop to %c%c%c%c", 
	 ((p->loop->next->type >> 24) & 0xff),
	 ((p->loop->next->type >> 16) & 0xff), 
	 ((p->loop->next->type >> 8) & 0xff),
	 ((p->loop->next->type) & 0xff) );
        DEBUG_LEVEL1 fprintf(stderr,"   count=%lx\n",p->loop->next->data);
      }
      FREE(p,0x6000); p=0;
    }
    else
    {
      pfx_play_temp = (PFX_PLAY_HDR *)malloc(sizeof(PFX_PLAY_HDR));
      if (pfx_play_temp == 0) TheEnd1("PFX: malloc PFX_PLAY_HDR error\n");
      pfx_play_temp->type = chid;
      pfx_play_temp->data = 0;
      pfx_play_temp->loop = 0;
      pfx_play_temp->next = 0;
      switch(chid)
      {
	case pfx_INIT:
	case pfx_GLOC:
	case pfx_GLOV:
	case pfx_REPE:
		PFX_PUSH_PLAY_HDR(pfx_play_temp);
		break;
	case pfx_BITP:
	case pfx_XDIM:
	case pfx_YDIM:
	case pfx_DURA:
	case pfx_HIGH:
	case pfx_FLAC:
	case pfx_COUN:
	case pfx_INTE:
	case pfx_AUST:
	case pfx_SPDU:
	case pfx_SLWD:
		pfx_play_temp->data = UTIL_Get_MSB_Long(fin); chlen-=4;
		PFX_PUSH_PLAY_HDR(pfx_play_temp);
		break;
	case pfx_PALL:
	case pfx_FRAM:
	case pfx_FILE:
		pfx_play_temp->data = UTIL_Get_MSB_UShort(fin); chlen-=2;
		PFX_PUSH_PLAY_HDR(pfx_play_temp);
		break;
	default:
		fprintf(stdout,"PFX read: Unknown STMT chid %lx\n",chid);
		return(FALSE);
		break;
      }
    }
  } /* end of while for reading play list */

  fclose(fin);
  /* free up Play List stack just in case it's not already freed up */
  {
    PFX_PLAY_HDR *p;
    do
    {
      p = PFX_POP_PLAY_HDR();
      if (p != 0) 
      {
        FREE(p,0x6000); p=0;
        fprintf(stderr,"PFX Warning: play list different than expected\n");
      }
    } while(p != 0);
  }


/* loop through play list to create frame list */
  pfx_play_lcur = pfx_play_start;
  while(pfx_play_lcur != 0)
  {
   ULONG garb;

    chid = pfx_play_lcur->type;
    switch(chid)
    {
      case pfx_INIT:
      case pfx_GLOC:
      case pfx_GLOV:
      case pfx_REPE: /* REPEAT: for now must be followed by COUN */
      case pfx_FILE: /* NOTE: this is comment only */
		break;
      case pfx_BITP: /* Num of Bitplanes */
		pfx_imaged = pfx_play_lcur->data;
		break;
      case pfx_XDIM: /* X size */
		pfx_imagex = pfx_play_lcur->data;
		pfx_xflag = TRUE;
		break;
      case pfx_YDIM: /* Y size */
		pfx_imagey = pfx_play_lcur->data;
		pfx_yflag = TRUE;
		break;
      case pfx_HIGH: /* ??? */
      case pfx_FLAC: /* ??? */
      case pfx_INTE: /* Interlace flag */
      case pfx_AUST: /* don't know */
		break;
      case pfx_DURA: /* ?Duration between frames */
		garb = pfx_play_lcur->data; if (garb == 0) garb = 1;
		pfx_time = garb * PFX_DEFAULT_TIME;
		break;
      case pfx_SPDU: /* speed up by this much */
		garb = pfx_play_lcur->data;
		pfx_time += garb * PFX_DEFAULT_TIME;
		break;
      case pfx_SLWD: /* slow down by this much */
		garb = pfx_play_lcur->data;
		pfx_time -= garb * PFX_DEFAULT_TIME;
		if (pfx_time <= 0) pfx_time = 1;
		break;
      case pfx_PALL: /* CMAP parm id */
		garb = pfx_play_lcur->data;
		PFX_Setup_CMAP(garb,first_parm);
		pfx_cflag = TRUE;
		break;
      case pfx_COUN:
		garb = pfx_play_lcur->data;
		    /* 0x3b9ac9ff for example is mouse button */
		if (garb >= 0x100) garb = 1;
		pfx_play_lcur->count = garb;
		break;
      case pfx_FRAM:
		garb = pfx_play_lcur->data;
		if (first_fram == 0)
		  first_fram = cur_fram = PFX_Alloc_FRAM();
		else
		{
		  cur_fram->next = PFX_Alloc_FRAM();
		  cur_fram = cur_fram->next;
		}
		cur_fram->frame = garb;
		cur_fram->time  = XA_GET_TIME(pfx_time);
		frame_count++;
		break;
      default: 
		fprintf(stdout,"PFX frame lst: Unknown STMT chid %lx\n",chid);
		return(FALSE);
		break;
     } /* end switch */
     if (   (pfx_xflag==TRUE) && (pfx_yflag==TRUE) 
         && (pfx_cflag==TRUE) && (pfx_rchg_flag==FALSE))
     {
       pfx_rchg_flag = TRUE;
       PFX_Extract_Images(anim_hdr,first_rchg,pfx_max_rchg);
     }
     if (pfx_play_lcur->loop != 0) 
     { 
       PFX_PLAY_HDR *p;
       p = pfx_play_lcur->loop;
       DEBUG_LEVEL2 fprintf(stderr,"PFX frame loop cnt=%lx\n",p->count);
       p->count--;
       if (p->count > 0) pfx_play_lcur = p; /* goto COUN */
     } 

     pfx_play_lcur = pfx_play_lcur->next;
   } /* end of while STMT */

   /* Free up play list */
   { 
     PFX_PLAY_HDR *p;
     while(pfx_play_start) 
     {
       p = pfx_play_start;
       pfx_play_start = pfx_play_start->next;
       FREE(p,0x6000); p=0;
     }
   }

 {
   PFX_FRAM_HDR *ptr_fram,*tmp_fram;
   ULONG i;

   anim_hdr->frame_lst = 
	(XA_FRAME *)malloc(sizeof(XA_FRAME) * (frame_count + 1));
   if (anim_hdr->frame_lst == NULL)
        TheEnd1("PFX_ANIM: couldn't malloc for frame_lst\0");

   DEBUG_LEVEL3 fprintf(stderr,"PFX frame List(%ld): ",frame_count);
   ptr_fram = first_fram;
   for(i=0; i<frame_count; i++)
   {  /* frames start at 1, nothing is at 0 */
     anim_hdr->frame_lst[i].act  = pfx_images[ptr_fram->frame].act;
     anim_hdr->frame_lst[i].time = ptr_fram->time;

     DEBUG_LEVEL3 fprintf(stderr,"<%ld>",ptr_fram->frame);
     tmp_fram = ptr_fram;
     ptr_fram = ptr_fram->next;
     FREE(tmp_fram,0x6000);
   }
   if (ptr_fram != 0) 
     fprintf(stderr," FRAME stuff: ptr_fram %lx non_zero\n",(ULONG)ptr_fram);
   DEBUG_LEVEL3 fprintf(stderr,"\n");
   anim_hdr->frame_lst[frame_count].time = 0;
   anim_hdr->frame_lst[frame_count].act  = 0;
   anim_hdr->loop_frame = 0;
   anim_hdr->last_frame = frame_count - 1;
   anim_hdr->imagex = pfx_imagex;
   anim_hdr->imagey = pfx_imagey;
   anim_hdr->imagec = pfx_imagec;
   anim_hdr->imaged = pfx_imaged;
 }

 { /* FREE PARM STRUCTURES */
   PFX_RCHG_HDR *tmp,*tmp1;

   if (pfx_images != 0) FREE(pfx_images,0x6000); /* free up image structures */
   pfx_images=0;
   tmp = first_parm;
   while(tmp) 
   { 
     tmp1 = tmp; 
     tmp = tmp->next;
     FREE(tmp1->data,0x6000);
     FREE(tmp1,0x6000);
   }
   first_parm=0;
 }
 return(TRUE);
}

 
void PFX_Extract_Images(anim_hdr,first_rchg,pfx_max_rchg)
XA_ANIM_HDR *anim_hdr;
PFX_RCHG_HDR *first_rchg;
ULONG pfx_max_rchg;
{
  ULONG psize,i;
  UBYTE *data,*pic;
  PFX_RCHG_HDR *tmp_rchg;

  psize = pfx_imagex * pfx_imagey;

  pfx_max_rchg++;  /* add 0 up front */
  pfx_images = (PFX_RCHG_HDR *)malloc(pfx_max_rchg * sizeof(PFX_RCHG_HDR));
  if (pfx_images == 0) TheEnd1("PFX: malloc failed 1\n");
  for(i=0; i<pfx_max_rchg;i++) 
  {
    pfx_images[i].orig = 0; 
    pfx_images[i].data = 0;
  }
  pfx_images[0].orig = 1; /* indicate it is used */ 

  tmp_rchg = first_rchg;
  while(tmp_rchg)
  {
    ULONG orig,dest,len;
    ULONG b_cnt,a_cnt,offset,d,dmask;
    PFX_RCHG_HDR *tmp1_rchg;

    orig = tmp_rchg->orig;
    dest = tmp_rchg->dest;
    len  = tmp_rchg->len;
    data = tmp_rchg->data;
    DEBUG_LEVEL2 fprintf(stderr,"PFX Extracting %ld %ld\n",orig,dest);


	/* new image */
    if ( (pfx_images[orig].orig == 0) || (pfx_images[dest].orig == 0 ) )
    {
      pic = (UBYTE *)malloc( XA_PIC_SIZE(psize) );
      if (pic == 0) TheEnd1("PFX: malloc failed 2\n");

      if (orig == 0) memset((char *)(pic),0x00,psize);
      else
      {
        if (pfx_images[orig].orig == 0) 
        { 
          i = orig; orig = dest; dest = i;
        }
	if (pfx_images[orig].orig == 0)
        { 
	  fprintf(stderr,"PFX orig doesn't exist yet. faking it.\n");
	  memset((char *)(pic),0x00,psize);
        }
	else memcpy((char *)(pic),(char *)(pfx_images[orig].data),psize);
      } 

      dmask = 0x01;
      while(len)
      {
        UBYTE *ptr;
        b_cnt = (ULONG)(*data++) << 8;   b_cnt |= (ULONG)(*data++);  len-=2;
        DEBUG_LEVEL3 fprintf(stderr,"b_cnt = %ld\n",b_cnt);
        while(len && b_cnt)
        {
          offset = (ULONG)(*data++) << 8; offset |= (ULONG)(*data++);  len-=2;
          a_cnt = (ULONG)(*data++) << 8;  a_cnt |= (ULONG)(*data++);  len-=2;
          DEBUG_LEVEL4 fprintf(stderr,"<%lx %lx> ",offset,a_cnt);
          ptr = (UBYTE *)(pic + (offset * 8));
	  for(i = 0; i <= a_cnt; i++)
	  {
            d = (ULONG)(*data++) << 8;  d |= (ULONG)(*data++);  len-=2;
	    IFF_Short_Mod(ptr,d,dmask,1);
            ptr += pfx_imagex;
          }
          b_cnt--;
        }
        DEBUG_LEVEL4 fprintf(stderr,"\n\n");
        dmask <<= 1;  /* move to next bitplane */
      }
      if (b_cnt != 0) fprintf(stderr,"b_cnt nonzero\n");

      pfx_images[dest].orig = dest;
      pfx_images[dest].data = pic;
      DEBUG_LEVEL2 fprintf(stderr,"New Image pfx_images[deset] = %ld\n",dest);
    } /* new image */

    tmp1_rchg = tmp_rchg;
    tmp_rchg = tmp_rchg->next; /* move to next image */
    FREE(tmp1_rchg->data,0x6000); tmp1_rchg->data=0;
    FREE(tmp1_rchg,0x6000); tmp1_rchg=0;

  } /* end of while rchg_hdr's */

  for(i=1; i<pfx_max_rchg; i++)
  {
    XA_ACTION *act;
    
    if (pfx_images[i].data == 0) fprintf(stderr,"ERROR: im not completed\n");
    act = ACT_Get_Action(anim_hdr);
    pfx_images[i].act = act;
    ACT_Setup_Mapped(act, pfx_images[i].data,
	pfx_chdr,0,0,pfx_imagex,pfx_imagey,pfx_imagex,pfx_imagey,FALSE,0,
	TRUE,TRUE,FALSE);
    ACT_Add_CHDR_To_Action(act,pfx_chdr);
  }
} /* end of function */

       
void PFX_Setup_CMAP(cmap_id,first_parm)
ULONG cmap_id;
PFX_RCHG_HDR *first_parm;
{
  ULONG found_flag,i;
  UBYTE *ptr;
  PFX_RCHG_HDR *tmp_parm;

  found_flag = FALSE;
  tmp_parm = first_parm;

  while(tmp_parm && (found_flag==FALSE))
  {
    if (tmp_parm->orig == cmap_id) found_flag = TRUE;
    else tmp_parm = tmp_parm->next;
  }

  if (found_flag == FALSE) TheEnd1(stderr,"PFX CMAP: not found\n");

  pfx_imagec = tmp_parm->len--;
  pfx_imagec /= 3;
  ptr = tmp_parm->data;
  for(i=0;i<pfx_imagec;i++)
  {
    ULONG d;
    d = (*ptr++) - 48; if (d > 9) d -= 7;   /* ascii to integer */
    pfx_cmap[i].red =  d & 0x0f;
    d = (*ptr++) - 48; if (d > 9) d -= 7;   /* ascii to integer */
    pfx_cmap[i].green =  d & 0x0f;
    d = (*ptr++) - 48; if (d > 9) d -= 7;   /* ascii to integer */
    pfx_cmap[i].blue =  d & 0x0f;
    DEBUG_LEVEL2 fprintf(stderr," %ld) %lx %lx %lx\n",
	i,pfx_cmap[i].red,pfx_cmap[i].green,pfx_cmap[i].blue);
  }
  pfx_chdr = ACT_Get_CMAP(pfx_cmap,pfx_imagec,0,pfx_imagec,0,4,4,4);
}
   

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.