/*
 * ==========================
 * Atari800 - Amiga Port Code
 * ==========================
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : NOT KNOWN (Before 2nd September 1995)
 * Last updated : 3rd September 1995
 *
 *
 *
 * Introduction:
 *
 * This file contains all the additional code required to get the Amiga
 * port of the Atari800 emulator up and running.
 *
 *
 *
 * Notes:
 *
 * o Now supports AGA graphics via -aga startup option. This option provides
 *   support for the Atari's full 256 colour palette.
 *     The emulator will default to this mode.
 *
 * o Should support ECS graphics via -ecs startup option. Unfortunately, I
 *   have not been able to test this on a real ECS based Amiga so I would
 *   appreciate it if someone would let me know whether it works or not.
 *     The only difference between this mode and the AGA mode is that
 *   the screen display is rendered with 32 pens as opposed to using the
 *   Atari's full 256 colour palette.
 *
 * o Should support OCS graphics via -ocs startup option. Unfortunately, I
 *   have not been able to test this on a real OCS based Amiga so I would
 *   appreciate it if someone would let me know whether it works or not. Of
 *   the three modes, this is the least likely to work. There is no real
 *   difference between this and the ECS mode, so I'm just hoping it does.
 *   However, certain operating system calls may not work, but without
 *   further details, I have no idea which these may be.
 *     Anyway, in this mode, the screen display should be rendered with 32
 *   pens just like the ECS mode.
 *
 * o The emulator has been tested on an Amiga A1200 using the OCS, ECS and
 *   AGA chipset options on powerup. However, due to the fact that the A1200
 *   uses Workbench 3.0, I have no idea whether it will work on real OCS and
 *   ECS based Amiga's. Sorry! I would appreciate it if someone would let me
 *   know whether it does work on these machines. Thanks!
 *
 * o Hooks have been provided for sound support as required by v0.1.9.
 *   However, sound is not currently supported (And probably won't be for a
 *   while yet!). If anyone is interested in developing this area please
 *   feel free.
 *
 * o Upon compilation you will reveive one warning regarding the definition
 *   of CLOSE. A standard Amiga define is conflicting with one defined
 *   within the "atari.h" file. This is unlikely to be corrected. Apart from
 *   this one warning, there should now be no other warnings of any kind.
 *
 * o Thanks to a little experimentation you can now see the menus more
 *   clearly and the windows (all two of them!) have been given a much
 *   needed facelift.
 *
 * o -grey startup option added. In this mode you will get a grey scale
 *   screen display.
 *
 * o -colour startup option added. In AGA modes you will get the full 256
 *   colour palette of the Atari. In OCS and ECS modes you will get the
 *   best representation the program can get using 32 pens.
 *     The emulator will default to this mode.
 */



#include <intuition/intuition.h>
#include <exec/memory.h>
#include <exec/types.h>
#include <devices/gameport.h>
#include <devices/inputevent.h>
#include <libraries/asl.h>
#include <stdio.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <string.h>
#include "system.h"

#include "atari.h"

#include "colours.h"

#define GAMEPORT0 0
#define GAMEPORT1 1

#define OCS_ChipSet 0
#define ECS_ChipSet 1
#define AGA_ChipSet 2

#ifdef DICE_C
static struct IntuitionBase	*IntuitionBase = NULL;
static struct GfxBase		*GfxBase = NULL;
static struct LayersBase	*LayersBase = NULL;
#endif

#ifdef GNU_C
struct IntuitionBase	*IntuitionBase = NULL;
struct GfxBase		*GfxBase = NULL;
struct LayersBase	*LayersBase = NULL;
#endif

static struct Window *WindowMain = NULL;
static struct Window *WindowAbout = NULL;
static struct Window *WindowNotSupported = NULL;
int old_stick_0;
int old_stick_1;

static int consol;
static int trig0;
static int stick0;

struct InputEvent gameport_data;
struct MsgPort *gameport_msg_port;
struct IOStdReq *gameport_io_msg;
BOOL gameport_error;

static UBYTE	*image_data;

static UWORD ScreenType;
static struct Screen *ScreenMain = NULL;
static struct NewScreen NewScreen;
static struct Image image_Screen;
static int ScreenID;
static int ScreenWidth;
static int ScreenHeight;
static int ScreenDepth;
static int TotalColours;

static struct Menu *menu_Project = NULL;
static struct MenuItem *menu_Project00 = NULL;
static struct MenuItem *menu_Project01 = NULL;
static struct MenuItem *menu_Project02 = NULL;

static struct Menu *menu_Console = NULL;
static struct MenuItem *menu_Console00 = NULL;
static struct MenuItem *menu_Console01 = NULL;
static struct MenuItem *menu_Console02 = NULL;
static struct MenuItem *menu_Console03 = NULL;
static struct MenuItem *menu_Console04 = NULL;
static struct MenuItem *menu_Console05 = NULL;

static struct Menu *menu_Prefs = NULL;
static struct MenuItem *menu_Prefs00 = NULL;
static struct MenuItem *menu_Prefs00s00 = NULL;
static struct MenuItem *menu_Prefs00s01 = NULL;
static struct MenuItem *menu_Prefs01 = NULL;
static struct MenuItem *menu_Prefs01s00 = NULL;
static struct MenuItem *menu_Prefs01s01 = NULL;

struct MemHeader MemHeader;

static UWORD *data_Screen;
static ChipSet;
static ColourEnabled;
static UpdatePalette;

static void Rule ();
static void ShowText ();
static void DisplayAboutWindow ();
static void DisplayNotSupportedWindow ();
static struct MenuItem *MakeMenuItem ();
static struct Menu *MakeMenu ();
static struct Gadget *MakeGadget ();

static int gui_GridWidth = 4;
static int gui_GridHeight = 7;
static int gui_WindowOffsetLeftEdge = 0; /* 4 */
static int gui_WindowOffsetTopEdge = 0; /* 11 */

#define gadget_Button 1
#define gadget_Check 2
#define gadget_String 3



/*
 * ================
 * Atari_Initialize
 * ================
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : NOT KNOWN (Before 2nd September 1995)
 * Last updated : 3rd September 1995
 */

void Atari_Initialise (int *argc, char *argv[])
{
	struct NewWindow	NewWindow;

	char *ptr;
	int i;
	int j;
	struct IntuiMessage *IntuiMessage;

	ULONG Class;
	USHORT Code;
	APTR Address;

	int QuitRoutine;

	/*
	 * ===========
	 * Screen Pens
	 * ===========
	 */

	WORD ScreenPens[13] =
	{
		15, /* Unknown */
		15, /* Unknown */
		0, /* Windows titlebar text when inactive */
		15, /* Windows bright edges */
		0, /* Windows dark edges */
		120, /* Windows titlebar when active */
		0, /* Windows titlebar text when active */
		4, /* Windows titlebar when inactive */
		0, /* Unknown */
		0, /* Menubar text */
		15, /* Menubar */
		0, /* Menubar base */
		-1
	};
/*
		?, ?, ?, ?, 0, 200, 0, ?, ?,
		?, ?, ?, ?, WindowDarkEdge, Titlebar(Active), titlebartext(active), ?, ?
*/

	/*
	 * =======================
 	 * Process startup options
	 * =======================
	 */

	ChipSet = AGA_ChipSet;
	ColourEnabled = TRUE;
	UpdatePalette = TRUE;

	for (i=j=1;i<*argc;i++)
	{
		printf("%d: %s\n", i,argv[i]);
		if (strcmp(argv[i], "-ocs") == 0)
		{
			printf ("Specified OCS based Amiga\n");
			ChipSet = OCS_ChipSet;
		}
		else if (strcmp(argv[i], "-ecs") == 0)
		{
			printf ("Specified ECS based Amiga\n");
			ChipSet = ECS_ChipSet;
		}
		else if (strcmp(argv[i], "-aga") == 0)
		{
			printf ("Specified AGA based Amiga\n");
			ChipSet = AGA_ChipSet;
/*
			aga_enabled = TRUE;
*/
		}
		else if (strcmp(argv[i], "-grey") == 0)
		{
			printf ("Specified grey scale display\n");
			ColourEnabled = FALSE;
		}
		else if (strcmp(argv[i], "-colour") == 0)
		{
			printf ("Specified colour display\n");
			ColourEnabled = TRUE;
		}
		else
		{
			argv[j++] = argv[i];
		}
	}

	*argc = j;

	IntuitionBase = (struct IntuitionBase*) OpenLibrary ("intuition.library", 0);
	if (!IntuitionBase)
	{
		printf ("Failed to open intuition.library\n");
		exit (1);
	}

	GfxBase = (struct GfxBase*) OpenLibrary ("graphics.library", 39);
	if (!GfxBase)
	{
		printf ("Failed to open graphics.library\n");
		exit (1);
	}

	LayersBase = (struct LayersBase*) OpenLibrary ("layers.library", 0);
	if (!LayersBase)
	{
		printf ("Failed to open layers.library\n");
		exit (1);
	}

	data_Screen = (UWORD *) AllocMem (46080 * 2, MEMF_CHIP);
	if (!data_Screen)
	{
		printf ("Oh BUGGER!\n");
	}

	printf ("data_Screen = %x\n", data_Screen);

	/*
	 * ==============
	 * Setup Joystick
	 * ==============
	 */

	gameport_msg_port = (struct MsgPort *) CreatePort (0, 0);
	if (!gameport_msg_port)
	{
		printf ("Failed to create gameport_msg_port\n");
		exit (1);
	}

	gameport_io_msg = (struct IOStdReq *) CreateStdIO (gameport_msg_port);
	if (!gameport_io_msg)
	{
		printf ("Failed to create gameport_io_msg\n");
		exit (1);
	}

	gameport_error = OpenDevice ("gameport.device", GAMEPORT1, gameport_io_msg, 0xFFFF);
	if (gameport_error)
	{
		printf ("Failed to open the gameport.device\n");
		exit (1);
	}

	{
		BYTE type = 0;

		gameport_io_msg->io_Command = GPD_ASKCTYPE;
		gameport_io_msg->io_Length = 1;
		gameport_io_msg->io_Data = (APTR) &type;

		DoIO (gameport_io_msg);

		if (type)
		{
			printf ("gameport already in use\n");
			gameport_error = TRUE;
		}
	}

	{
		BYTE type = GPCT_ABSJOYSTICK;

		gameport_io_msg->io_Command = GPD_SETCTYPE;
		gameport_io_msg->io_Length = 1;
		gameport_io_msg->io_Data = (APTR) &type;

		DoIO (gameport_io_msg);

		if (gameport_io_msg->io_Error)
		{
			printf ("Failed to set controller type\n");
		}

	}

	{
		struct GamePortTrigger gpt;

		gpt.gpt_Keys = GPTF_DOWNKEYS | GPTF_UPKEYS;
		gpt.gpt_Timeout = 0;
		gpt.gpt_XDelta = 1;
		gpt.gpt_YDelta = 1;

		gameport_io_msg->io_Command = GPD_SETTRIGGER;
		gameport_io_msg->io_Length = sizeof (gpt);
		gameport_io_msg->io_Data = (APTR) &gpt;

		DoIO (gameport_io_msg);

		if (gameport_io_msg->io_Error)
		{
			printf ("Failed to set controller trigger\n");
		}
	}

	{
		struct InputEvent *Data;

		gameport_io_msg->io_Command = GPD_READEVENT;
		gameport_io_msg->io_Length = sizeof (struct InputEvent);
		gameport_io_msg->io_Data = (APTR) &gameport_data;
		gameport_io_msg->io_Flags = 0;
	}

	SendIO (gameport_io_msg);

	/*
	 * =============
	 * Create Screen
	 * =============
	 */

	ScreenWidth = 640;
	ScreenHeight = 400;
	ScreenDepth = 7;

	ScreenWidth = ATARI_WIDTH - 64; /* ATARI_WIDTH + 8; */
	ScreenHeight = ATARI_HEIGHT; /* ATARI_HEIGHT + 13; */

	if (ChipSet == AGA_ChipSet)
	{
		ScreenDepth = 8;
	}
	else
	{
		ScreenDepth = 5;
	}

	NewScreen.LeftEdge = 0;
	NewScreen.TopEdge = 0;
	NewScreen.Width = ScreenWidth;
	NewScreen.Height = ScreenHeight;
	NewScreen.Depth = ScreenDepth;
	NewScreen.DetailPen = 1;
	NewScreen.BlockPen = 2; /* 2 */
	NewScreen.ViewModes = NULL;
	NewScreen.Type = CUSTOMSCREEN;
	NewScreen.Font = NULL;
	NewScreen.DefaultTitle = ATARI_TITLE;
	NewScreen.Gadgets = NULL;
	NewScreen.CustomBitMap = NULL;

	ScreenMain = (struct Screen *) OpenScreenTags
	(
		&NewScreen,
		SA_Left, 0,
		SA_Top, 0,
		SA_Width, ScreenWidth,
		SA_Height, ScreenHeight,
		SA_Depth, ScreenDepth,
		SA_DetailPen, 1,
		SA_BlockPen, 2, /* 2 */
		SA_Pens, ScreenPens,
		SA_Title, ATARI_TITLE,
		SA_Type, CUSTOMSCREEN,
/*
		SA_Overscan, OSCAN_STANDARD,
*/
/*
		SA_DisplayID, ScreenID,
*/
		SA_AutoScroll, TRUE,
/*
		SA_Interleaved, TRUE,
*/
		TAG_DONE
	);

	if (ChipSet == AGA_ChipSet)
	{
		TotalColours = 256;
	}
	else
	{
		TotalColours = 16;
	}

	for (i=0;i<TotalColours;i++)
	{
		int rgb = colortable[i];
		int red;
		int green;
		int blue;

		red = (rgb & 0x00ff0000) >> 20;
		green = (rgb & 0x0000ff00) >> 12;
		blue = (rgb & 0x000000ff) >> 4;

		SetRGB4 (&ScreenMain->ViewPort, i, red, green, blue);
	}

	/*
	 * =============
	 * Create Window
	 * =============
	 */

	NewWindow.LeftEdge = 0;
	NewWindow.TopEdge = 0;
	NewWindow.Width = ATARI_WIDTH - 64; /* ATARI_WIDTH + 8; */
	NewWindow.Height = ATARI_HEIGHT; /* ATARI_HEIGHT + 13; */
	NewWindow.DetailPen = 0;
	NewWindow.BlockPen = 148;
	NewWindow.IDCMPFlags = MENUPICK | MENUVERIFY | MOUSEBUTTONS | GADGETUP | RAWKEY | VANILLAKEY;
	NewWindow.Flags = BORDERLESS | GIMMEZEROZERO | /* WINDOWDRAG | WINDOWDEPTH | */ SMART_REFRESH | ACTIVATE;
	NewWindow.FirstGadget = NULL;
	NewWindow.CheckMark = NULL;
	NewWindow.Title = NULL; /* ATARI_TITLE; */
	NewWindow.Screen = ScreenMain;
	NewWindow.Type = CUSTOMSCREEN;
	NewWindow.BitMap = NULL;
	NewWindow.MinWidth = 92;
	NewWindow.MinHeight = 65;
	NewWindow.MaxWidth = 1280;
	NewWindow.MaxHeight = 512;

	WindowMain = (struct Window*) OpenWindowTags
	(
		&NewWindow,
		WA_NewLookMenus, TRUE,
		WA_MenuHelp, TRUE,
		WA_ScreenTitle, ATARI_TITLE,
		TAG_DONE
	);

	if (!WindowMain)
	{
		printf ("Failed to create window\n");
		exit (1);
	}

	DisplayAboutWindow ();

/*
 * Setup Project Menu
 */

	menu_Project00 = MakeMenuItem	(0, 0, 88, 10, "Help", 'H');
	menu_Project01 = MakeMenuItem (0, 15, 88, 10, "About", '?');
	menu_Project02 = MakeMenuItem	(0, 30, 88, 10, "Quit", 'N');

	menu_Project00->NextItem = menu_Project01;
	menu_Project01->NextItem = menu_Project02;

	menu_Project = MakeMenu (0, 0, 64, "Project", menu_Project00);

/*
 * Setup Console Menu
 */

	menu_Console00 = MakeMenuItem	(0, 0, 80, 10, "Option", NULL);
	menu_Console01 = MakeMenuItem	(0, 10, 80, 10, "Select", NULL);
	menu_Console02 = MakeMenuItem	(0, 20, 80, 10, "Start", NULL);
	menu_Console03 = MakeMenuItem	(0, 30, 80, 10, "Help", NULL);
	menu_Console04 = MakeMenuItem	(0, 45, 80, 10, "Reset", NULL);
	menu_Console05 = MakeMenuItem (0, 60, 80, 10, "Cold Start", NULL);

	menu_Console00->NextItem = menu_Console01;
	menu_Console01->NextItem = menu_Console02;
	menu_Console02->NextItem = menu_Console03;
	menu_Console03->NextItem = menu_Console04;
	menu_Console04->NextItem = menu_Console05;

	menu_Console = MakeMenu (64, 0, 64, "Console", menu_Console00);

/*
 * Setup Prefs Menu
 */

	menu_Prefs00 = MakeMenuItem (0, 0, 96, 10, "Controller »", NULL);
		menu_Prefs00s00 = MakeMenuItem (80, 0, 80, 10, "  Joystick", NULL);
		menu_Prefs00s01 = MakeMenuItem (80, 10, 80, 10, "  Paddle", NULL);

		menu_Prefs00s00->NextItem = menu_Prefs00s01;

		menu_Prefs00->SubItem = menu_Prefs00s00;

	menu_Prefs01 = MakeMenuItem (0, 10, 96, 10, "Display   »", NULL);
		menu_Prefs01s00 = MakeMenuItem (80, 0, 96, 10, "  Colour", NULL);
		menu_Prefs01s01 = MakeMenuItem (80, 10, 96, 10, "  Grey Scale", NULL);

		menu_Prefs01s00->NextItem = menu_Prefs01s01;

		menu_Prefs01->SubItem = menu_Prefs01s00;

	menu_Prefs00->NextItem = menu_Prefs01;

	menu_Prefs = MakeMenu (128, 0, 48, "Prefs", menu_Prefs00);

/*
 * Link Menus
 */

	menu_Project->NextMenu = menu_Console;
	menu_Console->NextMenu = menu_Prefs;

	SetMenuStrip (WindowMain, menu_Project);

	image_Screen.LeftEdge = 0;
	image_Screen.TopEdge = 0;
	image_Screen.Width = 384;
	image_Screen.Height = 240;
	image_Screen.Depth = 8;
	image_Screen.ImageData = data_Screen;
	image_Screen.PlanePick = 255;
	image_Screen.PlaneOnOff = NULL;
	image_Screen.NextImage = NULL;

/*
	============================
	Storage for Atari 800 Screen
	============================
*/
	image_data = (UBYTE*) malloc (ATARI_WIDTH * ATARI_HEIGHT);
	if (!image_data)
	{
		printf ("Failed to allocate space for image\n");
		exit (1);
	}

	for (ptr=image_data,i=0;i<ATARI_WIDTH*ATARI_HEIGHT;i++,ptr++) *ptr = 0;
	for (ptr=(char *)data_Screen,i=0;i<ATARI_WIDTH*ATARI_HEIGHT;i++,ptr++) *ptr = 0;

	trig0 = 1;
	stick0 = 15;
	consol = 7;
}



/*
 * ==========
 * Atari_Exit
 * ==========
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : NOT KNOWN (Before 2nd September 1995)
 * Last updated : 2nd September 1995
 */

int Atari_Exit (int run_monitor)
{
	if (run_monitor)
	{
		if (monitor ())
		{
			return TRUE;
		}
	}

	AbortIO (gameport_io_msg);

	while (GetMsg (gameport_msg_port))
	{
	}

	if (!gameport_error)
	{
		{
			BYTE type = GPCT_NOCONTROLLER;

			gameport_io_msg->io_Command = GPD_SETCTYPE;
			gameport_io_msg->io_Length = 1;
			gameport_io_msg->io_Data = (APTR) &type;

			DoIO (gameport_io_msg);

			if (gameport_io_msg->io_Error)
			{
				printf ("Failed to set controller type\n");
			}
		}

		CloseDevice (gameport_io_msg);
	}

	FreeMem (data_Screen, 46080 * 2);

	if (gameport_io_msg)
	{
		DeleteStdIO (gameport_io_msg);
	}

	if (gameport_msg_port)
	{
		DeletePort (gameport_msg_port);
	}

	if (WindowMain)
	{
		CloseWindow (WindowMain);
	}

	if (ScreenMain)
	{
		CloseScreen (ScreenMain);
	}

	if (LayersBase)
	{
		CloseLibrary (LayersBase);
	}

	if (GfxBase)
	{
		CloseLibrary (GfxBase);
	}

	if (IntuitionBase)
	{
		CloseLibrary (IntuitionBase);
	}

	return FALSE;
}



/*
 * ===================
 * Atari_DisplayScreen
 * ===================
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : NOT KNOWN (Before 2nd September 1995)
 * Last updated : 3rd September 1995
 */

void Atari_DisplayScreen (UBYTE *screen)
{
	int ypos;
	int	xpos;
	int	tbit = 15;
	UBYTE *scanline_ptr;

	BYTE pens[256];
	int pen;

	UWORD	*bitplane0;
	UWORD	*bitplane1;
	UWORD	*bitplane2;
	UWORD	*bitplane3;
	UWORD	*bitplane4;
	UWORD	*bitplane5;
	UWORD	*bitplane6;
	UWORD	*bitplane7;

	UWORD	word0, word1, word2, word3;
	UWORD	word4, word5, word6, word7;

	consol = 7;

	if (ChipSet == OCS_ChipSet || ChipSet == ECS_ChipSet)
	{
		for (pen=0;pen<256;pen++)
		{
			pens[pen] = 0;
		}

		pen = 1;
	}

	bitplane0 = &data_Screen[0];
	word0 = *bitplane0;

	bitplane1 = &data_Screen[5760]; 
	word1 = *bitplane1;

	bitplane2 = &data_Screen[11520];
	word2 = *bitplane2;

	bitplane3 = &data_Screen[17280];
	word3 = *bitplane3;

	bitplane4 = &data_Screen[23040];
	word4 = *bitplane4;

	if (ChipSet == AGA_ChipSet)
	{
		bitplane5 = &data_Screen[28800];
		word5 = *bitplane5;

		bitplane6 = &data_Screen[34560];
		word6 = *bitplane6;

		bitplane7 = &data_Screen[40320];
		word7 = *bitplane7;
	}

	scanline_ptr = image_data;

	for (ypos=0;ypos<ATARI_HEIGHT;ypos++)
	{
		for (xpos=0;xpos<ATARI_WIDTH;xpos++)
		{
			UBYTE	colour;

			if (ChipSet == AGA_ChipSet)
			{
				if (ColourEnabled)
				{
					colour = *screen++;
				}
				else
				{
					colour = *screen++ & 0x0f;
				}
			}
			else
			{
				if (ColourEnabled)
				{
					colour = *screen;

					if (pens[colour] == 0)
					{
						if (pen<33)
						{
							int rgb = colortable[colour];
							int red;
							int green;
							int blue;

							pens[colour] = pen;
							pen++;

							if (UpdatePalette)
							{
								red = (rgb & 0x00ff0000) >> 20;
								green = (rgb & 0x0000ff00) >> 12;
								blue = (rgb & 0x000000ff) >> 4;

								SetRGB4 (&ScreenMain->ViewPort, pen-1, red, green, blue);
							}
						}
					}

					colour = pens[*screen++];
				}
				else
				{
					colour = *screen++ & 0x0f;
				}
			}

			if (colour != *scanline_ptr)
			{
				UWORD mask;
				mask = ~(1 << tbit);

				word0 = (word0 & mask) | (((colour) & 1) << tbit);
				word1 = (word1 & mask) | (((colour >> 1) & 1) << tbit);
				word2 = (word2 & mask) | (((colour >> 2) & 1) << tbit);
				word3 = (word3 & mask) | (((colour >> 3) & 1) << tbit);
				word4 = (word4 & mask) | (((colour >> 4) & 1) << tbit);
				if (ChipSet == AGA_ChipSet)
				{
					word5 = (word5 & mask) | (((colour >> 5) & 1) << tbit);
					word6 = (word6 & mask) | (((colour >> 6) & 1) << tbit);
					word7 = (word7 & mask) | (((colour >> 7) & 1) << tbit);
				}

				*scanline_ptr++ = colour;
			}
			else
			{
				scanline_ptr++;
			}

			if (--tbit == -1)
			{
				*bitplane0++ = word0;
				word0 = *bitplane0;

				*bitplane1++ = word1;
				word1 = *bitplane1;

				*bitplane2++ = word2;
				word2 = *bitplane2;

				*bitplane3++ = word3;
				word3 = *bitplane3;

				*bitplane4++ = word4;
				word4 = *bitplane4;

				if (ChipSet == AGA_ChipSet)
				{
					*bitplane5++ = word5;
					word5 = *bitplane5;

					*bitplane6++ = word6;
					word6 = *bitplane6;

					*bitplane7++ = word7;
					word7 = *bitplane7;
				}

				tbit = 15;
			}
		}
	}

	DrawImage (WindowMain->RPort, &image_Screen, -32, 0);
}



/*
 * ==============
 * Atari_Keyboard
 * ==============
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : NOT KNOWN (Before 2nd September 1995)
 * Last updated : 3rd September 1995
 *
 * Notes: Currently contains GUI monitoring code as well. At some time in
 * the future I intend on removing this from this code.
 */

int Atari_Keyboard (void)
{
	int keycode;

	struct IntuiMessage *IntuiMessage;

	ULONG Class;
	USHORT Code;
	APTR Address;

	USHORT MenuItem = NULL;

	int Menu = NULL;
	int Item = NULL;
	int SubItem = NULL;

	keycode = -1;

	while (IntuiMessage = (struct IntuiMessage*) GetMsg (WindowMain->UserPort))
	{
		Class = IntuiMessage->Class;
		Code = IntuiMessage->Code;
		Address = IntuiMessage->IAddress;

		MenuItem = Code;

		Menu = MENUNUM (MenuItem);
		Item = ITEMNUM (MenuItem);
		SubItem = SUBNUM (MenuItem);

		if (Class == MENUVERIFY)
		{
			if (ChipSet == OCS_ChipSet || ChipSet == ECS_ChipSet)
			{
				int i;

				UpdatePalette = FALSE;

				for (i=0;i<16;i++)
				{
					int rgb = colortable[i];
					int red;
					int green;
					int blue;

					red = (rgb & 0x00ff0000) >> 20;
					green = (rgb & 0x0000ff00) >> 12;
					blue = (rgb & 0x000000ff) >> 4;

					SetRGB4 (&ScreenMain->ViewPort, i, red, green, blue);
				}

				SetRGB4 (&ScreenMain->ViewPort, 24, 6, 8, 11);
			}
		}

		ReplyMsg (IntuiMessage);

		switch (Class)
		{
			case VANILLAKEY :
printf ("VANILLAKEY = %x\n", Code);
				keycode = Code;

				switch (keycode)
				{
					case 0x01 :
						keycode = AKEY_CTRL_A;
						break;
					case 0x02 :
						keycode = AKEY_CTRL_B;
						break;
					case 0x03 :
						keycode = AKEY_CTRL_C;
						break;
					case 0x04 :
						keycode = AKEY_CTRL_D;
						break;
					case 0x05 :
						keycode = AKEY_CTRL_E;
						break;
					case 0x06 :
						keycode = AKEY_CTRL_F;
						break;
					case 0x07 :
						keycode = AKEY_CTRL_G;
						break;
/*
					case 0x08 :
						keycode = AKEY_CTRL_H;
						break;
*/
					case 0x09 :
						keycode = AKEY_CTRL_I;
						break;
					case 0x0a :
						keycode = AKEY_CTRL_J;
						break;
					case 0x0b :
						keycode = AKEY_CTRL_K;
						break;
					case 0x0c :
						keycode = AKEY_CTRL_L;
						break;
/*
					case 0x0d :
						keycode = AKEY_CTRL_M;
						break;
*/
					case 0x0e :
						keycode = AKEY_CTRL_N;
						break;
					case 0x0f :
						keycode = AKEY_CTRL_O;
						break;
					case 0x10 :
						keycode = AKEY_CTRL_P;
						break;
					case 0x11 :
						keycode = AKEY_CTRL_Q;
						break;
					case 0x12 :
						keycode = AKEY_CTRL_R;
						break;
					case 0x13 :
						keycode = AKEY_CTRL_S;
						break;
					case 0x14 :
						keycode = AKEY_CTRL_T;
						break;
					case 0x15 :
						keycode = AKEY_CTRL_U;
						break;
					case 0x16 :
						keycode = AKEY_CTRL_V;
						break;
					case 0x17 :
						keycode = AKEY_CTRL_W;
						break;
					case 0x18 :
						keycode = AKEY_CTRL_X;
						break;
					case 0x19 :
						keycode = AKEY_CTRL_Y;
						break;
					case 0x1a :
						keycode = AKEY_CTRL_Z;
						break;
					case 8 :
						keycode = AKEY_BACKSPACE;
						break;
					case 13 :
						keycode = AKEY_RETURN;
						break;
					case 0x1b :
						keycode = AKEY_ESCAPE;
						break;
					case '£' :
						keycode = AKEY_EXIT;
						break;
					default :
						break;
				}
				break;
			case RAWKEY :
printf ("RAWKEY = %x\n", Code);
				switch (Code)
				{
					case 0x50 :
						keycode = AKEY_WARMSTART;
						break;
					case 0x51 :
						consol &= 0x03;
						keycode = AKEY_NONE;
						break;
					case 0x52 :
						consol &= 0x05;
						keycode = AKEY_NONE;
						break;
					case 0x53 :
						consol &= 0x06;
						keycode = AKEY_NONE;
						break;
					case 0x54 :
						keycode = AKEY_COLDSTART;
						break;
					case 0x55 :
						keycode = AKEY_PIL;
						break;
					case 0x56 :
						keycode = AKEY_BREAK;
						break;
					case 0x57 :
						keycode = AKEY_DISKCHANGE;
						break;
					case 0x58 :
						keycode = AKEY_EXIT;
						break;
					case 0x59 :
						keycode = AKEY_NONE;
						break;
/*
					case :
						keycode = STICK_LL;
						break;
					case :
						keycode = STICK_BACK;
						break;
					case :
						keycode = STICK_LR;
						break;
					case :
						keycode = STICK_LEFT;
						break;
					case :
						keycode = STICK_CENTRE;
						break;
					case :
						keycode = STICK_RIGHT;
						break;
					case :
						keycode = STICK_UL;
						break;
					case :
						keycode = STICK_FORWARD;
						break;
					case :
						keycode = STICK_UR;
						break;
*/
					case 0x4f :
						keycode = AKEY_LEFT;
						break;
					case 0x4c :
						keycode = AKEY_UP;
						break;
					case 0x4e :
						keycode = AKEY_RIGHT;
						break;
					case 0x4d :
						keycode = AKEY_DOWN;
						break;
					default :
						break;
				}				
				break;
			case MENUPICK :
				UpdatePalette = TRUE;

				switch (Menu)
				{
					case 0 :
						printf ("Menu Project\n");
						switch (Item)
						{
							case 0 :
/*
								SystemTags
								(
									"Run >Nil: <Nil: MultiView Atari800.guide",
									SYS_Input, NULL,
									SYS_Output, NULL,
									TAG_DONE
								);
*/
								DisplayNotSupportedWindow ();
								break;
							case 1 :
								DisplayAboutWindow ();
								break;
							case 2 :
								keycode = AKEY_EXIT;
								break;
							default :
								break;
						}
						break;
					case 1 :
						printf ("Menu Console\n");
						switch (Item)
						{
							case 0 :
								consol &= 0x03;
								keycode = AKEY_NONE;
								break;
							case 1 :
								consol &= 0x05;
								keycode = AKEY_NONE;
								break;
							case 2 :
								consol &= 0x06;
								keycode = AKEY_NONE;
								break;
							case 3 :
/*
								keycode = AKEY_HELP;
*/
								break;
							case 4 :
								keycode = AKEY_WARMSTART;
								break;
							case 5 :
								keycode = AKEY_COLDSTART;
								break;
							default :
								break;
						}
						break;
					case 2 :
						printf ("Menu Prefs\n");
						switch (Item)
						{
							case 0 :
								DisplayNotSupportedWindow ();
								break;
							case 1 :
								switch (SubItem)
								{
									case 0 :
										ColourEnabled = TRUE;
										break;
									case 1 :
										{
											int i;

											ColourEnabled = FALSE;

											for (i=0;i<16;i++)
											{
												int rgb = colortable[i];
												int red;
												int green;
												int blue;

												red = (rgb & 0x00ff0000) >> 20;
												green = (rgb & 0x0000ff00) >> 12;
												blue = (rgb & 0x000000ff) >> 4;

												SetRGB4 (&ScreenMain->ViewPort, i, red, green, blue);
											}
										}
										break;
									default :
										break;
								}
								break;
							default :
								break;
						}
					default :
						break;
				}
				break;
			default :
				break;
		}
	}

	return keycode;
}



/*
 * ==============
 * Atari_Joystick
 * ==============
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : NOT KNOWN (Before 2nd September 1995)
 * Last updated : 2nd September 1995
 */

int Atari_Joystick ()
{
	WORD x;
	WORD y;
	UWORD code;

	int stick = 0;

	if (GetMsg (gameport_msg_port))
	{
		x = gameport_data.ie_X;
		y = gameport_data.ie_Y;
		code = gameport_data.ie_Code;

		switch (x)
		{
			case -1 :
				switch (y)
				{
					case -1 :
						stick = 10;
						break;
					case 0 :
						stick = 11;
						break;
					case 1 :
						stick = 9;
						break;
					default :
						break;
				}
				break;
			case 0 :
				switch (y)
				{
					case -1 :
						stick = 14;
						break;
					case 0 :
						stick = 15;
						break;
					case 1 :
						stick = 13;
						break;
					default :
						break;
				}
				break;
			case 1 :
				switch (y)
				{
					case -1 :
						stick = 6;
						break;
					case 0 :
						stick = 7;
						break;
					case 1 :
						stick = 5;
						break;
					default :
						break;
				}
				break;
			default :
				break;
		}

		if (code == IECODE_LBUTTON)
		{
			if (stick == 0)
			{
				stick = old_stick_0 & 15;
			}
			else
			{
				stick = stick & 15;
			}
		}

		if (code == IECODE_LBUTTON + IECODE_UP_PREFIX)
		{
			if (stick == 0)
			{
				stick = old_stick_0 | 16;
			}
			else
			{
				stick = stick | 16;
			}
		}

		old_stick_0 = stick;
		SendIO (gameport_io_msg);
	}
	
	if (stick == 0)
	{
		stick = old_stick_0;
	}

	stick0 = stick & 0x0f;
	trig0 = (stick & 0x10) >> 4;

/*
	return stick;
*/
}



/*
 * ==========
 * Atari_PORT
 * ==========
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 2nd September 1995
 * Last updated : 2nd September 1995
 *
 * Notes: Hook required by v0.1.9. All the work is actually done in
 * Atari_Joystick.
 */

int Atari_PORT (int num)
{
	if (num == 0)
	{
		Atari_Joystick ();
		return 0xf0 | stick0;
	}
	else
		return 0xff;
}



/*
 * ==========
 * Atari_TRIG
 * ==========
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 2nd September 1995
 * Last updated : 2nd September 1995
 *
 * Notes: Hook required by v0.1.9. All the work is actually done in
 * Atari_Joystick.
 */

int Atari_TRIG (int num)
{
	if (num == 0)
	{
		Atari_Joystick ();
		return trig0;
	}
	else
		return 1;
}



/*
 * =========
 * Atari_POT
 * =========
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 2nd September 1995
 * Last updated : 2nd September 1995
 *
 * Notes: Currently acts as nothing more than a hook.
 */

int Atari_POT (int num)
{
	return 228;
}



/*
 * ============
 * Atari_CONSOL
 * ============
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 2nd September 1995
 * Last updated : 2nd September 1995
 *
 * Notes: Hook required by v0.1.9. All the work is actually done in
 * Atari_Keyboard.
 */

int Atari_CONSOL (void)
{
	return consol;
}



/*
 * ==========
 * Atari_AUDC
 * ==========
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 2nd September 1995
 * Last updated : 2nd September 1995
 *
 * Notes: Currently acts as nothing more than a hook.
 */

void Atari_AUDC (int channel, int byte)
{
}



/*
 * ==========
 * Atari_AUDF
 * ==========
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 2nd September 1995
 * Last updated : 2nd September 1995
 *
 * Notes: Currently acts as nothing more than a hook.
 */

void Atari_AUDF (int channel, int byte)
{
}



/*
 * ============
 * Atari_AUDCTL
 * ============
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 2nd September 1995
 * Last updated : 2nd September 1995
 *
 * Notes: Currently acts as nothing more than a hook.
 */

void Atari_AUDCTL (int byte)
{
}



/*
 * ==================
 * DisplayAboutWindow
 * ==================
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 2nd September 1995
 * Last updated : 3rd September 1995
 */

void DisplayAboutWindow (void)

{
	ULONG Class;
	USHORT Code;
	APTR Address;

	struct IntuiMessage *IntuiMessage;

	struct NewWindow	NewWindow;

	struct Gadget *Gadget1 = NULL;

	int QuitRoutine;

	NewWindow.LeftEdge = 12;
	NewWindow.TopEdge = 46;
	NewWindow.Width = 296;
	NewWindow.Height = 149;
	NewWindow.DetailPen = 0;
	NewWindow.BlockPen = 15;
	NewWindow.IDCMPFlags = CLOSEWINDOW | GADGETUP;
	NewWindow.Flags = WINDOWCLOSE | GIMMEZEROZERO | WINDOWDRAG | SMART_REFRESH | ACTIVATE;
	NewWindow.FirstGadget = NULL;
	NewWindow.CheckMark = NULL;
	NewWindow.Title = ATARI_TITLE;
	NewWindow.Screen = ScreenMain;
	NewWindow.Type = CUSTOMSCREEN;
	NewWindow.BitMap = NULL;
	NewWindow.MinWidth = 92;
	NewWindow.MinHeight = 65;
	NewWindow.MaxWidth = 1280;
	NewWindow.MaxHeight = 512;

	WindowAbout = (struct Window*) OpenWindowTags
	(
		&NewWindow,
		WA_NewLookMenus, TRUE,
		WA_MenuHelp, TRUE,
		WA_ScreenTitle, ATARI_TITLE,
		TAG_DONE
	);

	SetRast (WindowAbout->RPort, 6);

	Rule (0, 15, 288, WindowAbout);

	{
		char temp[128];
		char *ptr;

		strcpy (temp, ATARI_TITLE);
		ptr = strchr(temp,',');
		if (ptr)
		{
			int title_len;
			int version_len;

			*ptr++ = '\0';
			ptr++;

			title_len = strlen(temp);
			version_len = strlen(ptr);

			ShowText ((36 - title_len), 1, WindowAbout, temp);
			ShowText ((36 - version_len), 4, WindowAbout, ptr);
		}
		else
		{
			ShowText (19, 1, WindowAbout, "Atari800 Emulator");
			ShowText (21, 4, WindowAbout, "Version Unknown");
		}

		ShowText (17, 7, WindowAbout, "Original program by");
		ShowText (25, 9, WindowAbout, "David Firth");
		ShowText (14, 12, WindowAbout, "Ported to the Amiga by");
		ShowText (20, 14, WindowAbout, "Stephen A. Firth");
	}

	Gadget1 = MakeGadget (0, 17, 288, 16, 0, WindowAbout, "Ok", gadget_Button);

	QuitRoutine = FALSE;

	while (QuitRoutine == FALSE)
	{
		while (IntuiMessage = (struct IntuiMessage*) GetMsg (WindowAbout->UserPort))
		{
			Class = IntuiMessage->Class;
			Code = IntuiMessage->Code;
			Address = IntuiMessage->IAddress;

			ReplyMsg (IntuiMessage);

			switch (Class)
			{
				case CLOSEWINDOW :
					QuitRoutine = TRUE;
					break;
				case GADGETUP :
					if (Address == (APTR) Gadget1)
					{
						QuitRoutine = TRUE;
					}
					break;
				default :
					break;
			}
		}
	}

	CloseWindow (WindowAbout);
}



/*
 * =========================
 * DisplayNotSupportedWindow
 * =========================
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 3rd September 1995
 * Last updated : 3rd September 1995
 */

void DisplayNotSupportedWindow (void)

{
	ULONG Class;
	USHORT Code;
	APTR Address;

	struct IntuiMessage *IntuiMessage;

	struct NewWindow	NewWindow;

	struct Gadget *Gadget1 = NULL;

	int QuitRoutine;

	NewWindow.LeftEdge = 12;
	NewWindow.TopEdge = 91;
	NewWindow.Width = 296;
	NewWindow.Height = 58;
	NewWindow.DetailPen = 0;
	NewWindow.BlockPen = 15;
	NewWindow.IDCMPFlags = CLOSEWINDOW | GADGETUP;
	NewWindow.Flags = WINDOWCLOSE | GIMMEZEROZERO | WINDOWDRAG | SMART_REFRESH | ACTIVATE;
	NewWindow.FirstGadget = NULL;
	NewWindow.CheckMark = NULL;
	NewWindow.Title = "Warning!";
	NewWindow.Screen = ScreenMain;
	NewWindow.Type = CUSTOMSCREEN;
	NewWindow.BitMap = NULL;
	NewWindow.MinWidth = 92;
	NewWindow.MinHeight = 65;
	NewWindow.MaxWidth = 1280;
	NewWindow.MaxHeight = 512;

	WindowNotSupported = (struct Window*) OpenWindowTags
	(
		&NewWindow,
		WA_NewLookMenus, TRUE,
		WA_MenuHelp, TRUE,
		WA_ScreenTitle, ATARI_TITLE,
		TAG_DONE
	);

	SetRast (WindowNotSupported->RPort, 6);

	Rule (0, 2, 288, WindowNotSupported);

	ShowText (15, 1, WindowNotSupported, "Feature not supported");

	Gadget1 = MakeGadget (0, 4, 288, 16, 0, WindowNotSupported, "Ok", gadget_Button);

	QuitRoutine = FALSE;

	while (QuitRoutine == FALSE)
	{
		while (IntuiMessage = (struct IntuiMessage*) GetMsg (WindowNotSupported->UserPort))
		{
			Class = IntuiMessage->Class;
			Code = IntuiMessage->Code;
			Address = IntuiMessage->IAddress;

			ReplyMsg (IntuiMessage);

			switch (Class)
			{
				case CLOSEWINDOW :
					QuitRoutine = TRUE;
					break;
				case GADGETUP :
					if (Address == (APTR) Gadget1)
					{
						QuitRoutine = TRUE;
					}
					break;
				default :
					break;
			}
		}
	}

	CloseWindow (WindowNotSupported);
}



/*
 * ============
 * MakeMenuItem
 * ============
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : NOT KNOWN (Before 2nd September 1995)
 * Last updated : 2nd September 1995
 *
 * Notes: A simple routine to help GUI development.
 */

struct MenuItem *MakeMenuItem (int LeftEdge, int TopEdge, int Width, 
int Height, char *Title, int Key)

{
	struct IntuiText	*IntuiText;
	struct MenuItem		*MenuItem;

	IntuiText = (struct IntuiText*)malloc(sizeof(struct IntuiText));
	if (!IntuiText)
	{
	}

	IntuiText->FrontPen = 1;
	IntuiText->BackPen = 2;
	IntuiText->DrawMode = JAM1;
	IntuiText->LeftEdge = NULL;
	IntuiText->TopEdge = 1;
	IntuiText->ITextFont = NULL;
	IntuiText->IText = (UBYTE*)Title;
	IntuiText->NextText = NULL;

	MenuItem = (struct MenuItem*)malloc(sizeof(struct MenuItem));
	if (!MenuItem)
	{
	}

	MenuItem->NextItem = NULL;
	MenuItem->LeftEdge = LeftEdge;
	MenuItem->TopEdge = TopEdge;
	MenuItem->Width = Width;
	MenuItem->Height = Height;

	if (Key==NULL)	
	{
		MenuItem->Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP;
	}
	else
	{
		MenuItem->Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ;
	}

	MenuItem->MutualExclude = NULL;
	MenuItem->ItemFill = (APTR)IntuiText;
	MenuItem->SelectFill = NULL;
	MenuItem->Command = (BYTE)Key;
	MenuItem->SubItem = NULL;
	MenuItem->NextSelect = MENUNULL;

	return MenuItem;
}



/*
 * ========
 * MakeMenu
 * ========
 */

/*
 * Revision     : v0.1.8
 * Introduced   : NOT KNOWN (Before 2nd September 1995)
 * Last updated : NOT KNOWN (Before 2nd September 1995)
 *
 * Notes: A simple routine to help GUI development.
 */

struct Menu *MakeMenu (int LeftEdge, int TopEdge, int Width, char *Title, struct MenuItem *MenuItem)

{
	struct Menu *Menu;

	Menu = (struct Menu*)malloc(sizeof(struct Menu));
	if (!Menu)
	{
	}

	Menu->NextMenu = NULL;
	Menu->LeftEdge = LeftEdge;
	Menu->TopEdge = TopEdge;
	Menu->Width = Width;
	Menu->Height = 0;
	Menu->Flags = MENUENABLED;
	Menu->MenuName = Title;
	Menu->FirstItem = MenuItem;

	return Menu;
}



/*
 * ==========
 * MakeGadget
 * ==========
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 2nd September 1995
 * Last updated : 3rd September 1995
 *
 * Notes: Not complete yet. The Type argument is currently not supported so
 * routine is only capable of producing boring click-me-to-continue type
 * gadgets.
 */

struct Gadget *MakeGadget (int LeftEdge, int TopEdge, int Width, int Height, int Offset, struct Window *Window, char *Title, int Type)

{
	int Result;
	int TextX;

	struct IntuiText *NewTextAddress = NULL;
	struct Gadget *NewGadgetAddress = NULL;

	NewGadgetAddress = (struct Gadget*)malloc(sizeof(struct Gadget));
	if (!NewGadgetAddress)
	{
	}

	NewGadgetAddress->NextGadget = NULL;
/*
	NewGadgetAddress->LeftEdge = LeftEdge;
	NewGadgetAddress->TopEdge = TopEdge;
*/
	NewGadgetAddress->Width = Width;
	NewGadgetAddress->Height = Height;

	NewGadgetAddress->Flags = GADGHCOMP;
	NewGadgetAddress->Activation = RELVERIFY;
	NewGadgetAddress->GadgetType = BOOLGADGET;
	NewGadgetAddress->GadgetRender = NULL;
	NewGadgetAddress->SelectRender = NULL;

	NewGadgetAddress->GadgetText = NULL;
	NewGadgetAddress->MutualExclude = NULL;
	NewGadgetAddress->SpecialInfo = NULL;
	NewGadgetAddress->GadgetID = 0;
	NewGadgetAddress->UserData = NULL;

	LeftEdge = (LeftEdge * gui_GridWidth) + gui_WindowOffsetLeftEdge;
	TopEdge = (TopEdge * gui_GridHeight) + gui_WindowOffsetTopEdge + 1 + ((gui_GridHeight - 7) * 2);

	NewGadgetAddress->LeftEdge = LeftEdge;
	NewGadgetAddress->TopEdge = TopEdge;
	NewGadgetAddress->Width = Width;
	NewGadgetAddress->Height = Height;

	TextX=(Width/2)-(strlen(Title)*4);

	NewTextAddress = (struct IntuiText*)malloc(sizeof(struct IntuiText));
	if (!NewTextAddress)
	{
	}

	NewTextAddress->FrontPen = 1;
	NewTextAddress->BackPen = 3;
	NewTextAddress->DrawMode = JAM1;
	NewTextAddress->LeftEdge = TextX;
	NewTextAddress->TopEdge = 3;
	NewTextAddress->ITextFont = NULL;
	NewTextAddress->IText = (UBYTE*)Title;
	NewTextAddress->NextText = NULL;

	NewGadgetAddress->GadgetText = NewTextAddress;

	if (NewGadgetAddress->Activation & TOGGLESELECT)
	{
		if (Title)
		{
			if (Offset)
			{
				NewTextAddress->LeftEdge = Offset;
			}
		}
	}

	if (Window)
	{
		Result = AddGadget (Window, NewGadgetAddress, -1);
		RefreshGadgets (NewGadgetAddress, Window, NULL);
	}

	return NewGadgetAddress;
}



/*
 * ========
 * ShowText
 * ========
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 2nd September 1995
 * Last updated : 2nd September 1995
 *
 * Notes: A simple routine to help any future GUI development.
 */

void ShowText (int LeftEdge, int TopEdge, struct Window *Window, char *TextString)

{
	SetAPen (Window->RPort, 0);
	SetBPen (Window->RPort, 6);

	LeftEdge = (LeftEdge * gui_GridWidth);
	TopEdge = (TopEdge * gui_GridHeight) + ((gui_GridHeight - 7) * 2);

	if (Window->Flags & GIMMEZEROZERO)
	{
		TopEdge = TopEdge + 9;
	}
	else
	{
		LeftEdge = LeftEdge + gui_WindowOffsetLeftEdge;
		TopEdge = TopEdge + gui_WindowOffsetTopEdge + 9;
	}

	Move (Window->RPort, LeftEdge, TopEdge);
	Text (Window->RPort, TextString, strlen(TextString));
}



/*
 * ====
 * Rule
 * ====
 */

/*
 * Revision     : v0.1.9a
 * Introduced   : 2nd September 1995
 * Last updated : 2nd September 1995
 *
 * Notes: A simple routine to help any future GUI development.
 */

void Rule (int LeftEdge, int TopEdge, int Width, struct Window *Window)

{
	int RightEdge;

	LeftEdge = (LeftEdge * gui_GridWidth) + gui_WindowOffsetLeftEdge;
	TopEdge = (TopEdge * gui_GridHeight) + 13 + gui_WindowOffsetTopEdge; /* + 44 */

	RightEdge = Width + LeftEdge - 1;

	SetAPen (Window->RPort, 0);
	Move (Window->RPort, LeftEdge, TopEdge);
	Draw (Window->RPort, RightEdge, TopEdge);
	SetAPen (Window->RPort, 15);
	Move (Window->RPort, LeftEdge, TopEdge + 1);
	Draw (Window->RPort, RightEdge, TopEdge + 1);
}
