/* screen.c -- code to open a screen and then call render */
#include <exec/types.h>
#include <stdio.h>
#include <math.h>
#include <intuition/intuition.h>

#include "globals.h"

#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/layers.h>

struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
struct LayersBase *LayersBase = NULL;

#define IREV 29
#define GREV 29

char defaultfile[] = "balls.default.dat";

#define DEPTH 6
int depth = DEPTH;

struct BitMap pbitmap = {	/* picture (screen) bitmap (*sbitmap) */
	0, 0, 0, 0, 0,
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};

struct BitMap tbitmap = {	/* temp (exact) bitmap */
	0, 0, 0, 0, 0,
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};

struct BitMap ibitmap = {	/* image bitmap */
	0, 0, 0, 0, 0,
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};

struct BitMap mbitmap = {	/* mask bitmap */
	0, 0, 0, 0, 0,
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};

struct NewScreen mynewscreen = {
	0, 0, WIDTH, 200, DEPTH,
	0, 15,
	HAM,
	CUSTOMSCREEN | CUSTOMBITMAP,
	NULL,
	"B & W   Low Res Screen",
	NULL,
	&pbitmap,
	};

struct Screen *myscreen = NULL;
struct ViewPort *vp;
struct BitMap *sbitmap = NULL;

struct NewWindow mynewwindow = {
	0, 1, WIDTH, 199,
	0, 15,
	MOUSEBUTTONS | MOUSEMOVE | CLOSEWINDOW,
	WINDOWCLOSE | SIMPLE_REFRESH | /* BACKDROP | */ BORDERLESS | 
		REPORTMOUSE | ACTIVATE,
	NULL,
	NULL,
	"   Please Wait . . . ",
	NULL,
	NULL,
	0, 0, 0, 0,
	CUSTOMSCREEN,
	};

struct Window *mywindow = NULL;

int bw = 0;

UWORD bwcolortable[16] = {
	0x000, 0x111, 0x222, 0x333, 0x444, 0x555, 0x666, 0x777,
	0x888, 0x999, 0xaaa, 0xbbb, 0xccc, 0xddd, 0xeee, 0xfff};

void
main(argc,argv)
int argc;
char *argv[];
{
	int i;
	void cleanup();

	switch (argc) {
		case 0: readballs(defaultfile);
			break;
		case 2:	readballs(argv[1]);
			break;
		case 3:	if (strcmp(argv[1],"-bw") == 0) {
				setbw();
				readballs(argv[2]);
				break;
			}
		default:dodefault();
	}

	onbreak(&cleanup);

	initrender();

	IntuitionBase = (struct IntuitionBase *)
		OpenLibrary("intuition.library",IREV);
	if (IntuitionBase == NULL) panic("Can't open intuition");
	GfxBase = (struct GfxBase *)
		OpenLibrary("graphics.library",GREV);
	if (GfxBase == NULL) panic("Can't open GfxBase");

	InitBitMap(&pbitmap,depth,WIDTH,HEIGHT);
	for (i=0; i < depth; i++) {
		pbitmap.Planes[i] = (PLANEPTR)AllocRaster(WIDTH,HEIGHT);
		if (pbitmap.Planes[i] == NULL)
			panic("Not enough memory for screen");
		BltClear(pbitmap.Planes[i],RASSIZE(WIDTH,HEIGHT),0);
	}
	if (!bw) {
	    InitBitMap(&tbitmap,depth,WIDTH,SMHEIGHT);
	    for (i=0; i < depth; i++) {
		tbitmap.Planes[i] = (PLANEPTR)AllocRaster(WIDTH,SMHEIGHT);
		if (tbitmap.Planes[i] == NULL)
			panic("Not enough memory for temp bit map");
		BltClear(tbitmap.Planes[i],RASSIZE(WIDTH,SMHEIGHT),0);
	    }
	}
	InitBitMap(&ibitmap,depth,maskw,maskh);
	for (i=0; i < depth; i++) {
		ibitmap.Planes[i] = (PLANEPTR)AllocRaster(maskw,maskh);
		if (ibitmap.Planes[i] == NULL)
			panic("Not enough memory for image bit map");
		BltClear(ibitmap.Planes[i],RASSIZE(maskw,maskh),0);
	}
	InitBitMap(&mbitmap,1,maskw,maskh);
	mbitmap.Planes[0] = (PLANEPTR)AllocRaster(maskw,maskh);
	if (mbitmap.Planes[0] == NULL)
		panic("Not enough memory for mask bit map");
	BltClear(mbitmap.Planes[0],RASSIZE(maskw,maskh),0);

	myscreen = (struct Screen *) OpenScreen(&mynewscreen);
	if (myscreen == NULL) panic("Can't open screen");
	vp = &(myscreen->ViewPort);
	sbitmap = &(myscreen->BitMap);

	mynewwindow.Screen = myscreen;
	mywindow = (struct Window *) OpenWindow(&mynewwindow);
	if (mywindow == NULL) panic("Can't open window");

	if (bw) LoadRGB4(&myscreen->ViewPort,bwcolortable,16);
	else    LoadRGB4(&myscreen->ViewPort,colortable,16);
	RethinkDisplay();

	render();

	cleanup();
}

void
panic(str)
char *str;
{
	fprintf(stderr,"%s\n",str);
	fflush(stderr);
	cleanup();
}

void
cleanup()
{
	int i;

	if (mywindow) CloseWindow(mywindow);
	if (myscreen) CloseScreen(myscreen);
	if (mbitmap.Planes[0]) FreeRaster(mbitmap.Planes[0],maskw,maskh);
	for (i = depth-1; i >= 0; i--) if (ibitmap.Planes[i])
		FreeRaster(ibitmap.Planes[i],maskw,maskh);
	for (i = depth-1; i >= 0; i--) if (tbitmap.Planes[i])
		FreeRaster(tbitmap.Planes[i],WIDTH,SMHEIGHT);
	for (i = depth-1; i >= 0; i--) if (pbitmap.Planes[i])
		FreeRaster(pbitmap.Planes[i],WIDTH,HEIGHT);
	if (GfxBase)  CloseLibrary((struct Library *)GfxBase);
	if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
	exit(0);
}

void
setbw()
{
	bw = TRUE;
	mynewscreen.Depth = depth = 4;
	mynewscreen.ViewModes &= ~HAM;
}

void
dodefault()
{
  printf("  %c33manimballs%c31m - An animation hack by JimG\n\n",0x9b,0x9b);
  printf("Usage: animballs [-bw] ballsfile\n\n");
  printf("  You have invoked animballs without parameters. I will use\n");
  printf("a default balls file (balls.default.dat). You should read the\n");
  printf("README file to see how to run this program. As a quick intro,\n");
  printf("there will be a delay and then you will see some balls appear.\n");
  printf("Press and hold the left mouse button, then drag the mouse to\n");
  printf("rotate the balls in 3-space. Click on the close gadget to end.\n\n");
  printf("Press <Return> to continue:");

  (void) getc(stdin);
  readballs(defaultfile);
}

