/*---------------------------------------------------------------------------*
  Project:  TwlSDK - build - demos - tips - DisplayLogo
  File:     main.c

  Copyright 2009 Nintendo.  All rights reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law.  They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Date:: 2009-11-24#$
  $Rev: 11184 $
  $Author: okubata_ryoma $
 *---------------------------------------------------------------------------*/

//---------------------------------------------------------------------------
// このデモサンプルは、Lisenced by Nintendo ロゴの表示を行います。
// フェードイン(0.27秒)→1秒間ロゴを表示→フェードアウト(0.27秒)
// の順に表示を行います。
// ロゴの表示中に A ボタンを押すことで「1秒間ロゴを表示」を中断し、
// フェードアウトを開始します。
//---------------------------------------------------------------------------

#ifdef SDK_TWL
#include <twl.h>
#else
#include <nitro.h>
#endif
#include "data.h"

/* 定数 */
#define SCREEN_SIZE 256 * 192 * 2 // データのサイズ（バイト単位）
#define DISP_FRAME_NUM 60         // 1秒間（60フレーム）を測るタイマーに使用する定数
#define BRIGHTNESS_MAX 16         // 輝度の最大値。初期値に使用

typedef enum
{
    FADE_IN  = 0,
    DISPLAY  = 1,
    FADE_OUT = 2,
    END      = 3
}
DISP_STATE;

typedef struct
{
    u16     trigger;
    u16     press;
}
KeyWork;

/* 関数プロトタイプ */
void Init(void);          // 初期化全般
void VBlankIntr(void);    // Vブランク割り込み定義
void ReadKey(KeyWork*);
void TwlMain(void);

/*---------------------------------------------------------------------------*
  Name:         Init

  Description:  初期化全般を行う。画像データの読み込みまでを行う。

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/

void Init(void)
{
    // 各ライブラリの初期化
    OS_Init();
    FX_Init();

    GX_Init();

    GX_DispOff();
    GXS_DispOff();

    OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
    (void)OS_EnableIrqMask(OS_IE_V_BLANK);
    (void)OS_EnableIrq();

    (void)GX_VBlankIntr(TRUE);

    //VRAMの初期化
    GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);                          //LCDCに全てのVRAMバンクを割り当て
    MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);     //メモリのゼロクリア
    (void)GX_DisableBankForLCDC();                                //VRAMバンクの割り当てを解除


/* 上画面（このデモでLisenced by Nintendoロゴを表示する画面）の初期化*/

    GX_SetBankForBG(GX_VRAM_BG_128_A);               // VRAM-A for BG

    GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS,         // graphics mode
                       GX_BGMODE_0,                  // BGMODE is 0
                       GX_BG0_AS_2D);                // BG #0 is for 2D

    G2_SetBG0Control(GX_BG_SCRSIZE_TEXT_256x256,     // 256pix x 256pix text
                     GX_BG_COLORMODE_16,             // ロゴは16色で表現可能.
                     GX_BG_SCRBASE_0x0000,           // スクリーンベースのオフセット設定
                     GX_BG_CHARBASE_0x04000,         // キャラクタベースのオフセット設定
                     GX_BG_EXTPLTT_01                // BG拡張パレットを使用する場合、スロット0を使用
                     );

    GX_SetVisiblePlane(GX_PLANEMASK_BG0);            // BG0を表示選択
    G2_SetBG0Priority(0);                            // BG0の優先順位をトップに設定
    G2_BG0Mosaic(FALSE);                             // BG0にモザイク効果を行わない

    GX_LoadBG0Char(data_Char, 0, sizeof(data_Char)); // ロゴ画像のロード
    GX_LoadBGPltt(data_Palette, 0, sizeof(data_Palette));
    GX_LoadBG0Scr(data_Screen, 0, sizeof(data_Screen));

    GX_SetMasterBrightness(BRIGHTNESS_MAX);          // 真っ白な状態からフェードインさせる

/* 上画面の初期化ここまで */

    OS_WaitVBlankIntr();
    GX_DispOn();

}

// Vブランク割り込み設定
void VBlankIntr(void)
{
    OS_SetIrqCheckFlag(OS_IE_V_BLANK); // VBlank 割り込みの確認フラグを設定
}

// キー読み込み設定
void ReadKey(KeyWork* key)
{
    u16     readData = PAD_Read();
    key->trigger = (u16)(readData & (readData ^ key->press));
    key->press = readData;
}

/*---------------------------------------------------------------------------*
  Name:         Twl/NitroMain

  Description:  メイン

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/

#ifdef SDK_TWL
void TwlMain(void)
#else
void NitroMain(void)
#endif
{
    KeyWork Key;                        // 押されたボタン、キーの変数
    DISP_STATE State = FADE_IN;         // 状態を表す変数
    int DispFrame = DISP_FRAME_NUM;     // 表示の1秒間を測る変数
    int Brightness = BRIGHTNESS_MAX;    // 明るさを表す変数

    Init();                             // 初期化処理
    OS_Printf("***********************************************\n");
    OS_Printf("*    Start Displaying the Logo.               *\n"); // メッセージを表示
    OS_Printf("*    A BUTTON :  Stop displaying the Logo.    *\n");
    OS_Printf("***********************************************\n");
 
    while(1)
    {
        ReadKey(&Key);                  // キーの読み込み
        switch (State) 
        {
            case FADE_IN:
                if ( (Brightness = GX_GetMasterBrightness()) > 0)    // 表示前のときフェードイン
                {
                    GX_SetMasterBrightness( Brightness - 1);
                }
                else
                {
                    State = DISPLAY;
                }
                break;
            case DISPLAY:                                      // 表示中。デフォルトで60フレーム（1秒間）表示
                if ( DispFrame > 0 )
                {
                    if ( Key.trigger & PAD_BUTTON_A )          // Aボタンで中断（フェードイン、フェードアウト中は受け付けない)
                    {
                        State = FADE_OUT;
                    }
                    else
                    {
                        DispFrame--;
                    }
                }
                else
                {
                    State = FADE_OUT;
                }
                break;
            case FADE_OUT:                                     // 表示が終わるとフェードアウト。ボタンによる中断時もフェードアウトする。
                if ( (Brightness = GX_GetMasterBrightness()) < BRIGHTNESS_MAX )
                {
                    GX_SetMasterBrightness( Brightness + 1);
                }
                else
                {
                    State = END;
                }
                break;
            case END:
                break;
            default:
                break;
        }
        
        if ( State == END )
        {
            break;
        }
        
        OS_WaitVBlankIntr();
    }
    
    OS_Printf( "==== Finish sample ====\n" );
    OS_Terminate();
}