mirror of
https://github.com/rvtr/TwlIPL.git
synced 2025-10-31 06:01:12 -04:00
LCFGデータおよびAPIの仕様変更に対応。 git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@813 b08762b0-b915-fc4b-9d8c-17b2551a87ff
826 lines
25 KiB
C
826 lines
25 KiB
C
/*---------------------------------------------------------------------------*
|
||
Project: TwlIPL
|
||
File: launcher.c
|
||
|
||
Copyright 2007 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:: $
|
||
$Rev$
|
||
$Author$
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
#include <twl.h>
|
||
#include "misc.h"
|
||
#include "launcher.h"
|
||
#include "bannerCounter.h"
|
||
#include "sound.h"
|
||
#include <math.h>
|
||
#include <sysmenu/mcu.h>
|
||
|
||
|
||
// define data------------------------------------------
|
||
|
||
// バックライトボタン関係
|
||
#define B_LIGHT_DW_BUTTON_TOP_X ( 191 )
|
||
#define B_LIGHT_DW_BUTTON_TOP_Y ( 0 )
|
||
#define B_LIGHT_DW_BUTTON_BOTTOM_X ( B_LIGHT_DW_BUTTON_TOP_X + 11 )
|
||
#define B_LIGHT_DW_BUTTON_BOTTOM_Y ( B_LIGHT_DW_BUTTON_TOP_Y + 13 )
|
||
#define B_LIGHT_UP_BUTTON_TOP_X ( 235 )
|
||
#define B_LIGHT_UP_BUTTON_TOP_Y ( 0 )
|
||
#define B_LIGHT_UP_BUTTON_BOTTOM_X ( B_LIGHT_UP_BUTTON_TOP_X + 11 )
|
||
#define B_LIGHT_UP_BUTTON_BOTTOM_Y ( B_LIGHT_UP_BUTTON_TOP_Y + 13 )
|
||
|
||
// スクロールバー関係
|
||
#define BAR_ZERO_X ( (WINDOW_WIDTH - ((ITEM_SIZE + ITEM_INTERVAL) * (LAUNCHER_TITLE_LIST_NUM - 1) + ITEM_SIZE)) / 2)
|
||
#define BAR_ZERO_Y WINDOW_HEIGHT - 32
|
||
#define BAR_HEIGHT 14
|
||
#define BAR_WIDTH 32 //((ITEM_SIZE + ITEM_INTERVAL) * 4 + ITEM_SIZE + 2)
|
||
#define BAR_LOOSENESS 2
|
||
#define ITEMDOT_PER_FRAME ((double)(ITEM_SIZE + ITEM_INTERVAL) / (double)FRAME_PER_SELECT)
|
||
#define FRAME_PER_ITEMDOT ((double)FRAME_PER_SELECT / (double)(ITEM_SIZE + ITEM_INTERVAL))
|
||
#define BAR_OFFSET 0 // 表示に"■"テキストを使っているので、タッチ座標を補正する目的のOFFSET
|
||
#define ITEM_SIZE 2
|
||
#define ITEM_INTERVAL 3
|
||
|
||
// バナー表示関係
|
||
#define DOT_PER_FRAME ((BANNER_WIDTH + BANNER_INTERVAL) / FRAME_PER_SELECT) // 割り切れないと動きがカクカクするはず
|
||
#define FRAME_PER_SELECT 14 // バナーからバナーへの移動にかかるフレーム数
|
||
#define BANNER_FAR_LEFT_POS (WINDOW_WIDTH/2 - BANNER_WIDTH*5/2 - BANNER_INTERVAL * 2)
|
||
#define BANNER_TOP (WINDOW_HEIGHT/2 - 16)
|
||
#define WINDOW_WIDTH 256
|
||
#define WINDOW_HEIGHT 192
|
||
#define BANNER_WIDTH 32
|
||
#define BANNER_HEIGHT 32
|
||
#define BANNER_INTERVAL 24
|
||
#define TITLE_V_CENTER 39
|
||
|
||
#define MAX_SHOW_BANNER 6
|
||
|
||
#define MAX_LOAD_IMAGES 128
|
||
|
||
// フェードアウト関係
|
||
#define FADE_COUNT_PER_ALPHA ((FADE_COUNT_MAX - FADE_START) / ALPHA_MAX)
|
||
#define FADE_COUNT_MAX 124
|
||
#define ALPHA_MAX 31
|
||
#define FADE_START 62
|
||
|
||
// extern data------------------------------------------
|
||
|
||
extern u32 bg_char_data[8 * 6];
|
||
extern u16 bg_scr_data[32 * 32];
|
||
extern u16 bg_scr_data2[32 * 32];
|
||
|
||
// function's prototype declaration---------------------
|
||
static void LoadBannerFiles( void );
|
||
static void BannerInit( void );
|
||
static void SetDefaultBanner( TitleProperty *titleprop );
|
||
static void SetAffineAnimation( BOOL (*flipparam)[4] );
|
||
static void SetBannerCounter( TitleProperty *titleprop );
|
||
static void SetOAMAttr( void );
|
||
static void BannerDraw( int selected, TitleProperty *titleprop);
|
||
static BOOL SelectCenterFunc( u16 *csr, TPData *tgt );
|
||
static BOOL SelectFunc( u16 *csr, TPData *tgt );
|
||
static void ProcessBackLightPads( void );
|
||
static TitleProperty *ProcessPads( TitleProperty *pTitleList );
|
||
static void MoveByScrollBar();
|
||
static void DrawScrollBar();
|
||
static void DrawBackLightSwitch(void);
|
||
|
||
// global variable -------------------------------------
|
||
RTCDrawProperty g_rtcDraw = {
|
||
TRUE, RTC_DATE_TOP_X, RTC_DATE_TOP_Y, RTC_TIME_TOP_X, RTC_TIME_TOP_Y
|
||
};
|
||
|
||
// static variable -------------------------------------
|
||
static int s_csr = 0; // 画面中央座標と、リストの一番最初にあるバナーの中央座標との距離を
|
||
// 移動するのに必要なフレーム数で表すための変数
|
||
static int csr_v = 0; // s_csrの速度的変数
|
||
|
||
static TWLBannerFile *empty_banner;
|
||
static TWLBannerFile *nobanner_banner;
|
||
static TWLBannerFile *no_card_banner;
|
||
static GXOamAttr banner_oam_attr[MAX_SHOW_BANNER+10];// アフィンパラメータ埋める関係で少し大きめ
|
||
static int selected = 0;
|
||
static int bar_left = BAR_ZERO_X;
|
||
static fx32 s_selected_banner_size;
|
||
static BOOL s_wavstop = FALSE;
|
||
static BannerCounter banner_counter[LAUNCHER_TITLE_LIST_NUM];
|
||
|
||
//static StreamInfo strm; // stream info
|
||
|
||
// const data -----------------------------------------
|
||
//const char filename[] = "data/fanfare.32.wav";
|
||
|
||
//===============================================
|
||
// Launcher.c
|
||
//===============================================
|
||
|
||
//======================================================
|
||
// ランチャー
|
||
//======================================================
|
||
|
||
// バナー表示関係(暫定)
|
||
#define DBGBNR
|
||
#ifdef DBGBNR
|
||
|
||
|
||
static void LoadBannerFiles( void )
|
||
{
|
||
// デフォルトバナーファイルの読み込み。最終的にリブートしてしまうので、解放処理は無し
|
||
u32 size = CMN_LoadFile( (void **)&empty_banner, "data/EmptyBanner.bnr", &g_allocator);
|
||
NNS_G2D_ASSERT( size > 0 );
|
||
size = CMN_LoadFile( (void **)&nobanner_banner, "data/NoBanner.bnr", &g_allocator);
|
||
NNS_G2D_ASSERT( size > 0 );
|
||
size = CMN_LoadFile( (void **)&no_card_banner, "data/NoCardBanner.bnr", &g_allocator);
|
||
NNS_G2D_ASSERT( size > 0 );
|
||
}
|
||
|
||
// パレットの読み込みやOBJ関係の初期化
|
||
static void BannerInit( void )
|
||
{
|
||
int l;
|
||
LoadBannerFiles();
|
||
|
||
MI_DmaFill32(3, banner_oam_attr, 192, sizeof(banner_oam_attr)); // let out of the screen if not display
|
||
|
||
// OBJModeの設定
|
||
GX_SetOBJVRamModeChar(GX_OBJVRAMMODE_CHAR_1D_128K); // 2D mapping mode
|
||
|
||
// BannerCounterの初期化
|
||
for( l=0; l<LAUNCHER_TITLE_LIST_NUM; l++ )
|
||
{
|
||
BNC_initCounter( &banner_counter[l], empty_banner);
|
||
}
|
||
|
||
//OBJATTRの初期化……表示前には値を弄る
|
||
for(l=0;l<MAX_SHOW_BANNER;l++)
|
||
{
|
||
G2_SetOBJAttr( &banner_oam_attr[l], // OAM pointer
|
||
0, // X position
|
||
BANNER_TOP, // Y position
|
||
1, // Priority
|
||
GX_OAM_MODE_NORMAL, // Bitmap mode
|
||
FALSE, // mosaic off
|
||
GX_OAM_EFFECT_NONE, // affine off
|
||
GX_OAM_SHAPE_32x32, // 32x32 size
|
||
GX_OAM_COLOR_16, // 16 color
|
||
0, // charactor
|
||
0, // palette
|
||
0); // affine
|
||
}
|
||
DC_FlushRange(&banner_oam_attr, sizeof(banner_oam_attr));
|
||
}
|
||
|
||
// TitlePropertyのIDとpBannerをチェックし、
|
||
// 特定の条件でpBannerにデフォルトバナーを指定する
|
||
static void SetDefaultBanner( TitleProperty *titleprop )
|
||
{
|
||
int l;
|
||
|
||
for(l=0;l<LAUNCHER_TITLE_LIST_NUM;l++)
|
||
{
|
||
if( !titleprop[l].flags.isValid ) //isValidフラグがFALSEの時はEmpty
|
||
{
|
||
if(l != 0)
|
||
{
|
||
titleprop[l].pBanner = empty_banner;
|
||
}
|
||
else
|
||
{
|
||
titleprop[l].pBanner = no_card_banner;
|
||
}
|
||
}
|
||
else if(titleprop[l].pBanner == NULL) //isValidフラグがTRUEでバナーがNULLならノーバナー
|
||
{
|
||
titleprop[l].pBanner = nobanner_banner;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 中央2枚(banner_oam_attr[2],banner_oam_attr[3])のバナーのアフィンパラメータの設定
|
||
// flipparamは左h,左v,右h,右vの順序
|
||
static void SetAffineAnimation( BOOL (*flipparam)[4] )
|
||
{
|
||
MtxFx22 mtx;
|
||
static double wav;
|
||
fx32 param;
|
||
u32 x,y;
|
||
|
||
if(s_csr%FRAME_PER_SELECT == 0){ // 適当に波打たせてみる
|
||
double s = sin(wav);
|
||
s_selected_banner_size = FX32_HALF - (long)( 0x80 * ( s - 1 ) );
|
||
param = s_selected_banner_size;
|
||
if(!s_wavstop) wav += 0.1;
|
||
}else{ // 適当に大きさを変えてみる
|
||
param = FX32_HALF + FX32_HALF*(s_csr%FRAME_PER_SELECT)/FRAME_PER_SELECT;
|
||
wav = 0;
|
||
}
|
||
|
||
// 中央左のバナー
|
||
mtx._00 = param * ( (*flipparam)[0] ? -1 : 1 );
|
||
mtx._01 = 0;
|
||
mtx._10 = 0;
|
||
mtx._11 = param * ( (*flipparam)[1] ? -1 : 1 );
|
||
G2_SetOBJAffine((GXOamAffine *)(&banner_oam_attr[0]), &mtx);
|
||
// アフィンでの反転時はアルゴリズムの関係で位置補正が必要……
|
||
G2_GetOBJPosition(&banner_oam_attr[2], &x, &y);
|
||
G2_SetOBJPosition(&banner_oam_attr[2], (int)x-( mtx._00==-FX32_ONE ? 1 : 0 ), (int)y-( mtx._11==-FX32_ONE ? 1 : 0 ));
|
||
|
||
// 中央右のバナー
|
||
param = FX32_ONE - FX32_HALF*(s_csr%FRAME_PER_SELECT)/FRAME_PER_SELECT;
|
||
mtx._00 = param * ( (*flipparam)[2] ? -1 : 1 );
|
||
mtx._11 = param * ( (*flipparam)[3] ? -1 : 1 );
|
||
G2_SetOBJAffine((GXOamAffine *)(&banner_oam_attr[4]), &mtx);
|
||
// アフィンでの反転時はアルゴリズムの関係で位置補正が必要……
|
||
G2_GetOBJPosition(&banner_oam_attr[3], &x, &y);
|
||
G2_SetOBJPosition(&banner_oam_attr[3], (int)x-( mtx._00==-FX32_ONE ? 1 : 0 ), (int)y-( mtx._11==-FX32_ONE ? 1 : 0 ));
|
||
}
|
||
|
||
static void SetBannerCounter( TitleProperty *titleprop )
|
||
{
|
||
int l;
|
||
for( l=0; l<LAUNCHER_TITLE_LIST_NUM; l++ )
|
||
{
|
||
// nandも一応毎回セット
|
||
BNC_setBanner( &banner_counter[l], titleprop[l].pBanner);
|
||
if( l==0 )
|
||
{
|
||
// カードの場合、バナーヘッダのv1のCRCが違ったらカウントをリセット
|
||
if ( BNC_getBanner( &banner_counter[l] )->h.crc16_v1 != titleprop[l].pBanner->h.crc16_v1)
|
||
{
|
||
BNC_resetCount( &banner_counter[l] );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// OAMデータの設定
|
||
static void SetOAMAttr( void )
|
||
{
|
||
int l;
|
||
int div1 = s_csr / FRAME_PER_SELECT;
|
||
int div2 = s_csr % FRAME_PER_SELECT;
|
||
BOOL flipparam[4];
|
||
|
||
for (l=0;l<MAX_SHOW_BANNER;l++)
|
||
{
|
||
int num = div1 - 2 + l;
|
||
if(-1 < num && num < LAUNCHER_TITLE_LIST_NUM){
|
||
// バナーカウンタからフレームデータを取得し、カウンタをインクリメント
|
||
FrameAnimeData fad = BNC_getFADAndIncCount( &banner_counter[num] );
|
||
|
||
// パレットのロード
|
||
GX_LoadOBJPltt( fad.pltt, (u16)(l * BANNER_PLTT_SIZE), BANNER_PLTT_SIZE );
|
||
G2_SetOBJMode(&banner_oam_attr[l], GX_OAM_MODE_NORMAL, l);
|
||
|
||
// バナー画像のロード
|
||
GX_LoadOBJ( fad.image, (u32)l*BANNER_IMAGE_SIZE , BANNER_IMAGE_SIZE);
|
||
|
||
// 表示画像の設定、キャラクタネーム境界128バイトである事に注意
|
||
banner_oam_attr[l].charNo = l*4;
|
||
|
||
// 位置およびエフェクトの設定
|
||
if(l == 2 || l == 3)
|
||
{
|
||
// 中央付近で大きくなったり小さくなったりする二つのバナー
|
||
G2_SetOBJEffect(&banner_oam_attr[l], GX_OAM_EFFECT_AFFINE_DOUBLE, l-2);
|
||
G2_SetOBJPosition(&banner_oam_attr[l],
|
||
BANNER_FAR_LEFT_POS - BANNER_WIDTH/2 + l*(BANNER_WIDTH + BANNER_INTERVAL) - div2 * DOT_PER_FRAME,
|
||
BANNER_TOP - BANNER_HEIGHT/2 );
|
||
flipparam[(l-2)*2] = fad.hflip;// フリップ情報は一旦保存
|
||
flipparam[(l-2)*2+1] = fad.vflip;
|
||
}
|
||
else
|
||
{
|
||
// その他のバナー
|
||
GXOamEffect effect = GX_OAM_EFFECT_NONE;
|
||
if( fad.vflip )
|
||
{
|
||
if( fad.hflip )
|
||
{
|
||
effect = GX_OAM_EFFECT_FLIP_HV;
|
||
}
|
||
else
|
||
{
|
||
effect = GX_OAM_EFFECT_FLIP_V;
|
||
}
|
||
}
|
||
else if( fad.hflip )
|
||
{
|
||
effect = GX_OAM_EFFECT_FLIP_H;
|
||
}
|
||
banner_oam_attr[l].x = BANNER_FAR_LEFT_POS + l*(BANNER_WIDTH + BANNER_INTERVAL) - div2 * DOT_PER_FRAME;
|
||
|
||
G2_SetOBJEffect(&banner_oam_attr[l],effect,0);
|
||
}
|
||
}else
|
||
{
|
||
// そのoamが担当する場所にはバナーがない
|
||
G2_SetOBJEffect(&banner_oam_attr[l],GX_OAM_EFFECT_NODISPLAY,0);
|
||
}
|
||
}
|
||
|
||
// アフィンパラメータの設定
|
||
SetAffineAnimation( &flipparam );
|
||
}
|
||
|
||
// バナー関係の描画
|
||
// 思ったよりVRAMへのロードが高速だったので、
|
||
// 特に難しいことを考えず表示するイメージデータだけ毎フレームVRAMにロード
|
||
static void BannerDraw(int selected, TitleProperty *titleprop)
|
||
{
|
||
static int fadecount = 0;
|
||
static u16 old_gameName[BANNER_LANG_LENGTH];
|
||
NNSG2dChar *str;
|
||
|
||
// デフォルトバナーをTitlePropertyに埋め込み
|
||
SetDefaultBanner( titleprop );
|
||
|
||
// バナーカウンタのバナーセット
|
||
SetBannerCounter( titleprop );
|
||
|
||
// OAMデータの設定
|
||
SetOAMAttr();
|
||
|
||
// OAMをVRAMへロード
|
||
DC_FlushRange(&banner_oam_attr, sizeof(banner_oam_attr));
|
||
GX_LoadOAM(&banner_oam_attr, 0, sizeof(banner_oam_attr));
|
||
|
||
// アプリ名表示
|
||
str = ((TWLBannerFile *)titleprop[selected].pBanner)->v1.gameName[ LCFG_TSD_GetLanguage() ];
|
||
if( STD_CompareNString( (const char *)old_gameName, (const char *)str, BANNER_LANG_LENGTH * 2 ) != 0 )
|
||
{
|
||
NNSG2dChar *str = ((TWLBannerFile *)titleprop[selected].pBanner)->v1.gameName[ LCFG_TSD_GetLanguage() ];
|
||
NNSG2dTextRect rect = NNS_G2dTextCanvasGetTextRect( &gTextCanvas, str );
|
||
NNS_G2dCharCanvasClearArea( &gCanvas, TXT_COLOR_NULL, 0, 24, WINDOW_WIDTH, 32 );
|
||
PutStringUTF16( (WINDOW_WIDTH-rect.width)>>1, TITLE_V_CENTER - (rect.height>>1), TXT_COLOR_BLACK, str );
|
||
MI_CpuCopy8( str, old_gameName, BANNER_LANG_LENGTH * 2 );
|
||
}
|
||
|
||
if(fadecount < (FADE_COUNT_MAX - FADE_START)) {
|
||
fadecount += 2;
|
||
G2_ChangeBlendAlpha( ALPHA_MAX-((fadecount)/FADE_COUNT_PER_ALPHA), (fadecount)/FADE_COUNT_PER_ALPHA );
|
||
}
|
||
}
|
||
|
||
#endif //DBGBNR
|
||
|
||
|
||
// ランチャーの初期化
|
||
void LauncherInit( TitleProperty *pTitleList )
|
||
{
|
||
#pragma unused( pTitleList )
|
||
|
||
InitBG(); // BG初期化
|
||
|
||
GX_DispOff();
|
||
GXS_DispOff();
|
||
|
||
ChangeUserColor( LCFG_TSD_GetUserColor() );
|
||
NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_NULL );
|
||
|
||
// BGデータのロード処理
|
||
GX_LoadBG1Char(bg_char_data, 0, sizeof(bg_char_data));
|
||
GX_LoadBG1Scr(bg_scr_data, 0, sizeof(bg_scr_data));
|
||
|
||
// フェードアウト用BGデータ作成とロード
|
||
SVC_CpuClear( 0x0004, &bg_scr_data2, sizeof(bg_scr_data2), 16 );
|
||
DC_FlushRange(&bg_scr_data2, sizeof(bg_scr_data2));
|
||
GX_LoadBG2Char(bg_char_data, 0, sizeof(bg_char_data));
|
||
GX_LoadBG2Scr(bg_scr_data2, 0, sizeof(bg_scr_data2));
|
||
|
||
DrawBackLightSwitch();
|
||
PutStringUTF16( 0, 0, TXT_COLOR_BLUE, L"TWL-SYSTEM MENU" );
|
||
// PrintfSJIS( 128, 0, TXT_COLOR_BLUE, "IPL:%s", g_strIPLSvnRevision );
|
||
// PrintfSJIS( 128, 12, TXT_COLOR_BLUE, "SDK:%s", g_strSDKSvnRevision );
|
||
|
||
SVC_CpuClear( 0x0000, &tpd, sizeof(TpWork), 16 );
|
||
|
||
GetAndDrawRTCData( &g_rtcDraw, TRUE );
|
||
|
||
GX_SetVisiblePlane( GX_PLANEMASK_BG0 | GX_PLANEMASK_BG1 | GX_PLANEMASK_BG2 | GX_PLANEMASK_OBJ );
|
||
G2_SetBlendAlpha(GX_BLEND_PLANEMASK_BG2,
|
||
GX_BLEND_PLANEMASK_BG0 | GX_BLEND_PLANEMASK_BG1 | GX_BLEND_PLANEMASK_OBJ, ALPHA_MAX,0);
|
||
|
||
GX_DispOn();
|
||
GXS_DispOn();
|
||
|
||
// streamInfo初期化
|
||
//FS_InitFile(&strm.file);
|
||
//strm.isPlay = FALSE;
|
||
|
||
#ifdef DBGBNR
|
||
BannerInit();
|
||
#endif
|
||
}
|
||
|
||
// 輝度表示ポーリングで呼んだSYSM_ReadMcuRegisterAsyncのコールバック
|
||
static OSThreadQueue s_callback_queue;
|
||
static SYSMMcuResult s_callback_result;
|
||
static void PollBackLightBlightnessCallBack( SYSMMcuResult result, void *arg )
|
||
{
|
||
s_callback_result = result;
|
||
OS_WakeupThread( &s_callback_queue );
|
||
}
|
||
|
||
// 輝度表示ポーリング
|
||
// X3基盤から、Select+音量で輝度変更できるようになったため、輝度スイッチ表示切り替えタイミングを変更
|
||
// 変化があれば輝度スイッチ表示を切り替えるように
|
||
static void PollBackLightBrightness( void )
|
||
{
|
||
static int old_brightness = -1;
|
||
#ifdef SDK_SUPPORT_PMIC_2
|
||
if ( SYSMi_GetMcuVersion() <= 1 )
|
||
{
|
||
}
|
||
else
|
||
#endif // SDK_SUPPORT_PMIC_2
|
||
{
|
||
u8 brightness;
|
||
( void )SYSM_ReadMcuRegisterAsync( MCU_REG_BL_ADDR, &brightness, PollBackLightBlightnessCallBack, NULL );
|
||
OS_SleepThread( &s_callback_queue ); // 値が返ってくるまでスリープ
|
||
if( s_callback_result==MCU_RESULT_SUCCESS && LCFG_TSD_GetBacklightBrightness() != brightness )
|
||
{
|
||
// マイコンから取ってきた輝度とLCFGの設定値がズレていたらLCFGの値を設定しなおし
|
||
LCFG_TSD_SetBacklightBrightness( brightness );
|
||
{
|
||
u8 *pBuffer = SYSM_Alloc( LCFG_WRITE_TEMP );
|
||
if( pBuffer != NULL ) {
|
||
LCFG_WriteTWLSettings( (u8 (*)[ LCFG_WRITE_TEMP ] )pBuffer );
|
||
SYSM_Free( pBuffer );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 1フレーム前の古い値とLCFGの値が違っていたら描画しなおし
|
||
if( old_brightness != LCFG_TSD_GetBacklightBrightness() )
|
||
{
|
||
old_brightness = LCFG_TSD_GetBacklightBrightness();
|
||
DrawBackLightSwitch();
|
||
}
|
||
}
|
||
|
||
// ROMのローディング中のランチャーフェードアウト
|
||
BOOL LauncherFadeout( TitleProperty *pTitleList )
|
||
{
|
||
static int fadecount = 0;
|
||
|
||
// 描画関係
|
||
|
||
// 輝度表示
|
||
|
||
PollBackLightBrightness();
|
||
|
||
DrawScrollBar( pTitleList );
|
||
|
||
#ifdef DBGBNR
|
||
BannerDraw( selected, pTitleList );
|
||
#endif
|
||
|
||
// 描画少し追加
|
||
{
|
||
MtxFx22 mtx;
|
||
static double wa;
|
||
double s = cos(wa*3);
|
||
if( s!=0 ) mtx._00 = (fx32)((s_selected_banner_size/s) * (1.0 + wa));
|
||
else mtx._00 = 0x8fff;
|
||
mtx._01 = 0;
|
||
mtx._10 = 0;
|
||
mtx._11 = (fx32)(s_selected_banner_size * (1.0 + wa));
|
||
G2_SetOBJAffine((GXOamAffine *)(&banner_oam_attr[0]), &mtx);
|
||
wa += 0.0333333333333;
|
||
}
|
||
|
||
DC_FlushRange(&banner_oam_attr, sizeof(banner_oam_attr));
|
||
GX_LoadOAM(&banner_oam_attr, 0, sizeof(banner_oam_attr));
|
||
|
||
// RTC情報の取得&表示
|
||
GetAndDrawRTCData( &g_rtcDraw, FALSE );
|
||
|
||
// フェードアウトのカウント処理
|
||
if(fadecount >= FADE_START)
|
||
{
|
||
G2_ChangeBlendAlpha( (fadecount-FADE_START)/FADE_COUNT_PER_ALPHA, ALPHA_MAX-((fadecount-FADE_START)/FADE_COUNT_PER_ALPHA) );
|
||
}
|
||
if(fadecount < FADE_COUNT_MAX) {
|
||
fadecount++;
|
||
return FALSE;
|
||
}else {
|
||
// ディスプレイOFFにしないと起動時にノイズが表示される
|
||
GX_DispOff();
|
||
GXS_DispOff();
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
// ProcessPadsのSelectSomethingByTPで使うSelectSomethingFuncの実装
|
||
static BOOL SelectCenterFunc( u16 *csr, TPData *tgt )
|
||
{
|
||
// 単純な実装例
|
||
int x = WINDOW_WIDTH/2 - BANNER_WIDTH;
|
||
int y = BANNER_TOP - BANNER_HEIGHT/2;
|
||
if(WithinRangeTP( x, y, x+BANNER_WIDTH*2, y+BANNER_HEIGHT*2, tgt ))
|
||
{
|
||
*csr = (u16)1;
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
static BOOL SelectFunc( u16 *csr, TPData *tgt )
|
||
{
|
||
int l;
|
||
|
||
for(l=0; l<2; l++)
|
||
{
|
||
int x = 11*8 + l*6*8;
|
||
int y = 17*8;
|
||
if(WithinRangeTP( x, y, x+32, y+16, tgt ))
|
||
{
|
||
*csr = (u16)l;
|
||
return TRUE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
static void ProcessBackLightPads( void )
|
||
{
|
||
static BOOL up_bl_bak = FALSE;
|
||
static BOOL dw_bl_bak = FALSE;
|
||
BOOL up_bl_trg = FALSE;
|
||
BOOL dw_bl_trg = FALSE;
|
||
int brightness;
|
||
|
||
if(tpd.disp.touch) {
|
||
BOOL up_bl = WithinRangeTP( B_LIGHT_UP_BUTTON_TOP_X, B_LIGHT_UP_BUTTON_TOP_Y,
|
||
B_LIGHT_UP_BUTTON_BOTTOM_X, B_LIGHT_UP_BUTTON_BOTTOM_Y, &tpd.disp );
|
||
BOOL dw_bl = WithinRangeTP( B_LIGHT_DW_BUTTON_TOP_X, B_LIGHT_DW_BUTTON_TOP_Y,
|
||
B_LIGHT_DW_BUTTON_BOTTOM_X, B_LIGHT_DW_BUTTON_BOTTOM_Y, &tpd.disp );
|
||
up_bl_trg = ( up_bl && tpd.disp.touch && !up_bl_bak ) ;
|
||
dw_bl_trg = ( dw_bl && tpd.disp.touch && !dw_bl_bak ) ;
|
||
up_bl_bak = tpd.disp.touch;
|
||
dw_bl_bak = tpd.disp.touch;
|
||
}else {
|
||
up_bl_bak = FALSE;
|
||
dw_bl_bak = FALSE;
|
||
}
|
||
|
||
if( (pad.trg & PAD_KEY_UP) || up_bl_trg ) {
|
||
brightness = LCFG_TSD_GetBacklightBrightness() + 1;
|
||
if( brightness > LCFG_TWL_BACKLIGHT_LEVEL_MAX ) {
|
||
brightness = LCFG_TWL_BACKLIGHT_LEVEL_MAX;
|
||
}
|
||
SYSM_SetBackLightBrightness( (u8)brightness );
|
||
}
|
||
if( ( pad.trg & PAD_KEY_DOWN) || dw_bl_trg ) {
|
||
brightness = LCFG_TSD_GetBacklightBrightness() - 1;
|
||
if( brightness < 0 ) {
|
||
brightness = 0;
|
||
}
|
||
SYSM_SetBackLightBrightness( (u8)brightness );
|
||
}
|
||
}
|
||
|
||
static TitleProperty *ProcessPads( TitleProperty *pTitleList )
|
||
{
|
||
SelectSomethingFunc func[1]={SelectCenterFunc};
|
||
BOOL tp_select = FALSE;
|
||
u16 dummy;
|
||
u16 tp_lr = 3;
|
||
TitleProperty *ret = NULL;
|
||
LauncherBootFlags tempflag = {TRUE, LAUNCHER_BOOTTYPE_NAND, TRUE, FALSE, FALSE, FALSE, 0};
|
||
|
||
// バックライト関係のキー処理
|
||
ProcessBackLightPads();
|
||
|
||
// その他のキー処理
|
||
if( tpd.disp.touch )
|
||
{
|
||
int x = WINDOW_WIDTH/2 - BANNER_WIDTH;
|
||
int y = BANNER_TOP - BANNER_HEIGHT/2;
|
||
if(WithinRangeTP( x, y, x+BANNER_WIDTH*2, y+BANNER_HEIGHT*2, &tpd.disp ))
|
||
{
|
||
s_wavstop = TRUE;
|
||
}else
|
||
{
|
||
s_wavstop = FALSE;
|
||
}
|
||
(void) SelectFunc( &tp_lr, &tpd.disp );
|
||
}else
|
||
{
|
||
s_wavstop = FALSE;
|
||
}
|
||
|
||
if( pad.trg & PAD_BUTTON_B ) {
|
||
OS_SetLauncherParamAndResetHardware( NULL, &tempflag );
|
||
}
|
||
|
||
if(pad.cont & PAD_KEY_RIGHT || tp_lr == 1){ // バナー選択
|
||
if(csr_v == 0) csr_v = 1;
|
||
}
|
||
if( pad.cont & PAD_KEY_LEFT || tp_lr == 0){
|
||
if(csr_v == 0) csr_v = -1;
|
||
}
|
||
s_csr += csr_v;
|
||
if((LAUNCHER_TITLE_LIST_NUM-1)*FRAME_PER_SELECT < s_csr) s_csr = (LAUNCHER_TITLE_LIST_NUM-1)*FRAME_PER_SELECT;
|
||
if( s_csr < 0 ) s_csr = 0;
|
||
|
||
selected = (s_csr + FRAME_PER_SELECT/2)/FRAME_PER_SELECT;
|
||
if(s_csr%FRAME_PER_SELECT == 0){
|
||
csr_v = 0;
|
||
|
||
// バナーが中央にあるときだけ決定可能
|
||
tp_select = SelectSomethingByTP(&dummy, func, 1 );
|
||
|
||
if( ( pad.trg & PAD_BUTTON_A ) || ( tp_select ) ) { // メニュー項目への分岐
|
||
if( pTitleList[selected].flags.isValid )
|
||
{
|
||
//PlayStream(&strm, filename);
|
||
ret = &pTitleList[selected];
|
||
}
|
||
}
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
// スクロールバーによるスクロール
|
||
static void MoveByScrollBar( void )
|
||
{
|
||
// スクロールバーによるスクロール
|
||
{
|
||
static BOOL holding = FALSE;
|
||
static int dx;
|
||
|
||
if(!holding)
|
||
{
|
||
bar_left = (int)(BAR_ZERO_X + (ITEMDOT_PER_FRAME * s_csr));
|
||
}
|
||
|
||
if(tpd.disp.touch)
|
||
{
|
||
if(holding)
|
||
{
|
||
if ( tpd.disp.x - dx < bar_left - BAR_LOOSENESS)
|
||
{
|
||
bar_left = tpd.disp.x - dx + BAR_LOOSENESS;
|
||
}
|
||
else if ( tpd.disp.x - dx > bar_left + BAR_LOOSENESS)
|
||
{
|
||
bar_left = tpd.disp.x - dx - BAR_LOOSENESS;
|
||
}
|
||
s_csr = (u16)((bar_left - BAR_ZERO_X) * FRAME_PER_ITEMDOT);
|
||
}
|
||
else if(WithinRangeTP(bar_left+5-BAR_WIDTH/2, BAR_ZERO_Y+BAR_OFFSET,bar_left+5+BAR_WIDTH/2,BAR_ZERO_Y+BAR_OFFSET+BAR_HEIGHT,&tpd.disp))
|
||
{
|
||
holding = TRUE;
|
||
dx = tpd.disp.x - bar_left;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(holding)
|
||
{
|
||
int det = s_csr % FRAME_PER_SELECT;
|
||
holding = FALSE;
|
||
csr_v = (det < FRAME_PER_SELECT/2) ? (det == 0 ? 0 : -1) : 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
// タッチパッドによるスクロール後の調整
|
||
if( BAR_ZERO_X + (ITEM_SIZE + ITEM_INTERVAL) * (LAUNCHER_TITLE_LIST_NUM - 1) < bar_left )
|
||
bar_left = BAR_ZERO_X + (ITEM_SIZE + ITEM_INTERVAL) * (LAUNCHER_TITLE_LIST_NUM - 1);
|
||
if( bar_left < BAR_ZERO_X ) bar_left = BAR_ZERO_X;
|
||
if((LAUNCHER_TITLE_LIST_NUM-1)*FRAME_PER_SELECT < s_csr) s_csr = (LAUNCHER_TITLE_LIST_NUM-1)*FRAME_PER_SELECT;
|
||
if( s_csr < 0 ) s_csr = 0;
|
||
}
|
||
|
||
static void DrawScrollBar( TitleProperty *pTitleList )
|
||
{
|
||
int l;
|
||
static int col_count = 0;
|
||
static int col_count_d = 1;
|
||
static const int COL_FLAME_MAX = 30;
|
||
static const int COL_NUM = 15;
|
||
static const int COL_DIV = (COL_FLAME_MAX / COL_NUM);
|
||
int colc_cold;
|
||
static int oldx;
|
||
|
||
col_count += col_count_d;
|
||
if(col_count < 0)
|
||
{
|
||
col_count = 0;
|
||
col_count_d = 1;
|
||
}
|
||
if(COL_FLAME_MAX <= col_count)
|
||
{
|
||
col_count = COL_FLAME_MAX - 1;
|
||
col_count_d = -1;
|
||
}
|
||
|
||
colc_cold = col_count/COL_DIV;
|
||
|
||
NNS_G2dCharCanvasClearArea( &gCanvas, TXT_COLOR_NULL, oldx, BAR_ZERO_Y, 12, 13 );
|
||
for(l=0; l<LAUNCHER_TITLE_LIST_NUM; l++)
|
||
{
|
||
PutStringUTF16( (int)(BAR_ZERO_X + l * (ITEM_SIZE + ITEM_INTERVAL)),
|
||
BAR_ZERO_Y,
|
||
(pTitleList[l].flags.isValid ? (TXT_UCOLOR_G0 + colc_cold) : TXT_COLOR_BLACK),
|
||
(const u16 *)L"・" );
|
||
}
|
||
for(l=0; l<4; l++)
|
||
{
|
||
oldx = (int)(bar_left - l%2);
|
||
PutStringUTF16( oldx, BAR_ZERO_Y - l/2, TXT_UCOLOR_G1, (const u16 *)L"□" );
|
||
}
|
||
}
|
||
|
||
// ランチャーメイン
|
||
TitleProperty *LauncherMain( TitleProperty *pTitleList )
|
||
{
|
||
TitleProperty *ret = NULL;
|
||
|
||
//#define DBGLP
|
||
#ifdef DBGLP
|
||
typedef struct NandFirmResetParameter {
|
||
u8 isHotStart :1;
|
||
u8 isResetSW :1;
|
||
u8 rsv :5;
|
||
u8 isValid :1;
|
||
}NandFirmResetParameter;
|
||
{
|
||
static BOOL a=FALSE;
|
||
if( pad.cont & PAD_BUTTON_Y )
|
||
{
|
||
u8 *p = (u8 *)SYSMi_GetLauncherParamAddr();
|
||
int l;
|
||
if( a )
|
||
{
|
||
return ret;
|
||
}
|
||
NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_NULL );
|
||
for(l=0;l<16;l++)
|
||
PrintfSJIS( 0, l*12, TXT_COLOR_RED, "%.02x%.02x%.02x%.02x %.02x%.02x%.02x%.02x",
|
||
*(p+l*8), *(p+1+l*8), *(p+2+l*8), *(p+3+l*8), *(p+4+l*8), *(p+5+l*8), *(p+6+l*8), *(p+7+l*8) );
|
||
a=TRUE;
|
||
return ret;
|
||
}
|
||
if( a ){
|
||
NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_NULL );
|
||
a=FALSE;
|
||
}
|
||
}
|
||
PrintfSJIS( 1, 12, TXT_COLOR_RED,
|
||
"ValidLParam:%d\n", SYSMi_GetWork()->flags.common.isValidLauncherParam );
|
||
#define OSi_GetNandFirmResetParam() ( (NandFirmResetParameter *)HW_NAND_FIRM_HOTSTART_FLAG )
|
||
PrintfSJIS( 1, 24, TXT_COLOR_RED,
|
||
"HotStartFlag:%d\n", OSi_GetNandFirmResetParam()->isHotStart );
|
||
PrintfSJIS( 1, 36, TXT_COLOR_RED,
|
||
"ResetSWFlag:%d\n", OSi_GetNandFirmResetParam()->isResetSW );
|
||
PrintfSJIS( 1, 48, TXT_COLOR_RED,
|
||
"LParamCRC16:%.04x\n", SVC_GetCRC16( 65535, &SYSMi_GetLauncherParamAddr()->body, SYSMi_GetLauncherParamAddr()->header.bodyLength ) );
|
||
PrintfSJIS( 1, 60, TXT_COLOR_RED,
|
||
"NandFirmResetParam:%.01x\n", *(u8 *)(OSi_GetNandFirmResetParam()) );
|
||
PrintfSJIS( 1, 72, TXT_COLOR_RED,
|
||
"McuVersion:%d\n", SYSMi_GetMcuVersion() );
|
||
#endif
|
||
|
||
// キー及びタッチ制御
|
||
ret = ProcessPads( pTitleList );
|
||
MoveByScrollBar();
|
||
|
||
// 描画関係
|
||
PollBackLightBrightness();
|
||
|
||
DrawScrollBar( pTitleList );
|
||
|
||
#ifdef DBGBNR
|
||
BannerDraw( selected, pTitleList );
|
||
#endif
|
||
|
||
// RTC情報の取得&表示
|
||
GetAndDrawRTCData( &g_rtcDraw, FALSE );
|
||
|
||
return ret;
|
||
}
|
||
|
||
// バックライトスイッチの表示
|
||
static void DrawBackLightSwitch(void)
|
||
{
|
||
NNS_G2dCharCanvasClearArea( &gCanvas, TXT_COLOR_NULL, B_LIGHT_DW_BUTTON_TOP_X + 24, B_LIGHT_DW_BUTTON_TOP_Y, 40, 13 );
|
||
PutStringUTF16( B_LIGHT_DW_BUTTON_TOP_X, B_LIGHT_DW_BUTTON_TOP_Y, TXT_COLOR_RED,
|
||
L"\xE01c \xE01b" );
|
||
PrintfSJIS( B_LIGHT_DW_BUTTON_TOP_X + 11, B_LIGHT_DW_BUTTON_TOP_Y, TXT_COLOR_RED,
|
||
"BL:%2d\n", LCFG_TSD_GetBacklightBrightness() );
|
||
}
|