/**************
 ******##****** Filename:                 >> AAC_SAVE.C <<
 *****####***** Edit Date: 02.10.92
 ****######****
 ***##*##*##*** By: Wolfgang Hofer,
 **##**##**##**     Convert Anim (stroe frames as Pic or anim files)
 ******##******
 ******##****** Compiler: AztecC 5.0
 ******##****** Link:     see makefile
 ************** Computer: AMIGA 500
 **************
 **************
 */


#define C_SKIP  1
#define C_SAME  2
#define C_UNIQ  3


/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   EndWrFile
	close IFF File
	and fill in real length of 1.st FORM chunk
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

EndWrFile()
{
  long form_len;
  UWORD valid_frames;

  if(g_wr_fh == NULL) return;

  form_len = g_wr_pos - 8;
  Seek(g_wr_fh, 4L, OFFSET_BEGINNING);
  Write(g_wr_fh, &form_len, 4L);

  if(g_DPANoffset)
  {
    /* Patch the DPAN chunk with number of valid frames */
    valid_frames = g_frames_in_file - 2;
    Seek(g_wr_fh, (long)(g_DPANoffset + 10), OFFSET_BEGINNING);
    Write(g_wr_fh, &valid_frames, 2L);

    if(g_cli) printf("frames handled: %d\n", g_frames_in_file);
  }
  g_DPANoffset = 0;
  g_frames_in_file = 0;

  Close(g_wr_fh);
  g_wr_fh = 0;
  g_wr_pos = 0;
}               /* end EndWrFile */

/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   OpenWrFile
	Open IFF File for write.
	Filename is made of basename + g_file_count
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

OpenWrFile()
{
  static char filename[110];

  if(g_file_count < 1000)
  {
       sprintf(&filename[0], "%s%03d\0", &g_basename[0], g_file_count);
  }
  else sprintf(&filename[0], "%s%d\0", &g_basename[0], g_file_count);


  g_wr_fh = Open(filename, MODE_NEWFILE);
  if (g_wr_fh == NULL)  GoodBye(g_OpenErr, filename);

  if(g_cli) printf("Output to file: %s\n", filename);

  g_file_count++;
  g_wr_pos = 0;
}               /* end OpenWrFile */

/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   WriteCnt
      write to outputfile and count current postition
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

WriteCnt(f_buff, f_len)

char   *f_buff;
long    f_len;
{
  long len;

  len = Write(g_wr_fh, f_buff, f_len);
  if(f_len != len)
  {
    GoodBye("Error while writing file %s%d\n",
             &g_basename[0], g_file_count-1 );
  }
  g_wr_pos += len;


  if (*g_RawKey == RAW_ESC)      /* exit at ESCAPE Key */
  {
    g_exit = 1;
    g_retcode = *g_RawKey;
  }

}               /* end WriteCnt */

/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   ClearBitMap
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

ClearBitMap(f_bm)

struct BitMap *f_bm;
{
  short pl;
  long  plsize;

  plsize = g_bm->BytesPerRow * g_bm->Rows;
  for(pl = 0; pl < f_bm->Depth; pl++)
  {
    BigMemset(f_bm->Planes[pl],     /* dest */
	      0L,                   /* fill data */
	      plsize);              /* length */
  }
}               /* end ClearBitMap */

/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   CopyBitMap
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

CopyBitMap(f_src, f_dst)

struct BitMap *f_src;
struct BitMap *f_dst;
{
   long  plsize;
   short pl;

   plsize = g_bm->BytesPerRow * f_dst->Rows;

   for(pl = 0; pl < f_dst->Depth; pl++)
   {
      LongMemcpy(f_dst->Planes[pl],   /* dest */
		 f_src->Planes[pl],   /* src  */
		 plsize);
   }
}               /* end CopyBitMap */


/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   WriteBODY()
	   save Bitplanes as IFF_BODY chunk
	   pack each line if Compress==TRUE
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

WriteBODY(f_bm, f_compress)

struct BitMap *f_bm;
long  f_compress;


{
  UBYTE byte_buff;
  long  body_pos;
  long  pos;

  struct BODY
  {
    long id;
    long len;
    /* (un)Compressed Bitplanedata in Line by Line Order */
  } body;


  LONG  row, pl, count, i;
  UBYTE *PlanePtr[8];                      /* max 8 BitPlane-pointrs */
  UBYTE *pw;            /* write pointer into LineBuffer */
  UBYTE *pct;           /* pointer/counter to current Codebyte in LineBuff */
  UBYTE *pr;            /* Bitplane Readpointer (Line+Plane Increment) */
  UBYTE *p;             /* Bitplane Readpointer (Byte increment) */
  SHORT old, older;     /* the last 2 Bytes of a Bitplane Line */

  SHORT eq_flag;

  SHORT ByteWidth, Height;
  SHORT Depth;
  LONG  LineLen;

  UBYTE LineBuffer[400]; /* for max 3200 pixel Width */




  ByteWidth  = f_bm->BytesPerRow;
  Height = f_bm->Rows;
  Depth  = f_bm->Depth;

  /* make a copy of the screens BitPlanePointers */
  for(i = 0; i < Depth; i++)
    PlanePtr[i] = f_bm->Planes[i];


  body.id = ID_BODY;
  /* calculate length of uncompressed Body */
  body.len = (long)ByteWidth * (long)Height * (long)Depth;

  /* note: body.len must be corrected
   *       downto compressed length after writing this chunk !!
   */
  body_pos = g_wr_pos;   /* save current write position */
  WriteCnt(&body, (long)(sizeof(struct BODY)));

  if ((f_compress == 0)
  || (ByteWidth > 128))  /* Compress dont works above this Size */
  {
    for(row = 0; row < Height; row++)
      for(pl = 0; pl < Depth; pl++)
	WriteCnt(PlanePtr[pl] + (ByteWidth * row), (long)(ByteWidth));
  }
  else
  {
    /*
     * pack Lines with fib. delta Method
     * Compress if 3 or more ident Bytes
     * Dont Compress if Line is getting longer
     */
    body.len = 0;
    for(row = 0; row < Height; row++)
    {
      for(pl = 0;  pl < Depth; pl++)
      {
	eq_flag = 0;
	old = -44;
	older = -44;

	pct = &LineBuffer[0];
	*pct = 0xff;        /* reset counter */
	pw = pct +1;          /* set write pointer to 1.st databyte */
	pr = PlanePtr[pl] + (ByteWidth * row);
	p  = pr;

	/* Compress one Line into LineBuffer */
	for(count = ByteWidth; count > 0; count--)
	{
	  if((*p == old) && (*p == older))
	  {
	    if(eq_flag == 0)
	    {
	      if(*pct > 1)      /* Test if more than 2 bytes (old/older) */
	      {
		*pct = *pct -2; /* reduce last count by 2 (old/older) */
		pct = pw -2;    /* get adress of new count byte */
	      }

	      (*pct) = 254;     /* counter preset to 3 compr.Bytes (257 -3) */
	      pw = pct + 2;     /* pw points now to next free byte */
	    }
	    else (*pct)--;  /* invers count for each next identical Byte */

	    eq_flag = 1;
	    p++;                /* pointer to next Bitplane databyte */
	  }
	  else
	  {
	    if(eq_flag != 0)
	    {
	      pct +=2;
	      *(pct) = 0;       /* counter preset for 1 uncompressed Byte */
	      pw = pct + 1;
	      eq_flag = 0;
	    }
	    else (*pct)++;      /* count up each uncompressed Byte */

	    *(pw++) = *p;       /* copy Bitplane databyte to LineBuffer */

	    older = old;
	    old = *p;
	    p++;                /* pointer to next Bitplane databyte */
	  }
	}       /* end for count (line compress done) */

	LineLen = (long)pw - (long)(&LineBuffer[0]);
	if(LineLen > ByteWidth)
	{
	  /* Compress would Increase Data, lets write uncompressed Line */
	  byte_buff = ByteWidth -1;
	  WriteCnt(&byte_buff, 1L);  /* Code for n Unchanged Bytes */

	  body.len++;
	  WriteCnt(pr, (long)(ByteWidth));
	  body.len += ByteWidth;
	}
	else
	{
	  /* Write Compressed Buffer */
	  WriteCnt(&LineBuffer[0], (long)LineLen);
	  body.len += LineLen;

	}

      }         /* end for pl */
    }           /* end for row */
  }             /* end if compress */

  /* Test if even Chunksize */
  if(body.len & 1)
  {
    byte_buff = 0;
    WriteCnt(&byte_buff, 1L);   /* Add a Padbyte */
    body.len++;
  }

  /* now fill in the real BODY length */
  pos = g_wr_pos;
  Seek(g_wr_fh, body_pos, OFFSET_BEGINNING);
  WriteCnt(&body, (long)(sizeof(struct BODY)));

  /* and re-position to the current end of the writefile */
  Seek(g_wr_fh, pos, OFFSET_BEGINNING);
  g_wr_pos = pos;
}               /* end WriteBODY */


/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   WriteCMAP
	Write The Screen's Colormap to CMAP Chunk
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

WriteCMAP(f_cm, f_depth)

struct ColorMap *f_cm;
long             f_depth;

{
  long   chunk_len;
  struct CMAP
  {
    long id;
    long len;
    /* for each Color 3 Bytes R G and B Value */
  } cmap;

  long   ctcol;
  long   i;
  UWORD *col;
  UWORD  rgb;
  UBYTE  r, g, b;           /* Basic Colors */


  ctcol = 1 << f_depth;
  /* Amiga limitation downto 32 Colorregisters */
  if(ctcol > 32) ctcol = 32;

  cmap.id = ID_CMAP;
  cmap.len = ctcol * 3;

  chunk_len = sizeof(cmap);
  WriteCnt(&cmap, chunk_len);

  col = (UWORD *)f_cm->ColorTable;
  for(i = 0; i < ctcol; i++)
  {
    /* get next color (rgb) from Colortable */
    rgb = *(col++);

    /* and split into r, g, b Bytes
     * (the amiga specific 4 Bit colorinformation
     * is stored in the upper nibble of the Bytes in the cmap chunk)
     */
    r = (rgb & 0xf00) >> 4;
    g = (rgb & 0xf0);
    b = (rgb & 0xf)   << 4;

    WriteCnt(&r, 1L);
    WriteCnt(&g, 1L);
    WriteCnt(&b, 1L);
  }

}   /* end WriteCMAP */


/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   WriteCAMG
	save Special AMIGA Viewmodes Chunk CAMG
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

WriteCAMG(f_modes)

long f_modes;
{
  long   chunk_len;
  struct CAMG
  {
    long  id;
    long  len;
    short pad;
    short viewmodes;
  } camg;

  camg.id = ID_CAMG;
  camg.len =  sizeof(camg) - 8;
  camg.pad = 0;
  camg.viewmodes = f_modes;

  chunk_len = sizeof(camg);
  WriteCnt(&camg, chunk_len);
}               /* end WriteCAMG */


/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   WriteDPAN
	save Special Dpaint Frame timing
	(independet from display frequency PAL/NTSC)
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

WriteDPAN(f_time)

long f_time;
{
  long   chunk_len;
  struct DPAN
  {
    long  id;
    long  len;
    /* I dont know the meaning of the pad bytes */
    UBYTE pad1[2];
    UWORD ct_valid_frames;
    UBYTE frames_per_sec;
    UBYTE pad2[3];
  } dpan;

  /* save offset to the DPAN chunk for an update at file-close time */
  g_DPANoffset = g_wr_pos;

  /* prevent from divide by zero */
  if(f_time < 1) f_time = 1;

  dpan.id = ID_DPAN;
  dpan.len =  sizeof(dpan) - 8;
  dpan.pad1[0] = 0;
  dpan.pad1[1] = 3;
  dpan.ct_valid_frames = 0;  /* this UWORD is updated before file-close */
  dpan.frames_per_sec = g_freq_hz / f_time;
  dpan.pad2[0] = 0;
  dpan.pad2[1] = 0;
  dpan.pad2[2] = 0;

  chunk_len = sizeof(dpan);
  WriteCnt(&dpan, chunk_len);
}               /* end WriteDPAN */


/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   WriteANHD
	save Animation header according to given BitMap
	used Animtype and frametiming
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

WriteANHD(f_bm, f_time)

struct BitMap *f_bm;
long           f_time;
{
  long   chunk_len;
  short  i;

  struct ANHD
  {
   LONG  id;
   LONG  len;

   UBYTE operation; /* == 5 for RIFF style, == 7 for LongSkip style */
   UBYTE mask;
   UWORD w,h;
   WORD  x,y;
   ULONG abstime; /* for timing start of anim file in jiffies (notused)*/
   ULONG reltime; /* for timing last frame in jiffies */
   UBYTE interleave; /* =0 for XORing to two frames back, =1 for last frame
		      *     (not used yet)
		      */
   UBYTE pad0;
   ULONG bits;
   UBYTE pad[16];
  } anhd;


  anhd.id  = ID_ANHD;
  anhd.len = sizeof(anhd) - 8;

  anhd.operation  = 7;       /* == 7 for Long/Short/Skip style */
  anhd.mask       = 0;
  anhd.w          = f_bm->BytesPerRow * 8;
  anhd.h          = f_bm->Rows;
  anhd.x          = 0;
  anhd.y          = 0;
  anhd.abstime    = 0;       /* (notused)*/
  anhd.reltime    = f_time;  /* for timing last frame in jiffies */
  anhd.interleave = 0;       /* =0 for two frames back */
  anhd.pad0       = 0;

  if(g_dta_size != 2)   anhd.bits = 1;   /* bit#0 set: long  */
  else                  anhd.bits = 0;   /* bit#0 clr: short */

  if(g_dta_size == 1)
  {
    anhd.bits = 0;   /* bit#0 set: long  */
    anhd.operation  = 5;       /* == 5 for vert. rlc with skips */
  }

  anhd.bits |= (1 << 4);                 /* bit#4 set: vertical */


  for(i=0; i < 16; i++) anhd.pad[i] = 0;

  chunk_len = sizeof(anhd);
  WriteCnt(&anhd, chunk_len);
}               /* end WriteANHD */


/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   WriteBMHD
	save Bitmapheader according to given BitMap
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

WriteBMHD(f_bm, f_compress, f_modes)

struct BitMap    *f_bm;
long              f_compress;
long              f_modes;
{
  long   chunk_len;
  struct BMHD
  {
    long  id;
    long  len;
    short width;
    short height;
    short xpos, ypos;
    char  depth;
    char  masking;
    char  compress;
    char  pad;
    short transp_color;
    char  xaspect, yaspect;
    short page_width;
    short page_height;
  } bmhd;

  bmhd.id = ID_BMHD;
  bmhd.len = sizeof(bmhd) - 8;
  bmhd.width = bmhd.page_width = f_bm->BytesPerRow * 8;
  bmhd.height = bmhd.page_height = f_bm->Rows;
  bmhd.depth = f_bm->Depth;
  bmhd.xpos = 0;
  bmhd.ypos = 0;
  bmhd.masking = 0;
  bmhd.compress = f_compress;
  bmhd.pad = 0;
  bmhd.transp_color = 0;
  /* aspect Values for LORES+NOLACE */
  bmhd.xaspect = 20;
  bmhd.yaspect = 22;

  if (f_modes & HIRES)  bmhd.xaspect /= 2;
  if (f_modes & LACE)   bmhd.yaspect /= 2;


  chunk_len = sizeof(bmhd);
  WriteCnt(&bmhd, chunk_len);
}        /* end WriteBMHD */


/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   WriteFORM
	write FORM Header
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

WriteFORM(f_id, f_len)

long f_id;
long f_len;
{
  long   chunk_len;
  struct FORM
  {
    long  id;
    long  len;
    long  id2;
  } form;

  form.id = ID_FORM;
  form.len = f_len,       /* maybe corrected in later */
  form.id2 = f_id;

  chunk_len = sizeof(struct FORM);
  WriteCnt(&form, chunk_len);
}               /* end WriteFORM */



/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   WriteDLTA
	write Delta difference between 2 frames as DLTA Chunk
	Using vertical RunLength Compression with skips
	IFF Anim5 Method.  (g_dta_size == 1)
	or
	Vertical RunLength Compression with skips
	and extra (SHORT or LONG) data list --> ANIM7 Method.
	(SHORT: g_dta_size == 2,   LONG: g_dta_size== 4)
   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */

WriteDLTA(f_bm_cur, f_bm_ref)

struct BitMap *f_bm_cur;
struct BitMap *f_bm_ref;
{
  extern unsigned char *skip_comp_line();
  extern int  CompressColumnL();
  extern int  CompressColumnS();

  long   chunk_len;
  long   opc_length, dta_length;
  long   pl_changes;
  long   col, max_col;
  long   ptr_block_len;

  long   pl_ptr_cur;
  long   pl_ptr_ref;
  short  pl;

  /* Current/old Pointers to Opcode/data buffers for DLTA Compress */
  UBYTE *act_opc, *old_opc, *nxt_opc;
  UBYTE *act_dta, *old_dta;

  struct DLTA
  {
    long   id;
    long   len;
    long   opc_ptr[8];
    long   dta_ptr[8];
  } dlta;


  ptr_block_len = (sizeof(dlta)) - 8;  /* minimum size of empty chunk */

  old_opc = act_opc = g_opc_buff;
  old_dta = act_dta = g_dta_buff;

  /* be sure to use data sizes 1, 2 or 4 */
  if((g_dta_size != 1)
  && (g_dta_size != 2))
  {
    g_dta_size = 4;
  }

  max_col = f_bm_cur->BytesPerRow / g_dta_size;

  for(pl = 0; pl < 8; pl++)
  {
    dlta.opc_ptr[pl] = 0;
    dlta.dta_ptr[pl] = 0;

    pl_changes = 0;

    if(pl >= f_bm_cur->Depth) continue;

    pl_ptr_cur = (long)f_bm_cur->Planes[pl];
    pl_ptr_ref = (long)f_bm_ref->Planes[pl];

    for(col = 0; col < max_col; col++)
    {
      if(g_dbug_print) printf("Plane %d (Column %d)\n",
                               (long)pl, (long)col);

      if(g_dta_size == 1)
      {
	/* Anim 5 DLTA Vert byte run with skips
	 * (anim5 uses dta buffer for both opcodes and dta
	 * remember that dta buffer is large enough for
	 * a full Picture, while opc_buffer is NOT !!)
	 */
	nxt_opc = skip_comp_line(pl_ptr_cur,
				 pl_ptr_ref,
				 act_dta,
				 (WORD)f_bm_cur->Rows,
				 (WORD)f_bm_cur->BytesPerRow);
	if(*act_dta)
	{
	  /* the opc count for this column is not 0
	   * therefore we note that there are
	   * changes in this plane plane
	   */
	  pl_changes++;
	}

	/* advance to next available space in opc buffer */
	act_dta = nxt_opc;
      }
      else
      {
	if(g_dta_size == 2)
	{
	  pl_changes += CompressColumnS(pl_ptr_cur,
					pl_ptr_ref,
					(long)f_bm_cur->Rows,
					(long)f_bm_cur->BytesPerRow,
					&act_dta,
					&act_opc);
	}
	else
	{
	  pl_changes += CompressColumnL(pl_ptr_cur,
					pl_ptr_ref,
					(long)f_bm_cur->Rows,
					(long)f_bm_cur->BytesPerRow,
					&act_dta,
					&act_opc);
	}
      }

      /* set plane pointers to next column */
      pl_ptr_cur += g_dta_size;
      pl_ptr_ref += g_dta_size;

    }   /* end for column */



    if(pl_changes == 0)
    {
      /* reset buffer pointers because of empty plane
       * (all colums are only 'skip column' ops)
       */
      act_opc = old_opc;
      act_dta = old_dta;
    }
    else
    {
      /* set opc and dta pointers
       * (opc_ptr is corrected later by adding dta offest) */
      dlta.dta_ptr[pl] = ptr_block_len
		       + ((long)old_dta - (long)g_dta_buff);
      dlta.opc_ptr[pl] = ptr_block_len
		       + ((long)old_opc - (long)g_opc_buff);
    }

    old_opc = act_opc;
    old_dta = act_dta;

  }     /* end for planes */




  /* sepearate opc pointers are not used in Anim5 DLTA's
   * (dta_size of 1)
   */
  if(g_dta_size == 1) opc_length = 0;
  else                opc_length = ((long)old_opc - (long)g_opc_buff);

  dta_length = ((long)act_dta - (long)g_dta_buff);

  /* round up one pad byte */
  opc_length = ((opc_length +1) & 0xfffffffe);
  dta_length = ((dta_length +1) & 0xfffffffe);

  for(pl = 0; pl < 8; pl++)
  {
    if(g_dta_size == 1)
    {
      /* use dta pointers as opc pointer (must set the 1st 8 pointers)
       * then clr dta pointers in Anim5 formats
       */
      dlta.opc_ptr[pl] = dlta.dta_ptr[pl];
      dlta.dta_ptr[pl] = 0;
    }
    else
    {
      /* calculate real offsets of the opc_pointer in Anim7 formats */
      if(dlta.opc_ptr[pl])  dlta.opc_ptr[pl] += dta_length;
    }
  }


  /* Write DLTA Chunk (dlta_fix_part, dta, opc) */
  dlta.id   = ID_DLTA;
  dlta.len  = ptr_block_len;  /* minimum size of empty chunk */
  dlta.len += dta_length;
  dlta.len += opc_length;

  chunk_len = sizeof(dlta);
  WriteCnt(&dlta, chunk_len);

  if(dta_length) WriteCnt(g_dta_buff, dta_length);
  if(opc_length) WriteCnt(g_opc_buff, opc_length);


  if(g_dbug_print) printf("\n\n End of pic\n\n");


}               /* end WriteDLTA */
