本体データ移行ツールを追加

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@2 385bec56-5757-e545-9c3a-d8741f4650f1
This commit is contained in:
N2614 2011-01-28 10:46:13 +00:00
parent ed25ddbd53
commit 5ed32bde66
64 changed files with 6835 additions and 0 deletions

View File

@ -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 <nn.h>
#include <nn/version.h>
#include <nn/ptm/CTR/ptm_ApiSysmenu.h>
#include <nn/mcu.h>
#include <nn/cfg/CTR/cfg_Api.h>
#include <nn/cfg/CTR/cfg_ApiInit.h>
#include <nn/cfg/CTR/cfg_ApiSys.h>
#include <nn/ps.h>
#include <nn/nwm.h>
#include <nn/ac.h>
#include <nn/friends.h>
#include <nn/friends/CTR/friends_ApiPrivate.h>
#include <nn/fs/CTR/fs_ArchiveTypesForSystem.h>
#include <nn/fs/CTR/MPCore/fs_FileSystemBasePrivate.h>
#include <nn/fs/fs_ApiSysSaveData.h>
#include <nn/cfg/CTR/cfg_ApiNor.h>
#include <nn/os/os_SharedInfo.h>
#include "demo.h"
#include <vector>
#include <string>
#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 <unnamed>
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<uptr>(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<u32>(friendCode / 100000000ULL % 10000ULL),
static_cast<u32>(friendCode / 10000ULL % 10000ULL),
static_cast<u32>(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<std::string> 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<u32>(friendCode / 100000000ULL % 10000ULL),
static_cast<u32>(friendCode / 10000ULL % 10000ULL),
static_cast<u32>(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<std::string>::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();
}
}
}
}

View File

@ -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 <nn.h>
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

View File

@ -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)"

View File

@ -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 <nn.h>
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 <unnamed>
bool NeedsAcAdateper()
{
return IsBatteryLower() && !IsAdapterConnected();
}
void ControlState(::std::vector<std::string>& 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

View File

@ -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 <vector>
#include <string>
namespace ConsoleBackup
{
void ControlState(::std::vector<std::string>& operationMessage, bool& nextStep, bool& continueBackup);
bool InProgress();
bool IsBackupSucceeded();
bool IsBackupFailed();
void OnSdEjected();
void InitializeState();
}
#endif /* CONTOROLLER_H_ */

View File

@ -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 <vector>
#include <cstdlib>
#include <cwchar>
#include <string>
#include <cstdlib>
#include <nn/fs/CTR/fs_ArchiveTypesForSystem.h>
#include <nn/fs/CTR/MPCore/fs_FileSystemBasePrivate.h>
#include <nn/cfg/CTR/cfg_ApiNor.h> // cfg:norの初期化に必要
#include <nn/cfg/CTR/cfg_NtrSettings.h>
#include <nn/ps/CTR/ps_API.h>
#include <nn/drivers/aes/CTR/ARM946ES/driverAes_Types.h>
#include <nn/crypto/crypto_SwAesCtrContext.h>
#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<EXPORT_THREAD_STACK_SIZE> 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<nn::fs::DirectoryEntry> entryList; //カレントディレクトリのエントリ一覧を格納
std::vector<nn::fs::DirectoryEntry>::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<bit8*> (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<char> (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;
}
}

View File

@ -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 <nn.h>
namespace ConsoleBackup
{
void ExportData();
u32 GetProgress();
bool IsExportFinished();
void FinalizeExportThread();
}
#endif /* EXPORTER_H_ */

View File

@ -0,0 +1,78 @@
#!/usr/bin/env omake
#----------------------------------------------------------------------------
# Project: Horizon
# File: OMakefile
#
# Copyright (C)2009 Nintendo Co., Ltd. All rights reserved.
#
# These coded instructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Rev$
#----------------------------------------------------------------------------
SUPPORTED_TARGETS = CTR-T*.Process.MPCore.*
#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)

View File

@ -0,0 +1,3 @@
#!/bin/bash -f
echo "#define BACKUP_VERSION_NUM \"`svnversion -n`\"" > version.h

View File

@ -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 <nn.h>
#include <nn/version.h>
#include <nn/ptm/CTR/ptm_ApiSysmenu.h>
#include <nn/mcu.h>
#include <nn/cfg/CTR/cfg_Api.h>
#include <nn/cfg/CTR/cfg_ApiInit.h>
#include <nn/cfg/CTR/cfg_ApiSys.h>
#include <nn/ps.h>
#include <nn/nwm.h>
#include <nn/ac.h>
#include <nn/friends.h>
#include <nn/friends/CTR/friends_ApiPrivate.h>
#include <nn/fs/CTR/fs_ArchiveTypesForSystem.h>
#include <nn/fs/CTR/MPCore/fs_FileSystemBasePrivate.h>
#include <nn/fs/fs_ApiSysSaveData.h>
#include <nn/cfg/CTR/cfg_ApiNor.h>
#include <nn/am/am_ApiSystemMenu.h>
#include <nn/os/os_SharedInfo.h>
#include "demo.h"
#include <vector>
#include <string>
#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 <unnamed>
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<uptr>(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<u32>(friendCode / 100000000ULL % 10000ULL),
static_cast<u32>(friendCode / 10000ULL % 10000ULL),
static_cast<u32>(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<std::string> 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<u32>(friendCode / 100000000ULL % 10000ULL),
static_cast<u32>(friendCode / 10000ULL % 10000ULL),
static_cast<u32>(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<std::string>::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();
}
}
}
}

View File

@ -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 <nn.h>
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

View File

@ -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)"

View File

@ -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 <nn.h>
#include <nn/ns.h>
#include <nn/CTR/CTR_DeliverArg.h>
#include <nn/fs/CTR/MPCore/fs_FileSystemBasePrivate.h>
#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 <unnamed>
bool NeedsAcAdater()
{
return IsBatteryLower() && !IsAdapterConnected();
}
bool CheckAndReadAPSetting(::std::vector<std::string>& 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<std::string>& 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<char*> (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

View File

@ -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 <nn.h>
#include <vector>
#include <string>
namespace ConsoleRestore
{
const u32 RETRY_MAX = 10;
void ControlState(::std::vector<std::string>& operationMessage, bool& nextStep, bool& continueRestore);
bool InProgress();
bool IsRestoreSucceeded();
bool IsRestoreFailed();
u32 GetProgress();
void OnSdEjected();
void InitializeState();
}
#endif /* CONTOROLLER_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -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 <nn.h>
#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_ */

View File

@ -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 <nn.h>
#include <nn/socket.h>
#include <nn/ac.h>
#include <nn/ptm.h>
#include <nn/ptm/CTR/ptm_ApiSysmenu.h>
#include <nn/ac/CTR/private/ac_InternalApi.h>
#include <nn/ac/CTR/private/ac_NetworkSetting.h>
#include <nn/math.h>
#include "Importer.h"
#include "CommonLogger.h"
namespace ConsoleRestore
{
namespace {
const size_t NTP_THREAD_STACK_SIZE = 0x1000;
nn::os::Thread s_NtpThread;
nn::os::StackBuffer<NTP_THREAD_STACK_SIZE> s_NtpThreadStack;
bool s_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<uptr>(reinterpret_cast<uptr> (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<u8*> (&addr), reinterpret_cast<u8*> (&netmask));
NN_ASSERT(ret == 0);
COMMON_LOGGER("host : %s\n", nn::socket::InetNtoA(addr));
COMMON_LOGGER("netmask : %s\n", nn::socket::InetNtoA(netmask));
nn::socket::InAddr dns1, dns2;
ret = nn::socket::GetResolver(reinterpret_cast<u8*> (&dns1), reinterpret_cast<u8*> (&dns2));
if (ret == 0)
{
COMMON_LOGGER("dns1 : %s\n", nn::socket::InetNtoA(dns1));
COMMON_LOGGER("dns2 : %s\n", nn::socket::InetNtoA(dns2));
}
nn::socket::InAddr gateway;
ret = nn::socket::GetDefaultGateway(reinterpret_cast<u8*> (&gateway));
if (ret == 0)
{
COMMON_LOGGER("gateway : %s\n", nn::socket::InetNtoA(gateway));
}
COMMON_LOGGER("\n");
#ifndef NN_SWITCH_DISABLE_DEBUG_PRINT
nn::socket::DumpRoutingTable();
#endif
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<u64 *> (serverHostent->addrList[0]));
}
serverSockAddrIn.addr.addr = serveraddr;
COMMON_LOGGER("Destination address: %s\n", nn::socket::InetNtoA(serverSockAddrIn.addr));
serverSockAddrIn.port = nn::socket::HtoNs(NTP_PORT_NUM); // ポート番号
// NTPパケットをSNTP用に初期化する
s_NTPSendPacket.controlWord = nn::socket::HtoNl(0x0B000000);
s_NTPSendPacket.rootDelay = 0;
s_NTPSendPacket.rootDispersion = 0;
s_NTPSendPacket.referenceId = 0;
s_NTPSendPacket.referenceTimestamp = 0;
s_NTPSendPacket.startTimestamp = 0;
s_NTPSendPacket.receiveTimestamp = 0;
s_NTPSendPacket.transmitTimestampSeconds = 0;
s_NTPSendPacket.transmitTimestampFractions = 0;
// サーバを指定してNTPパケットを送信する
if ((ret = nn::socket::SendTo(socket, reinterpret_cast<const void*> (&s_NTPSendPacket), sizeof(s_NTPSendPacket), 0,
&serverSockAddrIn)) < 0)
{
COMMON_LOGGER("Error: Failed Send to Server, %d\n", ret);
}
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<void*> (&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);
}
}

View File

@ -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_ */

View File

@ -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)

View File

@ -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 <nn/os.h>
#include <nn/Handle.h>
#include <nn/dbg.h>
#include <nn/nim.h>
#include <nn/cfg.h>
#include <nn/cfg/CTR/cfg_ApiInit.h>
#include <nn/ac/private/ac.h>
#include <nn/ac/CTR/private/ac_InternalApi.h>
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<UPDATER_THREAD_STACK_SIZE> 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;
}
}

View File

@ -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 <nn.h>
namespace ConsoleRestore
{
void StartFGNetworkUpdate();
void FinishFGNetworkUpdate();
bool IsNetworkUpdateFinished();
u32 GetUpdateProgress();
nn::Result GetUpdateResult();
}
#endif /* UPDATER_H_ */

View File

@ -0,0 +1,3 @@
#!/bin/bash -f
echo "#define RESTORE_VERSION_NUM \"`svnversion -n`\"" > version.h

View File

@ -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()

View File

@ -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:$
#----------------------------------------------------------------------------
# ディレクトリレイアウトについての説明
#
# a) ソースコードがルートディレクトリ直下に配置される場合
# 例:
# /OMakeroot
# /foo/bar/OMakefile
#
# 結果:
# OMakefile と同じディレクトリ以下に objects や images が生成されます。
#
# /foo/bar/objects/...
# /foo/bar/images/..
#
#
# b) ソースコードが sources 以下に配置される場合
# 例:
# /OMakeroot
# /sources/foo/bar/OMakefile
#
# 結果:
# ルートディレクトリ以下に objects や images が生成されます。
#
# /objects/foo/bar/...
# /images/foo/bar/...
#
#
# ルート環境変数の取得
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 が一致しません。同じパスを設定するか、どちらか一方だけを定義して下さい。)
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: .

View File

@ -0,0 +1,10 @@
【ビルド環境】
・SDK
Horizon 0_14 branch r33437
+ Horizon trunk r33597のcfgライブラリの変更をマージ
+ Horizon 1_0 branch r33839のRepairTool.descをマージ
・cygwin
・svnversion

View File

@ -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_ */

View File

@ -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;
}
}
}

View File

@ -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 <nn.h>
#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_ */

View File

@ -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_ */

View File

@ -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 <vector>
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<nn::fs::DirectoryEntry> entryList; //カレントディレクトリのエントリ一覧を格納
std::vector<nn::fs::DirectoryEntry>::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;
}
}

View File

@ -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 <nn.h>
#include <string>
#include <sstream>
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_ */

View File

@ -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;
}
}

View File

@ -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 <nn.h>
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_ */

View File

@ -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 <nn/nstd.h>
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<std::string>::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<std::string>::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

View File

@ -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 <vector>
#include <string>
#include <nn/fnd.h>
#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<std::string> 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_ */

View File

@ -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_ */

View File

@ -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()

View File

@ -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 <string>
#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<SDMC_EVENT_THREAD_STACK_SIZE> s_SdmcEjectedEventThreadStack;
nn::os::Thread s_SdmcInsertedEventThread;
nn::os::StackBuffer<SDMC_EVENT_THREAD_STACK_SIZE> 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

View File

@ -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 <nn.h>
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_ */

View File

@ -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 <nn.h>
#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);
}
}

View File

@ -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_ */

View File

@ -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();
}
}

View File

@ -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 <nn.h>
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_ */

View File

@ -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 <nn.h>
#include <nn/os.h>
#include <nn/fnd.h>
#include <nn/fs.h>
#include <nn/hid.h>
#include <nn/snd.h>
#include <string.h>
#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<SOUND_THREAD_STACK_SIZE> 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<u8*>(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<uptr>(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
*---------------------------------------------------------------------------*/

View File

@ -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_ */

View File

@ -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 <nn/cfg/CTR/cfg_NtrSettings.h>
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_ */

View File

@ -0,0 +1,153 @@
#include <wchar.h>
#include <nn/fs.h>
#include <cstdlib>
#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<wchar_t*>(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));
}
}

View File

@ -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_

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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 */
/*---------------------------------------------------------------------------*/

View File

@ -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 <nn/types.h>
#include <nn/fs.h>
#ifndef NN_BUILD_RELEASE // Release ビルドでは HostIO は使えません。
#include <nn/hio.h>
#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 */
/*---------------------------------------------------------------------------*/