diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.bsf b/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.bsf new file mode 100644 index 0000000..704d1b1 Binary files /dev/null and b/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.bsf differ diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.cpp b/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.cpp new file mode 100644 index 0000000..19f07bb --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.cpp @@ -0,0 +1,434 @@ +/*---------------------------------------------------------------------------* + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "demo.h" + +#include +#include + +#include "ConsoleBackup.h" +#include "FileName.h" +#include "Controller.h" +#include "SimplePlayer.h" +#include "Exporter.h" +#include "CommonLogger.h" +#include "SDMountManager.h" +#include "HeapManager.h" + +// svnリビジョン埋め込み用 +#include "version.h" +#ifndef BACKUP_VERSION_NUM +#define BACKUP_VERSION_NUM 0 +#endif + +namespace { + +// グラフィックスに割り当てるメモリ +const size_t s_GxHeapSize = 0x800000; + +const u16 PROGRESS_MAX_LINES = 160; + +// バッテリ残量 +u8 batteryRemain = 100; + +// シリアルナンバー +u8 s_SerialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + +// シリアルナンバーが読めるかどうか +bool s_CanReadSerialNumber = false; + +// IVSへのポインタ +void* sp_Ivs; + +size_t s_SizeofIvs; + +// IVSが読めるかどうか +bool s_CanReadIvs = false; + + +} // namespace + +namespace ConsoleBackup{ + +u32 GetRenderTarget(u32 target, bool flip = false); + +bool IsAdapterConnected() +{ + return nn::ptm::CTR::GetAdapterState() == nn::ptm::CTR::ADAPTERSTATE_CONNECTED; +} + +bool IsBatteryLower() +{ + return batteryRemain <= 10; +} + +bool CanReadIVS() +{ + return s_CanReadIvs; +} + +bool CanReadSerialNumber() +{ + return s_CanReadSerialNumber; +} + +void GetSerialNumber(u8** serial, size_t* size) +{ + *serial = s_SerialNo; + *size = nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN; +} + +void GetIvs(void** ivs, size_t* size) +{ + *ivs = sp_Ivs; + *size = s_SizeofIvs; +} + +u32 GetRenderTarget(u32 target, bool flip) +{ + if(flip) + { + if(target == NN_GX_DISPLAY0) + { + return NN_GX_DISPLAY1; + } + else + { + return NN_GX_DISPLAY0; + } + } + else + { + return target; + } +} + + +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(); + NN_UTIL_PANIC_IF_FAILED(result); + + // cfg の初期化 + nn::cfg::CTR::init::Initialize(); + nn::cfg::CTR::system::Initialize(); + + // 時計設定用ptm初期化 + nn::ptm::CTR::InitializeForSystemMenu(); + + // ps の初期化 + nn::ps::Initialize(); + + // friendsの初期化 + result = nn::friends::detail::Initialize(); + + // mcuの初期化 + nn::Handle mcuSession; + nn::mcu::CTR::InitializeHwCheck(&mcuSession); + + nn::mcu::CTR::HwCheck mcu(mcuSession); + + // ヒープの確保 + common::HeapManager::GetHeap()->Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + // RenderSystem の準備 + uptr heapForGx = reinterpret_cast(common::HeapManager::GetHeap()->Allocate(s_GxHeapSize)); + demo::RenderSystemDrawing s_RenderSystem; + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + + // サウンドスレッドの起動 + common::InitializeSimplePlayer(); + + // ログ描画の初期化 + common::Logger::GetLoggerInstance()->Initialize(CONSOLE_WIDTH, CONSOLE_HEIGHT, CONSOLE_MAX_LINE, &s_RenderSystem); + + // RenderSystemを作ってからログが出せる + common::Logger::InitializeEjectThread(); + common::Logger::SetEjectHandler(OnSdEjected); + COMMON_LOGGER("\n"); + COMMON_LOGGER("CTR Console Backup start\n"); + + // ボタン入力 + nn::hid::PadReader s_PadReader; + nn::hid::PadStatus padStatus; + + // データの準備 + + // 完全性検証SEEDの取得 + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + if (result.IsSuccess()) + { + nn::fs::FileInputStream fis; + + result = fis.TryInitialize(common::IVS_NAND_PATHNAME); + if (result.IsSuccess()) + { + s64 fileSize = fis.GetSize(); + s32 ret; + void* addr = NULL; + addr = common::HeapManager::GetHeap()->Allocate(fileSize); + if (addr != NULL) + { + sp_Ivs = addr; + s_SizeofIvs = fileSize; + result = fis.TryRead(&ret, addr, fileSize); + if (result.IsSuccess()) + { + s_CanReadIvs = true; + } + } + } + fis.Finalize(); + } + // 一旦アンマウントしておく + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + + // リージョンの取得 + nn::cfg::CTR::CfgRegionCode region; + region = nn::cfg::CTR::GetRegion(); + + // シリアルナンバーの取得 + std::memset(s_SerialNo, '\0', + nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN); + result = nn::cfg::CTR::system::GetSerialNo(s_SerialNo); + if(result.IsSuccess()) + { + s_CanReadSerialNumber = true; + } + common::Logger::GetLoggerInstance()->PrintResultIfFailed(result, __LINE__); + + // デバイスIDの取得 + bit32 deviceId; + result = nn::ps::CTR::GetDeviceId(&deviceId); + common::Logger::GetLoggerInstance()->PrintResultIfFailed(result, __LINE__); + + // MACアドレスの取得 + nn::nwm::Mac mac; + char8 macAddress[nn::nwm::Mac::MAC_STRING_SIZE]; + + result = nn::nwm::GetMacAddress(mac); + common::Logger::GetLoggerInstance()->PrintResultIfFailed(result, __LINE__); + mac.GetString(macAddress); + common::Logger::GetLoggerInstance()->PrintResultIfFailed(result, __LINE__); + + // フレンドコードの取得 + nn::friends::CTR::FriendKey friendKey; + result = nn::friends::CTR::GetMyFriendKey(&friendKey); + common::Logger::GetLoggerInstance()->PrintResultIfFailed(result , __LINE__); + u64 friendCode = nn::friends::CTR::FriendKeyToFriendCode(friendKey); + + // ReadOnlySharedInfoの取得 + const nn::os::ReadOnlySharedInfo& rosi = nn::os::GetReadOnlySharedInfo(); + + // 情報出力 + COMMON_LOGGER("CTR Console Backup %s Rev.%s\n", __DATE__, BACKUP_VERSION_NUM); + COMMON_LOGGER("System Ver. %d.%d (Rev.%d)\n", rosi.versionHi, rosi.versionLo, rosi.revision); + COMMON_LOGGER("System Region %s\n", nn::cfg::CTR::GetRegionCodeA3(region)); + COMMON_LOGGER("Serial Number %s\n", s_SerialNo); + COMMON_LOGGER("Device ID %X\n", deviceId); + COMMON_LOGGER("MAC Address %s\n", macAddress); + COMMON_LOGGER("Friend Code %04u-%04u-%04u\n", + static_cast(friendCode / 100000000ULL % 10000ULL), + static_cast(friendCode / 10000ULL % 10000ULL), + static_cast(friendCode % 10000ULL) ); + + + bool flip = false; + bool continueBackup = 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; + } + + // 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(); + } + + if(padStatus.hold & nn::hid::BUTTON_LEFT) + { + common::Logger::GetLoggerInstance()->ScrollToBegin(); + } + + if(padStatus.hold & nn::hid::BUTTON_RIGHT) + { + common::Logger::GetLoggerInstance()->ScrollToEnd(); + } + + + // 情報更新 + // バッテリ + mcu.GetBatteryRemain(&batteryRemain); + // ACアダプタ + std::string adapterState; + if(IsAdapterConnected()) + { + adapterState += ::std::string("Connected"); + } + else + { + adapterState += ::std::string("Not Connected"); + } + + // 操作用メッセージ + // 進捗確認メッセージを兼ねる? + ::std::vector operationMessage; + + ControlState(operationMessage, nextStep, continueBackup); + + // デフォルトで上画面に描画するもの + s_RenderSystem.SetRenderTarget(GetRenderTarget(NN_GX_DISPLAY0, flip)); + if(IsBackupSucceeded()) + { + s_RenderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY0, flip), SUCCESS_COLOR); + } + if(IsBackupFailed()) + { + s_RenderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY0, flip), FAIL_COLOR); + } + + s_RenderSystem.Clear(); + s_RenderSystem.SetColor(1.f, 1.f, 1.f); + u32 line = 0; + s_RenderSystem.DrawText(0, line++ * 10, "CTR Console Backup %s Rev.%s", __DATE__, BACKUP_VERSION_NUM); + s_RenderSystem.DrawText(0, line++ * 10, ""); + s_RenderSystem.DrawText(0, line++ * 10, "System Ver. %d.%d (Rev.%d)", rosi.versionHi, rosi.versionLo, rosi.revision); + s_RenderSystem.DrawText(0, line++ * 10, "System Region %s", nn::cfg::CTR::GetRegionCodeA3(region)); + s_RenderSystem.DrawText(0, line++ * 10, "Serial No. %s", s_SerialNo); + s_RenderSystem.DrawText(0, line++ * 10, "Device ID %X", deviceId); + s_RenderSystem.DrawText(0, line++ * 10, "MAC Address %s", macAddress); + s_RenderSystem.DrawText(0, line++ * 10, "Friend Code %04u-%04u-%04u", + static_cast(friendCode / 100000000ULL % 10000ULL), + static_cast(friendCode / 10000ULL % 10000ULL), + static_cast(friendCode % 10000ULL) ); + + s_RenderSystem.DrawText(0, line++ * 10, "Battery %d%%", batteryRemain); + s_RenderSystem.DrawText(0, line++ * 10, "AC Adaper %s", adapterState.c_str()); + s_RenderSystem.DrawText(0, line++ * 10, "Progress %02d%%", GetProgress()); + s_RenderSystem.SetColor(0.f, 0.2f, 0.f); + s_RenderSystem.DrawLine(19 * 8, (line-1) * 10, 19 * 8 + PROGRESS_MAX_LINES, (line-1) * 10); + s_RenderSystem.DrawLine(19 * 8, (line-1) * 10, 19 * 8, (line) * 10); + s_RenderSystem.DrawLine(19 * 8, (line) * 10, 19 * 8 + PROGRESS_MAX_LINES, (line) * 10); + s_RenderSystem.DrawLine(19 * 8 + PROGRESS_MAX_LINES, (line-1) * 10, 19 * 8 + PROGRESS_MAX_LINES, (line) * 10 + 1); + s_RenderSystem.SetColor(0.f, 0.5f, 0.f); + s_RenderSystem.FillRectangle(19 * 8 , (line-1) * 10, GetProgress() * PROGRESS_MAX_LINES / 100+ 1, 10); + + s_RenderSystem.SetColor(1.f, 1.f, 1.f); + s_RenderSystem.DrawText(0, line++ * 10, ""); + + ::std::vector::iterator it; + for(it = operationMessage.begin(); it != operationMessage.end(); it++) + { + s_RenderSystem.DrawText(0, line++ * 10 , "%s", it->c_str()); + } + + s_RenderSystem.SwapBuffers(); + + // デフォルトで下画面に描画するもの + s_RenderSystem.SetRenderTarget(GetRenderTarget(NN_GX_DISPLAY1, flip)); + if(IsBackupSucceeded()) + { + s_RenderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY1, flip), SUCCESS_COLOR); + } + if(IsBackupFailed()) + { + s_RenderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY1, flip), FAIL_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()) + { + common::Logger::GetLoggerInstance()->Finalize(); + // アンマウント + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + nn::fs::Unmount(common::SDMC_ARCHIVE_NAME); + s_RenderSystem.Finalize(); + + nn::mcu::CTR::FinalizeHwCheck(&mcuSession); + nn::friends::detail::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(); + } + } +} + + +} diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.h b/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.h new file mode 100644 index 0000000..7258e85 --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.h @@ -0,0 +1,47 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: ConsoleBackup.h + + 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$ + *---------------------------------------------------------------------------*/ + +#ifndef NN_CONSOLEBACKUP_H_ +#define NN_CONSOLEBACKUP_H_ + +#include + +namespace ConsoleBackup +{ + +bool IsAdapterConnected(); +bool IsBatteryLower(); +bool CanReadIVS(); +bool CanReadSerialNumber(); +void GetSerialNumber(u8** serial, size_t* size); +void GetIvs(void** ivs, size_t* size); + +const u32 CONSOLE_WIDTH = 38; +const u32 CONSOLE_HEIGHT = 24; +const u32 CONSOLE_MAX_LINE = 1000; + +} + +// 描画色の定義 +#define WHITE_COLOR 1.f, 1.f, 1.f, 1.f +#define GRAY_COLOR 0.5, 0.5, 0.5, 1.f +#define RED_COLOR 1.f, 0.f, 0.f, 1.f +#define GREEN_COLOR 0.f, 1.f, 0.f, 1.f +#define BLUE_COLOR 0.f, 0.f, 1.f, 1.f +#define SUCCESS_COLOR 0.f, 0.6f,0.f, 1.f +#define FAIL_COLOR 0.6f, 0.f,0.f, 1.f + +/* NN_CONSOLEBACKUP_H_ */ +#endif diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.rsf b/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.rsf new file mode 100644 index 0000000..1c5b8fe --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.rsf @@ -0,0 +1,49 @@ +BasicInfo: + Title : ConsoleBackup + ProductCode: ConsoleBackup + BackupMemoryType: None + +TitleInfo: + Use: Evaluation + Category: Application + UniqueId: 0xf8007 + Version: 0 + +SystemControlInfo: + AppType : Application + StackSize : 0x4000 + Dependency : + - gpio + - pdn + - spi + - i2c + - mcu + - ptm + - codec + - cfg + - hid + - gsp + - friends + +AccessControlInfo: + Priority : 16 + DisableDebug : false + + FileSystemAccess: + - DirectSdmc + - Debug + - Core + - CategoryFileSystemTool + + IoAccessControl: + - FsMountCardSpi + - FsMountNand + - FsMountTwln + +Option: + FreeProductCode: true + + +Rom: + # ROM に含めるファイルシステムのルートパスを指定します。 + HostRoot: "$(ROMFS_ROOT)" \ No newline at end of file diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/Controller.cpp b/trunk/ConsoleDataMigration/ConsoleBackup/Controller.cpp new file mode 100644 index 0000000..5c0c148 --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleBackup/Controller.cpp @@ -0,0 +1,225 @@ +/*---------------------------------------------------------------------------* + 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 "ConsoleBackup.h" +#include "Exporter.h" +#include "SimplePlayer.h" +#include "CommonLogger.h" + +#include + +namespace ConsoleBackup +{ + +namespace +{ + +typedef enum BackupState +{ + STARTUP, // 初期値 + IN_PROGRESS, // 吸出し中 + DONE, // 吸出し完了 + FINISHED, // SDカード抜き完了 + FAIL // 失敗 +} BackupState; + + +BackupState s_BackupState = STARTUP; +bool s_PlayedFinishedSound = false; +bool s_PlayedFailSound = false; + +} // namespace + +bool NeedsAcAdateper() +{ + return IsBatteryLower() && !IsAdapterConnected(); +} + +void ControlState(::std::vector& operationMessage, bool& nextStep, bool& continueBackup) +{ + // 状態遷移Controller + switch (s_BackupState) + { + + // 起動時 + case STARTUP: + { + bool error = false; + // 完全性検証SEEDを読めるか? + if (CanReadIVS()) + { + // SDカードが挿入されているか? + if (nn::fs::IsSdmcInserted()) + { + // 書き込み中に抜かないように + if (nextStep) + { + // SDカードに書き込みできるか? + if (nn::fs::IsSdmcWritable()) + { + // シリアルナンバーを読み取れるか? + if (!CanReadSerialNumber()) + { + common::PlaySound(common::SOUND_ANNOTATION); + COMMON_LOGGER("Can't Read Serial Number\n"); + } + } + else + { + error = true; + common::PlaySound(common::SOUND_ANNOTATION); + COMMON_LOGGER("Can't Write SD Card!!\n"); + } + + } + } + else + { + error = true; + operationMessage.push_back(::std::string("Insert SD Card!!")); + } + } + else + { + error = true; + operationMessage.push_back(::std::string("Can't Read IVS!!")); + } + + // ACアダプタが必要か? + if (NeedsAcAdateper()) + { + error = true; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // エラーが無ければ進行用メッセージ表示 + if(!error) + { + operationMessage.push_back(::std::string("Push A or START Button")); + } + + if (nextStep && !error) + { + COMMON_LOGGER("Start Export Data\n"); + s_BackupState = IN_PROGRESS; + common::PlaySound(common::SOUND_CURSOR); + } + } + break; + + // 吸出し中 + case IN_PROGRESS: + { + continueBackup = true; + + // ACアダプタが必要か? + if (NeedsAcAdateper()) + { + continueBackup = false; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // データを書き込む + ExportData(); + + // 処理が完了した + if (continueBackup && IsExportFinished()) + { + FinalizeExportThread(); + COMMON_LOGGER("Export NAND Data Finished.\n"); + + if(GetProgress() > 99) + { + s_BackupState = DONE; + } + else + { + s_BackupState = FAIL; + } + + } + } + break; + + // 吸出し完了 + case DONE: + { + operationMessage.push_back(::std::string("Backup Done. Pull Out SD Card.")); + } + break; + + // SDカード抜き完了 + case FINISHED: + { + operationMessage.push_back(::std::string("Backup Succeeded!!\n")); + if(!s_PlayedFinishedSound) + { + common::PlaySound(common::SOUND_OK); + s_PlayedFinishedSound = true; + } + } + break; + + // 吸出し失敗 + case FAIL: + { + operationMessage.push_back(::std::string("Backup Failed.")); + if(!s_PlayedFailSound) + { + common::PlaySound(common::SOUND_NG); + s_PlayedFailSound = true; + } + } + break; + + } +} + +bool InProgress() +{ + return s_BackupState == IN_PROGRESS; +} + +bool IsBackupSucceeded() +{ + return s_BackupState == FINISHED; +} + +bool IsBackupFailed() +{ + return s_BackupState == FAIL; +} + +void OnSdEjected() +{ + if(s_BackupState == DONE || s_BackupState == FINISHED) + { + s_BackupState = FINISHED; + } + else + { + InitializeState(); + } +} + +void InitializeState() +{ + s_BackupState = STARTUP; + s_PlayedFailSound = false; + s_PlayedFinishedSound = false; +} + +} // namespace ConsoleBackup diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/Controller.h b/trunk/ConsoleDataMigration/ConsoleBackup/Controller.h new file mode 100644 index 0000000..d7f2cbf --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleBackup/Controller.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------* + 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 +#include + +namespace ConsoleBackup +{ + +void ControlState(::std::vector& operationMessage, bool& nextStep, bool& continueBackup); +bool InProgress(); +bool IsBackupSucceeded(); +bool IsBackupFailed(); +void OnSdEjected(); +void InitializeState(); + +} + +#endif /* CONTOROLLER_H_ */ diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/Exporter.cpp b/trunk/ConsoleDataMigration/ConsoleBackup/Exporter.cpp new file mode 100644 index 0000000..0495cef --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleBackup/Exporter.cpp @@ -0,0 +1,414 @@ +/*---------------------------------------------------------------------------* + 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 +#include +#include +#include +#include +#include +#include +#include // cfg:norの初期化に必要 +#include +#include +#include +#include + +#include "Exporter.h" +#include "CommonLogger.h" +#include "SDMountManager.h" +#include "ConsoleBackup.h" +#include "HeapManager.h" +#include "SdReaderWriter.h" +#include "FileName.h" +#include "FileTransfer.h" +#include "common_Types.h" +#include "Aes_define.h" + +namespace ConsoleBackup +{ + +namespace +{ + +common::SdReaderWriter s_SdWriter; +common::NtrNorData s_NtrNorData; + +::std::string s_SysSaveRoot; + +const size_t EXPORT_THREAD_STACK_SIZE = 0x4000; +nn::os::Thread s_ExportThread; +nn::os::StackBuffer s_ExportThreadStack; + +wchar_t s_RootName[256]; + +bool s_IsExportThreadFinished = false; + +} + +void DeleteTrash() +{ + // TODO: リードオンリーのファイルが消去できない + + COMMON_LOGGER("Delete Trash.\n"); + + std::wstring currentDirectory = common::SDMC_ROOT_DIRECTORY_PATH; + nn::fs::FileInputStream fis; + nn::fs::Directory dir; + nn::Result result; + std::vector entryList; //カレントディレクトリのエントリ一覧を格納 + std::vector::iterator entryIndex; + + common::SdMountManager::Mount(); + + result = dir.TryInitialize(currentDirectory.c_str()); + + if (result.IsSuccess()) + { + nn::fs::DirectoryEntry entry; + s32 numEntry; + for (;;) + { + result = dir.TryRead(&numEntry, &entry, 1); + if (result.IsFailure()) + { + dir.Finalize(); + } + 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()); + if(result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + } + // ファイルならログとAP設定以外は削除する + else + { + if (std::wcscmp(entryIndex->entryName, common::AP_SETTING_FILENAME) != 0 && std::wcscmp( + entryIndex->entryName, common::Logger::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()); + if(result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + } + } + } + + // 削除完了 + 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); + } + } + } + } + else + { + NN_LOG("failed initialize directory\n"); + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + dir.Finalize(); + } + + common::SdMountManager::Unmount(); +} + +void WriteNorData() +{ + COMMON_LOGGER("Export NOR Data.\n"); + + nn::Result result; + + nn::cfg::nor::CTR::Initialize(); + + NN_LOG("Get NTR User Setting\n"); + + // ユーザカラー + result = nn::cfg::nor::CTR::GetUserColor(&s_NtrNorData.userColor); + if (result.IsSuccess()) + { + NN_LOG("NTR User Color = %d\n", s_NtrNorData.userColor); + } + else + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + // コメント + result = nn::cfg::nor::CTR::GetComment(&s_NtrNorData.comment); + if (result.IsSuccess()) + { + NN_LOG("NTR User Comment = %ls\n", s_NtrNorData.comment.buffer); + } + else + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + // TWL WiFi設定 + result = nn::cfg::nor::CTR::ReadTwlWifiSetting(0, s_NtrNorData.TwlWiFiSetting, common::TWL_WIFI_SETTING_SIZE); + if(result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + // NTR WiFi設定 + result = nn::cfg::nor::CTR::ReadNtrWifiSetting(0, s_NtrNorData.NtrWiFiSetting, common::NTR_WIFI_SETTING_SIZE); + if(result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + s_SdWriter.WriteBuf(common::NOR_PATHNAME, &s_NtrNorData, sizeof(common::NtrNorData)); +} + +void WriteSerialNumber() +{ + COMMON_LOGGER("Export Serial Number.\n"); + + u8* serial; + size_t size; + GetSerialNumber(&serial, &size); + + s_SdWriter.WriteBuf(common::SERIAL_PATHNAME, serial, size); +} + +void WriteIvs() +{ + COMMON_LOGGER("Export IVS.\n"); + + bit8 iv[AES_BLOCK_SIZE] = + { + 0xdf, 0x0f, 0xf9, 0x1b, 0x34, 0x47, 0x70, 0x7f, + 0x7d, 0x06, 0x85, 0xe6, 0xe7, 0xb6, 0x4e, 0xe9 + }; + + void* ivs; + size_t size; + GetIvs(&ivs, &size); + + void* enc; + nn::Result result; + enc = common::HeapManager::GetHeap()->Allocate(size); + if(enc != NULL) + { + // AES暗号化する + nn::crypto::Initialize(); + + nn::crypto::SwAesCtrContext swAesCtrContest; + + swAesCtrContest.Initialize(iv, common::key, sizeof(common::key)); + swAesCtrContest.Encrypt(enc, ivs, size); + + s_SdWriter.WriteBuf(common::IVS_PATHNAME, enc, size); + + common::HeapManager::GetHeap()->Free(enc); + } +} + +// IVSからセーブデータディレクトリ名を生成する +void GetSaveDataDirectoryRoot() +{ + nn::Result result; + using namespace nn::dbg; + + const size_t SEED_SIZE = 16; + bit8 hash[nn::crypto::Sha256Context::HASH_SIZE]; + const size_t SYS_SAVE_ROOT_LENGTH = 16; + char rootHash[SYS_SAVE_ROOT_LENGTH]; + char rootStr[SYS_SAVE_ROOT_LENGTH * 2 + 1]; + + void* addr; + size_t size; + GetIvs(&addr, &size); + + // 最後の16バイトのハッシュを使う + nn::crypto::CalculateSha256(hash, &reinterpret_cast (addr)[size - SEED_SIZE], SEED_SIZE); + + for (u8 i = 0; i < SEED_SIZE / 4; i++) + { + for (u8 j = 0; j < SEED_SIZE / 4; j++) + { + rootHash[i * 4 + j] = hash[i * 4 + 3 - j]; + } + } + + // 得られたハッシュから文字列を生成 + for (s32 k = 0; k < SEED_SIZE; k++) + { + for (s32 i = 6; i < 8; ++i) + { + bit32 n = (rootHash[k] >> ((7 - i) * 4)) & 0xf; + NN_TASSERT_(0 <= n && n < 16); + rootStr[i - 6 + k * 2] = static_cast (n < 10 ? '0' + n : 'a' + (n - 10)); + } + } + rootStr[SYS_SAVE_ROOT_LENGTH * 2] = '\0'; + + // セーブデータディレクトリ名を保存する + s_SysSaveRoot = ::std::string(rootStr); + + NN_LOG("%s\n", s_SysSaveRoot.c_str()); +} + + +void ExportThreadFunc() +{ + nn::Result result; + + s_IsExportThreadFinished = false; + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + if(result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + result = common::SdMountManager::Mount(); + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + NN_LOG("AllocatableSize = %d\n", bufSize); + + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if (buf != NULL) + { + + common::CopyDirectory( + (::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str(), + (common::SDMC_ROOT_DIRECTORY_PATH + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str(), + buf, bufSize); + + common::HeapManager::GetHeap()->Free(buf); + } + + common::SdMountManager::Unmount(); + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + + NN_LOG("Export Thread Finalize\n"); + s_IsExportThreadFinished = true; +} + +nn::Result WriteSaveData() +{ + // NANDからSDカードに書き出し + nn::Result result; + + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + if(result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + return result; + } + + u32 fileNum = 0; + u32 fileSize = 0; + common::CalculateFileNum(::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH), fileNum, fileSize); + + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + + NN_LOG("File Number = %d\n", fileNum); + NN_LOG("File Size = %d\n", fileSize); + // 進捗表示用 + common::SetTotalSize(fileSize); + + ::std::mbstowcs(s_RootName, s_SysSaveRoot.c_str(), s_SysSaveRoot.size() + 1); + + NN_LOG("%ls\n", (::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str()); + + // セーブデータディレクトリ以下のデータをSDカードにコピー + // コピー用ディレクトリ作成 + COMMON_LOGGER("Create Backup Directory.\n"); + s_SdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( + common::SD_SAVEDATA_ROOT_NAME)).c_str()); + s_SdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( + common::SD_SAVEDATA_ROOT_NAME) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str()); + + COMMON_LOGGER("Export NAND Data Start...\n"); + + // SDにコピーするためのスレッドの作成 + s_ExportThread.Start(ExportThreadFunc, s_ExportThreadStack); + + return result; +} + +void FinalizeExportThread() +{ + s_ExportThread.Join(); +} + +void ExportData() +{ + static bool init = true; + + if (init) + { + // 不要なデータを削除する + DeleteTrash(); + + // NORデータをSDカードに書き込む + WriteNorData(); + + // シリアルナンバーをSDカードに書き込む + WriteSerialNumber(); + + // 完全性検証SEEDをSDカードに書き込む + WriteIvs(); + + // IVSからセーブデータディレクトリ名を計算 + GetSaveDataDirectoryRoot(); + + // NANDのセーブデータをSDに書き出す + WriteSaveData(); + + init = false; + } +} + +u32 GetProgress() +{ + return common::GetProgress(); +} + +bool IsExportFinished() +{ + return s_IsExportThreadFinished; +} + +} diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/Exporter.h b/trunk/ConsoleDataMigration/ConsoleBackup/Exporter.h new file mode 100644 index 0000000..b102d0b --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleBackup/Exporter.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------* + 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 + +namespace ConsoleBackup +{ + + +void ExportData(); + +u32 GetProgress(); +bool IsExportFinished(); +void FinalizeExportThread(); + + +} + +#endif /* EXPORTER_H_ */ diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/OMakefile b/trunk/ConsoleDataMigration/ConsoleBackup/OMakefile new file mode 100644 index 0000000..9695fff --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleBackup/OMakefile @@ -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.* +#MAKECSU = true +#INSTALL_SDK_TOOL = true +CTR_APPTYPE = BOTH +CTR_MAKE_DEVELOPMENT_IMAGE = true + +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 + ../common/FileTransfer.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 + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +ROMFS_ROOT = ../common/romfiles + +LIBS += libnn_cfg \ + libnn_driversEeprom \ + libnn_driversi2c \ + libnn_driversCal \ + libnn_crypto \ + libnn_driversCodec \ + libnn_spi \ + libnn_gpio \ + libnn_pdn \ + libnn_mcu \ + libnn_i2c \ + libnn_driversCamera \ + libnn_ps \ + libnn_driversRsa \ + lib_demo \ + libnn_nwm \ + libnn_friends \ + +INSTALL_SDK_TOOL = true + +ROM_SPEC_FILE = $(TARGET_PROGRAM).rsf +DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/_private/RepairTool.desc + +include $(ROOT_OMAKE)/modulerules + +VERSION_H = $(file version.h) + +$(VERSION_H): $(SOURCES) + section + bash genversion.sh + +RequireSetup($(VERSION_H)) +build: $(VERSION_H) $(DEFAULT_TARGETS) diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/banner/big.ctpk b/trunk/ConsoleDataMigration/ConsoleBackup/banner/big.ctpk new file mode 100644 index 0000000..80d0235 Binary files /dev/null and b/trunk/ConsoleDataMigration/ConsoleBackup/banner/big.ctpk differ diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/banner/little.ctpk b/trunk/ConsoleDataMigration/ConsoleBackup/banner/little.ctpk new file mode 100644 index 0000000..124c063 Binary files /dev/null and b/trunk/ConsoleDataMigration/ConsoleBackup/banner/little.ctpk differ diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/banner/model.cbmd b/trunk/ConsoleDataMigration/ConsoleBackup/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/trunk/ConsoleDataMigration/ConsoleBackup/banner/model.cbmd differ diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/banner/sound.cbsd b/trunk/ConsoleDataMigration/ConsoleBackup/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/trunk/ConsoleDataMigration/ConsoleBackup/banner/sound.cbsd differ diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/genversion.sh b/trunk/ConsoleDataMigration/ConsoleBackup/genversion.sh new file mode 100755 index 0000000..180bd87 --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleBackup/genversion.sh @@ -0,0 +1,3 @@ +#!/bin/bash -f + +echo "#define BACKUP_VERSION_NUM \"`svnversion -n`\"" > version.h diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.bsf b/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.bsf new file mode 100644 index 0000000..7fba40c Binary files /dev/null and b/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.bsf differ diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.cpp b/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.cpp new file mode 100644 index 0000000..9bd511c --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.cpp @@ -0,0 +1,450 @@ +/*---------------------------------------------------------------------------* + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "demo.h" + +#include +#include + +#include "ConsoleRestore.h" +#include "Controller.h" +#include "SimplePlayer.h" +#include "CommonLogger.h" +#include "SDMountManager.h" +#include "HeapManager.h" + +// svnリビジョン埋め込み用 +#include "version.h" +#ifndef RESTORE_VERSION_NUM +#define RESOTRE_VERSION_NUM 0 +#endif + +namespace { + +// グラフィックスに割り当てるメモリ +const size_t s_GxHeapSize = 0x800000; + +demo::RenderSystemDrawing s_RenderSystem; +nn::Handle mcuSession; + +const u16 PROGRESS_MAX_LINES = 160; + +// バッテリ残量 +u8 batteryRemain = 100; + +// シリアルナンバー +u8 s_SerialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + +// シリアルナンバーが読めるかどうか +bool s_CanReadSerialNumber = false; + +// IVSへのポインタ +void* sp_Ivs; + +size_t s_SizeofIvs; + +// IVSが読めるかどうか +bool s_CanReadIvs = false; + + +} // namespace + +namespace ConsoleRestore{ + +u32 GetRenderTarget(u32 target, bool flip = false); + +bool IsAdapterConnected() +{ + return nn::ptm::CTR::GetAdapterState() == nn::ptm::CTR::ADAPTERSTATE_CONNECTED; +} + +bool IsBatteryLower() +{ + return batteryRemain <= 10; +} + +bool CanReadIVS() +{ + return s_CanReadIvs; +} + +bool CanReadSerialNumber() +{ + return s_CanReadSerialNumber; +} + +void GetSerialNumber(u8** serial, size_t* size) +{ + *serial = s_SerialNo; + *size = nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN; +} + +void GetIvs(void** ivs, size_t* size) +{ + *ivs = sp_Ivs; + *size = s_SizeofIvs; +} + +u32 GetRenderTarget(u32 target, bool flip) +{ + if(flip) + { + if(target == NN_GX_DISPLAY0) + { + return NN_GX_DISPLAY1; + } + else + { + return NN_GX_DISPLAY0; + } + } + else + { + return target; + } +} + +void FinalizeAll() +{ + common::Logger::GetLoggerInstance()->Finalize(); + // アンマウント + nn::fs::Unmount("nand:"); + nn::fs::Unmount("sdmc:"); + s_RenderSystem.Finalize(); + + nn::mcu::CTR::FinalizeHwCheck(&mcuSession); + nn::friends::detail::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(); +} + +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(); + NN_UTIL_PANIC_IF_FAILED(result); + + // cfg の初期化 + nn::cfg::CTR::init::Initialize(); + nn::cfg::CTR::system::Initialize(); + + // 時計設定用ptm初期化 + nn::ptm::CTR::InitializeForSystemMenu(); + + // ps の初期化 + nn::ps::Initialize(); + + // friendsの初期化 + result = nn::friends::detail::Initialize(); + + // mcuの初期化 + nn::mcu::CTR::InitializeHwCheck(&mcuSession); + + nn::mcu::CTR::HwCheck mcu(mcuSession); + + // amの初期化 + nn::am::InitializeForSystemMenu(); + + // ヒープの確保 + common::HeapManager::GetHeap()->Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + // RenderSystem の準備 + uptr heapForGx = reinterpret_cast(common::HeapManager::GetHeap()->Allocate(s_GxHeapSize)); + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + + // サウンドスレッドの起動 + common::InitializeSimplePlayer(); + + // ログ描画の初期化 + common::Logger::GetLoggerInstance()->Initialize(CONSOLE_WIDTH, CONSOLE_HEIGHT, CONSOLE_MAX_LINE, &s_RenderSystem); + + // RenderSystemを作ってからログが出せる + common::Logger::InitializeEjectThread(); + common::Logger::SetEjectHandler(OnSdEjected); + COMMON_LOGGER("\n"); + COMMON_LOGGER("CTR Console Restore start\n"); + + // ボタン入力 + nn::hid::PadReader s_PadReader; + nn::hid::PadStatus padStatus; + + // データの準備 + + // 完全性検証SEEDの取得 + result = nn::fs::MountSpecialArchive("nand:", nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + if (result.IsSuccess()) + { + nn::fs::FileInputStream fis; + + result = fis.TryInitialize(L"nand:/private/movable.sed"); + if (result.IsSuccess()) + { + s64 fileSize = fis.GetSize(); + s32 ret; + void* addr = NULL; + addr = common::HeapManager::GetHeap()->Allocate(fileSize); + if (addr != NULL) + { + sp_Ivs = addr; + s_SizeofIvs = fileSize; + result = fis.TryRead(&ret, addr, fileSize); + if (result.IsSuccess()) + { + s_CanReadIvs = true; + } + } + } + fis.Finalize(); + } + // 一旦アンマウントしておく + nn::fs::Unmount("nand:"); + + // リージョンの取得 + nn::cfg::CTR::CfgRegionCode region; + region = nn::cfg::CTR::GetRegion(); + + // シリアルナンバーの取得 + std::memset(s_SerialNo, '\0', + nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN); + result = nn::cfg::CTR::system::GetSerialNo(s_SerialNo); + if(result.IsSuccess()) + { + s_CanReadSerialNumber = true; + } + common::Logger::GetLoggerInstance()->PrintResultIfFailed(result, __LINE__); + + // デバイスIDの取得 + bit32 deviceId; + result = nn::ps::CTR::GetDeviceId(&deviceId); + common::Logger::GetLoggerInstance()->PrintResultIfFailed(result, __LINE__); + + // MACアドレスの取得 + nn::nwm::Mac mac; + char8 macAddress[nn::nwm::Mac::MAC_STRING_SIZE]; + + result = nn::nwm::GetMacAddress(mac); + common::Logger::GetLoggerInstance()->PrintResultIfFailed(result, __LINE__); + mac.GetString(macAddress); + common::Logger::GetLoggerInstance()->PrintResultIfFailed(result, __LINE__); + + // フレンドコードの取得 + nn::friends::CTR::FriendKey friendKey; + result = nn::friends::CTR::GetMyFriendKey(&friendKey); + common::Logger::GetLoggerInstance()->PrintResultIfFailed(result , __LINE__); + u64 friendCode = nn::friends::CTR::FriendKeyToFriendCode(friendKey); + + // ReadOnlySharedInfoの取得 + const nn::os::ReadOnlySharedInfo& rosi = nn::os::GetReadOnlySharedInfo(); + + + // 情報出力 + COMMON_LOGGER("CTR Console Restore %s Rev.%s\n", __DATE__, RESTORE_VERSION_NUM); + COMMON_LOGGER("System Ver. %d.%d (Rev.%d)\n", rosi.versionHi, rosi.versionLo, rosi.revision); + COMMON_LOGGER("System Region %s\n", nn::cfg::CTR::GetRegionCodeA3(region)); + COMMON_LOGGER("Serial Number %s\n", s_SerialNo); + COMMON_LOGGER("Device ID %X\n", deviceId); + COMMON_LOGGER("MAC Address %s\n", macAddress); + COMMON_LOGGER("Friend Code %04u-%04u-%04u\n", + static_cast(friendCode / 100000000ULL % 10000ULL), + static_cast(friendCode / 10000ULL % 10000ULL), + static_cast(friendCode % 10000ULL) ); + + + bool flip = false; + bool continueRestore = 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; + } + + // 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(); + } + + if(padStatus.hold & nn::hid::BUTTON_LEFT) + { + common::Logger::GetLoggerInstance()->ScrollToBegin(); + } + + if(padStatus.hold & nn::hid::BUTTON_RIGHT) + { + common::Logger::GetLoggerInstance()->ScrollToEnd(); + } + + + // 情報更新 + // バッテリ + mcu.GetBatteryRemain(&batteryRemain); + // ACアダプタ + std::string adapterState; + if(IsAdapterConnected()) + { + adapterState += ::std::string("Connected"); + } + else + { + adapterState += ::std::string("Not Connected"); + } + + // 操作用メッセージ + // 進捗確認メッセージを兼ねる? + ::std::vector operationMessage; + + ControlState(operationMessage, nextStep, continueRestore); + + // デフォルトで上画面に描画するもの + s_RenderSystem.SetRenderTarget(GetRenderTarget(NN_GX_DISPLAY0, flip)); + if(IsRestoreSucceeded()) + { + s_RenderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY0, flip), SUCCESS_COLOR); + } + else if(IsRestoreFailed()) + { + s_RenderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY0, flip), FAIL_COLOR); + } + else + { + s_RenderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY0, flip), NORMAL_COLOR); + } + + s_RenderSystem.Clear(); + s_RenderSystem.SetColor(1.f, 1.f, 1.f); + u32 line = 0; + s_RenderSystem.DrawText(0, line++ * 10, "CTR Console Restore %s Rev.%s", __DATE__, RESTORE_VERSION_NUM); + s_RenderSystem.DrawText(0, line++ * 10, ""); + s_RenderSystem.DrawText(0, line++ * 10, "System Ver. %d.%d (Rev.%d)", rosi.versionHi, rosi.versionLo, rosi.revision); + s_RenderSystem.DrawText(0, line++ * 10, "System Region %s", nn::cfg::CTR::GetRegionCodeA3(region)); + s_RenderSystem.DrawText(0, line++ * 10, "Serial No. %s", s_SerialNo); + s_RenderSystem.DrawText(0, line++ * 10, "Device ID %X", deviceId); + s_RenderSystem.DrawText(0, line++ * 10, "MAC Address %s", macAddress); + s_RenderSystem.DrawText(0, line++ * 10, "Friend Code %04u-%04u-%04u", + static_cast(friendCode / 100000000ULL % 10000ULL), + static_cast(friendCode / 10000ULL % 10000ULL), + static_cast(friendCode % 10000ULL) ); + + s_RenderSystem.DrawText(0, line++ * 10, "Battery %d%%", batteryRemain); + s_RenderSystem.DrawText(0, line++ * 10, "AC Adaper %s", adapterState.c_str()); + s_RenderSystem.DrawText(0, line++ * 10, "Progress %02d%%", GetProgress()); + s_RenderSystem.SetColor(0.f, 0.2f, 0.f); + s_RenderSystem.DrawLine(19 * 8, (line-1) * 10, 19 * 8 + PROGRESS_MAX_LINES, (line-1) * 10); + s_RenderSystem.DrawLine(19 * 8, (line-1) * 10, 19 * 8, (line) * 10); + s_RenderSystem.DrawLine(19 * 8, (line) * 10, 19 * 8 + PROGRESS_MAX_LINES, (line) * 10); + s_RenderSystem.DrawLine(19 * 8 + PROGRESS_MAX_LINES, (line-1) * 10, 19 * 8 + PROGRESS_MAX_LINES, (line) * 10 + 1); + s_RenderSystem.SetColor(0.f, 0.5f, 0.f); + s_RenderSystem.FillRectangle(19 * 8 , (line-1) * 10, GetProgress() * PROGRESS_MAX_LINES / 100+ 1, 10); + + s_RenderSystem.SetColor(1.f, 1.f, 1.f); + s_RenderSystem.DrawText(0, line++ * 10, ""); + + ::std::vector::iterator it; + for(it = operationMessage.begin(); it != operationMessage.end(); it++) + { + s_RenderSystem.DrawText(0, line++ * 10 , "%s", it->c_str()); + } + + s_RenderSystem.SwapBuffers(); + + // デフォルトで下画面に描画するもの + s_RenderSystem.SetRenderTarget(GetRenderTarget(NN_GX_DISPLAY1, flip)); + if(IsRestoreSucceeded()) + { + s_RenderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY1, flip), SUCCESS_COLOR); + } + else if(IsRestoreFailed()) + { + s_RenderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY1, flip), FAIL_COLOR); + } + else + { + s_RenderSystem.SetClearColor(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(); + } + } +} + + +} diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.h b/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.h new file mode 100644 index 0000000..5ed81ea --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.h @@ -0,0 +1,50 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: ConsoleRestore.h + + 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$ + *---------------------------------------------------------------------------*/ + +#ifndef NN_CONSOLERESTORE_H_ +#define NN_CONSOLERESTORE_H_ + +#include + +namespace ConsoleRestore +{ + +bool IsAdapterConnected(); +bool IsBatteryLower(); +bool CanReadIVS(); +bool CanReadSerialNumber(); +void GetSerialNumber(u8** serial, size_t* size); +void GetIvs(void** ivs, size_t* size); + +void FinalizeAll(); + +const u32 CONSOLE_WIDTH = 38; +const u32 CONSOLE_HEIGHT = 24; +const u32 CONSOLE_MAX_LINE = 1000; + +} + +// 描画色の定義 +#define WHITE_COLOR 1.f, 1.f, 1.f, 1.f +#define GRAY_COLOR 0.5, 0.5, 0.5, 1.f +#define RED_COLOR 1.f, 0.f, 0.f, 1.f +#define GREEN_COLOR 0.f, 1.f, 0.f, 1.f +#define BLUE_COLOR 0.f, 0.f, 1.f, 1.f +#define SUCCESS_COLOR 0.f, 0.6f,0.f, 1.f +#define FAIL_COLOR 0.6f, 0.f,0.f, 1.f +#define NORMAL_COLOR 0.f, 0.f, 0.f, 1.f + +/* NN_CONSOLERESTORE_H_ */ +#endif diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.rsf b/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.rsf new file mode 100644 index 0000000..78e3d99 --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.rsf @@ -0,0 +1,52 @@ +BasicInfo: + Title : ConsoleRestore + ProductCode: ConsoleRestore + BackupMemoryType: None + +TitleInfo: + Use: Evaluation + Category: Application + UniqueId: 0xf8007 + Version: 0 + +SystemControlInfo: + AppType : Application + StackSize : 0x4000 + Dependency : + - gpio + - pdn + - spi + - i2c + - mcu + - ptm + - codec + - cfg + - hid + - gsp + - friends + - nim + - ac + - ndm + +AccessControlInfo: + Priority : 16 + DisableDebug : false + + FileSystemAccess: + - DirectSdmc + - Debug + - Core + - CategoryFileSystemTool + + IoAccessControl: + - FsMountCardSpi + - FsMountNand + - FsMountTwln + +Option: + FreeProductCode: true + + +Rom: + # ROM に含めるファイルシステムのルートパスを指定します。 + HostRoot: "$(ROMFS_ROOT)" \ No newline at end of file diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/Controller.cpp b/trunk/ConsoleDataMigration/ConsoleRestore/Controller.cpp new file mode 100644 index 0000000..227709f --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/Controller.cpp @@ -0,0 +1,590 @@ +/*---------------------------------------------------------------------------* + 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 +#include +#include +#include + +#include "Controller.h" +#include "ConsoleRestore.h" +#include "SimplePlayer.h" +#include "CommonLogger.h" +#include "Importer.h" +#include "Updater.h" +#include "NtpClient.h" + +namespace ConsoleRestore +{ + +namespace +{ + +typedef enum RestoreState +{ + STARTUP, // 初期値 + SERIAL_IS_NOT_IN_SD, // シリアルナンバーファイルがSDカードにないことを表示 + SERIAL_IN_SD, // シリアルナンバーの情報を表示 + UPDATE_IN_PROGRESS, // アップデート中 + RESTORE_IN_PROGRESS, // 書き込み中 + POST_RESTORE, // 書き込み後の処理 + RESTORE_DONE, // 書き込み完了 + REBOOTING, // 再起動を行う + ERASE, // 削除処理を行う + TIME_ADJUST, // 時計あわせを行う + WAIT_SD_EJECT, // SDカードぬき待ち + ALL_DONE, // すべて完了 + FAIL // 失敗 +} RestoreState; + + +// Restore状態管理 +RestoreState s_RestoreState = STARTUP; + +// インターネット設定を読んだかどうか +bool s_ReadSettingDone = false; +// インターネット設定を読んだ結果 +bool s_ReadSettingSuccess = false; + +// APSettingの書式が無い警告サウンドを鳴らしたかどうか +bool s_ExistAPSettingAnnotation = false; +// APSettingの書式が違っている警告サウンドを鳴らしたかどうか +bool s_APSettingAnnotation = false; +// シリアルナンバーがない警告サウンドを鳴らしたかどうか +bool s_SerialNumberAnnotation = false; +// 失敗サウンドを鳴らしたかどうか +bool s_PlayedFailSound = false; + +// ネットワークアップデートを開始したかどうか +bool s_ExecuteFgNup = false; +// FGNUPを何回リトライしたか +u32 s_FgNupRetryCount = 0; + + +} // namespace + +bool NeedsAcAdater() +{ + return IsBatteryLower() && !IsAdapterConnected(); +} + +bool CheckAndReadAPSetting(::std::vector& operationMessage) +{ + if (!ExistsAPSetting()) + { + if(!s_ExistAPSettingAnnotation) + { + s_ExistAPSettingAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + operationMessage.push_back(::std::string("APSetting.txt does not exist!")); + return false; + } + + // 設定ファイルからAP設定を読み込む + if (!s_ReadSettingDone) + { + s_ReadSettingDone = true; + s_ReadSettingSuccess = ReadSetting(); + } + + if (!s_ReadSettingSuccess) + { + operationMessage.push_back(::std::string("Invalid APSetting.txt format!")); + if(!s_APSettingAnnotation) + { + s_APSettingAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + + } + + return s_ReadSettingSuccess; +} + +void ControlState(::std::vector& operationMessage, bool& nextStep, bool& continueRestore) +{ + // 状態遷移Controller + switch (s_RestoreState) + { + // 起動時 + case STARTUP: + { + bool error = false; + bool needsUpdate = false; + bool needsErase = false; + + // SDカードが挿入されているか? + if (nn::fs::IsSdmcInserted()) + { + // SDカードにアップデート完了ファイルがあるか? + if (ExistsUpdateCheckedFile()) + { + // SDカードに書き込み完了ファイルがあるか? + if (!ExistsWriteFinishedFile()) + { + // IVSを読めるか? + if (CanReadIVS()) + { + // 本体初期化完了ファイルがあるか? + if (ExistsConsoleInitializedFile()) + { + // SDカードにシリアルナンバーがあるか? + if (!ExistsSerialNumberFile()) + { + COMMON_LOGGER("Can't Read Serial Number in SD Card!!\n"); + error = true; + s_RestoreState = SERIAL_IS_NOT_IN_SD; + } + else + { + ::std::string serial(reinterpret_cast (ReadSerialNumber())); + operationMessage.push_back(::std::string("Serial Number in SD : ") + serial); + } + + // SDカードにIVSがあるか? + if (!ExistsIVSFile()) + { + // 移行不能なのでFAIL + COMMON_LOGGER("Can't Read IVS in SD Card!!\n"); + error = true; + s_RestoreState = FAIL; + } + else + { + // SDカードのIVSと本体のIVSは異なるか? + if (EqualsIVSFileandIVS()) + { + COMMON_LOGGER("Restore data to the same Console. Initialize.\n"); + // 本体初期化を行う + nn::fs::InitializeCtrFileSystem(); + error = true; + s_RestoreState = REBOOTING; + } + + // SDカードに書き込みできるか? + if (nextStep && !nn::fs::IsSdmcWritable()) + { + error = true; + common::PlaySound(common::SOUND_ANNOTATION); + COMMON_LOGGER("Can't Write SD Card!!\n"); + } + } + } + else + { + COMMON_LOGGER("Initialize Console\n"); + // 本体初期化完了ファイルを作る + CreateConsoleInitializedFile(); + + // 本体初期化を行う + nn::fs::InitializeCtrFileSystem(); + error = true; + s_RestoreState = REBOOTING; + } + } + else + { + error = true; + operationMessage.push_back(::std::string("Can't Read IVS!!")); + } + } + else + { + if(CheckAndReadAPSetting(operationMessage)) + { + // 削除処理を行う + needsErase = true; + } + else + { + error = true; + } + } + } + else + { + if (CheckAndReadAPSetting(operationMessage)) + { + // ネットワークアップデートを行う + needsUpdate = true; + } + else + { + error = true; + } + } + } + else + { + error = true; + operationMessage.push_back(::std::string("Insert SD Card!!")); + } + + // ACアダプタが必要か? + if (NeedsAcAdater()) + { + error = true; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // エラーが無ければ進行用メッセージ表示 + if (!error) + { + operationMessage.push_back(::std::string("Push A or START Button")); + if(needsUpdate) + { + operationMessage.push_back(::std::string("Network Update Mode")); + } + else if(needsErase) + { + operationMessage.push_back(::std::string("Clock Sync Mode")); + } + else + { + operationMessage.push_back(::std::string("Import Data Mode")); + } + } + + if (nextStep && !error) + { + if (needsUpdate) + { + COMMON_LOGGER("Start Network Update\n"); + s_RestoreState = UPDATE_IN_PROGRESS; + common::PlaySound(common::SOUND_CURSOR); + } + else if(needsErase) + { + COMMON_LOGGER("Erase Trash\n"); + s_RestoreState = ERASE; + common::PlaySound(common::SOUND_CURSOR); + } + else + { + COMMON_LOGGER("Start Import Data\n"); + s_RestoreState = RESTORE_IN_PROGRESS; + common::PlaySound(common::SOUND_CURSOR); + } + } + } + break; + + // シリアルナンバーがSDカードにないこと警告 + case SERIAL_IS_NOT_IN_SD: + { + operationMessage.push_back(::std::string("Serial Number Is Not In SD Card")); + operationMessage.push_back(::std::string("Push A or START Button")); + operationMessage.push_back(::std::string("Import Data Mode")); + + if (!s_SerialNumberAnnotation) + { + s_SerialNumberAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + + if (nextStep) + { + s_RestoreState = RESTORE_IN_PROGRESS; + } + } + break; + + // アップデート中 + case UPDATE_IN_PROGRESS: + { + continueRestore = true; + + // ACアダプタが必要か? + if (NeedsAcAdater()) + { + continueRestore = false; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // アップデートを行う + if(!s_ExecuteFgNup) + { + StartFGNetworkUpdate(); + s_ExecuteFgNup = true; + } + + // 動いていることを表示 + { + static u8 i = 0; + if( i < 0xff / 4) + { + operationMessage.push_back(::std::string("Updating /")); + } + else if(i < 0xff * 2 / 4) + { + operationMessage.push_back(::std::string("Updating |")); + } + else if(i < 0xff * 3 / 4) + { + operationMessage.push_back(::std::string("Updating \\")); + } + else + { + operationMessage.push_back(::std::string("Updating -")); + } + i++; + } + + + if (IsNetworkUpdateFinished()) + { + FinishFGNetworkUpdate(); + if (GetUpdateResult().IsSuccess()) + { + COMMON_LOGGER("Network Update Finished.\n"); + // アップデート完了ファイルを作成 + CreateUpdateFinishedFile(); + + // リブートする + s_RestoreState = REBOOTING; + } + else + { + if (s_FgNupRetryCount++ < RETRY_MAX) + { + // エラーのためやり直す + COMMON_LOGGER_RESULT(GetUpdateResult()); + COMMON_LOGGER("Network Update Failed. Retrying... %d\n", s_FgNupRetryCount); + + // FGNUP用のスレッドを作るとこからやり直し + s_ExecuteFgNup = false; + } + else + { + s_RestoreState = FAIL; + } + } + + } + } + break; + + // 書き込み中 + case RESTORE_IN_PROGRESS: + { + continueRestore = true; + + // ACアダプタが必要か? + if (NeedsAcAdater()) + { + continueRestore = false; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // データを読み込む + ImportData(); + + // 処理が完了した + if (continueRestore && IsImportFinished()) + { + COMMON_LOGGER("Import NAND Data Finished.\n"); + + if (GetProgress() > 99) + { + s_RestoreState = POST_RESTORE; + } + else + { + s_RestoreState = FAIL; + } + + } + } + break; + + // リブート中 + case REBOOTING: + { + static bool init = true; + + if (init) + { + // ErrDispから引用 + // 権限をもらえば成功するはず + nn::Result result = nn::ns::CTR::InitializeForShell(); + if (result.IsSuccess()) + { + COMMON_LOGGER("System Reboot.\n"); + + nn::ns::CTR::HardwareResetAsync(nn::CTR::MEMORY_ARRANGE_NORMAL); + while (!nn::applet::IsExpectedToCloseApplication()) + { + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(5)); + } + + nn::ns::CTR::FinalizeForShell(); + + // INFO: リブートは非同期のため処理は継続 + } + init = false; + } + } + break; + + // 書き込み後の処理 + case POST_RESTORE: + { + operationMessage.push_back(::std::string("Post Process...")); + // 書き込み完了ファイルを作成 + CreateWriteFinishedFile(); + + s_RestoreState = RESTORE_DONE; + } + break; + + // 書き込み完了 + case RESTORE_DONE: + { + operationMessage.push_back(::std::string("Restore Done.")); + operationMessage.push_back(::std::string("Press A or START Button to Reboot")); + + if (nextStep) + { + s_RestoreState = REBOOTING; + } + } + break; + + // 削除処理 + case ERASE: + { + Cleanup(); + s_RestoreState = TIME_ADJUST; + } + break; + + // 時計あわせ + case TIME_ADJUST: + { + static bool init = true; + if(init) + { + COMMON_LOGGER("Adjust Time\n"); + AdjustTime(); + init = false; + } + if(IsTimeAdjustFinished()) + { + s_RestoreState = WAIT_SD_EJECT; + } + } + break; + + // すべて完了 + case WAIT_SD_EJECT: + { + operationMessage.push_back(::std::string("ALL Done. Pull Out SD Card.")); + // SDカード抜けのみで次の状態に遷移する + + } + break; + + // すべて完了 + case ALL_DONE: + { + operationMessage.push_back(::std::string("Restore Succeeded!!")); + static bool init = true; + if (init) + { + common::PlaySound(common::SOUND_OK); + init = false; + } + } + break; + + // 書き込み失敗 + case FAIL: + { + operationMessage.push_back(::std::string("Failed.")); + if (!s_PlayedFailSound) + { + common::PlaySound(common::SOUND_NG); + s_PlayedFailSound = true; + } + } + break; + + } +} + +bool InProgress() +{ + return s_RestoreState == RESTORE_IN_PROGRESS; +} + +bool IsRestoreSucceeded() +{ + return s_RestoreState == ALL_DONE; +} + +bool IsRestoreFailed() +{ + return s_RestoreState == FAIL; +} + +void OnSdEjected() +{ + if(s_RestoreState == WAIT_SD_EJECT || s_RestoreState == ALL_DONE) + { + s_RestoreState = ALL_DONE; + } + else + { + InitializeState(); + } +} + +void InitializeState() +{ + s_RestoreState = STARTUP; + + InitializeFileCheck(); + + s_ExistAPSettingAnnotation = false; + s_ReadSettingDone = false; + s_ReadSettingSuccess = false; + s_APSettingAnnotation = false; + s_SerialNumberAnnotation = false; + s_PlayedFailSound = false; + s_ExecuteFgNup = false; + s_FgNupRetryCount = 0; +} + +u32 GetProgress() +{ + if(s_RestoreState == RESTORE_IN_PROGRESS || + s_RestoreState == POST_RESTORE || + s_RestoreState == RESTORE_DONE) + { + return GetImportProgress(); + } + else if(s_RestoreState == UPDATE_IN_PROGRESS) + { + return GetUpdateProgress(); + } + else + { + return 0; + } + +} + +} // namespace ConsoleRestore diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/Controller.h b/trunk/ConsoleDataMigration/ConsoleRestore/Controller.h new file mode 100644 index 0000000..3648c2e --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/Controller.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------------------------* + 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 +#include +#include + +namespace ConsoleRestore +{ + +const u32 RETRY_MAX = 10; + +void ControlState(::std::vector& operationMessage, bool& nextStep, bool& continueRestore); +bool InProgress(); +bool IsRestoreSucceeded(); +bool IsRestoreFailed(); +u32 GetProgress(); + +void OnSdEjected(); +void InitializeState(); + +} + +#endif /* CONTOROLLER_H_ */ diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/Importer.cpp b/trunk/ConsoleDataMigration/ConsoleRestore/Importer.cpp new file mode 100644 index 0000000..2292f9a --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/Importer.cpp @@ -0,0 +1,1030 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Importer.cpp + + Copyright 2009 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include // cfg:norの初期化に必要 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FileName.h" +#include "Importer.h" +#include "SdMountManager.h" +#include "ConsoleRestore.h" +#include "HeapManager.h" +#include "SdReaderWriter.h" +#include "CommonLogger.h" +#include "FileTransfer.h" +#include "common_Types.h" +#include "Aes_define.h" +#include "configLoader.h" + +#include +#include + +namespace ConsoleRestore +{ +namespace +{ +const size_t IMPORT_THREAD_STACK_SIZE = 0x4000; +nn::os::Thread s_ImportThread; +nn::os::StackBuffer s_ImportThreadStack; + +bool s_IsImportThreadFinished = false; +const size_t TIME_ZONE_LENGTH = 9; // "+23:45" +char s_TimeZoneStr[TIME_ZONE_LENGTH]; + +TimeZone s_TimeZone; +const size_t NTP_SERVER_NAME_LENGTH = 256; +char s_NtpServerName[NTP_SERVER_NAME_LENGTH]; + +// ファイルの存在確認 +bool CheckFileExists(const wchar_t* path); + +bool s_FileExistsChecked[EXISTS_MAX]; +bool s_FileExistsCheckeResult[EXISTS_MAX]; + +bool s_CheckedEqualsIVSFileandIVS = false; +bool s_ReadSerialNumber = false; + +// シリアルナンバー +u8 s_SerialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + +// 空のファイルを作成する +bool CreateEmptyFile(const wchar_t* path); +// SDからNANDにセーブデータをコピーする +void ImportSaveData(); +// SDからNORにNORデータをコピーする +void ImportNorData(); + +// IVS復号化用IV +bit8 s_IvsDecryptIv[AES_BLOCK_SIZE] = +{ + 0xdf, 0x0f, 0xf9, 0x1b, 0x34, 0x47, 0x70, 0x7f, + 0x7d, 0x06, 0x85, 0xe6, 0xe7, 0xb6, 0x4e, 0xe9 +}; + +} + +void ConvertTimeZoneString(const char* str) +{ + s_TimeZone.hour = 0; + s_TimeZone.minutes = 0; + s_TimeZone.isMinus = false; + + bool hour = true; + bool ten = true; + u32 count = 0; + for(u32 i = 0; i < TIME_ZONE_LENGTH && count < 2; i++) + { + switch (str[i]) + { + case ':': + { + hour = false; + } + break; + + case '"': + { + // 2回読んだら終了 + count++; + } + break; + + case '+': + { + s_TimeZone.isMinus = false; + } + break; + + case '-': + { + s_TimeZone.isMinus = true; + } + break; + + default: + { + if(hour) + { + if(ten) + { + s_TimeZone.hour += (str[i] - '0') * 10; + ten = false; + } + else + { + s_TimeZone.hour += str[i] - '0'; + ten = true; + } + } + else + { + if(ten) + { + s_TimeZone.minutes += (str[i] - '0') * 10; + ten = false; + } + else + { + s_TimeZone.minutes += str[i] - '0'; + ten = true; + } + } + } + break; + } + } + + + NN_LOG("Converted TimeZone = "); + if(s_TimeZone.isMinus) + { + NN_LOG("-"); + } + NN_LOG("%02d:%02d\n", s_TimeZone.hour, s_TimeZone.minutes); + +} + +namespace +{ + +bool CheckFileExists(const wchar_t* path) +{ + nn::Result result; + bool exist = false; + result = common::SdMountManager::Mount(); + + if (result.IsSuccess()) + { + nn::fs::FileInputStream fis; + + result = fis.TryInitialize(path); + if(result.IsSuccess()) + { + exist = true; + } + fis.Finalize(); + } + + common::SdMountManager::Unmount(); + + + return exist; +} + +bool CreateEmptyFile(const wchar_t* path) +{ + nn::Result result; + bool create = false; + result = common::SdMountManager::Mount(); + + if (result.IsSuccess()) + { + nn::fs::FileOutputStream fos; + + result = fos.TryInitialize(path, true); + if(result.IsSuccess()) + { + fos.TryFlush(); + create = true; + } + fos.Finalize(); + } + + common::SdMountManager::Unmount(); + + return create; +} + +bool ExistsFile(FileExistsCheck index) +{ + if(index > EXISTS_MAX) + { + NN_LOG("Invalid File index!!\n"); + return false; + } + + if(s_FileExistsChecked[index]) + { + return s_FileExistsCheckeResult[index]; + } + + s_FileExistsChecked[index] = true; + s_FileExistsCheckeResult[index] = CheckFileExists(FILENAME_TABLE[index]); + return s_FileExistsCheckeResult[index]; +} + +} + +bool ExistsUpdateCheckedFile() +{ + return ExistsFile(EXISTS_UPDATE_FINISHED); +} + +bool ExistsSerialNumberFile() +{ + return ExistsFile(EXISTS_SERIAL_NUMBER); +} + +bool ExistsIVSFile() +{ + return ExistsFile(EXISTS_IVS); +} + +void InitializeFileCheck() +{ + for(u32 i = 0; i < EXISTS_MAX; i++) + { + s_FileExistsChecked[i] = false; + } + + s_CheckedEqualsIVSFileandIVS = false; + s_ReadSerialNumber = false; +} + +u8* ReadSerialNumber() +{ + if(s_ReadSerialNumber) + { + return s_SerialNo; + } + + COMMON_LOGGER("Read Serial Number in SD.\n"); + + size_t size; + + common::SdReaderWriter sdReader; + sdReader.ReadBuf(common::SERIAL_PATHNAME, s_SerialNo, nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN, &size); + s_ReadSerialNumber = true; + return s_SerialNo; +} +bool ExistsWriteFinishedFile() +{ + return ExistsFile(EXISTS_WRITE_FINISHED); +} + +bool ExistsAPSetting() +{ + return ExistsFile(EXISTS_AP_SETTING); +} + +bool EqualsIVSFileandIVS() +{ + nn::Result result; + void* ivs; + size_t ivsSize; + size_t readSize; + static bool retval = false; + + if(s_CheckedEqualsIVSFileandIVS) + { + return retval; + } + + COMMON_LOGGER("Check IVS\n"); + + GetIvs(&ivs, &ivsSize); + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize() / 2; + NN_LOG("AllocatableSize = %d\n", bufSize); + + void* enc = common::HeapManager::GetHeap()->Allocate(bufSize); + if (enc != NULL) + { + common::SdReaderWriter sdReader; + + result = sdReader.ReadBuf(common::IVS_PATHNAME, enc, bufSize, &readSize); + if(result.IsSuccess()) + { + void *dec = common::HeapManager::GetHeap()->Allocate(readSize); + if(dec != NULL) + { + // AES復号化する + nn::crypto::Initialize(); + nn::crypto::SwAesCtrContext swAesCtrContest; + + swAesCtrContest.Initialize(s_IvsDecryptIv, common::key, sizeof(common::key)); + swAesCtrContest.Decrypt(dec, enc, readSize); + + NN_LOG("readSize = %d, ivsSize = %d\n", readSize, ivsSize); + // サイズ一致かつ内容一致でtrue + if (readSize == ivsSize && std::memcmp(ivs, dec, ivsSize) == 0) + { + retval = true; + } + + common::HeapManager::GetHeap()->Free(dec); + + } + else + { + NN_LOG("Failed Allocate Heap!! %s, %d", __FILE__, __LINE__); + } + } + else + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + s_CheckedEqualsIVSFileandIVS = true; + common::HeapManager::GetHeap()->Free(enc); + } + else + { + NN_LOG("Failed Allocate Heap!! %s, %d", __FILE__, __LINE__); + return retval; + } + + return retval; +} + +bool ExistsConsoleInitializedFile() +{ + return ExistsFile(EXISTS_CONSOLE_INTIALIZED); +} + +void ImportIvs() +{ + nn::Result result; + nn::fs::FileOutputStream fos; + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize() / 2; + void* enc = common::HeapManager::GetHeap()->Allocate(bufSize); + if (enc != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBuf(common::IVS_PATHNAME, enc, bufSize, &readSize); + if(result.IsSuccess()) + { + // SDから読み出し成功 + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + if (result.IsSuccess()) + { + void *dec = common::HeapManager::GetHeap()->Allocate(readSize); + if (dec != NULL) + { + // AES復号化する + nn::crypto::Initialize(); + nn::crypto::SwAesCtrContext swAesCtrContest; + + swAesCtrContest.Initialize(s_IvsDecryptIv, common::key, sizeof(common::key)); + swAesCtrContest.Decrypt(dec, enc, readSize); + + // IVS書き込み + result = fos.TryInitialize(common::IVS_NAND_PATHNAME, true); + if (result.IsSuccess()) + { + if (result.IsSuccess()) + { + s32 writeSize; + result = fos.TryWrite(&writeSize, dec, readSize, true); + if (result.IsSuccess()) + { + COMMON_LOGGER("Import IVS.\n"); + } + } + } + common::HeapManager::GetHeap()->Free(dec); + } + else + { + COMMON_LOGGER("Failed Allocate Heap!!\n"); + } + + } + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + } + common::HeapManager::GetHeap()->Free(enc); + } + else + { + COMMON_LOGGER("Failed Allocate Heap!!\n"); + } +} + +void ImportThreadFunc() +{ + nn::Result result; + + s_IsImportThreadFinished = false; + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + if(result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + result = common::SdMountManager::Mount(); + if(result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + NN_LOG("AllocatableSize = %d\n", bufSize); + + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if (buf != NULL) + { + + common::CopyDirectory( + (::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME)).c_str(), + common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH, + buf, bufSize); + + common::HeapManager::GetHeap()->Free(buf); + } + + common::SdMountManager::Unmount(); + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + + NN_LOG("Import Thread Finalize\n"); + s_IsImportThreadFinished = true; + +} + +namespace +{ + +void ImportSaveData() +{ + // SDカードからNANDに読み込み + nn::Result result; + + // SDカードにあるセーブデータサイズを計算 + u32 fileNum = 0; + u32 fileSize = 0; + + common::SdMountManager::Mount(); + common::CalculateFileNum(::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME), fileNum, fileSize); + common::SdMountManager::Unmount(); + + // ファイルサイズ設定 + common::SetTotalSize(fileSize); + + NN_LOG("File Number = %d\n", fileNum); + NN_LOG("File Size = %d\n", fileSize); + + // SDカードにあるセーブデータディレクトリ以下のデータをNANDにコピー + COMMON_LOGGER("Import NAND Data Start...\n"); + s_ImportThread.Start(ImportThreadFunc, s_ImportThreadStack); + +} + +void ImportNorData() +{ + COMMON_LOGGER("Import NOR Data.\n"); + + nn::Result result; + + nn::cfg::nor::CTR::Initialize(); + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + NN_LOG("AllocatableSize = %d\n", bufSize); + + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if (buf != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBuf(common::NOR_PATHNAME, buf, bufSize, &readSize); + if(result.IsSuccess()) + { + // cfgを使ってセットする + // ユーザカラー + NN_LOG("user color = %d\n", (reinterpret_cast(buf)->userColor)); + result = nn::cfg::nor::CTR::SetUserColor(reinterpret_cast(buf)->userColor); + if(result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + // コメント + result = nn::cfg::nor::CTR::SetComment(reinterpret_cast(buf)->comment); + if(result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + // TWL WiFi設定 + result = nn::cfg::nor::CTR::WriteTwlWifiSetting(0, reinterpret_cast(buf)->TwlWiFiSetting, + common::TWL_WIFI_SETTING_SIZE); + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + // NTR WiFi設定 + result = nn::cfg::nor::CTR::WriteNtrWifiSetting(0, reinterpret_cast(buf)->NtrWiFiSetting, + common::NTR_WIFI_SETTING_SIZE); + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + } + else + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } + + common::HeapManager::GetHeap()->Free(buf); + } + else + { + COMMON_LOGGER("Failed Allocate Heap!!\n"); + } + +} + +} + + +void Cleanup() +{ + nn::Result result; + bool execCleanup; + + result = nn::am::NeedsCleanup(&execCleanup, nn::fs::MEDIA_TYPE_NAND); + if(result.IsSuccess()) + { + if(execCleanup) + { + COMMON_LOGGER("Cleanup NAND\n"); + nn::am::DoCleanup(nn::fs::MEDIA_TYPE_NAND); + } + } + else + { + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + } +} + +void DeleteConsoleInitializedFile() +{ + nn::Result result; + common::SdMountManager::Mount(); + + result = nn::fs::TryDeleteFile(common::INITIALIZED_CHECK_PATHNAME); + COMMON_LOGGER_RESULT_IF_FAILED(result); + + common::SdMountManager::Unmount(); +} + +bool IsImportFinished() +{ + return s_IsImportThreadFinished; +} + +void CreateWriteFinishedFile() +{ + CreateEmptyFile(common::WRITE_FINISHED_PATHNAME); +} + +void CreateConsoleInitializedFile() +{ + CreateEmptyFile(common::INITIALIZED_CHECK_PATHNAME); +} + +void CreateUpdateFinishedFile() +{ + CreateEmptyFile(common::UPDATE_CHECK_PATHNAME); +} + +u32 GetImportProgress() +{ + return common::GetProgress(); +} + +bool UpdateNetworkSetting(nn::ac::NetworkSetting& networkSetting) +{ + nn::Result result; + bool retval = true; + + result = nn::ac::InitializeInternal(); + if(result.IsFailure()) + { + retval = false; + NN_LOG("Error: nn::ac::InitializeInternal() failed\n"); + } + else + { + //特に入力させる必要のない自動で設定する項目 + networkSetting.wireless.enable = true; + networkSetting.wireless.multiSsid.enable = false; + networkSetting.ip.enableDHCP = true; + networkSetting.scanlessConnect.hasConnected = false; + networkSetting.proxy.enable = false; + networkSetting.other.enableUPnP = false; + + result = nn::ac::UpdateNetworkSetting( 0, networkSetting ); + if(!result.IsSuccess()) + { + retval = false; + NN_LOG("Error: SetNetworkSetting (Update Error)\n"); + } + else + { + result = nn::ac::FlushNetworkSetting(); + if(!result.IsSuccess()) + { + retval = false; + NN_LOG("Error: SetNetworkSetting (Flush Error)\n"); + } + else + { + result = nn::ac::FinalizeInternal(); + if(!result.IsSuccess()) + { + retval = false; + NN_LOG("Error: SetNetworkSetting (Finalize Error)\n"); + } + } + } + } + + return retval; +} + +bool ReadSetting() +{ + nn::Result result; + bool retval = true; + common::ConfigFileLoader configfileLoader; + + common::SdMountManager::Mount(); + size_t size = common::HeapManager::GetHeap()->GetAllocatableSize(); + void* heapAddr = common::HeapManager::GetHeap()->Allocate(size); + + if(heapAddr != NULL) + { + result = configfileLoader.Initialize(common::AP_SETTING_PATHNAME, heapAddr, size); + if (result.IsSuccess()) + { + nn::ac::NetworkSetting networkSetting; + + { + const char* ssid = configfileLoader.ReadAsChar(L"SSID"); // SSID + if(ssid == NULL) + { + COMMON_LOGGER("SSID: is missing\n"); + retval = false; + } + else + { + std::strncpy(reinterpret_cast (networkSetting.wireless.essidSecurity.ssid), ssid, 32); + networkSetting.wireless.essidSecurity.ssidLength = std::strlen(ssid) % 33; + COMMON_LOGGER("SSID = %s\n", networkSetting.wireless.essidSecurity.ssid); + } + } + + + { + const char* mode = configfileLoader.ReadAsChar(L"MODE"); // MODE + if(mode == NULL) + { + COMMON_LOGGER("MODE: is missing\n"); + retval = false; + } + else + { + if (std::strcmp(mode, "OPEN") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::OPEN; + } + else if (std::strcmp(mode, "WEP40") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WEP_40BIT; + } + else if (std::strcmp(mode, "WEP104") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WEP_104BIT; + } + else if (std::strcmp(mode, "WEP128") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WEP_128BIT; + } + else if (std::strcmp(mode, "WPA_TKIP") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WPA_TKIP; + } + else if (std::strcmp(mode, "WPA2_TKIP") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WPA2_TKIP; + } + else if (std::strcmp(mode, "WPA_AES") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WPA_AES; + } + else if (std::strcmp(mode, "WPA2_AES") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WPA2_AES; + } + else + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::OPEN; + } + + switch (networkSetting.wireless.essidSecurity.securityMode) + { + case nn::ac::OPEN: + { + COMMON_LOGGER("MODE = OPEN\n"); + } + break; + + case nn::ac::WEP_40BIT: + { + COMMON_LOGGER("MODE = WEP_40BIT\n"); + } + break; + + case nn::ac::WEP_104BIT: + { + COMMON_LOGGER("MODE = WEP_104BIT\n"); + } + break; + + case nn::ac::WEP_128BIT: + { + COMMON_LOGGER("MODE = WEP_128BIT\n"); + } + break; + + case nn::ac::WPA_TKIP: + { + COMMON_LOGGER("MODE = WPA_TKIP\n"); + } + break; + + case nn::ac::WPA2_TKIP: + { + COMMON_LOGGER("MODE = WPA2_TKIP\n"); + } + break; + + case nn::ac::WPA_AES: + { + COMMON_LOGGER("MODE = WPA_AES\n"); + } + break; + + case nn::ac::WPA2_AES: + { + COMMON_LOGGER("MODE = WPA2_AES\n"); + } + break; + + } + + } + } + + { + const char* pass = configfileLoader.ReadAsChar(L"PASS"); // PASS + if(pass == NULL) + { + COMMON_LOGGER("PASS: is missing\n"); + retval = false; + } + else + { + switch (networkSetting.wireless.essidSecurity.securityMode) + { + case nn::ac::WEP_40BIT: + case nn::ac::WEP_104BIT: + case nn::ac::WEP_128BIT: + { + std::strncpy(reinterpret_cast (networkSetting.wireless.essidSecurity.passphrase), + pass, 64); + std::memcpy(networkSetting.wireless.essidSecurity.key, + networkSetting.wireless.essidSecurity.passphrase, 64); + } + break; + + case nn::ac::WPA_TKIP: + case nn::ac::WPA2_TKIP: + case nn::ac::WPA_AES: + case nn::ac::WPA2_AES: + { + std::strncpy(reinterpret_cast (networkSetting.wireless.essidSecurity.passphrase), + pass, 64); + size_t phrase_size = std::strlen( + reinterpret_cast (networkSetting.wireless.essidSecurity.passphrase)); + + nn::nwm::Ssid ssid(reinterpret_cast (networkSetting.wireless.essidSecurity.ssid)); + nn::nwm::ConvertPasswordToPsk( + reinterpret_cast (networkSetting.wireless.essidSecurity.passphrase), + phrase_size, ssid, networkSetting.wireless.essidSecurity.key); + } + break; + + case nn::ac::OPEN: + default: + { + //do nothing + } + break; + } + + COMMON_LOGGER("PASS = %s\n", networkSetting.wireless.essidSecurity.passphrase); + + } + } + + + { + s32 dnsAuto; // DNS_AUTO + dnsAuto = configfileLoader.ReadAsInteger(L"DNS_AUTO"); + if(configfileLoader.ReadAsChar(L"DNS_AUTO") == NULL) + { + COMMON_LOGGER("DNS_AUTO: is missing\n"); + retval = false; + } + else + { + if (dnsAuto == 1) + { + networkSetting.ip.autoDNSSetting = true; + } + else + { + networkSetting.ip.autoDNSSetting = false; + } + + COMMON_LOGGER("DNS_AUTO = %d\n", networkSetting.ip.autoDNSSetting); + + } + } + + { + const char* dnsPrimary = configfileLoader.ReadAsChar(L"DNS_PRI"); // プライマリDNS + if(!networkSetting.ip.autoDNSSetting && dnsPrimary == NULL) + { + COMMON_LOGGER("DNS_PRI: is missing\n"); + retval = false; + } + else + { + u8 dns[4]; + nn::socket::InAddr addr; + if (1 == nn::socket::InetAtoN(dnsPrimary, &addr)) + { + dns[3] = (0xff & (addr.addr >> 24)); + dns[2] = (0xff & (addr.addr >> 16)); + dns[1] = (0xff & (addr.addr >> 8)); + dns[0] = (0xff & (addr.addr)); + } + std::memcpy(networkSetting.ip.dns[0], dns, 4); + COMMON_LOGGER("DNS_PRI = %03d.%03d.%03d.%03d\n", networkSetting.ip.dns[0][0], + networkSetting.ip.dns[0][1], + networkSetting.ip.dns[0][2], + networkSetting.ip.dns[0][3]); + + } + } + + { + const char* dnsSecondary = configfileLoader.ReadAsChar(L"DNS_SEC"); // セカンダリDNS + if(!networkSetting.ip.autoDNSSetting && dnsSecondary == NULL) + { + COMMON_LOGGER("DNS_SEC: is missing\n"); + retval = false; + } + else + { + u8 dns[4]; + nn::socket::InAddr addr; + if (1 == nn::socket::InetAtoN(dnsSecondary, &addr)) + { + dns[3] = (0xff & (addr.addr >> 24)); + dns[2] = (0xff & (addr.addr >> 16)); + dns[1] = (0xff & (addr.addr >> 8)); + dns[0] = (0xff & (addr.addr)); + } + std::memcpy(networkSetting.ip.dns[1], dns, 4); + COMMON_LOGGER("DNS_SEC = %03d.%03d.%03d.%03d\n", networkSetting.ip.dns[1][0], + networkSetting.ip.dns[1][1], + networkSetting.ip.dns[1][2], + networkSetting.ip.dns[1][3]); + + } + } + + { + const char* ntpServerName = configfileLoader.ReadAsChar(L"NTPSRV"); // NTPサーバ + if(s_NtpServerName == NULL) + { + COMMON_LOGGER("NTPSRV: is missing\n"); + retval = false; + } + else + { + std::strlcpy(s_NtpServerName, ntpServerName, sizeof(s_NtpServerName)); + COMMON_LOGGER("NTPSRV = %s\n", s_NtpServerName); + } + + + } + + { + const char* timeZone = configfileLoader.ReadAsChar(L"TIMEZONE"); // タイムゾーン + if(timeZone == NULL) + { + COMMON_LOGGER("TIMEZONE: is missing\n"); + retval = false; + } + else + { + std::strlcpy(s_TimeZoneStr, timeZone, sizeof(s_TimeZoneStr)); + COMMON_LOGGER("TIMEZONE = %s\n", s_TimeZoneStr); + ConvertTimeZoneString(s_TimeZoneStr); + } + + } + + configfileLoader.Finalize(); + + // 書き込み完了しなければfalse + if(!UpdateNetworkSetting(networkSetting)) + { + retval = false; + } + + } + else + { + NN_LOG("configfileLoader Initialize Failed\n"); + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + retval = false; + } + common::HeapManager::GetHeap()->Free(heapAddr); + } + else + { + NN_LOG("Can't Allocate Heap\n"); + COMMON_LOGGER_RESULT_WITH_LINE(result , __LINE__); + retval = false; + } + + common::SdMountManager::Unmount(); + return retval; +} + +char* GetNtpServerName() +{ + return s_NtpServerName; +} + +TimeZone GetTimeZone() +{ + return s_TimeZone; +} + +void ImportData() +{ + static bool init = true; + if(init) + { + // NANDのごみを削除する + Cleanup(); + + // SDカードのIVSファイルを書き込む + ImportIvs(); + + // NORデータを書き込む + ImportNorData(); + + // SDカードのセーブデータをNANDに書き込む + ImportSaveData(); + + init = false; + } + +} + +} diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/Importer.h b/trunk/ConsoleDataMigration/ConsoleRestore/Importer.h new file mode 100644 index 0000000..245e7dd --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/Importer.h @@ -0,0 +1,82 @@ +/*---------------------------------------------------------------------------* + 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 +#include "FileName.h" + +namespace ConsoleRestore +{ + +typedef enum FILE_EXISTS_CHECK +{ + EXISTS_UPDATE_FINISHED, + EXISTS_SERIAL_NUMBER, + EXISTS_IVS, + EXISTS_CONSOLE_INTIALIZED, + EXISTS_WRITE_FINISHED, + EXISTS_AP_SETTING, + EXISTS_MAX +} FileExistsCheck; + +const wchar_t* const FILENAME_TABLE[EXISTS_MAX] = +{ + common::UPDATE_CHECK_PATHNAME, + common::SERIAL_PATHNAME, + common::IVS_PATHNAME, + common::INITIALIZED_CHECK_PATHNAME, + common::WRITE_FINISHED_PATHNAME, + common::AP_SETTING_PATHNAME +}; + +bool ExistsUpdateCheckedFile(); +bool ExistsSerialNumberFile(); +bool ExistsIVSFile(); +bool EqualsIVSFileandIVS(); +bool ExistsConsoleInitializedFile(); +void InitializeFileCheck(); +u8* ReadSerialNumber(); +bool ExistsWriteFinishedFile(); +bool ExistsAPSetting(); + +bool IsImportFinished(); +void ImportData(); +void CreateWriteFinishedFile(); +void CreateUpdateFinishedFile(); +void CreateConsoleInitializedFile(); +u32 GetImportProgress(); + +// NANDのごみを削除する +void Cleanup(); + +void DeleteConsoleInitializedFile(); + +struct TimeZone +{ + u32 hour; + u32 minutes; + bool isMinus; + NN_PADDING3; +}; + +bool ReadSetting(); +char* GetNtpServerName(); +TimeZone GetTimeZone(); + +} + +#endif /* IMPORTER_H_ */ diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/NtpClient.cpp b/trunk/ConsoleDataMigration/ConsoleRestore/NtpClient.cpp new file mode 100644 index 0000000..03cd1fe --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/NtpClient.cpp @@ -0,0 +1,364 @@ +/*---------------------------------------------------------------------------* + 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 +#include +#include +#include +#include +#include +#include +#include + +#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 s_NtpThreadStack; +bool s_IsNtpThreadFinish = 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 NETWORK_SETTING_SLOT_NUM = 3; +nn::ac::CTR::NetworkSetting s_CurrentNetoworkSetting[NETWORK_SETTING_SLOT_NUM]; + +const size_t TIMEOUT_MILLISECOND = 5000; // タイムアウト ミリ秒数 +NTP_Packet s_NTPSendPacket; // 送信するNTPパケット +NTP_Packet s_NTPRecvPacket; // 受信するNTPパケット +const u32 NTP_PORT_NUM = 123; + + nn::Result InitializeNetwork(void) + { + nn::Result result; + nn::ac::Config config; + + nn::fs::Initialize(); + result = nn::ac::Initialize(); + NN_UTIL_PANIC_IF_FAILED(result); + + // 接続要求用のパラメータを作成 + result = nn::ac::CreateDefaultConfig( &config ); + if (result.IsFailure()) + { + NN_UTIL_PANIC_IF_FAILED(nn::ac::Finalize()); + return result; + } + + // デバッグ用に接続テストを無効化 + nn::ac::DebugSetNetworkArea( &config, nn::ac::NETWORK_AREA_LAN ); + + // 接続要求を発行 + result = nn::ac::Connect( config ); + if (result.IsFailure()) + { + NN_UTIL_PANIC_IF_FAILED(nn::ac::Finalize()); + return result; + } + + return nn::ResultSuccess(); + } + + nn::Result FinalizeNetwork(void) + { + nn::Result result; + + // 接続要求用のパラメータを作成 + result = nn::ac::Close(); + NN_UTIL_RETURN_IF_FAILED(result); + + result = nn::ac::Finalize(); + NN_UTIL_PANIC_IF_FAILED(result); + + nn::fs::Finalize(); + + return nn::ResultSuccess(); + } +} + +u32 GetNtpTime() +{ + nn::Result result; + + u32 ntp_time; + NN_LOG("Initializing network.\n"); + + // 本体に書き込まれているネットワーク設定を使ってネットワーク接続を初期化 + result = InitializeNetwork(); + NN_UTIL_PANIC_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(reinterpret_cast (pWorkMemory), 4096); + + // ソケットライブラリの初期化 + result = nn::socket::Initialize(workMemoryAddress, workSizeForLibrary, bufferSizeForSockets, sessionCount); + NN_UTIL_PANIC_IF_FAILED(result); + + { + s32 ret; + nn::socket::InAddr addr, netmask; + ret = nn::socket::GetPrimaryAddress(reinterpret_cast (&addr), reinterpret_cast (&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 (&dns1), reinterpret_cast (&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 (&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 + NN_UNUSED_VAR(ret); + } + + { + 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; + serverHostent = nn::socket::GetHostByName(GetNtpServerName()); + if (serverHostent == NULL) + { + COMMON_LOGGER("Error: GetHostByName %s\n", GetNtpServerName()); + } + else + { + // サーバのホスト情報からIPアドレスをコピー + serveraddr = *(reinterpret_cast (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 (&s_NTPSendPacket), sizeof(s_NTPSendPacket), 0, + &serverSockAddrIn)) < 0) + { + COMMON_LOGGER("Error: Failed Send to Server, %d\n", ret); + } + + 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); + } + + NN_LOG("Poll Finished\n"); + + switch (pollFd.revents) + { + case nn::socket::POLLERR: // ソケットにエラーが発生しました。 + COMMON_LOGGER("Error: POLLERR %s %d\n", __FILE__, __LINE__); + break; + case nn::socket::POLLHUP: // ストリーム・ソケットが未接続です。 + COMMON_LOGGER("Error: POLLHUP %s %d\n", __FILE__, __LINE__); + break; + case nn::socket::POLLNVAL: // 不正なソケット記述子です。 + COMMON_LOGGER("Error: POLLNVAL %s %d\n", __FILE__, __LINE__); + break; + default: + COMMON_LOGGER("Poll: No Error\n"); + break; + } + + // サーバから時刻情報を受信する + // サーバを指定して受信を行う + // 受信するまで待たされる + if ((ret = nn::socket::RecvFrom(socket, reinterpret_cast (&s_NTPRecvPacket), sizeof(s_NTPRecvPacket), 0, + &serverSockAddrIn)) < 0) + { + NN_LOG("Error: RecvFrom, %d\n", ret); + } + + NN_LOG("RecvFrom finished\n"); + + // NTPサーバから取得した時刻を現地時間に変換する + ntp_time = nn::socket::NtoHl(s_NTPRecvPacket.transmitTimestampSeconds) - 2208988800; /* 1970/01/01 からの秒数に変換 */ + + NN_LOG("ntp_time = %d\n", ntp_time); + + nn::socket::Close(socket); + NN_UNUSED_VAR(ret); + } + + NN_LOG("Finalizing socket..\n"); + // ソケットライブラリの終了 + result = nn::socket::Finalize(); + NN_UTIL_PANIC_IF_FAILED(result); + + // ソケットライブラリを Finalize すればワーク領域を再利用できます。 + delete[] pWorkMemory; + } + + NN_LOG("Finalizing network.\n"); + result = FinalizeNetwork(); + NN_UTIL_PANIC_IF_FAILED(result); + + return ntp_time; +} + +void SaveCurrentInternetSetting() +{ + NN_LOG("Save Current Internet Setting\n"); + nn::Result result; + result = nn::ac::CTR::InitializeInternal(); + COMMON_LOGGER_RESULT_IF_FAILED(result); + + for(u8 i = 0; i < NETWORK_SETTING_SLOT_NUM; i++) + { + result = nn::ac::CTR::LoadNetworkSetting(i, s_CurrentNetoworkSetting[i]); + COMMON_LOGGER_RESULT_IF_FAILED(result); + } +} + +void RestoreCurrentInternetSetting() +{ + NN_LOG("Restore Current Internet Setting\n"); + nn::Result result; + for(u8 i = 0; i < NETWORK_SETTING_SLOT_NUM; i++) + { + result = nn::ac::CTR::UpdateNetworkSetting(i, s_CurrentNetoworkSetting[i]); + COMMON_LOGGER_RESULT_IF_FAILED(result); + } +} + +void NtpThreadFunc() +{ + // NTP時間を取得する + u32 ntpTime = GetNtpTime(); + + // タイムゾーンを考慮して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()); + + // インターネット設定を元に戻す + RestoreCurrentInternetSetting(); + + s_IsNtpThreadFinish = true; +} + +bool IsTimeAdjustFinished() +{ + return s_IsNtpThreadFinish; +} + +void AdjustTime() +{ + // インターネット設定を一時的に保存する + SaveCurrentInternetSetting(); + + // SDカードのインターネット設定を反映する + ReadSetting(); + + s_NtpThread.Start( NtpThreadFunc, s_NtpThreadStack); +} + +} diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/NtpClient.h b/trunk/ConsoleDataMigration/ConsoleRestore/NtpClient.h new file mode 100644 index 0000000..9c5d3e1 --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/NtpClient.h @@ -0,0 +1,27 @@ +/*---------------------------------------------------------------------------* + 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 +{ + +u32 AdjustTime(); +bool IsTimeAdjustFinished(); + +} + +#endif /* NTPCLIENT_H_ */ diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/OMakefile b/trunk/ConsoleDataMigration/ConsoleRestore/OMakefile new file mode 100644 index 0000000..b46063a --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/OMakefile @@ -0,0 +1,84 @@ +#!/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.* +#MAKECSU = true +#INSTALL_SDK_TOOL = true +CTR_APPTYPE = BOTH +CTR_MAKE_DEVELOPMENT_IMAGE = true + +TARGET_PROGRAM = ConsoleRestore + +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \ + ../common + +SOURCES[] = + ConsoleRestore.cpp + Controller.cpp + Importer.cpp + Updater.cpp + Ntpclient.cpp + ../common/FileTransfer.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 + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +ROMFS_ROOT = ../common/romfiles + +LIBS += libnn_cfg \ + libnn_driversEeprom \ + libnn_driversi2c \ + libnn_driversCal \ + libnn_crypto \ + libnn_driversCodec \ + libnn_spi \ + libnn_gpio \ + libnn_pdn \ + libnn_mcu \ + libnn_i2c \ + libnn_driversCamera \ + libnn_ps \ + libnn_driversRsa \ + lib_demo \ + libnn_nwm \ + libnn_friends \ + libnn_ns \ + libnn_am \ + libnn_nim \ + +INSTALL_SDK_TOOL = true + +ROM_SPEC_FILE = $(TARGET_PROGRAM).rsf +DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/_private/RepairTool.desc + +include $(ROOT_OMAKE)/modulerules + +VERSION_H = $(file version.h) + +$(VERSION_H): $(SOURCES) + section + bash genversion.sh + +RequireSetup($(VERSION_H)) +build: version.h $(DEFAULT_TARGETS) diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/Updater.cpp b/trunk/ConsoleDataMigration/ConsoleRestore/Updater.cpp new file mode 100644 index 0000000..fdf49f3 --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/Updater.cpp @@ -0,0 +1,256 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Updater.cpp + + Copyright 2009 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ConsoleRestore +{ + +using namespace ES_NAMESPACE; +using namespace EC_NAMESPACE; + +/* ------------------------------------------------------------------- + GetCustomerSupportCode +-------------------------------------------------------------------- */ +#define NIM_UPDATER_RESULT_CHECK(result) \ +do { \ + if (result.IsFailure()) \ + { \ + ECCustomerSupportCode csc; \ + NN_UTIL_PANIC_IF_FAILED( \ + nn::nim::Updater::GetCustomerSupportCode(&csc)); \ + NN_LOG("CSCode: %d\n", csc); \ + nn::dbg::PrintResult(result); \ + s_Result = result; \ + goto LABEL_FINALIZE; \ + } \ +} while(0) + +namespace +{ + +nn::Result s_Result = nn::ResultSuccess(); + +bool s_updateFinished = false; + +const size_t UPDATER_THREAD_STACK_SIZE = 0x1000; +nn::os::Thread s_UpdaterThread; +nn::os::StackBuffer s_UpdaterThreadStack; + +u64 s_Progress = 0; + +} + +nn::Result PrintNetworkSetting() +{ + nn::ac::NetworkSetting networkSetting; + NN_UTIL_RETURN_IF_FAILED(nn::ac::LoadNetworkSetting(0, networkSetting)); + NN_LOG("SSID: %s\n", networkSetting.wireless.essidSecurity.ssid); + NN_LOG("DNS : %d.%d.%d.%d\n", + networkSetting.ip.dns[0][0], networkSetting.ip.dns[0][1], + networkSetting.ip.dns[0][2], networkSetting.ip.dns[0][3]); + return nn::ResultSuccess(); +} + + +nn::Result ConnectNetwork() +{ + nn::Result result = nn::ResultSuccess(); + nn::ac::Config config; + + result = nn::ac::CreateDefaultConfig(&config); + NN_UTIL_RETURN_IF_FAILED(result); + + result = nn::ac::ConnectWithoutEula(config); + NN_UTIL_RETURN_IF_FAILED(result); + + NN_LOG("Success nn::ac::ConnectWithoutEula\n"); + + NN_UTIL_RETURN_IF_FAILED(PrintNetworkSetting()); + + return nn::ResultSuccess(); +} + +nn::Result InitializeInternal() +{ + nn::Result result = nn::ResultSuccess(); + + result = nn::ac::InitializeInternal(); + NN_UTIL_RETURN_IF_FAILED(result); + + result = ConnectNetwork(); + NN_UTIL_RETURN_IF_FAILED(result); + + return nn::ResultSuccess(); +} + +nn::Result FinalizeInternal() +{ + nn::Result result = nn::ResultSuccess(); + + nn::ac::CloseAll(); + + result = nn::ac::FinalizeInternal(); + NN_UTIL_RETURN_IF_FAILED(result); + + return nn::ResultSuccess(); +} + +void UpdateThreadFunc() +{ + nn::Result result; + + NN_LOG("********************UpdateThreadFunc Start********************\n"); + nn::cfg::CTR::init::Initialize(); + nn::cfg::CfgCountryCode country; + nn::cfg::CfgRegionCode region; + const char *regionStr; + const char *countryStr; + NN_UNUSED_VAR(regionStr); + NN_UNUSED_VAR(countryStr); + + country = nn::cfg::GetCountry(); + region = nn::cfg::GetRegion(); + countryStr = nn::cfg::GetCountryCodeA2(country); + regionStr = nn::cfg::GetRegionCodeA3(region); + + NN_LOG("[Updater] country:%2d:%s\n", country, countryStr); + NN_LOG("[Updater] region :%2d:%s\n", region, regionStr); + + /* ------------------------------------------------------------------- + Initialize + -------------------------------------------------------------------- */ + NN_LOG("[Updater] nn::nim::InitializeForUpdater\n"); + result = nn::nim::InitializeForUpdater(); + NIM_UPDATER_RESULT_CHECK(result); + + NN_LOG("[Updater] InitializeInternal\n"); + result = InitializeInternal(); + NIM_UPDATER_RESULT_CHECK(result); + + + /* ------------------------------------------------------------------- + StartNetworkUpdate + -------------------------------------------------------------------- */ + NN_LOG("[Updater] nn::nim::Updater::StartNetworkUpdate()\n"); + result = nn::nim::Updater::StartNetworkUpdate(); + NIM_UPDATER_RESULT_CHECK(result); + + /* ------------------------------------------------------------------- + GetProgress + -------------------------------------------------------------------- */ + NN_LOG("[Updater] nn::nim::Updater::GetProgress()\n"); + + while(true) + { + nn::nim::NetworkUpdateProgress progress; + NIM_UPDATER_RESULT_CHECK(nn::nim::Updater::GetProgress(&progress)); + NIM_UPDATER_RESULT_CHECK(progress.lastResult); + NN_LOG("\x1b[1A\x1b[K"); + NN_LOG("Downloading %2lld/%2lld %8lld/%8lld (%d)\n", + progress.downloadedTitleNum, + progress.totalTitleNum, + progress.currentDownloadedSize, + progress.currentTotalSize, + progress.state); + + // ゼロ除算を防ぐ + if(progress.totalTitleNum == 0) + { + progress.totalTitleNum++; + progress.downloadedTitleNum++; + } + if(progress.state > nn::nim::CTR::NUP_STATE_CHECKING) + { + s_Progress = progress.downloadedTitleNum * 100 / progress.totalTitleNum; + } + + if (progress.state == nn::nim::NUP_STATE_NO_NEED) + { + NN_LOG("[Updater] No need to NetworkUpdate\n"); + s_Progress = 100; + break; + } + if (progress.state == nn::nim::NUP_STATE_FINISHED) + { + NN_LOG("[Updater] Finished NetworkUpdate\n"); + s_Progress = 100; + break; + } + + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(300)); + } + + LABEL_FINALIZE: + + /* ------------------------------------------------------------------- + Finalize + -------------------------------------------------------------------- */ + NN_LOG("[Updater] nn::nim::FinalizeForUpdater\n"); + result = nn::nim::FinalizeForUpdater(); + NIM_UPDATER_RESULT_CHECK(result); + + result = FinalizeInternal(); + NIM_UPDATER_RESULT_CHECK(result); + + NN_LOG("[Updater] Finish nim Updater demo.\n"); + + s_updateFinished = true; + +} + +void StartFGNetworkUpdate() +{ + NN_LOG("Start FGNetworkUpdate\n"); + s_updateFinished = false; + s_Result = nn::ResultSuccess(); + s_UpdaterThread.Start(UpdateThreadFunc, s_UpdaterThreadStack); +} + +bool IsUpdaterThreadStateValid() +{ + return s_UpdaterThread.IsValid(); +} + +void FinishFGNetworkUpdate() +{ + NN_LOG("Finalize FGNetworkUpdate\n"); + s_UpdaterThread.Join(); +} + +bool IsNetworkUpdateFinished() +{ + return s_updateFinished; +} + +u32 GetUpdateProgress() +{ + return s_Progress; +} + +nn::Result GetUpdateResult() +{ + return s_Result; +} + + +} diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/Updater.h b/trunk/ConsoleDataMigration/ConsoleRestore/Updater.h new file mode 100644 index 0000000..32e6798 --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/Updater.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Updater.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 UPDATER_H_ +#define UPDATER_H_ + +#include + +namespace ConsoleRestore +{ + +void StartFGNetworkUpdate(); +void FinishFGNetworkUpdate(); +bool IsNetworkUpdateFinished(); +u32 GetUpdateProgress(); +nn::Result GetUpdateResult(); + +} + +#endif /* UPDATER_H_ */ diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/banner/big.ctpk b/trunk/ConsoleDataMigration/ConsoleRestore/banner/big.ctpk new file mode 100644 index 0000000..80d0235 Binary files /dev/null and b/trunk/ConsoleDataMigration/ConsoleRestore/banner/big.ctpk differ diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/banner/little.ctpk b/trunk/ConsoleDataMigration/ConsoleRestore/banner/little.ctpk new file mode 100644 index 0000000..124c063 Binary files /dev/null and b/trunk/ConsoleDataMigration/ConsoleRestore/banner/little.ctpk differ diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/banner/model.cbmd b/trunk/ConsoleDataMigration/ConsoleRestore/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/trunk/ConsoleDataMigration/ConsoleRestore/banner/model.cbmd differ diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/banner/sound.cbsd b/trunk/ConsoleDataMigration/ConsoleRestore/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/trunk/ConsoleDataMigration/ConsoleRestore/banner/sound.cbsd differ diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/genversion.sh b/trunk/ConsoleDataMigration/ConsoleRestore/genversion.sh new file mode 100755 index 0000000..f59c27a --- /dev/null +++ b/trunk/ConsoleDataMigration/ConsoleRestore/genversion.sh @@ -0,0 +1,3 @@ +#!/bin/bash -f + +echo "#define RESTORE_VERSION_NUM \"`svnversion -n`\"" > version.h diff --git a/trunk/ConsoleDataMigration/OMakefile b/trunk/ConsoleDataMigration/OMakefile new file mode 100644 index 0000000..203c656 --- /dev/null +++ b/trunk/ConsoleDataMigration/OMakefile @@ -0,0 +1,24 @@ +#!/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$ +#---------------------------------------------------------------------------- + +#.SUBDIRS: $(glob D, *) +.SUBDIRS: $(exist-dirs \ + common \ + ConsoleBackup \ + ConsoleRestore \ + ) + +DefineDefaultRules() diff --git a/trunk/ConsoleDataMigration/OMakeroot b/trunk/ConsoleDataMigration/OMakeroot new file mode 100644 index 0000000..7ee1cb5 --- /dev/null +++ b/trunk/ConsoleDataMigration/OMakeroot @@ -0,0 +1,73 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakeroot +# +# 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:$ +#---------------------------------------------------------------------------- + +# fBNgCAEgɂ‚Ă̐ +# +# a) \[XR[h[gfBNgɔzuꍇ +# : +# /OMakeroot +# /foo/bar/OMakefile +# +# : +# OMakefile ƓfBNgȉ objects images ܂B +# +# /foo/bar/objects/... +# /foo/bar/images/.. +# +# +# b) \[XR[h sources ȉɔzuꍇ +# : +# /OMakeroot +# /sources/foo/bar/OMakefile +# +# : +# [gfBNgȉ objects images ܂B +# +# /objects/foo/bar/... +# /images/foo/bar/... +# +# + +# [g‹ϐ̎擾 +public.HORIZON_ROOT = +if $(defined-env HORIZON_ROOT) + HORIZON_ROOT = $(absname $(getenv HORIZON_ROOT)) + export + +if $(defined-env CTRSDK_ROOT) + CTRSDK_ROOT = $(absname $(getenv CTRSDK_ROOT)) + if $(and $(defined-env HORIZON_ROOT), $(not $(equal $(HORIZON_ROOT), $(CTRSDK_ROOT)))) + eprintln(HORIZON_ROOT CTRSDK_ROOT v܂BpXݒ肷邩Aǂ炩`ĉB) + exit(1) + HORIZON_ROOT = $(CTRSDK_ROOT) + export + +if $(not $(HORIZON_ROOT)) + eprintln($"$$CTRSDK_ROOT `Ă܂") + exit(1) + +include $(HORIZON_ROOT)/build/omake/commondefs + +DefineCommandVars() + +.PHONY: all build clean clobber +.PHONY: run run-scripts run-emumem + +# +# OMakefile ̓ǂݍ +# +.SUBDIRS: . + diff --git a/trunk/ConsoleDataMigration/Readme.txt b/trunk/ConsoleDataMigration/Readme.txt new file mode 100644 index 0000000..2f2f0d5 --- /dev/null +++ b/trunk/ConsoleDataMigration/Readme.txt @@ -0,0 +1,10 @@ +yrh‹z + +ESDK +Horizon 0_14 branch r33437 + + Horizon trunk r33597cfgCu̕ύX}[W + + Horizon 1_0 branch r33839RepairTool.desc}[W + +Ecygwin +Esvnversion + diff --git a/trunk/ConsoleDataMigration/common/Aes_define.h b/trunk/ConsoleDataMigration/common/Aes_define.h new file mode 100644 index 0000000..34436ec --- /dev/null +++ b/trunk/ConsoleDataMigration/common/Aes_define.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Aes_define.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 AES_DEFINE_H_ +#define AES_DEFINE_H_ + +namespace common +{ + bit8 key[AES_KEY_SIZE] = + { + 0x81, 0x35, 0xc6, 0x54, 0x19, 0x1a, 0x47, 0x2a, + 0x6b, 0x78, 0xbe, 0x25, 0x90, 0xf6, 0xee, 0x74 + }; +} + +#endif /* AES_DEFINE_H_ */ diff --git a/trunk/ConsoleDataMigration/common/CommonLogger.cpp b/trunk/ConsoleDataMigration/common/CommonLogger.cpp new file mode 100644 index 0000000..c2e5f21 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/CommonLogger.cpp @@ -0,0 +1,125 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: CommonLogger.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 "CommonLogger.h" +#include "LogConsole_Private.h" + +namespace common +{ + +namespace Logger +{ + +namespace +{ + static CommonLogger s_CommonLogger; + +} + +CommonLogger::CommonLogger() +{ + // TODO 自動生成されたコンストラクター・スタブ + +} + +CommonLogger::~CommonLogger() +{ + // TODO Auto-generated destructor stub +} + +void CommonLogger::Initialize(u32 width, u32 height, u32 maxLine, demo::RenderSystemDrawing* renderSystem) +{ + m_CriticalSection.Initialize(); + GetConsoleInstance()->Initialize(width, height, maxLine, renderSystem); +} + +void CommonLogger::Finalize() +{ + +} + +void CommonLogger::Print(const char* fmt, ...) +{ + nn::os::CriticalSection::ScopedLock lock(m_CriticalSection); + va_list vlist; + + va_start(vlist, fmt); + + nn::dbg::detail::VPrintf(fmt, vlist); + GetSdInstance()->Print(fmt, vlist); + GetConsoleInstance()->AddText(fmt, vlist); + + va_end(vlist); +} + +void CommonLogger::PrintResult(const char* fmt, ...) +{ + va_list vlist; + + va_start(vlist, fmt); + + GetSdInstance()->Print(fmt, vlist); + + va_end(vlist); +} + +void CommonLogger::PrintResultIfFailed(nn::Result result, u32 line) +{ + if (result.IsFailure()) + { + if(line != 0) + { + COMMON_LOGGER_RESULT_WITH_LINE(result, line); + } + else + { + COMMON_LOGGER_RESULT(result); + } + } +} + +void CommonLogger::ScrollUp() +{ + GetConsoleInstance()->ScrollUp(); +} + +void CommonLogger::ScrollDown() +{ + GetConsoleInstance()->ScrollDown(); +} + +void CommonLogger::ScrollToBegin() +{ + GetConsoleInstance()->ScrollToBegin(); +} + +void CommonLogger::ScrollToEnd() +{ + GetConsoleInstance()->ScrollToEnd(); +} + +void CommonLogger::DrawConsole() +{ + GetConsoleInstance()->Print(); +} + +CommonLogger* GetLoggerInstance() +{ + return &s_CommonLogger; +} + +} + +} diff --git a/trunk/ConsoleDataMigration/common/CommonLogger.h b/trunk/ConsoleDataMigration/common/CommonLogger.h new file mode 100644 index 0000000..3af1e2d --- /dev/null +++ b/trunk/ConsoleDataMigration/common/CommonLogger.h @@ -0,0 +1,75 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: CommonLogger.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 COMMONLOGGER_H_ +#define COMMONLOGGER_H_ + +#include +#include "demo.h" + +#include "SdLogger.h" +#include "LogConsole.h" + +#define COMMON_LOGGER( ... ) (void)common::Logger::GetLoggerInstance()->Print(__VA_ARGS__) +#define COMMON_LOGGER_RESULT(result) \ + (void)nn::dbg::PrintResult(result); \ + (void)common::Logger::GetLoggerInstance()->PrintResult("Result = %X\n", result.GetPrintableBits()); \ + +#define COMMON_LOGGER_RESULT_WITH_LINE(result, line) \ + (void)nn::dbg::PrintResult(result); \ + (void)common::Logger::GetLoggerInstance()->PrintResult("line = %d\n", line); \ + (void)common::Logger::GetLoggerInstance()->PrintResult("Result = %X\n", result.GetPrintableBits()); \ + +#define COMMON_LOGGER_RESULT_IF_FAILED(result) \ + if(result.IsFailure()) \ + { \ + COMMON_LOGGER_RESULT(result); \ + } \ + + +namespace common +{ + +namespace Logger +{ + +class CommonLogger +{ +public: + CommonLogger(); + ~CommonLogger(); + + void Initialize(u32 width, u32 height, u32 maxLine, demo::RenderSystemDrawing* renderSystem); + void Finalize(); + + void Print(const char* fmt, ...); + void PrintResult(const char* fmt, ...); + void PrintResultIfFailed(nn::Result result, u32 line = 0); + void ScrollUp(); + void ScrollDown(); + void ScrollToBegin(); + void ScrollToEnd(); + void DrawConsole(); +private: + nn::os::CriticalSection m_CriticalSection; +}; + +CommonLogger* GetLoggerInstance(); + +} + +} + +#endif /* COMMONLOGGER_H_ */ diff --git a/trunk/ConsoleDataMigration/common/FileName.h b/trunk/ConsoleDataMigration/common/FileName.h new file mode 100644 index 0000000..412b126 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/FileName.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: FileName.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 FILENAME_H_ +#define FILENAME_H_ + +namespace common +{ + +const char* const NAND_ARCHIVE_NAME = "nand:"; +const char* const SD_ARCHIVE_NAME = "sdmc:"; + +const wchar_t* const SD_SAVEDATA_ROOT_NAME = L"CTR_ConsoleBackup/"; +const wchar_t* const AP_SETTING_FILENAME = L"APSetting.txt"; +const wchar_t* const AP_SETTING_PATHNAME = L"sdmc:/APSetting.txt"; +const wchar_t* const NOR_PATHNAME = L"sdmc:/NtrNorSetting.bin"; +const wchar_t* const SERIAL_PATHNAME = L"sdmc:/serial.bin"; +const wchar_t* const IVS_NAND_PATHNAME = L"nand:/private/movable.sed"; +const wchar_t* const IVS_PATHNAME = L"sdmc:/movable.sed"; +const wchar_t* const NAND_DATA_ROOT_PATHNAME_WITH_SLASH = L"nand:/data/"; +const wchar_t* const SDMC_ROOT_DIRECTORY_PATH = L"sdmc:/"; +const wchar_t* const WRITE_FINISHED_PATHNAME = L"sdmc:/WriteFinished"; +const wchar_t* const UPDATE_CHECK_PATHNAME = L"sdmc:/UpdateFinished"; +const wchar_t* const INITIALIZED_CHECK_PATHNAME = L"sdmc:/ConsoleInitialized"; + +} + +#endif /* FILENAME_H_ */ diff --git a/trunk/ConsoleDataMigration/common/FileTransfer.cpp b/trunk/ConsoleDataMigration/common/FileTransfer.cpp new file mode 100644 index 0000000..0a16e0a --- /dev/null +++ b/trunk/ConsoleDataMigration/common/FileTransfer.cpp @@ -0,0 +1,248 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: FileTransfer.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 "FileTransfer.h" +#include + +namespace common +{ + +namespace +{ + +u64 s_TotalFileSize; +u64 s_FinishedFileSize = 0; +u64 s_Progress = 0; + +} + +nn::Result CalculateFileNum(std::wstring currentDirectory, u32& fileNum, u32& fileSize) +{ + nn::fs::FileInputStream fis; + nn::fs::Directory dir; + nn::Result result; + std::vector entryList; //カレントディレクトリのエントリ一覧を格納 + std::vector::iterator entryIndex; + + result = dir.TryInitialize(currentDirectory.c_str()); + + if(result.IsSuccess()) + { + nn::fs::DirectoryEntry entry; + s32 numEntry; + for(;;) + { + result = dir.TryRead(&numEntry, &entry, 1); + if(result.IsFailure()) + { + dir.Finalize(); + return result; + } + if(numEntry == 0) + { + // カレントディレクトリを閉じる + dir.Finalize(); + + // カレントディレクトリの子を開く + for(entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++) + { + if(entryIndex->attributes.isDirectory) + { + CalculateFileNum(currentDirectory + std::wstring(entryIndex->entryName) + std::wstring(L"/"), fileNum, fileSize); + } + } + + return nn::ResultSuccess(); + } + + entryList.push_back(entry); + fileNum++; + fileSize+= entry.entrySize; + } + } + else + { + NN_LOG("failed initialize directory\n"); + dir.Finalize(); + return result; + } + +} + +// ディレクトリ間のコピー +// アーカイブ越しのコピーが可能 +// アーカイブにマウントした状態で呼び出す必要あり +// 書き込み先のディレクトリはあらかじめ消去しておくこと。 +// 引数はスラッシュ付き +bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf, const size_t bufSize) +{ + nn::fs::Directory from_dir; + nn::fs::DirectoryEntry entry; + s32 numread = 0; + std::wostringstream target_from; + std::wostringstream target_to; + bool ret_value = true; + + nn::Result result = from_dir.TryInitialize(from_path); + + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + return false; + } + + while (1) + { + result = from_dir.TryRead(&numread, &entry, 1); + if (result.IsFailure() || numread != 1) + { + break; + } + + if (std::wcscmp(entry.entryName, L".") == 0 || std::wcscmp(entry.entryName, L"..") == 0) + { + continue; + } + + target_from.str(L""); + target_from.clear(std::stringstream::goodbit); + target_from << from_path << entry.entryName; + + target_to.str(L""); + target_to.clear(std::stringstream::goodbit); + target_to << to_path << entry.entryName; + + // ディレクトリの場合 + if (entry.attributes.isDirectory) + { + // ディレクトリ作成 + NN_LOG("Create Directory %ls\n", target_to.str().c_str()); + result = nn::fs::TryCreateDirectory(target_to.str().c_str()); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + else + { + target_from << L"/"; + target_to << L"/"; + // 再帰処理 + if (!CopyDirectory(target_from.str().c_str(), target_to.str().c_str(), buf, bufSize)) + { + ret_value = false; + } + } + } + // ファイルの場合 + else + { + // ファイル作成 + nn::fs::FileInputStream from_file; + nn::fs::FileOutputStream to_file; + s64 filesize; + s32 readsize; + s32 writesize; + + NN_LOG("Copy File %ls\n", target_from.str().c_str()); + + // 読み込み対象ファイル開く + result = from_file.TryInitialize(target_from.str().c_str()); + + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + else + { + // 読み込み対象ファイルのサイズ取得 + result = from_file.TryGetSize(&filesize); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + else + { + // 書き込み対象ファイル作成 + result = nn::fs::TryCreateFile(target_to.str().c_str(), filesize); + result = to_file.TryInitialize(target_to.str().c_str(), false); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + else + { + while (1) + { + result = from_file.TryRead(&readsize, buf, bufSize); + + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + break; + } + else + { + if (readsize == 0) + { + result = to_file.TryFlush(); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + break; + } + else + { + result = to_file.TryWrite(&writesize, buf, readsize, false); + s_FinishedFileSize += readsize; + s_Progress = s_FinishedFileSize * 100/ s_TotalFileSize; + NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + } + } + } + } + to_file.Finalize(); + } + } + from_file.Finalize(); + } + } + + from_dir.Finalize(); + return ret_value; +} + +u32 GetProgress() +{ + return s_Progress; +} + +void SetTotalSize(u64 size) +{ + s_TotalFileSize = size; +} + +} diff --git a/trunk/ConsoleDataMigration/common/FileTransfer.h b/trunk/ConsoleDataMigration/common/FileTransfer.h new file mode 100644 index 0000000..9d6b878 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/FileTransfer.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: FileTransfer.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 FILETRANSFER_H_ +#define FILETRANSFER_H_ + +#include +#include +#include + +namespace common +{ + +nn::Result CalculateFileNum(std::wstring currentDirectory, u32& fileNum, u32& fileSize); +bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf, const size_t bufSize); +u32 GetProgress(); +void SetTotalSize(u64 size); + +} + +#endif /* FILETRANSFER_H_ */ diff --git a/trunk/ConsoleDataMigration/common/HeapManager.cpp b/trunk/ConsoleDataMigration/common/HeapManager.cpp new file mode 100644 index 0000000..29f4367 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/HeapManager.cpp @@ -0,0 +1,39 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: HeapManager.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 "HeapManager.h" + +namespace common +{ + +nn::fnd::ThreadSafeExpHeap HeapManager::s_AppHeap; + +HeapManager::HeapManager() +{ + // TODO 自動生成されたコンストラクター・スタブ + +} + +HeapManager::~HeapManager() +{ + // TODO Auto-generated destructor stub +} + +nn::fnd::ThreadSafeExpHeap* HeapManager::GetHeap() +{ + return &s_AppHeap; +} + +} diff --git a/trunk/ConsoleDataMigration/common/HeapManager.h b/trunk/ConsoleDataMigration/common/HeapManager.h new file mode 100644 index 0000000..b9fc469 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/HeapManager.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: HeapManager.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 HEAPMANAGER_H_ +#define HEAPMANAGER_H_ + +#include + +namespace common +{ + +class HeapManager +{ +public: + HeapManager(); + virtual ~HeapManager(); + + static nn::fnd::ThreadSafeExpHeap* GetHeap(); + +private: + // デバイスメモリ管理用拡張ヒープ + static nn::fnd::ThreadSafeExpHeap s_AppHeap; + +}; + +} // namespace common + +#endif /* HEAPMANAGER_H_ */ diff --git a/trunk/ConsoleDataMigration/common/LogConsole.cpp b/trunk/ConsoleDataMigration/common/LogConsole.cpp new file mode 100644 index 0000000..b77d6d0 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/LogConsole.cpp @@ -0,0 +1,171 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: LogConsole.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 "LogConsole.h" +#include + +namespace common +{ + +const size_t FONT_WIDTH = 8; +const size_t FONT_HEIGHT = 10; + +static LogConsole s_LogConsole; + +LogConsole* GetConsoleInstance() +{ + return &s_LogConsole; +} + +LogConsole::LogConsole() +{ + +} + +LogConsole::~LogConsole() +{ + +} + +void LogConsole::Initialize(u32 width, u32 height, u32 maxLine, demo::RenderSystemDrawing* renderSystem) +{ + m_Width = width; + m_Height = height; + m_MaxLine = maxLine; + m_RenderSystem = renderSystem; + m_CurrentViewLine = 0; + m_LineNum = 0; +} + +void LogConsole::AddText(const char* fmt, ::std::va_list arg) +{ + s32 stringSize; + const size_t STRING_BUFFER_SIZE = 256; + char formatStr[STRING_BUFFER_SIZE]; + + stringSize = nn::nstd::TVSNPrintf(formatStr, sizeof(formatStr), fmt, arg); + ::std::string str(formatStr); + + size_t addedText = 0; + while (addedText < stringSize) + { + if(m_LineNum >= m_MaxLine) + { + // 満杯なので先頭を削除する + ::std::vector::iterator it; + it = m_Log.begin(); + m_Log.erase(it); + m_LineNum--; + } + + // 部分文字列を追加 + AddWrapedText(str.substr(addedText, m_Width).c_str()); + m_LineNum++; + + // 画面領域以上追加したら末尾にスクロールする + if(m_LineNum > m_Height) + { + ScrollToEnd(); + } + + + if(stringSize - addedText > m_Width) + { + addedText += m_Width; + } + else + { + addedText += stringSize - addedText; + } + } +} + +void LogConsole::ScrollUp() +{ + if(m_CurrentViewLine > 0) + { + m_CurrentViewLine--; + } +} + + + +void LogConsole::ScrollDown() +{ + if (m_LineNum > m_Height) + { + if (m_CurrentViewLine < m_LineNum - m_Height) + { + m_CurrentViewLine++; + } + + } +} + +void LogConsole::ScrollToBegin() +{ + m_CurrentViewLine = 0; +} + +void LogConsole::ScrollToEnd() +{ + if(m_LineNum > m_Height) + { + m_CurrentViewLine = m_LineNum - m_Height; + } +} + + +void LogConsole::Print() +{ + ::std::vector::iterator it; + + it = m_Log.begin(); + it += m_CurrentViewLine; + + u32 count = 0; + for(; it != m_Log.end() && count < m_Height && count < m_MaxLine; it++) + { + m_RenderSystem->DrawText(0, count++ * 10, "%s", it->c_str()); + } + + if(m_LineNum > m_Height) + { + DrawScrollBar(); + } +} + + +void LogConsole::AddWrapedText(const char* str) +{ + m_Log.push_back(::std::string(str)); +} + +void LogConsole::DrawScrollBar() +{ + m_RenderSystem->SetColor(0.4f, 0.4f, 0.4f); + m_RenderSystem->DrawLine((m_Width + 1) * FONT_WIDTH, 0, (m_Width + 2) * FONT_WIDTH - 1, 0); + m_RenderSystem->DrawLine((m_Width + 1)* FONT_WIDTH, 0, (m_Width + 1)* FONT_WIDTH, m_Height * FONT_HEIGHT); + m_RenderSystem->DrawLine((m_Width + 2) * FONT_WIDTH - 1, 0, (m_Width + 2) * FONT_WIDTH - 1, m_Height * FONT_HEIGHT); + m_RenderSystem->DrawLine((m_Width + 1)* FONT_WIDTH, m_Height * FONT_HEIGHT - 1, (m_Width + 2) * FONT_WIDTH - 1, m_Height * FONT_HEIGHT - 1); + + u32 y = (m_Height * FONT_HEIGHT - 2) * m_CurrentViewLine / m_MaxLine; + m_RenderSystem->SetColor(0.7f, 0.7f, 0.7f); + m_RenderSystem->FillRectangle((m_Width + 1) * FONT_WIDTH, y + 1, FONT_WIDTH - 1, FONT_HEIGHT - 4); + + m_RenderSystem->SetColor(1.f, 1.f, 1.f); +} + +} //namespace ConsoleBackup diff --git a/trunk/ConsoleDataMigration/common/LogConsole.h b/trunk/ConsoleDataMigration/common/LogConsole.h new file mode 100644 index 0000000..b8a7d52 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/LogConsole.h @@ -0,0 +1,68 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: LogConsole.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 LOGCONSOLE_H_ +#define LOGCONSOLE_H_ + +#include +#include +#include +#include "demo.h" + +namespace common +{ + +//! @brief 画面にテキストコンソールを描画します +class LogConsole +{ + +public: + LogConsole(); + ~LogConsole(); + + void Initialize(u32 width, u32 height, u32 maxLine, demo::RenderSystemDrawing* renderSystem); + + void AddText(const char* fmt, ::std::va_list arg); + void ScrollUp(); + void ScrollDown(); + void ScrollToBegin(); + void ScrollToEnd(); + void Print(); + +private: + void AddWrapedText(const char* str); + void DrawScrollBar(); + + ::std::vector m_Log; + + //! @brief コンソールの列数 + u32 m_Width; + //! @brief コンソールの行数 + u32 m_Height; + //! @brief コンソールのログの最大行数 + u32 m_MaxLine; + //! @brief 描画のためのRenderSystemDrawingへのポインタ + demo::RenderSystemDrawing* m_RenderSystem; + //! @brief 追加したログの行数 + u32 m_LineNum; + //! @brief 表示を開始するログの行数 + u32 m_CurrentViewLine; + + +}; + +} + +#endif /* LOGCONSOLE_H_ */ diff --git a/trunk/ConsoleDataMigration/common/LogConsole_Private.h b/trunk/ConsoleDataMigration/common/LogConsole_Private.h new file mode 100644 index 0000000..8fbdd42 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/LogConsole_Private.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: LogConsole_Private.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 LOGCONSOLE_PRIVATE_H_ +#define LOGCONSOLE_PRIVATE_H_ + +#include "LogConsole.h" + +namespace common +{ + +LogConsole* GetConsoleInstance(); + +} + +#endif /* LOGCONSOLE_PRIVATE_H_ */ diff --git a/trunk/ConsoleDataMigration/common/OMakefile b/trunk/ConsoleDataMigration/common/OMakefile new file mode 100644 index 0000000..e874cbc --- /dev/null +++ b/trunk/ConsoleDataMigration/common/OMakefile @@ -0,0 +1,18 @@ +#!/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$ +#---------------------------------------------------------------------------- +include $(ROOT_OMAKE)/modulerules + +DefineDefaultRules() diff --git a/trunk/ConsoleDataMigration/common/SdLogger.cpp b/trunk/ConsoleDataMigration/common/SdLogger.cpp new file mode 100644 index 0000000..86042f2 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/SdLogger.cpp @@ -0,0 +1,195 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdLogger.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 "SdLogger.h" +#include +#include "SDMountManager.h" + +namespace common +{ + +namespace Logger +{ + +static SdLogger s_SdLogger; +static nn::os::LightEvent s_SdEjectedEvent; +static nn::os::LightEvent s_SdInsertedEvent; + +const size_t SDMC_EVENT_THREAD_STACK_SIZE = 1024; +nn::os::Thread s_SdmcEjectedEventThread; +nn::os::StackBuffer s_SdmcEjectedEventThreadStack; + +nn::os::Thread s_SdmcInsertedEventThread; +nn::os::StackBuffer s_SdmcInsertedEventThreadStack; + +void (*s_SdEjectedEventFunc)() = NULL; +void (*s_SdInsertedEventFunc)() = NULL; + +void PrintResultIfFailed(nn::Result result, u32 line = 0) +{ + if (result.IsFailure()) + { + if(line != 0) + { + NN_LOG("%s, %d\n", __FILE__, line); + } + nn::dbg::PrintResult(result); + } +} + +void SdmcEjectedEventThreadFunc() +{ + NN_LOG("********************:SD Ejected Event Thread Start**********************\n"); + + for(;;) + { + s_SdEjectedEvent.Wait(); + NN_LOG("********************:SD Card Ejected**********************\n"); + + if(s_SdEjectedEventFunc != NULL) + { + s_SdEjectedEventFunc(); + } + SdMountManager::ForceUnmount(); + s_SdEjectedEvent.ClearSignal(); + } +} + +void SdmcInsertedEventThreadFunc() +{ + NN_LOG("********************:SD Inserted Event Thread Start**********************\n"); + + for(;;) + { + s_SdInsertedEvent.Wait(); + NN_LOG("********************:SD Card Inserted*********************\n"); + + if(s_SdInsertedEventFunc != NULL) + { + s_SdInsertedEventFunc(); + } + s_SdInsertedEvent.ClearSignal(); + } +} + +void InitializeEjectThread() +{ + s_SdEjectedEvent.Initialize(true); + s_SdInsertedEvent.Initialize(true); + nn::fs::RegisterSdmcEjectedEvent(&s_SdEjectedEvent); + nn::fs::RegisterSdmcInsertedEvent(&s_SdInsertedEvent); + + // SDカード抜けを検知するためのスレッド作成 + s_SdmcEjectedEventThread.Start(SdmcEjectedEventThreadFunc, s_SdmcEjectedEventThreadStack); + + // SDカード挿入を検知するためのスレッド作成 + s_SdmcInsertedEventThread.Start(SdmcInsertedEventThreadFunc, s_SdmcInsertedEventThreadStack); + +} +void SetEjectHandler(void (*func)()) +{ + s_SdEjectedEventFunc = func; +} + +void SetInsertHandler(void (*func)()) +{ + s_SdInsertedEventFunc = func; +} + +SdLogger::SdLogger() +{ + +} + +SdLogger* GetSdInstance() +{ + return &s_SdLogger; +} + +void SdLogger::Print(const char* fmt, ::std::va_list arg) +{ + nn::Result result; + + result = SdMountManager::Mount(); + if (result.IsFailure()) + { + PrintResultIfFailed(result, __LINE__); + } + + s32 stringSize; + const size_t STRING_BUFFER_SIZE = 256; + char str[STRING_BUFFER_SIZE]; + + stringSize = nn::nstd::TVSNPrintf(str, sizeof(str), fmt, arg); + + ::std::wstring log(SDMC_ROOT_NAME); + log += LOG_FILENAME; + + result = sd.TryInitialize(log.c_str(), true); + if (result.IsSuccess()) + { + // 追記する + // サイズ取得 + s64 fileSize; + result = sd.TryGetSize(&fileSize); + if (result.IsSuccess()) + { + // 末尾に移動 + result = sd.TrySetPosition(fileSize); + if (result.IsSuccess()) + { + s32 writeSize; + result = sd.TryWrite(&writeSize, str, stringSize, true); + if (result.IsSuccess()) + { + result = sd.TryFlush(); + if (result.IsFailure()) + { + NN_LOG("SD TryFlush failed\n"); + PrintResultIfFailed(result, __LINE__); + } + } + else + { + NN_LOG("SD TryWrite failed\n"); + PrintResultIfFailed(result, __LINE__); + } + } + else + { + NN_LOG("SD TrySetPosition failed\n"); + PrintResultIfFailed(result, __LINE__); + } + } + else + { + NN_LOG("SD TryGetSize failed\n"); + PrintResultIfFailed(result, __LINE__); + } + } + else + { + NN_LOG("SD TryInitialize failed, %s, %d\n", __FILE__, __LINE__); + PrintResultIfFailed(result, __LINE__); + } + + sd.Finalize(); + SdMountManager::Unmount(); +} + +} // namespace Logger +} // namespace ConsoleBackup + + diff --git a/trunk/ConsoleDataMigration/common/SdLogger.h b/trunk/ConsoleDataMigration/common/SdLogger.h new file mode 100644 index 0000000..4c15ae9 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/SdLogger.h @@ -0,0 +1,55 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdLogger.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 SDLOGGER_H_ +#define SDLOGGER_H_ + +#include + +namespace common +{ + +namespace Logger +{ + +const wchar_t* const SDMC_ROOT_NAME = L"sdmc:/"; +const wchar_t* const LOG_FILENAME = L"ConsoleBackup_log.txt"; +const wchar_t* const TEST_FILENAME = L"sdmc:/Test_ConsoleBackup"; + + +class SdLogger +{ +public: + SdLogger(); + ~SdLogger() {}; + + void Print(const char* fmt, ::std::va_list arg); + +private: + nn::fs::FileOutputStream sd; + +}; + +void InitializeEjectThread(); +// SDカードが抜けた時に呼ばれるコールバック +void SetEjectHandler(void (*func)()); +// SDカードが挿入された時に呼ばれるコールバック +void SetInsertHandler(void (*func)()); +SdLogger* GetSdInstance(); + +} // namespace Logger +} // namespace ConsoleBackup + +#endif /* SDLOGGER_H_ */ diff --git a/trunk/ConsoleDataMigration/common/SdMountManager.cpp b/trunk/ConsoleDataMigration/common/SdMountManager.cpp new file mode 100644 index 0000000..2aadcb4 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/SdMountManager.cpp @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdMountManager.cpp + + Copyright 2009 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include "SdMountManager.h" + +namespace common +{ + +u32 SdMountManager::m_MountCounter = 0; + +SdMountManager::SdMountManager() +{ + // TODO 自動生成されたコンストラクター・スタブ + +} + +SdMountManager::~SdMountManager() +{ + // TODO Auto-generated destructor stub +} + +nn::Result SdMountManager::Mount() +{ + nn::Result result = nn::ResultSuccess(); + + if(m_MountCounter == 0) + { + result = nn::fs::MountSdmc(); + } + m_MountCounter++; + + return result; +} + +nn::Result SdMountManager::Unmount() +{ + nn::Result result = nn::ResultSuccess(); + if(m_MountCounter != 0 && --m_MountCounter == 0) + { + result = nn::fs::Unmount(SDMC_ARCHIVE_NAME); + } + + return result; +} + +nn::Result SdMountManager::ForceUnmount() +{ + m_MountCounter = 0; + return nn::fs::Unmount(SDMC_ARCHIVE_NAME); +} + + +} diff --git a/trunk/ConsoleDataMigration/common/SdMountManager.h b/trunk/ConsoleDataMigration/common/SdMountManager.h new file mode 100644 index 0000000..154387f --- /dev/null +++ b/trunk/ConsoleDataMigration/common/SdMountManager.h @@ -0,0 +1,44 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdMountManager.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 SDMOUNTMANAGER_H_ +#define SDMOUNTMANAGER_H_ + +namespace common +{ + +const char* const SDMC_ARCHIVE_NAME = "sdmc:"; + +//! @brief SDカードのMount状態を管理するためのクラスです +class SdMountManager +{ +public: + SdMountManager(); + virtual ~SdMountManager(); + + //! @brief マウントが必要ならマウントします。 + static nn::Result Mount(); + //! @brief アンマウントが必要ならアンマウントします。 + static nn::Result Unmount(); + //! @brief 強制的にアンマウントします。 + static nn::Result ForceUnmount(); + +private: + static u32 m_MountCounter; +}; + +} + +#endif /* SDMOUNTMANAGER_H_ */ diff --git a/trunk/ConsoleDataMigration/common/SdReaderWriter.cpp b/trunk/ConsoleDataMigration/common/SdReaderWriter.cpp new file mode 100644 index 0000000..63f53bd --- /dev/null +++ b/trunk/ConsoleDataMigration/common/SdReaderWriter.cpp @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdReaderWriter.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 "SdReaderWriter.h" +#include "SdMountManager.h" + +namespace common +{ + +nn::Result SdReaderWriter::Initialize() +{ + nn::Result result; + + // 初期化済みなら何もしない + if(m_IsInitialized) + { + return nn::ResultSuccess(); + } + + result = SdMountManager::Mount(); + if(result.IsSuccess()) + { + m_IsInitialized = true; + return nn::ResultSuccess(); + } + else + { + return result; + } +} + + +nn::Result SdReaderWriter::Finalize() +{ + nn::Result result; + result = SdMountManager::Unmount(); + + m_IsInitialized = false; + return result; +} + +nn::Result SdReaderWriter::WriteBuf(const wchar_t* path, void* buf, size_t size) +{ + NN_ASSERT(path != NULL); + NN_ASSERT(size > 0); + + nn::Result result; + result = Initialize(); + if(result.IsFailure()) + { + nn::dbg::PrintResult(result); + } + + result = file.TryInitialize(path, nn::fs::OPEN_MODE_WRITE | nn::fs::OPEN_MODE_CREATE); + if (result.IsSuccess()) + { + s32 writeSize; + result = file.TryWrite(&writeSize, buf, size, true); + if (result.IsSuccess()) + { + result = file.TryFlush(); + if (result.IsFailure()) + { + NN_LOG("SD TryFlush failed\n"); + nn::dbg::PrintResult(result); + } + } + else + { + NN_LOG("SD TryWrite failed\n"); + nn::dbg::PrintResult(result); + } + } + else + { + NN_LOG("SD TryInitialize failed\n"); + nn::dbg::PrintResult(result); + } + + file.Finalize(); + + result = Finalize(); + if(result.IsFailure()) + { + nn::dbg::PrintResult(result); + } + + return result; +} + +nn::Result SdReaderWriter::ReadBuf(const wchar_t* path, void* buf, size_t size, size_t* totalSize) +{ + NN_ASSERT(path != NULL); + NN_ASSERT(size > 0); + + nn::Result result; + if(!m_IsInitialized) + { + Initialize(); + } + + result = file.TryInitialize(path, nn::fs::OPEN_MODE_READ); + if (result.IsSuccess()) + { + s32 readSize; + result = file.TryRead(&readSize, buf, size); + if (result.IsSuccess()) + { + // TODO バッファを超えるサイズのファイル読み込み + *totalSize = readSize; + result = file.TryFlush(); + if (result.IsFailure()) + { + NN_LOG("SD TryFlush failed\n"); + nn::dbg::PrintResult(result); + } + } + else + { + NN_LOG("SD TryRead failed\n"); + nn::dbg::PrintResult(result); + } + } + else + { + NN_LOG("SD TryInitialize failed\n"); + nn::dbg::PrintResult(result); + } + + file.Finalize(); + return result; +} + +void SdReaderWriter::CreateDirectory(const wchar_t* path) +{ + nn::Result result; + + if(!m_IsInitialized) + { + Initialize(); + } + + NN_LOG("Create Directory %ls\n", path); + result = nn::fs::TryCreateDirectory(path); + if(result.IsFailure()) + { + nn::dbg::PrintResult(result); + } + + Finalize(); +} + +} diff --git a/trunk/ConsoleDataMigration/common/SdReaderWriter.h b/trunk/ConsoleDataMigration/common/SdReaderWriter.h new file mode 100644 index 0000000..dbb2772 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/SdReaderWriter.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdReaderWriter.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 SDWRITER_H_ +#define SDWRITER_H_ + +#include + +namespace common +{ + +//! @brief SDカードに書き込むためのクラスです。 +class SdReaderWriter +{ +public : + SdReaderWriter() : m_IsInitialized(false) {}; + ~SdReaderWriter() {}; + + //! @brief 渡されたバッファからサイズ分指定されたパス名で書きこみます + //! @param[in] path sdmc:で始まる出力パス名。予めディレクトリを作っておく必要があります。 + //! @param[in] buf 入力データへのポインタ + //! @param[in] size 入力データのサイズ + nn::Result WriteBuf(const wchar_t* path, void* buf, size_t size); + + //! @brief 渡されたバッファへサイズ分指定されたパス名から読み込みます + //! @param[in] path sdmc:で始まる入力パス名 + //! @param[in] buf 出力バッファへのポインタ + //! @param[in] size バッファサイズ + //! @param[out] totalSize 読み込んだデータのサイズ + nn::Result ReadBuf(const wchar_t* path, void* buf, size_t size, size_t* totalSize); + + + //! @brief 渡されたディレクトリ名のディレクトリを作成します + void CreateDirectory(const wchar_t* path); + +private: + //! @brief 初期化します。 + nn::Result Initialize(); + + //! @brief 終了します。 + nn::Result Finalize(); + + nn::fs::FileStream file; + + NN_PADDING3; + bool m_IsInitialized; + +}; + +} + +#endif /* SDWRITER_H_ */ diff --git a/trunk/ConsoleDataMigration/common/SimplePlayer.cpp b/trunk/ConsoleDataMigration/common/SimplePlayer.cpp new file mode 100644 index 0000000..9753b92 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/SimplePlayer.cpp @@ -0,0 +1,240 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SimplePlayer.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 +#include +#include +#include +#include +#include + +#include +#include "SimplePlayer.h" +#include "wave.h" +#include "HeapManager.h" + +namespace common +{ + +namespace +{ + const int nFiles = 4; // 使用できる voice の最大値は 24 + const char* apFileNames[nFiles] = + { + "rom:/ok.wav", + "rom:/ng.wav", + "rom:/cursor.wav", + "rom:/annotation.wav" + }; + + nn::snd::CTR::Voice* apVoice[nFiles]; + nn::snd::CTR::WaveBuffer aBuffer[nFiles]; + WaveFmt fmt[nFiles]; + WaveData data[nFiles]; + u8* apMemory[nFiles]; + + nn::os::CriticalSection s_CriticalSection; + bool s_SoundThreadInitialized = false; + + // サウンドスレッド関連 + const int SOUND_THREAD_STACK_SIZE = 4096; + nn::os::StackBuffer s_SoundThreadStack; + nn::os::Thread threadSound; + bool threadSoundFlag; + void SoundThreadFunc() + { + // サウンド出力をステレオに + nn::snd::SetSoundOutputMode(nn::snd::OUTPUT_MODE_STEREO); + + // マスターボリュームを設定 + nn::snd::SetMasterVolume( 1.0 ); + + NN_LOG("Loading wav files...\n"); + + // ファイルを開く + for (int i = 0; i < nFiles; i++) + { + if (apFileNames[i] == NULL) continue; + + nn::snd::Voice* pVoice = NULL; + + nn::fs::FileReader fileReader; + nn::Result result = fileReader.TryInitialize(apFileNames[i]); + NN_UTIL_PANIC_IF_FAILED(result); + if (::std::strcmp(::std::strrchr(apFileNames[i], '.'), ".wav") == false) + { + // 連続メモリ領域の取得、確認 + apMemory[i] = reinterpret_cast(HeapManager::GetHeap()->Allocate(GetWaveLength(fileReader), 32)); + if (apMemory[i] == NULL) + { + NN_LOG("Failed to allocate continuous memory\n"); + continue; + } + + + // Wave データを読み込み、キャッシュを無効に + data[i].buf = apMemory[i]; + LoadWave(fileReader, &fmt[i], &data[i]); + nn::snd::FlushDataCache(reinterpret_cast(apMemory[i]), data[i].size); + + NN_LOG("%s (%1dch, %5dHz, %2d-bit wav file)\n", + apFileNames[i], fmt[i].channel, fmt[i].sample_rate, fmt[i].quantum_bits); + + pVoice = apVoice[i] = nn::snd::AllocVoice(128, NULL, NULL); + NN_TASSERT_(pVoice); + + nn::snd::SampleFormat format = (fmt[i].quantum_bits == 8) ? + nn::snd::SAMPLE_FORMAT_PCM8 : + nn::snd::SAMPLE_FORMAT_PCM16; + + pVoice->SetChannelCount( fmt[i].channel ); + pVoice->SetSampleFormat( format ); + + nn::snd::InitializeWaveBuffer(&aBuffer[i]); + aBuffer[i].bufferAddress = apMemory[i]; + aBuffer[i].sampleLength = nn::snd::GetSampleLength(data[i].size, format, fmt[i].channel); + aBuffer[i].loopFlag = false; + + fileReader.Finalize(); + + // 音量の設定 + nn::snd::MixParam mix; + mix.mainBus[nn::snd::CHANNEL_INDEX_FRONT_LEFT ] = 0.707f; // メインボリューム (L) + mix.mainBus[nn::snd::CHANNEL_INDEX_FRONT_RIGHT] = 0.707f; // メインボリューム (R) + pVoice->SetMixParam(mix); + pVoice->SetVolume(1.0f); + + // pitch の設定 + pVoice->SetSampleRate(fmt[i].sample_rate); + pVoice->SetPitch(1.0f); + + } + } + + // 再生開始 + for (int i = 0; i < nFiles; i++) + { + if (apFileNames[i] != NULL) + { + apVoice[i]->SetState( nn::snd::Voice::STATE_PLAY ); + } + } + + s_SoundThreadInitialized = true; + + threadSoundFlag = true; + while (threadSoundFlag) + { + nn::snd::WaitForDspSync(); // DSP からのデータ受信を待つ。 + + + s_CriticalSection.Enter(); // メインスレッドとの排他制御 + nn::snd::SendParameterToDsp(); // パラメータを DSP に送信。 + s_CriticalSection.Leave(); // メインスレッドとの排他制御 + } + + // 再生終了 + for (int i = 0; i < nFiles; i++) + { + if (apVoice[i]) + { + nn::snd::FreeVoice(apVoice[i]); + } + } + } +} + +void InitializeSimplePlayer() +{ + NN_LOG("Initialize SimplePlayer\n"); + + nn::Result result; + + const size_t ROMFS_BUFFER_SIZE = 1024 * 64; + static char buffer[ROMFS_BUFFER_SIZE]; + NN_UTIL_PANIC_IF_FAILED( + nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE)); + + // dsp, snd の初期化 + result = nn::dsp::Initialize(); + NN_UTIL_PANIC_IF_FAILED(result); + result = nn::dsp::LoadDefaultComponent(); + NN_UTIL_PANIC_IF_FAILED(result); + result = nn::snd::Initialize(); + NN_UTIL_PANIC_IF_FAILED(result); + + s_CriticalSection.Initialize(); + + // サウンドスレッドを起動(DSP 割り込みイベント待ち) + threadSound.Start(SoundThreadFunc, s_SoundThreadStack); +} + +void PlaySound(u8 index) +{ + NN_ASSERT(0 <= index <= nFiles); + + while(!s_SoundThreadInitialized) + { + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(1)); + } + + nn::snd::CTR::Voice* pVoice = apVoice[index]; + + if (!pVoice->IsPlaying()) + { + nn::snd::InitializeWaveBuffer(&aBuffer[index]); + aBuffer[index].bufferAddress = apMemory[index]; + nn::snd::SampleFormat format = (fmt[index].quantum_bits == 8) ? nn::snd::SAMPLE_FORMAT_PCM8 + : nn::snd::SAMPLE_FORMAT_PCM16; + + aBuffer[index].sampleLength = nn::snd::GetSampleLength(data[index].size, format, fmt[index].channel); + aBuffer[index].loopFlag = false; + + pVoice->AppendWaveBuffer(&aBuffer[index]); + NN_LOG("[voice%d] %s (pitch = %f)\n", + index, + (pVoice->GetState() == nn::snd::Voice::STATE_PAUSE ? "pause" : "play "), + pVoice->GetPitch()); + } +} + +void FinalizeSimplePlayer() +{ + nn::Result result; + + // サウンドスレッドの破棄 + threadSoundFlag = false; + threadSound.Join(); + + // SND の終了処理 + result = nn::snd::Finalize(); + NN_UTIL_PANIC_IF_FAILED(result); + + s_CriticalSection.Finalize(); + + // DSP の終了処理 + result = nn::dsp::UnloadComponent(); + NN_UTIL_PANIC_IF_FAILED(result); + nn::dsp::Finalize(); + + + NN_LOG("Finalize SimplePlayer\n"); + +} + +} // namespace ConsoleBackup +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ diff --git a/trunk/ConsoleDataMigration/common/SimplePlayer.h b/trunk/ConsoleDataMigration/common/SimplePlayer.h new file mode 100644 index 0000000..b7fe76e --- /dev/null +++ b/trunk/ConsoleDataMigration/common/SimplePlayer.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SimplePlayer.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 SIMPLEPLAYER_H_ +#define SIMPLEPLAYER_H_ + +namespace common +{ + +enum SoundEffect +{ + SOUND_OK, + SOUND_NG, + SOUND_CURSOR, + SOUND_ANNOTATION +}; + +void InitializeSimplePlayer(); +void FinalizeSimplePlayer(); +void PlaySound(u8 index); + +} // namespace ConsoleBackup + + +#endif /* SIMPLEPLAYER_H_ */ diff --git a/trunk/ConsoleDataMigration/common/common_Types.h b/trunk/ConsoleDataMigration/common/common_Types.h new file mode 100644 index 0000000..dcba8bf --- /dev/null +++ b/trunk/ConsoleDataMigration/common/common_Types.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: common_Types.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 COMMON_TYPES_H_ +#define COMMON_TYPES_H_ + +#include + +namespace common +{ + +const u32 NTR_WIFI_SETTING_SIZE = 0x400; // NTR Wifi 設定のサイズ +const u32 TWL_WIFI_SETTING_SIZE = 0x600; // TWL Wifi 設定のサイズ + + +// NOR領域のみにある設定データ用構造体 +struct NtrNorData +{ + nn::cfg::CTR::NtrComment comment; + u8 TwlWiFiSetting[TWL_WIFI_SETTING_SIZE]; + u8 NtrWiFiSetting[NTR_WIFI_SETTING_SIZE]; + NN_PADDING1; + u8 userColor; + +}; + + +} + +#endif /* COMMON_TYPES_H_ */ diff --git a/trunk/ConsoleDataMigration/common/configLoader.cpp b/trunk/ConsoleDataMigration/common/configLoader.cpp new file mode 100644 index 0000000..2480ca1 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/configLoader.cpp @@ -0,0 +1,153 @@ +#include +#include +#include +#include "configLoader.h" + +namespace common +{ + +Result ConfigFileLoader::Initialize(const wchar_t* fileName, void* buffer, const size_t bufferSize) +{ + s64 fileSize; + FileInputStream fi; + NN_UTIL_RETURN_IF_FAILED(fi.TryInitialize(fileName)); + NN_UTIL_RETURN_IF_FAILED(fi.TryGetSize(&fileSize)); + + if (fileSize > bufferSize) + { + NN_TLOG_("Too Large File\n"); + return Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, nn::Result::DESCRIPTION_TOO_LARGE); + } + + m_Buffer = static_cast(buffer); + NN_UTIL_RETURN_IF_FAILED(fi.TryRead(&m_UsedBufferSize, m_Buffer, fileSize)); + + return ParseData(); +} + +void ConfigFileLoader::Finalize() +{ + m_Buffer = 0; + m_ParamNum = 0; +} + +Result ConfigFileLoader::ParseData() +{ + if (!m_Buffer) + { + return Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_INVALID_STATE, nn::Result::MODULE_COMMON, nn::Result::DESCRIPTION_NOT_INITIALIZED); + } + + int pos = 0; + + // ビッグエンディアンでないことを確認 + NN_ASSERTMSG(m_Buffer[0] != 0xfffe, "Invalid Config File's Endian\n"); + + if (m_Buffer[0] == 0xfeff) + { + // UTF-16 BOMの調整 + pos++; + } + + m_ParamNum = 0; + m_ParamName[m_ParamNum] = &(m_Buffer[pos]); + m_ParamValue[m_ParamNum] = L'\0'; + + // ダブルクウォート中なら : も文字として読み取る + bool inEscape = false; + // # で行末までコメント + bool inComment = false; + + while (pos < m_UsedBufferSize / sizeof(m_Buffer[0])) + { + switch (m_Buffer[pos]) + { + case L'"': + { + inEscape = !inEscape; + } + break; + + case L'#': + { + inComment = true; + } + break; + + case L':': + { + if(inEscape || inComment) + { + break; + } + m_Buffer[pos] = L'\0'; + m_ParamValue[m_ParamNum++] = &(m_Buffer[pos + 1]); + } + + break; + case L'\r': + case L'\n': + { + if(inComment) + { + inComment = false; + } + m_Buffer[pos] = L'\0'; + m_ParamName[m_ParamNum] = &(m_Buffer[pos + 1]); + m_ParamValue[m_ParamNum] = L'\0'; + } + break; + + } + pos++; + } + + return ResultSuccess(); +} + +s32 ConfigFileLoader::SearchParamName(const wchar_t *paramName) +{ + if (!m_Buffer) + { + NN_TLOG_("ConfigFileLoader not initialized.\n"); + return -1; + } + + for (s32 i = 0; i < m_ParamNum; i++) + { + if (wcscmp(m_ParamName[i], paramName) == 0) + { + return i; + } + } + return -1; +} + +const wchar_t *ConfigFileLoader::ReadAsWChar(const wchar_t *paramName) +{ + s32 idx = SearchParamName(paramName); + if (idx < 0) + { + NN_LOG("Unknown Parameter Name %ls\n", paramName); + } + return (idx < 0) ? L'\0' : m_ParamValue[idx]; +} + +const char *ConfigFileLoader::ReadAsChar(const wchar_t *paramName) +{ + memset(m_ReadCharBuffer, 0, sizeof(m_ReadCharBuffer)); + const wchar_t *value = ReadAsWChar(paramName); + if(value == L'\0') + { + return NULL; + } + wcstombs(m_ReadCharBuffer, value, wcslen(value)); + return m_ReadCharBuffer; +} + +int ConfigFileLoader::ReadAsInteger(const wchar_t *paramName) +{ + return atoi(ReadAsChar(paramName)); +} + +} diff --git a/trunk/ConsoleDataMigration/common/configLoader.h b/trunk/ConsoleDataMigration/common/configLoader.h new file mode 100644 index 0000000..560e142 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/configLoader.h @@ -0,0 +1,79 @@ +#ifndef NN_CONFIG_LOADER_H_ +#define NN_CONFIG_LOADER_H_ + + +namespace common +{ + using namespace nn; + using namespace nn::fs; + using namespace std; + +class ConfigFileLoader +{ +private: + static const int PARAM_NAME_MAX_STRING_LENGTH = 16; + static const int PARAM_VALUE_MAX_STRING_LENGTH = 128; + static const int PARAM_MAX_NUM = 64; + + char m_ReadCharBuffer[PARAM_VALUE_MAX_STRING_LENGTH]; + wchar_t *m_ParamName[PARAM_MAX_NUM]; + wchar_t *m_ParamValue[PARAM_MAX_NUM]; + wchar_t *m_Buffer; + + s32 m_UsedBufferSize; + s32 m_ParamNum; + +public: + ConfigFileLoader() : m_Buffer(0), m_UsedBufferSize(0), m_ParamNum(0) + { + } + +/* + @brief ConfigFileLoader を初期化します. + + 使用するファイルが存在するアーカイブは,あらかじめマウントしておく必要があります. + 読み込みに使用するバッファを確保し,引数 buffer に与える必要があります. + Finalize を呼ぶまでこのバッファは開放しないでください. + + 読み込ませることのできるフォーマット + ・エンコーディング:UTF-16 + ・バイトオーダ  :リトルエンディアン + ・改行記号    :不問 + + 半角コロンを含む行のみパラメータ記述行として読み込み,含まない行は無視します. + 半角コロンより前の文字はすべてパラメータ名として取得し, + 半角コロンより後の文字はすべてパラメータの値として取得します. + ParameterName : ParameterValue; + と記述すると + パラメータ名は L"ParameterName " + パラメータ値は L" ParameterValue;" + となります. + + @param[in] fileName 設定ファイル名 + @param[in] buffer ファイル読み込み用のバッファ + @param[in] bufferSize 上記 buffer の大きさ + + @return 結果を返します. + +*/ + Result Initialize(const wchar_t* fileName, void* buffer, const size_t bufferSize); + void Finalize(); + + // スレッドセーフです. + const wchar_t *ReadAsWChar(const wchar_t *paramName); + + // スレッドセーフではありません. + const char *ReadAsChar(const wchar_t *paramName); + + // スレッドセーフです. + int ReadAsInteger(const wchar_t *paramName); + +private: + Result ParseData(); + s32 SearchParamName(const wchar_t *paramName); +}; + +} + + +#endif // NN_CONFIG_LOADER_H_ diff --git a/trunk/ConsoleDataMigration/common/romfiles/annotation.wav b/trunk/ConsoleDataMigration/common/romfiles/annotation.wav new file mode 100644 index 0000000..b64f77b Binary files /dev/null and b/trunk/ConsoleDataMigration/common/romfiles/annotation.wav differ diff --git a/trunk/ConsoleDataMigration/common/romfiles/cursor.wav b/trunk/ConsoleDataMigration/common/romfiles/cursor.wav new file mode 100644 index 0000000..85765b3 Binary files /dev/null and b/trunk/ConsoleDataMigration/common/romfiles/cursor.wav differ diff --git a/trunk/ConsoleDataMigration/common/romfiles/ng.wav b/trunk/ConsoleDataMigration/common/romfiles/ng.wav new file mode 100644 index 0000000..dc2f3ef Binary files /dev/null and b/trunk/ConsoleDataMigration/common/romfiles/ng.wav differ diff --git a/trunk/ConsoleDataMigration/common/romfiles/ok.wav b/trunk/ConsoleDataMigration/common/romfiles/ok.wav new file mode 100644 index 0000000..bf5149f Binary files /dev/null and b/trunk/ConsoleDataMigration/common/romfiles/ok.wav differ diff --git a/trunk/ConsoleDataMigration/common/wave.cpp b/trunk/ConsoleDataMigration/common/wave.cpp new file mode 100644 index 0000000..a897109 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/wave.cpp @@ -0,0 +1,150 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: wave.c + + 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$ + *---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* includes */ +#include "wave.h" + +/*---------------------------------------------------------------------------*/ +/* functions */ + +/*---------------------------------------------------------------------------* + Name: LoadWave + + Description: Wave データを読み込む. + + Arguments: filepath : ファイルパス + fmt : Wave データの fmt チャンクを格納 + data : Wave データの data チャンクを格納 + + Returns: None. + *---------------------------------------------------------------------------*/ +void LoadWaveCore(nn::fs::FileReader& reader, WaveFmt * fmt, WaveData * data, bool isSizeOnly) +{ + reader.SetPosition(0); + + WaveRiff riff; // RIFF ヘッダ + WaveChunk chunk; // CHUNK + u32 readbyte = 0; // ファイル読み込みの判定に使用 + u32 fsize = reader.GetSize(); + + // RIFF ヘッダ読み込み + reader.Read((u8*)&riff, sizeof(WaveRiff)); + + // サイズを積算 + readbyte += sizeof(WaveRiff); + + // "RIFF" との一致を確認 + if (riff.tag != MAKE_WAVE_TAG_VALUE('R','I','F','F')) + { + NN_PANIC("Not RIFF format.\n"); + } + // "WAVE" との一致を確認 + if ( riff.type != MAKE_WAVE_TAG_VALUE('W','A','V','E') ) + { + NN_PANIC("Not Wave format.\n"); + } + + // ファイルサイズより大きくなるまで読み込む + while(fsize > readbyte) + { + // CHUNK の読み込み + reader.Read((u8*)&chunk, sizeof(WaveChunk)); + readbyte += sizeof(WaveChunk); + + // "fmt " + if (chunk.tag == MAKE_WAVE_TAG_VALUE('f','m','t',' ')) + { + reader.Read((u8*)fmt, sizeof(WaveFmt)); + readbyte += sizeof(WaveFmt); + + // 拡張領域があれば読み捨て + if (chunk.size > sizeof(WaveFmt)) + { + u16 ext_size; + + reader.Read((u8*)&ext_size, sizeof(ext_size)); + readbyte += sizeof(ext_size); + + readbyte += chunk.size; + if (readbyte == fsize) break; + + reader.Seek(ext_size, nn::fs::POSITION_BASE_CURRENT); + } + } + // "data" + else if (chunk.tag == MAKE_WAVE_TAG_VALUE('d','a','t','a')) + { + data->size = chunk.size; + + if (isSizeOnly) + { + return; + } + else + { + reader.Read((u8*)data->buf, data->size); + // 8-bit wav ファイルの場合は unsigned -> signed の変換が必要 + if (fmt->quantum_bits == 8) + { + s8* p = (s8*)data->buf; + for (int i = 0; i < data->size; i++) + { + p[i] -= 128; + } + } + } + readbyte += chunk.size; + } + // それ以外 + else + { + readbyte += chunk.size; + if (readbyte == fsize) break; + + // 読み飛ばす + reader.Seek(chunk.size, nn::fs::POSITION_BASE_CURRENT); + } + } +} + +#ifndef NN_BUILD_RELEASE // Release ビルドでは HostIO は使えません。 +void WriteWaveHeader(nn::hio::CTR::HostFile& hostFile, WaveFmt* fmt, s32 size) +{ + WaveRiff riff; + riff.tag = MAKE_WAVE_TAG_VALUE('R','I','F','F'); + riff.size = + + sizeof(WaveRiff) // riff header + + sizeof(WaveChunk) + sizeof(WaveFmt) // wave fmt header + + sizeof(WaveChunk) + size // wave data + - 8; + riff.type = MAKE_WAVE_TAG_VALUE('W','A','V','E'); + hostFile.Write(&riff, sizeof(WaveRiff)); + + WaveChunk chunk; + chunk.tag = MAKE_WAVE_TAG_VALUE('f','m','t',' '); + chunk.size = sizeof(WaveFmt); + hostFile.Write(&chunk, sizeof(WaveChunk)); + hostFile.Write(fmt, sizeof(WaveFmt)); + + chunk.tag = MAKE_WAVE_TAG_VALUE('d','a','t','a'); + chunk.size = size; + hostFile.Write(&chunk, sizeof(WaveChunk)); +} +#endif // NN_BUILD_RELEASE + +/*---------------------------------------------------------------------------*/ +/* end of file */ +/*---------------------------------------------------------------------------*/ diff --git a/trunk/ConsoleDataMigration/common/wave.h b/trunk/ConsoleDataMigration/common/wave.h new file mode 100644 index 0000000..cbaf2f3 --- /dev/null +++ b/trunk/ConsoleDataMigration/common/wave.h @@ -0,0 +1,148 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: wave.h + + 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$ + *---------------------------------------------------------------------------*/ + +#ifndef __WAVE_HEADER__ +#define __WAVE_HEADER__ + +/*---------------------------------------------------------------------------*/ +/* includes */ +#include +#include +#ifndef NN_BUILD_RELEASE // Release ビルドでは HostIO は使えません。 +#include +#endif // NN_BUILD_RELEASE + +/*---------------------------------------------------------------------------*/ +/* constants */ + +#define MAKE_WAVE_TAG_VALUE(c1, c2, c3, c4) \ + ( c1 | (c2<<8) | (c3<<16) | (c4<<24) ) + +#define MAKE_WAVE_TAG_STRING(str, val) \ + { \ + str[3] = (char) ( (val>>24)&0xff ) ; \ + str[2] = (char) ( (val>>16)&0xff ) ; \ + str[1] = (char) ( (val>> 8)&0xff ) ; \ + str[0] = (char) ( (val )&0xff ) ; \ + str[4] = (char) ( 0 ) ; \ + } + +#define MAKE_FMT_CHUNK(ch, s) \ + { \ + ch.tag = MAKE_WAVE_TAG_VALUE('f', 'm', 't', ' '); \ + ch.size = s; \ + } + +#define MAKE_DATA_CHUNK(ch, s) \ + { \ + ch.tag = MAKE_WAVE_TAG_VALUE('d', 'a', 't', 'a'); \ + ch.size = s; \ + } + +#define saturate(v, min, max) \ + { \ + if ( v < min ) {v = min;} \ + else if ( v > max ) {v = max;} \ + } + +#define swap(v,t) swap_##t##_(v) + +#define swap_u16_(v) \ + { \ + v = (u16)(((v)>> 8)&0x00ff | \ + ((v)<< 8)&0xff00); \ + } + +#define swap_s16_(v) \ + { \ + v = (s16)(((v)>> 8)&0x00ff | \ + ((v)<< 8)&0xff00); \ + } + +#define swap_u32_(v) \ + { \ + v = (u32)(((v)>>24)&0x000000ff | \ + ((v)>> 8)&0x0000ff00 | \ + ((v)<< 8)&0x00ff0000 | \ + ((v)<<24)&0xff000000); \ + } + +#define swap_s32_(v) \ + { \ + v = (s32)(((v)>>24)&0x000000ff | \ + ((v)>> 8)&0x0000ff00 | \ + ((v)<< 8)&0x00ff0000 | \ + ((v)<<24)&0xff000000); \ + } + +/*---------------------------------------------------------------------------*/ +/* typedef */ +typedef struct _riff +{ + u32 tag; + u32 size; + u32 type; +} +WaveRiff; + +typedef struct _chunk +{ + u32 tag; + u32 size; +} +WaveChunk; + +typedef struct _fmt +{ + u16 fmt_id; + u16 channel; + u32 sample_rate; + u32 trans_rate; + u16 block_size; + u16 quantum_bits; +} +WaveFmt; + +typedef struct _data +{ + u32 size; + u8* buf; +} +WaveData; + +/*---------------------------------------------------------------------------*/ +/* prototype */ + +void LoadWaveCore(nn::fs::FileReader&, WaveFmt*, WaveData*, bool); +static inline void LoadWave(nn::fs::FileReader& reader, WaveFmt* fmt, WaveData* data) +{ + LoadWaveCore(reader, fmt, data, false); +} +static inline int GetWaveLength(nn::fs::FileReader& reader) +{ + WaveFmt fmt; + WaveData data; + LoadWaveCore(reader, &fmt, &data, true); + return data.size; +} +#ifndef NN_BUILD_RELEASE // Release ビルドでは HostIO は使えません。 +void WriteWaveHeader(nn::hio::CTR::HostFile& hostFile, WaveFmt* fmt, s32 size); +#endif // NN_BUILD_RELEASE + +#endif // __WAVE_HEADER__ + +/*---------------------------------------------------------------------------*/ +/* end of file */ +/*---------------------------------------------------------------------------*/