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@829 385bec56-5757-e545-9c3a-d8741f4650f1
540 lines
15 KiB
C++
540 lines
15 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 "Controller.h"
|
||
#include "FileChecker.h"
|
||
#include "Exporter.h"
|
||
#include "SimplePlayer.h"
|
||
#include "CommonLogger.h"
|
||
#include "Checker.h"
|
||
#include "FileTransfer.h"
|
||
#include "MenuSavedataModifier.h"
|
||
#include <nn/am/am_ApiSystemMenu.h>
|
||
|
||
#include <nn.h>
|
||
|
||
namespace ConsoleBackup
|
||
{
|
||
|
||
namespace
|
||
{
|
||
|
||
typedef enum BackupState
|
||
{
|
||
STARTUP, // 初期値
|
||
MODIFY_MENU_SAVEDATA, // MMENセーブデータの修正
|
||
CHECK_SAVEDATA, // セーブデータの確認
|
||
EXPORT_TWL_NAND, // TWLセーブデータ領域の吸出し中
|
||
EXPORT_TWL_SOUND, // TWLサウンド領域の吸出し中
|
||
EXPORT_TWL_PHOTO, // TWL写真領域の吸出し中
|
||
EXPORT_CTR_NAND, // 吸出し中
|
||
DELETE_NIM, // nimのシステムセーブデータ削除
|
||
DONE, // 吸出し完了
|
||
FINISHED, // SDカード抜き完了
|
||
FAIL, // 失敗
|
||
FAIL_CHECK, // セーブデータのチェック時エラー
|
||
|
||
STATE_MAX
|
||
} BackupState;
|
||
|
||
|
||
// Backupモード管理
|
||
BackupMode s_BackupMode = BACKUP_MODE_CHECK;
|
||
|
||
// APSettingの書式が無い警告サウンドを鳴らしたかどうか
|
||
bool s_ExistAPSettingAnnotation = false;
|
||
// SDに書き込みできない警告サウンドを鳴らしたかどうか
|
||
bool s_SdWriteProetctAnnotation = false;
|
||
|
||
BackupState s_BackupState = STARTUP;
|
||
bool s_PlayedStartCursor = false;
|
||
bool s_PlayedSdPullOutCursor = false;
|
||
bool s_PlayedFinishedSound = false;
|
||
bool s_PlayedFailSound = false;
|
||
|
||
} // namespace <unnamed>
|
||
|
||
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;
|
||
}
|
||
|
||
bool NeedsAcAdapter(common::HardwareStateManager& manager)
|
||
{
|
||
return manager.IsBatteryLower() && !manager.IsAdapterConnected();
|
||
}
|
||
|
||
void ControlState(common::HardwareStateManager& manager, common::OperationMessage& operationMessage, bool& nextStep,
|
||
bool& continueBackup, bool forceDelete)
|
||
{
|
||
// 状態遷移Controller
|
||
switch (s_BackupState)
|
||
{
|
||
|
||
// 起動時
|
||
case STARTUP:
|
||
{
|
||
bool error = false;
|
||
// 完全性検証SEEDを読めるか?
|
||
if (manager.CanReadIvs())
|
||
{
|
||
// SDカードが挿入されているか?
|
||
if (nn::fs::IsSdmcInserted())
|
||
{
|
||
// SDカードに書き込みできるか?
|
||
if (!nn::fs::IsSdmcWritable())
|
||
{
|
||
if (!s_SdWriteProetctAnnotation)
|
||
{
|
||
s_SdWriteProetctAnnotation = true;
|
||
common::PlaySound(common::SOUND_ANNOTATION);
|
||
}
|
||
operationMessage.Add("Can*t Write SD Card!!\n");
|
||
break;
|
||
}
|
||
|
||
// 無線設定ファイルがあるか?
|
||
if (common::ExistsAPSetting())
|
||
{
|
||
// 書き込み中に抜かないように
|
||
if (nextStep)
|
||
{
|
||
// シリアルナンバーを読み取れるか?
|
||
if (!manager.CanReadSerialNumber())
|
||
{
|
||
common::PlaySound(common::SOUND_ANNOTATION);
|
||
COMMON_LOGGER("Can't Read Serial Number\n");
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
error = true;
|
||
if (!s_ExistAPSettingAnnotation)
|
||
{
|
||
s_ExistAPSettingAnnotation = true;
|
||
common::PlaySound(common::SOUND_ANNOTATION);
|
||
}
|
||
operationMessage.Add("Accsess_Point_Setting does not exist!");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
error = true;
|
||
operationMessage.Add("Insert SD Card!!");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
error = true;
|
||
operationMessage.Add("Can't Read SDCI!!");
|
||
}
|
||
|
||
// ACアダプタが必要か?
|
||
if (NeedsAcAdapter(manager))
|
||
{
|
||
error = true;
|
||
operationMessage.Add("Connect AC Adapter!!");
|
||
}
|
||
|
||
// エラーが無ければ進行用メッセージ表示
|
||
if (!error)
|
||
{
|
||
operationMessage.Add("Push A or START Button");
|
||
if (!s_PlayedStartCursor)
|
||
{
|
||
common::PlaySound(common::SOUND_CURSOR);
|
||
s_PlayedStartCursor = true;
|
||
}
|
||
}
|
||
|
||
if (nextStep && !error)
|
||
{
|
||
COMMON_LOGGER("Checking SaveData\n");
|
||
|
||
if(forceDelete)
|
||
{
|
||
s_BackupMode = BACKUP_MODE_DELETE_IF_FAILED;
|
||
}
|
||
s_BackupState = MODIFY_MENU_SAVEDATA;
|
||
}
|
||
}
|
||
break;
|
||
|
||
|
||
case MODIFY_MENU_SAVEDATA:
|
||
{
|
||
MenuSavedataModifier modifier;
|
||
common::VerDef version;
|
||
manager.GetVersionData(&version);
|
||
|
||
nn::Result result = modifier.Modify(nn::cfg::GetRegion(), version.cup);
|
||
COMMON_LOGGER_RESULT_IF_FAILED(result);
|
||
s_BackupState = CHECK_SAVEDATA;
|
||
}
|
||
break;
|
||
|
||
case CHECK_SAVEDATA:
|
||
{
|
||
static bool init = true;
|
||
if (init)
|
||
{
|
||
StartSaveDataCheck(s_BackupMode == BACKUP_MODE_DELETE_IF_FAILED);
|
||
init = false;
|
||
}
|
||
|
||
PutAliveMessage(operationMessage, "Checking SaveData");
|
||
|
||
if (IsCheckSaveDataFinished())
|
||
{
|
||
FinalizeSaveDataCheck();
|
||
// 削除モードでなければエラーにする
|
||
if (CheckSaveDataErrorOccured() && !forceDelete)
|
||
{
|
||
s_BackupState = FAIL_CHECK;
|
||
}
|
||
else
|
||
{
|
||
if (CheckSaveDataSucceeded())
|
||
{
|
||
COMMON_LOGGER("Start Export Data\n");
|
||
|
||
s_BackupState = EXPORT_TWL_NAND;
|
||
}
|
||
else
|
||
{
|
||
s_BackupState = FAIL;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
|
||
// TWLセーブデータ領域の吸出し中
|
||
case EXPORT_TWL_NAND:
|
||
{
|
||
static bool init = true;
|
||
if (init)
|
||
{
|
||
// 権利の無いタイトルを削除する
|
||
if(nn::am::DeleteAllExpiredUserPrograms().IsFailure())
|
||
{
|
||
COMMON_LOGGER("Can't delete expired titles");
|
||
s_BackupState = FAIL;
|
||
break;
|
||
}
|
||
|
||
// コンテキストを初期化する
|
||
InitializeFileListContext();
|
||
|
||
// データを書き込む
|
||
if (ExportTwlSaveData().IsFailure())
|
||
{
|
||
s_BackupState = FAIL;
|
||
break;
|
||
}
|
||
init = false;
|
||
}
|
||
|
||
PutAliveMessage(operationMessage, "Exporting TWL SaveData");
|
||
|
||
// 処理が完了した
|
||
if (IsExportThreadFinished())
|
||
{
|
||
FinalizeExportThread();
|
||
if (IsExportSucceeded())
|
||
{
|
||
s_BackupState = EXPORT_TWL_SOUND;
|
||
}
|
||
else
|
||
{
|
||
s_BackupState = FAIL;
|
||
}
|
||
|
||
}
|
||
}
|
||
break;
|
||
|
||
// TWLサウンド領域の吸出し中
|
||
case EXPORT_TWL_SOUND:
|
||
{
|
||
static bool init = true;
|
||
if (init)
|
||
{
|
||
// データを書き込む
|
||
ExportTwlSoundData();
|
||
init = false;
|
||
}
|
||
|
||
PutAliveMessage(operationMessage, "Exporting TWL Sound Data");
|
||
|
||
// 処理が完了した
|
||
if (IsExportThreadFinished())
|
||
{
|
||
FinalizeExportThread();
|
||
if (IsExportSucceeded())
|
||
{
|
||
s_BackupState = EXPORT_TWL_PHOTO;
|
||
}
|
||
else
|
||
{
|
||
s_BackupState = FAIL;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
// TWL写真領域の吸出し中
|
||
case EXPORT_TWL_PHOTO:
|
||
{
|
||
static bool init = true;
|
||
if (init)
|
||
{
|
||
// データを書き込む
|
||
ExportTwlPhotoData();
|
||
init = false;
|
||
}
|
||
|
||
PutAliveMessage(operationMessage, "Exporting TWL Photo Data");
|
||
|
||
// 処理が完了した
|
||
if (IsExportThreadFinished())
|
||
{
|
||
FinalizeExportThread();
|
||
if (IsExportSucceeded())
|
||
{
|
||
s_BackupState = EXPORT_CTR_NAND;
|
||
}
|
||
else
|
||
{
|
||
s_BackupState = FAIL;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
// 吸出し中
|
||
case EXPORT_CTR_NAND:
|
||
{
|
||
continueBackup = true;
|
||
|
||
// ACアダプタが必要か?
|
||
if (NeedsAcAdapter(manager))
|
||
{
|
||
continueBackup = false;
|
||
operationMessage.Add("Connect AC Adapter!!");
|
||
}
|
||
|
||
PutAliveMessage(operationMessage, "Exporting Nand Data");
|
||
|
||
// データを書き込む
|
||
if (!ExportData(manager))
|
||
{
|
||
s_BackupState = FAIL;
|
||
}
|
||
else
|
||
{
|
||
// 処理が完了した
|
||
if (continueBackup && IsExportThreadFinished())
|
||
{
|
||
FinalizeExportThread();
|
||
if (IsExportSucceeded())
|
||
{
|
||
COMMON_LOGGER("Export NAND Data Finished.\n");
|
||
|
||
if (GetExportProgress() > 99)
|
||
{
|
||
s_BackupState = DELETE_NIM;
|
||
}
|
||
else
|
||
{
|
||
s_BackupState = FAIL;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
s_BackupState = FAIL;
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
break;
|
||
|
||
// nimのシステムセーブデータ削除
|
||
case DELETE_NIM:
|
||
{
|
||
if (DeleteNimSaveData())
|
||
{
|
||
s_BackupState = DONE;
|
||
}
|
||
else
|
||
{
|
||
s_BackupState = FAIL;
|
||
}
|
||
|
||
}
|
||
break;
|
||
|
||
// 吸出し完了
|
||
case DONE:
|
||
{
|
||
operationMessage.Add("Backup Done. Pull Out SD Card.");
|
||
|
||
static bool init = true;
|
||
if(init)
|
||
{
|
||
manager.SetWifiOff();
|
||
init = false;
|
||
}
|
||
|
||
if (!s_PlayedSdPullOutCursor)
|
||
{
|
||
common::PlaySound(common::SOUND_CURSOR);
|
||
s_PlayedSdPullOutCursor = true;
|
||
}
|
||
}
|
||
break;
|
||
|
||
// SDカード抜き完了
|
||
case FINISHED:
|
||
{
|
||
operationMessage.Add("Backup Succeeded!!\n");
|
||
if (!s_PlayedFinishedSound)
|
||
{
|
||
common::PlaySound(common::SOUND_OK);
|
||
s_PlayedFinishedSound = true;
|
||
}
|
||
}
|
||
break;
|
||
|
||
// 吸出し失敗
|
||
case FAIL:
|
||
{
|
||
operationMessage.Add("Backup Failed.");
|
||
if (!s_PlayedFailSound)
|
||
{
|
||
common::PlaySound(common::SOUND_NG);
|
||
s_PlayedFailSound = true;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case FAIL_CHECK:
|
||
{
|
||
operationMessage.Add("Check Error.");
|
||
if (!s_PlayedFailSound)
|
||
{
|
||
common::PlaySound(common::SOUND_NG);
|
||
s_PlayedFailSound = true;
|
||
}
|
||
}
|
||
break;
|
||
|
||
}
|
||
}
|
||
|
||
u32 GetProgress()
|
||
{
|
||
if(s_BackupState == CHECK_SAVEDATA)
|
||
{
|
||
return GetCheckSaveDataProgress();
|
||
}
|
||
else if (s_BackupState == EXPORT_TWL_NAND || s_BackupState == EXPORT_TWL_PHOTO|| s_BackupState == EXPORT_TWL_SOUND)
|
||
{
|
||
return common::GetProgress();
|
||
}
|
||
else
|
||
{
|
||
return GetExportProgress();
|
||
}
|
||
}
|
||
|
||
// バックアップモードを取得する
|
||
BackupMode GetBackupMode()
|
||
{
|
||
return s_BackupMode;
|
||
}
|
||
|
||
bool InProgress()
|
||
{
|
||
return s_BackupState == EXPORT_CTR_NAND;
|
||
}
|
||
|
||
bool IsBackupSucceeded()
|
||
{
|
||
return s_BackupState == FINISHED;
|
||
}
|
||
|
||
bool IsBackupFailed()
|
||
{
|
||
return s_BackupState == FAIL;
|
||
}
|
||
|
||
bool IsBackupWarning()
|
||
{
|
||
return s_BackupState == FAIL_CHECK;
|
||
}
|
||
|
||
void OnSdEjected()
|
||
{
|
||
if(s_BackupState == DONE || s_BackupState == FINISHED)
|
||
{
|
||
s_BackupState = FINISHED;
|
||
}
|
||
else if(s_BackupState != FAIL && s_BackupState != FAIL_CHECK)
|
||
{
|
||
common::InitializeFileCheck();
|
||
InitializeState();
|
||
}
|
||
}
|
||
|
||
void OnSdInserted()
|
||
{
|
||
common::Logger::GetLoggerInstance()->ClearSdLog();
|
||
}
|
||
|
||
void InitializeState()
|
||
{
|
||
s_BackupState = STARTUP;
|
||
s_PlayedFailSound = false;
|
||
s_PlayedFinishedSound = false;
|
||
s_ExistAPSettingAnnotation = false;
|
||
s_PlayedStartCursor = false;
|
||
s_PlayedSdPullOutCursor = false;
|
||
s_SdWriteProetctAnnotation = false;
|
||
}
|
||
|
||
} // namespace ConsoleBackup
|