/*---------------------------------------------------------------------------* Project: Horizon File: main.cpp Copyright (C)2009 Nintendo Co., Ltd. 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. $Rev$ *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Drawer.h" namespace { char s_updaterBuffer[1<<20] NN_ATTRIBUTE_ALIGN(4096); // デモの初期化 void Initialize() { // os の初期化 nn::os::Initialize(); // NuiShellの初期化 (CUPに必須) NN_UTIL_PANIC_IF_FAILED(nn::ns::CTR::InitializeForShell()); // ndmの初期化 nn::ndm::Initialize(); // 全デーモンの自律動作をacの自動接続も含めて止める nn::ndm::SuspendScheduler(); // amの初期化 nn::am::InitializeForSystemMenu(); // fsの初期化 (カード確認用) nn::fs::Initialize(); // appletの初期化 nn::applet::Enable(); nn::cfg::Initialize(); } nn::Result UpdateCore() { nn::Result result; nn::cup::ProgressInfo info; /********************** アップデート*******************/ NN_UTIL_RETURN_IF_FAILED(nn::cup::CTR::DoUpdate()); // ステータスがStartedになるまで、プログレスは取得できない do{ result = nn::cup::CTR::GetProgressInfo(&info); NN_UTIL_RETURN_IF_FAILED(result); nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(40)); }while(info.state==nn::cup::CTR::UPDATE_STATE_INITIALIZING); // 抜けた際のstateがFAILEDかどうか確認 if(info.state==nn::cup::CTR::UPDATE_STATE_FAILED){ NN_UTIL_RETURN_IF_FAILED(info.lastResult); } /********************* アップデート中 ******************/ do{ result = nn::cup::CTR::GetProgressInfo(&info); NN_UTIL_RETURN_IF_FAILED(result); nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(40)); }while(info.state==nn::cup::CTR::UPDATE_STATE_STARTED); // 抜けた際のstateがFAILEDかどうか確認 if(info.state==nn::cup::CTR::UPDATE_STATE_FAILED){ NN_UTIL_RETURN_IF_FAILED(info.lastResult); } /***************** アップデート終了中 ******************/ do{ result = nn::cup::CTR::GetProgressInfo(&info); NN_UTIL_RETURN_IF_FAILED(result); nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(40)); }while(info.state==nn::cup::CTR::UPDATE_STATE_FINALIZING); // 抜けた際のstateがFAILEDかどうか確認 if(info.state==nn::cup::CTR::UPDATE_STATE_FAILED){ NN_UTIL_RETURN_IF_FAILED(info.lastResult); } /******************* アップデート終了 *******************/ return nn::ResultSuccess(); } nn::Result UpdateSequence(bool *isHandledError) { nn::Result result; nn::Result lastResult=nn::ResultSuccess(); /********************* CUPの初期化 *******************/ result=nn::cup::CTR::Initialize(s_updaterBuffer,sizeof(s_updaterBuffer)); if(result==nn::cup::CTR::ResultUpdatePartitionNotFound()){ *isHandledError=true; return result; } if(result==nn::cup::CTR::ResultUpdateNotRequired()){ *isHandledError=true; return result; } if(result==nn::cup::CTR::ResultInvalidUpdatePartitionFormat()){ *isHandledError=true; return result; } NN_UTIL_RETURN_IF_FAILED(result); lastResult=UpdateCore(); // Initializeに成功した場合のみ、再びInitializeするためにFinalizeが必要 NN_UTIL_RETURN_IF_FAILED(nn::cup::CTR::Finalize()); return lastResult; } } extern "C" void nnMain() { NN_LOG("Start cup demo\n"); nn::Result result; Initialize(); // ロゴ表示開始 StartDrawerThread(); nn::ProgramId MMEN_PROGRAM_ID = 0x0004003000008202; nn::cfg::CfgRegionCode region = nn::cfg::GetRegion(); switch(region) { case nn::cfg::CFG_REGION_AMERICA: { MMEN_PROGRAM_ID = 0x0004003000008f02; } break; case nn::cfg::CFG_REGION_EUROPE: case nn::cfg::CFG_REGION_AUSTRALIA: { MMEN_PROGRAM_ID = 0x0004003000009802; } break; case nn::cfg::CFG_REGION_JAPAN: { MMEN_PROGRAM_ID = 0x0004003000008202; } break; } nn::am::ProgramInfo outInfos; result = nn::am::GetProgramInfos(&outInfos, nn::fs::MEDIA_TYPE_NAND, &MMEN_PROGRAM_ID, 1); if (result.IsSuccess()) { /******************** CUPの実行 *******************/ bool isHandledError = false; result = UpdateSequence(&isHandledError); if (isHandledError == false && result.IsFailure()) { { // TODO:それ以外の場合は、エラーアプレットを表示 } } } else if(result == nn::am::ResultNotFound()) { // TODO:HOMEメニューが無いエラーをエラーアプレットで表示する } nn::os::Tick before = nn::os::Tick::GetSystemCurrent(); const u8 SHUTDOWN_WAIT_SECONDS = 2; for(;;) { // 画面描画 if (result.IsSuccess() || result == nn::cup::CTR::ResultUpdateNotRequired()) { // 成功したので終了処理に入る nn::os::Tick current = nn::os::Tick::GetSystemCurrent(); if ((current - before).ToTimeSpan().GetSeconds() > SHUTDOWN_WAIT_SECONDS) { NotifyFinished(); break; } } else { // 失敗したのでエラー表示を続ける NotifyFailed(0); } if (nn::applet::IsExpectedToCloseApplication()) { nn::applet::PrepareToCloseApplication(); nn::applet::CloseApplication(); } if (nn::applet::IsExpectedToProcessPowerButton()) { NotifyFinished(); break; } nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(16)); } FinalizeDrawerThread(); nn::ns::ShutdownAsync(); nn::ns::FinalizeForShell(); }