/*==== Header ==============================================================
**
** Filename ......... ycur2iff.c
** Purpose .......... Converts .CUR (WinNT cursor format) to iff pics
** Coder ............ Yoda
** Start date ....... 03-Sep-95
** Version ..........
** Last ver. date ...
**
**==========================================================================
**
**    Copyright (C) 1991  Rodrigo Ventura
**
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation; either version 2 of the License, or
**    (at your option) any later version.
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**==========================================================================
*/

char version[] = "$VER: ycur2iff 1.0 (C) 1995 Yoda";

/*========================================================================*/
/*=== Includes ===========================================================*/
/*========================================================================*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <dos/dos.h>
#include <dos/doshunks.h>
#include <libraries/iffparse.h>
#include <datatypes/pictureclass.h> /* Just for BMHD struct */
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/iffparse.h>

/*========================================================================*/
/*=== Macros =============================================================*/
/*========================================================================*/


#define WI 32     /* Width */
#define HE 32     /* Height */
#define DE 4      /* Depth */
#define NC 16     /* # of colors */
#define PO 62     /* Palette offset */
#define CH 126    /* CUR's header */
#define AH 146    /* ANI's header */
#define IH 8      /* icon's pre-header */

#define PS (WI*HE/8)            /* Plane size */
#define IS (IH+CH+WI*HE/2+PS)   /* Icon size */

/* This is #define-o-mania ! 8-) */
#define ID_AUTH MAKE_ID('A','N','N','O')
#define RIFF_NAME "RIFF"
#define RIFF_SIZE 4
#define POINT '.'
#define NUL '\0'
#define EXT_SIZE 4

#define BTST(b,x) (((x)&(1<<(b)))>0)
#define BSET(b,x) ((x)|=(1<<(b)))


/*========================================================================*/
/*=== Data ===============================================================*/
/*========================================================================*/


char fileName[FILENAME_MAX] = "";
BPTR fileHandle=NULL;
UBYTE *fileBuffer=NULL;
ULONG fileSize=0;
int isAnim;


/*========================================================================*/
/*=== Prototypes =========================================================*/
/*========================================================================*/

int main( int argc, char **argv );
void parseArgs( void );
int readFile( void );
void freeBuffer( void );
void convertIcon( UBYTE *start );
void convertAnim( void );
void stripFilename( char *name );

/*========================================================================*/
/*=== Functions ==========================================================*/
/*========================================================================*/


int main( int argc, char **argv )
{
  parseArgs();
  if ( readFile() )
  {
    stripFilename( fileName );
    if ( isAnim )
      convertAnim();
    else
      convertIcon( fileBuffer );
  }
  freeBuffer();
}


/*------------------------------------------------------------------------*/


void parseArgs( void )
{
  char *name=NULL;
  struct RDArgs *args;

  args = ReadArgs( "FILE/A", (LONG *)&name, NULL );
  if ( name )
    strcpy( fileName, name );
  else
  {
    printf(
"-- ycur2iff -- .CUR (WinNT) to IFF converter\n"
"            (C) 1995 Master Yoda\n"
"Usage:\n"
"  ycur2iff <filename>\n" );
    fileName[0] = '\0';
  }
  FreeArgs( args );
}


/*------------------------------------------------------------------------*/


int readFile( void )
{
  struct FileInfoBlock fib;

  fileHandle = Open( fileName, MODE_OLDFILE );
  if ( fileHandle )
  {
    printf( "Reading file '%s'", fileName );
    fflush( stdout );
    ExamineFH( fileHandle, &fib );
    fileSize = fib.fib_Size;
    fileBuffer = malloc( fileSize );
    if ( fileBuffer )
    {
      Read( fileHandle, fileBuffer, fileSize );
      printf( " (%ld bytes).\n", fileSize );
      fflush( stdout );
      isAnim = ( memcmp(RIFF_NAME,fileBuffer,RIFF_SIZE) == 0 );
      Close( fileHandle );
      return 1;
    }
    else
      printf( " - No memory to read %ld bytes !\n", fileSize );
    Close( fileHandle );
  }
  else
    printf( "File '%s' not found !\n", fileName );

  return 0;
}


/*------------------------------------------------------------------------*/


void freeBuffer( void )
{
  if ( fileBuffer ) free(fileBuffer);
}


/*------------------------------------------------------------------------*/


void convertIcon( UBYTE *start )
{
  static char name[FILENAME_MAX];
  BPTR file;
  struct IFFHandle *iff;
  static struct BitMapHeader bmhdBody =
  {
    WI, HE, 0, 0, DE,
    mskNone, cmpNone, 0, 0,
    1, 1, HE, WI
  };
  static struct BitMapHeader bmhdMask =
  {
    WI, HE, 0, 0, 1,
    mskNone, cmpNone, 0, 0,
    1, 1, WI, HE
  };
  static struct ColorRegister cmap[NC];
  static UBYTE bodyPlane[HE][DE][WI/8];
  register int p, o, b;
  register UBYTE *ptr;

  ptr = start + CH;
  sprintf( name, "%s.body.iff", fileName );
  file = Open( name, MODE_NEWFILE );
  if ( file )
  {
    printf( "Writing body to '%s'.\n", name );

    iff = AllocIFF();
    if ( iff )
    {
      iff->iff_Stream = file;
      InitIFFasDOS( iff );
      OpenIFF(iff,IFFF_WRITE);

      PushChunk( iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN );

      PushChunk( iff, ID_ILBM, ID_BMHD, sizeof(struct BitMapHeader) );
      WriteChunkBytes( iff, &bmhdBody, sizeof(bmhdBody) );
      PopChunk( iff );

      PushChunk( iff, ID_ILBM, ID_AUTH, sizeof(version)-5 );
      WriteChunkBytes( iff, version+5, sizeof(version)-5 );
      PopChunk( iff );

      PushChunk( iff, ID_ILBM, ID_CMAP, sizeof(cmap) );
      for ( p=0 ; p<NC ; p++ )
      {
        cmap[p].blue  = start[ PO+4*p+0 ];
        cmap[p].green = start[ PO+4*p+1 ];
        cmap[p].red = start[ PO+4*p+2 ];
      }
      WriteChunkBytes( iff, &cmap, sizeof(cmap) );
      PopChunk( iff );

      PushChunk( iff, ID_ILBM, ID_BODY, IFFSIZE_UNKNOWN );
      for ( p=0 ; p<DE ; p++ )
        for ( o=0 ; o<PS ; o++ )
        {
          register UBYTE planar, chunky;

          planar = 0;
          for ( b=0 ; b<8 ; b++ )
          {
            chunky = ptr[4*o+b/2];
            if ( BTST(4*(b%2)+p,chunky) ) BSET(7-b,planar);
          }
          bodyPlane[o/(WI/8)][p][o%(WI/8)] = planar;
        }
      WriteChunkBytes( iff, bodyPlane, sizeof(bodyPlane) );
      PopChunk( iff );

      PopChunk( iff );
      CloseIFF( iff );
      FreeIFF( iff );
    }
    Close( file );
  }
  else
    printf(" - Can't open body file '%s' !\n", name );

  ptr += HE*WI/2;
  sprintf( name, "%s.mask.iff", fileName );
  file = Open( name, MODE_NEWFILE );
  if ( file )
  {
    printf( "Writing mask to '%s'.\n", name );

    iff = AllocIFF();
    if ( iff )
    {
      iff->iff_Stream = file;
      InitIFFasDOS( iff );
      OpenIFF(iff,IFFF_WRITE);

      PushChunk( iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN );

      PushChunk( iff, ID_ILBM, ID_BMHD, sizeof(struct BitMapHeader) );
      WriteChunkBytes( iff, &bmhdMask, sizeof(bmhdMask) );
      PopChunk( iff );

      PushChunk( iff, ID_ILBM, ID_AUTH, sizeof(version)-5 );
      WriteChunkBytes( iff, version+5, sizeof(version)-5 );
      PopChunk( iff );

      PushChunk( iff, ID_ILBM, ID_BODY, PS );
      WriteChunkBytes( iff, ptr, PS );
      PopChunk( iff );

      PopChunk( iff );
      CloseIFF( iff );
      FreeIFF( iff );
    }
    Close( file );
  }
  else
    printf(" - Can't open mask file '%s' !\n", name );
}


/*------------------------------------------------------------------------*/


void convertAnim( void )
{
  static char realName[FILENAME_MAX];
  int offset, n;

  printf( "Converting an icon animation ...\n" );
  strcpy( realName, fileName );
  for ( offset=AH,n=0 ; offset<fileSize ; offset+=IS,n++ )
  {
    sprintf( fileName, "%s.fr%03d", realName, n );
    convertIcon( &fileBuffer[offset+IH] );
  }
  strcpy( fileName, realName );
}


/*------------------------------------------------------------------------*/


void stripFilename( char *name )
{
  static char tmp[FILENAME_MAX];
  int size;

  strcpy( tmp, FilePart(name) );
  size = strlen( tmp );
  if ( (size>EXT_SIZE) && (tmp[size-EXT_SIZE]==POINT) )
    tmp[size-EXT_SIZE] = NUL;
  strcpy( name, tmp );
}


/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/*========================================================================*/
/*=== End ================================================================*/
/*========================================================================*/
