/*----------------------------------------------------------------------

    Primitive2D application main sample

    Copyright (C) 2008 SEGA Corporation Creative Center Graphics Sect.
    All Rights Reserved.

    Module  : Primitive2D application main sample
    File    : smpapp.cpp
    Create  : 2008/07/23 (Ver.0.30.01)
    Modify  : 2008/08/06 (Ver.0.80.01)
	            ２Ｄのライン描画、２Ｄのポイント描画の高速化
			  2008/11/04 (Ver.0.80.02)
                nnExitVertexBufferDXG20 の記述忘れ。
			  2008/11/14 (Ver.0.80.03)
			    プラットフォーム別処理関数を smpmain.cpp へ移動した。
				nnGetDirect3DDeviceDXG20 に変更。
				D3DUSAGE_DYNAMIC を D3DUSAGE_WRITEONLY に変更。
			  2008/12/12 (Ver.0.80.04)
				D3DUSAGE_WRITEONLY を D3DUSAGE_DYNAMIC に変更(2008/11/14の変更をもとに戻した)。
			  2009/01/19 (Ver.0.80.05)
	            smpSetIncludePathDXG20 関数を追加。
			  2009/01/21 (Ver.0.80.06)
			    nnSetCompileErrorCallbackStdShaderDXG20 関数を追加。
			  2009/04/14 (Ver.0.80.07)
			    ブレンド拡張関数を追加(nnSetPrimitive2DBlendDXG20)。
			  2009/06/11 (Ver.0.80.08)
			    プラットフォーム別処理関数(IDirect3DDevice9_CreateVertexBuffer, IDirect3DVertexBuffer9_Release)を smpmain.cpp へ移動した。
	Version : 0.80.08
    Note    : 
----------------------------------------------------------------------*/

#define __SMPAPP_CPP__

//--------------------
// 組み込みファイル名
//--------------------
#include "smpapp.h"
#include "smputil.h"

#include "smpdata.h"

////////////////////////////////////////////////////////////////////////////////
#define SAMPLENAME "PRIMITIVE2D"

#define DEBUG_CHAR_MAX	(1200)

////////////////////////////////////////////////////////////////////////////////
NNS_MATRIXSTACK			gMtxStack;				// マトリクススタック

static void				*pPrintBuf;				// デバッグ文字用バッファ(メモリの解放が必要)

static void				*pMtxStackBuf;			// マトリクススタックバッファ先頭(メモリの解放が必要)

// 標準シェーダ用
static void				*pShaderMgrBuf;			// シェーダーマネージャバッファ領域(メモリの解放が必要)
static Uint32			VsCodeSize;				// 頂点シェーダコードサイズ
static Uint32			PsCodeSize;				// ピクセルシェーダコードサイズ
static void				*pVsCodeBuf;			// 頂点シェーダコードバッファ領域(メモリの解放が必要)
static void				*pPsCodeBuf;			// ピクセルシェーダコードバッファ領域(メモリの解放が必要)

static SMPPAD_STATUS	*pPad1, *pPad2;			// コントローラ情報

//------------------------------------------------------------------------------
// データ用

static void				*pTexListBuf0;			// TEXFILELIST0用テクスチャ情報領域用バッファ(メモリの解放が必要)
static NNS_TEXLIST		*pTexList0;				// TEXLIST0(メモリの解放が必要)

// プリミティブデータ
#define	PRIM_NUM	10
#define	TEX_VNUM	4
#define	POLY_VNUM	4
#define	LINE_VNUM	8
#define	POINT_VNUM	16
static	NNS_PRIM2D_PCT	gPrimTex[PRIM_NUM][TEX_VNUM];
static	NNS_PRIM2D_PC	gPrimPoly[PRIM_NUM][POLY_VNUM];
static	NNS_PRIM2D_P	gPrimLine[PRIM_NUM][LINE_VNUM];
static	NNS_PRIM2D_P	gPrimPoint[PRIM_NUM][POINT_VNUM];
static	NNS_RGBA	gPrimColor[PRIM_NUM] = {
	{ 1.00f, 0.00f, 0.00f, 1.00f },
	{ 0.98f, 0.54f, 0.00f, 1.00f },
	{ 1.00f, 0.95f, 0.00f, 1.00f },
	{ 0.17f, 0.98f, 0.00f, 1.00f },
	{ 0.00f, 0.98f, 0.51f, 1.00f },
	{ 0.00f, 0.83f, 0.98f, 1.00f },
	{ 0.00f, 0.21f, 0.98f, 1.00f },
	{ 0.49f, 0.00f, 0.98f, 1.00f },
	{ 0.98f, 0.00f, 0.90f, 1.00f },
	{ 0.98f, 0.00f, 0.39f, 1.00f }
};

// プリミティブデータ管理情報
typedef struct {
	Sint32			vnum;		// 頂点数
	void			*pVtx;		// 頂点データへのポインタ
} SMP_PRIM_VERTEX;

typedef struct {
	Sint32			pnum;		// 頂点リスト数
	SMP_PRIM_VERTEX	*pPrim;		// 頂点リストへのポインタ
} SMP_PRIM_DATA;

// 描画プリミティブタイプ
static	enum {
	PRIM_TEX,
	PRIM_POLY,
	PRIM_LINE,
	PRIM_POINT
} gPrimType = PRIM_TEX;

static Float gAlpha = 1.0f;

////////////////////////////////////////////////////////////////////////////////
// ブレンド関数
typedef
	struct{
		NNE_BLENDMODE	m_func;
		char			*m_pFuncString;
	} SMP_PRIM_BLEND_FUNC;

static SMP_PRIM_BLEND_FUNC g_pBlendFuncTbl[] = {
	NNE_BLENDMODE_ZERO,        "ZERO (0, 0, 0, 0)",
	NNE_BLENDMODE_ONE,         "ONE (1, 1, 1, 1)",
	NNE_BLENDMODE_SRCCOL,      "SRCCOL (Rs, Gs, Bs, As)",
	NNE_BLENDMODE_INVSRCCOL,   "INVSRCCOL (1-Rs, 1-Gs, 1-Bs, 1-As)",
	NNE_BLENDMODE_SRCALPHA,    "SRCALPHA (As, As, As, As)",
	NNE_BLENDMODE_INVSRCALPHA, "INVSRCALPHA (1-As, 1-As, 1-As, 1-As)",
	NNE_BLENDMODE_DSTALPHA,    "DSTALPHA (Ad, Ad, Ad, Ad)",
	NNE_BLENDMODE_INVDSTALPHA, "INVDSTALPHA (1-Ad, 1-Ad, 1-Ad, 1-Ad)",
	NNE_BLENDMODE_DSTCOL,      "DSTCOL (Rd, Gd, Bd, Ad)",
	NNE_BLENDMODE_INVDSTCOL,   "INVDSTCOL (1-Rd, 1-Gd, 1-Bd, 1-Ad)",
	NNE_BLENDMODE_SRCALPHASAT, "SRCALPHASAT (f, f, f, 1)、f = min(A, 1-Ad)"
};
static const Uint32 gNbBlendFunc = sizeof(g_pBlendFuncTbl) / sizeof(g_pBlendFuncTbl[0]);

// ブレンド計算式
typedef
	struct{
		NNE_BLENDOP	m_op;
		char		*m_pOpString;
	} SMP_PRIM_BLEND_OP;

static SMP_PRIM_BLEND_OP g_pBlendOpTbl[] = {
	NNE_BLENDOP_ADD,    "ADD (Src + Dest)",
	NNE_BLENDOP_SUB,    "SUB (Src - Dest)",
	NNE_BLENDOP_REVSUB, "REVSUB (Dest - Src)",
	NNE_BLENDOP_MIN,    "MIN (MIN( Src, Dest ))",
	NNE_BLENDOP_MAX,    "MAX (MAX( Src, Dest ))"
};
static const Uint32 gNbBlendOp = sizeof(g_pBlendOpTbl) / sizeof(g_pBlendOpTbl[0]);

// 初期化
static NNE_BOOL gDXG20Blend      = NNE_FALSE;
static Sint32   gBlendFuncSrcNum = 4;
static Sint32   gBlendFuncDstNum = 5;
static Sint32   gBlendOpNum      = 0;

////////////////////////////////////////////////////////////////////////////////
//-------------
// NN の初期化
//-------------
static void InitNN(void)
{
	// デバッグプリント初期化
	Uint32 size;
	size      = nnGetPrintBufferSize( DEBUG_CHAR_MAX );
	pPrintBuf = smpMemAlloc( size );
	nnInitPrint( pPrintBuf, DEBUG_CHAR_MAX, NULL );

	// マトリクススタック領域の確保、設定
	pMtxStackBuf = smpMemAlloc( MATRIX_STACK_SIZE * sizeof( NNS_MATRIX ) );
	nnSetUpMatrixStack( &gMtxStack, pMtxStackBuf, MATRIX_STACK_SIZE );

	// 標準シェーダーの初期化
	{
		NNS_STDSHADER_CONFIG shaderconfig;
		Uint32				 size;

		// 標準シェーダマネージャの初期化
        // 
		nnSetUpStdShaderConfigBasic( &shaderconfig );
		shaderconfig.bNormalizeVertexNormal	= NNE_TRUE;					// 頂点法線正規化
		//shaderconfig.bRescaleVertexNormal	= NNE_TRUE;					// 頂点法線再スケール
		shaderconfig.nMaxParallelLight		= 0;						// パラレルライト最大数
		shaderconfig.nMaxPointLight			= 0;						// ポイントライト最大数
		shaderconfig.nMaxSpotLight			= 0;						// スポットライト最大数
		shaderconfig.bLightAmbient			= NNE_FALSE;				// ライトアンビエント
		shaderconfig.PointLightDistAtten	= NNE_ATTEN_CONSTANT;		// ポイントライト距離減衰モデル
		//shaderconfig.PointLightDistAtten	= NNE_ATTEN_INVLINEAR;
		//shaderconfig.PointLightDistAtten	= NNE_ATTEN_INVQUADRATIC;
		shaderconfig.SpotLightDistAtten		= NNE_ATTEN_CONSTANT;		// スポットライト距離減衰モデル
		//shaderconfig.SpotLightDistAtten	= NNE_ATTEN_INVLINEAR;
		//shaderconfig.SpotLightDistAtten	= NNE_ATTEN_INVQUADRATIC;
		shaderconfig.FogModel				= NNE_FOG_NONE;				// フォグモデル
		//shaderconfig.FogModel				= NNE_FOG_LINEAR;
		//shaderconfig.FogModel				= NNE_FOG_EXP;
		//shaderconfig.FogModel				= NNE_FOG_EXP2;
		shaderconfig.bDistanceFog			= NNE_FALSE;				// 距離フォグ or Z値フォグ
		shaderconfig.bFragmentFog			= NNE_FALSE;				// フラグメントフォグ
		// 
		size = nnCalcStdShaderManageBufferSize( STDSHADER_NUM );
		pShaderMgrBuf = smpMemAlloc( size );
		nnConfigureStdShader( &shaderconfig,  pShaderMgrBuf, STDSHADER_NUM );

        // 標準シェーダコードのロード
        // 頂点シェーダ
		VsCodeSize = smpGetFileSize( STDVSPATH );
		pVsCodeBuf = smpMemAlloc( VsCodeSize );
		smpReadFile( STDVSPATH, pVsCodeBuf );
        // ピクセルシェーダー
		PsCodeSize = smpGetFileSize( STDPSPATH );
		pPsCodeBuf = smpMemAlloc( PsCodeSize );
		smpReadFile( STDPSPATH, pPsCodeBuf );
	}

    // 
	smpBinSetFilePath( BINPATH );
	smpTexSetFilePath( TEXPATH );

	// サンプル用パッドライブラリ初期化
	smpPadInit();
	pPad1 = smpPadGet( SMPPAD_PORT1 );	// １番ポート
	pPad2 = smpPadGet( SMPPAD_PORT2 );	// ２番ポート

	// サンプル用タイマライブラリ初期化
	smpTmrInit();
}

//------------------------
// サンプルデータのロード
//------------------------
static void LoadImage(void)
{
	Sint32 num;

	// テクスチャリスト領域の確保 (TEXFILELIST0用)
	num = TEXFILELIST0->nTex;	// テクスチャ数
	pTexListBuf0 = smpMemAlloc( (Uint32)nnEstimateTexlistSize(num) );

	// テクスチャリストの初期化
	nnSetUpTexlist( &pTexList0, num, pTexListBuf0 );

	// テクスチャのロード、テクスチャ情報の設定 (TEXFILELIST0用)
	if( smpTexLoadFile( pTexList0, TEXFILELIST0 ) < 0 ){
		while(1){}	// Texture file read error
	}
}

//----------------------
// 標準シェーダーの作成
//----------------------
static void BuildStdShader(void)
{
	// シェーダのインクルードのパス設定
	smpSetIncludePathDXG20(STDINCPATH);
#if OUTPUT_COMPILE_SHADER_ERROR
	// シェーダのコンパイルエラーコールバック関数の設定
	nnSetCompileErrorCallbackStdShaderDXG20(smpOutputCompileShaderErrorDXG20);
#endif
	// シェーダ作成
	nnBuildStdShader( (const char*)pVsCodeBuf, VsCodeSize,
					  (const char*)pPsCodeBuf, PsCodeSize );
}

//--------
// 初期化
//--------
void UserInit( void )
{
	pPrintBuf			= NULL;

	pMtxStackBuf		= NULL;

	{	// 標準シェーダ
		pShaderMgrBuf	= NULL;
		VsCodeSize		= 0;
		PsCodeSize		= 0;
		pVsCodeBuf		= NULL;
		pPsCodeBuf		= NULL;
	}
	{	// コントローラ
		pPad1			= NULL;
		pPad2			= NULL;
	}
	//
	InitNN();
	//
	LoadImage();
	//
	BuildStdShader();
}

//------
// 終了
//------
void UserExit(void)
{
	// テクスチャの解放 (TEXLIST0用)
	if(pTexList0 != NULL){
		if ( smpTexRelease( pTexList0 ) < 0 ){
			while(1){}	// Texture release error
		}
	}
	// テクスチャ情報領域の解放 (TEXLIST0用)
	smpMemFree( pTexListBuf0 );

	{	// シェーダの開放
		nnReleaseStdShader();			// ビルド済みシェーダ解放
		nnClearStdShaderProfiles();		// 登録済みシェーダの開放

		// シェーダーコード領域の開放
		smpMemFree( pPsCodeBuf );
		smpMemFree( pVsCodeBuf );

		// シェーダーマネージャー領域の開放
		smpMemFree( pShaderMgrBuf );
	}

	// マトリクススタック領域の解放
	smpMemFree( pMtxStackBuf );

	// デバッグプリントの終了
	nnExitPrint();
	smpMemFree( pPrintBuf );
}

//------------------------
// デバイスの消失時の処理
//------------------------
void UserDeviceLost(void)
{
	UserExit();
}

//--------------------------
// デバイスのリストアの処理
//--------------------------
void UserDeviceReset(void)
{
	UserInit();
}

//----------
// サンプル
//----------
static void CreateVertex( Float x, Float y, Float alpha )
{
	Sint32	i, j;
	Float	scale;
	NNS_RGBA8888	col;
	#define	_WIDTH	240.0f
	#define	_RGBA8888( r, g, b, a )	(((((Uint32)(r*255))&0xFF) << 24)	\
								   | ((((Uint32)(g*255))&0xFF) << 16)	\
								   | ((((Uint32)(b*255))&0xFF) <<  8)	\
								   | ((((Uint32)(a*255))&0xFF) <<  0))

	for( i = 0; i < PRIM_NUM; i++ )
	{
		gPrimColor[i].a = alpha;
	}

	for( i = 0, scale = 1.0f; i < PRIM_NUM; i++, scale -= 0.1f )
	{
		/* Polygon */
		col = _RGBA8888( gPrimColor[i].r, gPrimColor[i].g, gPrimColor[i].b, gPrimColor[i].a );
		gPrimPoly[i][0].Pos.x = 200.f + ((308.f - 200.f) / (PRIM_NUM - 1) * i) + ((x - 320.0f) / (PRIM_NUM - 1) * i);
		gPrimPoly[i][0].Pos.y = 120.f + ((228.f - 120.f) / (PRIM_NUM - 1) * i) + ((y - 240.0f) / (PRIM_NUM - 1) * i);
		gPrimPoly[i][0].Col   = col;

		gPrimPoly[i][1].Pos.x = gPrimPoly[i][0].Pos.x + _WIDTH * scale;
		gPrimPoly[i][1].Pos.y = gPrimPoly[i][0].Pos.y;
		gPrimPoly[i][1].Col   = col;

		gPrimPoly[i][2].Pos.x = gPrimPoly[i][0].Pos.x;
		gPrimPoly[i][2].Pos.y = gPrimPoly[i][0].Pos.y + _WIDTH * scale;
		gPrimPoly[i][2].Col   = col;

		gPrimPoly[i][3].Pos.x = gPrimPoly[i][0].Pos.x + _WIDTH * scale;
		gPrimPoly[i][3].Pos.y = gPrimPoly[i][0].Pos.y + _WIDTH * scale;
		gPrimPoly[i][3].Col   = col;

		/* Polygon with UV */
		gPrimTex[i][0].Pos.x = gPrimPoly[i][0].Pos.x;
		gPrimTex[i][0].Pos.y = gPrimPoly[i][0].Pos.y;
		gPrimTex[i][0].Col   = gPrimPoly[i][0].Col;
		gPrimTex[i][0].Tex.u = 0.0f;
		gPrimTex[i][0].Tex.v = 0.0f;

		gPrimTex[i][1].Pos.x = gPrimPoly[i][1].Pos.x;
		gPrimTex[i][1].Pos.y = gPrimPoly[i][1].Pos.y;
		gPrimTex[i][1].Col   = gPrimPoly[i][1].Col;
		gPrimTex[i][1].Tex.u = 1.0f;
		gPrimTex[i][1].Tex.v = 0.0f;

		gPrimTex[i][2].Pos.x = gPrimPoly[i][2].Pos.x;
		gPrimTex[i][2].Pos.y = gPrimPoly[i][2].Pos.y;
		gPrimTex[i][2].Col   = gPrimPoly[i][2].Col;
		gPrimTex[i][2].Tex.u = 0.0f;
		gPrimTex[i][2].Tex.v = 1.0f;

		gPrimTex[i][3].Pos.x = gPrimPoly[i][3].Pos.x;
		gPrimTex[i][3].Pos.y = gPrimPoly[i][3].Pos.y;
		gPrimTex[i][3].Col   = gPrimPoly[i][3].Col;
		gPrimTex[i][3].Tex.u = 1.0f;
		gPrimTex[i][3].Tex.v = 1.0f;

		/* Line */
		gPrimLine[i][0].Pos.x = gPrimPoly[i][0].Pos.x;
		gPrimLine[i][0].Pos.y = gPrimPoly[i][0].Pos.y;
		gPrimLine[i][1].Pos.x = gPrimPoly[i][1].Pos.x;
		gPrimLine[i][1].Pos.y = gPrimPoly[i][1].Pos.y;

		gPrimLine[i][2].Pos.x = gPrimPoly[i][1].Pos.x;
		gPrimLine[i][2].Pos.y = gPrimPoly[i][1].Pos.y;
		gPrimLine[i][3].Pos.x = gPrimPoly[i][3].Pos.x;
		gPrimLine[i][3].Pos.y = gPrimPoly[i][3].Pos.y;

		gPrimLine[i][4].Pos.x = gPrimPoly[i][3].Pos.x;
		gPrimLine[i][4].Pos.y = gPrimPoly[i][3].Pos.y;
		gPrimLine[i][5].Pos.x = gPrimPoly[i][2].Pos.x;
		gPrimLine[i][5].Pos.y = gPrimPoly[i][2].Pos.y;

		gPrimLine[i][6].Pos.x = gPrimPoly[i][2].Pos.x;
		gPrimLine[i][6].Pos.y = gPrimPoly[i][2].Pos.y;
		gPrimLine[i][7].Pos.x = gPrimPoly[i][0].Pos.x;
		gPrimLine[i][7].Pos.y = gPrimPoly[i][0].Pos.y;

		/* Point */
		for( j = 0; j < 4; j++ )
		{
			gPrimPoint[i][j +  0].Pos.x = gPrimPoly[i][0].Pos.x + (_WIDTH * scale / 4 * j);
			gPrimPoint[i][j +  0].Pos.y = gPrimPoly[i][0].Pos.y;

			gPrimPoint[i][j +  4].Pos.x = gPrimPoly[i][1].Pos.x;
			gPrimPoint[i][j +  4].Pos.y = gPrimPoly[i][1].Pos.y + (_WIDTH * scale / 4 * j);

			gPrimPoint[i][j +  8].Pos.x = gPrimPoly[i][3].Pos.x - (_WIDTH * scale / 4 * j);
			gPrimPoint[i][j +  8].Pos.y = gPrimPoly[i][3].Pos.y;

			gPrimPoint[i][j + 12].Pos.x = gPrimPoly[i][2].Pos.x;
			gPrimPoint[i][j + 12].Pos.y = gPrimPoly[i][2].Pos.y - (_WIDTH * scale / 4 * j);
		}
	}
}
static void Sample(void)
{
	Sint32	i;
	Float	Pri, PriAdd;
	static	Float	px = 320.0f, py = 240.0f;
	static	Float	mx = 3.0f, my = 3.0f;

	/* プライオリティタイプ */
	static	enum {
		SORT_DOWN,
		SORT_UP
	} PriSort = SORT_UP;

	/* パッド情報更新 */
	smpPadCheck();

	/* プリミティブタイプの切り替え */
	if( pPad1->Press & SMPPAD_BTN_A )
	{
		switch( gPrimType )
		{
			case PRIM_TEX:   gPrimType = PRIM_POLY;  break;
			case PRIM_POLY:  gPrimType = PRIM_LINE;  break;
			case PRIM_LINE:  gPrimType = PRIM_POINT; break;
			case PRIM_POINT: gPrimType = PRIM_TEX;   break;
		}
	}

	/* プライオリティタイプの切り替え */
	if( pPad1->Press & SMPPAD_BTN_B )
	{
		if( PriSort == SORT_UP )
			PriSort = SORT_DOWN;
		else
			PriSort = SORT_UP;
	}

	if( PriSort == SORT_UP )
	{
		Pri    = -10.0f;
		PriAdd = 1.0f;
	}
	else
	{
		Pri    = -1.0f;
		PriAdd = -1.0f;
	}

	/* アルファ値の変更 */
	if( pPad1->On & SMPPAD_BTN_U )	gAlpha += 0.01f;
	if( pPad1->On & SMPPAD_BTN_D )	gAlpha -= 0.01f;
	if( gAlpha < 0.0f )	gAlpha = 0.0f;
	if( gAlpha > 1.0f )	gAlpha = 1.0f;

	/* データ作成 */
	px += mx;
	if( (px < 0.0f) || (px > 640.0f) )
		mx *= -1.0f;
	py += my;
	if( (py < 0.0f) || (py > 480.0f) )
		my *= -1.0f;
	CreateVertex( px, py, gAlpha );

	{
		/* DXG20 のブレンド拡張[有効／無効] */
		if ( pPad1->Press & SMPPAD_BTN_TR ){
			gDXG20Blend = (NNE_BOOL)((Uint32)gDXG20Blend ^ (Uint32)NNE_TRUE);
		}
		/* ソースのブレンド関数を変更 */
		if ( pPad1->Press & SMPPAD_BTN_R ){
			gBlendFuncSrcNum++;
			gBlendFuncSrcNum %= gNbBlendFunc;
		} else if ( pPad1->Press & SMPPAD_BTN_L ){
			gBlendFuncSrcNum--;
			if(gBlendFuncSrcNum < 0) gBlendFuncSrcNum = gNbBlendFunc-1;
		}
		/* デストのブレンド関数を変更 */
		if ( pPad1->Press & SMPPAD_BTN_X ){
			gBlendFuncDstNum++;
			gBlendFuncDstNum %= gNbBlendFunc;
		} else if ( pPad1->Press & SMPPAD_BTN_Y ){
			gBlendFuncDstNum--;
			if(gBlendFuncDstNum < 0) gBlendFuncDstNum = gNbBlendFunc-1;
		}
		/* ブレンド計算式を変更 */
		if ( pPad1->Press & SMPPAD_BTN_TL ){
			gBlendOpNum++;
			gBlendOpNum %= gNbBlendOp;
		}
	}

	/* ブレンディング設定 */
	if(gDXG20Blend == NNE_FALSE){
		nnSetPrimitiveBlend( NNE_PRIM_BLEND_BLEND );
	} else{
		nnSetPrimitive2DBlendDXG20( g_pBlendFuncTbl[gBlendFuncSrcNum].m_func, g_pBlendFuncTbl[gBlendFuncDstNum].m_func, g_pBlendOpTbl[gBlendOpNum].m_op);
	}

	switch( gPrimType )
	{
		/* ポリゴンテクスチャの描画 */
		case PRIM_TEX:
			nnSetPrimitiveTexNum( pTexList0, 0 );
			nnSetPrimitiveTexState( NNE_PRIM_TEXBLEND_MODULATE, NNE_PRIM_TEXCOORD_UV,
									NNE_PRIM_TEXWRAP_REPEAT, NNE_PRIM_TEXWRAP_REPEAT );

			nnBeginDrawPrimitive2D( NNE_PRIM2D_FMT_PCT, NNE_PRIM_ALPHABLEND_ON );
			for( i = 0; i < PRIM_NUM; i++ )
			{
				nnDrawPrimitive2D( NNE_PRIM_TRIANGLE_STRIP, gPrimTex[i], TEX_VNUM, Pri + PriAdd * i );
			}
			nnEndDrawPrimitive2D();
			break;

		/* ポリゴンの描画 */
		case PRIM_POLY:
			nnBeginDrawPrimitive2D( NNE_PRIM2D_FMT_PC, NNE_PRIM_ALPHABLEND_ON );
			for( i = 0; i < PRIM_NUM; i++ )
			{
				nnDrawPrimitive2D( NNE_PRIM_TRIANGLE_STRIP, gPrimPoly[i], POLY_VNUM, Pri + PriAdd * i );
			}
			nnEndDrawPrimitive2D();
			break;

		/* ラインの描画 */
		case PRIM_LINE:
#if 0 /* 2008.08.06 */
			for( i = 0; i < PRIM_NUM; i++ )
			{
				nnBeginDrawPrimitiveLine2D( &gPrimColor[i], NNE_PRIM_ALPHABLEND_ON );
				nnDrawPrimitiveLine2D( NNE_PRIM_LINE_STRIP, gPrimLine[i], LINE_VNUM, Pri + PriAdd * i );
				nnEndDrawPrimitiveLine2D();
			}
#else
			/* 高速 */
			nnGetRegModeDrawPrimitiveDXG20();
			for( i = 0; i < PRIM_NUM; i++ )
			{
				nnBeginDrawPrimitiveLine2DDXG20( &gPrimColor[i], NNE_PRIM_ALPHABLEND_ON );
				nnDrawPrimitiveLine2D( NNE_PRIM_LINE_STRIP, gPrimLine[i], LINE_VNUM, Pri + PriAdd * i );
				nnEndDrawPrimitiveLine2DDXG20();
			}
			nnSetRegModeDrawPrimitiveDXG20();
#endif
			break;

		/* ポイントの描画*/
		case PRIM_POINT:
#if 0 /* 2008.08.06 */
			for( i = 0; i < PRIM_NUM; i++ )
			{
				nnBeginDrawPrimitivePoint2D( NNE_PRIM2D_POINT_FMT_P, &gPrimColor[i], NNE_PRIM_ALPHABLEND_ON );
				nnDrawPrimitivePoint2D( gPrimPoint[i], POINT_VNUM, Pri + PriAdd * i );
				nnEndDrawPrimitivePoint2D();
			}
#else
			/* 高速 */
			nnGetRegModeDrawPrimitiveDXG20();
			for( i = 0; i < PRIM_NUM; i++ )
			{
				nnBeginDrawPrimitivePoint2DDXG20( NNE_PRIM2D_POINT_FMT_P, &gPrimColor[i], NNE_PRIM_ALPHABLEND_ON );
				nnDrawPrimitivePoint2D( gPrimPoint[i], POINT_VNUM, Pri + PriAdd * i );
				nnEndDrawPrimitivePoint2DDXG20();
			}
			nnSetRegModeDrawPrimitiveDXG20();
#endif
			break;
	}
}

//--------
// メイン
//--------
void UserMain(void)
{
	Uint32 starttick, endtick;

	// フレーム開始時刻取得
	starttick = smpTmrGet();
	{
		Sample();
	}
	// フレーム終了時刻取得
	endtick = smpTmrGet();

	// 情報表示
	nnPrint( 3, 3, "NN "SAMPLENAME" SAMPLE" );
	nnPrint( 3, 4, "CPU Time%6d[us]", smpTmrDiff( endtick, starttick ) );

	switch( gPrimType )
	{
		case PRIM_TEX:   nnPrint( 3, 5, "[Texture Polygon]" );	break;
		case PRIM_POLY:  nnPrint( 3, 5, "[Polygon]" );			break;
		case PRIM_LINE:  nnPrint( 3, 5, "[Line]" );				break;
		case PRIM_POINT: nnPrint( 3, 5, "[Point]" );			break;
	}
	nnPrint( 3, 6, "Alpha %4.2f", gAlpha );

	nnPrint( 3, 24, "A BUTTON -> Change Primitive type" );
	nnPrint( 3, 25, "B BUTTON -> Change Priority" );
	nnPrint( 3, 26, "U, D BUTTON -> Change Alpha" );
	{
		if(gDXG20Blend == NNE_TRUE) nnPrint( 3, 29, "DXG20 Blend    = TRUE");
		else                        nnPrint( 3, 29, "DXG20 Blend    = FALSE");

		nnPrint( 3, 31, "TR BUTTON   -> Change DXG20 Blend" );

		if(gDXG20Blend == NNE_TRUE) nnSetPrintColor(0xf0b020ff);
		else                        nnSetPrintColor(0xc0c0c0ff);

		nnPrint( 3, 34, "Blend Func Src = %s", g_pBlendFuncTbl[gBlendFuncSrcNum].m_pFuncString);
		nnPrint( 3, 35, "Blend Func Dst = %s", g_pBlendFuncTbl[gBlendFuncDstNum].m_pFuncString);
		nnPrint( 3, 36, "Blend Op       = %s", g_pBlendOpTbl[gBlendOpNum].m_pOpString);

		nnPrint( 3, 38, "R, L BUTTON -> Change Blend Func Src" );
		nnPrint( 3, 39, "X, Y BUTTON -> Change Blend Func Dst" );
		nnPrint( 3, 40, "TL BUTTON   -> Change Blend Op" );

		// 元の設定
		nnSetPrintColor(0xc0c0c0ff);
	}

	// 登録文字の描画
	nnFlushPrint();
}
