#include <stdio.h>
#include <sys/types.h>

#include <exec/types.h>
#include <intuition/intuition.h>
#include <libraries/iffparse.h>
#include <clib/exec_protos.h>
#include <proto/intuition.h>
#include <proto/iffparse.h>
#include <proto/graphics.h>
#include <dos.h>

#define ID_ILBM		MAKE_ID('I','L','B','M')
#define ID_BODY		MAKE_ID('B','O','D','Y')
#define ID_BMHD		MAKE_ID('B','M','H','D')
#define ID_CMAP		MAKE_ID('C','M','A','P')

typedef struct {
        UWORD w, h;
        WORD  x, y;
        UBYTE nPlanes;
        UBYTE masking;
        UBYTE compression;
        UBYTE reserved;
        UWORD transparentColor;
        UBYTE xAspect, yAspect;
        WORD  pageWidth, pageHeight;
} BitMapHeader;

typedef struct {
        unsigned char R, G, B;
} IFFColorReg;

typedef struct {
        unsigned pad1:4, red:4, green:4, blue:4;
} color4;

extern struct Library *IntuitionBase, *GfxBase;
struct Library *IFFParseBase=NULL;

void ScreenDump( struct Screen *scr, char *fname )
{
  
        struct IFFHandle *iff;
        struct ViewPort vp;
	struct BitMap bm;
	struct ColorMap cm, *pcm;
	IFFColorReg *CMAPdata;
        unsigned AmiColorDat;
	unsigned cmapsize,i,j;
        BitMapHeader bmhd;

	if (sizeof(IFFColorReg)!=3) {
                printf("INTERNAL ERROR: IFFColorReg struct not packed!\n");
                return;
        };
        if (IntuitionBase==NULL || GfxBase==NULL) return;

	if(!(IFFParseBase = OpenLibrary("iffparse.library",0))) { 
		printf("Could not open iffparse.library!\n");
		return;
	};

        vp = scr->ViewPort;
	bm = scr->BitMap;
	cm = *vp.ColorMap;
        pcm = &cm;

        bmhd.w=scr->Width;
        bmhd.h=scr->Height;
        bmhd.x=0; 
        bmhd.y=0;
        bmhd.nPlanes=bm.Depth;
        bmhd.masking=0;
        bmhd.compression=0;
        bmhd.reserved=0;
        bmhd.transparentColor=0;
        bmhd.xAspect=1; 
        bmhd.yAspect=1;
        bmhd.pageWidth=scr->Width
        bmhd.pageHeight=scr->Height;

        iff = AllocIFF();
        iff->iff_Stream = Open( fname, MODE_NEWFILE);
        InitIFFasDOS(iff);
        OpenIFF(iff,IFFF_WRITE);

        PushChunk(iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN);

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

	cmapsize = ((1<<bm.Depth) * sizeof(IFFColorReg));
	CMAPdata = (IFFColorReg *) calloc(1,cmapsize);

        PushChunk(iff, ID_ILBM, ID_CMAP, cmapsize);
        for(i=0; i<(1<<bm.Depth); i++) {
		AmiColorDat = GetRGB4( &cm, i );
                CMAPdata[i].R = ((AmiColorDat & 0x0f00) >> 8) * 0x10;
                CMAPdata[i].G = ((AmiColorDat & 0x00f0) >> 4) * 0x10;
                CMAPdata[i].B =  (AmiColorDat & 0x000f) * 0x10;
		WriteChunkBytes(iff, &CMAPdata[i], 3);
        };
        PopChunk(iff);

        PushChunk(iff, ID_ILBM, ID_BODY, IFFSIZE_UNKNOWN);
	for(i=0;i<bm.Rows;i++) {
          for (j=0; j<bm.Depth; j++){
                WriteChunkBytes(iff, &bm.Planes[j][i*bm.BytesPerRow], bm.BytesPerRow);
          }
        }
        PopChunk(iff);

        PopChunk(iff);

        CloseIFF(iff);
        Close(iff->iff_Stream);
        FreeIFF(iff);
        if (IFFParseBase) CloseLibrary(IFFParseBase);
}
