/* $Id: un_sav.c,v 1.3 2000/07/06 10:19:58 jedwin Exp $ */

/*
 * un_sav: unpack the individual compressed files in the .sav file
 *
 * Note that this will also unpack .cbf files.
 *
 * 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 )
{
  unsigned long namelen;
  char namebuf[1024];
  unsigned long cmplen, uncmplen;
  FILE *fOut;
  void *destBuf, *srcBuf;
  unsigned long offset;

  offset = ftell( fIn );
  printf( "un-saving at offset 0x%08lx\n", offset );
  if ( fread( &namelen, 4, 1, fIn ) != 1 ) return 0;
  if ( fread( namebuf, 1, namelen, fIn ) != namelen ) return 0;
  if ( fread( &uncmplen, 4, 1, fIn ) != 1 ) return 0;
  if ( fread( &cmplen, 4, 1, fIn ) != 1 ) return 0;
  fOut = fopen( namebuf, "wb" );
  if ( fOut == NULL ) return 0;
  srcBuf = malloc( cmplen );
  destBuf = malloc( uncmplen );
  if ( !srcBuf || !destBuf || fread( srcBuf, 1, cmplen, fIn )!=cmplen )
    {
      fclose( fOut );
      if ( destBuf ) free( destBuf );
      if ( srcBuf ) free( srcBuf );
      return 0;
    }
  uncompress( destBuf, &uncmplen, srcBuf, cmplen );
  fwrite( destBuf, 1, uncmplen, fOut );
  fclose( fOut );
  free( destBuf );
  free( srcBuf );
  return 1;
}

void unSav( const char *filename )
{
  char signature[4], version[4];
  FILE *fIn = fopen( filename, "rb" );
  if ( !fIn ) return;
  fread( signature, 1, 4, fIn );
  fread( version, 1, 4, fIn );
  while( extractFile( fIn ) );
  fclose( fIn );
}

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