/*
** Copyright (C) 1988 by Jef Poskanzer and Craig Leres.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.

 *  Last modified: Mon Sep 14 01:33:35 1992 too
 *
 */

#include <math.h>
#include "amiga.h"
#include "original/tws.h"

#ifndef NULL
#define NULL 0
#endif

char *argv0;
int shadeflag = 0;
int demoflag = 0;
int reverseflag = 0;
int doubleflag = 0;

void	checkbitmapsize(int *, int *, int, int, int *, int *, int *, int *);
void	getbitmap(int, int, int, int, char **, int *, int *, int *, int *);

main(argc, argv)
	int argc;
	char **argv;
{
	int w, h, fm_w, fm_h, cx = 0, cy = 0, rx = 0, ry = 0;
	char *bits, *origbits;
	char *filename = NULL;
	int i, value;

	argv0 = argv[0];

again:
	argv++;
	argc--;
	if (argc > 0 && strcmp(argv[0], "-d") == 0) {
		doubleflag = 1;
		goto again;
	}
	if (argc > 0 && strcmp(argv[0], "-f") == 0) {
		if ((filename = argv[1]) == NULL)
		  goto usage;
		argv++;
		argc--;
		goto again;
	}
	if (argc > 0 && strcmp(argv[0], "-g") == 0) {
		argv++;
		argc--;
		for (i = 0; i < 4; i++) {
		  value = (int)argv[0][2 * i];
		  switch (value) {
		  case '\0':    goto again;
		  case '-':     value = -1;     break;
		  case '+':     value =  1;     break;
		  default:	goto usage;
		  }
		  if (!isdigit(argv[0][2 * i + 1]))
		    goto usage;
		  value = value * (argv[0][2 * i + 1] - '0');
		  switch (i) {
		  case 0:	cx = value;	break;
		  case 1:	cy = value;	break;
		  case 2:	rx = value;	break;
		  case 3:	ry = value;	break;
		  }
		}
		goto again;
	}
	if (argc > 0 && strcmp(argv[0], "-r") == 0) {
		reverseflag = 1;
		goto again;
	}
	if (argc > 0 && strcmp(argv[0], "-s") == 0) {
		shadeflag = 1;
		goto again;
	}
	if (argc > 0) {
usage:
		write(2, "usage: phoon [-d] [-s] [-f filename] [-g dcx[dcy[drx[dry]]]] [-r]\n", 66);
		exit(0);

	}
	write(1, "Phase of the moon, Amiga version 1.3 (14.9.1992)\n",50);
	am_OpenLibraries();

	am_GetScreenSize(&w, &h);
	bits = am_LoadFullmoon(&fm_w, &fm_h, filename);
	origbits = bits;
	checkbitmapsize(&w, &h, fm_w, fm_h, &cx, &cy, &rx, &ry);

	getbitmap(w, h, fm_w, fm_h, &bits, &cx, &cy, &rx, &ry);
	hackbits(dtwstime(), w, h, bits, cx, cy, rx, ry);
	am_MakeIFFile(w, h, bits, reverseflag);
	am_CloseLibraries();
	free(origbits);
	return 0;
}

short leftmask[16] = {
    0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
    0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
};
short rightmask[16] = {
    0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff, 0x00ff,
    0x007f, 0x003f, 0x000f, 0x001f, 0x0007, 0x0003, 0x0001, 0x0000,
};
#ifdef notdef
static char  leftmask[8] = {0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00};
static char rightmask[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
/*
static char  leftmask[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
static char rightmask[8] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
*/
#endif notdef

static short  shades_0_bits[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shades_1_bits[] = {0x0101,0x0000,0x0000,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shades_2_bits[] = {0x0101,0x0000,0x0404,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shades_3_bits[] = {0x0101,0x0000,0x0404,0x0000,0x8080,0x0000,
				  0x0000,0x0000};
static short  shades_4_bits[] = {0x0101,0x0000,0x0404,0x0000,0x8080,0x0000,
				  0x0000,0x1010};
static short  shades_5_bits[] = {0x0101,0x4040,0x0404,0x0000,0x8080,0x0000,
				  0x0000,0x1010};
static short  shades_6_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8080,0x0000,
				  0x0000,0x1010};
static short  shades_7_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8080,0x0000,
				  0x0101,0x1010};
static short  shades_8_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8080,0x2020,
				  0x0101,0x1010};
static short  shades_9_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8282,0x2020,
				  0x0101,0x1010};
static short shades_10_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8282,0x2020,
				  0x0505,0x1010};
static short shades_11_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8282,0x2020,
				  0x0505,0x5050};
static short shades_12_bits[] = {0x0101,0x4040,0x0505,0x2020,0x8282,0x2020,
				  0x0505,0x5050};
static short shades_13_bits[] = {0x0101,0x5050,0x0505,0x2020,0x8282,0x2020,
				  0x0505,0x5050};
static short shades_14_bits[] = {0x0101,0x5050,0x0505,0x2020,0x7575,0x2020,
				  0x0505,0x5050};
static short shades_15_bits[] = {0x0505,0x5050,0x0505,0x2020,0x7575,0x2020,
				  0x0505,0x5050};

short *shades_s[16] = {
    shades_0_bits,  shades_1_bits,  shades_2_bits,  shades_3_bits,
    shades_4_bits,  shades_5_bits,  shades_6_bits,  shades_7_bits,
    shades_8_bits,  shades_9_bits,  shades_10_bits, shades_11_bits,
    shades_12_bits, shades_13_bits, shades_14_bits, shades_15_bits };


static short  shaded_0_bits[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shaded_1_bits[] = {0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shaded_2_bits[] = {0x0003,0x0000,0x0030,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shaded_3_bits[] = {0x0003,0x0000,0x0030,0x0000,0xc000,0x0000,
				  0x0000,0x0000};
static short  shaded_4_bits[] = {0x0003,0x0000,0x0030,0x0000,0xc000,0x0000,
				  0x0000,0x0300};
static short  shaded_5_bits[] = {0x0003,0x3000,0x0030,0x0000,0xc000,0x0000,
				  0x0000,0x0300};
static short  shaded_6_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc000,0x0000,
				  0x0000,0x0300};
static short  shaded_7_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc000,0x0000,
				  0x0003,0x0300};
static short  shaded_8_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc000,0x0c00,
				  0x0003,0x0300};
static short  shaded_9_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc00c,0x0c00,
				  0x0003,0x0300};
static short shaded_10_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc00c,0x0c00,
				  0x0033,0x0300};
static short shaded_11_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc00c,0x0c00,
				  0x0033,0x3300};
static short shaded_12_bits[] = {0x0003,0x3000,0x0033,0x0c00,0xc00c,0x0c00,
				  0x0033,0x3300};
static short shaded_13_bits[] = {0x0003,0x3300,0x0033,0x0c00,0xc00c,0x0c00,
				  0x0033,0x3300};
static short shaded_14_bits[] = {0x0003,0x3300,0x0033,0x0c00,0x3f33,0x0c00,
				  0x0033,0x3300};
static short shaded_15_bits[] = {0x0033,0x3300,0x0033,0x0c00,0x3f33,0x0c00,
				  0x0033,0x3300};

short *shades_d[16] = {
    shaded_0_bits,  shaded_1_bits,  shaded_2_bits,  shaded_3_bits,
    shaded_4_bits,  shaded_5_bits,  shaded_6_bits,  shaded_7_bits,
    shaded_8_bits,  shaded_9_bits,  shaded_10_bits, shaded_11_bits,
    shaded_12_bits, shaded_13_bits, shaded_14_bits, shaded_15_bits };

#ifdef PI
#undef PI
#endif
#define PI 3.14159265358979323846  /* Assume not near black hole or in
				      Tennessee */

double jtime(), phase();

hackbits(t, w, h, bits, cx, cy, rx, ry)
	struct tws *t;
	int w, h;
	char *bits;
	int cx, cy, rx, ry;
{
	short *plane;
	double jd, angphase, cphase, aom, cdist, cangdia, csund, csuang;
	int i;
	register int x, y;
	int xleft, xright;
	double fxleft, fxright;
	double fy;
	int wxright, bxright, wxleft, bxleft;
	int off;
	double cap, ratio;
	int shadeindex;
	short shade, **shades;
	static double demoinc = 0.0;

	jd = jtime( t );

	angphase = phase( jd, &cphase, &aom, &cdist, &cangdia, &csund, &csuang);
	cap = cos( angphase );
	/* Hack to figure approximate earthlighting. */
	if ( cphase < 0.1 ) cphase = 0.1;
	if ( cphase > 0.9 ) cphase = 0.9;
	ratio = (1.0 - cphase) / cphase;  /* ratio varies from 9.0 to 0.111 */
	shadeindex = (int) ( ratio / 9.0 * 15.9999 );

#ifdef DEBUG
printf("angphase %f, cap %f\n", angphase, cap);
#endif
	shade = 0x0000;
	shades = doubleflag? shades_d: shades_s;

	plane = (short *)bits;

	for (i = 0; i < 2 * ry; i++) {
		y = cy - ry + i;
		fy = i - ry;
		fxright = rx * sqrt(1.0 - (fy * fy) / (ry * ry));
		fxleft = - fxright;
		if (angphase >= 0.0 && angphase < PI)
			fxright *= cap;
		else
			fxleft *= cap;

		xright = fxright + cx;
		xleft = fxleft + cx;

		wxright = xright / 16;
		bxright = xright % 16;

		wxleft = xleft / 16;
		bxleft = xleft % 16;

		off = y * ((w + 15) / 16);

		if ( shadeflag )
			shade = shades[shadeindex][y % 8];

		if (wxleft == wxright)
			plane[wxleft + off] &=
				leftmask[bxleft] | shade | rightmask[bxright];
		else {
			plane[wxleft + off] &= leftmask[bxleft] | shade;
			for (x = wxleft + 1; x < wxright; x++)
				plane[x + off] &= shade;
			plane[wxright + off] &= rightmask[bxright] | shade;
		}
	}
}

