/***************************************************************************
*  Old2ILBM.c v2 --  Convert old format .pic file to ILBM file
*                    by Carolyn Scheppner  CBM  02/86
*     Using IFF rtns by J.Morrison and S.Shaw of Electronic Arts
*
*         Note: This program does not create a .info file for
*               the new IFF file. If need an icon for the file,
*               (ex. for Graphicraft), copy the .info file
*               for another picture and rename it to your
*               IFF file name with a .info suffix.
*
* Alink information:
* FROM     LIB:LStartup.obj,Old2ILBM.o,iffw.o,ilbmw.o,packer.o
* TO       Old2ILBM
* LIBRARY  LIB:lc.lib,LIB:amiga.lib
*
*  Note: B: assigned to libs:  and SRC: assigned to dir of .o files
*
***************************************************************************/

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <graphics/gfxbase.h>
#include <graphics/rastport.h>
#include <graphics/gfx.h>
#include <graphics/view.h>

#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

#include <iff/ilbm.h>

#define bufSize 512

struct IntuitionBase *IntuitionBase;
struct GfxBase       *GfxBase;
ULONG  DosBase;

struct BitMap   oldBitMap;
struct OldHeader {
          WORD  filetype;      /* 0x0000 = pic */
          WORD  compression;   /* 0x0000 (not implemented) */
          WORD  planes;        /* 0x0000 or x0005 means 5 planes */
          WORD  mini;          /* 0x0000 */
          ULONG datasize;      /* 0x0000FA00 for 320x200, 5 planes */
          WORD  xorig;         /* 0x0000 */
          WORD  yorig;         /* 0x0000 */
          WORD  height;        /* in bits */
          WORD  width;         /* may in bytes ! */
          } oldHeader = {0};
struct OldColor {              /* Old .pic colorTable format */
          BYTE  red;           /* 0x00 to 0x0f  R */
          BYTE  green;         /* 0x00 to 0x0f  G */
          BYTE  blue;          /* 0x00 to 0x0f  B */
          BYTE  pad;           /* 0x00            */
          } oldColor = {0};

WORD   colorTable[32];         /* Amiga colorTable, each WORD is 0x0RGB */

int    depth, width, height, i;

/* main() */
void main(argc,argv)
int  argc;
char **argv;
   {
   LONG oldfile;
   LONG newfile;
   IFFP iffp = NO_FILE;
   WORD colortemp;
   int  planebytes;

   printf("\nOLd2ILBM v2 - Converts old format .pic to IFF\n\n");

   if (argc < 3)
      printf("   Usage: 'Old2ILBM oldfilename newfilename'\n\n");
   else
      {
      if ((IntuitionBase =
       (struct IntuitionBase *)OpenLibrary("intuition.library",0))==NULL)
         cleanexit(-1);

      if ((GfxBase =
       (struct GfxBase *)OpenLibrary("graphics.library",0))==NULL)
         cleanexit(-1);

      if ((DosBase = OpenLibrary("dos.library",0))==NULL)
         cleanexit(-1);

      if ((oldfile = Open(argv[1], MODE_OLDFILE))==NULL)
         printf("Can't open %s\n\n",argv[1]);
      else
         {
         if ((newfile = Open(argv[2], MODE_NEWFILE))==NULL)
            printf("Can't open %s\n\n",argv[2]);
         else
            {
            printf(" Note: This program does not create a .info file\n");
            printf("       for the IFF picture file.  If you need an\n");
            printf("       icon, copy a picture .info file from your\n");
            printf("       IFF paint package and give it the same name\n");
            printf("       as your picture file adding a .info suffix.\n\n");

            Read(oldfile,(BYTE *)&oldHeader,20);

            width  = oldHeader.width;
             if (width == 40)  width = 320;  /* may have been in bytes */
             if (width == 80)  width = 640;
            height = oldHeader.height;
            depth  = oldHeader.planes;
             if (depth == 0)   depth = 5;

            InitBitMap(&oldBitMap,depth,width,height);
            for(i=0; i < depth; i++)
               {
               if((oldBitMap.Planes[i] =
                (PLANEPTR)AllocRaster(width,height)) == NULL)
                  {
                  printf("Can't allocate RAM for bitmap.\n");
                  cleanexit(-1); 
                  }
               }

            printf("\nConverting '%s' to IFF '%s'...\n\n", argv[1],argv[2]);

            for (i=0; i < (1<<depth); i++)
               {
                colortemp = 0;
                Read(oldfile,(BYTE *)&oldColor,4);
                colortemp = oldColor.red;
                colortemp = colortemp << 4;
                colortemp |= oldColor.green;
                colortemp = colortemp << 4;
                colortemp |= oldColor.blue;
                colorTable[i] = colortemp;
                }

            planebytes = (int)((width/8)*height);
            for(i=0; i < depth; i++)
               {
               Read(oldfile,oldBitMap.Planes[i],planebytes);
               }

            Write(newfile,"x",1);  /* so Seek to beginning works ? */

            iffp = PutPicture(newfile, &oldBitMap, &colorTable[0]);

            Close(newfile);
            }
         Close(oldfile);
         }

      cleanup();
      }
   }


cleanexit(error)
int error;
   {
   cleanup();
   exit(error);
   }

cleanup()
   {
   for (i=0; i < depth; i++)
      {
      if(oldBitMap.Planes[i] != NULL)
       FreeRaster(oldBitMap.Planes[i],width,height);
      }

   if (DosBase) CloseLibrary(DosBase);
   if (GfxBase) CloseLibrary(GfxBase);
   if (IntuitionBase) CloseLibrary(IntuitionBase);
   }

/** PutPicture() ***********************************************************
 *
 * Put a picture into an IFF file.
 * This procedure calls PutAnILBM, passing in an <x, y> location of <0, 0>,
 * a NULL mask, and a locally-allocated buffer. It also assumes you want to
 * write out all the bitplanes in the BitMap.
 *
 ***************************************************************************/
Point2D nullPoint = {0, 0};

IFFP PutPicture(file, bitmap, colorMap)
      LONG file;  struct BitMap *bitmap;  WORD *colorMap;
   {
   BYTE buffer[bufSize];
   return( PutAnILBM(file, bitmap, NULL,
           colorMap, bitmap->Depth, &nullPoint,
           buffer, bufSize) );
   }    

   
/** PutAnILBM() ************************************************************
 *
 * Write an entire BitMap as a FORM ILBM in an IFF file.
 * This version works for any display mode (C. Scheppner).
 *
 * Normal return result is IFF_OKAY.
 *
 * The utility program IFFCheck would print the following outline of the
 * resulting file:
 *
 *   FORM ILBM
 *     BMHD
 *     CMAP
 *     BODY       (compressed)
 *
 ***************************************************************************/
#define CkErr(expression)  {if (ifferr == IFF_OKAY) ifferr = (expression);}

IFFP PutAnILBM(file, bitmap, mask, colorMap, depth, xy, buffer, bufsize)
      LONG file;  struct BitMap *bitmap;  BYTE *mask;  WORD *colorMap;
      UBYTE depth;  Point2D *xy;
      BYTE *buffer;  LONG bufsize;
   {
   BitMapHeader bmHdr;
   GroupContext fileContext, formContext;
   IFFP ifferr;
   WORD pageWidth, pageHeight;

   pageWidth  = (bitmap->BytesPerRow) << 3;
   pageHeight = bitmap->Rows;

   ifferr = InitBMHdr(&bmHdr, bitmap, mskNone,
                      cmpByteRun1, 0, pageWidth, pageHeight);
   /* You could write an uncompressed image by passing cmpNone instead
    * of cmpByteRun1 to InitBMHdr. */
   bmHdr.nPlanes = depth;   /* This must be  <= bitmap->Depth */
   if (mask != NULL) bmHdr.masking = mskHasMask;
   bmHdr.x = xy->x;   bmHdr.y = xy->y;

   CkErr( OpenWIFF(file, &fileContext, szNotYetKnown) );
   CkErr(StartWGroup(&fileContext, FORM, szNotYetKnown, ID_ILBM, &formContext));

   CkErr( PutBMHD(&formContext, &bmHdr) );
   CkErr( PutCMAP(&formContext, colorMap, depth) );
   CkErr( PutBODY(&formContext, bitmap, mask, &bmHdr, buffer, bufsize) );

   CkErr( EndWGroup(&formContext) );
   CkErr( CloseWGroup(&fileContext) );
   return( ifferr );
   }    
