mirror of
https://github.com/rvtr/ctr_Repair.git
synced 2025-10-31 13:51:08 -04:00
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@843 385bec56-5757-e545-9c3a-d8741f4650f1
287 lines
9.1 KiB
C++
287 lines
9.1 KiB
C++
/*---------------------------------------------------------------------------*
|
|
Project: Horizon
|
|
File: ActCompleter.cpp
|
|
|
|
Copyright (C)2013 Nintendo Co., Ltd. All rights reserved.
|
|
|
|
These coded instructions, statements, and computer programs contain
|
|
proprietary information of Nintendo of America Inc. and/or Nintendo
|
|
Company Ltd., and are protected by Federal copyright law. They may
|
|
not be disclosed to third parties or copied or duplicated in any form,
|
|
in whole or in part, without the prior written consent of Nintendo.
|
|
|
|
$Rev$
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
#include "ActCompleter.h"
|
|
#include "Util.h"
|
|
#include "CommonLogger.h"
|
|
#include "HeapManager.h"
|
|
#include <nn/ac/CTR/private/ac_InternalApi.h>
|
|
#include <nn/act/act_ApiAdmin.h>
|
|
#include <nn/act/act_ApiTransfer.h>
|
|
#include <nn/act/act_ResultPrivate.h>
|
|
#include <nn/actslv/actslv_Api.h>
|
|
#include <nn/fs/fs_ApiSysSaveData.h>
|
|
#include <nn/cfg/CTR/cfg_ApiSys.h>
|
|
#include <nn/drivers/aes/CTR/ARM946ES/driverAes_Types.h>
|
|
|
|
#include "AgeChecker.h"
|
|
|
|
namespace ConsoleRestore
|
|
{
|
|
nn::Result ActCompleter::s_Result;
|
|
const size_t ActCompleter::STACK_SIZE;
|
|
nn::os::Thread ActCompleter::s_Thread;
|
|
nn::os::Thread ActCompleter::s_UnmountThread;
|
|
nn::os::StackBuffer<ActCompleter::STACK_SIZE> ActCompleter::s_ThreadStack;
|
|
nn::os::StackBuffer<ActCompleter::STACK_SIZE> ActCompleter::s_UnmountThreadStack;
|
|
nn::os::Event ActCompleter::s_BeginEvent;
|
|
nn::os::Event ActCompleter::s_EndEvent;
|
|
u32 ActCompleter::s_ApprovalId;
|
|
ActCompleter::CompleteMode ActCompleter::s_Mode;
|
|
ActCompleter::SalvageCheck ActCompleter::s_SalvageCheck;
|
|
nn::cfg::CTR::CfgCountryCode ActCompleter::s_CfgCountryCode;
|
|
|
|
|
|
ActCompleter::ActCompleter()
|
|
{
|
|
}
|
|
|
|
ActCompleter::~ActCompleter()
|
|
{
|
|
}
|
|
|
|
nn::Result ActCompleter::GetResult()
|
|
{
|
|
return s_Result;
|
|
}
|
|
|
|
void ActCompleter::Start(CompleteMode mode, SalvageCheck check)
|
|
{
|
|
s_Mode = mode;
|
|
s_SalvageCheck = check;
|
|
s_ApprovalId = 0;
|
|
if(s_Mode == ACT_COMPLETE_TRANSFER_WITH_SALVEGE)
|
|
{
|
|
s_BeginEvent.Initialize(false);
|
|
s_EndEvent.Initialize(false);
|
|
}
|
|
|
|
s_Thread.Start(Exec, s_ThreadStack);
|
|
}
|
|
|
|
nn::cfg::CTR::CfgCountryCode ActCompleter::GetCountryCodeFromNna()
|
|
{
|
|
return s_CfgCountryCode;
|
|
}
|
|
|
|
bool ActCompleter::IsFinished()
|
|
{
|
|
return s_Thread.IsValid() && !s_Thread.IsAlive();
|
|
}
|
|
|
|
void ActCompleter::Finish()
|
|
{
|
|
if(s_Thread.IsValid())
|
|
{
|
|
s_Thread.Join();
|
|
s_Thread.Finalize();
|
|
}
|
|
if(s_Mode == ACT_COMPLETE_TRANSFER_WITH_SALVEGE)
|
|
{
|
|
if(s_UnmountThread.IsValid())
|
|
{
|
|
s_UnmountThread.Join();
|
|
s_UnmountThread.Finalize();
|
|
}
|
|
s_BeginEvent.Finalize();
|
|
s_EndEvent.Finalize();
|
|
}
|
|
}
|
|
|
|
void ActCompleter::Exec()
|
|
{
|
|
s_Result = ExecImpl();
|
|
}
|
|
|
|
void ActCompleter::UnmountThreadFunc()
|
|
{
|
|
nn::act::KeepUnmountAndBlock( &s_BeginEvent, &s_EndEvent );
|
|
}
|
|
|
|
nn::Result ActCompleter::ExecImpl()
|
|
{
|
|
if(!nn::ac::IsConnected())
|
|
{
|
|
NN_UTIL_RETURN_IF_FAILED(
|
|
common::InitializeNetwork());
|
|
}
|
|
|
|
NN_UTIL_RETURN_IF_FAILED(
|
|
nn::act::InitializeAdmin());
|
|
|
|
if (s_Mode == ACT_COMPLETE_TRANSFER_WITH_SALVEGE)
|
|
{
|
|
// アンマウント
|
|
s_UnmountThread.Start(UnmountThreadFunc, s_UnmountThreadStack);
|
|
s_BeginEvent.Wait();
|
|
|
|
// アンマウントできたのでアカウントサルベージを実行
|
|
nn::Result result = nn::act::SalvageAccounts();
|
|
// サルベージ終了をシステムに通知
|
|
s_EndEvent.Signal();
|
|
|
|
if(result.IsFailure())
|
|
{
|
|
if(nn::act::ResultRequestNotFound().Includes(result) && s_SalvageCheck == ACT_SALVAGE_WITHOUT_CHECK)
|
|
{
|
|
//サルベージ結果を無視するモードなので無視
|
|
}
|
|
else
|
|
{
|
|
NN_UTIL_RETURN_IF_FAILED_1(
|
|
nn::act::FinalizeAdmin(),
|
|
common::FinalizeNetwork());
|
|
|
|
NN_UTIL_RETURN_IF_FAILED(
|
|
common::FinalizeNetwork());
|
|
|
|
return result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// COPPA判定とPIN判定の準備
|
|
nn::cfg::CfgRegionCode region = nn::cfg::GetRegion();
|
|
u8 age = nn::act::GetAgeAtSalvage();
|
|
|
|
NN_UTIL_RETURN_IF_FAILED_2(
|
|
nn::act::GetCountryCodeAtSalvage(reinterpret_cast<u32*>(&s_CfgCountryCode)),
|
|
nn::act::FinalizeAdmin(),
|
|
common::FinalizeNetwork());
|
|
|
|
AgeChecker ageChecker;
|
|
|
|
if (region == nn::cfg::CFG_REGION_AMERICA)
|
|
{
|
|
|
|
if (ageChecker.IsCoppaRequired(age, region, s_CfgCountryCode))
|
|
{
|
|
// COPPA対象の年齢なら復元する
|
|
s_ApprovalId = nn::act::GetSalvagedApprovalId();
|
|
NN_UTIL_RETURN_IF_FAILED_2(
|
|
SaveApprovalId(),
|
|
nn::act::FinalizeAdmin(),
|
|
common::FinalizeNetwork());
|
|
}
|
|
}
|
|
|
|
// PIN必須ならフラグを立てる
|
|
if (ageChecker.IsPinRestrictionRequired(age, region, s_CfgCountryCode))
|
|
{
|
|
NN_UTIL_RETURN_IF_FAILED_2(
|
|
nn::cfg::CTR::system::SetForceParentalControlFlag(true),
|
|
nn::act::FinalizeAdmin(),
|
|
common::FinalizeNetwork());
|
|
|
|
NN_UTIL_RETURN_IF_FAILED_2(
|
|
nn::cfg::CTR::system::FlushConfig(),
|
|
nn::act::FinalizeAdmin(),
|
|
common::FinalizeNetwork());
|
|
}
|
|
}
|
|
}
|
|
|
|
// 移行完了
|
|
// サルベージの有無に関わらず呼び出す
|
|
NN_UTIL_RETURN_IF_FAILED_2(
|
|
nn::act::CompleteTransfer(),
|
|
nn::act::FinalizeAdmin(),
|
|
common::FinalizeNetwork());
|
|
|
|
NN_UTIL_RETURN_IF_FAILED_1(
|
|
nn::act::FinalizeAdmin(),
|
|
common::FinalizeNetwork());
|
|
|
|
NN_UTIL_RETURN_IF_FAILED(
|
|
common::FinalizeNetwork());
|
|
|
|
return nn::ResultSuccess();
|
|
}
|
|
|
|
nn::Result ActCompleter::SaveApprovalId()
|
|
{
|
|
// Cave-accountのシステムセーブデータ設定
|
|
const u32 CAVE_ACCOUNT_US_SAVEDATA_ID = 0x000202C0;
|
|
const u32 MAX_FILES = 5;
|
|
const u32 MAX_DIRECTORIES = 1;
|
|
const u32 SAVE_DATA_SIZE = 512 * 1024;
|
|
|
|
// Cave-accountのファイル書き込み設定
|
|
const char* const SYSTEM_SAVEDATA_ARCHIVE_NAME = "ssave:";
|
|
const char* const CAVE_FILE_NAME = "ssave:/s.bin";
|
|
const u32 APPROVAL_ID_OFFSET = 0x11000;
|
|
|
|
// Cave-accountのデフォルト値
|
|
const char* const CAVE_DEFAULT_FILE = "rom:/CAVE_ACCOUNT_save_0.bin";
|
|
|
|
NN_UTIL_RETURN_IF_FAILED(
|
|
nn::fs::CreateSystemSaveData(CAVE_ACCOUNT_US_SAVEDATA_ID, MAX_FILES, MAX_DIRECTORIES, SAVE_DATA_SIZE, true));
|
|
|
|
NN_UTIL_RETURN_IF_FAILED(
|
|
nn::fs::MountSystemSaveData(SYSTEM_SAVEDATA_ARCHIVE_NAME, CAVE_ACCOUNT_US_SAVEDATA_ID));
|
|
|
|
{
|
|
nn::fs::FileOutputStream out(CAVE_FILE_NAME, true);
|
|
|
|
// デフォルトデータを書く
|
|
nn::fs::FileInputStream defaultFile;
|
|
NN_UTIL_RETURN_IF_FAILED_1(
|
|
defaultFile.TryInitialize(CAVE_DEFAULT_FILE),
|
|
nn::fs::Unmount(SYSTEM_SAVEDATA_ARCHIVE_NAME));
|
|
|
|
s64 fileSize = defaultFile.GetSize();
|
|
common::HeapManager heap(fileSize, AES_BLOCK_SIZE);
|
|
void* buf = heap.GetAddr();
|
|
if(buf != NULL)
|
|
{
|
|
s32 readSize;
|
|
NN_UTIL_RETURN_IF_FAILED_1(
|
|
defaultFile.TryRead(&readSize, buf, fileSize),
|
|
nn::fs::Unmount(SYSTEM_SAVEDATA_ARCHIVE_NAME));
|
|
s32 writeSize;
|
|
NN_UTIL_RETURN_IF_FAILED_1(
|
|
out.TryWrite(&writeSize, buf, fileSize, true),
|
|
nn::fs::Unmount(SYSTEM_SAVEDATA_ARCHIVE_NAME));
|
|
}
|
|
else
|
|
{
|
|
nn::fs::Unmount(SYSTEM_SAVEDATA_ARCHIVE_NAME);
|
|
return nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON,
|
|
nn::Result::DESCRIPTION_OUT_OF_MEMORY);
|
|
}
|
|
|
|
// 所定の位置までシークしてApproval IDを書く
|
|
NN_UTIL_RETURN_IF_FAILED_1(
|
|
out.TrySeek(APPROVAL_ID_OFFSET, nn::fs::POSITION_BASE_BEGIN),
|
|
nn::fs::Unmount(SYSTEM_SAVEDATA_ARCHIVE_NAME));
|
|
s32 writeSize;
|
|
NN_UTIL_RETURN_IF_FAILED_1(
|
|
out.TryWrite(&writeSize, &s_ApprovalId, sizeof(s_ApprovalId), true),
|
|
nn::fs::Unmount(SYSTEM_SAVEDATA_ARCHIVE_NAME));
|
|
|
|
// コミットする
|
|
NN_UTIL_RETURN_IF_FAILED_1(
|
|
nn::fs::CommitSystemSaveData(SYSTEM_SAVEDATA_ARCHIVE_NAME),
|
|
nn::fs::Unmount(SYSTEM_SAVEDATA_ARCHIVE_NAME));
|
|
}
|
|
|
|
NN_UTIL_RETURN_IF_FAILED(
|
|
nn::fs::Unmount(SYSTEM_SAVEDATA_ARCHIVE_NAME));
|
|
|
|
return nn::ResultSuccess();
|
|
}
|
|
|
|
} /* namespace ConsoleRestore */
|