#include <exec/types.h>
#include <intuition/intuition.h>
#include <stdio.h>
#include "machine.h"

/* Ez a gépfüggő modul különböző grafikus funkciókat valósit
 * meg AMIGAN. Linkeld hozzá ezt a modult a programodhoz és
 * használd az alábbi funkciókat (hogy kéjhömpöly legyen a
 * grafika)
 *
 *					Little Horse
 *					  (or MAO)
 *
 *     init_graphics();        Inicializálja a grafikus környezetet
 *     exit_graphics();        Lezárja a grafikus környezetet
 *     get_input();	       Inputot kér és beteszi a bufferbe
 *     set_pen();	       Beállitja a rajzolás szinét, vagy 
 *			       a szürkesegi fokozatot,
 *     move();		       Beállitja az aktuális poziciót
 *     draw();		       Az aktualis poziciótól vonalat húz adott
 *                             pontba
 *     plot();		       Bekapcsolja az adott pontot
 *     clear();		       kepernyőtörles
 *     punt();		       Belső használatra
 *
 * init_graphics() állitsd be az x_size, y_size, es max_intensity global 
 * változákat a hivás előtt.
 */

/* systen functions */
extern struct Screen *OpenScreen();
extern struct Library *OpenLibrary();
extern struct ViewPort *ViewPortAddress();

/* system variables */
struct IntuitionBase *IntuitionBase = NULL;	/* public to system */
struct GfxBase *GfxBase = NULL;
struct Screen *screen = NULL;			/* screen and its rastport */
struct RastPort *rp;

/* public variables */
SHORT x_size, y_size, max_intensity, intensity;

/*
 * init_graphics sets up the graphics bitmap for use 
 */

struct NewScreen newscreen = {
	0, 0, MAXPIXELS, MAXLINE, 0, 0, 1, NULL,
	CUSTOMSCREEN, NULL, NULL, NULL, NULL
};

/* standard colormap (GEM map with black and white reversed) */
UWORD colormap[16];

void init_graphics(req_mode)
int req_mode;
{
	long i;
	static UWORD colors[] = {
	0x0000 /* black */,	0x0fff /* white */,
	0x0f00 /* red */,	0x00f0 /* green */,
	0x000f /* blue */,	0x00ff /* cyan */,
	0x0ff0 /* yellow */,	0x0f0f /* magneta */
};

newscreen.Depth = (req_mode == GREYS) ? 4 : 3 ;
x_size = MAXPIXELS;
y_size = MAXLINE;
max_intensity = (1 << newscreen.Depth) - 1;
intensity = -1;

/* open libraries and screen */
if ((IntuitionBase = (struct IntuitionBase *)
    OpenLibrary("intuition.library", 0L)) == NULL)
	punt("couldn`t open intuition");
if ((GfxBase = (struct GfxBase *)
    OpenLibrary("graphics.library", 0L)) == NULL)
	punt("couldn`t open graphics library");
if ((screen = OpenScreen(&newscreen)) == NULL)
    punt("couldn`t open screen");
rp = &(screen->RastPort);
rp->TmpRas = NULL;	/* small hack for Amiga AreaFill hack */

/* assign colors (either as grey-shades or colors) */
if (req_mode == GREYS)
	for (i = 0; i <= max_intensity; ++i)
		colormap[i] = i | (i << 4) | (i << 8);
else for (i = 0; i < 8; ++i) colormap[i] = colors[i];

	LoadRGB4(&screen->ViewPort, colormap, 16L);

	clear();
}

/*
 * exit_graphics() is called to terminate the graphics environment.
 * If passed a non-null string, it prints that as an error message.
 * Otherwise, you just get the normal exit-from-program message.
 */

void exit_graphics(s)
char *s;
{
	WBenchToFront();
	if (s) printf("%s\n",s);
	printf("Hit RETURN to exit from program (Amiga-M to see picture) -- ");
	getchar();
	if (screen) CloseScreen(screen);
	if (GfxBase) CloseLibrary(GfxBase);
	if (IntuitionBase) CloseLibrary(IntuitionBase);
}

/* 
 * get_input returns a line of input in buffer "s". The promt "=>"
 * is displayed. If end-of-file or error is encountered, NULL is returned.
 */

char *get_input(s)
char *s;
{
	extern char *gets();
	printf("=> ");
	return gets(s);
}

/*
 * set_pen(), move(), draw(), plot() and clear() are used as a simple interface
 * to the Amiga drawing routines. In set_pen(), we avoid calling the
 * (slow) system routine if the color is already what is requested.
 * Note that absolutely no clipping is performed, and the system may
 * crash if an attempt is made to draw outside the window. It is thus
 * the responsibility of the calling program to ensure that any
 * necessary clipping is done.
 */

void set_pen(new_intensity)
SHORT new_intensity;
{
	if (new_intensity != intensity) {
		SetAPen(rp, (long) new_intensity);
		intensity = new_intensity;
	}
}

void move(x, y) SHORT x, y; { Move(rp, (long) x, (long) y); }
void draw(x, y) SHORT x, y; { Draw(rp, (long) x, (long) y); }
void plot(x, y) SHORT x, y; { WritePixel(rp, (long) x, (long) y); }
void clear() { SetRast(rp, 0L); }

/* 
 * punt() takes a string parameter which is passes to exit_graphics()
 * and then exits with an error.
 */

void punt(s)
char *s;
{
	exit_graphics(s);
	exit(1);
}
