/** VGB: portable GameBoy emulator ***************************/
/**                                                         **/
/**                           Amiga.c                       **/
/**                                                         **/
/** Amiga-specific graphics and joystick routines           **/
/** drivers.                                                **/
/**                                                         **/
/** Copyright (C) Michael Boese & Matthias Bethke 1995      **/
/** based on the X11 version by Marat Fayzullin and         **/
/** Elan Feingold                                           **/
/**     You are not allowed to distribute this software     **/
/**     commercially. Please, notify me, if you make any    **/
/**     changes to this file.                               **/
/*************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include "GB.h"
#include "rawkeys.h"


/** Various variables and short functions ********************/
#define WIDTH  160
#define HEIGHT 144

char *Title = "VGB Amiga V0.3";

int  ExitFlag = 0;
int  SaveCPU  = 1;

byte *XBuf,*LinePtr;

struct Screen *scr;
struct Window *win;
struct RastPort *rp;
UBYTE Palette[4]={1,2,3,4};

char ReqText[]= "Virtual Gameboy V0.2\n\
Amiga version by\n\
Michael Boese & Matthias Bethke\n\n\
In-game keys:\n\
'x'   -   Button 'A'\n\
'y'   -   Button 'B'\n\
'.'   -   'Select'\n\
'-'   -   'Start'\n\
All 4 buttons simultaneously: RESET\n\n\
Cursorkeys: Joypad";

struct EasyStruct HelpReq =
{
	sizeof(struct EasyStruct),
	0,
	"VGB Amiga Help",
	ReqText,
	"Like it!"
};


int InitMachine()
{
	if(scr = LockPubScreen(NULL))
	{
		if(win = OpenWindowTags(NULL,
					WA_Left,(scr->Width - WIDTH)/2,
					WA_Top,(scr->Height - HEIGHT)/2,
					WA_InnerWidth,WIDTH,
					WA_InnerHeight,HEIGHT,
					WA_Title,Title,
					WA_GimmeZeroZero,TRUE,
					WA_CloseGadget,TRUE,
					WA_DragBar,TRUE,
					WA_SizeGadget,FALSE,
					WA_RMBTrap,TRUE,
					WA_Activate,TRUE,
					WA_IDCMP,IDCMP_RAWKEY|IDCMP_CLOSEWINDOW,
					TAG_END
			))
		{
			UnlockPubScreen(NULL,scr);
			rp = win->RPort;
			AllocatePens();
			if(XBuf=AllocVec(sizeof(byte)*HEIGHT*WIDTH,MEMF_ANY)) return(1);
		} else
		{
			fprintf(stderr,"Can't open window :(((\n");
		}
	} else
	{
		fprintf(stderr,"No default PubScreen!\n");
	}
}

/** TrashMachine *********************************************/  
/** Deallocate all resources taken by InitMachine().        **/
/*************************************************************/
void TrashMachine(void)
{
int i;
	FreeVec(XBuf);
	CloseWindow(win);
	for(i=0; i<4; i++) ReleasePen(scr->ViewPort.ColorMap,Palette[i]);
}


/** PutImage *************************************************/
/** Put an image on the screen.                             **/
/*************************************************************/
void PutImage(void)
{
	WriteChunkyPixels(rp,0,0,WIDTH,HEIGHT,XBuf,160);
}


/** Joystick *************************************************/
/** Return the current joystick state.                      **/
/*************************************************************/
byte Joystick(void)
{
struct IntuiMessage *imsg;
ULONG imsg_Class;
UWORD Code;
int J;
static byte JoyState=0xff;

		if(imsg = (struct IntuiMessage*)GetMsg(win->UserPort))
		{
			imsg_Class = imsg->Class;
			Code  = imsg->Code;
			ReplyMsg((struct Message*)imsg);
			switch(imsg_Class)
			{
				case IDCMP_CLOSEWINDOW	:	ExitFlag = 1;
													break;
				case IDCMP_RAWKEY			:
					if(Code & 0x80)
					{
						switch(Code & 0x7f)
						{
#ifdef DEBUG
							case KEY_F1:	Trace=!Trace;
												break;
							case KEY_F2:	puts("\n*** REGISTERS: ***");		//F2 up
												for(J=0xFF40;J<0xFF50;J++)
													printf("(%Xh) = $%X\n",J,*(RAM+J));
												printf("\n");
												break;
#endif
							case KEY_HELP:		EasyRequestArgs(NULL,&HelpReq,NULL,NULL);
							case KEY_DASH:		JoyState|=0x80;break;	//start
							case KEY_PERIOD:	JoyState|=0x40;break;	//select
							case KEY_Y:			JoyState|=0x20;break;	//B
							case KEY_X:			JoyState|=0x10;break;	//A
							case KEY_CDOWN:	JoyState|=0x08;break;	//down
							case KEY_CUP:		JoyState|=0x04;break;	//up
							case KEY_CLEFT:	JoyState|=0x02;break;	//left
							case KEY_CRIGHT:	JoyState|=0x01;break;	//right
						}
					} else
					{
						switch(Code)
						{
							case KEY_ESC:		ExitFlag = 1; break;
							case KEY_DASH:		JoyState&=0x7F;break;
							case KEY_PERIOD:	JoyState&=0xBF;break;
							case KEY_Y:			JoyState&=0xDF;break;
							case KEY_X:			JoyState&=0xEF;break;
							case KEY_CDOWN:	JoyState&=0xF7;break;
							case KEY_CUP:		JoyState&=0xFB;break;
							case KEY_CLEFT:	JoyState&=0xFD;break;
							case KEY_CRIGHT:	JoyState&=0xFE;break;
						}
					}
			}
		}

  if(ExitFlag)
  { TrashGB();TrashMachine();exit(0); }

  return(JoyState);
}

void AllocatePens(void)
{
int i;
struct
{
	LONG r,g,b;
} GB_Colors[4] = {{0xffffffff,0xffffffff,0xffffffff},{0x98ffffff,0x98ffffff,0x98ffffff},
						{0x58ffffff,0x58ffffff,0x58ffffff},{0x00ffffff,0x00ffffff,0x00ffffff}};

	for(i=0; i<4; i++)
	{
		Palette[i] = (UBYTE)(ObtainBestPenA(scr->ViewPort.ColorMap,GB_Colors[i].r,GB_Colors[i].g,GB_Colors[i].b,NULL));
	}
}

/** Common.h *************************************************/
/** Parts of the drivers common for Unix/X and MSDOS.       **/
/*************************************************************/
#include "Common.h"
