/*---------------------------------------------------------------------------* Project: Horizon File: SaveDataMover.cpp Copyright 2009-2011 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev$ *---------------------------------------------------------------------------*/ #include #include #include #include #include "SaveDataMover.h" #include "CommonLogger.h" #include "FileName.h" #include "SdReaderWriter.h" namespace common { namespace { const s32 MAX_SYSTEM_SAVE_DATA_ID_NUM = 256; nn::fs::SystemSaveDataId s_SystemSaveDataIdList[MAX_SYSTEM_SAVE_DATA_ID_NUM * sizeof(bit32)]; bool IsNotMovedId(bit32 id) { return id == 0x0001002c; // nim } } SaveDataMover::SaveDataMover() : m_Progress(0), m_FinishedSize(0), m_TotalSize(0), m_Result(nn::ResultSuccess()) { // TODO 自動生成されたコンストラクター・スタブ } SaveDataMover::~SaveDataMover() { // TODO Auto-generated destructor stub } void SaveDataMover::StartExport(void* buf, size_t bufSize, u64* progress) { SetupExport(); CalculateFileSize(); if(GetLastResult().IsFailure()) { return; } ExportSystemSaveData(buf, bufSize, progress); } nn::Result SaveDataMover::GetLastResult() { return m_Result; } void SaveDataMover::SetupExport() { // 1. デーモンの停止 m_Result = nn::ndm::Initialize(); COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); m_Result = nn::ndm::SuspendScheduler(); COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); // 2. StartDeviceMoveAsSource nn::fs::DeviceMoveContext moveContext; m_Result = nn::fs::StartDeviceMoveAsSource(&moveContext); COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); // 3. 出力用ディレクトリの作成 common::SdReaderWriter sdWriter; m_Result = sdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( common::SD_SAVEDATA_ROOT_NAME) + std::wstring(common::SD_SAEVDATA_SYS_NAME)).c_str()); COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); } void SaveDataMover::CalculateFileSize() { s32 systemSaveDataIdNum; m_Result = nn::fs::EnumerateSystemSaveData(&systemSaveDataIdNum, s_SystemSaveDataIdList, MAX_SYSTEM_SAVE_DATA_ID_NUM); COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); for(int i = 0; i < systemSaveDataIdNum; ++i) { nn::fs::FileInputStream input; bit32 id = s_SystemSaveDataIdList[i]; if(IsNotMovedId(id)) { continue; } m_Result = nn::fs::OpenSystemSaveDataRawStorageFile(&input, id); if(m_Result.IsFailure()) { COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(m_Result); continue; } m_TotalSize += input.GetSize(); } } void SaveDataMover::ExportSystemSaveData(void* buf, size_t bufSize, u64* progress) { s64 totalFileSize = 0; // 0. ID の列挙を行う。 s32 systemSaveDataIdNum; m_Result = nn::fs::EnumerateSystemSaveData(&systemSaveDataIdNum, s_SystemSaveDataIdList, MAX_SYSTEM_SAVE_DATA_ID_NUM); COMMON_LOGGER_RETURN_VOID_IF_FAILED(m_Result); for(int i = 0; i < systemSaveDataIdNum; ++i) { nn::fs::FileInputStream input; bit32 id = s_SystemSaveDataIdList[i]; if(IsNotMovedId(id)) { continue; } NN_LOG("id: %08x\n", id); // 1. fs::OpenSystemSaveDataRawStorageFile を呼び // ID に対するセーブデータの FileInputStream を得る。 m_Result = nn::fs::OpenSystemSaveDataRawStorageFile(&input, id); if(m_Result.IsFailure()) { COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(m_Result); continue; } NN_LOG("fileSize = %lld\n", input.GetSize()); totalFileSize += input.GetSize(); // SD へコピー { char outPath[64]; nn::nstd::TSNPrintf(outPath, 64, "%s/%08x", SD_SAVEDATA_SYS_ROOT_PATH, id); NN_LOG("outPath = %s\n", outPath); nn::fs::FileOutputStream output; m_Result = output.TryInitialize(outPath, true); if(m_Result.IsFailure()) { COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(m_Result); continue; } // 2. 1 で得たストリームからデータを読み込む。 // 本来はここで読み込んだデータを引っ越し先に転送するが // ここでは SD カードにエクスポートする。 m_Result = CopyFile(input, output, buf, bufSize, progress); if(m_Result.IsFailure()) { COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(m_Result); continue; } } } NN_LOG("\n"); NN_LOG("totalFileSize = %lld\n", totalFileSize); } // ファイルの読み書き nn::Result SaveDataMover::CopyFile(nn::fs::FileInputStream& is, nn::fs::FileOutputStream& os, void* pBuffer, const s32 bufferSize, u64* progress) { s64 restSize; NN_UTIL_RETURN_IF_FAILED(is.TryGetSize(&restSize)); while (restSize > 0) { s32 readSize = restSize > bufferSize ? bufferSize : restSize; s32 read = 0; s32 write = 0; NN_UTIL_RETURN_IF_FAILED(is.TryRead(&read, pBuffer, readSize)); NN_UTIL_RETURN_IF_FAILED(os.TryWrite(&write, pBuffer, read)); restSize -= read; m_FinishedSize += read; *progress = m_FinishedSize * 100 / m_TotalSize; NN_LOG("progress = %lld\n", *progress); } return nn::ResultSuccess(); } } /* namespace common */