mirror of
https://github.com/rvtr/ctr_Repair.git
synced 2025-10-31 13:51:08 -04:00
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@305 385bec56-5757-e545-9c3a-d8741f4650f1
941 lines
29 KiB
C++
941 lines
29 KiB
C++
/*---------------------------------------------------------------------------*
|
||
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 "Controller.h"
|
||
#include "FileChecker.h"
|
||
#include "ConsoleRestore.h"
|
||
#include "SimplePlayer.h"
|
||
#include "CommonLogger.h"
|
||
#include "Importer.h"
|
||
#include "Updater.h"
|
||
#include "NtpClient.h"
|
||
|
||
namespace ConsoleRestore
|
||
{
|
||
|
||
namespace
|
||
{
|
||
|
||
typedef enum RestoreState
|
||
{
|
||
STARTUP, // 初期値
|
||
SERIAL_IS_NOT_IN_SD, // シリアルナンバーファイルがSDカードにないことを表示
|
||
SERIAL_IN_SD, // シリアルナンバーの情報を表示
|
||
UPDATE_IN_PROGRESS, // アップデート中
|
||
UPDATE_DONE, // アップデート完了
|
||
NUP_ONLY_WAIT_SD_EJECT, // NUP_ONLYモードでSDカード抜き待ち
|
||
NUP_ONLY_WAIT_NEXT, // NUP_ONLYモードでキー入力待ち
|
||
RESTORE_TWL_SOUND, // TWLサウンドの書き込み中
|
||
RESTORE_TWL_PHOTO, // TWL写真の書き込み中
|
||
RESTORE_IN_PROGRESS, // 書き込み中
|
||
POST_RESTORE, // 書き込み後の処理
|
||
RESTORE_DONE, // 書き込み完了
|
||
REBOOTING, // 再起動を行う
|
||
ERASE, // 削除処理を行う
|
||
HISTORY_RECOVER, // プレイ履歴の書き戻しを行う
|
||
TIME_ADJUST, // 時計あわせを行う
|
||
WAIT_SD_EJECT, // SDカードぬき待ち
|
||
ALL_DONE, // すべて完了
|
||
SHUTDOWN, // シャットダウン中
|
||
FAIL // 失敗
|
||
} RestoreState;
|
||
|
||
// Restore状態管理
|
||
RestoreState s_RestoreState = STARTUP;
|
||
// Restoreモード管理
|
||
RestoreMode s_RestoreMode = RESTORE_MODE_RESTORE;
|
||
|
||
// インターネット設定を読んだかどうか
|
||
bool s_ReadSettingDone = false;
|
||
// インターネット設定を読んだ結果
|
||
bool s_ReadSettingSuccess = false;
|
||
// NUP専用モードかどうか
|
||
bool s_NupOnlyMode = false;
|
||
|
||
// APSettingの書式が無い警告サウンドを鳴らしたかどうか
|
||
bool s_ExistAPSettingAnnotation = false;
|
||
// APSettingの書式が違っている警告サウンドを鳴らしたかどうか
|
||
bool s_APSettingAnnotation = false;
|
||
// シリアルナンバーがない警告サウンドを鳴らしたかどうか
|
||
bool s_SerialNumberAnnotation = false;
|
||
// 失敗サウンドを鳴らしたかどうか
|
||
bool s_PlayedFailSound = false;
|
||
// 操作開始サウンドを鳴らしたかどうか
|
||
bool s_PlayedStartCursor = false;
|
||
// リブート開始前サウンドを鳴らしたかどうか
|
||
bool s_PlayedRebootCursor = false;
|
||
// SD抜き出し前サウンドを鳴らしたかどうか
|
||
bool s_PlayedSdPullOutCursor = false;
|
||
// バージョンデータが無い警告サウンドを鳴らしたかどうか
|
||
bool s_ExistsVersionDataAnnotation = false;
|
||
// バージョンデータを読んだかどうか
|
||
bool s_ReadVersionDone = false;
|
||
// バージョンデータを読んだ結果
|
||
nn::Result s_ReadVersionResult = nn::ResultSuccess();
|
||
// SDに書き込みできない警告サウンドを鳴らしたかどうか
|
||
bool s_SdWriteProetctAnnotation = false;
|
||
|
||
// ネットワークアップデートを開始したかどうか
|
||
bool s_ExecuteFgNup = false;
|
||
// FGNUPを何回リトライしたか
|
||
u32 s_FgNupRetryCount = 0;
|
||
|
||
|
||
} // namespace <unnamed>
|
||
|
||
bool NeedsAcAdater()
|
||
{
|
||
return IsBatteryLower() && !IsAdapterConnected();
|
||
}
|
||
|
||
bool CheckAndReadAPSetting(::std::vector<std::string>& operationMessage)
|
||
{
|
||
using namespace common;
|
||
|
||
if (!ExistsAPSetting())
|
||
{
|
||
if(!s_ExistAPSettingAnnotation)
|
||
{
|
||
s_ExistAPSettingAnnotation = true;
|
||
common::PlaySound(common::SOUND_ANNOTATION);
|
||
}
|
||
operationMessage.push_back(::std::string("Accsess_Point_Setting does not exist!"));
|
||
return false;
|
||
}
|
||
|
||
// 設定ファイルからAP設定を読み込む
|
||
if (!s_ReadSettingDone)
|
||
{
|
||
s_ReadSettingDone = true;
|
||
s_ReadSettingSuccess = ReadSetting(&s_NupOnlyMode);
|
||
}
|
||
|
||
if(s_NupOnlyMode)
|
||
{
|
||
s_RestoreMode = RESTORE_MODE_NUP_ONLY;
|
||
}
|
||
|
||
if (!s_ReadSettingSuccess)
|
||
{
|
||
operationMessage.push_back(::std::string("Invalid Accsess_Point_Setting format!"));
|
||
if(!s_APSettingAnnotation)
|
||
{
|
||
s_APSettingAnnotation = true;
|
||
common::PlaySound(common::SOUND_ANNOTATION);
|
||
}
|
||
|
||
}
|
||
|
||
return s_ReadSettingSuccess;
|
||
}
|
||
|
||
nn::Result CheckAndReadVersionData(::std::vector<std::string>& operationMessage)
|
||
{
|
||
using namespace common;
|
||
|
||
if (!ExistsVersionData())
|
||
{
|
||
if(!s_ExistsVersionDataAnnotation)
|
||
{
|
||
s_ExistsVersionDataAnnotation = true;
|
||
common::PlaySound(common::SOUND_ANNOTATION);
|
||
}
|
||
operationMessage.push_back(::std::string("Version Data does not exist!"));
|
||
return nn::Result(nn::Result::LEVEL_PERMANENT, nn::Result::SUMMARY_NOT_FOUND, nn::Result::MODULE_COMMON,
|
||
nn::Result::DESCRIPTION_NOT_FOUND);
|
||
}
|
||
|
||
// バージョン情報ファイルを読み込む
|
||
if (!s_ReadVersionDone)
|
||
{
|
||
s_ReadVersionDone = true;
|
||
s_ReadVersionResult = ReadVersionData();
|
||
}
|
||
|
||
return s_ReadVersionResult;
|
||
}
|
||
|
||
void PutAliveMessage(::std::vector<std::string>& operationMessage, const char* str)
|
||
{
|
||
std::string message = std::string(str);
|
||
static u8 i = 0;
|
||
if (i < 0xff / 4)
|
||
{
|
||
operationMessage.push_back(message + std::string(" /"));
|
||
}
|
||
else if (i < 0xff * 2 / 4)
|
||
{
|
||
operationMessage.push_back(message + std::string(" |"));
|
||
}
|
||
else if (i < 0xff * 3 / 4)
|
||
{
|
||
operationMessage.push_back(message + std::string(" \\"));
|
||
}
|
||
else
|
||
{
|
||
operationMessage.push_back(message + std::string(" -"));
|
||
}
|
||
i += 4;
|
||
}
|
||
|
||
nn::Result ExecSyncMcuRtc()
|
||
{
|
||
nn::Result result = nn::ResultSuccess();
|
||
if(!common::ExistsRtcSyncFinishedFile())
|
||
{
|
||
result = ImportMcuRtc();
|
||
if(result.IsSuccess())
|
||
{
|
||
// RTCを同期完了ファイルを作る
|
||
CreateRtcSyncFinishedFile();
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// Zero NUP限定コード
|
||
bool NeedsNup()
|
||
{
|
||
if(AlreadyExecutedNup() || s_NupOnlyMode)
|
||
{
|
||
return !common::ExistsUpdateCheckedFile();
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
void ControlState(::std::vector<std::string>& operationMessage, bool& nextStep, bool& continueRestore)
|
||
{
|
||
using namespace common;
|
||
nn::Result result;
|
||
|
||
// 状態遷移Controller
|
||
switch (s_RestoreState)
|
||
{
|
||
// 起動時
|
||
case STARTUP:
|
||
{
|
||
bool error = false;
|
||
bool needsUpdate = false;
|
||
bool needsErase = false;
|
||
bool validApSetting = false;
|
||
|
||
// SDカードが挿入されているか?
|
||
if (nn::fs::IsSdmcInserted())
|
||
{
|
||
// SDカードに書き込みできるか?
|
||
if (!nn::fs::IsSdmcWritable())
|
||
{
|
||
if (!s_SdWriteProetctAnnotation)
|
||
{
|
||
s_SdWriteProetctAnnotation = true;
|
||
PlaySound(SOUND_ANNOTATION);
|
||
}
|
||
operationMessage.push_back(::std::string("Can*t Write SD Card!!\n"));
|
||
break;
|
||
}
|
||
|
||
result = CheckAndReadVersionData(operationMessage);
|
||
if(result.IsFailure())
|
||
{
|
||
// バージョン情報の取得に失敗
|
||
error = true;
|
||
s_RestoreState = FAIL;
|
||
}
|
||
|
||
validApSetting = CheckAndReadAPSetting(operationMessage);
|
||
if (!validApSetting)
|
||
{
|
||
error = true;
|
||
}
|
||
else
|
||
{
|
||
// NUPが必要か?
|
||
if (!NeedsNup())
|
||
{
|
||
if (s_NupOnlyMode)
|
||
{
|
||
s_RestoreState = NUP_ONLY_WAIT_SD_EJECT;
|
||
|
||
// リストア状態チェックファイルをすべて削除
|
||
DeleteAllCheckFiles();
|
||
|
||
break;
|
||
}
|
||
|
||
// SDカードに書き込み完了ファイルがあるか?
|
||
if (!ExistsWriteFinishedFile())
|
||
{
|
||
// IVSを読めるか?
|
||
if (CanReadIVS())
|
||
{
|
||
// 本体初期化完了ファイルがあるか?
|
||
if (ExistsConsoleInitializedFile())
|
||
{
|
||
// SDカードにシリアルナンバーがあるか?
|
||
if (!ExistsSerialNumberFile())
|
||
{
|
||
COMMON_LOGGER("Can't Read Serial Number in SD Card!!\n");
|
||
error = true;
|
||
s_RestoreState = SERIAL_IS_NOT_IN_SD;
|
||
}
|
||
else
|
||
{
|
||
u8 serial[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN];
|
||
result = ReadSerialNumber(serial);
|
||
if(result.IsSuccess())
|
||
{
|
||
::std::string serialStr(reinterpret_cast<char*> (serial));
|
||
operationMessage.push_back(::std::string("Serial Number in SD : ") + serialStr);
|
||
}
|
||
else
|
||
{
|
||
error = true;
|
||
s_RestoreState = FAIL;
|
||
}
|
||
}
|
||
|
||
|
||
// SDカードにリージョンデータがあるか?
|
||
if (ExistsRegionData())
|
||
{
|
||
// リージョンデータは一致しているか?
|
||
if (EqualsRegionDataandRegion().IsFailure())
|
||
{
|
||
COMMON_LOGGER("Current Region and Region in SD differ!!\n");
|
||
error = true;
|
||
s_RestoreState = FAIL;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 移行不能なのでFAIL
|
||
COMMON_LOGGER("Can't Read Region in SD Card!!\n");
|
||
error = true;
|
||
s_RestoreState = FAIL;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
if (!ExistsIVSFile())
|
||
{
|
||
// 移行不能なのでFAIL
|
||
COMMON_LOGGER("Can't Read IVS in SD Card!!\n");
|
||
error = true;
|
||
s_RestoreState = FAIL;
|
||
}
|
||
else
|
||
{
|
||
COMMON_LOGGER("Initialize Console\n");
|
||
|
||
// 本体初期化完了ファイルを作る
|
||
CreateConsoleInitializedFile();
|
||
|
||
// ファイルシステムの初期化を行う
|
||
InitializeFileSystem();
|
||
error = true;
|
||
s_RestoreState = REBOOTING;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
error = true;
|
||
operationMessage.push_back(::std::string("Can't Read IVS!!"));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (validApSetting)
|
||
{
|
||
// 削除処理を行う
|
||
needsErase = true;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (validApSetting)
|
||
{
|
||
// ネットワークアップデートを行う
|
||
needsUpdate = true;
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
else
|
||
{
|
||
error = true;
|
||
operationMessage.push_back(::std::string("Insert SD Card!!"));
|
||
}
|
||
|
||
// ACアダプタが必要か?
|
||
if (NeedsAcAdater())
|
||
{
|
||
error = true;
|
||
operationMessage.push_back(::std::string("Connect AC Adapter!!"));
|
||
}
|
||
|
||
// エラーが無ければ進行用メッセージ表示
|
||
if (!error)
|
||
{
|
||
operationMessage.push_back(::std::string("Push A or START Button"));
|
||
if(needsUpdate)
|
||
{
|
||
operationMessage.push_back(::std::string("Network Update Mode"));
|
||
}
|
||
else if(needsErase)
|
||
{
|
||
operationMessage.push_back(::std::string("Clock Sync Mode"));
|
||
}
|
||
else
|
||
{
|
||
operationMessage.push_back(::std::string("Import Data Mode"));
|
||
}
|
||
|
||
if(!s_PlayedStartCursor)
|
||
{
|
||
PlaySound(SOUND_CURSOR);
|
||
s_PlayedStartCursor = true;
|
||
}
|
||
}
|
||
|
||
if (nextStep && !error)
|
||
{
|
||
if (needsUpdate)
|
||
{
|
||
COMMON_LOGGER("Start Network Update\n");
|
||
s_RestoreState = UPDATE_IN_PROGRESS;
|
||
}
|
||
else if(needsErase)
|
||
{
|
||
COMMON_LOGGER("Erase Trash\n");
|
||
s_RestoreState = ERASE;
|
||
}
|
||
else
|
||
{
|
||
COMMON_LOGGER("Start Import Data\n");
|
||
// Zero NUP限定
|
||
// RTC同期を行う
|
||
// NUPされない場合があるのでここで同期
|
||
result = ExecSyncMcuRtc();
|
||
if(result <= nn::fs::ResultVerificationFailed())
|
||
{
|
||
s_RestoreState = FAIL;
|
||
}
|
||
else
|
||
{
|
||
s_RestoreState = RESTORE_TWL_SOUND;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
// シリアルナンバーがSDカードにないこと警告
|
||
case SERIAL_IS_NOT_IN_SD:
|
||
{
|
||
operationMessage.push_back(::std::string("Serial Number Is Not In SD Card"));
|
||
operationMessage.push_back(::std::string("Push A or START Button"));
|
||
operationMessage.push_back(::std::string("Import Data Mode"));
|
||
|
||
if (!s_SerialNumberAnnotation)
|
||
{
|
||
s_SerialNumberAnnotation = true;
|
||
PlaySound(SOUND_ANNOTATION);
|
||
}
|
||
|
||
if (nextStep)
|
||
{
|
||
s_RestoreState = RESTORE_TWL_SOUND;
|
||
}
|
||
}
|
||
break;
|
||
|
||
// アップデート中
|
||
case UPDATE_IN_PROGRESS:
|
||
{
|
||
continueRestore = true;
|
||
|
||
// ACアダプタが必要か?
|
||
if (NeedsAcAdater())
|
||
{
|
||
continueRestore = false;
|
||
operationMessage.push_back(::std::string("Connect AC Adapter!!"));
|
||
}
|
||
|
||
// アップデートを行う
|
||
if(!s_ExecuteFgNup)
|
||
{
|
||
if(ImportCountryLanguageData().IsSuccess())
|
||
{
|
||
StartFGNetworkUpdate();
|
||
s_ExecuteFgNup = true;
|
||
}
|
||
else
|
||
{
|
||
s_RestoreState = FAIL;
|
||
}
|
||
}
|
||
|
||
// 動いていることを表示
|
||
{
|
||
PutAliveMessage(operationMessage, "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");
|
||
// アップデート完了ファイルを作成
|
||
CreateUpdateFinishedFile();
|
||
|
||
s_RestoreState = UPDATE_DONE;
|
||
|
||
}
|
||
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;
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
break;
|
||
|
||
// アップデート完了
|
||
case UPDATE_DONE:
|
||
{
|
||
operationMessage.push_back(::std::string("Network Update Done."));
|
||
operationMessage.push_back(::std::string("Press A or START Button to Reboot"));
|
||
|
||
if(!s_PlayedRebootCursor)
|
||
{
|
||
PlaySound(SOUND_CURSOR);
|
||
s_PlayedRebootCursor = true;
|
||
}
|
||
|
||
if (nextStep)
|
||
{
|
||
s_RestoreState = REBOOTING;
|
||
}
|
||
}
|
||
break;
|
||
|
||
|
||
// TWLサウンド領域の書き込み中
|
||
case RESTORE_TWL_SOUND:
|
||
{
|
||
static bool init = true;
|
||
if (init)
|
||
{
|
||
// データを書き込む
|
||
ImportTwlSoundData();
|
||
init = false;
|
||
}
|
||
|
||
// 処理が完了した
|
||
if (IsImportFinished())
|
||
{
|
||
FinalizeImportThread();
|
||
s_RestoreState = RESTORE_TWL_PHOTO;
|
||
}
|
||
}
|
||
break;
|
||
|
||
// TWL写真領域の書き込み
|
||
case RESTORE_TWL_PHOTO:
|
||
{
|
||
static bool init = true;
|
||
if (init)
|
||
{
|
||
// データを書き込む
|
||
ImportTwlPhotoData();
|
||
init = false;
|
||
}
|
||
|
||
// 処理が完了した
|
||
if (IsImportFinished())
|
||
{
|
||
FinalizeImportThread();
|
||
s_RestoreState = RESTORE_IN_PROGRESS;
|
||
}
|
||
}
|
||
break;
|
||
|
||
|
||
// 書き込み中
|
||
case RESTORE_IN_PROGRESS:
|
||
{
|
||
continueRestore = true;
|
||
|
||
// ACアダプタが必要か?
|
||
if (NeedsAcAdater())
|
||
{
|
||
continueRestore = false;
|
||
operationMessage.push_back(::std::string("Connect AC Adapter!!"));
|
||
}
|
||
|
||
// データを読み込む
|
||
if(ImportData().IsFailure())
|
||
{
|
||
s_RestoreState = FAIL;
|
||
}
|
||
|
||
// 処理が完了した
|
||
if (continueRestore && IsImportFinished())
|
||
{
|
||
COMMON_LOGGER("Import NAND Data Finished.\n");
|
||
|
||
if (GetProgress() > 99)
|
||
{
|
||
s_RestoreState = POST_RESTORE;
|
||
}
|
||
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.push_back(::std::string("Post Process..."));
|
||
// 書き込み完了ファイルを作成
|
||
CreateWriteFinishedFile();
|
||
|
||
s_RestoreState = RESTORE_DONE;
|
||
}
|
||
break;
|
||
|
||
// 書き込み完了
|
||
case RESTORE_DONE:
|
||
{
|
||
operationMessage.push_back(::std::string("Restore Done."));
|
||
operationMessage.push_back(::std::string("Press A or START Button to Reboot"));
|
||
|
||
if(!s_PlayedRebootCursor)
|
||
{
|
||
PlaySound(SOUND_CURSOR);
|
||
s_PlayedRebootCursor = true;
|
||
}
|
||
|
||
if (nextStep)
|
||
{
|
||
s_RestoreState = REBOOTING;
|
||
}
|
||
}
|
||
break;
|
||
|
||
// 削除処理
|
||
case ERASE:
|
||
{
|
||
Cleanup();
|
||
s_RestoreState = HISTORY_RECOVER;
|
||
}
|
||
break;
|
||
|
||
// 削除処理
|
||
case HISTORY_RECOVER:
|
||
{
|
||
static bool init = true;
|
||
if (init)
|
||
{
|
||
// ptmのセーブデータ移行後に時計を無効化する
|
||
nn::ptm::CTR::InvalidateSystemTime();
|
||
|
||
// cfgの本体固有値をcal値で初期化する
|
||
InitializeHardwareDependentSetting();
|
||
|
||
init = false;
|
||
}
|
||
|
||
s_RestoreState = TIME_ADJUST;
|
||
}
|
||
|
||
|
||
// 時計あわせ
|
||
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())
|
||
{
|
||
s_RestoreState = WAIT_SD_EJECT;
|
||
}
|
||
else
|
||
{
|
||
s_RestoreState = FAIL;
|
||
}
|
||
|
||
// リストア状態チェックファイルをすべて削除
|
||
DeleteAllCheckFiles();
|
||
}
|
||
}
|
||
break;
|
||
|
||
// すべて完了
|
||
case WAIT_SD_EJECT:
|
||
{
|
||
operationMessage.push_back(::std::string("ALL Done. Pull Out SD Card."));
|
||
// SDカード抜けのみで次の状態に遷移する
|
||
|
||
if (!s_PlayedSdPullOutCursor)
|
||
{
|
||
common::PlaySound(common::SOUND_CURSOR);
|
||
s_PlayedSdPullOutCursor = true;
|
||
}
|
||
|
||
}
|
||
break;
|
||
|
||
// すべて完了
|
||
case ALL_DONE:
|
||
{
|
||
operationMessage.push_back(::std::string("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.push_back(::std::string("Failed."));
|
||
if (!s_PlayedFailSound)
|
||
{
|
||
PlaySound(SOUND_NG);
|
||
s_PlayedFailSound = true;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case NUP_ONLY_WAIT_SD_EJECT:
|
||
{
|
||
operationMessage.push_back(::std::string("Update Done. Pull Out SD Card."));
|
||
|
||
// SDカード抜けのみで次の状態に遷移する
|
||
if (!s_PlayedSdPullOutCursor)
|
||
{
|
||
common::PlaySound(common::SOUND_CURSOR);
|
||
s_PlayedSdPullOutCursor = true;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case NUP_ONLY_WAIT_NEXT:
|
||
{
|
||
operationMessage.push_back(::std::string("A or START Button to Shutdown."));
|
||
|
||
if(nextStep)
|
||
{
|
||
s_RestoreState = SHUTDOWN;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case SHUTDOWN:
|
||
{
|
||
// 本体初期化を行う
|
||
InitializeFileSystem();
|
||
|
||
// シャットダウンする
|
||
nn::ptm::CTR::ShutdownAsync(0, nn::fnd::TimeSpan::FromSeconds(0));
|
||
}
|
||
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 = ALL_DONE;
|
||
}
|
||
else if(s_RestoreState == NUP_ONLY_WAIT_SD_EJECT || s_RestoreState == NUP_ONLY_WAIT_NEXT)
|
||
{
|
||
s_RestoreState = NUP_ONLY_WAIT_NEXT;
|
||
}
|
||
// FAILのときは一旦電源を切らないと動かないようにしておく
|
||
else if(s_RestoreState != FAIL)
|
||
{
|
||
InitializeState();
|
||
ClearFileReadResult();
|
||
}
|
||
}
|
||
|
||
void InitializeState()
|
||
{
|
||
s_RestoreState = STARTUP;
|
||
s_RestoreMode = RESTORE_MODE_RESTORE;
|
||
|
||
common::InitializeFileCheck();
|
||
|
||
s_ExistAPSettingAnnotation = false;
|
||
s_ReadSettingDone = false;
|
||
s_ReadSettingSuccess = false;
|
||
s_APSettingAnnotation = false;
|
||
s_SerialNumberAnnotation = false;
|
||
s_PlayedFailSound = false;
|
||
s_ExecuteFgNup = false;
|
||
s_FgNupRetryCount = 0;
|
||
s_PlayedStartCursor = false;
|
||
s_PlayedRebootCursor = false;
|
||
s_PlayedSdPullOutCursor = false;
|
||
s_NupOnlyMode = false;
|
||
s_ReadVersionDone = false;
|
||
s_SdWriteProetctAnnotation = false;
|
||
s_ReadVersionResult = nn::ResultSuccess();
|
||
}
|
||
|
||
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 == UPDATE_IN_PROGRESS ||
|
||
s_RestoreState == UPDATE_DONE)
|
||
{
|
||
return GetUpdateProgress();
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
}
|
||
|
||
RestoreMode GetRestoreMode()
|
||
{
|
||
return s_RestoreMode;
|
||
}
|
||
|
||
} // namespace ConsoleRestore
|