ctr_Repair/trunk/ConsoleDataMigration/sources/ConsoleRestore/Controller.cpp
N2614 842d745c5e NUP実行前にSDカードに吸い出したシリアルナンバーを表示するように
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@725 385bec56-5757-e545-9c3a-d8741f4650f1
2013-02-25 02:41:13 +00:00

2084 lines
67 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*---------------------------------------------------------------------------*
Project: Horizon
File: Controller.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 <nn.h>
#include <nn/ns.h>
#include <nn/CTR/CTR_DeliverArg.h>
#include <nn/fs/CTR/MPCore/fs_FileSystemBasePrivate.h>
#include <nn/ptm/CTR/ptm_ApiSysmenu.h>
#include <nn/ptm/CTR/ptm_ApiSystem.h>
#include <nn/pl/CTR/pl_PlayHistoryApiSysmenu.h>
#include <nn/cfg/CTR/cfg_ApiSys.h>
#include <nn/nwm.h>
#include <nn/am/am_ApiSystemMenu.h>
#include "Controller.h"
#include "FileChecker.h"
#include "SimplePlayer.h"
#include "CommonLogger.h"
#include "Importer.h"
#include "Updater.h"
#include "NtpClient.h"
#include "TitleDownloader.h"
#include "Shop.h"
#include "Util.h"
namespace ConsoleRestore
{
namespace
{
// ネットワーク設定ファイルを読んだかどうか
bool s_ReadSettingDone = false;
// インターネット設定を読んだ結果
bool s_ReadSettingIsSuccess = false;
// NUP専用モードかどうか
bool s_NupOnlyMode = false;
// IVS取得専用モードかどうか
bool s_GetIvsOnlyMode = false;
// SDカード確認専用モード
bool s_CheckSdOnlyMode = false;
// NUPスキップモードかどうか
bool s_SkipNupMode = false;
// プリインストール書き込みモードかどうか
bool s_DownloadPreinstallMode = false;
// 強制プリインストール書き込みモードかどうか
bool s_ForceDownloadPreinstall = false;
// 失敗サウンドを鳴らしたかどうか
bool s_PlayedFailSound = false;
// ネットワークアップデートを開始したかどうか
bool s_ExecuteFgNup = false;
// FGNUPを何回リトライしたか
u32 s_FgNupRetryCount = 0;
// 時計同期モードかどうか
bool s_IsSyncClock = false;
// TWLタイトルのダウンロードを開始したかどうか
bool s_ExecuteTwlTitleDownload = false;
// TWLタイトルのダウンロードを何回リトライしたか
u32 s_TwlTitleDownloadRetryCount = 0;
// プリインストールタイトルのダウンロード準備を開始したかどうか
bool s_ExecutePreparePreinstallTitleDownload = false;
// プリインストールタイトルのダウンロード準備を何回リトライしたか
u32 s_PreparePreinstallTitleDownloadRetryCount = 0;
// プリインストールタイトルのダウンロードを開始したかどうか
bool s_ExecutePreinstallTitleDownload = false;
// プリインストールタイトルのダウンロードを何回リトライしたか
u32 s_PreinstallTitleDownloadRetryCount = 0;
// プリインストールタイトルのダウンロードが成功したかどうか
bool s_PreinstallTitleDownloadSuccess = false;
// ショップ処理を開始したかどうか
bool s_ShopOperationExecuted[SHOP_OPERATION_NUM_MAX];
// ショップ処理を何回リトライしたか
u32 s_ShopOperationRetryCount[SHOP_OPERATION_NUM_MAX];
void PutAliveMessage(common::OperationMessage& operationMessage, const char* str);
bool CheckAndReadAPSetting(common::OperationMessage& operationMessage);
bool NeedsAcAdater(common::HardwareStateManager& manager)
{
return manager.IsBatteryLower() && !manager.IsAdapterConnected();
}
bool HasValidRtcData()
{
return !s_CheckSdOnlyMode && !s_NupOnlyMode && !s_GetIvsOnlyMode && !s_DownloadPreinstallMode;
}
typedef enum RestoreState
{
STARTUP, // 初期値
INITIALIZE_CONSOLE, // セーブデータ領域のNAND初期化を行う
SERIAL_IS_NOT_IN_SD, // シリアルナンバーファイルがSDカードにないことを表示
WAIT_START_UPDATE, // アップデート開始入力待ち
WAIT_START_IMPORT, // 書き込み開始入力待ち
WAIT_START_SYNC_CLOCK, // 時計合わせ開始入力待ち
IMPORT_RTC, // RTC同期
UPDATE_IN_PROGRESS, // アップデート中
UPDATE_DONE, // アップデート完了
NUP_ONLY_WAIT_SD_EJECT, // NUP_ONLYモードでSDカード抜き待ち
NUP_ONLY_WAIT_NEXT, // NUP_ONLYモードでキー入力待ち
WAIT_START_TRANSFER_ACCOUNT, // アカウント転送開始入力まち
TRANSFER_ACCOUNT, // アカウント転送を完了させる
TRANSFER_ACCOUNT_DONE, // アカウント転送完了
DOWNLOAD_IVS, // インフラからIVSを取得する
DOWNLOAD_IVS_DONE, // インフラからIVSを取得完了
DOWNLOAD_IVS_WAIT_NEXT, // IVS取得モードでキー入力待ち
CHECK_IVS, // IVSとSDカードのセーブデータディレクトリの一致を確認
CHECK_SD_DIRECTORY, // SDカードのIVS依存ディレクトリを探す
CHECK_SD_DIRECTORY_SUCCESS, // SDカードのIVS依存ディレクトリチェック完了
CHECK_SD_DIRECTORY_FAIL, // SDカードのIVS依存ディレクトリが見つからなかった
WAIT_START_DELETE_ACCOUNT, // ショップアカウント削除開始入力待ち,
DELETE_ACCOUNT, // ショップアカウントを削除する
DELETE_ACCOUNT_DONE, // ショップアカウント削除完了
SYNC_TICKET, // eTicketを同期する
READ_FILELIST, // ファイル一覧の読み込み
RESTORE_TWL_NAND, // TWL NANDの書き込み中
RESTORE_TWL_SOUND, // TWLサウンドの書き込み中
RESTORE_TWL_PHOTO, // TWL写真の書き込み中
RESTORE_IN_PROGRESS, // 書き込み中
POST_RESTORE, // 書き込み後の処理
RESTORE_DONE, // 書き込み完了
REBOOTING, // 再起動を行う
ERASE, // 削除処理を行う
RESTORE_CAL, // cfgの一部をcal値で上書きする
REPAIR_SIMPLE_ADDRESS_ID, // 本ツールで過去に破壊されたSimpleAddress.idを修正する
TIME_ADJUST, // 時計あわせを行う
DOWNLOAD_TWL, // TWLアプリ本体をダウンロードする
WAIT_SD_EJECT, // SDカードぬき待ち
ALL_DONE, // すべて完了
INITIALIZE_AND_SHUTDOWN, // 本体初期化後にシャットダウン中
FAIL, // 失敗
// プリインストールダウンロードモード
PREINSTALL_WAIT_START_UPDATE, // NUP開始待ち
PREINSTALL_WAIT_SYNC_TICKET, // 開始ボタン待ち
PREINSTALL_DELETE_PERSONALIZED_TICKET, // Personalized eTicketの削除
PREINSTALL_WAIT_USER_SD_INSERT, // ユーザSD挿入待ち
PREINSTALL_WAIT_USER_SD_INSERT_WAIT_NEXT, // ユーザSD挿入後Aボタン待ち
PREINSTALL_CHECK_USER_SD_INSERT, // ユーザSDの挿入チェック
PREINSTALL_CHECK_USER_SD, // ユーザSDのチェック
PREINSTALL_CHECK_USER_SD_ALREADY_INITIALIZED, // ユーザSDのチェック、既に初期化済み
PREINSTALL_CHECK_SD_FAIL, // ユーザSDのチェック失敗
PREINSTALL_FAIL_CHECK_REPAIR_SD, // ユーザSDのチェック失敗後の修理用SDのチェック
PREINSTALL_DOWNLOAD_APP, // アプリダウンロード
PREINSTALL_DOWNLOAD_APP_NOT_ENOUGH_SPACE, // アプリダウンロード失敗、空き容量不足
PREINSTALL_WAIT_USER_SD_EJECT, // ユーザSD抜き出し待ち
PREINSTALL_CHECK_REPAIR_SD_WAIT_NEXT, // 修理用SDのチェック・Aボタン待ち
PREINSTALL_CHECK_REPAIR_SD, // 修理用SDのチェック
RESTORE_STATE_MAX
} RestoreState;
enum AnnotationSound
{
ANNOTATION_SD_WRITE_PROTECT,
ANNOTATION_WIFI_OFF,
ANNOTATION_SETTING_NOT_FOUND,
ANNOTATION_INVALID_SETTING,
ANNOTATION_SERIAL_NUMBER_NOT_IN_SD,
ANNOTATION_MAX
};
bool s_PlayedCursorSound[RESTORE_STATE_MAX];
bool s_PlayedAnnotationSound[ANNOTATION_MAX];
void PlayCursorSound(RestoreState state)
{
if(!s_PlayedCursorSound[state])
{
common::PlaySound(common::SOUND_CURSOR);
s_PlayedCursorSound[state] = true;
}
}
void PlayAnnotationSound(AnnotationSound index)
{
if(!s_PlayedAnnotationSound[index])
{
common::PlaySound(common::SOUND_ANNOTATION);
s_PlayedAnnotationSound[index] = true;
}
}
#define BREAK_IF_STATE_CHANGED(saved, current) \
if(saved != current) \
{\
break;\
}\
// SD挿抜が起こらなかった時のみ次の状態に遷移する
void ChangeState(RestoreState saved, RestoreState& current, RestoreState next)
{
if(saved == current)
{
current = next;
s_PlayedCursorSound[next] = false;
}
}
// Restore状態管理
RestoreState s_RestoreState = STARTUP;
// Restoreモード管理
RestoreMode s_RestoreMode = RESTORE_MODE_RESTORE;
void CheckSdInserted(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckAcAdapter(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckSdWritable(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckApSetting(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckNupExecuted(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckDownloadIvs(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckAccountDeleted(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckAccountTransfered(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckWriteFinished(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckReadIvs(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckConsoleInitialized(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckExistsSerialNumber(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckIvsinSd(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
void CheckRegioinSd(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep);
bool DisplaySerialNumberinSD(common::OperationMessage& message)
{
u8 serial[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN];
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(
ReadSerialNumber(serial));
::std::string serialStr(reinterpret_cast<char*>(serial));
message.Add((::std::string("Serial Number in SD : ") + serialStr).c_str());
return true;
}
// SDカード挿入チェック
void CheckSdInserted(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
if (nn::fs::IsSdmcInserted())
{
CheckAcAdapter(manager, message, goNextStep);
}
else
{
message.Add("Insert SD Card!!");
s_RestoreState = STARTUP;
}
}
// ACアダプタが必要かどうかチェック
void CheckAcAdapter(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
// ACアダプタが必要か
if (NeedsAcAdater(manager))
{
message.Add("Connect AC Adapter!!");
s_RestoreState = STARTUP;
}
else
{
CheckSdWritable(manager, message, goNextStep);
}
}
// SDカード書き込みチェック
void CheckSdWritable(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
// SDカードに書き込みできるか
if (nn::fs::IsSdmcWritable())
{
CheckApSetting(manager, message, goNextStep);
}
else
{
PlayAnnotationSound(ANNOTATION_SD_WRITE_PROTECT);
message.Add("Can't Write SD Card!!\n");
s_RestoreState = STARTUP;
}
}
// 設定ファイル書式チェック
void CheckApSetting(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
NN_UNUSED_VAR(manager);
NN_UNUSED_VAR(goNextStep);
if (CheckAndReadAPSetting(message))
{
s_RestoreState = IMPORT_RTC;
}
else
{
s_RestoreState = STARTUP;
}
}
// NUP済みかどうかチェック
void CheckNupExecuted(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
if (common::ExistsUpdateCheckedFile())
{
if (s_NupOnlyMode)
{
s_RestoreState = WAIT_START_DELETE_ACCOUNT;
}
else if(s_DownloadPreinstallMode)
{
s_RestoreState = PREINSTALL_WAIT_SYNC_TICKET;
}
else
{
CheckAccountDeleted(manager, message, goNextStep);
}
}
else
{
// NUPを実行
if (CheckAndReadAPSetting(message))
{
if (nn::nwm::CTR::IsWifiOn())
{
if(s_DownloadPreinstallMode)
{
s_RestoreState = PREINSTALL_WAIT_START_UPDATE;
}
else
{
// ネットワークアップデートを行う
s_RestoreState = WAIT_START_UPDATE;
}
}
else
{
PlayAnnotationSound(ANNOTATION_WIFI_OFF);
message.Add("Wireless is Off\n");
s_RestoreState = STARTUP;
}
}
}
}
// インフラからIVS取得済みかチェック
void CheckDownloadIvs(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
NN_UNUSED_VAR(message);
NN_UNUSED_VAR(goNextStep);
// IVS取得確認ファイルがあるか
if (common::ExistsDownloadIvsCheckedFile())
{
if(s_GetIvsOnlyMode)
{
s_RestoreState = DOWNLOAD_IVS_WAIT_NEXT;
}
else
{
CheckWriteFinished(manager, message, goNextStep);
}
}
else
{
COMMON_LOGGER("Download SDCI\n");
s_RestoreState = DOWNLOAD_IVS;
}
}
// アカウント削除済みかチェック
void CheckAccountDeleted(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
// アカウント削除確認ファイルがあるか?
if (common::ExistsDeleteAccountChecked())
{
CheckAccountTransfered(manager, message, goNextStep);
}
else
{
// 同一本体下記書き戻しの場合はアカウント削除しない
if(EqualsDeviceIdFileandDeviceId(manager).IsSuccess())
{
// IVS専用モードならばIVSを取得させる
if(s_GetIvsOnlyMode)
{
CheckDownloadIvs(manager, message, goNextStep);
}
else
{
CheckAccountTransfered(manager, message, goNextStep);
}
}
else
{
s_RestoreState = WAIT_START_DELETE_ACCOUNT;
}
}
}
// アカウント移行済みかチェック
void CheckAccountTransfered(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
// アカウント移行確認ファイルがあるか?
if (common::ExistsTransferAccountChecked())
{
CheckDownloadIvs(manager, message, goNextStep);
}
else
{
s_RestoreState = WAIT_START_TRANSFER_ACCOUNT;
}
}
// 書き込み完了かどうかチェック
void CheckWriteFinished(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
NN_UNUSED_VAR(goNextStep);
// SDカードに書き込み完了ファイルがあるか
if (common::ExistsWriteFinishedFile())
{
if (CheckAndReadAPSetting(message))
{
if (nn::nwm::CTR::IsWifiOn())
{
// 削除処理を行う
s_RestoreState = WAIT_START_SYNC_CLOCK;
}
else
{
PlayAnnotationSound(ANNOTATION_WIFI_OFF);
message.Add("Wireless is Off\n");
}
}
}
else
{
CheckReadIvs(manager, message, goNextStep);
}
}
// IVSを読めるかどうかチェック
void CheckReadIvs(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
// IVSを読めるか
if (manager.CanReadIvs())
{
CheckConsoleInitialized(manager, message, goNextStep);
}
else
{
s_RestoreState = FAIL;
COMMON_LOGGER("Can't Read SDCI!!");
}
}
// 本体初期化済みかどうかチェック
void CheckConsoleInitialized(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
// 本体初期化完了ファイルがあるか?
if (common::ExistsConsoleInitializedFile())
{
CheckRegioinSd(manager, message, goNextStep);
}
else
{
CheckIvsinSd(manager, message, goNextStep);
}
}
// シリアルナンバーがあるかどうかチェック
void CheckExistsSerialNumber(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
NN_UNUSED_VAR(manager);
NN_UNUSED_VAR(message);
NN_UNUSED_VAR(goNextStep);
// SDカードにシリアルナンバーがあるか
if (common::ExistsSerialNumberFile())
{
u8 serial[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN];
nn::Result result = ReadSerialNumber(serial);
if (result.IsSuccess())
{
s_RestoreState = WAIT_START_IMPORT;
}
else
{
s_RestoreState = FAIL;
}
}
else
{
COMMON_LOGGER("Can't Read Serial Number in SD Card!!\n");
s_RestoreState = SERIAL_IS_NOT_IN_SD;
}
}
// SDカードにIVSがあるかどうかチェック
void CheckIvsinSd(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
NN_UNUSED_VAR(manager);
NN_UNUSED_VAR(message);
NN_UNUSED_VAR(goNextStep);
if (common::ExistsIVSFile())
{
s_RestoreState = INITIALIZE_CONSOLE;
}
else
{
// 移行不能なのでFAIL
COMMON_LOGGER("Can't Read SDCI in SD Card!!\n");
s_RestoreState = FAIL;
}
}
// SDカードにリージョンデータがあるかどうかチェック
void CheckRegioinSd(common::HardwareStateManager& manager, common::OperationMessage& message, bool& goNextStep)
{
NN_UNUSED_VAR(message);
NN_UNUSED_VAR(goNextStep);
// SDカードにリージョンデータがあるか
if (common::ExistsRegionData())
{
// リージョンデータは一致しているか?
if (EqualsRegionDataandRegion().IsFailure())
{
COMMON_LOGGER("Current Region and Region in SD differ!!\n");
s_RestoreState = FAIL;
}
else
{
CheckExistsSerialNumber(manager, message, goNextStep);
}
}
else
{
// 移行不能なのでFAIL
COMMON_LOGGER("Can't Read Region in SD Card!!\n");
s_RestoreState = FAIL;
}
}
void ShopOperationSuccess(ShopOperation op, const char* logMessage, RestoreState nextState)
{
COMMON_LOGGER("%s", logMessage);
if (op == SHOP_OPERATION_UNREGISTER || op == SHOP_OPERATION_FORCE_UNREGISTER)
{
CreateDeleteAccountFinishedFile();
}
else if (op == SHOP_OPERATION_GET_IVS)
{
CreateTransferAccountFinishedFile();
CreateDownloadIvsFinishedFile();
}
s_RestoreState = nextState;
}
void ShopOperationSingleTemplate(
common::HardwareStateManager& manager,
common::OperationMessage& message,
ShopOperation op,
const char* aliveMessage,
const char* logMessage,
const char* retryLogMessage,
RestoreState nextState
)
{
// ACアダプタが必要か
if (NeedsAcAdater(manager))
{
message.Add("Connect AC Adapter!!");
}
// アップデートを行う
if (!s_ShopOperationExecuted[op])
{
if (ImportCountryLanguageData().IsSuccess())
{
StartShopOperationSingle(op);
s_ShopOperationExecuted[op] = true;
}
else
{
s_RestoreState = FAIL;
}
}
// 動いていることを表示
{
PutAliveMessage(message, aliveMessage);
}
if (IsShopOperationSingleFinished())
{
FinalizeShopOperationSingle();
// エラーがあったら表示する
if (GetShopOperationSingleResult().IsSuccess())
{
ShopOperationSuccess(op, logMessage, nextState);
}
// IVSがアップロードされていない場合もあるため
// IVSを取得できない状況も成功として扱う
// IVSサイズが違う場合も成功として扱う
else if(op == SHOP_OPERATION_GET_IVS && ( GetShopOperationSingleResult() == nn::nim::ResultCannotGetIvs() ||
GetShopOperationSingleResult() == nn::nim::ResultInvalidData()
))
{
ShopOperationSuccess(op, logMessage, nextState);
}
else if(op == SHOP_OPERATION_CONNECT && nextState == TRANSFER_ACCOUNT_DONE &&
GetShopOperationSingleResult() == nn::nim::ResultNeedGetIvs())
{
NN_LOG("ResultNeedGetIvs\n");
ShopOperationSuccess(op, logMessage, nextState);
}
else
{
if (GetShopOperationSingleResult().IsFailure())
{
if (GetShopOperationSingleResult() == nn::ac::ResultFailedConnectAp())
{
COMMON_LOGGER("Failed Connect AccesPoint.");
nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromSeconds(5));
}
// APが見つからない
if (GetUpdateResult() == nn::ac::ResultNotFoundAccessPoint())
{
COMMON_LOGGER("No Access Point Found!");
}
}
if (s_ShopOperationRetryCount[op]++ < RETRY_MAX)
{
// エラーのためやり直す
COMMON_LOGGER_RESULT_IF_FAILED(GetShopOperationSingleResult());
COMMON_LOGGER("%s %d\n", retryLogMessage, s_ShopOperationRetryCount[op]);
// スレッドを作るとこからやり直し
s_ShopOperationExecuted[op] = false;
}
else
{
s_RestoreState = FAIL;
}
}
}
}
void UpdateOperation(common::HardwareStateManager& manager, common::OperationMessage& message, RestoreState nextState)
{
// ACアダプタが必要か
if (NeedsAcAdater(manager))
{
message.Add("Connect AC Adapter!!");
}
// アップデートを行う
if (!s_ExecuteFgNup)
{
if (ImportCountryLanguageData().IsSuccess())
{
StartFGNetworkUpdate();
s_ExecuteFgNup = true;
}
else
{
s_RestoreState = FAIL;
}
}
// 動いていることを表示
{
PutAliveMessage(message, "Updating");
}
if (IsNetworkUpdateFinished())
{
FinishFGNetworkUpdate();
// エラーがあったら表示する
if (GetUpdateResult().IsFailure())
{
// APが見つからない
if (GetUpdateResult() == nn::ac::ResultNotFoundAccessPoint())
{
COMMON_LOGGER("No Access Point Found!");
}
}
if (GetUpdateResult().IsSuccess())
{
COMMON_LOGGER("Network Update Finished.\n");
if(nextState == UPDATE_DONE)
{
// アップデート完了ファイルを作成
CreateUpdateFinishedFile();
}
s_RestoreState = nextState;
}
else
{
if (s_FgNupRetryCount++ < RETRY_MAX)
{
// エラーのためやり直す
COMMON_LOGGER_RESULT_IF_FAILED(GetUpdateResult());
COMMON_LOGGER("Network Update Failed. Retrying... %d\n", s_FgNupRetryCount);
// FGNUP用のスレッドを作るとこからやり直し
s_ExecuteFgNup = false;
}
else
{
s_RestoreState = FAIL;
}
}
}
}
bool CheckAndReadAPSetting(common::OperationMessage& operationMessage)
{
using namespace common;
if (!ExistsAPSetting())
{
PlayAnnotationSound(ANNOTATION_SETTING_NOT_FOUND);
operationMessage.Add("Accsess_Point_Setting does not exist!");
return false;
}
// 設定ファイルからAP設定を読み込む
if (!s_ReadSettingDone)
{
s_ReadSettingDone = true;
s_ReadSettingIsSuccess = ReadSetting(&s_NupOnlyMode, &s_GetIvsOnlyMode, &s_CheckSdOnlyMode, &s_SkipNupMode, &s_DownloadPreinstallMode);
}
if (s_NupOnlyMode && s_GetIvsOnlyMode
|| s_GetIvsOnlyMode && s_CheckSdOnlyMode
|| s_CheckSdOnlyMode && s_NupOnlyMode)
{
operationMessage.Add("Only one special mode setting is valid!!");
s_ReadSettingIsSuccess = false;
}
else if(s_NupOnlyMode && s_SkipNupMode)
{
operationMessage.Add("Both NUP_ONLY and SKIP_NUP are described!!");
s_ReadSettingIsSuccess = false;
}
else
{
if (s_NupOnlyMode)
{
s_RestoreMode = RESTORE_MODE_NUP_ONLY;
}
if (s_GetIvsOnlyMode)
{
s_RestoreMode = RESTORE_MODE_GET_IVS;
}
if(s_CheckSdOnlyMode)
{
s_RestoreMode = RESTORE_MODE_CHECK_SD;
}
if(s_DownloadPreinstallMode)
{
s_RestoreMode = RESTORE_MODE_DOWNLOAD_PREINSTALL;
}
}
if (!s_ReadSettingIsSuccess)
{
operationMessage.Add("Invalid Accsess_Point_Setting format!");
PlayAnnotationSound(ANNOTATION_INVALID_SETTING);
}
return s_ReadSettingIsSuccess;
}
void PutAliveMessage(common::OperationMessage& operationMessage, const char* str)
{
std::string message = std::string(str);
static u8 i = 0;
if (i < 0xff / 4)
{
operationMessage.Add((message + std::string(" /")).c_str());
}
else if (i < 0xff * 2 / 4)
{
operationMessage.Add((message + std::string(" |")).c_str());
}
else if (i < 0xff * 3 / 4)
{
operationMessage.Add((message + std::string(" \\")).c_str());
}
else
{
operationMessage.Add((message + std::string(" -")).c_str());
}
i += 4;
}
nn::Result ExecSyncMcuRtc(common::HardwareStateManager& manager)
{
nn::Result result = nn::ResultSuccess();
if(!common::ExistsRtcSyncFinishedFile())
{
result = ImportMcuRtc(manager);
if(result.IsSuccess())
{
// RTCを同期完了ファイルを作る
CreateRtcSyncFinishedFile();
}
}
return result;
}
} // namespace <unnamed>
void ControlState(common::HardwareStateManager& manager, common::OperationMessage& operationMessage, bool& nextStep,
bool operateBmsDone, bool forcePreinstall)
{
using namespace common;
nn::Result result;
// 状態遷移Controller
switch (s_RestoreState)
{
// 起動時
case STARTUP:
{
CheckSdInserted(manager, operationMessage, nextStep);
}
break;
case INITIALIZE_CONSOLE:
{
COMMON_LOGGER("Initialize Console\n");
// 本体初期化完了ファイルを作る
CreateConsoleInitializedFile();
// ファイルシステムの初期化を行う
if(InitializeFileSystem())
{
s_RestoreState = REBOOTING;
}
else
{
s_RestoreState = FAIL;
}
}
break;
case WAIT_START_UPDATE:
{
//シリアルが存在しない場合がある
if (common::ExistsSerialNumberFile() && !DisplaySerialNumberinSD(operationMessage))
{
s_RestoreState = FAIL;
}
operationMessage.Add("Push A or START Button");
operationMessage.Add("Network Update Mode");
PlayCursorSound(WAIT_START_UPDATE);
if (nextStep)
{
COMMON_LOGGER("Start Network Update\n");
// インポートコンテキストの削除
result = nn::am::DeleteAllImportContexts(nn::fs::MEDIA_TYPE_NAND);
COMMON_LOGGER_RESULT_IF_FAILED(result);
nn::am::DeleteAllImportContexts(nn::fs::MEDIA_TYPE_SDMC);
s_RestoreState = UPDATE_IN_PROGRESS;
}
}
break;
case WAIT_START_IMPORT:
{
// 必ずシリアルが存在するはず
if(!DisplaySerialNumberinSD(operationMessage))
{
s_RestoreState = FAIL;
}
operationMessage.Add("Push A or START Button");
operationMessage.Add("Import Data Mode");
PlayCursorSound(WAIT_START_IMPORT);
if (nextStep)
{
s_RestoreState = READ_FILELIST;
}
}
break;
case WAIT_START_SYNC_CLOCK:
{
operationMessage.Add("Push A or START Button");
operationMessage.Add("DownLoad Twl Title and Clock Sync Mode");
PlayCursorSound(WAIT_START_SYNC_CLOCK);
if (nextStep)
{
COMMON_LOGGER("Erase Trash\n");
s_RestoreState = ERASE;
}
}
break;
// ここから各設定で処理が分岐する
case IMPORT_RTC:
{
result = nn::ResultSuccess();
if (HasValidRtcData())
{
result = ExecSyncMcuRtc(manager);
if (result <= nn::fs::ResultVerificationFailed())
{
s_RestoreState = FAIL;
}
else
{
if (s_SkipNupMode)
{
CheckAccountTransfered(manager, operationMessage, nextStep);
}
else
{
CheckNupExecuted(manager, operationMessage, nextStep);
}
}
}
else
{
if(s_SkipNupMode)
{
CheckAccountTransfered(manager, operationMessage, nextStep);
}
else if (s_CheckSdOnlyMode)
{
s_RestoreState = CHECK_IVS;
}
else
{
CheckNupExecuted(manager, operationMessage, nextStep);
}
}
}
break;
// シリアルナンバーがSDカードにないこと警告
case SERIAL_IS_NOT_IN_SD:
{
operationMessage.Add("Serial Number Is Not In SD Card");
operationMessage.Add("Push A or START Button");
operationMessage.Add("Import Data Mode");
PlayAnnotationSound(ANNOTATION_SERIAL_NUMBER_NOT_IN_SD);
if (nextStep)
{
s_RestoreState = READ_FILELIST;
}
}
break;
// アップデート中
case UPDATE_IN_PROGRESS:
{
UpdateOperation(manager, operationMessage, UPDATE_DONE);
}
break;
// アップデート完了
case UPDATE_DONE:
{
operationMessage.Add("Network Update Done.");
operationMessage.Add("Press A or START Button to Reboot");
PlayCursorSound(UPDATE_DONE);
if (nextStep)
{
s_RestoreState = REBOOTING;
}
}
break;
case DOWNLOAD_IVS:
{
ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_GET_IVS, "Get SDCI",
"Get SDCI Finished.\n", "Get SDCI Failed. Retrying...", DOWNLOAD_IVS_DONE);
}
break;
case DOWNLOAD_IVS_DONE:
{
operationMessage.Add("Get SDCI Done.");
operationMessage.Add("Press A or START Button to Reboot");
PlayCursorSound(DOWNLOAD_IVS_DONE);
if (nextStep)
{
s_RestoreState = REBOOTING;
}
}
break;
case CHECK_IVS:
{
operationMessage.Add("Insert User's SD Card");
}
break;
case CHECK_SD_DIRECTORY:
{
if (nn::fs::IsSdmcInserted())
{
NN_LOG("Check User's SD Card\n");
// ユーザのSDカードにはAP設定ファイルは無いはず
if (ExistsAPSetting())
{
NN_LOG("AP Setting Exists. Retry\n");
s_RestoreState = CHECK_IVS;
}
else
{
NN_LOG("Read User's SD Card\n");
std::string sysSaveRoot;
common::Util::GetSaveDataDirectoryRoot(sysSaveRoot);
if (ExistsIvsDirectory(sysSaveRoot))
{
s_RestoreState = CHECK_SD_DIRECTORY_SUCCESS;
}
else
{
s_RestoreState = CHECK_SD_DIRECTORY_FAIL;
}
}
}
}
break;
case CHECK_SD_DIRECTORY_SUCCESS:
{
operationMessage.Add("Check User's SD Card Succeeded.");
operationMessage.Add("Pull Out SD Card");
}
break;
case CHECK_SD_DIRECTORY_FAIL:
{
operationMessage.Add("Check User's SD Card Failed.");
operationMessage.Add("Pull Out SD Card");
}
break;
case WAIT_START_TRANSFER_ACCOUNT:
{
if(s_SkipNupMode)
{
operationMessage.Add("After Operating BMS Account Transfer,");
}
operationMessage.Add("Push A or START Button");
operationMessage.Add("Transfer Account Mode");
PlayCursorSound(WAIT_START_TRANSFER_ACCOUNT);
if (nextStep)
{
COMMON_LOGGER("Transfer Account\n");
s_RestoreState = TRANSFER_ACCOUNT;
}
}
break;
case TRANSFER_ACCOUNT:
{
ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_GET_IVS, "Transfer Account",
"Transfer Account Finished.\n", "Transfer Account Failed. Retrying...", DOWNLOAD_IVS_DONE);
}
break;
case WAIT_START_DELETE_ACCOUNT:
{
operationMessage.Add("Push A or START Button");
operationMessage.Add("Delete Account Mode");
PlayCursorSound(WAIT_START_DELETE_ACCOUNT);
if (nextStep)
{
COMMON_LOGGER("Delete Account\n");
s_RestoreState = DELETE_ACCOUNT;
}
}
break;
case DELETE_ACCOUNT:
{
if(s_NupOnlyMode)
{
ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_FORCE_UNREGISTER, "Deleting Account",
"Delete Account Finished.\n", "Delete Account Failed. Retrying...", DELETE_ACCOUNT_DONE);
}
else
{
ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_UNREGISTER, "Deleting Account",
"Delete Account Finished.\n", "Delete Account Failed. Retrying...", DELETE_ACCOUNT_DONE);
}
}
break;
case DELETE_ACCOUNT_DONE:
{
if(s_NupOnlyMode)
{
s_RestoreState = NUP_ONLY_WAIT_SD_EJECT;
// リストア状態チェックファイルをすべて削除
DeleteAllCheckFiles();
}
else
{
operationMessage.Add("Delete Account Done.");
operationMessage.Add("Operate BMS.", nn::util::Color8(0, 255, 255, 255));
operationMessage.Add("");
operationMessage.Add("Press Y Button to Continue");
PlayCursorSound(DELETE_ACCOUNT_DONE);
if (operateBmsDone)
{
s_RestoreState = STARTUP;
}
}
}
break;
case READ_FILELIST:
{
result = SetupVersionAndFileList();
COMMON_LOGGER_RESULT_IF_FAILED(result);
if (result.IsSuccess())
{
if (s_IsSyncClock)
{
s_RestoreState = RESTORE_TWL_NAND;
}
else
{
s_RestoreState = RESTORE_TWL_SOUND;
}
}
else
{
s_RestoreState = FAIL;
}
}
break;
// TWLサウンド領域の書き込み中
case RESTORE_TWL_SOUND:
{
static bool init = true;
if (init)
{
// データを書き込む
ImportTwlSoundData();
init = false;
}
PutAliveMessage(operationMessage, "Importing TWL Sound Data");
// 処理が完了した
if (IsImportThreadFinished())
{
FinalizeImportThread();
if(IsImportSucceeded())
{
s_RestoreState = RESTORE_TWL_PHOTO;
}
else
{
s_RestoreState = FAIL;
}
}
}
break;
// TWL写真領域の書き込み
case RESTORE_TWL_PHOTO:
{
static bool init = true;
if (init)
{
// データを書き込む
ImportTwlPhotoData();
init = false;
}
PutAliveMessage(operationMessage, "Importing TWL Photo Data");
// 処理が完了した
if (IsImportThreadFinished())
{
FinalizeImportThread();
if(IsImportSucceeded())
{
s_RestoreState = RESTORE_IN_PROGRESS;
}
else
{
s_RestoreState = FAIL;
}
}
}
break;
// 書き込み中
case RESTORE_IN_PROGRESS:
{
// ACアダプタが必要か
if (NeedsAcAdater(manager))
{
operationMessage.Add("Connect AC Adapter!!");
}
// データを読み込む
if (ImportData().IsFailure())
{
s_RestoreState = FAIL;
}
else
{
PutAliveMessage(operationMessage, "Importing Nand Data");
// 処理が完了した
if (!NeedsAcAdater(manager) && IsImportThreadFinished())
{
if (IsImportSucceeded())
{
COMMON_LOGGER("Import NAND Data Finished.\n");
if (GetProgress() > 99)
{
s_RestoreState = POST_RESTORE;
}
else
{
s_RestoreState = FAIL;
}
}
else
{
s_RestoreState = FAIL;
}
}
}
}
break;
// リブート中
case REBOOTING:
{
static bool init = true;
if (init)
{
// ErrDispから引用
result = nn::ns::CTR::InitializeForShell();
if (result.IsSuccess())
{
COMMON_LOGGER("System Reboot.\n");
nn::ns::CTR::HardwareResetAsync(nn::CTR::MEMORY_ARRANGE_NORMAL);
while (!nn::applet::IsExpectedToCloseApplication())
{
nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(5));
}
nn::ns::CTR::FinalizeForShell();
// INFO: リブートは非同期のため処理は継続
}
init = false;
}
}
break;
// 書き込み後の処理
case POST_RESTORE:
{
operationMessage.Add("Post Process...");
// SDカードのIVSファイルを書き込む
if(ImportIvsData())
{
// 書き込み完了ファイルを作成
CreateWriteFinishedFile();
s_RestoreState = RESTORE_DONE;
}
else
{
s_RestoreState = FAIL;
}
}
break;
// 書き込み完了
case RESTORE_DONE:
{
operationMessage.Add("Restore Done.");
operationMessage.Add("Press A or START Button to Reboot");
PlayCursorSound(RESTORE_DONE);
if (nextStep)
{
s_RestoreState = REBOOTING;
}
}
break;
// 削除処理
case ERASE:
{
Cleanup();
s_RestoreState = RESTORE_CAL;
}
break;
// 削除処理
case RESTORE_CAL:
{
// ptmのセーブデータ移行後に時計を無効化する
nn::ptm::CTR::InvalidateSystemTime();
// cfgの本体固有値をcal値で初期化する
result = InitializeHardwareDependentSetting();
if (result.IsFailure())
{
s_RestoreState = FAIL;
}
COMMON_LOGGER("Sync eTicket\n");
s_RestoreState = SYNC_TICKET;
}
break;
case SYNC_TICKET:
{
if(s_GetIvsOnlyMode)
{
ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_CONNECT, "Shop Connect",
"Shop Connect Finished.\n", "Shop Connect Failed. Retrying...", WAIT_SD_EJECT);
}
else if(s_DownloadPreinstallMode)
{
ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_CONNECT, "Shop Connect",
"Shop Connect Finished.\n", "Shop Connect Failed. Retrying...", REPAIR_SIMPLE_ADDRESS_ID);
}
else
{
ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_CONNECT, "Shop Connect",
"Shop Connect Finished.\n", "Shop Connect Failed. Retrying...", DOWNLOAD_TWL);
}
}
break;
case DOWNLOAD_TWL:
{
// ファイルリストがなければ次へ
if( !ExistsTwlTitleListFile())
{
s_IsSyncClock = true;
s_RestoreState = READ_FILELIST;
}
else
{
if (!s_ExecuteTwlTitleDownload)
{
COMMON_LOGGER("Download Twl Title\n");
s_ExecuteTwlTitleDownload = true;
StartTwlTitleDownload();
}
// 動いていることを表示
{
PutAliveMessage(operationMessage, "Download Twl Title");
}
if (IsDownloadTitleFinished())
{
FinalizeTitleDownload();
if (DownloadTitleSucceeded())
{
s_IsSyncClock = true;
s_RestoreState = READ_FILELIST;
}
else
{
if (s_TwlTitleDownloadRetryCount++ < RETRY_MAX)
{
// エラーのためやり直す
COMMON_LOGGER_RESULT_IF_FAILED(GetTitleDownloadResult());
COMMON_LOGGER("Download Twl Title Failed. Retrying... %d\n", s_TwlTitleDownloadRetryCount);
s_ExecuteTwlTitleDownload = false;
}
else
{
s_RestoreState = FAIL;
}
}
}
}
}
break;
// TWL NAND領域の書き込み中
case RESTORE_TWL_NAND:
{
static bool init = true;
if (init)
{
// データを書き込む
ImportTwlSaveData();
init = false;
}
PutAliveMessage(operationMessage, "Importing TWL SaveData");
// 処理が完了した
if (IsImportThreadFinished())
{
FinalizeImportThread();
s_RestoreState = REPAIR_SIMPLE_ADDRESS_ID;
}
}
break;
case REPAIR_SIMPLE_ADDRESS_ID:
{
RepairSimpleAddress();
s_RestoreState = TIME_ADJUST;
}
break;
// 時計あわせ
case TIME_ADJUST:
{
static bool init = true;
if (init)
{
COMMON_LOGGER("Adjust Time\n");
AdjustTime();
init = false;
}
// 動いていることを表示
{
PutAliveMessage(operationMessage, "Sync Clock");
}
if (IsTimeAdjustFinished())
{
if (IsTimeAdjustSuccessed())
{
if(s_DownloadPreinstallMode)
{
s_RestoreState = PREINSTALL_WAIT_USER_SD_INSERT;
}
else
{
s_RestoreState = WAIT_SD_EJECT;
// インターネット設定を元に戻す
RestoreCurrentInternetSetting();
// リストア状態チェックファイルをすべて削除
DeleteAllCheckFiles();
}
}
else
{
// インターネット設定を元に戻す
RestoreCurrentInternetSetting();
s_RestoreState = FAIL;
}
}
}
break;
// すべて完了
case WAIT_SD_EJECT:
{
operationMessage.Add("ALL Done. Pull Out SD Card.");
// SDカード抜けのみで次の状態に遷移する
PlayCursorSound(WAIT_SD_EJECT);
}
break;
// すべて完了
case ALL_DONE:
{
operationMessage.Add("Restore Succeeded!!");
static bool init = true;
if (init)
{
PlaySound(SOUND_OK);
init = false;
}
}
break;
// 書き込み失敗
case FAIL:
{
static bool init = true;
if (init)
{
// 状態初期化
DeleteAllCheckFiles();
init = false;
}
operationMessage.Add("Failed.");
if (!s_PlayedFailSound)
{
PlaySound(SOUND_NG);
s_PlayedFailSound = true;
}
}
break;
case NUP_ONLY_WAIT_SD_EJECT:
{
operationMessage.Add("Update Done. Pull Out SD Card.");
PlayCursorSound(NUP_ONLY_WAIT_SD_EJECT);
}
break;
case DOWNLOAD_IVS_WAIT_NEXT:
{
operationMessage.Add("Press A or START Button to Continue.");
if(nextStep)
{
s_RestoreState = SYNC_TICKET;
DeleteAllCheckFiles();
}
}
break;
case NUP_ONLY_WAIT_NEXT:
{
operationMessage.Add("Press A or START Button to Shutdown.");
if (nextStep)
{
s_RestoreState = INITIALIZE_AND_SHUTDOWN;
}
}
break;
case INITIALIZE_AND_SHUTDOWN:
{
// 本体初期化を行う
if(!InitializeFileSystem())
{
s_RestoreState = FAIL;
}
// シャットダウンする
nn::ptm::CTR::ShutdownAsync(0, nn::fnd::TimeSpan::FromSeconds(0));
}
break;
case PREINSTALL_WAIT_START_UPDATE:
{
operationMessage.Add("Operate BMS to Transfer PreInstalled Application", nn::util::Color8(0, 255, 255, 255));
operationMessage.Add("Press Y Button to Continue.");
PlayCursorSound(PREINSTALL_WAIT_START_UPDATE);
if (operateBmsDone)
{
s_RestoreState = WAIT_START_UPDATE;
}
}
break;
case PREINSTALL_WAIT_SYNC_TICKET:
{
operationMessage.Add("Press A or START Button to Continue.");
PlayCursorSound(PREINSTALL_WAIT_SYNC_TICKET);
if(nextStep)
{
s_RestoreState = SYNC_TICKET;
}
}
break;
case PREINSTALL_WAIT_USER_SD_INSERT:
{
PlayCursorSound(PREINSTALL_WAIT_USER_SD_INSERT);
operationMessage.Add("Insert User's SD Card");
operationMessage.Add("and Press A or START Button.");
}
break;
case PREINSTALL_WAIT_USER_SD_INSERT_WAIT_NEXT:
{
operationMessage.Add("Insert User's SD Card");
operationMessage.Add("and Press A or START Button.");
if(nextStep)
{
s_RestoreState = PREINSTALL_CHECK_USER_SD_INSERT;
}
}
break;
case PREINSTALL_CHECK_USER_SD_INSERT:
{
RestoreState saved = PREINSTALL_CHECK_USER_SD_INSERT;
if (nn::fs::IsSdmcInserted())
{
NN_LOG("Check User's SD Card\n");
// ユーザのSDカードにはAP設定ファイルは無いはず
if (ExistsAPSetting())
{
NN_LOG("AP Setting Exists. Retry\n");
ChangeState(saved, s_RestoreState, PREINSTALL_WAIT_USER_SD_INSERT);
}
else
{
// SD挿抜が起こったら抜ける
BREAK_IF_STATE_CHANGED(saved, s_RestoreState);
ChangeState(saved, s_RestoreState, PREINSTALL_CHECK_USER_SD);
}
}
}
break;
case PREINSTALL_CHECK_USER_SD:
{
if (!s_ExecutePreparePreinstallTitleDownload)
{
COMMON_LOGGER("Checking User's SD Card\n");
s_ExecutePreparePreinstallTitleDownload = true;
StartPreparePreinstallTitleDownload(s_ForceDownloadPreinstall);
}
// 動いていることを表示
{
PutAliveMessage(operationMessage, "Checking User's SD Card");
}
if (IsDownloadTitleFinished())
{
FinalizeTitleDownload();
if (DownloadTitleSucceeded())
{
s_RestoreState = PREINSTALL_DOWNLOAD_APP;
}
else
{
if (s_PreparePreinstallTitleDownloadRetryCount++ < RETRY_MAX)
{
COMMON_LOGGER_RESULT_IF_FAILED(GetTitleDownloadResult());
if (GetTitleDownloadResult()
== nn::MakePermanentResult(nn::Result::SUMMARY_OUT_OF_RESOURCE,
nn::Result::MODULE_APPLICATION, nn::Result::DESCRIPTION_OUT_OF_MEMORY))
{
// SDカード容量不足
s_RestoreState = PREINSTALL_DOWNLOAD_APP_NOT_ENOUGH_SPACE;
}
else if(GetTitleDownloadResult() <= nn::fs::ResultNotEnoughSpace())
{
// SDカード容量不足
// 作成したデータを削除する
COMMON_LOGGER_RESULT_IF_FAILED(nn::fs::DeleteSdmcRoot());
s_RestoreState = PREINSTALL_DOWNLOAD_APP_NOT_ENOUGH_SPACE;
}
else if (GetTitleDownloadResult()
== nn::MakePermanentResult(nn::Result::SUMMARY_INVALID_STATE,
nn::Result::MODULE_APPLICATION, nn::Result::DESCRIPTION_ALREADY_INITIALIZED))
{
// ユーザSDが初期化済み
s_RestoreState = PREINSTALL_CHECK_USER_SD_ALREADY_INITIALIZED;
}
else if (GetTitleDownloadResult()
== nn::MakePermanentResult(nn::Result::SUMMARY_NOT_FOUND,
nn::Result::MODULE_APPLICATION, nn::Result::DESCRIPTION_NOT_FOUND))
{
// プリインストールテーブルが無い
COMMON_LOGGER("No PreInstalled Application Found\n");
s_RestoreState = PREINSTALL_CHECK_SD_FAIL;
}
else
{
// エラーのためやり直す
COMMON_LOGGER("Checking User's SD Card Failed. Retrying... %d\n", s_PreinstallTitleDownloadRetryCount);
s_ExecutePreparePreinstallTitleDownload = false;
}
}
else
{
s_RestoreState = PREINSTALL_CHECK_SD_FAIL;
}
}
}
}
break;
case PREINSTALL_CHECK_USER_SD_ALREADY_INITIALIZED:
{
operationMessage.Add("User's SD Card is already initialized.");
operationMessage.Add("Press Y Button to Continue.", nn::util::Color8(0, 255, 255, 255));
operationMessage.Add("Press A or START Button to Abort");
if(nextStep)
{
s_RestoreState = PREINSTALL_CHECK_SD_FAIL;
}
else if(forcePreinstall)
{
s_RestoreState = PREINSTALL_CHECK_USER_SD;
s_ExecutePreparePreinstallTitleDownload = false;
s_ForceDownloadPreinstall = true;
}
}
break;
case PREINSTALL_CHECK_SD_FAIL:
{
PlayCursorSound(PREINSTALL_CHECK_SD_FAIL);
operationMessage.Add("Check User's SD Card Failed.");
operationMessage.Add("Pull Out User's SD Card");
operationMessage.Add("and Insert Repairing SD Card");
}
break;
case PREINSTALL_FAIL_CHECK_REPAIR_SD:
{
operationMessage.Add("Press A or START Button to Continue.");
if(!nextStep)
{
break;
}
RestoreState saved = PREINSTALL_FAIL_CHECK_REPAIR_SD;
if (nn::fs::IsSdmcInserted())
{
NN_LOG("Check SD Card\n");
// 修理用SDカードにはAP設定ファイルがあるはず
if (ExistsAPSetting())
{
NN_LOG("AP Setting Exists. OK\n");
COMMON_LOGGER("Download PreInstalled Application failed\n");
// インターネット設定を元に戻す
RestoreCurrentInternetSetting();
ChangeState(saved, s_RestoreState, FAIL);
}
else
{
// SD挿抜が起こったら抜ける
BREAK_IF_STATE_CHANGED(saved, s_RestoreState);
ChangeState(saved, s_RestoreState, PREINSTALL_CHECK_SD_FAIL);
}
}
}
break;
case PREINSTALL_DOWNLOAD_APP:
{
if (!s_ExecutePreinstallTitleDownload)
{
COMMON_LOGGER("Download PreInstalled Application\n");
s_ExecutePreinstallTitleDownload = true;
StartPreinstallTitleDownload();
}
// 動いていることを表示
{
PutAliveMessage(operationMessage, "Download PreInstalled Title");
}
if (IsDownloadTitleFinished())
{
FinalizeTitleDownload();
if (DownloadTitleSucceeded())
{
s_PreinstallTitleDownloadSuccess = true;
s_RestoreState = PREINSTALL_WAIT_USER_SD_EJECT;
}
else
{
if (s_PreinstallTitleDownloadRetryCount++ < RETRY_MAX)
{
// エラーのためやり直す
COMMON_LOGGER_RESULT_IF_FAILED(GetTitleDownloadResult());
if(GetTitleDownloadResult() <= nn::fs::ResultNotEnoughSpace())
{
// SDカード容量不足
// 作成したデータを削除する
COMMON_LOGGER_RESULT_IF_FAILED(nn::fs::DeleteSdmcRoot());
s_RestoreState = PREINSTALL_DOWNLOAD_APP_NOT_ENOUGH_SPACE;
}
else
{
COMMON_LOGGER("Download PreInstalled Title Failed. Retrying... %d\n", s_PreinstallTitleDownloadRetryCount);
s_ExecutePreinstallTitleDownload = false;
}
}
else
{
s_RestoreState = PREINSTALL_WAIT_USER_SD_EJECT;
}
}
}
}
break;
case PREINSTALL_DOWNLOAD_APP_NOT_ENOUGH_SPACE:
{
PlayCursorSound(PREINSTALL_DOWNLOAD_APP_NOT_ENOUGH_SPACE);
operationMessage.Add("Not enough space on User's SD Card");
operationMessage.Add("Pull out User's SD Card");
operationMessage.Add("and Insert Repairing SD Card");
}
break;
case PREINSTALL_WAIT_USER_SD_EJECT:
{
PlayCursorSound(PREINSTALL_WAIT_USER_SD_EJECT);
operationMessage.Add("Pull out User's SD Card");
operationMessage.Add("and Insert Repairing SD Card");
}
break;
case PREINSTALL_CHECK_REPAIR_SD:
{
operationMessage.Add("Press A or START Button to Continue.");
if(!nextStep)
{
break;
}
RestoreState saved = PREINSTALL_CHECK_REPAIR_SD;
if (nn::fs::IsSdmcInserted())
{
NN_LOG("Check SD Card\n");
// 修理用SDカードにはAP設定ファイルがあるはず
if (ExistsAPSetting())
{
NN_LOG("AP Setting Exists. OK\n");
// インターネット設定を元に戻す
RestoreCurrentInternetSetting();
if(s_PreinstallTitleDownloadSuccess)
{
COMMON_LOGGER("Download PreInstalled Application done\n");
ChangeState(saved, s_RestoreState, WAIT_SD_EJECT);
// リストア状態チェックファイルをすべて削除
DeleteAllCheckFiles();
}
else
{
COMMON_LOGGER("Download PreInstalled Application failed\n");
ChangeState(saved, s_RestoreState, FAIL);
}
}
else
{
// SD挿抜が起こったら抜ける
BREAK_IF_STATE_CHANGED(saved, s_RestoreState);
ChangeState(saved, s_RestoreState, PREINSTALL_WAIT_USER_SD_EJECT);
}
}
}
break;
}
}
bool InProgress()
{
return s_RestoreState == RESTORE_IN_PROGRESS;
}
bool IsRestoreSucceeded()
{
return s_RestoreState == ALL_DONE;
}
bool IsRestoreFailed()
{
return s_RestoreState == FAIL;
}
void OnSdEjected()
{
if (s_RestoreState == WAIT_SD_EJECT || s_RestoreState == ALL_DONE || s_RestoreState == CHECK_SD_DIRECTORY_SUCCESS)
{
s_RestoreState = ALL_DONE;
}
else if (s_RestoreState == NUP_ONLY_WAIT_SD_EJECT || s_RestoreState == NUP_ONLY_WAIT_NEXT)
{
s_RestoreState = NUP_ONLY_WAIT_NEXT;
}
// ユーザのSDが抜かれてからFAILにする
else if (s_RestoreState == CHECK_SD_DIRECTORY_FAIL)
{
s_RestoreState = FAIL;
}
else if(s_RestoreState == PREINSTALL_CHECK_USER_SD_INSERT)
{
s_RestoreState = PREINSTALL_WAIT_USER_SD_INSERT;
}
else if(s_RestoreState == PREINSTALL_CHECK_REPAIR_SD)
{
s_RestoreState = PREINSTALL_WAIT_USER_SD_EJECT;
}
else if(s_RestoreState == PREINSTALL_FAIL_CHECK_REPAIR_SD)
{
s_RestoreState = PREINSTALL_CHECK_SD_FAIL;
}
// FAILのときは一旦電源を切らないと動かないようにしておく
// IVSチェック時はユーザのSDカードを挿入してもらうため
// プリインストール時はユーザのSDカードを挿入してもらうため
else if (s_RestoreState != FAIL && s_RestoreState != CHECK_IVS && s_RestoreState != PREINSTALL_WAIT_USER_SD_INSERT
&& s_RestoreState != PREINSTALL_WAIT_USER_SD_EJECT && s_RestoreState != PREINSTALL_CHECK_SD_FAIL &&
s_RestoreState != PREINSTALL_DOWNLOAD_APP_NOT_ENOUGH_SPACE && s_RestoreState != PREINSTALL_WAIT_USER_SD_INSERT_WAIT_NEXT)
{
InitializeState();
ClearFileReadResult();
}
}
void OnSdInserted()
{
if(s_RestoreState == CHECK_IVS)
{
// SDカードが変わるのでファイルチェックは初期化する
common::InitializeFileCheck();
s_RestoreState = CHECK_SD_DIRECTORY;
}
else if(s_RestoreState == PREINSTALL_WAIT_USER_SD_INSERT)
{
// SDカードが変わるのでファイルチェックは初期化する
common::InitializeFileCheck();
s_RestoreState = PREINSTALL_WAIT_USER_SD_INSERT_WAIT_NEXT;
}
else if(s_RestoreState == PREINSTALL_WAIT_USER_SD_EJECT)
{
// SDカードが変わるのでファイルチェックは初期化する
common::InitializeFileCheck();
s_RestoreState = PREINSTALL_CHECK_REPAIR_SD;
}
else if(s_RestoreState == PREINSTALL_CHECK_SD_FAIL || s_RestoreState == PREINSTALL_DOWNLOAD_APP_NOT_ENOUGH_SPACE)
{
// SDカードが変わるのでファイルチェックは初期化する
common::InitializeFileCheck();
s_RestoreState = PREINSTALL_FAIL_CHECK_REPAIR_SD;
}
}
void InitializeState()
{
s_RestoreState = STARTUP;
s_RestoreMode = RESTORE_MODE_RESTORE;
for(u32 i = 0; i < SHOP_OPERATION_NUM_MAX; i++)
{
s_ShopOperationExecuted[i] = false;
s_ShopOperationRetryCount[i] = 0;
}
for(u32 i = 0; i < RESTORE_STATE_MAX; i++)
{
s_PlayedCursorSound[i] = false;
}
for(u32 i = 0; i < ANNOTATION_MAX; i++)
{
s_PlayedAnnotationSound[i] = false;
}
common::InitializeFileCheck();
s_ReadSettingDone = false;
s_ReadSettingIsSuccess = false;
s_PlayedFailSound = false;
s_ExecuteFgNup = false;
s_FgNupRetryCount = 0;
s_NupOnlyMode = false;
s_GetIvsOnlyMode = false;
s_CheckSdOnlyMode = false;
s_SkipNupMode = false;
s_ExecutePreparePreinstallTitleDownload = false;
s_ExecutePreinstallTitleDownload = false;
s_PreinstallTitleDownloadSuccess = false;
}
u32 GetProgress()
{
if(s_RestoreState == RESTORE_TWL_SOUND ||
s_RestoreState == RESTORE_TWL_PHOTO ||
s_RestoreState == RESTORE_IN_PROGRESS ||
s_RestoreState == POST_RESTORE ||
s_RestoreState == RESTORE_DONE)
{
return GetImportProgress();
}
else if (s_RestoreState == RESTORE_TWL_NAND)
{
return GetImportProgressTwlNand();
}
else if(s_RestoreState == UPDATE_IN_PROGRESS ||
s_RestoreState == UPDATE_DONE)
{
return GetUpdateProgress();
}
else if (s_RestoreState == DOWNLOAD_TWL || s_RestoreState == PREINSTALL_DOWNLOAD_APP)
{
return GetTitleDownloadProgress();
}
else
{
return 0;
}
}
RestoreMode GetRestoreMode()
{
return s_RestoreMode;
}
} // namespace ConsoleRestore