/* $Id: un_bamc.c,v 1.1 2000/10/09 17:53:58 jedwin Exp $ */

/*
 * un_bamc: unpack a compressed .bam file
 *
 * This is a sample program from the Infinity Engine File Format Hacking
 * Project.  Use it as you like.  Author assumes no responsibility, yada yada
 * yada.
 */

#include <zlib.h>
#include <stdio.h>
#include <stdlib.h>

int extractFile( FILE *fIn, FILE *outfile, unsigned long outLen )
{
  unsigned long fileLen, temp;
  void *destBuf, *srcBuf;
  int status;

  /* read block header */
  temp = ftell( fIn );
  fseek( fIn, 0, SEEK_END );
  fileLen = ftell( fIn );
  fseek( fIn, temp, SEEK_SET );
  fileLen -= temp;

  /* allocate buffers for decompression */
  srcBuf = malloc( fileLen );
  destBuf = malloc( outLen );

  /* read block to compress */
  if ( !srcBuf || !destBuf || fread( srcBuf, 1, fileLen, fIn )!=fileLen )
    {
      if ( destBuf ) free( destBuf );
      if ( srcBuf ) free( srcBuf );
      return 0;
    }

  /* try the decompression */
  status=uncompress( destBuf, &outLen, srcBuf, fileLen );

  /* if success, write the decompressed data to the outfile */
  if ( status == Z_OK )
      fwrite( destBuf, 1, outLen, outfile );

  /* clean up our buffers */
  free( destBuf );
  free( srcBuf );

  /* if decompression was a success, return 1 */
  if ( status == Z_OK )
      return 1;
  else
      return 0;
}

void unBamc( const char *filename )
{
  char buffer[1024];
  char signature[4], version[4];
  unsigned long uncmplen;
  FILE *fOut;
  FILE *fIn;

  /* open input file */
  fIn = fopen( filename, "rb" );
  if ( !fIn ) return;

  /* create output file */
  sprintf( buffer, "%s.uncompressed", filename );
  fOut = fopen( buffer, "wb" );
  if ( !fOut )
  {
    fclose( fIn );
    return;
  }

  /* read header */
  fread( signature, 1, 4, fIn );
  fread( version, 1, 4, fIn );
  fread( &uncmplen, 4, 1, fIn );
  printf( "total BIF size (uncompressed): %d\n", uncmplen );

  /* extract all blocks */
  extractFile( fIn, fOut, uncmplen );

  fclose( fIn );
  fclose( fOut );
}

int main( int c, char **v )
{
  unBamc( v[1] );
  return 0;
}
