/*---------------------------------------------------------------------------* Project: Horizon File: Updater.cpp 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. $Rev$ *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include "CommonLogger.h" namespace ConsoleRestore { using namespace ES_NAMESPACE; using namespace EC_NAMESPACE; /* ------------------------------------------------------------------- GetCustomerSupportCode -------------------------------------------------------------------- */ #define NIM_UPDATER_RESULT_CHECK(result) \ do { \ if (result.IsFailure()) \ { \ ECCustomerSupportCode csc; \ NN_UTIL_PANIC_IF_FAILED( \ nn::nim::Updater::GetCustomerSupportCode(&csc)); \ COMMON_LOGGER("CSCode: %d\n", csc); \ nn::dbg::PrintResult(result); \ s_Result = result; \ goto LABEL_FINALIZE; \ } \ } while(0) namespace { nn::Result s_Result = nn::ResultSuccess(); const size_t UPDATER_THREAD_STACK_SIZE = 0x1000; nn::os::Thread s_UpdaterThread; nn::os::StackBuffer s_UpdaterThreadStack; u64 s_Progress = 0; nn::Result PrintNetworkSetting() { nn::ac::NetworkSetting networkSetting; NN_UTIL_RETURN_IF_FAILED(nn::ac::LoadNetworkSetting(0, networkSetting)); COMMON_LOGGER("SSID: %s\n", networkSetting.wireless.essidSecurity.ssid); COMMON_LOGGER("DNS : %d.%d.%d.%d\n", networkSetting.ip.dns[0][0], networkSetting.ip.dns[0][1], networkSetting.ip.dns[0][2], networkSetting.ip.dns[0][3]); return nn::ResultSuccess(); } nn::Result ConnectNetwork() { nn::Result result = nn::ResultSuccess(); nn::ac::Config config; result = nn::ac::CreateDefaultConfig(&config); NN_UTIL_RETURN_IF_FAILED(result); result = nn::ac::ConnectWithoutEula(config); NN_UTIL_RETURN_IF_FAILED(result); NN_LOG("Success nn::ac::ConnectWithoutEula\n"); NN_UTIL_RETURN_IF_FAILED(PrintNetworkSetting()); return result; } nn::Result InitializeInternal() { nn::Result result = nn::ResultSuccess(); result = nn::ac::InitializeInternal(); NN_UTIL_RETURN_IF_FAILED(result); result = ConnectNetwork(); NN_UTIL_RETURN_IF_FAILED(result); return result; } nn::Result FinalizeInternal() { nn::Result result = nn::ResultSuccess(); nn::ac::CloseAll(); result = nn::ac::FinalizeInternal(); NN_UTIL_RETURN_IF_FAILED(result); return result; } } void UpdateThreadFunc() { nn::Result result; NN_LOG("********************UpdateThreadFunc Start********************\n"); nn::cfg::CTR::init::Initialize(); nn::cfg::CfgCountryCode country; nn::cfg::CfgRegionCode region; const char *regionStr; const char *countryStr; NN_UNUSED_VAR(regionStr); NN_UNUSED_VAR(countryStr); country = nn::cfg::GetCountry(); region = nn::cfg::GetRegion(); countryStr = nn::cfg::GetCountryCodeA2(country); regionStr = nn::cfg::GetRegionCodeA3(region); COMMON_LOGGER("[Updater] country:%2d:%s\n", country, countryStr); COMMON_LOGGER("[Updater] region :%2d:%s\n", region, regionStr); /* ------------------------------------------------------------------- Initialize -------------------------------------------------------------------- */ NN_LOG("[Updater] nn::nim::InitializeForUpdater\n"); result = nn::nim::InitializeForUpdater(); NIM_UPDATER_RESULT_CHECK(result); NN_LOG("[Updater] InitializeInternal\n"); result = InitializeInternal(); NIM_UPDATER_RESULT_CHECK(result); /* ------------------------------------------------------------------- StartNetworkUpdate -------------------------------------------------------------------- */ NN_LOG("[Updater] nn::nim::Updater::StartNetworkUpdate()\n"); result = nn::nim::Updater::StartNetworkUpdate(); NIM_UPDATER_RESULT_CHECK(result); /* ------------------------------------------------------------------- GetProgress -------------------------------------------------------------------- */ NN_LOG("[Updater] nn::nim::Updater::GetProgress()\n"); while(true) { nn::nim::NetworkUpdateProgress progress; NIM_UPDATER_RESULT_CHECK(nn::nim::Updater::GetProgress(&progress)); NIM_UPDATER_RESULT_CHECK(progress.lastResult); NN_LOG("\x1b[1A\x1b[K"); NN_LOG("Downloading %2lld/%2lld %8lld/%8lld (%d)\n", progress.downloadedTitleNum, progress.totalTitleNum, progress.currentDownloadedSize, progress.currentTotalSize, static_cast(progress.state)); // ゼロ除算を防ぐ if(progress.totalTitleNum == 0) { progress.totalTitleNum++; progress.downloadedTitleNum++; } if(progress.state > nn::nim::CTR::NUP_STATE_CHECKING) { s_Progress = progress.downloadedTitleNum * 100 / progress.totalTitleNum; } if (progress.state == nn::nim::NUP_STATE_NO_NEED) { COMMON_LOGGER("[Updater] No need to NetworkUpdate\n"); s_Progress = 100; break; } if (progress.state == nn::nim::NUP_STATE_FINISHED) { COMMON_LOGGER("[Updater] Finished NetworkUpdate\n"); s_Progress = 100; break; } nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(300)); } LABEL_FINALIZE: /* ------------------------------------------------------------------- Finalize -------------------------------------------------------------------- */ NN_LOG("[Updater] nn::nim::FinalizeForUpdater\n"); result = nn::nim::FinalizeForUpdater(); NIM_UPDATER_RESULT_CHECK(result); result = FinalizeInternal(); NIM_UPDATER_RESULT_CHECK(result); NN_LOG("[Updater] Finish nim Updater demo.\n"); } void StartFGNetworkUpdate() { NN_LOG("Start FGNetworkUpdate\n"); s_Result = nn::ResultSuccess(); s_UpdaterThread.Start(UpdateThreadFunc, s_UpdaterThreadStack); } void FinishFGNetworkUpdate() { NN_LOG("Finalize FGNetworkUpdate\n"); s_UpdaterThread.Join(); s_UpdaterThread.Finalize(); } bool IsNetworkUpdateFinished() { return s_UpdaterThread.IsValid() && !s_UpdaterThread.IsAlive(); } u32 GetUpdateProgress() { return s_Progress; } nn::Result GetUpdateResult() { return s_Result; } }