/*---------------------------------------------------------------------------* Project: TwlIPL File: DS_DownloadPlay.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$ *---------------------------------------------------------------------------*/ // ※※※ mb_private.hのPRINT_DEBUGを"1"にしていると、ダウンロード後に正常にブートできなくなっているので、注意。 #include #include // ここはとするのはOK? #include #include "mb_child.h" #include "mb_private.h" #include "misc.h" #include "DS_Setting.h" #include "DS_DownloadPlay.h" // define data------------------------------------------ #define PARENT_VIEW_NUM 4 // 親機情報リストの一画面表示数 #define PLIST_X 1 // 親機情報リストの表示X位置 #define PLIST_Y 4 // 親機情報リストの表示Y位置 #define MB_DMA_NO 2 // マルチブート用DMA番号 #define PRG_NEXT_SEQ_QUE_NUM 4 // 次のプログラムシーケンスを格納するキューの数 #define MY_GGID 0x00000000 // マルチブート用GGID #define G_INTRO_X 1 // ゲーム内容説明表示X位置 #define G_INTRO_Y 4 // ゲーム内容説明表示Y位置 #define G_MEMBER_X 1 // 通信メンバー表示X位置 #define G_MEMBER_Y 10 // 通信メンバー表示Y位置 #define MSG_VIEW_COUNT 75 // メッセージ表示Vカウント数 #define MSG_BLINK_COUNT 12 // メッセージ点滅カウント数 #define NINLOGO_LOAD_1D_CHAR // Nintendoロゴデータを1Dマッピングキャラクタでロードする。 // プログラムシーケンス typedef enum PrgSeq { PSEQ_READY = 0, PSEQ_INIT, PSEQ_INITIALIZING, PSEQ_ENDING, PSEQ_END, PSEQ_CANCELLED, PSEQ_DISCONNECTED_BY_PARENT, PSEQ_SCANNING, PSEQ_CONNECTING, PSEQ_CONNECT_SUCCEEDED, PSEQ_CONNECT_FAILED, PSEQ_REQ_REFUSED, PSEQ_MEMBER_FULL, PSEQ_DOWNLOAD_READY, PSEQ_DOWNLOADING, PSEQ_DOWNLOAD_COMPLETED, PSEQ_DOWNLOAD_FAILED, PSEQ_BOOT_REQ_WAIT, PSEQ_BOOT_READY, PSEQ_BOOT_START, PSEQ_BOOT_FAILED }PrgSeq; static char *str_prgSeq[] = { "PSEQ_READY", "PSEQ_INIT", "PSEQ_INITIALIZING", "PSEQ_ENDING", "PSEQ_END", "PSEQ_CANCELLED", "PSEQ_DISCONNECTED_BY_PARENT", "PSEQ_SCANNING", "PSEQ_CONNECTING", "PSEQ_CONNECT_SUCCEEDED", "PSEQ_CONNECT_FAILED", "PSEQ_REQ_REFUSED", "PSEQ_MEMBER_FULL", "PSEQ_DOWNLOAD_READY", "PSEQ_DOWNLOADING", "PSEQ_DOWNLOAD_COMPLETED", "PSEQ_DOWNLOAD_FAILED", "PSEQ_BOOT_REQ_WAIT", "PSEQ_BOOT_READY", "PSEQ_BOOT_START", "PSEQ_BOOT_FAILED", }; // 親機情報発見時間データ typedef struct FindTime { BOOL find; // 発見したかどうか int vcount; // 発見時間 }FindTime; // メッセージ表示ステータス typedef struct MsgViewStatus { u16 handle; u16 vcount; u16 flag; u16 color; const u8 *str; int (*nextProcessp)(void); }MsgViewStatus; // 次プログラムシーケンスを格納用キュー typedef struct PrgNextSeqQue { BOOL lock; u8 pad; u8 num; u8 top; u8 bottom; PrgSeq seq[ PRG_NEXT_SEQ_QUE_NUM ]; }PrgNextSeqQue; // extern data------------------------------------------ extern void MBw_SetMaxScanTime( u16 time ); extern int MBw_GetScanChannel( void ); extern void UnCompNintendoLogo( u16 *NintendoLogoDatap, u16 *dstp, u32 *temp ); // function's prototype declaration--------------------- // メインシーケンス static void SEQ_DSDL_init( void ); static int SEQ_DSDL_Connect( void ); static int SEQ_DSDL_Download( void ); static BOOL CheckNextSeq_Connect( void ); static BOOL CheckNextSeq_Download( void ); // 無線コールバック static void CallbackChild_MB( u32 status, void *arg ); // マルチブート用コールバック関数 // 表示系 static void DispTopScreen( void ); static void DispScanStatus( void ); static void DispParentNum( void ); static void DispParentList( void ); static void DispGameIntroduction( void ); static void DispPlayMember( void ); static void DispParentGameInfo( u32 view_no, u32 listNo, BOOL drawFixedDataFlag ); static void ClearDispParentGameInfo( u32 view_no, u32 listNo ); static void DispGameIntroduction_Core( u32 listNo ); static void DispPlayMember_Core( u32 listNo ); static void ClearDispGameIntroduction( void ); static void ClearDispPlayMember( void ); static void DecimalToString( u8 *dstp, const void *valuep, u8 drawLength, u8 size ); static void InitParentFindTime( void ); static void CountParentFindTime( void ); static BOOL CheckParentFindTime( u32 index ); static void CountAndDispTotalTime( void ); static void SetIconOBJ( u32 index ); static void ClearIconOBJ( u32 index ); static void SetDispMessage( u16 color, const u8 *str ); static BOOL DispMessage( void ); static void SetBlinkMessage( u16 color, const u8 *str ); static void DispBlinkMessage( void ); // Nintendoロゴ表示 static void InitDispNintendoLogo( void ); static BOOL DispNintendoLogo( void ); // その他 static void SetMyUserInfo( MBUserInfo *my ); static BOOL IsScanLock( void ); // 割り込み static void VBlankIntr_WDL( void ); // シーケンスキュー処理 static void InitPrgNextSeqQue( void ); static BOOL SetPrgNextSeqQue( PrgSeq seq ); static BOOL GetPrgNextSeqQue( PrgSeq *seqp ); static void LockPrgNextSeqQue( void ); static void UnlockPrgNextSeqQue( void ); static BOOL IsEmptyPrgNextSeqQue( void ); void SearchPatchAddress( void ); // global variable ------------------------------------- // static variable ------------------------------------- static int (*wdProcess)( void ); // 現在実行中のプロセスへのポインタ static int csrC; // メニューのカーソル位置 static int csrC_old; // メニューの前カーソル位置 static PrgSeq prgSeq; // プログラムシーケンス static PrgNextSeqQue nextSeq; // 次のプログラムシーケンスを格納するキュー static BOOL end_flag; // 終了フラグ static MsgViewStatus msgStat; // メッセージ表示ステータス static MBUserInfo myUser; // 自分のユーザー情報 static u16 tgid = 0; static u16 tp_touch_count = 0; static u32 gameInfoLostCount = 0; // 親機リストの表示に使用 static int unrenewalFlag; static int total_vcount; static int time_ms; // 親機発見時間ms static int time_sec; // 親機発見時間sec static u16 msgHandle; // メッセージ表示ハンドル static u16 dispGameInfoFlag; // 既に表示したゲーム情報をビットで示す。 static u16 dispIntroFlag; // ゲームの詳細データ描画フラグ static u16 dispMemberFlag; // ゲームの詳細データ描画フラグ static u16 gameName[ MB_GAME_NAME_LENGTH + 1 ]; // 親機ゲームネーム static u16 userName[ MB_USER_NAME_LENGTH + 1 ]; // 親機ユーザーネーム static u16 gameIntroduction[2][ MB_GAME_INTRO_LENGTH / 2 + 1 ]; // 親機ゲーム内容説明 static u16 playMember[ MB_MEMBER_MAX_NUM ][ MB_USER_NAME_LENGTH + 1]; // 通信メンバー名リスト static u8 parentListNo[ PARENT_VIEW_NUM ][ 4 ] ATTRIBUTE_ALIGN(2); // 親機リスト番号 static u32 objVramBuff[ (MB_ICON_DATA_SIZE * PARENT_VIEW_NUM + 0x20) / sizeof(u32) ] ATTRIBUTE_ALIGN(32); static FindTime findTime[ MB_GAME_INFO_RECV_LIST_NUM ]; // 親機発見時間データ static GXOamAttr oamBakM[ 128 ] ATTRIBUTE_ALIGN(32); // OAM バックアップ static const MbBeaconRecvStatus *mbrsp; // MBライブラリ用ワーク static u32 mbwork[ MB_CHILD_SYSTEM_BUF_SIZE / sizeof(u32) ]; // Nintendoロゴ表示 static int loop_count; static u32 ninLogoBuff[ 0x700 / sizeof(u32) ]; static MBDownloadFileInfo dlfileinfo; static u8 output_buffer[ AUTH_BUFFER_LEN ]; // const data ----------------------------------------- // 表示用文字列 static const u8 str_sura[] ATTRIBUTE_ALIGN(2) = "/"; static const u8 str_period[] ATTRIBUTE_ALIGN(2) = "."; static const u8 str_sec[] ATTRIBUTE_ALIGN(2) = "sec"; static const u8 str_disconnected[] ATTRIBUTE_ALIGN(2) = "disconnected by parent."; static const u8 str_connect_succeeded[] ATTRIBUTE_ALIGN(2) = "connect succeeded."; static const u8 str_connect_failed[] ATTRIBUTE_ALIGN(2) = "connect failed."; static const u8 str_req_refused[] ATTRIBUTE_ALIGN(2) = "req refused."; static const u8 str_member_full[] ATTRIBUTE_ALIGN(2) = "member full."; static const u8 str_downloading[] ATTRIBUTE_ALIGN(2) = "DOWNLOADING...."; static const u8 str_download_completed[] ATTRIBUTE_ALIGN(2) = "download completed."; static const u8 str_download_cancelled[] ATTRIBUTE_ALIGN(2) = "download cancelled."; // メニュー関数用 親機リストuカ字列リスト static u8 *str_parentListNo[] ATTRIBUTE_ALIGN(2) = { parentListNo[0], parentListNo[1], parentListNo[2], parentListNo[3], }; // メニュー関数用 メニュー構成データ static const MenuComponent childModeSel = { PARENT_VIEW_NUM, // 項目数 PLIST_X, // X位置(キャラ数) PLIST_Y, // Y位置( 〃  ) 0, // 次の項目へのX位置キャラ数 4, // 次の項目へのY位置キャラ数 3, WHITE, // 非選択色 HIGHLIGHT_Y, // 選択色 (const u8 **)&str_parentListNo, // メニュー項目文字列リスト }; //====================================================== // メインループ //====================================================== // 無線マルチブートのメインループ int DS_DownloadPlayMain(void) { SEQ_DSDL_init(); wdProcess = SEQ_DSDL_Connect; OS_TPrintf("MbBeaconRecvStatus:%d\n", sizeof(MbBeaconRecvStatus) ); while(1) { OS_WaitIrq(1, OS_IE_V_BLANK); ReadKeyPad(); mf_KEYPAD_rapid(); mbrsp = MB_GetBeaconRecvStatus(); if( wdProcess != NULL ) { if(wdProcess()) { return 0; } } //// ここから //// { static int touch = 0; TPData tmp1 ATTRIBUTE_ALIGN(32); TPData tmp2 ATTRIBUTE_ALIGN(32); while (TP_RequestRawSampling(&tmp1) != 0) {} TP_GetCalibratedPoint(&tmp2, &tmp1); if (tmp2.touch != touch) { tp_touch_count++; (void)DrawDecimalSJIS( 16, 0, RED, &tp_touch_count, 4, 2 ); OS_Printf("touch change %d validity = %d\n", tmp2.touch, tmp2.validity); touch = tmp2.touch; } } //// ここまで //// // if (SYSM_IsCardPulledOut()) { // カード抜け検出 if ( 0 ) { OS_Printf("Card is pulled out.\n"); #ifdef __DEBUG OS_Terminate(); #endif } if (PAD_DetectFold() == TRUE) { // スリープモードへの遷移 // SYSM_GoSleepMode(); } OS_PrintServer(); // ARM7からのプリントデバッグを処理する } return 0; } //====================================================== // 無線マルチブート(初期化) //====================================================== // 無線マルチブートの初期化 static void SEQ_DSDL_init(void) { GXS_SetVisiblePlane( GX_PLANEMASK_NONE ); GX_SetVisiblePlane ( GX_PLANEMASK_NONE ); (void)OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr_WDL); GXS_SetOBJVRamModeChar(GX_OBJVRAMMODE_CHAR_1D_32K); // NITROカードのROM内登録データのクリア MI_CpuClearFast( (void *)HW_ROM_HEADER_BUF, 0x160 ); // サブスクリーンのクリア MI_CpuClearFast( bgBakS, sizeof(bgBakS) ); MI_CpuFillFast ( (void *)HW_OAM, 192 , HW_OAM_SIZE ); MI_CpuFillFast ( (void *)oamBakS, 192 , sizeof(oamBakS) ); // 192でフィルしないと、未使用OBJが(0, 0)にキャラNo.0で全部表示されてしまう。 // メインスクリーンのクリア MI_CpuClearFast( (void *)HW_BG_VRAM, 0x10000 ); MI_CpuClearFast( (void *)HW_OBJ_VRAM, 0x8000 ); MI_CpuClearFast( bgBakM, sizeof(bgBakM) ); MI_CpuFillFast ( (void *)oamBakM, 192 , sizeof(oamBakM) ); // 192でフィルしないと、未使用OBJが(0, 0)にキャラNo.0で全部表示されてしまう。 MI_CpuFillFast ( (void *)HW_OAM, 192 , HW_OAM_SIZE ); MI_CpuCopyFast ( myPlttData, (void *)HW_BG_PLTT, sizeof(myPlttData) ); // BGパレット セット ClearAllStringSJIS(); (void)DrawStringSJIS ( 1, 0, WHITE, (const u8 *)"NICKNAME="); (void)DrawStringSJIS ( 1, 2, LIGHTGREEN, (const u8 *)"PARENT NUM ="); // (void)DrawStringSJIS ( 1, 22, LIGHTGREEN, (const u8 *)"GINFO LOST COUNT ="); (void)DrawStringSJISEx( 26, 2, CYAN, str_period, PARENT_VIEW_NUM); (void)DrawStringSJISEx( 29, 2, CYAN, str_sec, PARENT_VIEW_NUM); InitPrgNextSeqQue(); unrenewalFlag = 0; end_flag = FALSE; prgSeq = PSEQ_INIT; msgHandle = 0x8000; dispGameInfoFlag = 0; dispIntroFlag = 0; dispMemberFlag = 0; csrC_old = 2; // 最初はわざと違う値にしておく csrC = 0; { int i; for( i = 0; i < PARENT_VIEW_NUM; i++ ) { parentListNo[i][2] = '.'; parentListNo[i][3] = 0x00; } } SetMyUserInfo( &myUser ); // MBUserInfoをNITRO設定データから読み出してセット { // ニックネーム表示 u16 nickname[ MB_USER_NAME_LENGTH + 1 ]; ExUTF16_LEtoSJIS_BE( (u8 *)nickname, (u16 *)myUser.name, myUser.nameLength ); nickname[ myUser.nameLength ] = 0; (void)DrawStringSJIS( 8, 0, WHITE, (const u8 *)nickname ); } InitParentFindTime(); // 親機発見時間変数のクリア while( (SYSM_GetBootFlag() & BFLG_WM_INITIALIZED) == 0 ) {} LOADER_Init( NULL ); GXS_SetVisiblePlane( GX_PLANEMASK_OBJ | GX_PLANEMASK_BG1 ); GX_SetVisiblePlane ( GX_PLANEMASK_OBJ | GX_PLANEMASK_BG1 ); } // TOPスクリーンへの表示 static void DispTopScreen( void ) { SetTargetScreenSJIS( TOP_SCREEN ); ClearAllStringSJIS(); (void)DrawStringSJIS( 1, 0, YELLOW, (const u8 *)"WIRELESS DOWNLOAD"); (void)DrawStringSJIS( G_INTRO_X, G_INTRO_Y, LIGHTGREEN, (const u8 *)"GAME INTRODUCTION"); (void)DrawStringSJIS( G_MEMBER_X, G_MEMBER_Y, LIGHTGREEN, (const u8 *)"MEMBER LIST"); SetTargetScreenSJIS( BOTTOM_SCREEN ); } //====================================================== // 無線マルチブート(親機サーチ 〜 接続) //====================================================== // 無線マルチブートの接続シーケンス static int SEQ_DSDL_Connect(void) { // 現在のprgSeqに応じた処理 BOOL getSeqFlag = CheckNextSeq_Connect(); switch ( prgSeq ) { case PSEQ_INIT: // 子機モードの開始(ライブラリの初期化〜StartScanまでの流れを実行) if ( MB_Init( mbwork, &myUser, MY_GGID, tgid, MB_DMA_NO ) != WM_ERRCODE_SUCCESS ) { OS_Printf("MB init failed.\n"); break; } MB_CommSetChildStateCallback( CallbackChild_MB ); if ( MB_StartChild() != WM_ERRCODE_SUCCESS ) { OS_Printf("MB start failed.\n"); break; } tgid++; DispTopScreen(); prgSeq = PSEQ_INITIALIZING; break; case PSEQ_INITIALIZING: break; case PSEQ_SCANNING: // スキャン中は随時、次シーケンスチェックを行う。 case PSEQ_ENDING: if( !getSeqFlag ) { return 0; } break; case PSEQ_CONNECTING: // 接続中はキー入力を受け付けずにリターンする。(次シーケンスチェックは行う) return 0; case PSEQ_CONNECT_SUCCEEDED: // メッセージ表示後、ダウンロードシーケンスに移行。 if( DispMessage() ) { UnlockPrgNextSeqQue(); // シーケンスロック解除 wdProcess = SEQ_DSDL_Download; } return 0; case PSEQ_CONNECT_FAILED: // メッセージ表示後、スキャン再開。(スキャン再開そのものは、ライブラリが自動で行う。) if( DispMessage() ) { UnlockPrgNextSeqQue(); // シーケンスロック解除 prgSeq = PSEQ_SCANNING; } break; case PSEQ_DISCONNECTED_BY_PARENT: // 切断検出メッセージ表示設定。 if( DispMessage() ) { UnlockPrgNextSeqQue(); // シーケンスロック解除 prgSeq = PSEQ_INIT; } break; case PSEQ_CANCELLED: // 終了 return 0; default: break; } // カーソル移動 if(pad.trg & PAD_KEY_DOWN){ // カーソルの移動 if( ++csrC == MB_GAME_INFO_RECV_LIST_NUM ){ csrC = 0; } } if(pad.trg & PAD_KEY_UP){ if( --csrC & 0x80 ){ csrC = MB_GAME_INFO_RECV_LIST_NUM - 1; } } DrawMenu((u16)(csrC & (PARENT_VIEW_NUM - 1)), &childModeSel); // リスト番号(カーソル)の表示 DispParentNum(); // 発見親機数の表示 DispParentList(); // 親機リストの表示 DispScanStatus(); // WMスキャン状態の表示 CountAndDispTotalTime(); // トータル時間のカウント&表示 CountParentFindTime(); // 親機発見時間のカウント // 親機への接続 if(pad.trg & PAD_BUTTON_A) { if( mbrsp->usefulGameInfoFlag & (0x0001 << csrC) ) { if( MB_CommDownloadRequest( csrC ) == WM_ERRCODE_SUCCESS ) { // 接続開始 OS_Printf("start conntct to parent.\n"); prgSeq = PSEQ_CONNECTING; }else { OS_Printf("this parent info is invalid.\n"); } } }else if(pad.trg & PAD_BUTTON_B) { // 終了開始 if( prgSeq == PSEQ_SCANNING ) { OS_Printf("MB End start\n"); prgSeq = PSEQ_ENDING; // end_flag = TRUE; MB_End(); } }else if( pad.trg & PAD_BUTTON_R ) { unrenewalFlag ^= 0x01; // MB_SetUnrenewalGameInfoFlag( (BOOL)unrenewalFlag ); } csrC_old = csrC; // 旧カーソル位置の退避 return 0; } // 次シーケンスのチェック(コールバックでメインループとは非同期に返される次シーケンスへの移行をメインループのプログラム進行に合わせる。) static BOOL CheckNextSeq_Connect(void) { PrgSeq seq; // MBコールバックによって、シーケンスが移行していた場合の処理 if( GetPrgNextSeqQue( &seq) ) { // MBコールバックによって、シーケンスが移行していた場合の処理 prgSeq = seq; OS_Printf("prgSeq = %s\n", str_prgSeq[ prgSeq ]); switch( seq ) { case PSEQ_SCANNING: { /* u8 *ver = MBw_GetWLVersion(); (void)DrawStringSJIS( 21, 0, WHITE, (const u8 *)"WL ver=" ); (void)DrawStringSJIS( 26, 0, WHITE, (const u8 *)ver ); */ } break; case PSEQ_CONNECT_SUCCEEDED: // 接続成功メッセージ表示設定。 SetDispMessage( YELLOW, str_connect_succeeded ); LockPrgNextSeqQue(); // prgSeqをロックする。 return FALSE; case PSEQ_CONNECT_FAILED: // 接続失敗メッセージ表示設定。 SetDispMessage( RED, str_connect_failed); LockPrgNextSeqQue(); // prgSeqをロックする。 return FALSE; case PSEQ_DISCONNECTED_BY_PARENT: // 切断検出メッセージ表示設定。 SetDispMessage( RED, str_disconnected); LockPrgNextSeqQue(); // prgSeqをロックする。 return FALSE; case PSEQ_CANCELLED: // 終了 { u32 i; for( i = 0; i < PARENT_VIEW_NUM; i++ ) { ClearIconOBJ( i ); // 全アイコンの消去 } // if( end_flag ) { // ClearAllStringSJIS(); // SetTargetScreenSJIS( TOP_SCREEN ); // ClearAllStringSJIS(); // SetTargetScreenSJIS( BOTTOM_SCREEN ); // (void)DrawStringSJIS( 11, 11, WHITE, (const u8 *)"しゅうりょうしました。"); // }else { prgSeq = PSEQ_INIT; // } } return FALSE; } } return TRUE; // シーケンス移行がなかった場合もしくはFALSEリターンのシーケンスでなかった場合はTRUEリターン。 } //====================================================== // 無線マルチブート(ダウンロード) //====================================================== // 無線マルチブートのファイルダウンロードシーケンス static int SEQ_DSDL_Download(void) { static int count_old = 0; // 現在のprgSeqに応じた処理 BOOL getSeqFlag = CheckNextSeq_Download(); switch(prgSeq) { case PSEQ_REQ_REFUSED: case PSEQ_MEMBER_FULL: // メッセージ表示後、一旦終了して初期化からやり直し。 if( DispMessage() ) { UnlockPrgNextSeqQue(); // シーケンスロック解除 prgSeq = PSEQ_ENDING; wdProcess = SEQ_DSDL_Connect; MB_End(); } break; // ダウンロードファイル情報を受信し、ダウンロード準備ができた状態 case PSEQ_DOWNLOAD_READY: // if (pad.trg & PAD_BUTTON_A) { // ダウンロード開始 OS_Printf("Start download.\n"); ClearStringSJIS_handle(msgHandle); (void)MB_CommStartDownload(); SetBlinkMessage( YELLOW, str_downloading ); // } break; // ダウンロード中 case PSEQ_DOWNLOADING: if( getSeqFlag ) { DispBlinkMessage(); msgHandle = msgStat.handle; if( 1 ) { u16 percent = MB_GetChildProgressPercentage(); msgHandle = DrawDecimalSJIS( 16, 21, WHITE, &percent ,3, 2 ); } } break; // ダウンロード完了 case PSEQ_DOWNLOAD_COMPLETED: if( DispMessage() ) { { msgHandle = DrawStringSJIS( 4, 21, LIGHTGREEN, "Sign Digest...."); if ( ACSignDigest ( output_buffer, &dlfileinfo ) ) { ClearStringSJIS_handle( msgHandle ); msgHandle = DrawStringSJIS( 4, 21, LIGHTGREEN, "Digest SUCCEEDED."); }else { ClearStringSJIS_handle( msgHandle ); msgHandle = DrawStringSJIS( 4, 21, RED, "Digest FAILED."); } { int i; for ( i = 0; i < 120; i++ ) { SVC_WaitVBlankIntr(); } } ClearStringSJIS_handle( msgHandle ); } UnlockPrgNextSeqQue(); // シーケンスロック解除 prgSeq = PSEQ_BOOT_REQ_WAIT; msgHandle = DrawStringSJIS( 4, 21, WHITE, "Waiting BOOT-REQ from parent."); } break; // 親機からのブート許可待ち case PSEQ_BOOT_REQ_WAIT: break; // ダウンロードが完了し、ブート準備ができた状態 // case PSEQ_BOOT_READY: // (void)LOADER_Start(); // ここでARM7によって、ダウンロードプログラムの再配置を行う。 // return 1; // "1"でリターンすることで、無線マルチブートのメインループから抜けてIPL2に処理を戻す。 // 親機からのブート要求受信により、起動可否チェックを行う。(Nintendoロゴ表示&チェック) case PSEQ_BOOT_READY: if( DispNintendoLogo() ) { if( SYSM_CheckNinLogo( (u16 *)SYSM_GetCardRomHeader()->nintendo_logo ) ) { prgSeq = PSEQ_BOOT_START; }else { SetDispMessage( RED, (const u8 *)"Illegal game data."); prgSeq = PSEQ_BOOT_FAILED; } } break; // ブート開始 case PSEQ_BOOT_START: ClearStringSJIS_handle(msgHandle); SearchPatchAddress(); (void)LOADER_Start(); // ここでARM7によって、ダウンロードプログラムの再配置を行う。 return 1; // "1"でリターンすることで、無線マルチブートのメインループから抜けてIPL2に処理を戻す。 // ブート失敗 // 親機によって、接続が切断された状態 // キャンセルをした場合 case PSEQ_BOOT_FAILED: case PSEQ_DISCONNECTED_BY_PARENT: case PSEQ_CANCELLED: if( DispMessage() ) { // 指定メッセージを一定期間表示 UnlockPrgNextSeqQue(); // シーケンスロック解除 ClearStringSJIS_handle( msgHandle ); prgSeq = PSEQ_INIT; wdProcess = SEQ_DSDL_Connect; } break; default: break; } // Bボタンで終了処理を行う if( pad.trg & PAD_BUTTON_B ) { MB_End(); // キャンセル時は、親機サーチ状態からやり直す。 } DrawMenu((u16)(csrC & (PARENT_VIEW_NUM - 1)), &childModeSel); // リスト番号(カーソル)の表示 DispParentNum(); // 発見親機数の表示 DispParentList(); // 親機リストの表示 DispScanStatus(); // WMスキャン状態の表示 CountAndDispTotalTime(); // トータル時間のカウント&表示 CountParentFindTime(); // 親機発見時間のカウント return 0; } // 次シーケンスのチェック(コールバックでメインループとは非同期に返される次シーケンスへの移行をメインループのプログラム進行に合わせる。) static BOOL CheckNextSeq_Download(void) { PrgSeq seq; // MBコールバックによって、シーケンスが移行していた場合の処理 if( GetPrgNextSeqQue( &seq) ) { prgSeq = seq; OS_Printf("prgSeq = %s\n", str_prgSeq[ prgSeq ]); switch( seq ) { case PSEQ_REQ_REFUSED: // 接続拒否メッセージ表示設定 SetDispMessage( RED, str_req_refused); LockPrgNextSeqQue(); // prgSeqをロックする。 return FALSE; case PSEQ_MEMBER_FULL: // メンバーFULLメッセージ表示設定。 SetDispMessage( RED, str_member_full); LockPrgNextSeqQue(); // prgSeqをロックする。 return FALSE; case PSEQ_DOWNLOAD_READY: // ダウンロード準備完了 ClearStringSJIS_handle( msgHandle ); { msgHandle = DrawStringSJIS( 4, 21, WHITE, "Sign Decript...."); if ( ACSignDecrpto( output_buffer, &dlfileinfo ) ) { ClearStringSJIS_handle( msgHandle ); msgHandle = DrawStringSJIS( 4, 21, LIGHTGREEN, "Decript SUCCEEDED."); }else { ClearStringSJIS_handle( msgHandle ); msgHandle = DrawStringSJIS( 4, 21, RED, "Decript FAILED."); } { int i; for ( i = 0; i < 120; i++ ) { SVC_WaitVBlankIntr(); } } ClearStringSJIS_handle( msgHandle ); } msgHandle = DrawStringSJIS( 4, 21, WHITE, "PUSH [A] TO DOWNLOAD."); break; case PSEQ_DOWNLOAD_COMPLETED: // ダウンロード完了 ClearStringSJIS_handle( msgHandle ); SetDispMessage( YELLOW, str_download_completed ); LockPrgNextSeqQue(); // シーケンスロック return FALSE; // case PSEQ_BOOT_READY: // ブート準備完了 // ClearStringSJIS_handle( msgHandle ); // break; case PSEQ_BOOT_READY: // ブート準備完了 ClearStringSJIS_handle( msgHandle ); InitDispNintendoLogo(); break; case PSEQ_CANCELLED: ClearStringSJIS_handle( msgHandle ); SetDispMessage( RED, str_download_cancelled ); LockPrgNextSeqQue(); // シーケンスロック return FALSE; case PSEQ_DISCONNECTED_BY_PARENT: // 切断検出メッセージ表示設定。 ClearStringSJIS_handle( msgHandle ); SetDispMessage( RED, str_disconnected ); LockPrgNextSeqQue(); // prgSeqをロックする。 return FALSE; default: break; } } return TRUE; } //====================================================== // コールバック //====================================================== // 子機モードでのコールバック static void CallbackChild_MB( u32 status, void *arg ) { switch (status) { case MB_COMM_CSTATE_INIT_COMPLETE: // 初期化完了 OS_Printf("CB: init completed.\n"); (void)SetPrgNextSeqQue( PSEQ_SCANNING ); break; // case MB_COMM_CSTATE_END_COMPLETE: // マルチブート終了 // OS_Printf("CB: end completed.\n"); // (void)SetPrgNextSeqQue( PSEQ_END ); // break; case MB_COMM_CSTATE_REQ_REFUSED: // 親機からのエントリー拒否 OS_Printf("CB: request refused.\n"); (void)SetPrgNextSeqQue( PSEQ_REQ_REFUSED ); break; case MB_COMM_CSTATE_MEMBER_FULL: // ゲームが定員に達した OS_Printf("CB: member full.\n"); (void)SetPrgNextSeqQue( PSEQ_MEMBER_FULL ); break; case MB_COMM_CSTATE_CONNECT: // 親機への接続成功 OS_Printf("CB: connected.\n"); (void)SetPrgNextSeqQue( PSEQ_CONNECT_SUCCEEDED ); break; case MB_COMM_CSTATE_CONNECT_FAILED: // 親機への接続失敗 OS_Printf("CB: connect failed!\n"); (void)SetPrgNextSeqQue( PSEQ_CONNECT_FAILED ); break; case MB_COMM_CSTATE_DLINFO_ACCEPTED: // 親機からダウンロード情報を受信 OS_Printf("CB: dlinfo accepted.\n"); (void)SetPrgNextSeqQue( PSEQ_DOWNLOAD_READY ); MI_CpuCopy16( (void *)arg, (void *)&dlfileinfo, sizeof( MBDownloadFileInfo ) ) ; break; case MB_COMM_CSTATE_RECV_PROCEED: // 受信開始 OS_Printf("CB: recv proceed.\n"); (void)SetPrgNextSeqQue( PSEQ_DOWNLOADING ); break; case MB_COMM_CSTATE_RECV_COMPLETE: // 受信成功 OS_Printf("CB: recv completed.\n"); (void)SetPrgNextSeqQue( PSEQ_DOWNLOAD_COMPLETED ); break; case MB_COMM_CSTATE_BOOT_READY: // ブート準備完了 OS_Printf("CB: boot ready.\n"); // SYSMi_GetWork()->mb_flag = 1; // SYSMi_GetWork()->mb_ggid = *(u32 *)( MB_GetBeaconRecvStatus()->list[ pCwork->connectTargetNo ].bssDesc.gameInfo.ggid ); // SYSMi_GetWork()->mb_ggid = MB_GetBeaconRecvStatus()->list[ pCwork->connectTargetNo ].gameInfo.ggid; (void)SetPrgNextSeqQue( PSEQ_BOOT_READY ); break; case MB_COMM_CSTATE_CANCELLED: // ダウンロードキャンセル OS_Printf("CB: download cancel.\n"); (void)SetPrgNextSeqQue( PSEQ_CANCELLED ); break; case MB_COMM_CSTATE_DISCONNECTED_BY_PARENT: // 親機からの切断通知 OS_Printf("CB: disconnected by parent!\n"); (void)SetPrgNextSeqQue( PSEQ_DISCONNECTED_BY_PARENT ); break; case MB_COMM_CSTATE_GAMEINFO_LOST: gameInfoLostCount++; break; } } //====================================================== // 表示系サブルーチン //====================================================== // スキャン状態の表示 static void DispScanStatus(void) { #if 0 int channel = MBw_GetScanChannel(); (void)DrawHexSJIS( 13, 2, WHITE, &channel, 2); if( IsScanLock() ) { // スキャンロック中なら、その時間を表示 (void)DrawStringSJIS( 15, 2, RED, (const u8 *)"LOCK"); (void)DrawHexSJIS ( 19, 2, WHITE, &mbrsp->nowLockTimeCount, 4); }else { (void)DrawStringSJIS( 15, 2, RED, (const u8 *)" "); } #endif } // 発見した親機数の表示 static void DispParentNum(void) { int i; int num = 0; for (i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++) { // 親機数のカウント if( mbrsp->usefulGameInfoFlag & (0x0001 << i) ) num++; } (void)DrawDecimalSJIS( 10, 2, LIGHTGREEN, &num, 2, 4); } // 親機情報リストの表示 static void DispParentList(void) { u32 i; u32 listNo = (u32)( csrC & ~(PARENT_VIEW_NUM - 1) ); // 現在表示中のリストの先頭を算出(~表示数でマスク) u32 listNo_old = (u32)( csrC_old & ~(PARENT_VIEW_NUM - 1) ); // 前回表示したリストの先頭を算出 // (void)DrawDecimalSJISEx( 15, 22, WHITE, &gameInfoLostCount, 8, 4, 0); // ゲーム内容説明の表示 DispGameIntroduction(); // 通信メンバーの表示 DispPlayMember(); // 親機リストの表示 for( i = 0; i < PARENT_VIEW_NUM; i++ ) { if( (listNo != listNo_old) || !(mbrsp->usefulGameInfoFlag & (0x0001 << listNo)) ){ if( dispGameInfoFlag & (0x0001 << listNo_old) ) { // 表示リスト位置が変更 or 該当親機が有効でなくなった場合、前回表示データが既に表示済みならクリアする。 ClearDispParentGameInfo( i, listNo_old); dispGameInfoFlag ^= 0x0001 << listNo_old; } } if( mbrsp->usefulGameInfoFlag & (0x0001 << listNo) ) { // 該当リストbフデータが有効で、かつ未表示なら表示する。 DispParentGameInfo( i, listNo , !(dispGameInfoFlag & (0x0001 << listNo)) ); dispGameInfoFlag |= 0x0001 << listNo; } if( csrC != csrC_old ) { DecimalToString( parentListNo[i], &listNo, 2, 2); // ビュー画面の先頭リストナンバーからを文字列バッファに入れる。 } listNo++; listNo_old++; } } // ゲーム内容説明の表示 static void DispGameIntroduction( void ) { BOOL clear = FALSE; if( ( ( csrC != csrC_old ) && ( dispIntroFlag & (0x0001 << csrC_old) ) ) || ( !(mbrsp->usefulGameInfoFlag & (0x0001 << csrC)) && ( dispIntroFlag & (0x0001 << csrC) ) ) ) { ClearDispGameIntroduction(); // カーソルが動いて、前カーソル位置の詳細表示を行っていたか、 dispIntroFlag = 0; clear = TRUE; } if( (mbrsp->usefulGameInfoFlag & (0x0001 << csrC)) && !( dispIntroFlag & (0x0001 << csrC) ) ) { if ( !clear ){ // 現在カーソル位置のゲーム情報が有効で、まだ詳細表示を行っていなかったら表示。 ClearDispGameIntroduction(); } DispGameIntroduction_Core( (u32)csrC ); dispIntroFlag = (u16)( 0x0001 << csrC ); // カーソルが移動された時か、現在位置のゲーム情報が未表示の時にのみ表示 or クリアを行う。 } } // 通信メンバーのクリア&表示 static void DispPlayMember( void ) { BOOL clear = FALSE; if( ( ( csrC != csrC_old ) && ( dispMemberFlag & (0x0001 << csrC_old) ) ) || ( !(mbrsp->validGameInfoFlag & (0x0001 << csrC)) && ( dispMemberFlag & (0x0001 << csrC) ) ) ) { ClearDispPlayMember(); // カーソル位置のゲーム詳細情報を表示していて、そのゲーム情報が無効になったらクリア。 dispMemberFlag = 0; clear = TRUE; } if( (mbrsp->validGameInfoFlag & (0x0001 << csrC)) && !( dispMemberFlag & (0x0001 << csrC) ) ) { if ( !clear ){ // 現在カーソル位置のゲーム情報が有効で、まだ詳細表示を行っていなかったら表示。 ClearDispPlayMember(); } DispPlayMember_Core( (u32)csrC ); dispMemberFlag = (u16)( 0x0001 << csrC ); // カーソルが移動された時か、現在位置のゲーム情報が未表示の時にのみ表示 or クリアを行う。 } } // 指定された親機情報の表示 static void DispParentGameInfo( u32 view_no, u32 listNo, BOOL drawFixedDataFlag) { if(drawFixedDataFlag) { // 変化しない情報の表示 MI_CpuClear16( gameName, MB_GAME_NAME_LENGTH * 2 ); MI_CpuClear16( userName, MB_USER_NAME_LENGTH * 2 ); ExUTF16_LEtoSJIS_BE( (u8 *)gameName, (u16 *)mbrsp->list[ listNo ].gameInfo.fixed.gameName, MB_GAME_NAME_LENGTH * 2 ); ExUTF16_LEtoSJIS_BE( (u8 *)userName, (u16 *)mbrsp->list[ listNo ].gameInfo.fixed.parent.name, (u16)( mbrsp->list[ listNo ].gameInfo.fixed.parent.nameLength * 2)); // MI_CpuCopy16( mbrsp->list[ listNo ].gameInfo.fixed.gameName, gameName, MB_GAME_NAME_LENGTH * 2); // MI_CpuCopy16( mbrsp->list[ listNo ].gameInfo.fixed.parent.name, userName, mbrsp->list[ listNo ].gameInfo.fixed.parent.nameLength * 2); gameName[ MB_GAME_NAME_LENGTH ] = 0; userName[ mbrsp->list[ listNo ].gameInfo.fixed.parent.nameLength ] = 0; (void)ClearStringSJISEx( gameName, view_no); (void)ClearStringSJISEx( userName, view_no); (void)DrawStringSJISEx( 9, (PLIST_Y + (int)view_no*4), WHITE, gameName, view_no); (void)DrawStringSJISEx( 9, (PLIST_Y + (int)view_no*4 + 2), WHITE, userName, view_no); (void)DrawStringSJISEx( 26, (PLIST_Y + (int)view_no*4), YELLOW, str_sura, view_no); (void)DrawDecimalSJIS ( 27, (PLIST_Y + (int)view_no*4), YELLOW, &mbrsp->list[ listNo ].gameInfo.fixed.maxPlayerNum, 2, 1); // 親機発見時間の表示 (void)CheckParentFindTime( listNo ); // ここで親機を発見しているかを再確認しておく。 time_ms = (int)findTime[listNo].vcount * 17; time_sec = time_ms / 1000; time_ms = (time_ms % 1000) / 10; (void)DrawDecimalSJISEx( 23, (PLIST_Y + (int)view_no*4 + 2), CYAN, &time_sec, 4, 4, view_no); (void)DrawDecimalSJISEx( 27, (PLIST_Y + (int)view_no*4 + 2), CYAN, &time_ms, 2, 4, view_no); (void)DrawStringSJISEx ( 26, (PLIST_Y + (int)view_no*4 + 2), CYAN, str_period, view_no); (void)DrawStringSJISEx ( 29, (PLIST_Y + (int)view_no*4 + 2), CYAN, str_sec, view_no); SetIconOBJ( listNo ); // アイコンの表示 } { // 変化する情報(現メンバー数・親機寿命カウントの表示) (void)DrawDecimalSJIS( 24, (PLIST_Y + (int)view_no*4), YELLOW, &mbrsp->list[ listNo ].gameInfo.volat.nowPlayerNum, 2, 1); (void)DrawHexSJIS ( 19, (PLIST_Y + (int)view_no*4 + 2), CYAN, &mbrsp->list[ listNo ].lifetimeCount, 4); { u16 color = RED; if ( mbrsp->validGameInfoFlag & ( 0x0001 << listNo ) ) { color = CYAN; } (void)DrawHexSJIS ( 19, (PLIST_Y + (int)view_no*4), color, &mbrsp->list[ listNo ].gameInfo.seqNoVolat, 2); } } } // 指定された親機情報の表示クリア static void ClearDispParentGameInfo( u32 view_no, u32 listNo) { // ※これらの変数のアドレスは、DispParentGameInfo側のものと一致してないと、表示をクリアすることができないので注意。(自動変数で表示するときはアドレスが変わってしまう) // (これはDrawStringSJIS関数の仕様) ClearStringSJISEx( gameName, view_no ); // ゲーム名 ClearStringSJISEx( userName, view_no ); // ユーザー名 ClearStringSJISEx( &time_sec, view_no ); // 親機発見時間sec ClearStringSJISEx( &time_ms, view_no ); // 親機発見時間ms ClearStringSJISEx( (void *)str_sura, view_no ); // "/" ClearStringSJISEx( (void *)str_period, view_no ); // "." ClearStringSJISEx( (void *)str_sec, view_no ); // "sec" ClearStringSJIS ( (void *)&mbrsp->list[ listNo ].lifetimeCount ); // 親機寿命カウント ClearStringSJIS ( (void *)&mbrsp->list[ listNo ].gameInfo.volat.nowPlayerNum ); // プレイ人数 ClearStringSJIS ( (void *)&mbrsp->list[ listNo ].gameInfo.fixed.maxPlayerNum ); // 最大プレイ人数 ClearStringSJIS ( (void *)&mbrsp->list[ listNo ].gameInfo.seqNoVolat ); // 最大プレイ人数 ClearIconOBJ( listNo ); // アイコンの消去 } // ゲーム内容説明の表示(実処理) static void DispGameIntroduction_Core( u32 listNo ) { int i; const u16 *strp = mbrsp->list[ listNo ].gameInfo.fixed.gameIntroduction; u16 *dstp; u16 gameIntroTmp[ MB_GAME_INTRO_LENGTH / 2 + 1 ]; MI_CpuClear16( gameIntroduction[0], (MB_GAME_INTRO_LENGTH / 2 + 1) * sizeof(u16) ); MI_CpuClear16( gameIntroduction[1], (MB_GAME_INTRO_LENGTH / 2 + 1) * sizeof(u16) ); dstp = gameIntroTmp; for ( i = 0; i < MB_GAME_INTRO_LENGTH / 2; i++ ) { // バイト単位でのコピーなので、1行分は、MB_GAME_INTRO_LENGTH/2*2。 if( ( *strp == NULL) || ( *strp == 0x000a ) ) { *dstp++ = 0x0000; }else { *dstp++ = *strp++; } } ExUTF16_LEtoSJIS_BE( (u8 *)gameIntroduction[ 0 ], gameIntroTmp, MB_GAME_INTRO_LENGTH / 2 ); if( *strp == 0x000a ) { strp++; } dstp = gameIntroTmp; for ( i = 0; i < MB_GAME_INTRO_LENGTH / 2; i++ ) { if( ( *strp == NULL) || ( *strp == 0x000a ) ) { *dstp++ = 0x00; }else { *dstp++ = *strp++; } } ExUTF16_LEtoSJIS_BE( (u8 *)gameIntroduction[ 1 ], gameIntroTmp, MB_GAME_INTRO_LENGTH / 2 + 1 ); ClearDispGameIntroduction(); SetTargetScreenSJIS( TOP_SCREEN ); (void)DrawStringSJIS( ( G_INTRO_X + 1 ), ( G_INTRO_Y + 2 ), WHITE, (const u8 *)gameIntroduction[0] ); (void)DrawStringSJIS( ( G_INTRO_X + 1 ), ( G_INTRO_Y + 4 ), WHITE, (const u8 *)gameIntroduction[1] ); SetTargetScreenSJIS( BOTTOM_SCREEN ); } // ゲーム内容説明表示のクリア static void ClearDispGameIntroduction( void ) { SetTargetScreenSJIS( TOP_SCREEN ); ClearStringSJIS( (void *)gameIntroduction[0] ); ClearStringSJIS( (void *)gameIntroduction[1] ); SetTargetScreenSJIS( BOTTOM_SCREEN ); } // 通信メンバーの表示(実処理) static void DispPlayMember_Core( u32 listNo ) { int n, count_x; u16 nameLength; int pos_x, pos_y; const MBUserInfo *memberp = &mbrsp->list[ listNo ].gameInfo.volat.member[ 0 ]; u16 *dstp; SetTargetScreenSJIS( TOP_SCREEN ); MI_CpuClear16( playMember, sizeof(playMember) ); count_x = 0; pos_x = G_MEMBER_X + 1; pos_y = G_MEMBER_Y + 2; for ( n = 0; n < MB_MEMBER_MAX_NUM; n++ ) { if( memberp->nameLength > MB_USER_NAME_LENGTH ) { // 名前長のチェック nameLength = MB_USER_NAME_LENGTH; }else { nameLength = memberp->nameLength; } dstp = playMember[ n ]; if( mbrsp->list[ listNo ].gameInfo.volat.nowPlayerFlag & (0x0002 << n ) ) { ExUTF16_LEtoSJIS_BE( (u8 *)dstp, (u16 *)memberp->name, nameLength ); playMember[ n ][ nameLength ] = 0; (void)DrawStringSJIS( pos_x, pos_y, WHITE, (const u8 *)playMember[ n ] ); }else { MI_CpuCopy16( (void *)"----------", (void *)playMember[ n ], MB_USER_NAME_LENGTH + 1); (void)DrawStringSJIS( pos_x, pos_y, WHITE, playMember[ n ] ); } memberp++; if( ++count_x == 3 ) { // 表示位置の算出 pos_x -= 20; pos_y += 2; count_x = 0; }else { pos_x += 10; } } SetTargetScreenSJIS( BOTTOM_SCREEN ); } // 通信メンバー表示のクリア static void ClearDispPlayMember( void ) { int i; SetTargetScreenSJIS( TOP_SCREEN ); for( i = 0; i < MB_MEMBER_MAX_NUM + 1; i++ ) { ClearStringSJIS( (void *)playMember[ i ] ); } SetTargetScreenSJIS( BOTTOM_SCREEN ); } // 10進データを文字列に変換 static void DecimalToString(u8 *dstp, const void *valuep, u8 drawLength, u8 size) { u16 count; u32 mask, divisor, target; mask = 0xff; while(--size > 0) { mask = (mask << 8) | 0xff; } target=(*(u32 *)valuep) & mask; count=10; divisor=1000000000; while(count) { CP_SetDiv32_32(target, divisor); if (count <= drawLength) { *dstp++ = (u8)(CP_GetDivResult32()+0x0030); } target=(u32)CP_GetDivRemainder32(); CP_SetDiv32_32(divisor, 10); divisor=(u32)CP_GetDivResult32(); count--; } } // 親機発見時間変数のクリア static void InitParentFindTime( void ) { int i; for( i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++) { findTime[i].find = FALSE; findTime[i].vcount = 0; } total_vcount = 0; } // 親機発見時間のカウント static void CountParentFindTime( void ) { u32 i; for( i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++ ) { if( !CheckParentFindTime( i ) ) { findTime[i].vcount = total_vcount; // 親機情報が見つかるまでカウント } } } // 親機情報が揃ったかどうかチェックして、発見時間カウントを停止する。 static BOOL CheckParentFindTime( u32 index ) { if( mbrsp->validGameInfoFlag & (0x01 << index) ) { // 親機情報が発見されたなら、カウントを停止する。 findTime[ index ].find = TRUE; } return findTime[ index ].find; } // トータル時間のカウント&表示 static void CountAndDispTotalTime( void ) { total_vcount++; time_ms = total_vcount * 17; time_sec = time_ms / 1000; time_ms = (time_ms % 1000) / 10; (void)DrawDecimalSJISEx( 23, 2, CYAN, &time_sec, 4, 4, PARENT_VIEW_NUM); (void)DrawDecimalSJISEx( 27, 2, CYAN, &time_ms, 2, 4, PARENT_VIEW_NUM); } // アイコンOBJのロード static void SetIconOBJ( u32 index ) { u16 view_no = (u16)( index & 0x03 ); const MBIconInfo *iconp = &mbrsp->list[ index ].gameInfo.fixed.icon; GXS_LoadOBJPltt( iconp->palette, (u32)( MB_ICON_PALETTE_SIZE * view_no ), MB_ICON_PALETTE_SIZE ); MI_CpuCopyFast( iconp->data, (void *)((u32)objVramBuff + 0x20 + MB_ICON_DATA_SIZE * view_no), MB_ICON_DATA_SIZE ); G2_SetOBJAttr( (GXOamAttr*)&oamBakS[ view_no ], // OAM pointer 8 * (PLIST_X + 3), // X position 8 * PLIST_Y + (view_no * 32), // Y position 0, // Priority GX_OAM_MODE_NORMAL, // Bitmap mode FALSE, // mosaic off GX_OAM_EFFECT_NONE, // affine off GX_OAM_SHAPE_32x32, // 16x16 size GX_OAM_COLOR_16, // 16 color 1 + view_no * 16, // charactor view_no, // palette 0); // affine } // アイコンOBJのクリア static void ClearIconOBJ( u32 index ) { u16 view_no = (u16)( index & 0x03 ); u16 *oamp = (u16 *)&oamBakS[ view_no ]; *oamp++ = 192; // Y座標を画面外に。(オール0クリアではダメ) *oamp++ = 0; *oamp++ = 0; *oamp = 0; } // メッセージ表示のセット static void SetDispMessage( u16 color, const u8 *str ) { msgStat.vcount = MSG_VIEW_COUNT; msgStat.color = color; msgStat.str = str; } // メッセージ表示 static BOOL DispMessage(void) { if( msgStat.vcount == MSG_VIEW_COUNT ) { msgStat.handle = DrawStringSJIS( 4, 21, msgStat.color, msgStat.str ); } if ( --msgStat.vcount == 0 ) { ClearStringSJIS_handle( msgStat.handle ); return TRUE; } return FALSE; } // メッセージ表示のセット(点滅表示) static void SetBlinkMessage( u16 color, const u8 *str ) { msgStat.vcount = MSG_BLINK_COUNT; msgStat.flag = 1; msgStat.color = color; msgStat.str = str; } // メッセージ表示 static void DispBlinkMessage( void ) { if( ( msgStat.vcount == MSG_BLINK_COUNT ) && msgStat.flag ) { msgStat.handle = DrawStringSJIS( 4, 21, msgStat.color, msgStat.str ); } if ( --msgStat.vcount == 0 ) { ClearStringSJIS_handle( msgStat.handle ); msgStat.flag ^= 0x01; msgStat.vcount = MSG_BLINK_COUNT; } } //============================================================================= // Nintendoロゴ表示 //============================================================================= // Nintendoロゴ表示の初期化 static void InitDispNintendoLogo( void ) { int i; u16 *palettep = (u16 *)(HW_OBJ_PLTT + 0x20 * 15 ) + 1; // パレット15のカラー1に。 *palettep++ = 0x7fff; *palettep = 0x1111; // TOP画面の全表示クリア SetTargetScreenSJIS( TOP_SCREEN ); ClearAllStringSJIS(); SetTargetScreenSJIS( BOTTOM_SCREEN ); // 画面上に受信したゲームのNintendoロゴを表示する。 #ifdef NINLOGO_LOAD_1D_CHAR // 1Dマッピングでのロード&表示 GX_SetOBJVRamModeChar( GX_OBJVRAMMODE_CHAR_1D_32K ); SYSM_LoadNintendoLogo1D( (u16 *)SYSM_GetCardRomHeader()->nintendo_logo, (u16 *)( HW_OBJ_VRAM + 0x40 ), 1, ninLogoBuff ); // SYSM_LoadNintendoLogo1D( (u16 *)SYSROM9_NINLOGO_ADR, (u16 *)( HW_OBJ_VRAM + 0x40 ), 1, ninLogoBuff ); for ( i = 0; i < 3; i++ ) { G2_SetOBJAttr( &oamBakM[ 10 + i ], // OAM pointer 72 + 32 * i, // X position 88, // Y position 0, // Priority GX_OAM_MODE_NORMAL, // Bitmap mode FALSE, // mosaic off GX_OAM_EFFECT_NONE, // affine off GX_OAM_SHAPE_32x8, // 16x16 size GX_OAM_COLOR_16, // 16 color 0x2 + i * 4, // charactor 15, // palette 0); // affine } { G2_SetOBJAttr( &oamBakM[ 13 ], // OAM pointer 72 + 32 * 3, // X position 88, // Y position 0, // Priority GX_OAM_MODE_NORMAL, // Bitmap mode FALSE, // mosaic off GX_OAM_EFFECT_NONE, // affine off GX_OAM_SHAPE_8x8, // 16x16 size GX_OAM_COLOR_16, // 16 color 0x2 + 3 * 4, // charactor 15, // palette 0); // affine } for ( i = 0; i < 3; i++ ) { G2_SetOBJAttr( &oamBakM[ 14 + i ], // OAM pointer 72 + 32 * i, // X position 96, // Y position 0, // Priority GX_OAM_MODE_NORMAL, // Bitmap mode FALSE, // mosaic off GX_OAM_EFFECT_NONE, // affine off GX_OAM_SHAPE_32x8, // 16x16 size GX_OAM_COLOR_16, // 16 color 0x0f + i * 4, // charactor 15, // palette 0); // affine } { G2_SetOBJAttr( &oamBakM[ 17 ], // OAM pointer 72 + 32 * 3, // X position 96, // Y position 0, // Priority GX_OAM_MODE_NORMAL, // Bitmap mode FALSE, // mosaic off GX_OAM_EFFECT_NONE, // affine off GX_OAM_SHAPE_8x8, // 16x16 size GX_OAM_COLOR_16, // 16 color 0xf + 3 * 4, // charactor 15, // palette 0); // affine } #else // 2Dマッピングでのロード&表示 GX_SetOBJVRamModeChar( GX_OBJVRAMMODE_CHAR_2D ); SYSM_LoadNintendoLogo2D( (u16 *)SYSM_GetCardRomHeader()->nintendo_logo, (u16 *)( HW_OBJ_VRAM + 0x40 ), 1, ninLogoBuff ); // SYSM_LoadNintendoLogo2D( (u16 *)SYSROM9_NINLOGO_ADR, (u16 *)( HW_OBJ_VRAM + 0x40 ), 1, ninLogoBuff ); for ( i = 0; i < 4; i++ ) { G2_SetOBJAttr( &oamBakM[11 + i], // OAM pointer 72 + 32 * i, // X position 88, // Y position 0, // Priority GX_OAM_MODE_NORMAL, // Bitmap mode FALSE, // mosaic off GX_OAM_EFFECT_NONE, // affine off GX_OAM_SHAPE_32x16, // 16x16 size GX_OAM_COLOR_16, // 16 color 0x2 + i * 4, // charactor 15, // palette 0); // affine } #endif loop_count = 120; } // Nintendoロゴ表示 static BOOL DispNintendoLogo( void ) { if( --loop_count == 0 ) { { int i; for ( i = 0; i < 4; i++ ) { G2_SetOBJPosition( &oamBakM[ 11 + i ], 0, 192 ); } } return TRUE; } return FALSE; } //============================================================================= // その他サブルーチン //============================================================================= // 自分のユーザー情報をNITRO設定データから読み出してセット static void SetMyUserInfo( MBUserInfo *my ) { NvNickname *nickname = NCD_GetNickname(); MI_CpuCopy16( nickname->str, my->name, (u32)( nickname->length * 2 ) ); my->nameLength = nickname->length; my->playerNo = 0; // とりあえず0にする。 my->favoriteColor = NCD_GetFavoriteColor(); } // 現在スキャンロック中かどうかを取得する。 static BOOL IsScanLock(void) { return mbrsp->nowScanTargetFlag ? TRUE : FALSE; } //============================================================================= // 割り込みルーチン //============================================================================= // Vブランク割り込み static void VBlankIntr_WDL(void) { // OAM, BG-VRAMの更新 DC_FlushRange (oamBakM, sizeof(oamBakM)); DC_FlushRange (oamBakS, sizeof(oamBakS)); DC_FlushRange (bgBakM, sizeof(bgBakM)); DC_FlushRange (bgBakS, sizeof(bgBakS)); DC_FlushRange (objVramBuff, sizeof(objVramBuff)); MI_CpuCopyFast(oamBakM, (void*)HW_OAM, sizeof(oamBakM)); MI_CpuCopyFast(oamBakS, (void*)HW_DB_OAM, sizeof(oamBakS)); MI_CpuCopyFast(bgBakM, (void*)(HW_BG_VRAM + 0xf000), sizeof(bgBakM)); MI_CpuCopyFast(bgBakS, (void*)(HW_DB_BG_VRAM + 0xf000), sizeof(bgBakS)); MI_CpuCopyFast(objVramBuff, (void*)HW_DB_OBJ_VRAM, sizeof(objVramBuff)); //---- 割り込みチェックフラグ OS_SetIrqCheckFlag(OS_IE_V_BLANK); } //============================================================================= // プログラムシーケンスキュー処理 //============================================================================= // キュー初期化 static void InitPrgNextSeqQue( void ) { MI_CpuClear16( &nextSeq, sizeof(nextSeq) ); } // 次のPrgSeqをキューにセットする。 static BOOL SetPrgNextSeqQue( PrgSeq seq ) { BOOL preIRQ = OS_DisableIrq(); BOOL retval = FALSE; if( nextSeq.num != PRG_NEXT_SEQ_QUE_NUM ) { nextSeq.seq[ nextSeq.bottom ] =seq; nextSeq.num++; nextSeq.bottom++; if( nextSeq.bottom == PRG_NEXT_SEQ_QUE_NUM ) { nextSeq.bottom = 0; } retval = TRUE; } (void)OS_RestoreIrq( preIRQ ); return retval; } // 次のPrgSeqをキューから取り出す static BOOL GetPrgNextSeqQue( PrgSeq *seqp ) { BOOL preIRQ = OS_DisableIrq(); BOOL retval = FALSE; if( ( !nextSeq.lock ) && ( nextSeq.num != 0 ) ) { // キューがロックされておらず、かつ次Seqが存在するなら、キューから取り出し。 *seqp = nextSeq.seq[ nextSeq.top ]; nextSeq.num--; nextSeq.top++; if( nextSeq.top == PRG_NEXT_SEQ_QUE_NUM ) { nextSeq.top = 0; } retval = TRUE; } (void)OS_RestoreIrq( preIRQ ); return retval; } // キューをロックする。(ロック中はGetPrgNextSeqQueで次Seqを取り出せなくなります。) static void LockPrgNextSeqQue(void) { nextSeq.lock = TRUE; } // キューのロック解除。 static void UnlockPrgNextSeqQue(void) { nextSeq.lock = FALSE; } // キューが空か? static BOOL IsEmptyPrgNextSeqQue(void) { return nextSeq.num ? FALSE : TRUE; } static const u32 searchCode[] = { 0xe59f1028, 0xe59f2028, 0xe1d200b0, 0xe2100001, 0x1afffffc, 0xe1d100b0, 0xe3500006, 0x0afffff9, 0xe1d100b0, 0xe3500005, 0x0afffff6, 0xe12fff1e, 0x04808214, 0x0480819c, }; void SearchPatchAddress( void ) { MBDownloadFileInfo *dlfinfo = (MBDownloadFileInfo *)MB_DOWNLOAD_FILEINFO_ADDRESS; BOOL find = FALSE; u32 *tgtp = (u32 *)MB_ARM7_STATIC_RECV_BUFFER; u32 size = dlfinfo->seg[ 2 ].size >> 2; while( size-- ) { if( *tgtp++ == searchCode[0] ) { u32 *srcp = (u32 *)&searchCode[ 1 ]; u32 *checkp = tgtp ; int i = sizeof( searchCode ) / sizeof(u32) - 1; while( i-- ) { if( *srcp++ != *checkp++ ) break; } if( i < 0 ) { u32 addr = (u32)tgtp - 0x04 + 0x18; OS_TPrintf("Found! -> 0x%08x\n", addr ); find = TRUE; } } } if( !find ) { OS_TPrintf("Not found.\n"); } }