/*==========================================================================*
 * large.c - Large code model routines for Discovery                        *
 * Copyright (c) 1985 by David Joiner (Talin)                               *
 *==========================================================================*/

#include "welcome.h"

#define CTRL_ESC

/* #include <pragmas.h> */

void gport_handler(struct in_work *mydata);

extern struct GfxBase		*GfxBase;
extern struct IntuitionBase *IntuitionBase;
extern WORD					numreq;
extern WORD					stopgame;
extern WORD					skipped;
extern struct View			*myView,*oldview;
extern struct Process		*myprocess;

struct InputEvent *HandlerInterface(struct InputEvent *ev,struct in_work *mydata);
#pragma regcall( HandlerInterface(a0,a1) )

struct InputEvent *HandlerInterface(struct InputEvent *ev,struct in_work *mydata)
{	struct InputEvent	*nxt;
	short				nextput,count;
	BYTE				key;

	if (numreq > 0) return ev;

	nxt = ev;

	while (nxt != NULL)
	{
		switch (nxt->ie_Class)
		{
			case IECLASS_RAWKEY:
#ifdef CTRL_ESC
			if (nxt->ie_Code == 0x50 && (nxt->ie_Qualifier & CONTROL))
			{
				if (stopgame == 0) LoadView(oldview);
				else
				{	oldview = GfxBase->ActiView;
					LoadView(myView);
				}
				stopgame ^= 1;
				nxt->ie_Class = IECLASS_NULL;
				break;
			}
			if (stopgame == 0)
#endif
			{	Forbid();
				nextput = (mydata->laydown + 1) & 127;
				if (nextput != mydata->pickup && (nxt->ie_Code & 0x80)==0 )
				{	key = 0;

					if (nxt->ie_Code >= 0x50 && nxt->ie_Code <= 0x59)
					{	if (nxt->ie_Qualifier & SHIFT)
							key = (nxt->ie_Code - 0x50) + S_FUNKEY1;
						else key = (nxt->ie_Code - 0x50) + FUNKEY1;
					}
					else if (nxt->ie_Code >= 0x4c && nxt->ie_Code <= 0x4f)
					{
			/*			if (nxt->ie_Qualifier & SHIFT)
							key = (nxt->ie_Code - 0x4c) + S_UP_ARROW;
						else
			*/
							key = (nxt->ie_Code - 0x4c) + UP_ARROW;
					}
					else if (nxt->ie_Code == 0x5f) key = HELP_KEY;
					else if (nxt->ie_Code < 0x60)
					{	count = RawKeyConvert(nxt,(char *)&key,1,NULL);
						if (count != 1) key = 0;
					}

					if (key)
					{
						if (key == RETURN || key == ' ' || key == ESCAPE)
						{	skipped = TRUE;
							Signal(&myprocess->pr_Task,SIGBREAKF_CTRL_C);
						}

						mydata->keybuf[mydata->laydown] = key;
						mydata->laydown = nextput;
					}
				}
				Permit();
			}
			break;

			case IECLASS_DISKINSERTED:
			if (stopgame == 0) mydata->newdisk = 2;
			break;

			case IECLASS_DISKREMOVED:
			if (stopgame == 0) mydata->newdisk = 1;
			break;

			case IECLASS_TIMER:
		/*	color_handler(); */
			if (stopgame == 0 && mydata->timeout > 0) mydata->timeout--;

			if (stopgame == 0) gport1_handler(mydata);		/* if gameport unit 1 */
			break;

			case IECLASS_RAWMOUSE:
				/* code for using gameport unit 0 (maybe) */
			if (stopgame == 0) gport0_handler(mydata,nxt);
			break;
		}

		if (stopgame == 0) nxt->ie_Class = IECLASS_NULL;

		nxt = nxt->ie_NextEvent;
	}

	return ev;
}

PVF old_autoreq;

long doautoreq(struct Window *Window,struct IntuiText *Body,
	struct IntuiText *PText,struct IntuiText *NText,long PFlag,long NFlag,
	long W,long H,PVF func);
long myautoreq(struct Window *Window,struct IntuiText *Body,
	struct IntuiText *PText,struct IntuiText *NText,long PFlag,long NFlag,
	long W,long H);

#pragma regcall( myautoreq(a0,a1,a2,a3,d0,d1,d2,d3) )
#pragma regcall( doautoreq(a0,a1,a2,a3,d0,d1,d2,d3,d4) )

long myautoreq(struct Window *Window,struct IntuiText *Body,
	struct IntuiText *PText,struct IntuiText *NText,long PFlag,long NFlag,
	long W,long H)
{
	long result;

	numreq++;

	if (GfxBase->ActiView == myView) LoadView(oldview);

	result = doautoreq(Window,Body,PText,NText,PFlag,NFlag,W,H,old_autoreq);

	if (--numreq == 0)
	{	oldview = GfxBase->ActiView;
		LoadView(myView);
		FreeSprite(0);
	}

	return result;
}

#asm

		xref	_IntuitionBase

_doautoreq
		movem.l	a4/a6,-(sp)
		move.l	_IntuitionBase,a6
		move.l	d4,a4
		jsr		(a4)
		movem.l	(sp)+,a4/a6
		rts

#endasm

patch_autorequest()
{
/*	old_autoreq = SetFunction((void *)IntuitionBase,-0x015c,(PVF)myautoreq); */
}

unpatch_autorequest()
{
/*	if (old_autoreq) SetFunction((void *)IntuitionBase,-0x015c,old_autoreq); */
	old_autoreq = NULL;
}

/* ==================================================================== */
/*						Color Animation Routines						*/
/* ==================================================================== */

	/* copy a range of colors from the source palette beginning to the dest */

void CopyColors(UWORD *palette,struct ColorEntry *ce)
{	int i;

	CopyMem(ce->source_colors,
			palette,
			ce->range_size * sizeof (UWORD));

/*	for (i=0; i < ce->range_size; i++)
	{	palette[ce->range_start + i] = ce->source_colors[i];
	}
*/
}

	/* fill a range of colors with a single color
		(source_length is overloaded as fill)
	*/

void FillColors(UWORD *palette,struct ColorEntry *ce)
{	int					i;

	for (i=0; i < ce->range_size; i++) *palette++ = ce->source_length;
}

	/* for each color in the range, randomely choose a color in the set */

void RandomColors(UWORD *palette,struct ColorEntry *ce)
{	int					i;

	if (ce->count == 0)
	{
		for (i=0; i < ce->range_size; i++)
		{	*palette++ = ce->source_colors[lchaos(ce->source_length)];
		}
		ce->count = ce->rate;
	}
	else ce->count--;
}

	/* cycle the colors a la DPaint, only more so... */

void CycleColors(UWORD *palette,struct ColorEntry *ce)
{	int					i;
	UWORD				offset;

	offset = ce->count / ce->rate;

	for (i = 0; i < ce->range_size; i++)
	{	*palette++ = ce->source_colors[(offset + i) % ce->source_length];
	}
	ce->count++;
}

void ReverseCycle(UWORD *palette,struct ColorEntry *ce)
{	int					i;
	UWORD				offset;

	offset = ce->count / ce->rate;

	for (i = 0; i < ce->range_size; i++)
	{	*palette++ = ce->source_colors[(offset + i) % ce->source_length];
	}
	ce->count--;
}

	/* fade the colors to black (or some other color). */
	/* this one requires that the dimness be set manually by the program... */

static UWORD black_palette[32];

void DimColors(UWORD *palette,struct ColorEntry *ce)
{
	InterpolateColors(
		black_palette,
		ce->source_colors,
		palette,
		ce->range_size,
		(ce->fade_level << 8));
}

	/* fade to a solid color */

void FadeTo(UWORD *palette,struct ColorEntry *ce)
{	static UWORD temp_palette[32];
	int i;

	for (i=0; i<32; i++) temp_palette[i] = ce->source_length;

	InterpolateColors(
		temp_palette,
		ce->source_colors,
		palette,
		ce->range_size,
		(ce->fade_level << 8));
}

	/* called by VBlank to do the color handling */

struct ColorAnimation *color_list;

color_handler()
{	struct ColorAnimation	*ca;
	struct ColorEntry		*ce;

	for (ca = color_list; ca; ca = ca->next)
	{	for (ce = ca->entry_list; ce; ce = ce->next_entry)
		{	if (ce->func) (ce->func)(ca->result_palette + ce->range_start,ce);
		}
		/* if (ca->result_colormap) ??? */
		if (ca->result_viewport)
			LoadRGB4(ca->result_viewport,ca->result_palette,32);
	}
}

static int flip = 0;

int VBlankInterface()
{	flip++;
	if (flip & 1) color_handler();
	return 0;
}
