#include <sg_xpt.h>
#include <shinobi.h>
#include <sg_btFnt.h>
#include "test.h"
#include "addr.h"

#define USE_SMPH (0)
#define USE_TEST (0)

#define COLOUR565_WHITE (0xc618)
#define COLOUR565_BLUE  (0x0018)
#define COLOUR565_GREEN (0x0600)
#define COLOUR565_RED   (0xc000)
#define COLOUR565_BLACK (0x0000)

#define BACK_COLOUR565 COLOUR565_WHITE
#define FORE_COLOUR565 COLOUR565_BLACK

void displayLetter( void *addr, SYE_BT_FNT_FONTSET set, Sint16 letter, Sint16 x, Sint16 y );
void displayChar( void *addr, SYE_BT_FNT_FONTSET set, Sint16 letter, Sint16 x, Sint16 y );
void fillBuffer( Uint32 *addr, Uint32 colour, Sint32 size );
void setPoint( Uint16 *offset, Sint32 x, Sint32 y, Uint16 colour );
void setChar( Sint32 x, Sint32 y, Uint16 colour );


void initFntMode( SMS_FNT_MODE fntMode )
{
	void *bootRomAddr;

#if USE_TEST
	bootRomAddr = (void *)(FONT_ADDR+0x20);
#else
	bootRomAddr = syBtFntGet(SYD_BT_FNTINI);
#endif

	fntMode->code = 0x88a4;
	fntMode->currentCode = 0x88a4;
	fntMode->cursor = 0;
	fntMode->currentDrawIndex = 0;
	fntMode->currentFontset = SYE_BT_FNT_FONTSET_JP_LVL2_24;
	fntMode->mode = SMD_FNT_MODE_CHANGE;
	fntMode->bootRomAddr = bootRomAddr;
	fntMode->currentFontset = SYE_BT_FNT_FONTSET_JP_LVL2_24;
}

void chooseFont( SMS_FNT_MODE fntMode )
{
	const PDS_PERIPHERALINFO* info;
	const PDS_PERIPHERAL* per;

	per = pdGetPeripheral(PDD_PORT_A0);

	/* コントローラが接続されているかどうかの判別 */
	if (!(per->info->type & PDD_DEVTYPE_CONTROLLER)) {
		return;
	}

	if( per->press & NJD_DGT_KR ) {
		(fntMode->cursor)++;
		if( fntMode->cursor >= 5 ) {
			fntMode->cursor = 0;
		}
	} else {
		if( per->press & NJD_DGT_KL ) {
			if( fntMode->cursor == 0 ) {
				fntMode->cursor = 4;
			} else {
				fntMode->cursor--;
			}
		}
	}

	switch( fntMode->cursor ) {
	case 1:
	case 2:
	case 3:
	case 4:
		if( per->press & NJD_DGT_KU ) {
			if( fntMode->currentCode == 0xffff ) {
				fntMode->currentCode = 0x0000;
			} else {
				fntMode->currentCode+=0x0001 << ((4-fntMode->cursor)*4);
			}
		} else {
			if( per->press & NJD_DGT_KD ) {
				if( fntMode->currentCode == 0x0000 ) {
					fntMode->currentCode = 0xffff;
				} else {
					fntMode->currentCode-=0x0001 << ((4-fntMode->cursor)*4);
				}
			}
		}
		break;
	case 0:
	default:
		if( per->press & NJD_DGT_KU ) {
			switch( fntMode->currentFontset ) {
			case SYE_BT_FNT_FONTSET_WESTERN_24:
				fntMode->currentFontset = SYE_BT_FNT_FONTSET_VMSICON;
				break;
			case SYE_BT_FNT_FONTSET_JP_JIS_24:
				fntMode->currentFontset = SYE_BT_FNT_FONTSET_WESTERN_24;
				break;
			case SYE_BT_FNT_FONTSET_JP_LVL2_24:
				fntMode->currentFontset = SYE_BT_FNT_FONTSET_JP_JIS_24;
				break;
			case SYE_BT_FNT_FONTSET_JP_GAIJ_24:
				fntMode->currentFontset = SYE_BT_FNT_FONTSET_JP_LVL2_24;
				break;
			case SYE_BT_FNT_FONTSET_VMSICON:
				fntMode->currentFontset = SYE_BT_FNT_FONTSET_JP_GAIJ_24;
				break;
			default:
				fntMode->currentFontset = SYE_BT_FNT_FONTSET_JP_LVL2_24;
				break;
			}
		} else {
			if( per->press & NJD_DGT_KD ) {
				switch( fntMode->currentFontset ) {
				case SYE_BT_FNT_FONTSET_WESTERN_24:
					fntMode->currentFontset = SYE_BT_FNT_FONTSET_JP_JIS_24;
					break;
				case SYE_BT_FNT_FONTSET_JP_JIS_24:
					fntMode->currentFontset = SYE_BT_FNT_FONTSET_JP_LVL2_24;
					break;
				case SYE_BT_FNT_FONTSET_JP_LVL2_24:
					fntMode->currentFontset = SYE_BT_FNT_FONTSET_JP_GAIJ_24;
					break;
				case SYE_BT_FNT_FONTSET_JP_GAIJ_24:
					fntMode->currentFontset = SYE_BT_FNT_FONTSET_VMSICON;
					break;
				case SYE_BT_FNT_FONTSET_VMSICON:
					fntMode->currentFontset = SYE_BT_FNT_FONTSET_WESTERN_24;
					break;
				default:
					fntMode->currentFontset = SYE_BT_FNT_FONTSET_JP_LVL2_24;
					break;
				}
			}
		}
		break;
	}

	if( per->press & NJD_DGT_TA ) {
		fntMode->code = fntMode->currentCode;
		fntMode->fontset = fntMode->currentFontset;
		fntMode->mode = SMD_FNT_MODE_CHANGE;
	}
}

void displayFont( SMS_FNT_MODE fntMode )
{
	Sint32 chooseX, chooseY;
	Sint32 displayX, displayY;
	char *text[] = {
		"WESTERN_24",			/* 0 */
		"JP_JIS_24",			/* 1 */
		"JP_KANA_24",			/* 2 */
		"JP_LVL1_24",			/* 3 */
		"JP_LVL2_24",			/* 4 */
		"JP_GAIJ_24",			/* 5 */
		"VMSICON_32",			/* 6 */
		"UNKNOWN" };

	chooseX = 3; chooseY = 4;
	displayX = 5; displayY = 19;

	switch( fntMode->currentFontset ) {
	case SYE_BT_FNT_FONTSET_WESTERN_24:
		njPrintC( NJM_LOCATION( chooseX, chooseY ), "*" );
		break;
	case SYE_BT_FNT_FONTSET_JP_JIS_24:
		njPrintC( NJM_LOCATION( chooseX, chooseY+1 ), "*" );
		break;
	case SYE_BT_FNT_FONTSET_JP_LVL2_24:
		njPrintC( NJM_LOCATION( chooseX, chooseY+2 ), "*" );
		break;
	case SYE_BT_FNT_FONTSET_JP_GAIJ_24:
		njPrintC( NJM_LOCATION( chooseX, chooseY+3 ), "*" );
		break;
	case SYE_BT_FNT_FONTSET_VMSICON:
		njPrintC( NJM_LOCATION( chooseX, chooseY+4 ), "*" );
		break;
	default:
		break;
	}

	njPrintC( NJM_LOCATION( chooseX+2, chooseY ), text[0] );
	njPrintC( NJM_LOCATION( chooseX+2, chooseY+1 ), text[1] );
	njPrintC( NJM_LOCATION( chooseX+2, chooseY+2 ), text[4] );
	njPrintC( NJM_LOCATION( chooseX+2, chooseY+3 ), text[5] );
	njPrintC( NJM_LOCATION( chooseX+2, chooseY+4 ), text[6] );

	if( fntMode->cursor == 0 ) {
		njPrintC( NJM_LOCATION( chooseX, chooseY-1 ), "=" );
		njPrintC( NJM_LOCATION( chooseX, chooseY+4+1 ), "=" );
	} else {
		njPrintC( NJM_LOCATION( chooseX+16+1+fntMode->cursor, chooseY+1-1 ), "=" );
		njPrintC( NJM_LOCATION( chooseX+16+1+fntMode->cursor, chooseY+1+1 ), "=" );
	}

	njPrintC( NJM_LOCATION( chooseX+16+1, chooseY+1 ), "[" );
	njPrintH( NJM_LOCATION( chooseX+16+2, chooseY+1 ), fntMode->currentCode, 4 );
	njPrintC( NJM_LOCATION( chooseX+16+6, chooseY+1 ), "]" );

	njPrintC( NJM_LOCATION( displayX, displayY ), " set=" );
	if( fntMode->fontset >= SYE_BT_FNT_FONTSET_END ) {
		njPrintC( NJM_LOCATION( displayX+5, displayY ), text[8] );
	} else {
		njPrintC( NJM_LOCATION( displayX+5, displayY ), text[fntMode->fontset] );
	}
	njPrintC( NJM_LOCATION( displayX, displayY+1 ), "code=" );
	njPrintH( NJM_LOCATION( displayX+5, displayY+1 ), fntMode->code, 4 );

	switch( fntMode->mode ) {
	case SMD_FNT_MODE_CHANGE:
		fillBuffer( (Uint32 *)kanjiBuffPtr, COLOUR565_WHITE<<16|COLOUR565_WHITE, KANJI_BUFF_SIZE/4 );
		displayLetter( fntMode->bootRomAddr, fntMode->fontset, fntMode->code, 0, 0 );
		njReLoadTextureNum( fntMode->currentDrawIndex?0:1, kanjiBuffPtr,
			NJD_TEXATTR_TYPE_MEMORY,0);
		fntMode->mode = SMD_FNT_MODE_FLIP;
		break;
	case SMD_FNT_MODE_FLIP:
		fntMode->currentDrawIndex = fntMode->currentDrawIndex?0:1;
		fntMode->mode = SMD_FNT_MODE_STATIC;
		break;
	case SMD_FNT_MODE_INIT:
	case SMD_FNT_MODE_STATIC:
	default:
		break;
	}

	displayChar( fntMode->bootRomAddr, fntMode->fontset, fntMode->code, 27, 4 );

	njDrawTexture( poly, 4, fntMode->currentDrawIndex, FALSE );

	return;
}

void displayLetter( void *fntAddr, SYE_BT_FNT_FONTSET set, Sint16 letter, Sint16 x, Sint16 y )
{
	Uint8 *addr;
	Sint32 i, j, count;
	SYS_BT_FNT_INFO fontinfo;
	Uint8 c;

	syBtFntGetInfo( set, letter, &fontinfo );
	addr = (Uint8 *)fntAddr;
	addr += syBtFntGetAddr( set, letter );

	if( syBtFntChkSmph() == SYD_BT_FNT_SMPH_SUCCESS ) {
		count = 0;
		for( i=0; count<(fontinfo.height)*(fontinfo.width); i++ ) {
			c = *(addr++);
			for( j=0; j<8; j++ ) {
				setPoint( kanjiBuffPtr, x+(count%fontinfo.width), y+(count/fontinfo.width), ((c & 0x80)!=0)?BACK_COLOUR565:FORE_COLOUR565 );
				c<<=1;
				count++;
				if( count >= (fontinfo.width)*(fontinfo.height) ) {
					break;
				}
			}
		}
		syBtFntClrSmph();
	} else {
		njPrintC( NJM_LOCATION(10, 3), "KANJI SEMAPHORE ERROR!" );
	}

	return;
}

void displayChar( void *fntAddr, SYE_BT_FNT_FONTSET set, Sint16 letter, Sint16 x, Sint16 y )
{
	Uint8 *addr;
	Sint32 i, j, count;
	SYS_BT_FNT_INFO fontinfo;
	Uint8 c;

	syBtFntGetInfo( set, letter, &fontinfo );
	addr = (Uint8 *)fntAddr;
	addr += syBtFntGetAddr( set, letter );

#if USE_SMPH
	if( syBtFntChkSmph() == SYD_BT_FNT_SMPH_SUCCESS ) {
#endif
		count = 0;
		for( i=0; count<(fontinfo.height)*(fontinfo.width); i++ ) {
			c = *(addr++);
			for( j=0; j<8; j++ ) {
				setChar( x+(count%fontinfo.width), y+(count/fontinfo.width), ((c & 0x80)!=0)?BACK_COLOUR565:FORE_COLOUR565 );
				c<<=1;
				count++;
				if( count >= (fontinfo.width)*(fontinfo.height) ) {
					break;
				}
			}
		}
#if USE_SMPH
		syBtFntClrSmph();
	} else {
		njPrintC( NJM_LOCATION(10, 3), "KANJI SEMAPHORE ERROR!" );
	}
#endif

	return;
}

void fillBuffer( Uint32 *addr, Uint32 colour, Sint32 size )
{
	Sint32 i;
	for( i=0; i<size; i++ ) {
		*addr++ = colour;
	}
}

void setPoint( Uint16 *offset, Sint32 x, Sint32 y, Uint16 colour )
{
	Uint16 *addr;

	addr = offset + y * KANJI_BUFF_W + x;
	*addr = colour;
}

void setChar( Sint32 x, Sint32 y, Uint16 colour )
{
	if( colour == BACK_COLOUR565 ) {
		njPrintC( NJM_LOCATION(x,y), "0" );
	} else {
		njPrintC( NJM_LOCATION(x,y), "1" );
	}
}
