/*---------------------------------------------------------------------------* 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 #include #include "demo.h" #include #include #include "ConsoleBackup.h" #include "DrawSystemState.h" #include "FileName.h" #include "Controller.h" #include "SimplePlayer.h" #include "Exporter.h" #include "CommonLogger.h" #include "SDMountManager.h" #include "HeapManager.h" #include "PlayHistoryManager.h" #include "common_Types.h" #include "VersionDetect.h" #include "HardwareInfo.h" // svnリビジョン埋め込み用 #include "version.h" #ifndef BACKUP_VERSION_NUM #define BACKUP_VERSION_NUM 0 #endif namespace { // グラフィックスに割り当てるメモリ const size_t s_GxHeapSize = 0x800000; // バッテリ残量 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; nn::Handle s_McuSession; } // namespace namespace ConsoleBackup{ 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; } nn::Handle GetMcuHandle() { return s_McuSession; } 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(&s_McuSession); nn::mcu::CTR::HwCheck mcu(s_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::GetLoggerInstance()->ClearLog(); 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; } common::HeapManager::GetHeap()->Free(addr); } } 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__); common::HardwareInfo hwInfo; hwInfo.AddCheckDigit(reinterpret_cast(s_SerialNo)); // デバイス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::VerDef mVerData; common::GetSystemVersion(&mVerData, region); // 情報出力 COMMON_LOGGER("CTR Console Backup %s Rev.%s\n", __DATE__, BACKUP_VERSION_NUM); COMMON_LOGGER("System Ver. %d.%d.%d-%d\n", mVerData.cup.majorVersion, mVerData.cup.minorVersion, mVerData.cup.microVersion, mVerData.nup.majorVersion); 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); nn::util::FloatColor titleColor; titleColor.r = 0.3f; titleColor.g = 0.f; titleColor.b = 0.2f; // 上画面表示 common::DrawSystemState("CTR Console Backup", s_RenderSystem, titleColor, flip, adapterState, BACKUP_VERSION_NUM, &mVerData, batteryRemain, deviceId, friendCode, GetProgress(), IsBackupFailed(), IsBackupSucceeded(), macAddress, operationMessage, region, rosi, s_SerialNo ); s_RenderSystem.SwapBuffers(); // デフォルトで下画面に描画するもの s_RenderSystem.SetRenderTarget(common::GetRenderTarget(NN_GX_DISPLAY1, flip)); if(IsBackupSucceeded()) { s_RenderSystem.SetClearColor(common::GetRenderTarget(NN_GX_DISPLAY1, flip), SUCCESS_COLOR); } if(IsBackupFailed()) { s_RenderSystem.SetClearColor(common::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(&s_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(); } } } }