/***************************************************************************
 *
 *				CONFIG.c
 *
 ***************************************************************************
 *
 *			1999 version - mjk
 *		Convert (from a process) to a shell screen June 1999
 ***************************************************************************/

/*
 * includes
 */

#if DEBUG
	#define GAME_PAK_ONLY	1
#else
	#define GAME_PAK_ONLY	1
#endif

#include "ult_64.h"
#include "generic.h"
#include "gameinc.h"
#include "locale.h"

// following in gameinc.h
//#include "main.h"
//#include "defs.h"
//#include "n64res.h"
//#include "defs.h"
//#include "static_s.h"
//#include "resman.h"
//#include "config.h"
//#include "fontcode.h"
//#include "ctrl.h"

#include "render.h"
#include "shell.h"
#include "shellgfx.h"
#include "shellres.h"
#include "states.h"
#include "mempak.h"
#include "res/config.id"
#include "stats.h"
#include "help.h"

//#include "res\shell.id"


/*
 * defines
 */

#define MAX_IMG_SIZE		32768


#define STATE_INIT			-	1
#define STATE_SELECT			0
#define STATE_FULL				1
#define STATE_FULLNOTE			2
#define STATE_READING_MEMPAK	3
#define STATE_WRITING_MEMPAK	4
#define STATE_DELETE			5
#define STATE_RUMBLE			6
#define STATE_DELETEYESNO		7
#define STATE_ERROR				8
#define STATE_ERRORREPAIR		9
#define STATE_ERROROURREPAIR	10
#define STATE_CLEAR_EEP_YESNO	11
#define STATE_CLEAR_EEP_DONE	12
#define STATE_WRITEBUGGERED		13
#define STATE_DONE				14


/*
 * typedefs
 */
#define THREADS		0	// conditional compile


/*
 * structures
 */

/*
 * globals
 */


global	int	CheckFirstTimeEverPoweredOn(void);		// from Flash Rom
void ReadGameDataFromGamePak(void);

int				configFrame;

//unsigned char	defaultEepromFile[2048];

int			configTimeout;
//int			configValid=0;		// looked at by Main to see where to go after exit (if 0, back to intro loop)
int			configNewDataLoaded;

extern n64Script	*titleLineScript;
//char			gameTitle[]="NBA COURTSIDE\0\0\0";
char			gameTitle[]="NBA COURTSIDE 2\0";	//16 chars max - Nintendo standard??? 

//char			gameTitle[]="!\"#'*+,-./:=?@\0\0";	//16 chars max - Nintendo standard??? 

int			companyCode	=	0x3031;			// ascii 01
//int		gameCode	=	0x4E4E4245;		// ascii NNBE	- Kobe 1
int			gameCode	=	0x4E434B45;		// ascii NCKE	- Kobe 2

char		headerSig[4]="BRS!";
char		headerBuffer[MEMPAK_HEADER_LENGTH];

int			configRequiredBlocks;

extern Vp			vp;
extern struct openSet		*pcl__ShellRes;
//extern SprTexture_T		*pcl__gBackSpr[2]
extern SprTexture_T		*pcl__gForeSpr;

//extern unsigned short		*ovPal;
//extern unsigned short		*currentData;
//img				*sideLogo;


// following in config.id
//extern unsigned long int ID_TEX_CONTROL,ID_TEX_CART;
//extern unsigned long int ID_TEX_PACK1,ID_TEX_PACK2,ID_TEX_PACK3,ID_TEX_PACK4;
//extern unsigned long int ID_TEX_BALL,ID_TEX_RUMBLE;

//extern int ID_TEX_CONTROL,ID_TEX_CART;
//extern int ID_TEX_PACK1,ID_TEX_PACK2,ID_TEX_PACK3,ID_TEX_PACK4;
//extern int ID_TEX_BALL,ID_TEX_RUMBLE;


enum controllersprites {
	CONFIG_SPR_CART,
	CONFIG_SPR_CONTROLLER,
	CONFIG_SPR_MEMPACK1,
	CONFIG_SPR_MEMPACK2,

	CONFIG_SPR_MEMPACK3,
	CONFIG_SPR_MEMPACK4,
	CONFIG_SPR_BALL,
	CONFIG_SPR_RUMBLE,
	
	NUM_CONT_SPRITES

};
//#define NUM_CONT_SPRITES	8


unsigned long int		*contSpriteIds[NUM_CONT_SPRITES]=
{
	&ID_TEX_CART,&ID_TEX_CONTROL,
	&ID_TEX_PACK1,&ID_TEX_PACK2,&ID_TEX_PACK3,&ID_TEX_PACK4,
	&ID_TEX_BALL,&ID_TEX_RUMBLE
};
texture				*contSprites[NUM_CONT_SPRITES];
unsigned short			*contPal,*contPalLo;

/****************
#define	RGB_TRANS_GRN     DP_RGB( 6), DP_RGB( 25), DP_RGB(6), 0xC0

//UD	configBlueBox[]=  { 0x0000FF40, 0x0000FF40, 0x0000FF40, 0x0000FF40, 0xB28100FF };
//UD	configRedBox[] =  { 0xFF000040, 0xFF000040, 0xFF000040, 0xFF000040, 0xB28100FF };
UB	configGreenBox[]={ RGB_TRANS_GRN,RGB_TRANS_GRN,RGB_TRANS_GRN,RGB_TRANS_GRN,RGB_SOLID_YEL };
UB	configBlueBox[]= { RGB_TRANS_BLU,RGB_TRANS_BLU,RGB_TRANS_BLU,RGB_TRANS_BLU,RGB_SOLID_YEL };
UB	configRedBox[]=  { RGB_TRANS_RED,RGB_TRANS_RED,RGB_TRANS_RED,RGB_TRANS_RED,RGB_SOLID_YEL };
********/

static struct openSet		*configRes;

/*********
static Mtx			configFlipMatrix=
{
	0x00010000,	0x00000000,
	0x00000001,	0x00000000,
	0x00000000,	0xFFFF0000,
	0x00000000,	0x00000001,
	0x00000000,	0x00000000,
	0x00000000,	0x00000000,
	0x00000000,	0x00000000,
	0x00000000,	0x00000000
};
*************/

int		configUseRumble		=0;
int		configUseCtrlPak	=0;	// default to eeprom

//int		curCtrlSel=1;
int		curCtrlSel=0;
int		selAlpha;
int		iconStatus[5];
int		pakBits;
int		pakDirValid;
int		currentState;
int             lastState = STATE_RUMBLE;
int		fileOffset;
int		fileSel;
int		pakGotGame;

int		pakFreeSpace[4];
int		pakNumFiles[4];
int		pakOurFhs[4];

long	currentSerialNo;

int		DidIntro = 0;
int		DidSaveOptions = 0;

#define HILITE_PAL	FPAL_BRIGHT_WHITE	// FPAL_BLACK

char	*promptStrings[]=		// all entries MUST have 3 lines!!!!
{

#if GAME_PAK_ONLY
	"",	//Game Pak Selection",
	"",
	"",
#else
	"Insert/Select a Controller Pak to be used, and",	// only this line is used
	"press the A Button, or select the Game Pak.",
	"",
//	"press A, or select the Game Pak to save only",
//	"minimal statistics.",
#endif

	"The Controller Pak you have selected does",
	"not have enough free space. Would you like",
	"to delete some previously saved game notes?",

	"The Controller Pak you have selected already has",
	"the maximum number of saved notes. Would you",
	"like to delete some previously saved notes?",

	"Reading Controller Pak... do not remove!",
	"",
	"",

	"Initializing Controller Pak... do not remove!",
	"",
	"",

//	"Select a game note to delete, and press A.",
//	"To finish, press B.",
//	"",
	// as per NOA (must be "the A Button" - not just "A")
	"Select a game note to delete, and press the",	
	"A Button. To finish, press the B Button.",
	"",

//	"Would you like to use Rumble Pak Accessories",	bug #1053
//      IQUE flattened this; the game only goes into STATE_RUMBLE for about a frame
//      after you choose the rumble pack, so I zeroed these out. 
	"",
	"",
	"",

	"",
	"",
	"",

// 	STATE_ERROR				8

	"An error occurred while accessing the",
	"Controller Pak. Please ensure that all paks",
	"are correctly connected.",

//#define STATE_ERRORREPAIR		9

//	"The Controller Pak may not be connected",
//	"properly, or the data on it may be corrupted.",
//	"Attempting repair may cause saved data to be lost.",
	"The Controller Pak may not be connected properly,",	// reworked due to bug #683
	"or the data on it may be corrupted. Attempting",
	"repair may cause saved data to be lost.",

//#define STATE_ERROROURREPAIR	10

	"Corrupted data was detected on this Controller",
	"Pak. Please ensure that all paks are correctly",
	"connected.",

//#define STATE_CLEAR_EEP_YESNO	11

//	"Deleting the Game Pak saved data will reset any",
//	"team statistics, custom users, as well as any",
//	"preference settings. Are you sure?",

//	"Deleting the Game Pak will delete all saved data.",	// bug # 620 (insert anal comment here)
	"Erasing the Game Pak will delete all saved data.",	// bug # 620 (insert anal comment here)
	"                    Are you sure?",
	"",

	"The Game Pak data has been deleted.",
	"",
	"",

	"This Controller Pak appears to be damaged.",
	"",
	"",
};


char idcomparevalue[FR_PAGE_SIZE_BYTES] = 
{
	1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,	
	2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,1,	
	3,4,5,6,7,8,9,10,11,12,13,14,15,16,1,2,	
	4,5,6,7,8,9,10,11,12,13,14,15,16,1,2,3,	

	0xff ,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
	0x55,0x55,0x55,0x55,0x55,0x55,0x55,

};





int		lastX,lastY,lastW,lastH;
char	fileTitle[80];
char	fileNames[5][80];
int		fileExts[5][5];
int		fileSizes[5];
int		fileNos[5];
static int	optNo,numOpts;
char		**optStrings=NULL;
char		*yesNoOptStrings[] =		{ "Yes","No" };
char		*okOptStrings[] =			{ "Ok" };
char		*corruptOptStrings[]=		{ "Repair","Retry","Cancel" };
char		*ourCorruptOptStrings[]=	{ "Retry Connection","Clear Data" };
char		*writeBuggeredOptStrings[]=	{ "Retry", "Cancel" };


char *gamepakOptStrings[] = {
	"Save to Game Pak",
	"Continue without Saving",
	"Erase Game Pak",
};



extern char  acz__gGamePakDataLostText[];






/*
 * function prototypes
 */

Gfx *RenderText(Gfx *gp,char *s,int x,int y,int f,int c,int center);
extern Gfx *DrawShellBackground(Gfx *, dyn *);
//Gfx *RenderImg(Gfx *gp,img *im,int x,int y);
Gfx *RenderBmp(Gfx *gp,int x,int y,int sx,int sy,unsigned char *data);
Gfx *RenderTex(Gfx *gp,texture *t,int x,int y);
void UpdateDir(int pk);

/*
 * code
 */


#define DEFAULT_MEMPAK_BUFFER	dfb[32*1024]


/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

void FlipTexture(texture *t)
{
	int i,j,k;
	unsigned char *s,*d;

	s=(unsigned char *)(*(t->bitmapHandle));
	d=&s[t->sx*(t->sy-1)];

	for(i=0;i<t->sy/2;i++)
	{
		for(j=0;j<t->sx;j++)
		{
			k=*s; *s=*d; *d=k;
			s++; d++;
		}
		d-=(t->sx*2);
	}
}




#if DEBUG
#define CONFIG_TIMEOUT_VALUE	300*30*2
#else
#define CONFIG_TIMEOUT_VALUE	30*30*2
#endif

//extern int	ID_SPR_BACKNBA;


/*  game pak screen */
static	UB       aub__sSprScreenConfig [] =
{
	SPR_SRUMBLE,
	SPR_SCART,
	SPR_SCONTRL,
//	SPR_SCONTRLB,	// ghosted
	0
};

int FirstTimeInConfig;


/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/


//void ConfigOpen(void *arg)
int InitScreenConfig(int shellstate)
{
	int		i,j,k;
//	extern int	ID_SPR_BACKNBA;
//	extern int	ID_SPR_BLUBALL;
//	extern int	ID_SHP_TLINES;
	extern unsigned long int	ID_PAL_BKPPAL,ID_IMG_BACKUP;
	extern unsigned long int	ID_PAL_CONTPAL,ID_PAL_CONTLO;
	char		*p;

Options_T saveoptions[4];

//	InitFlashRom();

	configFrame=0;

	configTimeout = CONFIG_TIMEOUT_VALUE;

	configNewDataLoaded	= 0;	//configValid = 0;

	sb___gSaveDisabled = 0;	// BUG # 1054
	FirstTimeInConfig = 1;

	/*
	 * set required blocks...
	 */

	configRequiredBlocks=((si___gMemPakNeed +  MEMPAK_HEADER_LENGTH) + 255) / 256;

	/*
	 * open relevant resource sets...
	 */

	i=ResOpenSet("config",&configRes);
	if(i) exit(234);

//	i=ResOpenSet("shell",&pcl__ShellRes);	already opened
//	if(i) exit(345);

	/*
	 * init other misc stuff
	 */

//	InitChrList();
//	InitAllSprites();

	/*
	 * load some shell stuff
	 */

//	pcl__gBackSpr[0] = pcl__gBackSpr[1]	= pcl__gForeSpr = NULL;

//	LoadShellBackgroundSpr(START_BG_CYCLING);
//	LoadShellBackgroundSpr(ID_SPR_BACK_KB3);	// it's kobe as of 8/30/99
	BG_Load( BG_KOBE3, 0 );
	
//	titleLineScript=(n64Script *)ResOpenID(pcl__ShellRes, ID_SHP_TLINES);

	/*
	 * load some spritey things...
	 */

	contPal=(unsigned short *)ResOpenID(configRes,ID_PAL_CONTPAL);
	contPalLo=(unsigned short *)ResOpenID(configRes,ID_PAL_CONTLO);
	for(i=0;i<NUM_CONT_SPRITES;i++)
	{
		contSprites[i]=(texture *)ResOpenID(configRes,*(contSpriteIds[i]));
		FlipTexture(contSprites[i]);
	}

	/*
	 * load sidebar graphic
	 */

/*******
	sideLogo=(img *)ResOpenID(configRes,ID_IMG_BACKUP);
	ovPal=(unsigned short *)ResOpenID(configRes,ID_PAL_BKPPAL);
	currentData=(unsigned short *)MemMalloc(2*(MAX_IMG_SIZE+64),MEM_ANY);
	CardDecompress(sideLogo);
****/
	memset(iconStatus,0,sizeof(iconStatus));
	pakBits=0;

	pakDirValid=0;
	for(i=0;i<5;i++) fileNames[i][0]=0;
	fileTitle[0]=0;
	currentState=STATE_INIT;
	optStrings=NULL;
	pakGotGame=0;

	numOpts=2;

	/*
	 * get default eeprom file
	 */


	wordcpy(&saveoptions,	&acl__gOptions, sizeof(Options_T)*4);	// save options
	wordcpy(&acl__gOptions,&acl__gDefaultOptions, sizeof(Options_T)*4);

	// MakeMemPakFile() looks at acl__gOptions (which need to be default)	
	p=(char *)&DEFAULT_MEMPAK_BUFFER;	// store in upper part of Z-buffer
	MakeMemPakFile(&p);
	wordcpy(&acl__gOptions,&saveoptions, sizeof(Options_T)*4);	// restore

//	p=(char *)&defaultEepromFile[24];
//	MakeEepromFile(&p);
//	memset(defaultEepromFile,0,24);		// preferences loaded during ShellOpen()

	/*
	 * we're done...
	 */

#if GAME_PAK_ONLY
	gStateTitleText2[shellstate] = NULL;
	gStateTitleText[shellstate] = "GAME PAK";

	ReadGameDataFromGamePak();	// to see if valid
#endif

	LoadSpriteList(aub__sSprScreenConfig);


	return(shellstate);
}



/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

//void ConfigClose(void *arg)
int	ExitScreenConfig (int shellstate)

{

	FreeSpriteList(aub__sSprScreenConfig);

	ResCloseSet(configRes);

/***********
	ResCloseSet(pcl__ShellRes);
	ResCloseSet(configRes);

//	MemFree(pcl__gBackSpr);
//	MemFree(pcl__gForeSpr);
//	pcl__gBackSpr=NULL;
//	pcl__gForeSpr=NULL;

//	FreeShellForeground();
	FreeShellBackground(0);
	FreeShellBackground(1);

	MemFree(currentData);	// sidelogo
	currentData=NULL;

*******/
	if(configNewDataLoaded)
	{
		SeasonRosterToGameRoster();	// need here as before only done in shell open
	}

	return(shellstate);

}



/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *				R  E N D E R     C O N F I G    S C R E E N 
 *
 ***************************************************************************/



#if GAME_PAK_ONLY	/////////////=====================


#define CONFIG_Y0	38
#define CONFIG_Y0a	(CONFIG_Y0+MENU_LINE_H)

#define CONFIG_Y1	71
#define CONFIG_Y1a	(CONFIG_Y1+MENU_LINE_H)
#define CONFIG_Y2	131
#define CONFIG_Y2a	(CONFIG_Y2+MENU_LINE_H)
#define CONFIG_Y3	(143+1)
#define CONFIG_Y3a	(CONFIG_Y3+MENU_LINE_H)

struct rcbox ConfigScreenBoxes[] = 
{	
	{0,   0,			512,			CONFIG_Y0,				RGB_TRANS_BLUE,0,0,0,0},
	HLINE(0,  CONFIG_Y0,  512),

	{0,   CONFIG_Y0a,	512,			CONFIG_Y1-CONFIG_Y0a,	RGB_TRANS_ORANGE,0,0,0,0},
//	{0,   0,			512,			CONFIG_Y1,				RGB_TRANS_ORANGE,0,0,0,0},

	HLINE(0,  CONFIG_Y1,  512),

	{0,   CONFIG_Y1a,	512,		CONFIG_Y2-CONFIG_Y1a,		RGB_TRANS_BLUE,0,0,0,0},
	HLINE(0,  CONFIG_Y2,  512),
//	{0,   CONFIG_Y2a,	512,		CONFIG_Y3-CONFIG_Y2a,		RGB_SOLID_YEL,0,0,0,0},
	{0,   CONFIG_Y2a,	512,		CONFIG_Y3-CONFIG_Y2a,		RGB_TRANS_ORANGE,0,0,0,0},
	HLINE(0,  CONFIG_Y3,  512),
	{0,   CONFIG_Y3a,	512,		MENU_BOTTOM_LINE_Y-CONFIG_Y3a,	RGB_TRANS_BLUE,0,0,0,0},

	HLINE(0,  MENU_BOTTOM_LINE_Y,  512),
	BOTTOM_COLORS

	{-1,0,0,0,0,NO_CORNERS}

};

#define PRIM_MOD	PRIMITIVE,0,TEXEL0,0,PRIMITIVE,0,TEXEL0,0
#define  CONT_Y		(CONFIG_Y3a + 18-3)  //33
#define  GP_Y		(CONFIG_Y1-24) 			//CONFIG_Y3a+12
#define	GP_X		140

//#define	RGB_TRANS_ORANGE	184,80,0, 0x70

Gfx *DrawScreenConfig(int shellstate, Gfx *gp)		// GAME_PAK_ONLY method 9/28/99 (no moe controller paks)
{
int		i,j,k,x;
char	tmpString[80];
int		w;

	gp = DrawRCBoxes(gp,ConfigScreenBoxes);


	if(currentState==STATE_DELETE ||
	   currentState==STATE_DELETEYESNO)
	{
		i=fileSel-fileOffset;
		gp=RenderTBOX(gp,130,i*12+150,330,11,
	              	255,255,255,selAlpha);
	}

	/*
	 * draw some sprites...
	 */

	gDPPipeSync(gp++);
	gDPSetTextureLUT(gp++,G_TT_RGBA16);
	gDPSetRenderMode(gp++,G_RM_AA_XLU_SURF,G_RM_AA_XLU_SURF);

	gDPSetCombineMode(gp++,PRIM_MOD,PRIM_MOD);

	for(i=0; i<5; i++)		// 1 game pak + 4 controllers
	{
		IntToStr(i,tmpString);

		x = 132-84 +(84*i);
	
		gDPPipeSync(gp++);
/******
		if(iconStatus[i] & 0x100)	// not plugged in
		{
			gDPLoadTLUT_pal256(gp++,(unsigned int)puw__gMainPal2);
			gDPSetPrimColor(gp++,0,0,128,128,128,64);
		}
		else if(curCtrlSel==i)
		{
			gDPLoadTLUT_pal256(gp++,(unsigned int)contPal);
			gDPSetPrimColor(gp++,0,0,255,255,255,255);
		}
		else
		{
			gDPLoadTLUT_pal256(gp++,(unsigned int)contPalLo);
//			gDPSetPrimColor(gp++,0,0,128,128,128,255);
			gDPSetPrimColor(gp++,0,0,192,192,192,255);
		}
*******/

		j=iconStatus[i] & 0xFF;
		switch(j)
		{
			case 0:
				break;
			case 1:		// the cartridge
//				gp=RenderTex(gp,contSprites[CONFIG_SPR_CART],
//					118+(72/2)-(contSprites[CONFIG_SPR_CART]->sx/2)+4,
//					CONFIG_Y3a+12);
		
				gp = RenderSprite(gp, SPR_PTR(SPR_SCART), (UI) puw__gMainPal2,GP_X, GP_Y);

				if(sb___gSaveDisabled)
				{
					gp=RenderText(gp,"Data will NOT be saved to Game Pak.",
							GP_X+80,GP_Y+8,FONT_BLKCN18,FPAL_BLACK,0);
				}
				else
				{
					gp=RenderText(gp,"Data will be saved to Game Pak.",
							GP_X+80,GP_Y+8,FONT_BLKCN18,FPAL_BLACK,0);
				}

				gp=RenderText(gp,"Game Pak Save Status",GP_X,CONFIG_Y0-10,FONT_BLKCN18,FPAL_BRIGHT_WHITE,0);

				break;

			case 3:	case 4:	case 5:	case 6:	// controller with controller pak
			case 2:		// controller only

//				gp=RenderTex(gp,contSprites[CONFIG_SPR_CONTROLLER],tmp,33);

				if(iconStatus[i] & 0x100)	// not plugged in
				{
//					SetRCColors(RGB_TRANS_GRY);
//					gp = RenderCorner(gp,SPR_PTR(SPR_SCONTRLB),x,CONT_Y);
					gp = RenderTSPR(gp, SPR_PTR(SPR_SCONTRL), (UI) puw__gMainPal2,x,CONT_Y,100);
				}
				else
				{
					gp = RenderSprite(gp, SPR_PTR(SPR_SCONTRL), (UI) puw__gMainPal2,x,CONT_Y);
				}

				gp=RenderText(gp,tmpString,x+33,CONT_Y- 10,FONT_BLKCN18,FPAL_WHITE,1);


				break;

			case 7:	case 8:	case 9:	case 10:	// controller with rumble pak
				// wiggle any rumble paks
				gp = RenderSprite(gp, SPR_PTR(SPR_SCONTRL), (UI) puw__gMainPal2,x,CONT_Y+(MyRnd()&1));
				gp = RenderSprite(gp, SPR_PTR(SPR_SRUMBLE), (UI) puw__gMainPal2,x-6,CONT_Y+22-(MyRnd()&1));

				gp=RenderText(gp,tmpString,x+33,CONT_Y- 10,FONT_BLKCN18,FPAL_WHITE,1);

//				gp=RenderTex(gp,contSprites[CONFIG_SPR_CONTROLLER],tmp,33+(MyRnd()&1));
//				gp=RenderTex(gp,contSprites[CONFIG_SPR_RUMBLE],x-32,40-(MyRnd()&1));
				break;
		}
	}

	/*
	 * let's have some text...
	 */

	if(currentState!=STATE_INIT)
	{
		for(i=0;i<3;i++)
		{
			gp=RenderText(gp,promptStrings[currentState*3+i],125,i*12+80,FONT_BLKCN18,FPAL_WHITE,0);
		}
	}

	gp=RenderText(gp,fileTitle,GP_X,135,FONT_BLKCN18,FPAL_BLACK,0);

	/*
	 * render options
	 */

	if(currentState==STATE_RUMBLE ||
	   currentState==STATE_FULL ||
	   currentState==STATE_FULLNOTE ||
	   currentState==STATE_DELETEYESNO ||
	   currentState==STATE_CLEAR_EEP_YESNO ||
	   currentState==STATE_CLEAR_EEP_DONE ||
	   currentState==STATE_ERROR ||
	   currentState==STATE_ERRORREPAIR ||
	   currentState==STATE_WRITEBUGGERED ||
	   currentState==STATE_ERROROURREPAIR)
	{
		j=350/(numOpts+1);
		k=112+j;
		for(i=0;i<numOpts;i++)
		{
			gp=RenderText(gp,optStrings[i],k,116,FONT_BLKCN18,i==optNo ? HILITE_PAL :FPAL_WHITE ,1);
			if(i==optNo)
			{
				w = lastW + 20;	
				gp = DrawOvalCursorHilite(gp, lastX-10 + w/2, lastY+3, w);
			}
			k+=j;
		}
	}

	else if (currentState == STATE_SELECT)
	{
		j= 15;	//12
		k = 82;	//92;
		for(i=0;i<numOpts;i++)
		{
			gp=RenderText(gp,optStrings[i],290,k,FONT_BLKCN18,i==optNo ? HILITE_PAL :FPAL_WHITE ,1);

			if(i==optNo)
			{
//				gp=RenderTBOX(gp,lastX-2-4,lastY-1,lastW+4+8,lastH+2,255,255,255,selAlpha);
				w = lastW + 20;	
				gp = DrawOvalCursorHilite(gp, lastX-10 + w/2, lastY+3, w);
			}
			k+=j;
		}

	}

	// Help message.
	gp = DrawHelpTeaser(gp, 290);

	/*
	 * draw chars
	 */

	gp=DrawChrList(gp);


	return(gp);
}



#else		// ======================	#if GAME_PAK_ONLY ----------


#define CONFIG_Y1	71
#define CONFIG_Y1a	(CONFIG_Y1+MENU_LINE_H)
#define CONFIG_Y2	131
#define CONFIG_Y2a	(CONFIG_Y2+MENU_LINE_H)
#define CONFIG_Y3	(143+1)
#define CONFIG_Y3a	(CONFIG_Y3+MENU_LINE_H)

struct rcbox ConfigScreenBoxes[] = 
{	

	{0,   0,			512,			CONFIG_Y1,				RGB_TRANS_ORANGE,0,0,0,0},
	HLINE(0,  CONFIG_Y1,  512),

	{0,   CONFIG_Y1a,	512,		CONFIG_Y2-CONFIG_Y1a,		RGB_TRANS_BLUE,0,0,0,0},
	HLINE(0,  CONFIG_Y2,  512),
//	{0,   CONFIG_Y2a,	512,		CONFIG_Y3-CONFIG_Y2a,		RGB_SOLID_YEL,0,0,0,0},
	{0,   CONFIG_Y2a,	512,		CONFIG_Y3-CONFIG_Y2a,		RGB_TRANS_ORANGE,0,0,0,0},
	HLINE(0,  CONFIG_Y3,  512),
	{0,   CONFIG_Y3a,	512,		MENU_BOTTOM_LINE_Y-CONFIG_Y3a,	RGB_TRANS_BLUE,0,0,0,0},

	HLINE(0,  MENU_BOTTOM_LINE_Y,  512),
	BOTTOM_COLORS

	{-1,0,0,0,0,NO_CORNERS}

};


//void ConfigRender(dyn *d,int draw_buffer,Gfx **gl)
Gfx *DrawScreenConfig(int shellstate, Gfx *gp)
{
int		i,j,k,x;
char	tmpString[80];
int		tmp;
int		w;

#if 0	//********--------------------------
	Gfx		*gp;
	u16		nmlz;
	Mtx		tmp1;

	/*
	 * get display list ptr
	 */

	gp=*gl;

	/*
	 * set shell stuff
	 */

	si___gWindowX = 0;
	si___gWindowY = 0;
	si___gWindowW = 512;
	si___gWindowH = 240;

	/*
	 * build matrices...
	 */

	MakeMat64PRH((long *)(&d->identity), 0, 0, 0, 0, 0, 0, 256);

	guOrtho(&tmp1,
		-currentProcess->ScreenX/2,
		 currentProcess->ScreenX/2,
		-currentProcess->ScreenY/2,
		 currentProcess->ScreenY/2,
		NEAR_Z,
		FAR_Z,
		1.0);

	guMtxCatL(
		&configFlipMatrix,
		&tmp1,
		&d->shellOrtho);

	gSPSegment(gp++, 0, 0x0);
	gSPDisplayList(gp++, DLInitRDP);
	gSPDisplayList(gp++, DLInitRSP);

	/*
	 * set up viewport
	 */

	gDPSetScissor(gp++,G_SC_NON_INTERLACE,0,0,
		      (currentProcess->ScreenX),
		      (currentProcess->ScreenY));

	vp.vp.vscale[0]=currentProcess->ScreenX*2;
	vp.vp.vscale[1]=currentProcess->ScreenY*2;
	vp.vp.vtrans[0]=currentProcess->ScreenX*2;
	vp.vp.vtrans[1]=currentProcess->ScreenY*2;
	gSPViewport(gp++,&vp);

	/*
	 * set and clear color framebuffer
	 */

	gDPSetColorImage(gp++,G_IM_FMT_RGBA, G_IM_SIZ_16b, currentProcess->ScreenX,
				OS_K0_TO_PHYSICAL(cfb[draw_buffer]));
	gDPPipeSync(gp++);

#if 1
	gDPSetCycleType(gp++,G_CYC_FILL);
	gDPSetFillColor(gp++,
	        	GPACK_RGBA5551(0,0,0,0) << 16 |
	        	GPACK_RGBA5551(0,0,0,0));
	gDPFillRectangle(gp++,0, 0, currentProcess->ScreenX-1, currentProcess->ScreenY-1);
	gDPPipeSync(gp++);
	gDPSetCycleType(gp++,G_CYC_1CYCLE);
#endif

	/*
	 * set up matrices
	 */

	gSPMatrix(gp++,OS_K0_TO_PHYSICAL(&(d->identity)),
	        	G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);

	/*
	 * more misc stuff
	 */

	gSPClearGeometryMode(gp++,G_CULL_BOTH);
	gDPSetColorDither(gp++,G_CD_MAGICSQ);
	gDPPipeSync(gp++);
	gSPClearGeometryMode(gp++,G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR);
	gSPClearGeometryMode(gp++,G_SHADE | G_SHADING_SMOOTH);
	gSPClearGeometryMode(gp++,G_ZBUFFER);

	/*
	 * draw some background stuff
	 */

	NextVtxList();
	gp=DrawShellBackground(gp,d);

	gSPMatrix(gp++,OS_K0_TO_PHYSICAL(&(d->shellOrtho)),
	        	G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);

	gDPLoadTLUT_pal256(gp++,(unsigned int)ovPal);
	gp=RenderImg(gp,sideLogo,44,19);

#endif




	/*
	 * draw boxes
	 */

	gp = DrawRCBoxes(gp,ConfigScreenBoxes);

/*******
	gp=RenderShadedBox(gp,109,19,372,54,configBlueBox);
	gp=RenderShadedBox(gp,109,71,372,62,configRedBox);
	gp=RenderShadedBox(gp,109,143,372,71,configGreenBox);
	gp=RenderTBOX(gp,109,19,2,208,RGB_SOLID_YEL);
	gp=RenderTBOX(gp,109,131,372,12,RGB_SOLID_YEL);
********/

	x=(72*curCtrlSel)+118+(72/2);
	gp=RenderTBOX(gp,x-34,31,68,33,
	              255,255,255,currentState==STATE_SELECT?selAlpha:128);

	if(currentState==STATE_DELETE ||
	   currentState==STATE_DELETEYESNO)
	{
		i=fileSel-fileOffset;
		gp=RenderTBOX(gp,130,i*12+150,330,11,
	              	255,255,255,selAlpha);
	}

	/*
	 * draw some sprites...
	 */

	gDPPipeSync(gp++);
	gDPSetTextureLUT(gp++,G_TT_RGBA16);
	gDPSetRenderMode(gp++,G_RM_AA_XLU_SURF,G_RM_AA_XLU_SURF);

#define PRIM_MOD	PRIMITIVE,0,TEXEL0,0,PRIMITIVE,0,TEXEL0,0
	gDPSetCombineMode(gp++,PRIM_MOD,PRIM_MOD);

	for(i=0; i<5; i++)		// 1 game pak + 4 controllers
	{
		x=72*i+118+(72/2);
	
		gDPPipeSync(gp++);
		if(iconStatus[i] & 0x100)	// not plugged in
		{
			gDPLoadTLUT_pal256(gp++,(unsigned int)contPalLo);
			gDPSetPrimColor(gp++,0,0,128,128,128,64);
		}
		else if(curCtrlSel==i)
		{
			gDPLoadTLUT_pal256(gp++,(unsigned int)contPal);
			gDPSetPrimColor(gp++,0,0,255,255,255,255);
		}
		else
		{
			gDPLoadTLUT_pal256(gp++,(unsigned int)contPalLo);
//			gDPSetPrimColor(gp++,0,0,128,128,128,255);
			gDPSetPrimColor(gp++,0,0,192,192,192,255);
		}

		j=iconStatus[i] & 0xFF;
		tmp = x-(contSprites[CONFIG_SPR_CONTROLLER]->sx/2);	// save a little code

		switch(j)
		{
			case 0:
				break;
			case 1:		// the cartridge
				gp=RenderTex(gp,contSprites[CONFIG_SPR_CART],x-(contSprites[CONFIG_SPR_CART]->sx/2),33);
				break;

			case 3:	case 4:	case 5:	case 6:	// controller with controller pak
				gp=RenderTex(gp,contSprites[CONFIG_SPR_CONTROLLER],tmp,33);
				gp=RenderTex(gp,contSprites[j-1],x-32,45);
				break;

			case 2:		// controller only

				gp=RenderTex(gp,contSprites[CONFIG_SPR_CONTROLLER],tmp,33);
				break;
			case 7:	case 8:	case 9:	case 10:	// controller with rumble pak
				// wiggle any rumble paks
				gp=RenderTex(gp,contSprites[CONFIG_SPR_CONTROLLER],tmp,33+(MyRnd()&1));
				gp=RenderTex(gp,contSprites[CONFIG_SPR_RUMBLE],x-32,40-(MyRnd()&1));
				break;
		}
		j=iconStatus[i] >> 9;
		switch(j)
		{
			case 0:
				break;
			case 1:		// valid controller pak with a Kobe saved game
				gp=RenderTex(gp,contSprites[CONFIG_SPR_BALL],x-(contSprites[CONFIG_SPR_BALL]->sx/2),33);
				break;
		}
	}

	/*
	 * let's have some text...
	 */

	if(currentState!=STATE_INIT)
	{
		for(i=0;i<3;i++)
		{
			gp=RenderText(gp,promptStrings[currentState*3+i],125,i*12+80,FONT_BLKCN18,FPAL_WHITE,0);
		}

		if(currentState==STATE_SELECT && curCtrlSel!=0)
		{
			if(pakNumFiles[curCtrlSel-1]>0)
			{
				// following not NOA standard (must be "the B Button"
//				gp=RenderText(gp,"Press B to selectively delete saved game notes.",125,3*12+80,FONT_BLKCN18,FPAL_WHITE,0);
//		following was too long so had to go to 2 lines
//				gp=RenderText(gp,"Press the B button to selectively delete saved game notes.",125,3*12+80,FONT_BLKCN18,FPAL_WHITE,0);

//				gp=RenderText(gp,"Press the B Button to",125,2*12+80,FONT_BLKCN18,FPAL_WHITE,0);
//				gp=RenderText(gp,"selectively delete saved game notes.",125,3*12+80,FONT_BLKCN18,FPAL_WHITE,0);

				gp=RenderText(gp,"Press START to continue without saving. Press the",125,2*12+80,FONT_BLKCN18,FPAL_WHITE,0);
				gp=RenderText(gp,"B Button to selectively delete saved game notes.",125,3*12+80,FONT_BLKCN18,FPAL_WHITE,0);
			}
		}
		else if(currentState==STATE_SELECT && curCtrlSel==0)
		{
//			gp=RenderText(gp,"Press B to delete the Game Pak saved data.",125,3*12+80,FONT_BLKCN18,FPAL_WHITE,0);
//			gp=RenderText(gp,"Press the B button to delete the Game Pak saved data.",125,3*12+80,FONT_BLKCN18,FPAL_WHITE,0);
//			gp=RenderText(gp,"Press the B Button to",125,2*12+80,FONT_BLKCN18,FPAL_WHITE,0);
//			gp=RenderText(gp,"delete the Game Pak saved data.",125,3*12+80,FONT_BLKCN18,FPAL_WHITE,0);

			gp=RenderText(gp,"Press START to continue without saving. Press the",125,2*12+80,FONT_BLKCN18,FPAL_WHITE,0);
			gp=RenderText(gp,"B Button to delete the Game Pak saved data.",125,3*12+80,FONT_BLKCN18,FPAL_WHITE,0);
		}
	}

	/*
	 * render file list...
	 */

	for(i=0;i<5;i++)
	{
		if(fileNames[i][0])
		{
			IntToStr(fileNos[i],tmpString);
			strcat(tmpString,".");
			gp=RenderText(gp,tmpString,135,i*12+152,FONT_BLKCN18,FPAL_WHITE,0);
			gp=RenderText(gp,fileNames[i],170,i*12+152,FONT_BLKCN18,FPAL_WHITE,0);
			IntToStr(fileSizes[i],tmpString);
			strcat(tmpString," page");
			if(fileSizes[i]!=1)
			{
				strcat(tmpString,"s");
			}
			gp=RenderText(gp,tmpString,380,i*12+152,FONT_BLKCN18,FPAL_WHITE,0);
		}
	}
	gp=RenderText(gp,fileTitle,125,135,FONT_BLKCN18,FPAL_BLACK,0);

	/*
	 * render options
	 */

	if(currentState==STATE_RUMBLE ||
	   currentState==STATE_FULL ||
	   currentState==STATE_FULLNOTE ||
	   currentState==STATE_DELETEYESNO ||
	   currentState==STATE_CLEAR_EEP_YESNO ||
	   currentState==STATE_CLEAR_EEP_DONE ||
	   currentState==STATE_ERROR ||
	   currentState==STATE_ERRORREPAIR ||
	   currentState==STATE_WRITEBUGGERED ||
	   currentState==STATE_ERROROURREPAIR)
	{
		j=350/(numOpts+1);
		k=112+j;
		for(i=0;i<numOpts;i++)
		{
			gp=RenderText(gp,optStrings[i],k,116,FONT_BLKCN18,FPAL_WHITE,1);
			if(i==optNo)
			{
				gp=RenderTBOX(gp,lastX-2,lastY-1,lastW+4,lastH+2,255,255,255,selAlpha);
			}
			k+=j;
		}
	}

	// Help message.
	gp = DrawHelpTeaser(gp, 290);

	/*
	 * draw chars
	 */

	gp=DrawChrList(gp);

	/*
	 * we're done
	 */

//	*gl=gp;
	return(gp);
}


#endif		// ======================	#if GAME_PAK_ONLY  --------



/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

/************

#define REPEAT_DELAY	8
#define INITIAL_DELAY	30
int repctr[4];

void AutoRepeatKey(int key,int c,int cur,int *old)
{
	if(cur & key)
	{
		if((*old) & key)	repctr[c]++;
		else			repctr[c]=-(INITIAL_DELAY-REPEAT_DELAY);
	}
	else
	{
		repctr[c]=0;
	}
	if(repctr[c] > REPEAT_DELAY)
	{
		repctr[c]=0;
		(*old) &= (~key);
	}
}

void AutoRepeat(int cur,int *old)
{
	AutoRepeatKey(CTRL_PAD_LEFT,0,cur,old);
	AutoRepeatKey(CTRL_PAD_RIGHT,1,cur,old);
	AutoRepeatKey(CTRL_PAD_UP,2,cur,old);
	AutoRepeatKey(CTRL_PAD_DOWN,3,cur,old);
}

*********/


void ReadGameDataFromGamePak(void)
{
int error;
int retry;
int numpages;
					
					
	for(retry=0;retry<3;retry++)
	{
		numpages = (si___gMemPakNeed+(FR_PAGE_SIZE-1))/FR_PAGE_SIZE;
	
		ReadFlashRom(GAME_DATA_FLASH_PAGE_NUM, numpages, (unsigned char *)dfb);	// read into Z-buffer
		error = ReadMemPakFile((unsigned char *)dfb);	// decode data that's in Z-buffer

		if(!error)
		{
//			SeasonRosterToGameRoster();
			configNewDataLoaded = 1;
			break;
		}
	}

	if(error)
	{	// copy default into flash rom
						
		int firsttime;
		// is this the first time ever powered on???
		firsttime = CheckFirstTimeEverPoweredOn();
		if(firsttime)		// from Flash Rom
		{		// write "1st time" header to flash rom
			WriteFlashRom(FIRST_TIME_DATA_FLASH_PAGE_NUM, 1, idcomparevalue);
		}
		else	// not 1st time ever on, must have pulled pak out/ reset/ power failure during last write
		{	
			InitPopup("GAME PAK", acz__gGamePakDataLostText, NULL);
		}
						
		WriteFRError = WriteFlashRom(GAME_DATA_FLASH_PAGE_NUM, numpages,(char *) &DEFAULT_MEMPAK_BUFFER); // write back default data
		ReadMemPakFile((char *) &DEFAULT_MEMPAK_BUFFER);		// move default data to where it should go


		configNewDataLoaded = 1;	// still must LinkCustomPlayers

		if(!firsttime)	
		{
			AudioPlaySfx(SFX_ERROR, 11025, 255, 7);

		}
	}
}








void GotoRumbleState(void)
{
   lastState = currentState;
	currentState=STATE_DONE;
	configUseRumble=0;
	configUseCtrlPak=(curCtrlSel==0)?0:1;
}


void GotoSelectState(void)
{
#if GAME_PAK_ONLY

#if LOCALE==CHINA
   optNo = 1;  // don't save to game pack
#else 
	optNo = 0;	// assume "Save to Game Pak"
#endif
	numOpts = 3;
	optStrings = gamepakOptStrings;	//yesNoOptStrings;

#endif

	currentState = STATE_SELECT;
}

int GamePakSelect(int btn)		// new 9/27/99
{

int sound = -1;
//int error;
//int retry;
//int numpages;

	if(btn & (CTRL_START | CTRL_FIRE_A) )
	{
		sound = SFX_ID_OK;

		switch(optNo)
		{
			case 0:
				sb___gSaveDisabled = 0;

			//	ReadGameDataFromGamePak(); moved to Initscreen
	
				GotoRumbleState();
				break;

			case 1:
				sb___gSaveDisabled = 1;	// continue without saving
				GotoRumbleState();
				break;

			case 2:
				currentState=STATE_CLEAR_EEP_YESNO;
				numOpts=2; optNo=1; optStrings=yesNoOptStrings;
			
				break;

		}
	}
	else if(btn & CTRL_PAD_UP)
	{ 
		optNo=(optNo+numOpts-1) % numOpts;
		sound = SFX_ID_SCROLL;

	}
	else if(btn & CTRL_PAD_DOWN)
	{
		optNo=(optNo+1) % numOpts;
		sound = SFX_ID_SCROLL;
	}



	return(sound);

}



/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

int oldp=0,lastDir=1;

//void ConfigProcess(signed int *p)

int		ProcScreenConfig	(int shellstate)
{
int status, cnum;
unsigned char	c;
int		i,j,k,h;
int		newp,new;
int		pk;
//extern int	ctrlReading;
int		error;
int numpages;
int	changed=0;
int	sound = -1;

/********
	newp=0;
	for(i=0;i<4;i++)
	{
		j=p[i];
		if((j & 0xC0000000u) == 0xC0000000u && (j & CTRL_UP)) j|=CTRL_PAD_UP;
		if((j & 0xC0000000u) == 0xC0000000u && (j & CTRL_DOWN)) j|=CTRL_PAD_DOWN;
		if((j & 0x0C000000u) == 0x0C000000u && (j & CTRL_LEFT)) j|=CTRL_PAD_LEFT;
		if((j & 0x0C000000u) == 0x0C000000u && (j & CTRL_RIGHT)) j|=CTRL_PAD_RIGHT;
		newp|=j;
	}
	AutoRepeat(newp,&oldp);
	new=newp & (~oldp);
********/
	new = newp = asi__gTeamBtn[EVERYBODY];

	apcz_gStateHelpMsg[shellstate] = acz__gHelpScreenMoveLR; 

	if(configFrame++<5) new=0;	// no input for first X frames
/****
	if(!ctrlReading)
	{
		CtrlUpdate();
		CtrlStartReading();
	}

*******/


	if (si___gPopupVal < 0)
	{
		goto allDone;
	}

	// Popup result available ?

	if (si___gPopupVal > 0)		//No humans - continue?
	{
		si___gPopupVal = 0;
		goto allDone;
	}

//	configTimeout=CONFIG_TIMEOUT_VALUE/2;	// never timeout

	if(newp || !DidIntro)	// key pressed???
	{	// if never did Intro, must have got here by START on power up, so no timeout exit
		configTimeout=CONFIG_TIMEOUT_VALUE/2;
	}
	else
	{
		if(--configTimeout < 0)
		{	// auto exit if no buttons pressed for a while
//			currentProcess->status=PROCESS_FREEING;

//			DidSaveOptions = 1;		// looked at by Main to see where to go after exit (if 0, back to intro loop)
//			shellstate = STATE_MAIN_MENU;

			shellstate = STATE_STOP_SHELL;	// will do intro/title
			LeaveShellMethod = 	LEAVE_SHELL_TO_INTRO;

			goto allDone;
		}
	}
	
//	configTimeout=CONFIG_TIMEOUT_VALUE/2;	// never timeout


	switch(currentState)
	{
		case STATE_ERROR:
			if(new & CTRL_FIRE_A)
			{
				GotoSelectState();
				sound = SFX_ID_OK;
			}
			break;

		case STATE_WRITEBUGGERED:
			if(new & CTRL_PAD_LEFT)
			{
				optNo=(optNo+numOpts-1) % numOpts;
				sound = SFX_ID_SCROLL;
			}
			else if(new & CTRL_PAD_RIGHT)
			{	
				optNo=(optNo+1) % numOpts;
				sound = SFX_ID_SCROLL;
			}
			else if(new & CTRL_FIRE_A)
			{
				sound = SFX_ID_OK;
				if(optNo==0)
				{
					GotoSelectState();

					CtrlScan();
				}
				else
				{
					curCtrlSel=0;
					GotoSelectState();
					CtrlScan();
				}
			}
			break;

		case STATE_ERRORREPAIR:
			if(new & CTRL_PAD_LEFT)
			{
				optNo=(optNo+numOpts-1) % numOpts;
				sound = SFX_ID_SCROLL;
			}
			else if(new & CTRL_PAD_RIGHT)
			{
				optNo=(optNo+1) % numOpts;
				sound = SFX_ID_SCROLL;
			}
			else if(new & CTRL_FIRE_B)
			{
				GotoSelectState();
//				currentState=STATE_SELECT;
				sound = SFX_ID_BACK;
			}
			else if(new & CTRL_FIRE_A)
			{
				sound = SFX_ID_OK;
				if(optNo==1)
				{
					GotoSelectState();
		//			currentState=STATE_SELECT;
					CtrlScan();
				}
				else if(optNo==0)
				{
					i=CtrlPakRepair(curCtrlSel-1);
					CtrlScan();
					pakDirValid &= ~(1<<(curCtrlSel-1));
					if(i == PFS_ERR_ID_FATAL || i == PFS_ERR_DEVICE || i==PFS_ERR_INVALID)
					{
						currentState=STATE_WRITEBUGGERED;
						numOpts=2;
						optNo=0;
						optStrings=writeBuggeredOptStrings;
					}
					else
					{		// repair was successful
						GotoSelectState();
//						currentState=STATE_SELECT;
					}
				}
				else
				{
					curCtrlSel=0;
					GotoSelectState();  // currentState=STATE_SELECT;
				}
			}
			break;

		case STATE_ERROROURREPAIR:
			cnum = curCtrlSel-1;
			if(new & CTRL_PAD_LEFT)
			{
				optNo=(optNo+numOpts-1) % numOpts;
				sound = SFX_ID_SCROLL;
			}
			else if(new & CTRL_PAD_RIGHT)
			{
				optNo=(optNo+1) % numOpts;
				sound = SFX_ID_SCROLL;
			}
			else if(new & CTRL_FIRE_B)
			{
				GotoSelectState();  // currentState=STATE_SELECT;
				sound = SFX_ID_BACK;
			}
			else if(new & CTRL_FIRE_A)
			{
				sound = SFX_ID_OK;
				if(optNo==0)
				{
					currentState=STATE_READING_MEMPAK;
				}
				else
				{
					i=CtrlPakDeleteFile(cnum,ctrlPakDirEntries[cnum][pakOurFhs[cnum]].fileId);
					if(i==-PFS_ERR_ID_FATAL)
					{
						currentState=STATE_ERRORREPAIR;
						numOpts=3; optNo=0; optStrings=corruptOptStrings;
					}
					else if(i<0)
					{
						currentState=STATE_ERROR;
						numOpts=1; optNo=0; optStrings=okOptStrings;
					}
					else
					{
						UpdateDir(cnum);
						GotoSelectState();  // currentState=STATE_SELECT;
					}
				}
			}
			break;
		
		case STATE_INIT:

#if GAME_PAK_ONLY		
			GotoSelectState();

#else

			for(i=0;i<4;i++) UpdateDir(i);
/***
			for(i=0;i<4;i++)
			{
				if(pakGotGame & (1<<i))
				{	// find first controller pak with our game data
					curCtrlSel=i+1;
					break;
				}
			}
****/
#endif
			curCtrlSel = 0;	// Kobe 2 - always start with flash rom
			GotoSelectState();  // currentState=STATE_SELECT;
			break;
		
		case STATE_READING_MEMPAK:
			cnum = curCtrlSel-1;

			status = (1<<cnum);
			if(		(paksValid &   status)
				 && (pakDirValid & status)
				 && (pakGotGame &  status)
			  )
			{
				// read whole file (into Z-buffer)
				error = CtrlPakReadFile( cnum,ctrlPakDirEntries[cnum][pakOurFhs[cnum]].fileId,
										0,configRequiredBlocks*256,(unsigned char *)dfb);
				memcpy(headerBuffer,dfb,MEMPAK_HEADER_LENGTH);
				
				if(error == -PFS_ERR_ID_FATAL)
				{
					currentState=STATE_ERRORREPAIR;
					numOpts=3; optNo=0; optStrings=corruptOptStrings;
				}
				else if(error == -PFS_ERR_BAD_DATA)
				{
					currentState=STATE_ERROROURREPAIR;
					numOpts=2;
					optNo=0;
					optStrings=ourCorruptOptStrings;
				}
				else if(error == -PFS_ERR_NEW_PACK)
				{
					currentState=STATE_ERROR;
					numOpts=1; optNo=0; optStrings=okOptStrings;
					UpdateDir(cnum);
				}
				else if(ctrlPakDirEntries[cnum][pakOurFhs[cnum]].size != configRequiredBlocks*256)
				{
					currentState=STATE_ERROROURREPAIR;
					numOpts=2;
					optNo=0;
					optStrings=ourCorruptOptStrings;
				}
				else if(error < 0)
				{
					currentState=STATE_ERROR;
					numOpts=1; optNo=0; optStrings=okOptStrings;
				}
				else if(headerBuffer[0]!=headerSig[0] ||
					headerBuffer[1]!=headerSig[1] ||
					headerBuffer[2]!=headerSig[2] ||
					headerBuffer[3]!=headerSig[3] ||
					*((long *)(&headerBuffer[8])) != LFP_FILE_VERSION ||
					error != 0)
				{
					currentState=STATE_ERROROURREPAIR;
					numOpts=2;
					optNo=0;
					optStrings=ourCorruptOptStrings;
				}
				else
				{
					// ok... header's fine... check integrity of john's data...
					error = ReadMemPakFile(((char *)dfb)+MEMPAK_HEADER_LENGTH);
					if(error)
					{
						currentState=STATE_ERROROURREPAIR;
						numOpts=2;
						optNo=0;
						optStrings=ourCorruptOptStrings;
					}
					else
					{
						// HEY! HEY! IT'S OK!
//						SeasonRosterToGameRoster();	// need here as before only done in shell open
						configNewDataLoaded = 1;

						currentSerialNo=*((long *)(&headerBuffer[4]));
						GotoRumbleState();
//						currentState=STATE_RUMBLE;
//						if(motorValid) optNo=0;
//						else optNo=1;
//						numOpts=2;
//						optStrings=yesNoOptStrings;
					}
				}
			}
			break;


		case STATE_SELECT:	// -------------------  Main case ---------------------


#if GAME_PAK_ONLY
			apcz_gStateHelpMsg[shellstate] = acz__gHelpScreenMoveUD; 
			sb___gSaveDisabled = 0;

			sound = GamePakSelect(new);		// new 9/27/99
#else
			

			cnum = curCtrlSel-1;	// save a bit of code

			if(new & CTRL_START)
			{
				sound = SFX_ID_OK;
				sb___gSaveDisabled = 1;	// continue without saving
				GotoRumbleState();
			}
			else
			if(new & CTRL_FIRE_A)
			{
				sound = SFX_ID_OK;

				// try to use current cart

				if(curCtrlSel == 0)		//Game Pak (i.e. Flash Rom)
				{
					int retry;

#if 1
					for(retry=0;retry<3;retry++)
					{
						numpages = (si___gMemPakNeed+(FR_PAGE_SIZE-1))/FR_PAGE_SIZE;
	
						ReadFlashRom(GAME_DATA_FLASH_PAGE_NUM, numpages, (unsigned char *)dfb);	// read into Z-buffer
						error = ReadMemPakFile((unsigned char *)dfb);	// decode data that's in Z-buffer

						if(!error)
						{
//							SeasonRosterToGameRoster();
							configNewDataLoaded = 1;
							break;
						}
					}

					if(error)
					{	// copy default into flash rom
						
			
						WriteFRError = WriteFlashRom(GAME_DATA_FLASH_PAGE_NUM, numpages,(char *) &DEFAULT_MEMPAK_BUFFER); // write back default data
						ReadMemPakFile((char *) &DEFAULT_MEMPAK_BUFFER);			// decode default data

						configNewDataLoaded = 1;	// still must LinkCustomPlayers

					}



#else //======== no more eeproms
/*******
					// try reading...
					for(retry=0;retry<3;retry++)
					{
						CtrlEepromReadBuffer( 24>>3, (unsigned char *)dfb, 2024/8);	// read into Z-buffer
						error = ReadEepromFile((char *)dfb);	// returns ZERO if no errors
						if(!error)
						{
//							SeasonRosterToGameRoster();
							configNewDataLoaded = 1;
							break;
						}
					}

					if(error)
					{
						CtrlEepromWriteBuffer(0,defaultEepromFile,2048/8);
						ReadEepromFile(((char *)defaultEepromFile)+24);
					}
*******/
#endif

					// go to rumble pak menu
					GotoRumbleState();
//					currentState=STATE_RUMBLE;
//					if(motorValid) optNo=0;	// start on YES if rumble inserted
//					else optNo=1;
	
//					numOpts=2;
//					optStrings=yesNoOptStrings;
				}
				else if(pakDirValid & (1<<(cnum)))	// using MemPak
				{
					UpdateDir(cnum);

//					if(pakGotGame & (1<<curCtrlSel-1))
					if(pakGotGame & (1<<cnum))
					{
						currentState=STATE_READING_MEMPAK;
					}
					else if(pakFreeSpace[cnum] < configRequiredBlocks)
					{
						sound = SFX_ERROR;
						currentState=STATE_FULL;
						optNo=0;
						numOpts=2;
						optStrings=yesNoOptStrings;
					}
					else if(pakNumFiles[cnum]==MAX_CTRLPAK_FILES)
					{
						sound = SFX_ERROR;

						currentState=STATE_FULLNOTE;
						optNo=0;
						numOpts=2;
						optStrings=yesNoOptStrings;
					}
					else
					{
						currentState=STATE_WRITING_MEMPAK;
					}
				}
			}
			else if(new & CTRL_PAD_LEFT)
			{
				curCtrlSel=(curCtrlSel+4)%5;
				sound = SFX_ID_SCROLL;
			}
			else if(new & CTRL_PAD_RIGHT)
			{
				curCtrlSel=(curCtrlSel+1)%5;
				sound = SFX_ID_SCROLL;
			}
			else if(new & CTRL_PAD_UP)
			{
				fileOffset--;
				sound = SFX_ID_SCROLL;
			}
			else if(new & CTRL_PAD_DOWN)
			{
				fileOffset++;
				sound = SFX_ID_SCROLL;
			}

			else if(new & CTRL_FIRE_B)
			{
				sound = SFX_ID_OK;
				if(curCtrlSel > 0)	// delete a file
				{
					if(pakNumFiles[cnum])
					{
						currentState=STATE_DELETE;
						optStrings=yesNoOptStrings;
					}
				}
				else
				{
					currentState=STATE_CLEAR_EEP_YESNO;
					numOpts=2; optNo=1; optStrings=yesNoOptStrings;
				}
			}
#endif
			break;

		case STATE_WRITING_MEMPAK:
			cnum = curCtrlSel-1;	//use local instead of subtracting every time

			// try and create new file...
			pakDirValid &= ~(1<<(cnum));
//			int CtrlPakCreateFile(int pak,char *n,char *extension,int companyCode,int gameCode,int size)

			h = CtrlPakCreateFile(cnum,gameTitle,"",companyCode,gameCode,configRequiredBlocks*256);
			
			if(h == -PFS_ERR_ID_FATAL)
			{
				currentState=STATE_ERRORREPAIR;
				numOpts=3; optNo=0; optStrings=corruptOptStrings;
			}
			else if(h < 0)
			{
				currentState=STATE_ERROR;
				numOpts=1; optNo=0; optStrings=okOptStrings;
			}
			else
			{
				char *p;
				int retry;

				// try reading eeprom file...
				for(retry=0; retry < 3; retry++)
				{
	
					ReadFlashRom(GAME_DATA_FLASH_PAGE_NUM, si___gMemPakNeed/FR_PAGE_SIZE_BYTES, (unsigned char *)dfb);	// read into Z-buffer
					error = ReadMemPakFile((unsigned char *)dfb);	// decode data that's in Z-buffer

//					CtrlEepromReadBuffer(24>>3,(unsigned char *)dfb,2024/8);
//					error = ReadEepromFile((char *)dfb);
					if(!error) break;
				}

				// write signature + serial code
				p=((char *)dfb) + MEMPAK_HEADER_LENGTH;
				MakeMemPakFile(&p);

				memcpy(headerBuffer,headerSig,4);
				*((long *)(&headerBuffer[4]))=osGetCount();
				*((long *)(&headerBuffer[8]))=LFP_FILE_VERSION;
				memcpy(dfb,headerBuffer,MEMPAK_HEADER_LENGTH);

				error = CtrlPakWriteFile(cnum,h,0,configRequiredBlocks*256,(unsigned char *)dfb);
				if(error < 0)
				{
					CtrlPakDeleteFile(cnum,h);
					pakDirValid &= ~(1<<(cnum));

					currentState=STATE_ERROR;
					numOpts=1; optNo=0;
					optStrings=okOptStrings;
				}
				else
				{
					// ok... try and read back!
					currentState=STATE_READING_MEMPAK;
				}
			}
			break;

		case STATE_FULL:
		case STATE_FULLNOTE:
			if(new & CTRL_PAD_LEFT)
			{ 
				optNo=(optNo+numOpts-1) % numOpts;
				sound = SFX_ID_SCROLL;

			}
			else if(new & CTRL_PAD_RIGHT)
			{
				optNo=(optNo+1) % numOpts;
				sound = SFX_ID_SCROLL;
			}
			else if(new & CTRL_FIRE_B)
			{
				GotoSelectState();  //  currentState=STATE_SELECT;
				sound = SFX_ID_BACK;

			}
			else if(new & CTRL_FIRE_A)
			{
				sound = SFX_ID_OK;

				if(optNo==0)
				{
					currentState=STATE_DELETE;
					pakDirValid &= ~(1<<(curCtrlSel-1));
				}
				else
				{
					GotoSelectState();  // currentState=STATE_SELECT;
				}
			}
			break;

		case STATE_RUMBLE:
			{
			   // IQUE: Rumble pack is always done.
				// DONE!
				sound = SFX_ID_OK;
				currentState=STATE_DONE;
				configUseRumble=0;
				configUseCtrlPak=(curCtrlSel==0)?0:1;
			}
			break;

		case STATE_DELETE:
			if(new & CTRL_PAD_UP) { fileSel--;  sound = SFX_ID_SCROLL;}
			else if(new & CTRL_PAD_DOWN) { fileSel++;  sound = SFX_ID_SCROLL;}
			else if(new & CTRL_FIRE_B) { GotoSelectState();   sound = SFX_ID_BACK;}
			else if(new & CTRL_FIRE_A)
			{
				sound = SFX_ID_OK;
				currentState=STATE_DELETEYESNO;
				numOpts=2; optNo=1; optStrings=yesNoOptStrings;
			}
			break;

		case STATE_CLEAR_EEP_DONE:
			if(new & (CTRL_FIRE_A | CTRL_FIRE_B))
			{
				sound = SFX_ID_OK;
// 				currentState=STATE_SELECT;
//				numOpts=1; optNo=0; optStrings=okOptStrings;
				GotoSelectState();

			}
			break;

		case STATE_DELETEYESNO:
			if(new & CTRL_PAD_LEFT) { optNo=(optNo+numOpts-1) % numOpts;  sound = SFX_ID_SCROLL;}
			else if(new & CTRL_PAD_RIGHT) { optNo=(optNo+1) % numOpts;  sound = SFX_ID_SCROLL;}
			else if(new & CTRL_FIRE_B) { currentState=STATE_DELETE;  sound = SFX_ID_BACK;}
			else if(new & CTRL_FIRE_A)
			{
				sound = SFX_ID_OK;
				if(optNo==0)
				{
					pakDirValid &= ~(1<<(curCtrlSel-1));
					i=CtrlPakDeleteFile(curCtrlSel-1,ctrlPakDirEntries[curCtrlSel-1][fileSel].fileId);
					if(i==-PFS_ERR_ID_FATAL)
					{
						 sound = SFX_ERROR;
						currentState=STATE_ERRORREPAIR;
						numOpts=3; optNo=0; optStrings=corruptOptStrings;
					}
					else if(i<0)
					{
						 sound = SFX_ERROR;
						currentState=STATE_ERROR;
						numOpts=1; optNo=0; optStrings=okOptStrings;
					}
					else
					{
						currentState=STATE_DELETE;
					}
				}
				else
				{
					currentState=STATE_DELETE;
				}
			}
			break;

		case STATE_CLEAR_EEP_YESNO:
			if(new & CTRL_PAD_LEFT) { optNo=(optNo+numOpts-1) % numOpts; sound = SFX_ID_SCROLL; }
			else if(new & CTRL_PAD_RIGHT) { optNo=(optNo+1) % numOpts;  sound = SFX_ID_SCROLL;}
			else if(new & CTRL_FIRE_B) { GotoSelectState();  sound = SFX_ID_BACK; }
			else if(new & CTRL_FIRE_A)
			{
				
				int retry;
				sound = SFX_ID_OK;
				if(optNo==0)
				{
					osFlashAllErase();		// clear everything on flash rom(i.e Custom users,pref,rosters, season stats...) 

					// write back default team rosters, etc
					WriteFRError = WriteFlashRom(GAME_DATA_FLASH_PAGE_NUM, 
								(si___gMemPakNeed+(FR_PAGE_SIZE-1))/FR_PAGE_SIZE,
								(char *) &DEFAULT_MEMPAK_BUFFER); 
			
					// the "final" bug - 10/11/99
					ReadMemPakFile((char *) &DEFAULT_MEMPAK_BUFFER); // move default data to where it should go

					WriteFlashRom(FIRST_TIME_DATA_FLASH_PAGE_NUM, 1, idcomparevalue);
					

		//			CtrlEepromWriteBuffer(0,defaultEepromFile,2048/8);	// config - re- init
					InitCustomUsers();
	
					NeedCustomUserSave = 1;
					SaveCustomUserData();	// and save it

					// restore defaults
					wordcpy(&cl___gPreferences,&DefaultPreferences, sizeof(Preferences_T));
					SavePreferences(&cl___gPreferences);	// and put them back on memcard

					wordcpy(&acl__gOptions,&acl__gDefaultOptions, sizeof(Options_T)*4);
					
					currentState=STATE_CLEAR_EEP_DONE;
					optStrings=okOptStrings;
					numOpts=1;
				}
				else
				{
					GotoSelectState();	//	currentState=STATE_SELECT;
				}
			}
			break;
	}

	if(new & CTRL_PAD_LEFT) lastDir=-1;
	else lastDir=1;

	/*
	 * pulse alpha value
	 */

	selAlpha=frame%60;
	if(selAlpha>30) selAlpha=60-selAlpha;
	selAlpha=(selAlpha*64)/30+32;

	/*
	 * do a quick scan, every 1/2 second...
	 */

	if(!((frame%30)/2)  || FirstTimeInConfig)
	{
		FirstTimeInConfig = 0;
		CtrlScanQuick(&c);
		changed = pakBits ^ ((c)|(validcontrollers<<16));
		if(changed)
		{
			CtrlScan();
		}

		pakBits=(c) | (validcontrollers<<16);
	}

	paksValid |= dodgyPaks;

	/*
	 * set icons
	 */

	iconStatus[0] = 1;	// cartridge is always there

	for(i=0;i<4;i++)
	{
		cnum = (1<<i);
		if(!(validcontrollers & (cnum)))
		{
			status	=0x102;	// not plugged in
		}
		else if(!(pakBits & (cnum)))
		{
			status		=2;		// plugged in - no rumble or pak
		}
		else if( !(paksValid & (cnum)))
		{
			if(motorValid & cnum)
			{
				status	=7+i;	// rumble pak
			}
			else
			{	// transfer pak or damaged controller pak - bug # 241
				status		=2;		// plugged in - no rumble or pak
			}
		}
		else
		{
			status	=3+i;	// controller pak
		}
		
		if((pakGotGame & (cnum)) && (pakBits & (cnum)))
		{
			status |= 0x200;	// controller pak with valid Kobe saved game
		}
		iconStatus[i+1] = status;

	}

	/*
	 * if current pak invalid, cycle to next...
	 */

	i=curCtrlSel;
	while(!(paksValid & (1<<curCtrlSel-1)) && curCtrlSel!=0)
	{
		curCtrlSel=(curCtrlSel+5+lastDir) % 5;
	}
	// if this happened, ensure we're in SELECT state...
	if(i!=curCtrlSel) GotoSelectState();  // currentState=STATE_SELECT;

	if(dodgyPaks & (1<<(curCtrlSel-1)) && (currentState!=STATE_ERRORREPAIR && currentState!=STATE_WRITEBUGGERED))
	{
		currentState=STATE_ERRORREPAIR;
		numOpts=3;
		optNo=0;
		optStrings=corruptOptStrings;
	}

	/*
	 * invalidate changed directories
	 */

	for(i=0;i<4;i++) if((changed & (1<<i)) || (changed & (1<<(i+16)))) pakDirValid &= ~(1<<i);
	pakGotGame &= pakDirValid;
	pakGotGame &= paksValid;

	/*
	 * read directory if it may have changed...
	 */

	if(currentState!=STATE_ERRORREPAIR && currentState!=STATE_WRITEBUGGERED)
	{
		for(pk=0;pk<4;pk++)
		{
			if((!(pakDirValid & (1<<pk))) &&
	//		   (pakBits & (1<<pk)) &&
		   	(paksValid & (1<<pk)))
			{
				UpdateDir(pk);
			}
		}
	}

	/*
	 * update file title bar and file strings
	 */

	cnum = curCtrlSel-1;
	if((curCtrlSel>0) && (paksValid & (1<<(cnum))))
	{
//		if(fileOffset>pakNumFiles[cnum]-5) fileOffset=pakNumFiles[cnum]-5;

		if( fileOffset > pakNumFiles[cnum] - 5)
		{
			fileOffset = pakNumFiles[cnum ] - 5;
		}
		
		if(fileOffset<0) fileOffset=0;

		for(i=fileOffset,j=0; i<fileOffset+5; i++,j++)
		{
			if(ctrlPakDirEntries[cnum][i].fileId!=-1)
			{
				strcpy(fileNames[j],ctrlPakDirEntries[cnum][i].gameName);
				if(ctrlPakDirEntries[cnum][i].extension[0])
				{
					strcat(fileNames[j],".");
					strcat(fileNames[j],ctrlPakDirEntries[cnum][i].extension);
				}
				fileNos[j]=i+1;
				fileSizes[j]=ctrlPakDirEntries[cnum][i].size/256;
			}
			else
			{
				fileNames[j][0]=0;
			}
		}
		strcpy(fileTitle,"Controller Pak ");
		IntToStr(curCtrlSel,&fileTitle[strlen(fileTitle)]);
		strcat(fileTitle,": ");
		if(pakGotGame & (1<<(cnum)))
		{
			strcat(fileTitle,"NBA Courtside 2 data found");
		}
		else
		{
			if(pakNumFiles[cnum]==MAX_CTRLPAK_FILES)
			{
				strcpy(fileTitle,"All ");
				IntToStr(MAX_CTRLPAK_FILES,&fileTitle[strlen(fileTitle)]);
				strcat(fileTitle," game notes used.");
			}
			else
			{
				IntToStr(pakFreeSpace[cnum],&fileTitle[strlen(fileTitle)]);
				strcat(fileTitle," pages available, ");
				IntToStr(configRequiredBlocks,&fileTitle[strlen(fileTitle)]);
				strcat(fileTitle," required");
			}
		}
	}
	else
	{
		if(curCtrlSel==0)
		{
//			strcpy(fileTitle,"Game Pak - minimal stats only");
#if GAME_PAK_ONLY
//			strcpy(fileTitle,"Game Pak Save Status");
			strcpy(fileTitle,"Controller Status");
#else
			strcpy(fileTitle,"Game Pak");
#endif
		}
		else
		{
			strcpy(fileTitle,"No Controller Pak on Controller ");
			IntToStr(curCtrlSel,&fileTitle[strlen(fileTitle)]);
		}
		for(i=0;i<5;i++) fileNames[i][0]=0;
	}

	/*
	 * move selection bar
	 */

	if(currentState==STATE_DELETE)
	{
		if(fileSel>pakNumFiles[cnum]-1) fileSel=pakNumFiles[cnum]-1;
		if(fileSel<0) fileSel=0;
		while(fileOffset > fileSel) fileOffset--;
		while(fileOffset+4 < fileSel) fileOffset++;
	}

	oldp=newp;

/*******
	if(currentState==STATE_DONE)
	{
		configValid=1;	// looked at by Main to see where to go after exit (if 0, back to intro loop)
		currentProcess->status=PROCESS_FREEING;
	}
******/
	if(currentState==STATE_DONE)
	{
		currentState = lastState;	// kludge so last render doesn't suck
		DidSaveOptions = 1;		// looked at by Main to see where to go after exit (if 0, back to intro loop)
//		configValid=1;
		if(DidIntro)
		{
			shellstate = STATE_MAIN_MENU;
		}
		else
		{	// START must have been pressed on power up to get here
			shellstate = STATE_STOP_SHELL;	// go do intro/title
			LeaveShellMethod = 	LEAVE_SHELL_TO_INTRO;

		}

	}

	allDone:

	if(sound != -1)
	{
		AudioPlaySfx(sound, 11025, 255, 7);
	}


	return(shellstate);


}


/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

Gfx *RenderText(Gfx *gp,char *s,int x,int y,int f,int c,int center)
{
	TXTCEL_T	*tc;

	tc=InitTxtCel(NULL,0,f,c,FFLG_YL);
	ClearTxtCel(tc);
	WriteTxtCel(tc,s);
	if(center) x-=(tc->ui___tcW/2);
	DrawTxtCel(tc,x,y+tc->ui___tcH-1);
	lastX=x; lastY=y;
	lastW=tc->ui___tcW;
	lastH=tc->ui___tcH;
	FreeTxtCel(tc);
	MemFree(tc);

	return(gp);
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

/***************
Gfx *RenderImg(Gfx *gp,img *im,int x,int y)
{
	int		xx,yy;
	int		i,j;
	unsigned short	*data;

	j=im->numTiles;
	data=currentData;
	gDPSetTextureLUT(gp++,G_TT_NONE);
	gDPSetRenderMode(gp++,G_RM_OPA_SURF,G_RM_OPA_SURF2);
	gDPSetCombineMode(gp++,G_CC_DECALRGBA, G_CC_DECALRGBA);
	gSPTexture(gp++,0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON);
	gDPSetTexturePersp(gp++,G_TP_NONE);
	gDPSetAlphaCompare(gp++,G_AC_NONE);
	gDPSetTextureFilter(gp++,G_TF_POINT);

	for(i=0;i<j;i++)
	{
		xx=x+im->data[i*4+0];
		yy=y+im->data[i*4+1];

		// force 4-byte alignment
		data=(unsigned short *)(((int)data+1) & ~1);

		gDPLoadTextureBlock(gp++,
		                (unsigned int)data,
      				G_IM_FMT_RGBA,
 	     			G_IM_SIZ_16b,
				im->data[i*4+2],
				im->data[i*4+3],
				0,
				0,0,
				0,0,
				G_TX_NOLOD,G_TX_NOLOD);

		gSPTextureRectangle(gp++,
			    	(xx<<2),
				(yy<<2),
				(xx+im->data[i*4+2])<<2,
				(yy+im->data[i*4+3])<<2,
			    	G_TX_RENDERTILE,
			    	0,0,1<<10,1<<10);
		data+=(im->data[i*4+2])*(im->data[i*4+3]);
	}

	return(gp);
}

*******/

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

Gfx *RenderBmp(Gfx *gp,int x,int y,int sx,int sy,unsigned char *data)
{
	gDPLoadTextureBlock(gp++,
		        (unsigned int)data,
      			G_IM_FMT_CI,
 	     		G_IM_SIZ_8b,
			sx,
			sy,
			0,
			0,0,
			0,0,
			G_TX_NOLOD,G_TX_NOLOD);

	gSPTextureRectangle(gp++,
			(x<<2),
			(y<<2),
			(x+sx)<<2,
			(y+sy)<<2,
			G_TX_RENDERTILE,
			0,0,1<<10,1<<10);

	return(gp);
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

Gfx *RenderTex(Gfx *gp,texture *t,int x,int y)
{
	gp=RenderBmp(gp,x,y,t->sx,t->sy,*(t->bitmapHandle));
	return(gp);
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

void UpdateDir(int pk)
{
	int i,j,k;

	pakNumFiles[pk]=0;
	pakFreeSpace[pk]=0;
	pakGotGame &= ~(1<<pk);

	fileOffset=0;
	i=CtrlPakReadDirectory(pk);
	if(i<0 && pk==(curCtrlSel-1))
	{
		if(i==-PFS_ERR_ID_FATAL)
		{
			currentState=STATE_ERRORREPAIR;
			optNo=0; numOpts=3; optStrings=corruptOptStrings;
			return;
		}
		else if(i==-PFS_ERR_NEW_PACK)
		{
			CtrlScanSingle(curCtrlSel-1);
			i=CtrlPakReadDirectory(pk);
			if(i<0)
			{
				currentState=STATE_ERROR;
				numOpts=1; optNo=0; optStrings=okOptStrings;
				return;
			}
		}
		else
		{
			return;
		}
	}
	else if(i==-PFS_ERR_ID_FATAL)
	{
//		curCtrlSel=pk+1;
//		currentState=STATE_ERRORREPAIR;
//		optNo=0; numOpts=2; optStrings=corruptOptStrings;
		return;
	}

	for(i=0;i<16;i++)
	{
		if(ctrlPakDirEntries[pk][i].gameCode==gameCode &&
			ctrlPakDirEntries[pk][i].companyCode==companyCode)
		{
			pakGotGame |= (1<<pk);
			pakOurFhs[pk]=i;
		}
		if(ctrlPakDirEntries[pk][i].fileId==-1) break;
	}
	pakNumFiles[pk]=i;

	pakFreeSpace[pk]=CtrlPakQuerySpace(pk);
	if(pakFreeSpace[pk]<0 && pk==(curCtrlSel-1))
	{
		GotoSelectState();  // currentState=STATE_SELECT;
		return;
	}
	pakFreeSpace[pk]/=256;

	if(pakNumFiles[pk]==0 && currentState==STATE_DELETE)
	{
		GotoSelectState();  // currentState=STATE_SELECT;
	}
	pakDirValid |= (1<<pk);
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

int ConfigLocateCurrentPak(int *fh)
{
	int		i,j,k,pk,r;

	CtrlWaitReading();

	// try last selected one!
	for(i=0;i<4;i++)
	{
		pk=((curCtrlSel-1)+i)%4;

		CtrlScanSingle(pk);		//sets motorvalid
		if(!(paksValid & (1<<pk))) continue;

		j=CtrlPakReadDirectory(pk);
		if(j) continue;

		for(j=0;j<16;j++)
		{
			if(ctrlPakDirEntries[pk][j].gameCode==gameCode &&
			   ctrlPakDirEntries[pk][j].companyCode==companyCode)
			{
				break;
			}
		}
		if(j==16) continue;

		// check serial no...
		memset(headerBuffer,0,sizeof(headerBuffer));
		r=CtrlPakReadFile(pk,ctrlPakDirEntries[pk][j].fileId,0,MEMPAK_HEADER_LENGTH,headerBuffer);
		if(r) continue;
		if(*((long *)(&headerBuffer[4])) != currentSerialNo) continue;

		curCtrlSel=pk+1;
		*fh=ctrlPakDirEntries[pk][j].fileId;
		return(pk);
	}

	return(-1);
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/
/********
Gfx *RenderBox(Gfx *gp,int x,int y,int x2,int y2,int r,int g,int b,int a)
{
	x2-=x; y2-=y;
	gp=RenderTBOX(gp,x,y,x2,y2,r,g,b,a);
	return(gp);
}
*****/
/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/






global	int	CheckFirstTimeEverPoweredOn(void)		// from Flash Rom
{
	// Local Variables.

char *     pcl__Temp;
int		i, error;

	pcl__Temp = MemCalloc(FR_PAGE_SIZE_BYTES + 16, MEM_ANY);

	// Read the identifing data from Flash ROM.

	error = ReadFlashRom(FIRST_TIME_DATA_FLASH_PAGE_NUM, 1, (char *) pcl__Temp);

	// Compare the data to the original.

	for(i=0; i< FR_PAGE_SIZE_BYTES; i++)
	{
		if(pcl__Temp[i] != idcomparevalue[i])
		{
			error = 1;
			break;
		}
	}
	
	// Free up the temporary workspace.
	MemFree(pcl__Temp);

	if(error)
	{	// this must be first time on
//		WriteFlashRom(FIRST_TIME_DATA_FLASH_PAGE_NUM, 1, idcomparevalue);
	}


	return(error);
}







/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

