/*****************************************************************************\
 * $VER: TetrisQ_figurectrl.c 1.4                                            *
 *                               DICE/LATTICE C/SAS C/AZTEC C + AmigaOS 2.04 *
 *                 _                                                         *
 * 4.10.92    _   // (c)1992 by "Quarky" Dieter Temme                        *
 *            \\ //                                                          *
 * :ts=4       \X/ --- Freeware --- ONLY AMIGA MAKES IT POSSIBLE             *
 *                                                                           *
\*****************************************************************************/

#include "amigacompq.h"
#include "definitions.h"

#include <stdlib.h>
#include <string.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <exec/memory.h>
#include <libraries/gadtools.h>

#ifdef PRAGMAS_
 #include <pragmas/dos_lib.h>
 #include <pragmas/exec_lib.h>
 #include <pragmas/graphics_lib.h>
 #include <pragmas/intuition_lib.h>
#endif

/*>> local variables <<*/
BYTE row[2];		/* actual uppest row of falling figure (0..ROWS_-1) */
BYTE col[2];		/* actual leftest column of falling figure (0..COLS_-1) */
BYTE rot[2];		/* actual rotation of figure (0..3) */
BYTE fig[2];		/* actual figure number */
BYTE wdt[2];		/* actual width of falling figure */
BYTE hgt[2];		/* actual height of falling figure */
WORDBITS figure[2][4]; /* bit representation of figure in the playfield */
WORDBITS field[2][20]; /* bit representation of playfield */
BOOL isvisible[2];	/* TRUE if falling figure is now visible */
BOOL depth;			/* TRUE if screen depth is greater than 2 */
UWORD length;		/* length of imagedata */
void *ptr;			/* pointer for figure image in chip memory */
struct Image image=	/* image for figure imagedata */
{	0,0, PIXX_,PIXY_, 2, NULL, 0x03,0x00, NULL
};
UBYTE player1keys[NUMPLAYERKEYS]; /* rawkeys for player 1 */
UBYTE player2keys[NUMPLAYERKEYS]; /* rawkeys for player 2 */
UBYTE pausekey[1];	/* rawkey to pause */


/*==== initialize figure memory (TRUE if successful) ====*/
void FC_OpenFigure_(void)
{	extern struct Window *win; /* from "playerctrl.c" */

	depth= (win->RPort->BitMap->Depth > 2);
	image.Depth= 2+depth;
	length= depth? 54*sizeof(UWORD) : 36*sizeof(UWORD);
	image.ImageData= ptr= AllocMemQ_(length, MEMF_CHIP);
}

/*==== free figure memory ====*/
void FC_CloseFigure_(void)
{	if (ptr)
	{	FreeMem(ptr, length);
		ptr= NULL;
	}
}

/*==== set/remove falling from playfield ====*/
#define fc_SET_	TRUE
#define fc_CLR_	FALSE

void SetClrFigure_(const BOOL set)
{	extern struct RastPort *rport; /* from "playerctrl.c" */
	extern UWORD wbleft, wbtop, winoffs[2]; /* from "playerctrl.c" */
	extern BYTE players, pl; /* from "playerctrl.c" */
	ULONG x, y, rig;
	UWORD bit;
	UBYTE i;

	static UWORD imagedata4[7][36]=
	{	{	0x0000,0x4000,0x3fff,0xc000,0x3fff,0xc000,0x3ccb,0xc000,
			0x3c03,0xc000,0x3e07,0xc000,0x3f1f,0xc000,0x3fff,0xc000,
			0x7fff,0xc000,0xffff,0x8000,0xffff,0x0000,0xf8c7,0x0000,
			0xf007,0x0000,0xf00f,0x0000,0xf81f,0x0000,0xfe3f,0x0000,
			0xffff,0x0000,0x8000,0x0000
		},
		{	0x0000,0x4000,0x3fff,0xc000,0x3fff,0xc000,0x3e1f,0xc000,
			0x3c03,0xc000,0x3e07,0xc000,0x3c0f,0xc000,0x3fff,0xc000,
			0x7fff,0xc000,0xffff,0x8000,0xffff,0x0000,0xfc0f,0x0000,
			0xf807,0x0000,0xf00f,0x0000,0xf81f,0x0000,0xffff,0x0000,
			0xffff,0x0000,0x8000,0x0000
		},
		{	0x0000,0x4000,0x3fff,0xc000,0x3ffd,0xc000,0x3c03,0xc000,
			0x3c0f,0xc000,0x3c3f,0xc000,0x38ff,0xc000,0x3fff,0xc000,
			0x7fff,0xc000,0xffff,0x8000,0xffff,0x0000,0xf003,0x0000,
			0xf00f,0x0000,0xf03f,0x0000,0xf1ff,0x0000,0xf7ff,0x0000,
			0xffff,0x0000,0x8000,0x0000
		},
		{	0x0000,0x4000,0x3fff,0xc000,0x3ffb,0xc000,0x3c03,0xc000,
			0x3c03,0xc000,0x3c03,0xc000,0x3803,0xc000,0x3fff,0xc000,
			0x7fff,0xc000,0xffff,0x8000,0xffff,0x0000,0xf007,0x0000,
			0xf00f,0x0000,0xf00f,0x0000,0xf00f,0x0000,0xf7ff,0x0000,
			0xffff,0x0000,0x8000,0x0000
		},
		{	0x0000,0x4000,0x3fff,0xc000,0x3fff,0xc000,0x3fff,0xc000,
			0x3fff,0xc000,0x3fff,0xc000,0x3fff,0xc000,0x3fff,0xc000,
			0x7fff,0xc000,0xffff,0x8000,0xffff,0x0000,0xfc1f,0x0000,
			0xf9e3,0x0000,0xf3ff,0x0000,0xf9e3,0x0000,0xfc1f,0x0000,
			0xffff,0x0000,0x8000,0x0000
		},
		{	0x0000,0x4000,0x3fff,0xc000,0x3f7f,0xc000,0x3edf,0xc000,
			0x3dff,0xc000,0x3bdf,0xc000,0x37bf,0xc000,0x3fff,0xc000,
			0x7fff,0xc000,0xffff,0x8000,0xffff,0x0000,0xff87,0x0000,
			0xff27,0x0000,0xfe07,0x0000,0xfce7,0x0000,0xf843,0x0000,
			0xffff,0x0000,0x8000,0x0000
		},
		{	0x0000,0x4000,0x3fff,0xc000,0x3ffc,0xc000,0x3ff0,0xc000,
			0x3fc0,0xc000,0x3f30,0xc000,0x3c0c,0xc000,0x3003,0xc000,
			0x7fff,0xc000,0xffff,0x8000,0xc000,0x0000,0xf003,0x0000,
			0xfc0f,0x0000,0xff3f,0x0000,0xfc0f,0x0000,0xf003,0x0000,
			0xc000,0x0000,0x8000,0x0000
		}
	};
	static UWORD imagedata8[4][54]=
	{	{	0x0000,0x4000,0x3FFF,0xC000,0x3FFF,0xC000,0x3FFF,0xC000,0x3FFF,
			0xC000,0x3FFF,0xC000,0x3FFF,0xC000,0x3FFF,0xC000,0x7FFF,0xC000,
			0xFFFF,0x8000,0xC000,0x0000,0xC000,0x0000,0xC000,0x0000,0xC000,
			0x0000,0xC000,0x0000,0xC000,0x0000,0xC000,0x0000,0x8000,0x0000,
			0x0000,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,
			0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x0000,0x0000
		},
		{	0x0000,0x4000,0x0000,0xC000,0x0000,0xC000,0x0000,0xC000,0x0000,
			0xC000,0x0000,0xC000,0x0000,0xC000,0x0000,0xC000,0x7FFF,0xC000,
			0xFFFF,0x8000,0xFFFF,0x0000,0xFFFF,0x0000,0xFFFF,0x0000,0xFFFF,
			0x0000,0xFFFF,0x0000,0xFFFF,0x0000,0xFFFF,0x0000,0x8000,0x0000,
			0x0000,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,
			0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x0000,0x0000
		},
		{	0x0000,0x4000,0x3FFF,0xC000,0x3FFF,0xC000,0x3FFF,0xC000,0x3FFF,
			0xC000,0x3FFF,0xC000,0x3FFF,0xC000,0x3FFF,0xC000,0x7FFF,0xC000,
			0xFFFF,0x8000,0xFFFF,0x0000,0xFFFF,0x0000,0xFFFF,0x0000,0xFFFF,
			0x0000,0xFFFF,0x0000,0xFFFF,0x0000,0xFFFF,0x0000,0x8000,0x0000,
			0x0000,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,
			0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x0000,0x0000
		},
		{	0x0000,0x4000,0x0000,0xC000,0x0000,0xC000,0x0000,0xC000,0x0000,
			0xC000,0x0000,0xC000,0x0000,0xC000,0x0000,0xC000,0x7FFF,0xC000,
			0xFFFF,0x8000,0xC000,0x0000,0xC000,0x0000,0xC000,0x0000,0xC000,
			0x0000,0xC000,0x0000,0xC000,0x0000,0xC000,0x0000,0x8000,0x0000,
			0x0000,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,
			0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x3FFF,0x0000,0x0000,0x0000
		}

	};

	/*- if figure is not visible at the moment, return -*/
	if (set == isvisible[pl]) return;

	/*- if figure is to set, copy imagedata into ChipMem -*/
	if (set)
	{	CopyMem(depth? imagedata8[fig[pl]&3] : imagedata4[fig[pl]], ptr,
			length);
		if (depth) image.PlanePick= (fig[pl] <= 3)? 0x07 : 0x03;
	} else
		SetAPen(rport, 0);

	/*- draw or delete figure in playfield -*/
	i= 0;
	y= wbtop+PGTOP_+row[pl]*PIXY_;
	rig= winoffs[pl]+(col[pl]+wdt[pl])*PIXX_;
	do
	{	x= wbleft+PGLEFT_+winoffs[pl]+col[pl]*PIXX_; bit= 1<<(15-col[pl]);
		do
		{	if (figure[pl][i]&bit)
				if (set)	DrawImage(rport, &image, x, y);
				else		RectFill(rport, x, y, x+PIXXM1_, y+PIXYM1_);
			bit>>= 1;
		} while ((x+= PIXX_) < rig);
		y+= PIXY_;
	} while (++i < hgt[pl]);

	/*- set state of invisibility -*/
	isvisible[pl]= set;
}

/*==== test if the manipulation of a figure is acceptable ====*/
BOOL NoCollision_(const BYTE xrel, const BYTE yrel)
{	extern BYTE players, pl; /* from "playerctrl.c" */
	UBYTE i, j= row[pl]+yrel;

	for (i= 0; i < hgt[pl]; j++, i++)
		if ((j >= ROWS_) || (field[pl][j]&((xrel > 0) ?
			figure[pl][i]>>xrel : figure[pl][i]<<(-xrel)))) return FALSE;
	return TRUE;
}

/*==== take over a (rotated) figure pattern into the appropiate field ====*/
#define fc_NEW_	TRUE
#define fc_OLD_	FALSE

void GetFigure_(const BOOL new)
{	BYTE i;
	extern UBYTE status[2]; /* from "playerctrl.c" */
	extern BYTE players, pl; /* from "playerctrl.c" */

	static UBYTE figures[7][4][4]=
	{	0xc0, 0xc0, 0x00, 0x00, /* blue 0 */
		0xc0, 0xc0, 0x00, 0x00, /* blue 1 */
		0xc0, 0xc0, 0x00, 0x00, /* blue 2 */
		0xc0, 0xc0, 0x00, 0x00, /* blue 3 */
		0xf0, 0x00, 0x00, 0x00, /* red 0 */
		0x80, 0x80, 0x80, 0x80, /* red 1 */
		0xf0, 0x00, 0x00, 0x00, /* red 2 */
		0x80, 0x80, 0x80, 0x80, /* red 3 */
		0xc0, 0x60, 0x00, 0x00, /* lblue 0 */
		0x40, 0xc0, 0x80, 0x00, /* lblue 1 */
		0xc0, 0x60, 0x00, 0x00, /* lblue 2 */
		0x40, 0xc0, 0x80, 0x00, /* lblue 3 */
		0x60, 0xc0, 0x00, 0x00, /* green 0 */
		0x80, 0xc0, 0x40, 0x00, /* green 1 */
		0x60, 0xc0, 0x00, 0x00, /* green 2 */
		0x80, 0xc0, 0x40, 0x00, /* green 3 */
		0x40, 0xe0, 0x00, 0x00, /* yellow 0 */
		0x40, 0xc0, 0x40, 0x00, /* yellow 1 */
		0xe0, 0x40, 0x00, 0x00, /* yellow 2 */
		0x80, 0xc0, 0x80, 0x00, /* yellow 3 */
		0xc0, 0x40, 0x40, 0x00, /* lilac 0 */
		0xe0, 0x80, 0x00, 0x00, /* lilac 1 */
		0x80, 0x80, 0xc0, 0x00, /* lilac 2 */
		0x20, 0xe0, 0x00, 0x00, /* lilac 3 */
		0xc0, 0x80, 0x80, 0x00, /* grey 0 */
		0x80, 0xe0, 0x00, 0x00, /* grey 1 */
		0x40, 0x40, 0xc0, 0x00, /* grey 2 */
		0xe0, 0x20, 0x00, 0x00  /* grey 3 */
	};
	static BYTE modific[7][4][2]= /* pairs of col,row */
	{	+0,+0, +0,+0, +0,+0, +0,+0, /* blue */
		-2,+1, +2,-1, -2,+1, +2,-1, /* red */
		-1,+1, +1,-1, -1,+1, +1,-1, /* lblue */
		-1,+1, +1,-1, -1,+1, +1,-1, /* green */
		-1,+0, +0,+0, +0,+1, +1,-1, /* yellow */
		+0,+0, +0,+1, +0,-1, +0,+0, /* lilac */
		+0,-1, +0,+0, +0,+0, +0,+1, /* grey */
	};
	static BYTE dimens[7][2]= /* pairs of wid,hgt */
	{	2,2, /* blue */
		4,1, /* red */
		3,2, /* lblue */
		3,2, /* green */
		3,2, /* yellow */
		2,3, /* lilac */
		2,3, /* grey */
	};
	static BYTE column[7]=
	{	+1, +0, +0, +0, +0, +1, +1
	};

	if (new)
	{	fig[pl]= rand()%7;
		rot[pl]= 0;
		col[pl]= 3+column[fig[pl]];
		row[pl]= 0;
		isvisible[pl]= FALSE;
	}

	wdt[pl]= dimens[fig[pl]][rot[pl]&1];
	hgt[pl]= dimens[fig[pl]][(rot[pl]&1)^1];

	if (!new)
	{	col[pl]+= modific[fig[pl]][rot[pl]][0];
		if (col[pl] < 0) col[pl]= 0;
		if ((i= col[pl]+wdt[pl]-COLS_) > 0) col[pl]-= i;
		row[pl]+= modific[fig[pl]][rot[pl]][1];
		if (row[pl] < 0) row[pl]= 0;
		if ((i= row[pl]+hgt[pl]-ROWS_) > 0) row[pl]-= i;
	}

	for (i= 0; i <= 3; i++)
		figure[pl][i]= figures[fig[pl]][rot[pl]][i]<<(8-col[pl]);

	if (new)
	{	SetClrFigure_(fc_SET_);
		if (!NoCollision_(0, 0))
		{	status[pl]= WAITING_;
			PC_ProcessGadget_(pl|GID_ABORT_);
			if (!players || (status[pl^1] == WAITING_)) LS_InputEntry_();
		}
	}
}

/*==== let figure fall down, if possible (TRUE), else kill full lines ====*/
#define fc_VIS_		TRUE
#define fc_UNVIS_	FALSE

BOOL DownFigure_(const BOOL visible)
{	extern struct RastPort *rport; /* from "playerctrl.c" */
	extern UWORD wbleft, wbtop, winoffs[2]; /* from "playerctrl.c" */
	extern BYTE players, pl; /* from "playerctrl.c" */
	BYTE i, j;
	UWORD x, y;

	if (NoCollision_(0, 1))
	{	SetClrFigure_(fc_CLR_);
		row[pl]++;
		if (visible) SetClrFigure_(fc_SET_);
		return TRUE;
	} else
	{	SetClrFigure_(fc_SET_);
		for (i= 0; i < hgt[pl]; i++) field[pl][row[pl]+i]|= figure[pl][i];
		i= ROWS_;
		while (i-- > 0)
			while (field[pl][i] == 0xffc0)
			{	LS_IncLines_(IL_INC_);
				x= wbleft+winoffs[pl]+PGLEFT_;
				y= wbtop+PGTOP_;
				ScrollRaster(rport, 0, -PIXY_,
					x, y, x+PGWIDTH_-1, y+PIXY_-1+i*PIXY_);
				for (j= i-1; j >= 0; j--) field[pl][j+1]= field[pl][j];
				field[pl][0]= 0;
			}
		return FALSE;
	}
}

/*==== clear the field for a new game ====*/
void ClearField_(void)
{	extern struct RastPort *rport; /* from "playerctrl.c" */
	extern UWORD wbleft, wbtop, winoffs[2]; /* from "playerctrl.c" */
	extern BYTE players, pl; /* from "playerctrl.c" */
	ULONG j= wbleft+winoffs[pl]+PGLEFT_, k= wbtop+PGTOP_;
	UBYTE i;

	SetAPen(rport, 0);
	RectFill(rport, j, k, j+PGWIDTH_-1, k+PGHEIGHT_-1);
	for (i= 0; i < ROWS_; i++) field[pl][i]= 0;
	isvisible[pl]= FALSE;
}

/*==== do initializations to start game ====*/
void FC_StartGame_(void)
{	extern BYTE players, pl; /* from "playerctrl.c" */
	ULONG secs, micros;

	ClearField_();
	if (!pl)
	{	CurrentTime(&secs, &micros);
		srand((int)micros);
	}
	GetFigure_(fc_NEW_);
}

/*==== manipulate figure controlled by keystroke ====*
 *==== (TRUE if pause/continuation requested)    ====*/
void FC_ProcessKey_(UBYTE key)
{	extern UBYTE status[2]; /* from "playerctrl.c" */
	extern BYTE players, pl; /* from "playerctrl.c" */
	BYTE tempcol, temprow, tempwdt, temphgt;
	WORDBITS tempfig[4];
	BYTE chr;

	if (key == pausekey[0])
	{	if (players) FC_ProcessKey_(player2keys[5]);
		key= player1keys[5];
	}

	{	TEXT *index;

		if (index= memchr(player1keys, key, NUMPLAYERKEYS))
		{	chr= index-player1keys;
			pl= 0;
		} else if (index= memchr(player2keys, key, NUMPLAYERKEYS))
		{	chr= index-player2keys;
			pl= players;
		} else
			return;
	}

	switch (chr)
	{	case 1: /* figure left */
			if ((status[pl] == RUNNING_) && col[pl] && NoCollision_(-1, 0))
			{	SetClrFigure_(fc_CLR_);
				col[pl]--;
				figure[pl][0]<<= 1; figure[pl][1]<<= 1;
				figure[pl][2]<<= 1; figure[pl][3]<<= 1;
				SetClrFigure_(fc_SET_);
			}
			break;
		case 2: /* rotate figure left */
			if (status[pl] == RUNNING_)
			{	SetClrFigure_(fc_CLR_);
				rot[pl]= (rot[pl]+1)&3;
				tempcol= col[pl]; temprow= row[pl];
				tempwdt= wdt[pl]; temphgt= hgt[pl];
				CopyMem(figure[pl], tempfig, sizeof(figure[pl]));
				GetFigure_(fc_OLD_);
				if (!NoCollision_(0, 0))
				{	rot[pl]= (rot[pl]+3)&3;
					col[pl]= tempcol; row[pl]= temprow;
					wdt[pl]= tempwdt; hgt[pl]= temphgt;
					CopyMem(tempfig, figure[pl], sizeof(figure[pl]));
				}
				SetClrFigure_(fc_SET_);
			}
			break;
		case 3: /* figure right */
			if ((status[pl] == RUNNING_)
				&& (col[pl]+wdt[pl] != COLS_) && NoCollision_(1, 0))
				{	SetClrFigure_(fc_CLR_);
					col[pl]++;
					figure[pl][0]>>= 1; figure[pl][1]>>= 1;
					figure[pl][2]>>= 1; figure[pl][3]>>= 1;
					SetClrFigure_(fc_SET_);
				}
			break;
		case 0: /* start game/drop figure */
			if (status[pl] == RUNNING_)
			{	LS_IncScore_(row[pl]);
				TC_CtrlTimer_(CT_STOP_);
				while (DownFigure_(fc_UNVIS_));
				GetFigure_(fc_NEW_);
				TC_CtrlTimer_(CT_START_);
			} else if ((status[pl] == WAITING_) && (status[pl^1] == WAITING_))
				PC_ProcessGadget_(pl|GID_START_);
			break;
		case 4: /* increase level */
			if (status[pl] == RUNNING_) LS_IncLevel_(IL_INC_);
			break;
		case 5: /* pause/continue */
			if (status[pl] != WAITING_)
			{	TC_CtrlTimer_(status[pl]-RUNNING_);
				status[pl]= RUNNING_+PAUSING_-status[pl];
			}
	}
}

/*==== operate on timer signals ====*/
void FC_ProcessTimer_(UBYTE num)
{	extern UBYTE status[2]; /* from "playerctrl.c" */
	extern BYTE players, pl; /* from "playerctrl.c" */

	pl= num;
	TC_CtrlTimer_(CT_STOP_);
	if (status[pl] == RUNNING_)
	{	TC_CtrlTimer_(CT_START_);
		if (!DownFigure_(fc_VIS_))
		{	LS_IncScore_(row[pl]);
			GetFigure_(fc_NEW_);
		}
	}
}

/*==== print title picture ====*/
void FC_ShowTitle_(const BOOL help)
{	extern struct TextAttr textattr; /* from "playerctrl.c" */
	extern struct RastPort *rport; /* from "playerctrl.c" */
	extern UWORD wbleft, wbtop, winoffs[2]; /* from "playerctrl.c" */
	extern BYTE players, pl; /* from "playerctrl.c" */

	static struct TextAttr ta_bold=
	{	"topaz.font", TOPAZ_EIGHTY, FSF_BOLD, FPF_ROMFONT
	};

	static UWORD imagedata[]=
	{	0xFFFF,0xFFCF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFF81,0xFF81,
		0xFFFF,0xF800,0xFFFF,0xFFCF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
		0xFFE1,0xFF87,0xFFFF,0xF800,0xFFFF,0xFFCF,0xFFFF,0xFFFF,
		0xFFFF,0xFFFF,0xFFF1,0xFF8F,0xFFFF,0xF800,0xFFFF,0xFFCF,
		0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFF9,0xFF8F,0xFFFF,0xF800,
		0xFFFF,0xFFCF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFF9,0xFF9F,
		0xFFFF,0xF800,0x00FF,0xC00F,0xFC00,0x0000,0xFFC0,0x0FFC,
		0x3FF8,0x001F,0xFC00,0x0000,0x00FF,0xC00F,0xFC00,0x0000,
		0xFFC0,0x0FFC,0x1FF9,0xFF9F,0xF800,0x0000,0x00FF,0xC00F,
		0xFC00,0x0000,0xFFC0,0x0FFC,0x3FF9,0xFF9F,0xFC00,0x0000,
		0x00FF,0xC00F,0xFFFF,0x8000,0xFFC0,0x0FFF,0xFFF9,0xFF9F,
		0xFFFF,0x8000,0x00FF,0xC00F,0xFFFF,0x8000,0xFFC0,0x0FFF,
		0xFFF9,0xFF8F,0xFFFF,0xE000,0x00FF,0xC00F,0xFFFF,0x8000,
		0xFFC0,0x0FFF,0xFFF1,0xFF8F,0xFFFF,0xF000,0x00FF,0xC00F,
		0xFFFF,0x8000,0xFFC0,0x0FFF,0xFFE1,0xFF87,0xFFFF,0xF000,
		0x00FF,0xC00F,0xFFFF,0x8000,0xFFC0,0x0FFF,0xFF81,0xFF81,
		0xFFFF,0xF800,0x00FF,0xC00F,0xFC00,0x0000,0xFFC0,0x0FFD,
		0xFF81,0xFF80,0x003F,0xF800,0x00FF,0xC00F,0xFC00,0x0000,
		0xFFC0,0x0FFD,0xFFC1,0xFF80,0x001F,0xF800,0x00FF,0xC00F,
		0xFC00,0x0000,0xFFC0,0x0FFC,0xFFC1,0xFF80,0x003F,0xF800,
		0x00FF,0xC00F,0xFFFF,0xFC00,0xFFC0,0x0FFC,0xFFE1,0xFF9F,
		0xFFFF,0xF800,0x00FF,0xC00F,0xFFFF,0xFC00,0xFFC0,0x0FFC,
		0x7FF1,0xFF9F,0xFFFF,0xF000,0x00FF,0xC00F,0xFFFF,0xFC00,
		0xFFC0,0x0FFC,0x3FF1,0xFF9F,0xFFFF,0xF000,0x00FF,0xC00F,
		0xFFFF,0xFC00,0xFFC0,0x0FFC,0x3FF9,0xFF9F,0xFFFF,0xE000,
		0x00FF,0xC00F,0xFFFF,0xFC00,0xFFC0,0x0FFC,0x1FF9,0xFF9F,
		0xFFFF,0x8000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
		0x0000,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
		0x0000,0x0000,0x0000,0x1800,0x0000,0x0000,0xFFFF,0xFFC0,
		0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFE00,0x1800,0x7FFF,0xF800,
		0x000C,0x0000,0xC000,0x0000,0x0C00,0x00C0,0x0700,0x1800,
		0xE000,0x0000,0x000C,0x0000,0xC000,0x0000,0x0C00,0x00C0,
		0x0380,0x1801,0xC000,0x0000,0x000C,0x0000,0xC000,0x0000,
		0x0C00,0x00C0,0x0180,0x0001,0x8000,0x0000,0x000C,0x0000,
		0xC000,0x0000,0x0C00,0x00C0,0x0180,0x1801,0x8000,0x0000,
		0x000C,0x0000,0xC000,0x0000,0x0C00,0x00C0,0x0180,0x1801,
		0x8000,0x0000,0x000C,0x0000,0xC000,0x0000,0x0C00,0x00C0,
		0x0380,0x1801,0xC000,0x0000,0x000C,0x0000,0xC000,0x0000,
		0x0C00,0x00C0,0x0700,0x1800,0xE000,0x0000,0x000C,0x0000,
		0xFFFF,0x8000,0x0C00,0x00FF,0xFE00,0x1800,0x7FFE,0x0000,
		0x000C,0x0000,0xC000,0x0000,0x0C00,0x00C0,0x3000,0x1800,
		0x0007,0x0000,0x000C,0x0000,0xC000,0x0000,0x0C00,0x00C0,
		0x1000,0x1800,0x0003,0x8000,0x000C,0x0000,0xC000,0x0000,
		0x0C00,0x00C0,0x1800,0x1800,0x0001,0x8000,0x000C,0x0000,
		0xC000,0x0000,0x0C00,0x00C0,0x0800,0x1800,0x0001,0x8000,
		0x000C,0x0000,0xC000,0x0000,0x0C00,0x00C0,0x0C00,0x1800,
		0x0001,0x8000,0x000C,0x0000,0xC000,0x0000,0x0C00,0x00C0,
		0x0400,0x1800,0x0003,0x8000,0x000C,0x0000,0xC000,0x0000,
		0x0C00,0x00C0,0x0200,0x1800,0x0007,0x0000,0x000C,0x0000,
		0xFFFF,0xFC00,0x0C00,0x00C0,0x0300,0x181F,0xFFFE,0x0000,
		0x000C,0x0000,0x0000,0x0000,0x0C00,0x00C0,0x0100,0x1800,
		0x0000,0x0000,0x000C,0x0000,0x0000,0x0000,0x0C00,0x00C0,
		0x0180,0x1800,0x0000,0x0000
	};

	#define CENTER(x) (PGLEFT_+(PGWIDTH_>>1)-(4*x))

	static struct Image titleimage=
	{	CENTER(149/8),30, 149,21, 2, NULL, 0x0003,0x0000, NULL
	};

	static struct IntuiText titletext[]=
	{	1,0, JAM1, CENTER( 8), 20, &ta_bold, "Quarky's", &titletext[1],
		3,0, JAM1, CENTER(15), 60, &textattr, "created in 1992", &titletext[2],
		3,0, JAM1, CENTER(15), 70, &textattr, "by Dieter Temme", &titletext[3],
		3,0, JAM1, CENTER( 4), 80, &textattr, "V" VERSION, &titletext[4],
		3,0, JAM1, CENTER(18), 90, &textattr, "Dedicated to Conny", &titletext[5],
		1,0, JAM1, CENTER(19),105, &ta_bold, "Save the ONE world!", &titletext[6],
		2,0, JAM1, CENTER(14),120, &textattr, "Please support", &titletext[7],
		2,0, JAM1, CENTER(18),130, &textattr, "Greenpeace, UNICEF", &titletext[8],
		2,0, JAM1, CENTER(18),140, &textattr, "and The Red Cross!", NULL
	};

	static UBYTE offsets[NUMPLAYERKEYS+1]=
	{	1, 4, 7, 9, 11, 13, 15
	};
	static struct IntuiText helptext[]=
	{	1,0, JAM1, CENTER(10),  6, &ta_bold, "Used keys:", &helptext[1],
		1,0, JAM1, CENTER(21), 16, &textattr, NULL, &helptext[2],
		1,0, JAM1, CENTER(21), 24, &textattr, "  pause/cont for both", &helptext[3],
		2,0, JAM1, CENTER( 8), 46, &ta_bold, "Player 1", &helptext[4],
		3,0, JAM1, CENTER(21), 57, &textattr, NULL, &helptext[5],
		3,0, JAM1, CENTER(21), 65, &textattr, "  start game for both", &helptext[6],
		3,0, JAM1, CENTER(21), 73, &textattr, "  or drop figure", &helptext[7],
		3,0, JAM1, CENTER(21), 84, &textattr, NULL, &helptext[8],
		3,0, JAM1, CENTER(21), 92, &textattr, "  figure left", &helptext[9],
		3,0, JAM1, CENTER(21),103, &textattr, NULL, &helptext[10],
		3,0, JAM1, CENTER(21),111, &textattr, "  rotate figure", &helptext[11],
		3,0, JAM1, CENTER(21),122, &textattr, NULL, &helptext[12],
		3,0, JAM1, CENTER(21),130, &textattr, "  figure right", &helptext[13],
		3,0, JAM1, CENTER(21),141, &textattr, NULL, &helptext[14],
		3,0, JAM1, CENTER(21),149, &textattr, "  increase level", &helptext[15],
		3,0, JAM1, CENTER(21),160, &textattr, NULL, &helptext[16],
		3,0, JAM1, CENTER(21),168, &textattr, "  pause/continue", NULL
	};

	titleimage.ImageData= AllocMemQ_(sizeof(imagedata), MEMF_CHIP);
	CopyMem(imagedata, titleimage.ImageData, sizeof(imagedata));

	if (!help)
	{	for (pl= 0; pl <= players; pl++)
		{	ClearField_();
			DrawImage(rport, &titleimage, wbleft+winoffs[pl], wbtop+PGTOP_);
			PrintIText(rport, &titletext, wbleft+winoffs[pl], wbtop+PGTOP_);
		}
	} else
	{	TEXT texts[NUMPLAYERKEYS+1][2*MAXKEYLEN+19], *s1, *s2;
		UBYTE i;

		for (i= 0; i < NUMPLAYERKEYS+1; i++)
			helptext[offsets[i]].IText= texts[i];

		for (pl= 0; pl <= players; pl++)
		{	ClearField_();
			helptext[3].IText[7]= '1'+pl;
			for (i= 0; i < NUMPLAYERKEYS+1; i++)
			{	sprintf(texts[i], "«%s»:", LS_UncodeRawKey_(!i? pausekey[0]
					: (!pl? player1keys : player2keys)[i-1]));
				texts[i][21]= '\0';
			}
			PrintIText(rport, &helptext, wbleft+winoffs[pl], wbtop+PGTOP_);
		}
	}

	FreeMem(titleimage.ImageData, sizeof(imagedata));
}
