#include	<clib/all_protos.h>
#include	<exec/memory.h>
#include	<iff/iff.h>
#include	<iff/ilbm.h>
#include	<iffp/packer.h>


extern WORD WWidth,WHeight,WDepth;
extern struct Screen *WBScreen;
extern struct BitMap *TmpBitMap;
extern struct BitMap *NWBitMap;
extern struct RastPort VTmpRast;
extern struct RastPort *CWRast;
extern struct RastPort NWRast;
extern LONG BLeft,BTop;
extern int WriteFile(char *,ULONG);
extern UBYTE *GetColors(UBYTE *,ULONG);
extern int OpenWrite(UBYTE *);
extern void CloseWrite(void);
extern void ChangeNW(void);
extern void DisLine(struct RastPort *,char *,int);
extern struct NewWindow nw;
extern struct TextFont *CWFont;
extern struct Window *IntWindow;
extern struct GfxBase *GfxBase;

void Save(void)
{
ULONG	CTSize,CTCount,HeaderLength,BodyLength,ActualBody,LineLength;
LONG	PixCnt;
ULONG	*HdrSize,*HdrTop,*HdrBottom;
UBYTE	*MyColors;
ChunkHeader		*Chunk3D;
BitMapHeader	*MyHeader;

typedef		struct	{
	ID		ckID;
	}	sChunk;

SHORT PlnCnt;
UBYTE *OffPtr;
struct Window *SavingWnd;
UBYTE TmpArray[1600];
sChunk	*ChunkID;
char	*HdrBuffer,*BodyBuffer,*BytPtr;

ULONG	*ModBuf;
USHORT	LineCount;
	HdrBuffer = AllocMem(1200,MEMF_PUBLIC|MEMF_CLEAR);
	if (!HdrBuffer) {
		printf("Couldn't allocate memory for the header\n");
		return;
		}
	Chunk3D = (ChunkHeader *) HdrBuffer;
	Chunk3D -> ckID = FORM;
	Chunk3D++;
	ChunkID = (sChunk *) Chunk3D;
	ChunkID -> ckID = ID_ILBM;
	ChunkID++;
	ChunkID -> ckID = ID_BMHD;
	ChunkID++;
	HdrSize = (ULONG *)ChunkID;
	*HdrSize++ = 20;
	MyHeader = (BitMapHeader *)HdrSize;
	MyHeader -> w = WWidth;
	MyHeader -> h = WHeight;
	MyHeader -> compression = 1;
	CTCount = WDepth;
	MyHeader -> nPlanes = CTCount;
	MyHeader -> xAspect = 10;
	MyHeader -> yAspect = 10;
	MyHeader -> pageWidth = WWidth;
	MyHeader -> pageHeight = WHeight;
	MyHeader++;
	Chunk3D = (ChunkHeader *)MyHeader;
	Chunk3D -> ckID = ID_CMAP;
	CTSize = 1;
	while (CTCount)	{
		CTSize <<= 1;
		--CTCount;
		}
	Chunk3D -> ckSize = 3*CTSize;
	Chunk3D++;
	MyColors = (UBYTE *)Chunk3D;
	CTCount = WDepth;
	MyColors = GetColors(MyColors,CTSize);
	Chunk3D = (ChunkHeader *)MyColors;
	Chunk3D -> ckID = ID_CAMG;
	Chunk3D -> ckSize = 4;
	Chunk3D++;
	ModBuf = (ULONG *)Chunk3D;
	*ModBuf++ = WBScreen->ViewPort.Modes;
	Chunk3D = (ChunkHeader *)ModBuf;
	Chunk3D -> ckID = ID_BODY;
	CTCount = WWidth;
	CTCount >>= 3;
	CTCount = CTCount*WHeight;
	CTCount = CTCount*WDepth;
	TmpBitMap = (struct BitMap *)AllocBitMap((ULONG)WWidth,1,WDepth,BMF_CLEAR|BMF_DISPLAYABLE,WBScreen->RastPort.BitMap);
	if (!TmpBitMap) {
		printf("Couldn't allocate the 1st BitMap!\n");
		if (HdrBuffer) FreeMem(HdrBuffer,1200);
		}
	InitRastPort(&VTmpRast);
	VTmpRast.Layer = NULL;
	VTmpRast.BitMap = TmpBitMap;
	NWBitMap = (struct BitMap *)AllocBitMap((ULONG)WWidth,WHeight,WDepth,BMF_CLEAR,0);
	if (!NWBitMap) {
		printf("Couldn't allocate the 2nd BitMap!\n");
		FreeBitMap(TmpBitMap);
		if (HdrBuffer) FreeMem(HdrBuffer,1200);
		}
	InitRastPort(&NWRast);
	NWRast.BitMap = NWBitMap;
	CTCount = NWRast.BitMap->BytesPerRow;
	CTCount = CTCount*WHeight;
	CTCount = CTCount*WDepth;
	BodyLength = CTCount;
	BodyBuffer = AllocMem(BodyLength,MEMF_CLEAR);
	if (!BodyBuffer) {
		printf("Couldn't allocate memory for the image!\n");
		FreeBitMap(NWBitMap);
		FreeBitMap(TmpBitMap);
		if (HdrBuffer) FreeMem(HdrBuffer,1200);
		}
	ChangeNW();
	SavingWnd = OpenWindow(&nw);
	SetFont(SavingWnd->RPort,CWFont);
	BytPtr = BodyBuffer;
	PlnCnt = 0;
	LineCount = 0;
	while (LineCount < WHeight)	{
		ReadPixelLine8(CWRast,BLeft,LineCount+BTop,WWidth,&TmpArray[0],&VTmpRast);
		WritePixelLine8(&NWRast,0,LineCount,WWidth,&TmpArray[0],&VTmpRast);
		DisLine(SavingWnd->RPort,"Prepping Line ",WHeight - LineCount);
		LineCount++;
		}
	LineCount = 0;
	ActualBody = 0;
	LineLength = NWRast.BitMap->BytesPerRow;
	while (LineCount < WHeight)	{
		PlnCnt = 0;
		while (PlnCnt < WDepth) {
			OffPtr = (UBYTE *)NWRast.BitMap->Planes[PlnCnt];
			OffPtr = OffPtr + LineCount*LineLength;
			PixCnt = 0;
			PixCnt = PackRow((BYTE **)OffPtr,(BYTE **)BytPtr,(LONG)LineLength);
			if (!PixCnt) printf("0 returned, and Body Size Current is %lx\n",(ULONG)ActualBody);
			ActualBody = ActualBody + PixCnt;
			PlnCnt++;
			}
		DisLine(SavingWnd->RPort,"Saving Line ",WHeight - LineCount);
		Delay(1);
		++LineCount;
		}
/*	printf("The body length is %x\n",ActualBody);*/
	if ((ActualBody/2)*2 != ActualBody) {
		Chunk3D -> ckSize = ActualBody;
		ActualBody++;
			}
	else Chunk3D -> ckSize = ActualBody;
	Chunk3D++;
	HdrTop = (ULONG *)Chunk3D;
	HdrBottom = (ULONG *)HdrBuffer;
	HeaderLength = HdrTop - HdrBottom;
	HeaderLength <<= 2;	 /*Get # bytes */
	Chunk3D = (ChunkHeader *)HdrBuffer;
	CTCount = ActualBody + HeaderLength;
	Chunk3D -> ckSize = CTCount - 8;
	Delay(50);
	OpenWrite((UBYTE *)"Mand.iff");
	WriteFile(HdrBuffer,HeaderLength);
	WriteFile(BodyBuffer,ActualBody);
	CloseWrite();
	Delay(50);
	if (SavingWnd) CloseWindow(SavingWnd);
	if (BodyBuffer) FreeMem(BodyBuffer,BodyLength);
	if (HdrBuffer) FreeMem(HdrBuffer,1200);
	FreeBitMap(NWBitMap);
	FreeBitMap(TmpBitMap);
}

