ConsoleRestoreからNetworkUpdaterを作るためのブランチ作成

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@777 385bec56-5757-e545-9c3a-d8741f4650f1
This commit is contained in:
N2614 2014-04-09 01:07:56 +00:00
parent 7811c33af3
commit ad5225b6c5
594 changed files with 29653 additions and 0 deletions

View File

@ -0,0 +1,64 @@
ビルド環境
========
SDK
----
CTR_SDK-3_3 branch r45925 + r51434 + r54939
コンパイラ
-------
ARM C/C++ Compiler, 4.1 [Build 1247] for Nintendo
ミドルウェア
--------
QRコードエンコーダ 1.2.3
ビルド時の注意
------------
### AES鍵の変更
リリース用ビルドでは開発機・量産機でAES鍵を変えるため、
量産機用ビルドの場合
./build.sh PROD
でビルドすること。
開発機用ビルドの場合
./build.sh UNFIXEDKEY
でビルドすること。
### 自動無線ON/OFF
無線ON/OFF切り替えのため、`sources/common/nwm_ExtAPI.cpp` を
`$HORIZON_ROOT/sources/libraries/nwm/CTR`
にコピーしてからnwmをリビルドする必要がある。
### NNA移行完了
NNA移行完了のため、
trunk r54688からactライブラリをコピーする必要がある。
3_3 branch のcfgには無いシンボルを参照してしまうので、trunkでactライブラリをビルドする時に
`sources/common/act_ApiAdmin.cpp.patch`を当ててからビルドすること。
#### trunkからコピーするファイル
* $HORIZON_ROOT/include/nn/act
* $HORIZON_ROOT/include/nn/mii
* $HORIZON_ROOT/include/nn/Result.h
* $HORIZON_ROOT/libraries/CTR-TS.Process.MPCore/release/libnn_act.fast.a
* $HORIZON_ROOT/libraries/CTR-TS.Process.MPCore/release/libnn_act.small.a
* $HORIZON_ROOT/libraries/CTR-TS.Process.MPCore/verbose/libnn_act.fast.a
* $HORIZON_ROOT/libraries/CTR-TS.Process.MPCore/verbose/libnn_act.small.a
リリース時の注意
=============
ConsoleRestoreのReleaseビルドは、ショップ接続時などにで無限ループする不具合があるためDevelopmentビルドを使用する。
その他
=====
PC上でのgoogletestを使う場合BOM付きのUTF-8を
コンパイルできるgccが必要。
cygwin 1.7.9-1
で動作確認済み。
`sources/tests/googletest/common/common.om`にgtestのインストール先を指定する必要がある

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

View File

@ -0,0 +1,106 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: Checker.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 "common_Types.h"
#include "CommonLogger.h"
#include "HeapManager.h"
#include "SaveDataChecker.h"
#include <nn/drivers/aes/CTR/ARM946ES/driverAes_Types.h>
namespace ConsoleBackup
{
namespace
{
const size_t CHECKER_STACK_SIZE = 0x4000;
nn::os::Thread s_CheckerThread;
nn::os::StackBuffer<CHECKER_STACK_SIZE> s_CheckerThreadStackSize;
nn::Result s_CheckerResult;
NandSavedataChecker* s_pChecker;
bool s_CheckErrorOccured = false;
}
s32 GetCheckSaveDataProgress()
{
if(s_pChecker != NULL)
{
return s_pChecker->GetProgress();
}
else
{
return 0;
}
}
void CheckSaveDataThreadFunc(bool erase)
{
size_t bufSize = common::GetAllocatableSize();
if(bufSize > common::FILE_COPY_HEAP_SIZE)
{
bufSize = common::FILE_COPY_HEAP_SIZE;
}
common::HeapManager heap(bufSize);
if (heap.GetAddr() != NULL)
{
s_pChecker = new NandSavedataChecker(heap.GetAddr(), bufSize);
s_CheckerResult = s_pChecker->CleanUp(erase);
}
else
{
s_CheckerResult = nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE,
nn::Result::MODULE_COMMON, nn::Result::DESCRIPTION_OUT_OF_MEMORY);
}
}
void StartSaveDataCheck(bool erase)
{
s_CheckerThread.Start(CheckSaveDataThreadFunc, erase, s_CheckerThreadStackSize);
}
bool IsCheckSaveDataFinished()
{
return s_CheckerThread.IsValid() && !s_CheckerThread.IsAlive();
}
void FinalizeSaveDataCheck()
{
s_CheckerThread.Join();
s_CheckerThread.Finalize();
if(s_pChecker != NULL)
{
s_CheckErrorOccured = s_pChecker->GetCheckErrorOccured();
delete s_pChecker;
}
}
bool CheckSaveDataErrorOccured()
{
return s_CheckErrorOccured;
}
bool CheckSaveDataSucceeded()
{
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(s_CheckerResult);
return s_CheckerResult.IsSuccess();
}
}

View File

@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: Checker.h
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$
*---------------------------------------------------------------------------*/
#ifndef CHECKER_H_
#define CHECKER_H_
namespace ConsoleBackup
{
s32 GetCheckSaveDataProgress();
//!@ brief セーブデータのチェックを開始する
//!@ param[in] erase エラー発生時にファイルを削除するかどうか
void StartSaveDataCheck(bool erase);
bool IsCheckSaveDataFinished();
void FinalizeSaveDataCheck();
bool CheckSaveDataErrorOccured();
bool CheckSaveDataSucceeded();
}
#endif /* CHECKER_H_ */

View File

@ -0,0 +1,316 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: ConsoleBackup.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 <nn.h>
#include <nn/version.h>
#include <nn/ptm/CTR/ptm_ApiSysmenu.h>
#include <nn/mcu.h>
#include <nn/cfg/CTR/cfg_Api.h>
#include <nn/cfg/CTR/cfg_ApiInit.h>
#include <nn/cfg/CTR/cfg_ApiSys.h>
#include <nn/ps.h>
#include <nn/nwm.h>
#include <nn/ac.h>
#include <nn/fs/CTR/fs_ArchiveTypesForSystem.h>
#include <nn/fs/CTR/MPCore/fs_FileSystemBasePrivate.h>
#include <nn/fs/fs_ApiSysSaveData.h>
#include <nn/cfg/CTR/cfg_ApiNor.h>
#include <nn/os/os_SharedInfo.h>
#include <nn/pl/CTR/pl_Version.h>
#include <nn/fs/fs_ApiSharedExtSaveData.h>
#include <nn/nim.h>
#include <nn/ndm.h>
#include <nn/am.h>
#include "demo.h"
#include <vector>
#include <string>
#include "DrawSystemState.h"
#include "FileName.h"
#include "Controller.h"
#include "SimplePlayer.h"
#include "Exporter.h"
#include "CommonLogger.h"
#include "SDMountManager.h"
#include "HeapManager.h"
#include "common_Types.h"
#include "VersionDetect.h"
#include "Util.h"
#include "ResFont.h"
#include "HardwareStateManager.h"
#include "OperationMessage.h"
// バージョン表示用
#include "version.h"
namespace {
// グラフィックスに割り当てるメモリ
const size_t s_GxHeapSize = 0x800000;
common::Util s_HwUtility;
} // namespace <unnamed>
extern "C" void nninitSetupDaemons(void)
{
}
namespace ConsoleBackup{
extern "C" void nnMain(void)
{
nn::Result result;
// os の初期化
nn::os::Initialize();
// fs の初期化
nn::fs::Initialize();
// appletの初期化
nn::applet::Enable( false );
// hid の初期化
result = nn::hid::Initialize();
COMMON_LOGGER_RESULT_IF_FAILED(result);
// ndmの初期化
result = nn::ndm::Initialize();
COMMON_LOGGER_RESULT_IF_FAILED(result);
// 全デーモンの自律動作をacの自動接続も含めて止める
result = nn::ndm::SuspendScheduler();
COMMON_LOGGER_RESULT_IF_FAILED(result);
// cfg の初期化
nn::cfg::CTR::init::Initialize();
nn::cfg::CTR::system::Initialize();
// 時計設定用ptm初期化
nn::ptm::CTR::InitializeForSystemMenu();
// ps の初期化
nn::ps::Initialize();
// amの初期化
nn::am::InitializeForLocalImporter();
// ヒープの確保
common::InitializeHeap();
// RenderSystem の準備
common::HeapManager gxHeapManager(s_GxHeapSize);
uptr heapForGx = reinterpret_cast<uptr>(gxHeapManager.GetAddr());
demo::RenderSystemDrawing renderSystem;
renderSystem.Initialize(heapForGx, s_GxHeapSize);
// ResFontの初期化
common::InitializeResFont();
// サウンドスレッドの起動
common::InitializeSimplePlayer();
// ログ描画の初期化
common::Logger::GetLoggerInstance()->Initialize(common::CONSOLE_WIDTH, common::CONSOLE_HEIGHT,
common::CONSOLE_MAX_LINE, &renderSystem);
// RenderSystemを作ってからログが出せる
common::Logger::InitializeEjectThread();
common::Logger::SetEjectHandler(OnSdEjected);
common::Logger::SetInsertHandler(OnSdInserted);
// 起動時に削除
common::Logger::GetLoggerInstance()->ClearSdLog();
COMMON_LOGGER("\n");
COMMON_LOGGER("CTR Console Backup start\n");
// ボタン入力
nn::hid::PadReader s_PadReader;
nn::hid::PadStatus padStatus;
// データの準備
s_HwUtility.InitializeForBackup();
common::HardwareStateManager manager(s_HwUtility);
// 無線OFF
s_HwUtility.SetWifiOff();
// 情報出力
COMMON_LOGGER("CTR Console Backup %s-%s-%s\n", CONSOLE_REPAIR_VERSION_MAJOR, CONSOLE_REPAIR_VERSION_MINOR, CONSOLE_REPAIR_VERSION_MICRO);
COMMON_LOGGER("System Ver. %d.%d.%d-%d\n",
s_HwUtility.GetCupMajorVersion(),
s_HwUtility.GetCupMinorVersion(),
s_HwUtility.GetCupMicroVersion(),
s_HwUtility.GetNupVersion());
COMMON_LOGGER("System Region %s\n", s_HwUtility.GetRegionCodeA3());
COMMON_LOGGER("Serial Number %s\n", s_HwUtility.GetSerialNumber());
COMMON_LOGGER("Device ID %llu\n", s_HwUtility.GetInfraDeviceId());
COMMON_LOGGER("MAC Address %s\n", s_HwUtility.GetMacAddress());
bool flip = false;
bool continueBackup = false;
bool forceDelete = false;
for(;;)
{
bool nextStep = false;
s_PadReader.ReadLatest(&padStatus);
// AまたはSTARTボタンで進行
if(padStatus.trigger & nn::hid::BUTTON_A ||
padStatus.trigger & nn::hid::BUTTON_START)
{
nextStep = true;
if(padStatus.hold & nn::hid::BUTTON_LEFT)
{
forceDelete = true;
}
}
// LまたはRボタンで上下画面フリップ
if(padStatus.trigger & nn::hid::BUTTON_R ||
padStatus.trigger & nn::hid::BUTTON_L)
{
flip = !flip;
}
// コンソールスクロール
if(padStatus.hold & nn::hid::BUTTON_UP)
{
common::Logger::GetLoggerInstance()->ScrollUp();
}
// コンソールスクロール
if(padStatus.hold & nn::hid::BUTTON_DOWN)
{
common::Logger::GetLoggerInstance()->ScrollDown();
}
// 情報更新
// ACアダプタ
std::string adapterState;
if(manager.IsAdapterConnected())
{
adapterState += ::std::string("Connected");
}
else
{
adapterState += ::std::string("Not Connected");
}
// 操作用メッセージ
// 進捗確認メッセージを兼ねる?
common::OperationMessage operationMessage;
ControlState(manager, operationMessage, nextStep, continueBackup, forceDelete);
nn::util::FloatColor titleColor;
titleColor.r = 0.3f;
titleColor.g = 0.f;
titleColor.b = 0.2f;
// 上画面表示
common::DrawSystemState("CTR Console Backup",
renderSystem,
titleColor,
flip,
adapterState,
s_HwUtility.GetCupMajorVersion(),
s_HwUtility.GetCupMinorVersion(),
s_HwUtility.GetCupMicroVersion(),
s_HwUtility.GetNupVersion(),
s_HwUtility.GetBatteryRemain(),
s_HwUtility.GetInfraDeviceId(),
s_HwUtility.GetFriendcode(),
GetProgress(),
IsBackupFailed(),
IsBackupSucceeded(),
IsBackupWarning(),
s_HwUtility.GetMacAddress(),
operationMessage,
s_HwUtility.GetRegion(),
s_HwUtility.GetSerialNumber(),
s_HwUtility.HasReadFriendCode(),
s_HwUtility.IsWifiOn()
);
if (GetBackupMode() == BACKUP_MODE_DELETE_IF_FAILED)
{
const u8 spaceSize = 10;
const u8 lineBottom = 23;
const u32 screenWidth = 400;
renderSystem.SetColor(1.f, 1.f, 1.f);
renderSystem.DrawText(0, lineBottom * spaceSize, "Delete Error File Mode");
renderSystem.SetColor(titleColor.r, titleColor.g, titleColor.b);
renderSystem.FillRectangle(0, lineBottom * spaceSize, screenWidth, spaceSize);
renderSystem.SetColor(1.f, 1.f, 1.f);
}
renderSystem.SwapBuffers();
// デフォルトで下画面に描画するもの
renderSystem.SetRenderTarget(common::Util::GetRenderTarget(NN_GX_DISPLAY1, flip));
if(IsBackupSucceeded())
{
renderSystem.SetClearColor(common::Util::GetRenderTarget(NN_GX_DISPLAY1, flip), SUCCESS_COLOR);
}
if(IsBackupWarning())
{
renderSystem.SetClearColor(common::Util::GetRenderTarget(NN_GX_DISPLAY1, flip), WARN_COLOR);
}
else if(IsBackupFailed())
{
renderSystem.SetClearColor(common::Util::GetRenderTarget(NN_GX_DISPLAY1, flip), FAIL_COLOR);
}
renderSystem.Clear();
renderSystem.SetColor(1.f, 1.f, 1.f);
common::Logger::GetLoggerInstance()->DrawConsole();
renderSystem.SwapBuffers();
renderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
// 電源長押しで終了
if ( nn::applet::IsExpectedToCloseApplication())
{
common::Logger::GetLoggerInstance()->Finalize();
// アンマウント
nn::fs::Unmount(common::NAND_ARCHIVE_NAME);
nn::fs::Unmount(common::SDMC_ARCHIVE_NAME);
renderSystem.Finalize();
nn::ps::Finalize();
nn::ptm::CTR::FinalizeForSystemMenu();
nn::cfg::CTR::system::Finalize();
nn::cfg::CTR::init::Finalize();
nn::hid::Finalize();
nn::fs::Finalize();
nn::applet::PrepareToCloseApplication();
nn::applet::CloseApplication();
}
}
}
}

View File

@ -0,0 +1,43 @@
BasicInfo:
Title : ConsoleBackup
ProductCode: CTR-P-22TA
BackupMemoryType: None
TitleInfo:
Use: Evaluation
Category: Application
UniqueId: 0xf8021
Version: 0
SystemControlInfo:
AppType : Application
StackSize : 0x4000
Dependency :
- codec
- hid
- gsp
- nwm
AccessControlInfo:
Priority : 16
DisableDebug : true
FileSystemAccess:
- DirectSdmc
- Core
- CategoryFileSystemTool
- ExportImportIvs
IoAccessControl:
- FsMountNand
- FsMountTwln
Option:
FreeProductCode: true
CardInfo:
CardDevice: None
Rom:
# ROM に含めるファイルシステムのルートパスを指定します。
HostRoot: "$(ROMFS_ROOT)"

View File

@ -0,0 +1,516 @@
/*---------------------------------------------------------------------------*
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 <nn.h>
namespace ConsoleBackup
{
namespace
{
typedef enum BackupState
{
STARTUP, // 初期値
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 = 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)
{
// コンテキストを初期化する
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

View File

@ -0,0 +1,72 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: Contoroller.h
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$
*---------------------------------------------------------------------------*/
#ifndef CONTOROLLER_H_
#define CONTOROLLER_H_
#include <vector>
#include <string>
#include "HardwareStateManager.h"
#include "OperationMessage.h"
namespace ConsoleBackup
{
typedef enum BackupMode
{
BACKUP_MODE_CHECK, // セーブデータのチェック後エラーが無ければ吸出し
BACKUP_MODE_DELETE_IF_FAILED // 読み取りエラーのセーブデータを削除後吸出し
} BackupMode;
//! @brief 状態遷移を管理する
//! @param[in] manager ハードウェア情報を取得するためのラッパ
//! @param[in] operationMessage 操作情報として表示したい文字列
//! @param[in] nextStep 次の状態に遷移してもよいかどうか
//! @param[in] continueBackup 処理を続けてもよいかどうか
//! @param[in] forceDelete チェックエラー発生時に削除を実行してもよいかどうか
void ControlState(common::HardwareStateManager& manager, common::OperationMessage& operationMessage, bool& nextStep,
bool& continueBackup, bool forceDelete);
// バックアップ処理中かどうか
bool InProgress();
// バックアップが完了したかどうか
bool IsBackupSucceeded();
// バックアップが失敗したかどうか
bool IsBackupFailed();
// バックアップ時に警告があったかどうか
bool IsBackupWarning();
// SDカードが抜き出されたときに実行したい関数
void OnSdEjected();
// SDカードが挿し込まれたときに実行する処理
void OnSdInserted();
// 状態を初期化する
void InitializeState();
// 進捗を取得する
u32 GetProgress();
// バックアップモードを取得する
BackupMode GetBackupMode();
}
#endif /* CONTOROLLER_H_ */

View File

@ -0,0 +1,985 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: Exporter.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 <vector>
#include <cstdlib>
#include <cwchar>
#include <string>
#include <cstdlib>
#include <nn/nstd.h>
#include <nn/fs/CTR/fs_ArchiveTypesForSystem.h>
#include <nn/fs/CTR/MPCore/fs_FileSystemBasePrivate.h>
#include <nn/fs/fs_ApiDeviceMove.h>
#include <nn/cfg/CTR/cfg_Api.h>
#include <nn/cfg/CTR/cfg_ApiNor.h> // cfg:norの初期化に必要
#include <nn/cfg/CTR/cfg_NtrSettings.h>
#include <nn/ps/CTR/ps_API.h>
#include <nn/drivers/aes/CTR/ARM946ES/driverAes_Types.h>
#include <nn/crypto/crypto_AesCmac.h>
#include <nn/crypto/crypto_SwAesCtrContext.h>
#include <nn/crypto/crypto_Sha256.h>
#include <nn/crypto/crypto_SwAesCmac.h>
#include <nn/mcu.h>
#include <nn/am.h>
#include <nn/pl/CTR/pl_PlayHistoryApi.h>
#include <nn/pl/CTR/pl_PlayHistoryApiSysmenu.h>
#include <nn/nim.h>
#include "Exporter.h"
#include "CommonLogger.h"
#include "SDMountManager.h"
#include "HeapManager.h"
#include "SdReaderWriter.h"
#include "FileName.h"
#include "FileTransfer.h"
#include "common_Types.h"
#include "Aes_define.h"
#include "VersionDetect.h"
#include "Util.h"
#include "SaveDataMover.h"
namespace ConsoleBackup
{
namespace
{
common::NtrNorData s_NtrNorData;
common::CfgCountryLanguage s_CountryLanguage;
const size_t EXPORT_THREAD_STACK_SIZE = 0x4000;
nn::os::Thread s_ExportThread;
nn::os::StackBuffer<EXPORT_THREAD_STACK_SIZE> s_ExportThreadStack;
bool s_IsExportSucceeded;
wchar_t s_RootName[256];
nn::crypto::Sha256Context s_FileListContext;
u64 s_ExportProgress = 0;
}
bool AddCmac(nn::fs::FileOutputStream* file, nn::crypto::Sha256Context* context);
nn::Result DeleteTrash(std::wstring currentDirectory)
{
// TODO: リードオンリーのファイルが消去できない
COMMON_LOGGER("Delete Trash.\n");
nn::fs::FileInputStream fis;
nn::fs::Directory dir;
nn::Result result;
std::vector<nn::fs::DirectoryEntry> entryList; //カレントディレクトリのエントリ一覧を格納
std::vector<nn::fs::DirectoryEntry>::iterator entryIndex;
result = common::SdMountManager::Mount();
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
result = dir.TryInitialize(currentDirectory.c_str());
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
nn::fs::DirectoryEntry entry;
s32 numEntry;
for (;;)
{
result = dir.TryRead(&numEntry, &entry, 1);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
if (numEntry == 0)
{
// ルートディレクトリを閉じる
dir.Finalize();
// ルートディレクトリの子を開く
for (entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++)
{
// ディレクトリなら削除する
if (entryIndex->attributes.isDirectory)
{
NN_LOG("Try Delete %ls%ls/\n", currentDirectory.c_str(), entryIndex->entryName);
result = nn::fs::TryDeleteDirectoryRecursively(
(currentDirectory + ::std::wstring(entryIndex->entryName)).c_str());
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
}
// ファイルならログとAP設定以外は削除する
else
{
if (std::wcscmp(entryIndex->entryName, common::AP_SETTING_FILENAME) != 0
&& std::wcscmp(entryIndex->entryName, common::LOG_FILENAME) != 0)
{
NN_LOG("Try Delete %ls%ls\n", currentDirectory.c_str(), entryIndex->entryName);
result = nn::fs::TryDeleteFile(
(currentDirectory + ::std::wstring(entryIndex->entryName)).c_str());
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
}
}
}
// 削除完了
break;
}
else
{
// vectorに保存する
entryList.push_back(entry);
if (entry.attributes.isDirectory)
{
NN_LOG("%ls%ls/\n", currentDirectory.c_str(), entry.entryName);
}
else
{
NN_LOG("%ls%ls\n", currentDirectory.c_str(), entry.entryName);
}
}
}
result = common::SdMountManager::Unmount();
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
return nn::ResultSuccess();
}
nn::Result WriteTwlTitleList(std::vector<std::wstring>& programIdList)
{
nn::Result result;
COMMON_LOGGER("Export TwlTitle List.\n");
size_t heapSize = common::GetAllocatableSize();
if(heapSize > common::FILE_COPY_HEAP_SIZE)
{
heapSize = common::FILE_COPY_HEAP_SIZE;
}
common::HeapManager manager(heapSize);
char* titleListBuf = reinterpret_cast<char*> (manager.GetAddr());
size_t writeSize = 0;
if (titleListBuf != NULL)
{
for (std::vector<std::wstring>::iterator it = programIdList.begin(); it != programIdList.end(); it++)
{
nn::nstd::TSNPrintf(titleListBuf + writeSize, heapSize - writeSize, "%s\n", common::GetCharStr(it->c_str()));
NN_LOG("%ls\n", it->c_str());
writeSize += it->size() + sizeof('\n');
}
common::SdReaderWriter sdWriter;
return sdWriter.WriteBufWithCmac(common::TWL_TITLELIST_PATHNAME, titleListBuf, writeSize);
}
else
{
return nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON,
nn::Result::DESCRIPTION_OUT_OF_MEMORY);
}
}
nn::Result WriteRegionData()
{
COMMON_LOGGER("Export Region Data.\n");
nn::cfg::CTR::CfgRegionCode region;
region = nn::cfg::CTR::GetRegion();
common::SdReaderWriter sdWriter;
return sdWriter.WriteBufWithCmac(common::REGION_DATA_PATHNAME, &region, sizeof(nn::cfg::CTR::CfgRegionCode));
}
nn::Result WriteCountryLanguageData()
{
COMMON_LOGGER("Export Country and Language Data.\n");
nn::Result result;
nn::cfg::nor::CTR::Initialize();
// 国設定
s_CountryLanguage.country = nn::cfg::CTR::GetCountry();
if (s_CountryLanguage.country != nn::cfg::CTR::CFG_COUNTRY_UNKNOWN)
{
// 言語設定
s_CountryLanguage.language = nn::cfg::CTR::GetLanguage();
common::SdReaderWriter sdWriter;
return sdWriter.WriteBufWithCmac(common::COUNTRY_SETTING_PATHNAME, &s_CountryLanguage, sizeof(s_CountryLanguage));
}
return nn::ResultSuccess();
}
nn::Result WriteNorData()
{
COMMON_LOGGER("Export NOR Data.\n");
nn::Result result;
nn::cfg::nor::CTR::Initialize();
NN_LOG("Get NTR User Setting\n");
// NTR設定
result = nn::cfg::nor::CTR::GetNtrSetting(&s_NtrNorData.ntrConfig.ncd, &s_NtrNorData.ntrConfig.ncd_ex);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
// TWL WiFi設定
result = nn::cfg::nor::CTR::ReadTwlWifiSetting(0, s_NtrNorData.TwlWiFiSetting, common::TWL_WIFI_SETTING_SIZE);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
// NTR WiFi設定
result = nn::cfg::nor::CTR::ReadNtrWifiSetting(0, s_NtrNorData.NtrWiFiSetting, common::NTR_WIFI_SETTING_SIZE);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
common::SdReaderWriter sdWriter;
return sdWriter.WriteBufWithCmac(common::NOR_PATHNAME, &s_NtrNorData, sizeof(common::NtrNorData));
}
nn::Result WriteSerialNumber(common::HardwareStateManager& manager)
{
COMMON_LOGGER("Export Serial Number.\n");
u8* serial;
size_t size;
manager.GetSerialNumber(&serial, &size);
common::SdReaderWriter sdWriter;
return sdWriter.WriteBufWithCmac(common::SERIAL_PATHNAME, serial, size);
}
nn::Result WriteDeviceId(common::HardwareStateManager& manager)
{
COMMON_LOGGER("Export Device ID.\n");
bit32 deviceId = manager.GetDeviceId();
common::SdReaderWriter sdWriter;
return sdWriter.WriteBufWithCmac(common::DEVICE_ID_PATHNAME, &deviceId, sizeof(deviceId));
}
nn::Result WriteIvs(common::HardwareStateManager& manager)
{
COMMON_LOGGER("Export SDCI.\n");
void* ivs;
size_t size;
manager.GetIvs(&ivs, &size);
void* enc;
nn::Result result;
common::HeapManager ivsHeap(size);
enc = ivsHeap.GetAddr();
if(enc != NULL)
{
// AES暗号化する
nn::crypto::SwAesCtrContext swAesCtrContest;
swAesCtrContest.Initialize(common::iv, common::key, sizeof(common::key));
swAesCtrContest.Encrypt(enc, ivs, size);
common::SdReaderWriter sdWriter;
return sdWriter.WriteBufWithCmac(common::IVS_PATHNAME, enc, size);
}
else
{
return nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON,
nn::Result::DESCRIPTION_OUT_OF_MEMORY);
}
}
void CreateTwlDirectory(enum common::TWL_PATH_INDEX path)
{
NN_ASSERT(path < common::TWL_PATHNAME_MAX);
common::SdReaderWriter sdWriter;
sdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) +
std::wstring(common::SD_TWL_ROOTNAME_TABLE[path])).c_str());
}
bool ListTwlSaveData(std::wstring currentDirectory, std::vector<common::SavePathInfo>* list)
{
nn::fs::Directory dir;
nn::fs::DirectoryEntry entry;
s32 numEntry;
nn::Result result = dir.TryInitialize(currentDirectory.c_str());
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
for (;;)
{
result = dir.TryRead(&numEntry, &entry, 1);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
if (numEntry == 0)
{
break;
}
else
{
common::SavePathInfo pathInfo;
pathInfo.name = currentDirectory + std::wstring(L"/") + std::wstring(entry.entryName);
pathInfo.isDirectory = false;
list->push_back(pathInfo);
}
}
return true;
}
void AddCurrentProgramIdPath(std::vector<std::wstring>* programIdList, std::wstring currentDir)
{
std::wstring currentPath(currentDir);
std::wstring token(common::NAND_TWL_DATA_ROOT_PATHNAME_WITHOUT_SLASH);
std::wstring::size_type pos;
pos = currentPath.find(token);
if(pos != std::wstring::npos)
{
std::wstring subStr = currentPath.substr(token.size());
std::wstring slash(L"/");
pos = subStr.find(slash);
while(pos != std::wstring::npos)
{
subStr.erase(pos, slash.size());
pos = subStr.find(slash);
}
std::wstring ctrProgramIdHi(L"00048");
subStr.replace(0, ctrProgramIdHi.size(), ctrProgramIdHi);
programIdList->push_back(subStr);
}
else
{
NN_LOG("Can't find %ls\n", common::NAND_TWL_DATA_ROOT_PATHNAME_WITHOUT_SLASH);
}
}
void AddCurrentDirectory(std::vector<common::SavePathInfo>* list, std::wstring currentDir, wchar_t* currentEntry)
{
common::SavePathInfo pathInfo;
pathInfo.name = currentDir + std::wstring(L"/") + std::wstring(currentEntry) + std::wstring(L"/");
pathInfo.isDirectory = true;
list->push_back(pathInfo);
}
// TWLセーブデータが存在するディレクトリの一覧をlistに追加する
// return: dataディレクトリが存在するかどうか
bool ListTwlSaveDataDirectory(std::wstring currentDirectory, u32 level, std::vector<common::SavePathInfo>* list,
std::vector<std::wstring>* programIdList)
{
nn::fs::FileInputStream fis;
nn::fs::Directory dir;
nn::Result result;
std::vector<nn::fs::DirectoryEntry> entryList; //カレントディレクトリのエントリ一覧を格納
std::vector<nn::fs::DirectoryEntry>::iterator entryIndex;
// level 0 1 2
// twln:/title/00030005/484e4441/data/
const u8 TWL_SAVEDATA_DIRECTORY_LEVEL = 2; // data ディレクトリまでの階層
const wchar_t* const TWL_SAVEDATA_DIRECTORY_NAME = L"data";
result = dir.TryInitialize(currentDirectory.c_str());
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
nn::fs::DirectoryEntry entry;
s32 numEntry;
for (;;)
{
result = dir.TryRead(&numEntry, &entry, 1);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
if (numEntry == 0)
{
dir.Finalize();
bool hasDataDirectory = false;
for (entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++)
{
// レベル2未満のディレクトリなら再帰的に開く
if (level < TWL_SAVEDATA_DIRECTORY_LEVEL)
{
if (entryIndex->attributes.isDirectory)
{
if (!ListTwlSaveDataDirectory(
currentDirectory + std::wstring(L"/") + std::wstring(entryIndex->entryName), level + 1,
list, programIdList))
{
hasDataDirectory |= false;
}
else
{
NN_LOG("%ls/%ls has data directory.\n", currentDirectory.c_str(), entryIndex->entryName);
AddCurrentDirectory(list, currentDirectory, entryIndex->entryName);
hasDataDirectory |= true;
}
}
}
// レベル2のディレクトリなら data かどうかチェック
else if (level == TWL_SAVEDATA_DIRECTORY_LEVEL && entryIndex->attributes.isDirectory)
{
if (std::wcscmp(entryIndex->entryName, TWL_SAVEDATA_DIRECTORY_NAME) == 0)
{
// ファイル一覧を取得する
if (!ListTwlSaveData(
currentDirectory + std::wstring(L"/") + std::wstring(entryIndex->entryName), list))
{
hasDataDirectory |= false;
}
NN_LOG("%ls/%ls has data directory.\n", currentDirectory.c_str(), entryIndex->entryName);
AddCurrentDirectory(list, currentDirectory, entryIndex->entryName);
AddCurrentProgramIdPath(programIdList, currentDirectory);
hasDataDirectory |= true;
}
}
else
{
return false;
}
}
return hasDataDirectory;
}
else
{
// vectorに保存する
entryList.push_back(entry);
}
}
}
void WriteTwlData(enum common::TWL_PATH_INDEX path)
{
NN_ASSERT(path < common::TWL_PATHNAME_MAX);
nn::Result result;
s_IsExportSucceeded = true;
result = nn::fs::MountSpecialArchive(common::TWL_ARCHIVE_NAME_TABLE[path], common::TWL_FS_ARCHIVE_KIND[path]);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
result = common::SdMountManager::Mount();
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
u32 fileNum = 0;
s64 fileSize = 0;
result = common::CalculateFileNum(::std::wstring(common::NAND_TWL_ROOT_PATHNAME_WITH_SLASH_TABLE[path]), fileNum, fileSize);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
nn::fs::Unmount(common::NAND_ARCHIVE_NAME);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
NN_LOG("File Number = %d\n", fileNum);
NN_LOG("File Size = %lld\n", fileSize);
// 進捗表示用
common::InitializeTransferProgress(fileSize);
size_t bufSize = common::GetAllocatableSize(AES_BLOCK_SIZE * 2);
NN_LOG("AllocatableSize = %d\n", bufSize);
if(bufSize > common::FILE_COPY_HEAP_SIZE)
{
bufSize = common::FILE_COPY_HEAP_SIZE;
}
common::HeapManager writeHeap(bufSize, AES_BLOCK_SIZE * 2);
void* buf = writeHeap.GetAddr();
if (buf != NULL)
{
nn::fs::FileOutputStream list;
result = list.TryInitialize(common::FILE_LIST_PATHNAME, true);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
result = list.TryGetSize(&fileSize);
if (result.IsSuccess())
{
// 末尾に移動
result = list.TrySetPosition(fileSize);
if (result.IsSuccess())
{
wchar_t archiveName[nn::fs::MAX_FILE_PATH_LENGTH];
::std::mbstowcs(archiveName, common::TWL_ARCHIVE_NAME_TABLE[path],
std::strlen(common::TWL_ARCHIVE_NAME_TABLE[path]) + 1);
std::wstring archiveString(archiveName);
if (!common::CopyDirectory(
NULL,
(archiveString + ::std::wstring(L"/")).c_str(),
(common::SDMC_ROOT_DIRECTORY_PATH + ::std::wstring(common::SD_TWL_ROOTNAME_TABLE[path])).c_str(),
buf, bufSize, true, &list, &s_FileListContext))
{
s_IsExportSucceeded = false;
return;
}
}
list.TryFlush();
list.Finalize();
}
}
common::SdMountManager::Unmount();
nn::fs::Unmount(common::TWL_ARCHIVE_NAME_TABLE[path]);
}
nn::Result CalculateTwlSaveData(std::vector<common::SavePathInfo>* fileList, s64* fileSize)
{
NN_NULL_ASSERT(fileList);
NN_NULL_ASSERT(fileSize);
*fileSize = 0;
nn::Result result = nn::ResultSuccess();
for (std::vector<common::SavePathInfo>::iterator it = fileList->begin(); it != fileList->end(); it++)
{
if(!it->isDirectory)
{
nn::fs::FileInputStream file;
result = file.TryInitialize(it->name.c_str());
if(result.IsSuccess())
{
s64 size;
result = file.TryGetSize(&size);
if(result.IsSuccess())
{
*fileSize += size;
}
}
}
}
return result;
}
void WriteTwlSaveData()
{
nn::Result result;
s_IsExportSucceeded = true;
std::vector<common::SavePathInfo> fileList;
std::vector<std::wstring> programIdList;
COMMON_LOGGER("Export Twl Save Data.\n");
// ディレクトリ作成
common::SdReaderWriter sdWriter;
result = sdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) +
std::wstring(common::SD_SAVEDATA_TWL_ROOT_NAME)).c_str());
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
// セーブデータを含むディレクトリ一覧を生成
result = nn::fs::MountSpecialArchive(common::NAND_TWL_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_TWL_NAND);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
if(!ListTwlSaveDataDirectory(std::wstring(common::NAND_TWL_DATA_ROOT_PATHNAME_WITHOUT_SLASH), 0, &fileList, & programIdList))
{
NN_LOG("No Twl Savedata\n");
s_IsExportSucceeded = true;
return;
}
NN_LOG("listup Twl Savedata Directory\n");
for (std::vector<common::SavePathInfo>::reverse_iterator it = fileList.rbegin(); it != fileList.rend(); it++)
{
NN_LOG("%ls\n", it->name.c_str());
}
result = WriteTwlTitleList(programIdList);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
// 合計サイズ取得
s64 fileSize;
result = CalculateTwlSaveData(&fileList, &fileSize);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
common::InitializeTransferProgress(fileSize);
NN_LOG("\n");
// SDに書き出し
result = common::SdMountManager::Mount();
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
size_t bufSize = common::GetAllocatableSize(AES_BLOCK_SIZE * 2);
NN_LOG("AllocatableSize = %d\n", bufSize);
if(bufSize > common::FILE_COPY_HEAP_SIZE)
{
bufSize = common::FILE_COPY_HEAP_SIZE;
}
common::HeapManager writeHeap(bufSize, AES_BLOCK_SIZE * 2);
void* buf = writeHeap.GetAddr();
if (buf != NULL)
{
nn::fs::FileOutputStream list;
result = list.TryInitialize(common::FILE_LIST_PATHNAME, true);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
result = list.TryGetSize(&fileSize);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
// 末尾に移動
result = list.TrySetPosition(fileSize);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
wchar_t archiveName[nn::fs::MAX_FILE_PATH_LENGTH];
::std::mbstowcs(archiveName, common::NAND_TWL_ARCHIVE_NAME, std::strlen(common::NAND_TWL_ARCHIVE_NAME) + 1);
std::wstring archiveString(archiveName);
for (std::vector<common::SavePathInfo>::reverse_iterator it = fileList.rbegin(); it != fileList.rend(); it++)
{
// twln:/title/をsdmc:/CTR_Console_Repair/TWLBackup/に置換
std::wstring toPath(it->name.c_str());
toPath.replace(0, std::wcslen(common::NAND_TWL_DATA_ROOT_PATHNAME_WITHOUT_SLASH) + 1,
std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + std::wstring(common::SD_SAVEDATA_TWL_ROOT_NAME));
if (it->isDirectory)
{
if(!common::ExportTwlSaveDirectory(toPath.c_str(), &list, &s_FileListContext))
{
s_IsExportSucceeded = false;
return;
}
}
else
{
if(!common::ExportTwlSaveFile(it->name.c_str(), toPath.c_str(), buf, bufSize, &list, &s_FileListContext))
{
s_IsExportSucceeded = false;
return;
}
}
}
result = list.TryFlush();
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
list.Finalize();
}
result = common::SdMountManager::Unmount();
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
result = nn::fs::Unmount(common::NAND_TWL_ARCHIVE_NAME);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded);
}
void WriteTwlPhotoData()
{
COMMON_LOGGER("Export Twl Photo Data.\n");
CreateTwlDirectory(common::TWL_PHOTO);
WriteTwlData(common::TWL_PHOTO);
}
void WriteTwlSoundData()
{
COMMON_LOGGER("Export Twl Sound Data.\n");
CreateTwlDirectory(common::TWL_SOUND);
WriteTwlData(common::TWL_SOUND);
}
void InitializeFileListContext()
{
s_FileListContext.Initialize();
}
nn::Result ExportTwlSaveData()
{
// 不要なデータを削除する
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(
DeleteTrash((std::wstring(common::LOG_ROOT_DIRECTORY_PATH) + std::wstring(L"/")).c_str()));
s_ExportThread.Start(WriteTwlSaveData, s_ExportThreadStack);
return nn::ResultSuccess();
}
void ExportTwlPhotoData()
{
s_ExportThread.Start(WriteTwlPhotoData, s_ExportThreadStack);
}
void ExportTwlSoundData()
{
s_ExportThread.Start(WriteTwlSoundData, s_ExportThreadStack);
}
nn::Result WriteMcuRtcData(common::HardwareStateManager& manager)
{
COMMON_LOGGER("Export RTC Data.\n");
nn::Result result;
nn::Handle handle = manager.GetMcuHandle();
if(handle.IsValid())
{
nn::mcu::CTR::HwCheck mcu(handle);
nn::mcu::CTR::RtcData rtc;
const u8 RETRY = 10;
for (u8 i = 0; i < RETRY; i++)
{
result = mcu.GetRtcAll(&rtc);
if (result.IsSuccess())
{
NN_LOG("RTC = 20%02d/%02d/%02d %02d:%02d:%02d\n", rtc.m_Year, rtc.m_Month, rtc.m_Day, rtc.m_Hour, rtc.m_Minute, rtc.m_Second);
common::SdReaderWriter sdWriter;
return sdWriter.WriteBufWithCmac(common::MCU_RTC_PATHNAME, &rtc, sizeof(rtc));
}
nn::os::Thread::Sleep(
nn::fnd::TimeSpan::FromMilliSeconds(
nn::os::Tick::GetSystemCurrent().ToTimeSpan().GetMilliSeconds() % 100));
}
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
}
else
{
NN_LOG("invalid handle\n");
return nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_INVALID_STATE, nn::Result::MODULE_COMMON,
nn::Result::DESCRIPTION_INVALID_HANDLE);
}
return nn::ResultSuccess();
}
bool AddCmactoExportFileList()
{
nn::Result result;
nn::fs::FileOutputStream list;
result = list.TryInitialize(common::FILE_LIST_PATHNAME, true);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
s64 fileSize = 0;
result = list.TryGetSize(&fileSize);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
// 末尾に移動
result = list.TrySetPosition(fileSize);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
return AddCmac(&list, &s_FileListContext);
}
void ExportThreadFunc()
{
nn::Result result;
s_IsExportSucceeded = true;
result = common::SdMountManager::Mount();
size_t bufSize = common::GetAllocatableSize(AES_BLOCK_SIZE * 2);
NN_LOG("AllocatableSize = %d\n", bufSize);
if(bufSize > common::FILE_COPY_HEAP_SIZE)
{
bufSize = common::FILE_COPY_HEAP_SIZE;
}
common::HeapManager writeHeap(bufSize, AES_BLOCK_SIZE * 2);
void* buf = writeHeap.GetAddr();
if (buf != NULL)
{
common::SaveDataMover saveDataMover;
saveDataMover.StartExport(buf, bufSize, &s_ExportProgress);
COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(
saveDataMover.GetLastResult(), s_IsExportSucceeded
);
}
// FileListにCMACを付加する
if(!AddCmactoExportFileList())
{
s_IsExportSucceeded = false;
}
common::SdMountManager::Unmount();
NN_LOG("Export Thread Finalize\n");
}
nn::Result WriteSaveData()
{
// NANDからSDカードに書き出し
nn::Result result;
// セーブデータディレクトリ以下のデータをSDカードにコピー
// コピー用ディレクトリ作成
common::SdReaderWriter sdWriter;
result = sdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(
common::SD_SAVEDATA_ROOT_NAME)).c_str());
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
COMMON_LOGGER("Export NAND Data Start...\n");
// SDにコピーするためのスレッドの作成
s_ExportThread.Start(ExportThreadFunc, s_ExportThreadStack);
return result;
}
void FinalizeExportThread()
{
s_ExportThread.Join();
s_ExportThread.Finalize();
}
nn::Result WriteVersionData(common::HardwareStateManager& manager)
{
COMMON_LOGGER("Export Version Data.\n");
common::VerDef versionData;
manager.GetVersionData(&versionData);
common::SdReaderWriter sdWriter;
return sdWriter.WriteBufWithCmac(common::VERSION_DATA_PATHNAME, &versionData, sizeof(common::VerDef));
}
nn::Result DeleteNimSystemSaveData()
{
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(
nn::nim::InitializeForUpdater());
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(
nn::nim::CTR::Updater::FormatSaveData());
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(
nn::nim::FinalizeForUpdater());
return nn::ResultSuccess();
}
bool DeleteNimSaveData()
{
nn::Result result;
::std::wstring nimSaveDataPath =
::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) +
::std::wstring(common::SD_SAVEDATA_ROOT_NAME) +
::std::wstring(s_RootName) +
::std::wstring(L"/") +
std::wstring(common::NIM_SAVEDATA_DIRECTORY_NAME);
result = common::SdMountManager::Mount();
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
NN_LOG("%ls\n", nimSaveDataPath.c_str());
result = nn::fs::TryDeleteDirectoryRecursively(nimSaveDataPath.c_str());
if (result.IsFailure() && !nn::fs::ResultNotFound::Includes(result))
{
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
}
result = common::SdMountManager::Unmount();
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(
DeleteNimSystemSaveData());
return true;
}
void AddShutDownPtmEvent()
{
nn::pl::CTR::NotifyPlayEvent(nn::pl::CTR::EVENTTYPE_TERMINATE, nn::CTR::INVALID_PROGRAM_ID,
nn::fnd::DateTime::GetNow());
}
bool ExportData(common::HardwareStateManager& manager)
{
static bool init = true;
if (init)
{
nn::Result result;
// 電源断の履歴をptmに追加する
AddShutDownPtmEvent();
// リージョンデータをSDに書き込む
result = WriteRegionData();
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
// 国データと言語データをSDに書き込む
result = WriteCountryLanguageData();
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
// NORデータをSDカードに書き込む
result = WriteNorData();
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
// シリアルナンバーをSDカードに書き込む
result = WriteSerialNumber(manager);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
// デバイスIDをSDカードに書き込む
result = WriteDeviceId(manager);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
// 完全性検証SEEDをSDカードに書き込む
result = WriteIvs(manager);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
// RTCをSDに書き出す
result = WriteMcuRtcData(manager);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
// バージョン情報をSDに書き出す
result = WriteVersionData(manager);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
// NANDのセーブデータをSDに書き出す
result = WriteSaveData();
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
init = false;
}
return true;
}
u32 GetExportProgress()
{
return s_ExportProgress;
}
bool IsExportThreadFinished()
{
return s_ExportThread.IsValid() && !s_ExportThread.IsAlive();
}
bool IsExportSucceeded()
{
return s_IsExportSucceeded;
}
//!@ brief ファイルにSHA256から計算したAES-CMACを付加します
//!@ param[in] file CMACを付加したいInitialize済みのファイル
//!@ param[in] context CMAC計算元のSHA256コンテキスト
bool AddCmac(nn::fs::FileOutputStream* file, nn::crypto::Sha256Context* context)
{
nn::Result result;
bit8 sha256Hash[nn::crypto::Sha256Context::HASH_SIZE];
context->GetHash(sha256Hash);
bit8 cmac[nn::crypto::AES_CMAC_MAC_SIZE];
result = nn::crypto::CalculateAesCmacSw(cmac, sha256Hash, nn::crypto::Sha256Context::HASH_SIZE, common::cmacKey);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
s32 writeSize;
result = file->TryWrite(&writeSize, cmac, sizeof(cmac), false);
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
result = file->TryFlush();
COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result);
return true;
}
}

View File

@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: Exporter.h
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$
*---------------------------------------------------------------------------*/
#ifndef EXPORTER_H_
#define EXPORTER_H_
#include <nn.h>
#include "HardwareStateManager.h"
namespace ConsoleBackup
{
// 出力ファイルリストのコンテキストを初期化する。出力ファイルリストを
// 生成する前に必ず呼び出す必要がある
void InitializeFileListContext();
// 新たにスレッドを起動して、DSiWareのセーブデータをSDカードに出力する
nn::Result ExportTwlSaveData();
// 新たにスレッドを起動して、TWL写真領域のデータをSDカードに出力する
void ExportTwlPhotoData();
// 新たにスレッドを起動して、TWLサウンド領域のデータをSDカードに出力する
void ExportTwlSoundData();
// 本体固有情報をSDカードに出力する
// 新たにスレッドを起動して、CTR領域のセーブデータをSDカードに出力する
bool ExportData(common::HardwareStateManager& manager);
// NIMのセーブデータをSDカードから削除する
bool DeleteNimSaveData();
// 出力スレッドの進捗を返す
u32 GetExportProgress();
// 出力スレッドが終了したかどうか
bool IsExportThreadFinished();
// 出力スレッドを終了する
void FinalizeExportThread();
// 出力が成功したかどうか
bool IsExportSucceeded();
}
#endif /* EXPORTER_H_ */

View File

@ -0,0 +1,78 @@
#!/usr/bin/env omake
#----------------------------------------------------------------------------
# Project: Horizon
# File: OMakefile
#
# 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$
#----------------------------------------------------------------------------
SUPPORTED_TARGETS = CTR-T*.Process.MPCore.fast
CTR_APPTYPE = CARD
TARGET_PROGRAM = ConsoleBackup
SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include)
INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \
../common
SOURCES[] =
ConsoleBackup.cpp
Controller.cpp
Exporter.cpp
Checker.cpp
SavedataChecker.cpp
../common/Util.cpp
../common/DrawSystemState.cpp
../common/FileTransfer.cpp
../common/FileChecker.cpp
../common/SdReaderWriter.cpp
../common/HeapManager.cpp
../common/SdLogger.cpp
../common/wave.cpp
../common/SimplePlayer.cpp
../common/LogConsole.cpp
../common/CommonLogger.cpp
../common/SdMountManager.cpp
../common/VersionDetect.cpp
../common/ResFont.cpp
../common/HardwareStateManager.cpp
../common/SaveDataMover.cpp
../common/OperationMessage.cpp
include $(ROOT)/common/BuildSwitch.om
CTR_BANNER_SPEC = $(TARGET_NAME).bsf
ROMFS_ROOT = ../common/romfiles
SHADER_BIN = nnfont_RectDrawerShader.shbin
SHADER_PATH = $(ROMFS_ROOT)/$(SHADER_BIN)
ROMFS_DEPENDENCIES = $(SHADER_PATH)
LIBS += libnn_cfg \
libnn_crypto \
libnn_mcu \
libnn_i2c \
libnn_ps \
lib_demo \
libnn_nwm \
libnn_friends \
libnn_nim \
libnn_am \
INSTALL_SDK_TOOL = true
ROM_SPEC_FILE = $(TARGET_NAME).rsf
DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/private/RepairTool.desc
include $(ROOT_OMAKE)/modulerules
build: $(DEFAULT_TARGETS)

View File

@ -0,0 +1,490 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: NandSavedataChecker.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/fs/fs_ApiSysSaveData.h>
#include <nn/fs/fs_ApiSharedExtSaveData.h>
#include <nn/fs/fs_ResultPrivate.h>
#include "SavedataChecker.h"
#include "CommonLogger.h"
#include "FileTransfer.h"
#include "FileName.h"
namespace ConsoleBackup
{
SavedataCheckerBase::SavedataCheckerBase(void* buf, size_t size) :
m_Buf(buf), m_Bufsize(size), m_CalculatedFileSize(0), m_TotalReadSize(0), m_CheckErrorOccured(false)
{
}
SavedataCheckerBase::~SavedataCheckerBase()
{
NN_LOG("m_TotalReadSize = %lld\n", m_TotalReadSize);
}
nn::Result SavedataCheckerBase::CleanUpFilesRecursively(bool* metaDataCrashed, bool* modified, std::string baseName,
std::wstring currentDirectory, bool erase)
{
nn::fs::Directory dir;
nn::fs::DirectoryEntry entry;
nn::Result result;
NN_LOG("%s\n", common::GetCharStr(currentDirectory.c_str()));
result = dir.TryInitialize(currentDirectory.c_str());
if (result.IsFailure())
{
COMMON_LOGGER_WARN(
"Error: %s/%s\n", baseName.c_str(), common::GetCharStr(GetFilePathWithoutArchive(currentDirectory).c_str()));
m_CheckErrorOccured = true;
COMMON_LOGGER_RESULT_IF_FAILED(result);
if (erase)
{
*metaDataCrashed = true;
}
return result;
}
for (;;)
{
s32 numRead;
result = dir.TryRead(&numRead, &entry, 1);
if (result.IsFailure())
{
dir.Finalize();
COMMON_LOGGER_WARN(
"Error: %s/%s\n", baseName.c_str(), common::GetCharStr(GetFilePathWithoutArchive(currentDirectory).c_str()));
m_CheckErrorOccured = true;
COMMON_LOGGER_RESULT_IF_FAILED(result);
if (erase)
{
*metaDataCrashed = true;
}
// ディレクトリの読み取りエラーなので再度読み取ってもエラーになる
return result;
}
if(numRead == 0)
{
break;
}
if (std::wcscmp(entry.entryName, L".") == 0 || std::wcscmp(entry.entryName, L"..") == 0)
{
continue;
}
// ディレクトリの場合
if (entry.attributes.isDirectory)
{
result = CleanUpFilesRecursively(metaDataCrashed, modified, baseName,
currentDirectory + std::wstring(entry.entryName) + std::wstring(L"/"), erase);
if(erase && result.IsFailure())
{
return result;
}
}
// ファイルの場合
else
{
nn::fs::FileInputStream file;
std::wstring filePath = (currentDirectory + std::wstring(entry.entryName)).c_str();
const wchar_t* path = filePath.c_str();
NN_LOG("%s\n", common::GetCharStr(path));
result = file.TryInitialize(path);
if(result.IsFailure())
{
COMMON_LOGGER_RESULT_IF_FAILED(result);
const bool silent = IsForceDeleteFile(common::GetCharStr(entry.entryName));
if(!silent)
{
COMMON_LOGGER_WARN("Error: %s/%s\n", baseName.c_str(), common::GetCharStr(GetFilePathWithoutArchive(filePath).c_str()));
m_CheckErrorOccured = true;
COMMON_LOGGER_RESULT_IF_FAILED(result);
}
if (erase || silent)
{
if(!silent)
{
COMMON_LOGGER_WARN("Deleting: %s/%s\n", baseName.c_str(), common::GetCharStr(GetFilePathWithoutArchive(filePath).c_str()));
}
result = nn::fs::TryDeleteFile(path);
*modified = true;
}
continue;
}
for (;;)
{
s32 readSize;
result = file.TryRead(&readSize, m_Buf, m_Bufsize);
if(result.IsFailure())
{
COMMON_LOGGER_RESULT_IF_FAILED(result);
const bool silent = IsForceDeleteFile(common::GetCharStr(entry.entryName));
if(!silent)
{
COMMON_LOGGER_WARN("Error: %s/%s\n", baseName.c_str(), common::GetCharStr(GetFilePathWithoutArchive(filePath).c_str()));
m_CheckErrorOccured = true;
COMMON_LOGGER_RESULT_IF_FAILED(result);
}
m_TotalReadSize += file.GetSize();
file.Finalize();
if (erase || silent)
{
if(!silent)
{
COMMON_LOGGER_WARN("Deleting: %s/%s\n", baseName.c_str(), common::GetCharStr(GetFilePathWithoutArchive(filePath).c_str()));
}
result = nn::fs::TryDeleteFile(path);
COMMON_LOGGER_RESULT_IF_FAILED(result);
*modified = true;
}
break;
}
else
{
m_TotalReadSize += readSize;
}
if(readSize == 0)
{
break;
}
}
}
}
return nn::ResultSuccess();
}
nn::Result SavedataCheckerBase::GetFileSize(std::wstring currentDirectory)
{
return common::CalculateFileSizeRecursively(currentDirectory, m_CalculatedFileSize);
}
s64 SavedataCheckerBase::GetCalculatedSize()
{
return m_CalculatedFileSize;
}
s64 SavedataCheckerBase::GetTotalReadSize()
{
return m_TotalReadSize;
}
bool SavedataCheckerBase::GetCheckErrorOccured()
{
return m_CheckErrorOccured;
}
std::wstring SavedataCheckerBase::GetFilePathWithoutArchive(std::wstring path)
{
std::wstring::size_type pos = path.find(L":/");
if(pos != std::wstring::npos)
{
return path.substr(pos + sizeof(L""));
}
else
{
return path;
}
}
bool SavedataCheckerBase::IsForceDeleteFile(const char* name)
{
if((std::strcmp(common::BASHOTORYA_FILE_NAME, name) == 0) ||
(std::strcmp(common::BASHOTORYA2_FILE_NAME, name) == 0))
{
return true;
}
else
{
return false;
}
}
NandSavedataChecker::NandSavedataChecker()
{
// TODO 自動生成されたコンストラクター・スタブ
}
NandSavedataChecker::NandSavedataChecker(void* buf, size_t size) : m_Buf(buf), m_Bufsize(size)
{
m_pSharedExtSaveChecker = new SharedExtSavedataChecker(buf, size);
m_pSysSaveChecker = new SystemSavedataChecker(buf, size);
}
NandSavedataChecker::~NandSavedataChecker()
{
delete m_pSharedExtSaveChecker;
delete m_pSysSaveChecker;
}
nn::Result NandSavedataChecker::CleanUp(bool erase)
{
nn::Result result;
m_pSharedExtSaveChecker->CalculateFileSize();
m_pSysSaveChecker->CalculateFileSize();
result = m_pSharedExtSaveChecker->CleanUp(erase);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
result = m_pSysSaveChecker->CleanUp(erase);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
return nn::ResultSuccess();
}
s64 NandSavedataChecker::GetProgress()
{
if (m_pSharedExtSaveChecker->GetCalculatedSize() == 0 || m_pSysSaveChecker->GetCalculatedSize() == 0)
{
return 0;
}
else
{
return (m_pSharedExtSaveChecker->GetTotalReadSize() + m_pSysSaveChecker->GetTotalReadSize()) * 100
/ (m_pSharedExtSaveChecker->GetCalculatedSize() + m_pSysSaveChecker->GetCalculatedSize());
}
}
bool NandSavedataChecker::GetCheckErrorOccured()
{
return m_pSharedExtSaveChecker->GetCheckErrorOccured() || m_pSysSaveChecker->GetCheckErrorOccured();
}
SystemSavedataChecker::SystemSavedataChecker()
{
}
SystemSavedataChecker::SystemSavedataChecker(void* buf, size_t size) : SavedataCheckerBase(buf, size)
{
}
SystemSavedataChecker::~SystemSavedataChecker()
{
}
nn::Result SystemSavedataChecker::CleanUp(bool erase)
{
nn::Result result;
std::wstring currentDirectory;
for (s32 i = 0; i < SYSTEM_SAVE_DATA_NUM; i++)
{
bool metaDataCrashed = false;
bool modified = false;
// SPIDERのスキップ
if(SYSTEM_SAVEDATA_COUPLE_LIST[i].id == 0x00020088 ||
SYSTEM_SAVEDATA_COUPLE_LIST[i].id == 0x0002009d ||
SYSTEM_SAVEDATA_COUPLE_LIST[i].id == 0x00020094)
{
NN_LOG("Skip SPIDER\n");
continue;
}
result = nn::fs::MountSystemSaveData(SYSTEM_SAVEDATA_ARCHIVE_NAME, SYSTEM_SAVEDATA_COUPLE_LIST[i].id );
if (result.IsFailure())
{
if(result <= nn::fs::ResultVerificationFailed())
{
NN_LOG("Mount Error: %s\n", SYSTEM_SAVEDATA_COUPLE_LIST[i].name.c_str());
COMMON_LOGGER_WARN(
"Error: %s/\n", SYSTEM_SAVEDATA_COUPLE_LIST[i].name.c_str());
m_CheckErrorOccured = true;
COMMON_LOGGER_RESULT_IF_FAILED(result);
if (erase)
{
COMMON_LOGGER_WARN(
"Deleting: %s/\n", SYSTEM_SAVEDATA_COUPLE_LIST[i].name.c_str());
// 削除する
result = nn::fs::DeleteSystemSaveData(SYSTEM_SAVEDATA_COUPLE_LIST[i].id);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
}
}
}
else
{
NN_LOG("Mount %s\n", SYSTEM_SAVEDATA_COUPLE_LIST[i].name.c_str());
// ファイルを個別にチェックする
result = CleanUpFilesRecursively(&metaDataCrashed, &modified, SYSTEM_SAVEDATA_COUPLE_LIST[i].name.c_str(), L"ssave:/", erase);
// メタデータエラーの場合は一旦アンマウントしてからアーカイブごと削除
if (erase && metaDataCrashed)
{
// 削除する
COMMON_LOGGER_WARN( "Deleting: %s/\n", SYSTEM_SAVEDATA_COUPLE_LIST[i].name.c_str());
result = nn::fs::Unmount(SYSTEM_SAVEDATA_ARCHIVE_NAME);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
result = nn::fs::DeleteSystemSaveData(SYSTEM_SAVEDATA_COUPLE_LIST[i].id);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
continue;
}
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
if(modified)
{
result = nn::fs::CommitSystemSaveData(SYSTEM_SAVEDATA_ARCHIVE_NAME);
}
result = nn::fs::Unmount(SYSTEM_SAVEDATA_ARCHIVE_NAME);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
}
}
return nn::ResultSuccess();
}
nn::Result SystemSavedataChecker::CalculateFileSize()
{
nn::Result result;
for (s32 i = 0; i < SYSTEM_SAVE_DATA_NUM; i++)
{
result = nn::fs::MountSystemSaveData(SYSTEM_SAVEDATA_ARCHIVE_NAME, SYSTEM_SAVEDATA_COUPLE_LIST[i].id );
if (result.IsSuccess())
{
result = GetFileSize(L"ssave:/");
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
result = nn::fs::Unmount(SYSTEM_SAVEDATA_ARCHIVE_NAME);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
}
}
NN_LOG("CalculatedFileSize = %lld\n", m_CalculatedFileSize);
return result;
}
SharedExtSavedataChecker::SharedExtSavedataChecker()
{
}
SharedExtSavedataChecker::SharedExtSavedataChecker(void* buf, size_t size) : SavedataCheckerBase(buf, size)
{
}
SharedExtSavedataChecker::~SharedExtSavedataChecker()
{
}
nn::Result SharedExtSavedataChecker::CleanUp(bool erase)
{
nn::Result result;
const size_t ARRAY_SIZE = 256;
s32 numId;
bit32 IdArray[ARRAY_SIZE];
result = nn::fs::EnumerateSharedExtSaveData(&numId, IdArray, ARRAY_SIZE);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
NN_LOG_DEBUG("ExtData num = %d\n", numId);
for (s32 i = 0; i < numId; i++ )
{
bool metaDataCrashed = false;
bool modified = false;
char baseName[10];
nn::nstd::TSNPrintf(baseName, sizeof(baseName), "%X", IdArray[i]);
result = nn::fs::MountSharedExtSaveData(SHARED_EXT_SAVEDATA_ARCHIVE_NAME, IdArray[i]);
if (result.IsSuccess())
{
NN_LOG("Mount %x\n", IdArray[i]);
// アーカイブ内のファイル・ディレクトリをチェックする
result = CleanUpFilesRecursively(&metaDataCrashed, &modified, baseName, L"shext:/", erase);
// メタデータが壊れていた場合はアンマウントしてから削除する
if(erase && metaDataCrashed)
{
COMMON_LOGGER_WARN("Deleting %x/\n", IdArray[i]);
result = nn::fs::Unmount(SHARED_EXT_SAVEDATA_ARCHIVE_NAME);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
result = nn::fs::DeleteSharedExtSaveData(IdArray[i]);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
continue;
}
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
result = nn::fs::Unmount(SHARED_EXT_SAVEDATA_ARCHIVE_NAME);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
}
else
{
// アーカイブごと削除する
if(result <= nn::fs::ResultVerificationFailed() || result <= nn::fs::ResultDbmFileNotFound())
{
NN_LOG("Mount Error: %x\n", IdArray[i]);
COMMON_LOGGER_WARN("Error: %x/\n", IdArray[i]);
m_CheckErrorOccured = true;
COMMON_LOGGER_RESULT_IF_FAILED(result);
if (erase)
{
COMMON_LOGGER_WARN("Deleting %x/\n", IdArray[i]);
result = nn::fs::DeleteSharedExtSaveData(IdArray[i]);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
}
}
}
}
return nn::ResultSuccess();
}
nn::Result SharedExtSavedataChecker::CalculateFileSize()
{
nn::Result result;
const size_t ARRAY_SIZE = 256;
s32 numId;
bit32 IdArray[ARRAY_SIZE];
result = nn::fs::EnumerateSharedExtSaveData(&numId, IdArray, ARRAY_SIZE);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
NN_LOG_DEBUG("ExtData num = %d\n", numId);
for (s32 i = 0; i < numId; i++ )
{
result = nn::fs::MountSharedExtSaveData(SHARED_EXT_SAVEDATA_ARCHIVE_NAME, IdArray[i]);
if (result.IsSuccess())
{
result = GetFileSize(L"shext:/");
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
result = nn::fs::Unmount(SHARED_EXT_SAVEDATA_ARCHIVE_NAME);
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
}
}
NN_LOG("CalculatedFileSize = %lld\n", m_CalculatedFileSize);
return nn::ResultSuccess();
}
} /* namespace ConsoleBackup */

View File

@ -0,0 +1,237 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: NandSavedataChecker.h
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$
*---------------------------------------------------------------------------*/
#ifndef SAVEDATACHECKER_H_
#define SAVEDATACHECKER_H_
#include <string>
#include <nn.h>
#include <nn/fs/fs_ParametersForSystem.h>
namespace ConsoleBackup
{
struct SystemSaveDataCouple
{
std::string name;
nn::fs::SystemSaveDataId id;
};
const SystemSaveDataCouple SYSTEM_SAVEDATA_COUPLE_LIST[] =
{
{"fill_data", 0x00010000 },
{"cfg", 0x00010017 },
{"ptm", 0x00010022 },
{"cecd", 0x00010026 },
{"nim", 0x0001002C },
{"friends", 0x00010032 },
{"boss", 0x00010034 },
{"news", 0x00010035 },
{"ACTIVITY_LOG_JP", 0x00020202 },
{"ACTIVITY_LOG_US", 0x00020212 },
{"ACTIVITY_LOG_EU", 0x00020222 },
{"MII_MAKER_JP", 0x00020207 },
{"MII_MAKER_US", 0x00020217 },
{"MII_MAKER_EU", 0x00020227 },
{"PHOTO_JP", 0x00020204 },
{"PHOTO_US", 0x00020214 },
{"PHOTO_EU", 0x00020224 },
{"SOUND_JP", 0x00020205 },
{"SOUND_US", 0x00020215 },
{"SOUND_EU", 0x00020225 },
{"ESHOP_JP", 0x00020209 },
{"ESHOP_US", 0x00020219 },
{"ESHOP_EU", 0x00020229 },
{"ZONE_JP", 0x0002020b },
{"ZONE_US", 0x0002021b },
{"ZONE_EU", 0x0002022b },
{"MIGRATION_JP", 0x0002020a },
{"MIGRATION_US", 0x0002021a },
{"MIGRATION_EU", 0x0002022a },
{"DIARY_JP", 0x0002020c },
{"DIARY_US", 0x0002021c },
{"DIARY_EU", 0x0002022c },
{"MII_PLAZA_JP", 0x00020208 },
{"MII_PLAZA_US", 0x00020218 },
{"MII_PLAZA_EU", 0x00020228 },
{"ARGAMES_HAL_JP", 0x0002020d },
{"ARGAMES_HAL_US", 0x0002021d },
{"ARGAMES_HAL_EU", 0x0002022d },
{"ARGAMES_NCL_JP", 0x0002020e },
{"ARGAMES_NCL_US", 0x0002021e },
{"ARGAMES_NCL_EU", 0x0002022e },
{"MENU_JP", 0x00020081 },
{"MENU_US", 0x0002008f },
{"MENU_EU", 0x00020098 },
{"friend_JP", 0x0002008d },
{"friend_US", 0x00020096 },
{"friend_EU", 0x0002009f },
{"BROWSER_JP", 0x00020088 },
{"BROWSER_US", 0x0002009d },
{"BROWSER_EU", 0x00020094 },
{"ESPEC_JP", 0x00020086 },
{"ESPEC_US", 0x00020092 },
{"ESPEC_EU", 0x0002009b },
{"MEMO_JP", 0x00020087 },
{"MEMO_US", 0x00020093 },
{"MEMO_EU", 0x0002009c },
{"error", 0x000200c5 }
};
const char* const SYSTEM_SAVEDATA_ARCHIVE_NAME = "ssave:";
const char* const SHARED_EXT_SAVEDATA_ARCHIVE_NAME = "shext:";
const size_t SYSTEM_SAVE_DATA_NUM = sizeof(SYSTEM_SAVEDATA_COUPLE_LIST)/sizeof(SYSTEM_SAVEDATA_COUPLE_LIST[0]);
class SavedataCheckerBase
{
public:
SavedataCheckerBase() {}
SavedataCheckerBase(void* buf, size_t size);
~SavedataCheckerBase();
//! @brief セーブデータを調べて問題があるファイルを削除するインタフェース
//! @param[in] erase 問題があるファイルを削除するかどうか
virtual nn::Result CleanUp(bool erase) = 0;
//! @brief ファイルサイズをチェックするインタフェース
virtual nn::Result CalculateFileSize() = 0;
//! @return 事前に計算したサイズ
s64 GetCalculatedSize();
//! @return 読み取ったサイズ
s64 GetTotalReadSize();
//! @brief チェック時にエラーが起こったかどうか調べる
//! @return エラーが起こったかどうか
bool GetCheckErrorOccured();
protected:
//! @brief ファイルとディレクトリを再帰的にチェックする。エラーがあれば削除する
//! @param[out] metaDataCrashed メタデータが壊れていたかどうか。アーカイブごと削除するかどうかの判断に使用する
//! @param[out] modified ファイルかディレクトリを削除したかどうか。Commitするかどうかの判断に使用する
//! @param[in] baseName 削除するセーブデータの区別に表示するための名前
//! @param[in] currentDirectory チェックを開始するディレクトリ。スラッシュで終端すること
//! @param[in] erase ファイルかディレクトリを削除するかどうか
nn::Result CleanUpFilesRecursively(bool* metaDataCrashed, bool* modified, std::string baseName, std::wstring currentDirectory,
bool erase);
//! @brief ファイルサイズを取得する
//! @param[out] size ファイルサイズ
//! @param[in] currentDirectory チェックを開始するディレクトリ。スラッシュで終端すること。
nn::Result GetFileSize(std::wstring currentDirectory);
//! バッファ
void* m_Buf;
//! バッファサイズ
size_t m_Bufsize;
NN_PADDING4;
//! 事前読み取りサイズ
s64 m_CalculatedFileSize;
//! 累計読み取りサイズ
s64 m_TotalReadSize;
NN_PADDING3;
//! @brief チェック時にエラーが起こったかどうか
bool m_CheckErrorOccured;
NN_PADDING4;
private:
std::wstring GetFilePathWithoutArchive(std::wstring path);
bool IsForceDeleteFile(const char* name);
};
//! @brief システムセーブデータをチェックするためのクラス
class SystemSavedataChecker : public SavedataCheckerBase
{
public:
SystemSavedataChecker();
SystemSavedataChecker(void* buf, size_t size);
~SystemSavedataChecker();
//! @brief システムセーブデータを調べて問題があるファイルを削除する
//! @param[in] erase 問題があるファイルを削除するかどうか
virtual nn::Result CleanUp(bool erase);
//! @brief ファイルサイズをチェックする
virtual nn::Result CalculateFileSize();
};
//! @brief 共有拡張セーブデータをチェックするためのクラス
class SharedExtSavedataChecker : public SavedataCheckerBase
{
public:
SharedExtSavedataChecker();
SharedExtSavedataChecker(void* buf, size_t size);
~SharedExtSavedataChecker();
//! @brief 共有拡張セーブデータを調べて問題があるファイルを削除する
//! @param[in] erase 問題があるファイルを削除するかどうか
virtual nn::Result CleanUp(bool erase);
//! @brief ファイルサイズをチェックする
virtual nn::Result CalculateFileSize();
};
class NandSavedataChecker
{
public:
NandSavedataChecker();
NandSavedataChecker(void* buf, size_t size);
~NandSavedataChecker();
nn::Result CleanUp(bool erase);
s64 GetProgress();
bool GetCheckErrorOccured();
private:
SharedExtSavedataChecker* m_pSharedExtSaveChecker;
SystemSavedataChecker* m_pSysSaveChecker;
//! バッファ
void* m_Buf;
//! バッファサイズ
size_t m_Bufsize;
};
} /* namespace ConsoleBackup */
#endif /* SAVEDATACHECKER_H_ */

View File

@ -0,0 +1 @@
В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫фВ╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫ф8ф8фШчГГГГГГВВ╫8фВВВВВГГГГшчфГШФВ╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫фВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВ╫yнВ╫yнВВВВВ╫YнВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВГГГГШчyнYнВ╫шчшчВВфВВ╫шчyнШчВ╫yнГГГГyнШФГГГГГшчВВВВ╫YнГyнГВВВВВ╫yнфшчГШФГYнyнВВВ╫yнВ╫╨жВВВВВ╫yнВ╫yнВВВВВ╫YнВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВ╫yнГYнГВ╫В╫В╫В╫В╫фВ╫В╫ГyнГ8фВВВВфВ╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫

View File

@ -0,0 +1 @@
ВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВ╫YнВВВВВВВВВВВВВВВВВВВВВВВВВВВ╫8фВВ╫8ф8фВВВ╫╨ж8ф╨жГГшчГГГГГГГГГГГГГГГГГГГГГГГВВВВВВВВВВ╫8ф8фВВфВ╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫ГГГГГШФГГГГГГГГГГ жфГГВ╫В╫ жВ╫ГГГГГ жГГВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВ╫8фВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВ╫шчВ╫шчВВВВВГВ╫ШчВ╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫╨жВ╫В╫В╫В╫В╫В╫В╫В╫В╫В╫ГГГГГГГГГГГГГГГГГГШФ8фШчшчВВ жВ╫YнВВВВВГГYнyнГГyнфВ╫В╫В╫В╫В╫В╫В╫В╫фВ╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫шчшчГшчШФВ╫В╫ГГYнГВ╫В╫В╫В╫В╫шчВ╫шчГГГГГГГГГГГГГГГГВВ╫YнШч жГГГГГГГГГГГГГГГГГГГГГГГГшч╨жВ жВ╫шчВВВВВ╫ШФВ╫ШФВВВВВВВВВВВВВВВВВВВВВ╫шчВ╫yнВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВ╫YнВ жГГГГВ╫шчВ╫шчГГГГВВВВВВВВВВВВВВВВВ╫8фВВ╫╨жшчВВВВВ╫YнфyнГГГГГГГГГ жГГГГ╨жВ╫YнВ╫ШФYнВВВВВВВВВВВВВВ╫шч жВВВВВВ╫yнВГШФВ╫В╫фВ╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫В╫ШФВ╫ГГГГГВ╫ШчВ╫YнГГШФГВВВВВВВВВВВВВВВВВВВВВ╫8фВВВВВВВВВВГГГГ жВ╫шчВ╫ГГГшч жВВВВВВВВВВВВВВВВВВВ╫8фВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВ

View File

@ -0,0 +1,92 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: ActCompleter.cpp
Copyright (C)2013 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 "ActCompleter.h"
#include "Util.h"
#include "CommonLogger.h"
#include <nn/ac/CTR/private/ac_InternalApi.h>
#include <nn/act/act_ApiAdmin.h>
#include <nn/act/act_ApiTransfer.h>
#include <nn/act/act_ResultPrivate.h>
namespace ConsoleRestore
{
nn::Result ActCompleter::s_Result;
const size_t ActCompleter::STACK_SIZE;
nn::os::Thread ActCompleter::s_Thread;
nn::os::StackBuffer<ActCompleter::STACK_SIZE> ActCompleter::s_ThreadStack;
ActCompleter::ActCompleter()
{
// TODO 自動生成されたコンストラクター・スタブ
}
ActCompleter::~ActCompleter()
{
// TODO Auto-generated destructor stub
}
nn::Result ActCompleter::GetResult()
{
return s_Result;
}
void ActCompleter::Start()
{
s_Thread.Start(Exec, s_ThreadStack);
}
bool ActCompleter::IsFinished()
{
return s_Thread.IsValid() && !s_Thread.IsAlive();
}
void ActCompleter::Finish()
{
s_Thread.Join();
s_Thread.Finalize();
}
void ActCompleter::Exec()
{
s_Result = ExecImpl();
}
nn::Result ActCompleter::ExecImpl()
{
if(!nn::ac::IsConnected())
{
NN_UTIL_RETURN_IF_FAILED(
common::InitializeNetwork());
}
NN_UTIL_RETURN_IF_FAILED(
nn::act::InitializeAdmin());
NN_UTIL_RETURN_IF_FAILED(
nn::act::CompleteTransfer());
NN_UTIL_RETURN_IF_FAILED(
nn::act::FinalizeAdmin());
NN_UTIL_RETURN_IF_FAILED(
common::FinalizeNetwork());
return nn::ResultSuccess();
}
} /* namespace ConsoleRestore */

View File

@ -0,0 +1,46 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: ActCompleter.h
Copyright (C)2013 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$
*---------------------------------------------------------------------------*/
#ifndef ACTCOMPLETER_H_
#define ACTCOMPLETER_H_
#include <nn.h>
namespace ConsoleRestore
{
class ActCompleter
{
public:
ActCompleter();
virtual ~ActCompleter();
static nn::Result GetResult();
static void Start();
static bool IsFinished();
static void Finish();
private:
static void Exec();
static nn::Result ExecImpl();
static nn::Result s_Result;
static const size_t STACK_SIZE = 0x1000;
static nn::os::Thread s_Thread;
static nn::os::StackBuffer<STACK_SIZE> s_ThreadStack;
};
} /* namespace ConsoleRestore */
#endif /* ACTCOMPLETER_H_ */

View File

@ -0,0 +1,369 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: ConsoleRestore.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 <nn.h>
#include <nn/version.h>
#include <nn/ptm/CTR/ptm_ApiSysmenu.h>
#include <nn/mcu.h>
#include <nn/cfg/CTR/cfg_Api.h>
#include <nn/cfg/CTR/cfg_ApiInit.h>
#include <nn/cfg/CTR/cfg_ApiSys.h>
#include <nn/ps.h>
#include <nn/nwm.h>
#include <nn/ac.h>
#include <nn/fs/CTR/fs_ArchiveTypesForSystem.h>
#include <nn/fs/CTR/MPCore/fs_FileSystemBasePrivate.h>
#include <nn/fs/fs_ApiSysSaveData.h>
#include <nn/cfg/CTR/cfg_ApiNor.h>
#include <nn/am/am_ApiSystemMenu.h>
#include <nn/os/os_SharedInfo.h>
#include <nn/ndm.h>
#include <nn/nim.h>
#include <nn/am.h>
#include "demo.h"
#include <vector>
#include <string>
#include "DrawSystemState.h"
#include "Controller.h"
#include "SimplePlayer.h"
#include "CommonLogger.h"
#include "SDMountManager.h"
#include "HeapManager.h"
#include "VersionDetect.h"
#include "Util.h"
#include "ResFont.h"
#include "HardwareStateManager.h"
#include "OperationMessage.h"
#include "QrImage.h"
// バージョン表示用
#include "version.h"
namespace {
// グラフィックスに割り当てるメモリ
const size_t s_GxHeapSize = 0x800000;
common::Util s_HwUtility;
demo::RenderSystemDrawing s_RenderSystem;
} // namespace <unnamed>
namespace ConsoleRestore{
void FinalizeAll()
{
common::FinalizeSimplePlayer();
common::Logger::GetLoggerInstance()->Finalize();
// アンマウント
nn::fs::Unmount("nand:");
nn::fs::Unmount("sdmc:");
s_RenderSystem.Finalize();
s_HwUtility.FinalizeForRestore();
nn::ps::Finalize();
nn::ptm::CTR::FinalizeForSystemMenu();
nn::cfg::CTR::system::Finalize();
nn::cfg::CTR::init::Finalize();
nn::hid::Finalize();
nn::fs::Finalize();
nn::applet::PrepareToCloseApplication();
nn::applet::CloseApplication();
}
extern "C" void nnMain(void)
{
nn::Result result;
// fs の初期化
nn::fs::Initialize();
// appletの初期化
nn::applet::Enable( false );
// hid の初期化
result = nn::hid::Initialize();
NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result);
// ndmの初期化
result = nn::ndm::Initialize();
NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result);
// デーモンの自律動作を停止
result = nn::ndm::Suspend(nn::ndm::DN_CEC);
NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result);
result = nn::ndm::Suspend(nn::ndm::DN_BOSS);
NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result);
result = nn::ndm::Suspend(nn::ndm::DN_FRIENDS);
NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result);
result = nn::ndm::Suspend(nn::ndm::DN_NIM);
NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result);
// cfg の初期化
nn::cfg::CTR::init::Initialize();
nn::cfg::CTR::system::Initialize();
// 時計設定用ptm初期化
nn::ptm::CTR::InitializeForSystemMenu();
// ps の初期化
nn::ps::Initialize();
// amの初期化
nn::am::InitializeForLocalImporter();
// ヒープの確保
common::InitializeHeap();
// RenderSystem の準備
common::HeapManager gxHeap(s_GxHeapSize);
uptr heapForGx = reinterpret_cast<uptr>(gxHeap.GetAddr());
s_RenderSystem.Initialize(heapForGx, s_GxHeapSize);
// ResFontの初期化
common::InitializeResFont();
// サウンドスレッドの起動
common::InitializeSimplePlayer();
// ログ描画の初期化
common::Logger::GetLoggerInstance()->Initialize(common::CONSOLE_WIDTH, common::CONSOLE_HEIGHT,
common::CONSOLE_MAX_LINE, &s_RenderSystem);
// RenderSystemを作ってからログが出せる
common::Logger::InitializeEjectThread();
common::Logger::SetEjectHandler(OnSdEjected);
common::Logger::SetInsertHandler(OnSdInserted);
COMMON_LOGGER("\n");
COMMON_LOGGER("CTR Console Restore start\n");
// ボタン入力
nn::hid::PadReader s_PadReader;
nn::hid::PadStatus padStatus;
// データの準備
s_HwUtility.InitializeForRestore();
common::HardwareStateManager manager(s_HwUtility);
// 無線ON
s_HwUtility.SetWifiOn();
// 情報出力
COMMON_LOGGER("CTR Console Restore %s-%s-%s\n", CONSOLE_REPAIR_VERSION_MAJOR, CONSOLE_REPAIR_VERSION_MINOR, CONSOLE_REPAIR_VERSION_MICRO);
COMMON_LOGGER("System Ver. %d.%d.%d-%d\n", s_HwUtility.GetCupMajorVersion(),
s_HwUtility.GetCupMinorVersion(),
s_HwUtility.GetCupMicroVersion(),
s_HwUtility.GetNupVersion());
COMMON_LOGGER("System Region %s\n", s_HwUtility.GetRegionCodeA3());
COMMON_LOGGER("Serial Number %s\n", s_HwUtility.GetSerialNumber());
COMMON_LOGGER("Device ID %llu\n", s_HwUtility.GetInfraDeviceId());
COMMON_LOGGER("MAC Address %s\n", s_HwUtility.GetMacAddress());
COMMON_LOGGER("Friend Code %04u-%04u-%04u\n",
static_cast<u32>(s_HwUtility.GetFriendcode() / 100000000ULL % 10000ULL),
static_cast<u32>(s_HwUtility.GetFriendcode() / 10000ULL % 10000ULL),
static_cast<u32>(s_HwUtility.GetFriendcode() % 10000ULL) );
bool flip = false;
bool qr = false;
InitializeState();
for(;;)
{
bool nextStep = false;
bool operateBmsDone = false;
bool forcePreinstall = false;
bool unregister = false;
s_PadReader.ReadLatest(&padStatus);
// AまたはSTARTボタンで進行
if(padStatus.trigger & nn::hid::BUTTON_A ||
padStatus.trigger & nn::hid::BUTTON_START)
{
nextStep = true;
}
// YボタンでBMS操作完了
// Yボタンで強制プリインストール
if(padStatus.trigger & nn::hid::BUTTON_Y)
{
operateBmsDone = true;
forcePreinstall = true;
unregister = true;
}
// LまたはRボタンで上下画面フリップ
if(padStatus.trigger & nn::hid::BUTTON_R ||
padStatus.trigger & nn::hid::BUTTON_L)
{
flip = !flip;
}
// 左ボタンでQR切替
if(padStatus.trigger & nn::hid::BUTTON_RIGHT)
{
qr = !qr;
}
// コンソールスクロール
if(padStatus.hold & nn::hid::BUTTON_UP)
{
common::Logger::GetLoggerInstance()->ScrollUp();
}
// コンソールスクロール
if(padStatus.hold & nn::hid::BUTTON_DOWN)
{
common::Logger::GetLoggerInstance()->ScrollDown();
}
// 情報更新
// ACアダプタ
std::string adapterState;
if(manager.IsAdapterConnected())
{
adapterState += ::std::string("Connected");
}
else
{
adapterState += ::std::string("Not Connected");
}
// 操作用メッセージ
// 進捗確認メッセージを兼ねる?
common::OperationMessage operationMessage;
if(qr)
{
u8 serial[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN];
s_HwUtility.GetSerialNumberWithoutCD(serial);
common::QrImage::Draw(s_RenderSystem, s_HwUtility.GetInfraDeviceId(), serial, flip);
}
else
{
ControlState(manager, operationMessage, nextStep, operateBmsDone, forcePreinstall, unregister);
nn::util::FloatColor titleColor;
if (GetRestoreMode() == RESTORE_MODE_RESTORE)
{
titleColor.r = 0.1f;
titleColor.g = 0.25f;
titleColor.b = 0.1f;
}
else if (GetRestoreMode() == RESTORE_MODE_NUP_ONLY)
{
titleColor.r = 0.35f;
titleColor.g = 0.35f;
titleColor.b = 0.f;
}
else if (GetRestoreMode() == RESTORE_MODE_GET_IVS)
{
titleColor.r = 1.0f;
titleColor.g = 0.2f;
titleColor.b = 0.2f;
}
else if (GetRestoreMode() == RESTORE_MODE_CHECK_SD)
{
titleColor.r = 0.2f;
titleColor.g = 0.2f;
titleColor.b = 1.2f;
}
else if (GetRestoreMode() == RESTORE_MODE_DOWNLOAD_PREINSTALL)
{
titleColor.r = 1.0f;
titleColor.g = 0.55f;
titleColor.b = 1.0f;
}
// 上画面表示
common::DrawSystemState("CTR Console Restore", s_RenderSystem, titleColor, flip, adapterState,
s_HwUtility.GetCupMajorVersion(), s_HwUtility.GetCupMinorVersion(),
s_HwUtility.GetCupMicroVersion(), s_HwUtility.GetNupVersion(), s_HwUtility.GetBatteryRemain(),
s_HwUtility.GetInfraDeviceId(), s_HwUtility.GetFriendcode(), GetProgress(), IsRestoreFailed(),
IsRestoreSucceeded(), false, s_HwUtility.GetMacAddress(), operationMessage, s_HwUtility.GetRegion(),
s_HwUtility.GetSerialNumber(), s_HwUtility.HasReadFriendCode(), s_HwUtility.IsWifiOn());
if (GetRestoreMode() != RESTORE_MODE_RESTORE)
{
const u8 spaceSize = 10;
const u8 lineBottom = 23;
const u32 screenWidth = 400;
s_RenderSystem.SetColor(1.f, 1.f, 1.f);
if (GetRestoreMode() == RESTORE_MODE_NUP_ONLY)
{
s_RenderSystem.DrawText(0, lineBottom * spaceSize, "NUP-Only Mode");
}
else if (GetRestoreMode() == RESTORE_MODE_GET_IVS)
{
s_RenderSystem.DrawText(0, lineBottom * spaceSize, "GET-SDCI Mode");
}
else if (GetRestoreMode() == RESTORE_MODE_CHECK_SD)
{
s_RenderSystem.DrawText(0, lineBottom * spaceSize, "CHECK-SD Mode");
}
else if (GetRestoreMode() == RESTORE_MODE_DOWNLOAD_PREINSTALL)
{
s_RenderSystem.DrawText(0, lineBottom * spaceSize, "DL_PREINATALL Mode");
}
s_RenderSystem.SetColor(titleColor.r, titleColor.g, titleColor.b);
s_RenderSystem.FillRectangle(0, lineBottom * spaceSize, screenWidth, spaceSize);
s_RenderSystem.SetColor(1.f, 1.f, 1.f);
}
s_RenderSystem.SwapBuffers();
// デフォルトで下画面に描画するもの
s_RenderSystem.SetRenderTarget(common::Util::GetRenderTarget(NN_GX_DISPLAY1, flip));
if (IsRestoreSucceeded())
{
s_RenderSystem.SetClearColor(common::Util::GetRenderTarget(NN_GX_DISPLAY1, flip), SUCCESS_COLOR);
}
else if (IsRestoreFailed())
{
s_RenderSystem.SetClearColor(common::Util::GetRenderTarget(NN_GX_DISPLAY1, flip), FAIL_COLOR);
}
else
{
s_RenderSystem.SetClearColor(common::Util::GetRenderTarget(NN_GX_DISPLAY1, flip), NORMAL_COLOR);
}
s_RenderSystem.Clear();
s_RenderSystem.SetColor(1.f, 1.f, 1.f);
common::Logger::GetLoggerInstance()->DrawConsole();
s_RenderSystem.SwapBuffers();
}
s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
// 電源長押しで終了
if ( nn::applet::IsExpectedToCloseApplication())
{
FinalizeAll();
}
}
}
}

View File

@ -0,0 +1,46 @@
BasicInfo:
Title : ConsoleRestore
ProductCode: CTR-P-22UA
BackupMemoryType: None
TitleInfo:
Use: Evaluation
Category: Application
UniqueId: 0xf8022
Version: 0
SystemControlInfo:
AppType : Application
StackSize : 0x4000
Dependency :
- codec
- hid
- gsp
- friends
- nim
- ac
- ndm
AccessControlInfo:
Priority : 16
DisableDebug : true
FileSystemAccess:
- DirectSdmc
- Core
- CategoryFileSystemTool
- ExportImportIvs
IoAccessControl:
- FsMountNand
- FsMountTwln
Option:
FreeProductCode: true
CardInfo:
CardDevice: None
Rom:
# ROM に含めるファイルシステムのルートパスを指定します。
HostRoot: "$(ROMFS_ROOT)"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: Contoroller.h
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$
*---------------------------------------------------------------------------*/
#ifndef CONTOROLLER_H_
#define CONTOROLLER_H_
#include <nn.h>
#include <vector>
#include <string>
#include "HardwareStateManager.h"
#include "OperationMessage.h"
namespace ConsoleRestore
{
typedef enum RestoreMode
{
RESTORE_MODE_RESTORE,
RESTORE_MODE_NUP_ONLY,
RESTORE_MODE_GET_IVS,
RESTORE_MODE_CHECK_SD,
RESTORE_MODE_DOWNLOAD_PREINSTALL
} RestoreMode;
// ネットワーク処理のリトライ回数の最大値
const u32 RETRY_MAX = 3;
// 状態遷移を管理する
// manager ハードウェア情報を取得するためのラッパ
// operationMessage 操作情報として表示したい文字列
// nextStep 次の状態に遷移してもよいかどうか
// operateBmsDone BMS操作を完了したかどうか
// forcePreinstall ユーザSDが初期化済みだが、プリインストールアプリを書き込むかどうか
// unregister アカウント削除を開始しても良いか
void ControlState(common::HardwareStateManager& manager, common::OperationMessage& operationMessage, bool& nextStep,
bool operateBmsDone, bool forcePreinstall, bool unregister);
// リストア処理中かどうか
bool InProgress();
// リストアが完了したかどうか
bool IsRestoreSucceeded();
// リストアが失敗したかどうか
bool IsRestoreFailed();
// 書き込みスレッドの進捗を返す
u32 GetProgress();
// SDカードが抜き出されたときに実行したい関数
void OnSdEjected();
// SDカードが挿入されたときに実行したい関数
void OnSdInserted();
// 状態を初期化する
void InitializeState();
// リストア状態を取得する
RestoreMode GetRestoreMode();
}
#endif /* CONTOROLLER_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,176 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: Importer.h
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$
*---------------------------------------------------------------------------*/
#ifndef IMPORTER_H_
#define IMPORTER_H_
#include <nn.h>
#include "FileName.h"
#include <nn/ac/CTR/private/ac_NetworkSetting.h>
#include <string>
#include "HardwareStateManager.h"
namespace ConsoleRestore
{
// SDカードのデバイスIDファイルが存在するか
nn::Result ExistsDeviceIdFile();
// SDカードのデバイスIDファイルと本体のデバイスIDが一致しているかどうか
bool EqualsDeviceIdFileandDeviceId(common::HardwareStateManager& manager);
// SDカードのリージョンと本体のリージョンが一致しているかどうか
nn::Result EqualsRegionDataandRegion();
// シリアルナンバーを取得する
nn::Result ReadSerialNumber(u8* serial);
// 出力ファイル一覧を読み込む
nn::Result SetupVersionAndFileList();
// インポート用のスレッドを終了する
void FinalizeImportThread();
// インポート用のスレッドが終了したかどうか
bool IsImportThreadFinished();
// 新たにスレッドを立て、TWLサウンド領域をインポートする
void ImportTwlSoundData();
// 新たにスレッドを立て、TWL-NAND領域をインポートする
void ImportTwlSaveData();
// 新たにスレッドを立て、TWL写真領域をインポートする
void ImportTwlPhotoData();
// 本体固有データを読み込む
// 新たにスレッドを立て、CTRセーブデータ領域をインポートする
nn::Result ImportData();
// インポート完了ファイルを作る
void CreateWriteFinishedFile();
// ネットワークアップデート完了ファイルを作る
void CreateUpdateFinishedFile();
// 本体初期化完了ファイルを作る
void CreateConsoleInitializedFile();
// RTC書き込み完了ファイルを作る
void CreateRtcSyncFinishedFile();
// IVSダウンロード完了ファイルを作る
void CreateDownloadIvsFinishedFile();
// アカウント削除完了ファイルを作る
void CreateDeleteAccountFinishedFile();
// アカウント移行完了ファイルを作る
void CreateTransferAccountFinishedFile();
// インポートスレッドの進捗を取得する
u32 GetImportProgress();
// インポートスレッドの進捗を取得する
u32 GetImportProgressTwlNand();
// NANDのごみを削除する
nn::Result Cleanup();
// ファイルが存在するかどうか確認するためのテーブル
const wchar_t* const CHECK_FILENAME_TABLE[] =
{
common::UPDATE_CHECK_PATHNAME,
common::INITIALIZED_CHECK_PATHNAME,
common::WRITE_FINISHED_CHECK_PATHNAME,
common::RTC_SYNC_CHECK_PATHNAME,
common::DOWNLOAD_IVS_CHECK_PATHNAME,
common::DELETE_ACCOUNT_CHECK_PATHNAME,
common::TRANSFER_ACCOUNT_CHECK_PATHNAME
};
// ファイル存在確認をクリアする
void DeleteAllCheckFiles();
struct TimeZone
{
u32 hour;
u32 minutes;
bool isMinus;
NN_PADDING3;
};
// ネットワーク設定ファイルを読み込む
bool ReadSetting(bool* nupOnly, bool* getIvs, bool* checkSd, bool* skipNup, bool* dlPreinstall);
// ネットワーク設定ファイルからNTPサーバの名前を取得する
// 先にReadSettingが成功している必要がある
char* GetNtpServerName();
// ネットワーク設定ファイルからタイムゾーンを取得する
// 先にReadSettingが成功している必要がある
TimeZone GetTimeZone();
// インターネット設定をユーザの設定に戻す
void RestoreCurrentInternetSetting();
struct CheckedNetworkSetting
{
nn::ac::CTR::NetworkSetting setting;
bool isValid;
NN_PADDING3;
};
// SDカードから読み込んだネットワーク設定ファイルから生成した
// インターネット設定へのポインタを取得する
// インターネット設定は内部のバッファに読み込む
CheckedNetworkSetting* GetTempNetworkSetting();
// 国設定を読み込む
nn::Result ImportCountryLanguageData();
// RTCを読み込む
nn::Result ImportMcuRtc(common::HardwareStateManager& manager);
// TWL写真領域を初期化してから本体初期化を行う
bool InitializeFileSystem();
// SDカードのファイルと本体情報の比較結果をクリアする
void ClearFileReadResult();
// プレイ履歴を読み込みます。ptmのセーブデータ移行後に呼び出す必要があります
void ImportPlayHistory();
// cfgのハードウェア固有領域をcal値で初期化します
nn::Result InitializeHardwareDependentSetting();
// SDカード上のバージョン情報を読みます
nn::Result ReadVersionData();
// SDカードのNintendo 3DS以下ににIVSと一致するディレクトリがあるかどうか
bool ExistsIvsDirectory(std::string& ivsRoot);
// SDカードのIVSデータを書き込む
bool ImportIvsData();
// 書き込みが成功したかどうか
bool IsImportSucceeded();
void RepairSimpleAddress();
}
#endif /* IMPORTER_H_ */

View File

@ -0,0 +1,309 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: NtpClient.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/socket.h>
#include <nn/ac.h>
#include <nn/ptm.h>
#include <nn/ptm/CTR/ptm_ApiSysmenu.h>
#include <nn/ac/private/ac.h>
#include <nn/ac/CTR/private/ac_InternalApi.h>
#include <nn/ac/CTR/private/ac_NetworkSetting.h>
#include <nn/math.h>
#include "Importer.h"
#include "CommonLogger.h"
namespace ConsoleRestore
{
namespace {
const size_t NTP_THREAD_STACK_SIZE = 0x1000;
nn::os::Thread s_NtpThread;
nn::os::StackBuffer<NTP_THREAD_STACK_SIZE> s_NtpThreadStack;
bool s_NtpSyncSuccessed = false;
struct NTP_Packet{ // NTPパケット
u32 controlWord;
u32 rootDelay;
u32 rootDispersion;
u32 referenceId;
s64 referenceTimestamp;
s64 startTimestamp;
s64 receiveTimestamp;
u32 transmitTimestampSeconds;
u32 transmitTimestampFractions;
};
const size_t TIMEOUT_MILLISECOND = 5000; // タイムアウト ミリ秒数
NTP_Packet s_NTPSendPacket; // 送信するNTPパケット
NTP_Packet s_NTPRecvPacket; // 受信するNTPパケット
const u32 NTP_PORT_NUM = 123;
bool GetNtpTime(u32* ntpTime)
{
nn::Result result;
bool retval = true;
NN_LOG("Initializing network.\n");
// 本体に書き込まれているネットワーク設定を使ってネットワーク接続を初期化
if(!nn::ac::IsConnected())
{
result = common::InitializeNetwork();
COMMON_LOGGER_RESULT_IF_FAILED(result);
}
{
NN_LOG("Initializing socket..\n");
// 一つのスレッドからソケット API を利用する
const s32 sessionCount = 1;
// ソケットの送受信バッファとして 64 KB を割り当て
const size_t bufferSizeForSockets = 65536;
// ソケットライブラリに必要なワークサイズを求める
const size_t workSizeForLibrary = nn::socket::GetRequiredMemorySize(bufferSizeForSockets, sessionCount);
// ワークメモリを確保して 4KB にアラインにする
u8* pWorkMemory = new u8[workSizeForLibrary + 4096];
uptr workMemoryAddress = nn::math::RoundUp<uptr>(reinterpret_cast<uptr> (pWorkMemory), 4096);
// ソケットライブラリの初期化
result = nn::socket::Initialize(workMemoryAddress, workSizeForLibrary, bufferSizeForSockets, sessionCount);
COMMON_LOGGER_RESULT_IF_FAILED(result);
{
s32 ret;
nn::socket::InAddr addr, netmask;
ret = nn::socket::GetPrimaryAddress(reinterpret_cast<u8*> (&addr), reinterpret_cast<u8*> (&netmask));
NN_ASSERT(ret == 0);
COMMON_LOGGER("host : %s\n", nn::socket::InetNtoA(addr));
COMMON_LOGGER("netmask : %s\n", nn::socket::InetNtoA(netmask));
nn::socket::InAddr dns1, dns2;
ret = nn::socket::GetResolver(reinterpret_cast<u8*> (&dns1), reinterpret_cast<u8*> (&dns2));
if (ret == 0)
{
COMMON_LOGGER("dns1 : %s\n", nn::socket::InetNtoA(dns1));
COMMON_LOGGER("dns2 : %s\n", nn::socket::InetNtoA(dns2));
}
nn::socket::InAddr gateway;
ret = nn::socket::GetDefaultGateway(reinterpret_cast<u8*> (&gateway));
if (ret == 0)
{
COMMON_LOGGER("gateway : %s\n", nn::socket::InetNtoA(gateway));
}
COMMON_LOGGER("\n");
#ifndef NN_SWITCH_DISABLE_DEBUG_PRINT
nn::socket::DumpRoutingTable();
#endif
}
{
s32 socket = nn::socket::Socket(nn::socket::PF_INET, nn::socket::SOCK_DGRAM, 0);
NN_LOG("socket = %d\n", socket);
// クライアントアドレスの設定
nn::socket::SockAddrIn host_addr;
host_addr.len = sizeof(nn::socket::SockAddrIn);
host_addr.family = nn::socket::AF_INET;
host_addr.addr.addr = 0;
host_addr.port = nn::socket::HtoNs(NTP_PORT_NUM);
// ローカルアドレスをバインド
s32 ret = nn::socket::Bind(socket, &host_addr);
NN_LOG("bind = %d\n", ret);
// ********************************************************************************
// NTPパケットを生成して送る
// ********************************************************************************
// サーバアドレスの設定
nn::socket::SockAddrIn serverSockAddrIn;
serverSockAddrIn.len = sizeof(nn::socket::SockAddrIn);
serverSockAddrIn.family = nn::socket::AF_INET;
// GetHostByNameを使う場合
nn::socket::HostEnt* serverHostent;
u64 serveraddr = 0;
serverHostent = nn::socket::GetHostByName(GetNtpServerName());
if (serverHostent == NULL)
{
COMMON_LOGGER("Error: GetHostByName %s\n", GetNtpServerName());
retval = false;
}
else
{
// サーバのホスト情報からIPアドレスをコピー
serveraddr = *(reinterpret_cast<u64 *> (serverHostent->addrList[0]));
}
serverSockAddrIn.addr.addr = serveraddr;
COMMON_LOGGER("Destination address: %s\n", nn::socket::InetNtoA(serverSockAddrIn.addr));
serverSockAddrIn.port = nn::socket::HtoNs(NTP_PORT_NUM); // ポート番号
// NTPパケットをSNTP用に初期化する
s_NTPSendPacket.controlWord = nn::socket::HtoNl(0x0B000000);
s_NTPSendPacket.rootDelay = 0;
s_NTPSendPacket.rootDispersion = 0;
s_NTPSendPacket.referenceId = 0;
s_NTPSendPacket.referenceTimestamp = 0;
s_NTPSendPacket.startTimestamp = 0;
s_NTPSendPacket.receiveTimestamp = 0;
s_NTPSendPacket.transmitTimestampSeconds = 0;
s_NTPSendPacket.transmitTimestampFractions = 0;
// サーバを指定してNTPパケットを送信する
if ((ret = nn::socket::SendTo(socket, reinterpret_cast<const void*> (&s_NTPSendPacket), sizeof(s_NTPSendPacket), 0,
&serverSockAddrIn)) < 0)
{
COMMON_LOGGER("Error: Failed Send to Server, %d\n", ret);
retval = false;
}
NN_LOG("SendTo finished\n");
// 受信待ち
nn::socket::PollFd pollFd;
pollFd.fd = socket;
pollFd.events = nn::socket::POLLRDNORM;
if ((ret = nn::socket::Poll(&pollFd, 1, TIMEOUT_MILLISECOND)) < 0)
{
COMMON_LOGGER("Error: recv error, %d\n", ret);
retval = false;
}
NN_LOG("Poll Finished\n");
switch (pollFd.revents)
{
case nn::socket::POLLERR: // ソケットにエラーが発生しました。
COMMON_LOGGER("Error: POLLERR %s %d\n", __func__, __LINE__);
retval = false;
break;
case nn::socket::POLLHUP: // ストリーム・ソケットが未接続です。
COMMON_LOGGER("Error: POLLHUP %s %d\n", __func__, __LINE__);
retval = false;
break;
case nn::socket::POLLNVAL: // 不正なソケット記述子です。
COMMON_LOGGER("Error: POLLNVAL %s %d\n", __func__, __LINE__);
retval = false;
break;
default:
break;
}
// サーバから時刻情報を受信する
// サーバを指定して受信を行う
// 受信するまで待たされる
if ((ret = nn::socket::RecvFrom(socket, reinterpret_cast<void*> (&s_NTPRecvPacket), sizeof(s_NTPRecvPacket), nn::socket::MSG_DONTWAIT,
&serverSockAddrIn)) < 0)
{
COMMON_LOGGER("Error: RecvFrom, %d\n", ret);
retval = false;
}
NN_LOG("RecvFrom finished\n");
// NTPサーバから取得した時刻を現地時間に変換する
*ntpTime = nn::socket::NtoHl(s_NTPRecvPacket.transmitTimestampSeconds) - 2208988800; /* 1970/01/01 からの秒数に変換 */
NN_LOG("ntp_time = %d\n", ntpTime);
nn::socket::Close(socket);
NN_UNUSED_VAR(ret);
}
NN_LOG("Finalizing socket..\n");
// ソケットライブラリの終了
result = nn::socket::Finalize();
COMMON_LOGGER_RESULT_IF_FAILED(result);
}
NN_LOG("Finalizing network.\n");
result = common::FinalizeNetwork();
COMMON_LOGGER_RESULT_IF_FAILED(result);
return retval;
}
}
void NtpThreadFunc()
{
// NTP時間を取得する
u32 ntpTime;
if (GetNtpTime(&ntpTime))
{
// タイムゾーンを考慮してDateTimeに変換する
TimeZone timeZone = GetTimeZone();
// 1970/01/01
nn::fnd::DateTime utc = nn::fnd::DateTime(1970, 1, 1, 0, 0, 0, 0);
nn::fnd::DateTime current = utc + nn::fnd::TimeSpan::FromSeconds(ntpTime);
if (timeZone.isMinus)
{
current -= (nn::fnd::TimeSpan::FromHours(timeZone.hour) + nn::fnd::TimeSpan::FromMinutes(timeZone.minutes));
}
else
{
current += nn::fnd::TimeSpan::FromHours(timeZone.hour) + nn::fnd::TimeSpan::FromMinutes(timeZone.minutes);
}
// SWCを書き込む
nn::ptm::CTR::SetUserTime(current);
COMMON_LOGGER("Set User Time %04d/%02d/%02d %02d:%02d:%02d\n",
current.GetYear(), current.GetMonth(), current.GetDay(), current.GetHour(), current.GetMinute(), current.GetSecond());
s_NtpSyncSuccessed = true;
}
else
{
COMMON_LOGGER("Failed Get Ntp Time\n");
s_NtpSyncSuccessed = false;
}
}
bool IsTimeAdjustFinished()
{
// Initialize済みかつ終了
return s_NtpThread.IsValid() && !s_NtpThread.IsAlive();
}
bool IsTimeAdjustSuccessed()
{
return s_NtpSyncSuccessed;
}
void AdjustTime()
{
nn::Result result;
result = nn::ac::CTR::InitializeInternal();
COMMON_LOGGER_RESULT_IF_FAILED(result);
if(IsTimeAdjustFinished())
{
s_NtpThread.Join();
s_NtpThread.Finalize();
}
s_NtpThread.Start( NtpThreadFunc, s_NtpThreadStack);
}
}

View File

@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: NtpClient.h
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$
*---------------------------------------------------------------------------*/
#ifndef NTPCLIENT_H_
#define NTPCLIENT_H_
namespace ConsoleRestore
{
// 新たにスレッドを立て、NTPサーバと同期する
u32 AdjustTime();
// NTPサーバとの同期が終了したかどうか
bool IsTimeAdjustFinished();
// NTPサーバとの同期が完了したかどうか
bool IsTimeAdjustSuccessed();
}
#endif /* NTPCLIENT_H_ */

View File

@ -0,0 +1,91 @@
#!/usr/bin/env omake
#----------------------------------------------------------------------------
# Project: Horizon
# File: OMakefile
#
# 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$
#----------------------------------------------------------------------------
SUPPORTED_TARGETS = CTR-T*.Process.MPCore.fast
CTR_APPTYPE = CARD
TARGET_PROGRAM = ConsoleRestore
SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include)
INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \
$(dir $(CTRMW_QRE_ROOT)/include/mw/qre) \
../common
SOURCES[] =
ConsoleRestore.cpp
Controller.cpp
Importer.cpp
Updater.cpp
Ntpclient.cpp
TitleDownloader.cpp
Shop.cpp
RegionIdModifier.cpp
PreinstallImporter.cpp
ActCompleter.cpp
../common/Util.cpp
../common/DrawSystemState.cpp
../common/FileTransfer.cpp
../common/FileChecker.cpp
../common/SdReaderWriter.cpp
../common/HeapManager.cpp
../common/SdLogger.cpp
../common/wave.cpp
../common/SimplePlayer.cpp
../common/LogConsole.cpp
../common/CommonLogger.cpp
../common/SdMountManager.cpp
../common/configLoader.cpp
../common/VersionDetect.cpp
../common/ResFont.cpp
../common/HardwareStateManager.cpp
../common/SaveDataMover.cpp
../common/OperationMessage.cpp
../common/QrImage.cpp
include $(ROOT)/common/BuildSwitch.om
CTR_BANNER_SPEC = $(TARGET_NAME).bsf
ROMFS_ROOT = ../common/romfiles
SHADER_BIN = nnfont_RectDrawerShader.shbin
SHADER_PATH = $(ROMFS_ROOT)/$(SHADER_BIN)
ROMFS_DEPENDENCIES = $(SHADER_PATH)
LIBS += libnn_cfg \
libnn_crypto \
libnn_mcu \
libnn_ps \
lib_demo \
libnn_nwm \
libnn_friends \
libnn_ns \
libnn_am \
libnn_nim \
libnn_xml_simple \
libnn_act \
QRE_LIBRARIES[] = libmw_qre
LIBFILES += $`(addprefix $(CTRMW_QRE_ROOT)$(DIRSEP)$(SUBDIR_LIBRARIES)$(DIRSEP)$(config.getTargetSubDirectory true)$(DIRSEP), $(QRE_LIBRARIES)) \
INSTALL_SDK_TOOL = true
ROM_SPEC_FILE = $(TARGET_NAME).rsf
DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/private/RepairTool.desc
include $(ROOT_OMAKE)/modulerules
build: $(DEFAULT_TARGETS)

View File

@ -0,0 +1,83 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: PreinstallImporter.cpp
Copyright 2009-2011 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 "CommonLogger.h"
#include "HeapManager.h"
#include "PreinstallImporter.h"
#include <cstring>
#include <nn/am/am_ApiSystemMenu.h>
namespace ConsoleRestore
{
PreinstallImporter::PreinstallImporter()
{
// TODO 自動生成されたコンストラクター・スタブ
}
PreinstallImporter::~PreinstallImporter()
{
// TODO Auto-generated destructor stub
}
nn::Result PreinstallImporter::SetupSd(bool* isAlreadyAvailable, bool forcePreinstall)
{
// SDカードがインポート可能状態かどうかチェック
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(
nn::am::QueryAvailableExternalTitleDatabase(isAlreadyAvailable)
);
// タイトルデータベースを作成する
if (!*isAlreadyAvailable)
{
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(
nn::am::InitializeExternalTitleDatabase()
);
}
if(forcePreinstall)
{
// 未初期化として返す
*isAlreadyAvailable = false;
}
return nn::ResultSuccess();
}
nn::Result PreinstallImporter::ListTitlesBasedOnTickets(nn::ProgramId* list, size_t* num)
{
s32 personalizedTicketNum;
nn::am::TicketInfo ticketInfo[256];
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(
nn::am::GetPersonalizedTicketInfoList(&personalizedTicketNum, ticketInfo, 256)
);
if(personalizedTicketNum == 0)
{
return nn::MakePermanentResult(nn::Result::SUMMARY_NOT_FOUND,
nn::Result::MODULE_APPLICATION, nn::Result::DESCRIPTION_NOT_FOUND);
}
*num = 0;
for(s32 i = 0; i < personalizedTicketNum; i++)
{
list[*num] = ticketInfo[i].titleId;
(*num)++;
}
return nn::ResultSuccess();
}
} /* namespace ConsoleRestore */

View File

@ -0,0 +1,42 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: PreinstallImporter.h
Copyright 2009-2011 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$
*---------------------------------------------------------------------------*/
#ifndef PREINSTALLIMPORTER_H_
#define PREINSTALLIMPORTER_H_
#include <nn.h>
#include <nn/xml/simple/xml_simple_SimpleXmlParser.h>
namespace ConsoleRestore
{
//! @brief プリインストールをSDカードに書き込むためのクラスです
class PreinstallImporter
{
public:
PreinstallImporter();
virtual ~PreinstallImporter();
//! @brief 外部タイトルデータベースを作成します
//! @param[out] list    SDカードが初期化済みかどうか
//! @param[in] forcePreinstall    SDカードが初期化済みでもプリインストールを書き込むかどうか
nn::Result SetupSd(bool* isAlreadyAvailable, bool forcePreinstall);
//!@ brief プリインストールタイトルをeTicketに基づいてリストアップする
nn::Result ListTitlesBasedOnTickets(nn::ProgramId* list, size_t* num);
};
} /* namespace ConsoleRestore */
#endif /* PREINSTALLIMPORTER_H_ */

View File

@ -0,0 +1,153 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: RegionIdModifier.cpp
Copyright (C)2011 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 "RegionIdModifier.h"
#include <cwchar>
#include <cstring>
struct CountryData
{
u32 id; // 上記定数にあるように、国IDと地域IDを組み合わせたID
u16 regionName[nn::cfg::CTR::CFG_SIMPLE_ADDRESS_NUM_LANGUAGES][nn::cfg::CTR::CFG_SIMPLE_ADDRESS_NAME_LENGTH]; // NULL終端込み
u8 order[nn::cfg::CTR::CFG_SIMPLE_ADDRESS_NUM_LANGUAGES]; // 言語ごとの地域名並び順「未設定」が0になるので、最初の地域は1
u16 latitude; // リストの値を 65536/360 倍して格納して下さい
u16 longitude; // リストの値を 65536/360 倍して格納して下さい
};
const size_t NUP_VERSION_TO_REGIONNUM[] =
{
1, // ローンチ(0)
1, // 0thNUP(1)
2, // 1stNUP(2)
2, // 1.05NUP(3)
2, // 1.1NUP(4)
3, // 2ndNUP(5)
3, // 2.1NUP(6)
};
const wchar_t* DIR_PATH[] =
{
L"0/JP/",
L"0/US/",
L"0/EU/",
L"2/JP/",
L"2/US/",
L"2/EU/",
L"5/JP/",
L"5/US/",
L"5/EU/"
};
RegionIdModifier::RegionIdModifier(u16 id, u8 nupVersion, u8 regionCode, const wchar_t* regionName)
{
m_Id = id;
m_NupVersion = nupVersion;
m_RegionCode = regionCode;
if (regionName != NULL)
{
std::wcsncpy(m_RegionName, regionName, sizeof(m_RegionName) / sizeof(wchar_t));
}
}
bool RegionIdModifier::IsValid()
{
return (m_Id & 0x00ff) != 0x01;
}
const PathList* RegionIdModifier::GetDirectoryPath()
{
// 範囲外のリージョン
if (nn::cfg::CTR::CFG_REGION_EUROPE < m_RegionCode)
{
return NULL;
}
for (u8 i = 0; i < nn::cfg::CTR::CFG_REGION_EUROPE + 1; i++)
{
std::wcsncpy(m_DirectoryPathBuf[i].path, DIR_PATH[m_RegionCode + i * (nn::cfg::CTR::CFG_REGION_EUROPE + 1)],
PATHLIST_LENGTH);
}
return m_DirectoryPathBuf;
}
size_t RegionIdModifier::GetDirectoryPathNum()
{
// 範囲外のリージョン
if (nn::cfg::CTR::CFG_REGION_EUROPE < m_RegionCode)
{
return 0;
}
const size_t countryNum = sizeof(NUP_VERSION_TO_REGIONNUM) / sizeof(NUP_VERSION_TO_REGIONNUM[0]);
if (m_NupVersion > countryNum - 1)
{
return NUP_VERSION_TO_REGIONNUM[countryNum - 1];
}
else
{
return NUP_VERSION_TO_REGIONNUM[m_NupVersion];
}
}
const wchar_t* RegionIdModifier::GetFileName()
{
std::swprintf(m_FileNameBuf, sizeof(m_FileNameBuf), L"%d_LZ.bin", m_Id >> 8);
return m_FileNameBuf;
}
const PathList* RegionIdModifier::GetFilePath()
{
std::memset(m_FilePathBuf, 0, sizeof(m_FilePathBuf));
GetDirectoryPath();
for (u8 i = 0; i < GetDirectoryPathNum(); i++)
{
size_t writeSize = std::wcslen(m_DirectoryPathBuf[i].path);
std::wcsncpy(m_FilePathBuf[i].path, m_DirectoryPathBuf[i].path, writeSize);
std::wcsncat(m_FilePathBuf[i].path, GetFileName(), PATHLIST_LENGTH - writeSize);
}
return m_FilePathBuf;
}
size_t RegionIdModifier::GetFilePathNum()
{
return GetDirectoryPathNum();
}
bool RegionIdModifier::GetValidRegionId(void* buf, size_t size, u8* id)
{
if (buf == NULL || size == 0)
{
return false;
}
u32 numRegion; // その国に含まれる地域の数
numRegion = *reinterpret_cast<u32*>(buf);
CountryData* pCountry;
pCountry = reinterpret_cast<CountryData*>(&reinterpret_cast<u32*>(buf)[1]);
for (u32 i = 0; i < numRegion + 1; i++)
{
if (std::wcscmp(m_RegionName, reinterpret_cast<wchar_t*>(pCountry->regionName[0])) == 0)
{
*id = (pCountry->id >> 16) & 0x00ff;
return true;
}
pCountry++;
}
return false;
}

Some files were not shown because too many files have changed in this diff Show More