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@661 385bec56-5757-e545-9c3a-d8741f4650f1
461 lines
11 KiB
C++
461 lines
11 KiB
C++
/*---------------------------------------------------------------------------*
|
|
Project: Horizon
|
|
File: Util.cpp
|
|
|
|
Copyright (C)2010-2011 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 <cctype>
|
|
|
|
#include <nn.h>
|
|
#include <nn/ptm/CTR/ptm_ApiSysmenu.h>
|
|
#include <nn/fs/CTR/fs_ArchiveTypesForSystem.h>
|
|
#include <nn/fs/CTR/MPCore/fs_FileSystemBasePrivate.h>
|
|
#include <nn/fs/CTR/MPCore/fs_ApiIntegrityVerificationSeed.h>
|
|
#include <nn/fs/fs_ApiSysSaveData.h>
|
|
#include <nn/cfg/CTR/cfg_Api.h>
|
|
#include <nn/cfg/CTR/cfg_ApiInit.h>
|
|
#include <nn/cfg/CTR/cfg_ApiSys.h>
|
|
#include <nn/friends.h>
|
|
#include <nn/friends/CTR/friends_ApiPrivate.h>
|
|
#include <nn/ps.h>
|
|
#include <nn/drivers/mcu/CTR/driverMcuRegisterMap.h>
|
|
|
|
#include <nn/ac.h>
|
|
#include <nn/ac/private/ac.h>
|
|
#include <nn/ac/CTR/private/ac_InternalApi.h>
|
|
#include <nn/ac/CTR/private/ac_NetworkSetting.h>
|
|
|
|
#include "Util.h"
|
|
#include "FileName.h"
|
|
#include "CommonLogger.h"
|
|
#include "HeapManager.h"
|
|
#include "FileTransfer.h"
|
|
|
|
|
|
namespace common
|
|
{
|
|
|
|
Util::Util() :
|
|
m_FriendCode(0), mp_Ivs(NULL), m_SizeofIvs(0), m_SerialNoWithoutCGLen(0), m_BatteryRemain(100), m_CanReadSerialNumber(false), m_CanReadIvs(
|
|
false), m_HasReadFriendCode(false)
|
|
{
|
|
|
|
}
|
|
|
|
Util::~Util()
|
|
{
|
|
|
|
}
|
|
|
|
void Util::InitializeForBackup()
|
|
{
|
|
Initialize();
|
|
}
|
|
|
|
void Util::InitializeForRestore()
|
|
{
|
|
Initialize();
|
|
|
|
// friendsの初期化
|
|
nn::Result result = nn::friends::detail::Initialize();
|
|
|
|
// フレンドコードの取得
|
|
nn::friends::CTR::FriendKey friendKey;
|
|
result = nn::friends::CTR::GetMyFriendKey(&friendKey);
|
|
COMMON_LOGGER_RESULT_IF_FAILED(result);
|
|
m_FriendCode = nn::friends::CTR::FriendKeyToFriendCode(friendKey);
|
|
|
|
m_HasReadFriendCode = true;
|
|
}
|
|
|
|
void Util::Initialize()
|
|
{
|
|
nn::Result result;
|
|
|
|
// mcuの初期化
|
|
nn::mcu::CTR::InitializeHwCheck(&m_McuSession);
|
|
mp_Mcu = new nn::mcu::CTR::HwCheck(m_McuSession);
|
|
|
|
// シリアルナンバーの取得
|
|
std::memset(m_SerialNo, '\0',
|
|
nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN);
|
|
result = nn::cfg::CTR::system::GetSerialNo(m_SerialNo);
|
|
if(result.IsSuccess())
|
|
{
|
|
m_CanReadSerialNumber = true;
|
|
}
|
|
COMMON_LOGGER_RESULT_IF_FAILED(result);
|
|
AddCheckDigit(reinterpret_cast<char*>(m_SerialNo));
|
|
|
|
|
|
// デバイスIDの取得
|
|
result = nn::ps::CTR::GetDeviceId(&m_DeviceId);
|
|
COMMON_LOGGER_RESULT_IF_FAILED(result);
|
|
|
|
// リージョンの取得
|
|
m_Region = nn::cfg::CTR::GetRegion();
|
|
|
|
// バージョンの取得
|
|
common::GetSystemVersion(&m_VerData, m_Region);
|
|
|
|
// IVSの取得
|
|
ReadIvs(m_VerData.cup.majorVersion);
|
|
|
|
// MACアドレスの取得
|
|
nn::nwm::Mac mac;
|
|
|
|
result = nn::nwm::GetMacAddress(mac);
|
|
COMMON_LOGGER_RESULT_IF_FAILED(result);
|
|
mac.GetString(m_MacAddress);
|
|
COMMON_LOGGER_RESULT_IF_FAILED(result);
|
|
}
|
|
|
|
void Util::FinalizeForBackup()
|
|
{
|
|
Finalize();
|
|
}
|
|
|
|
void Util::FinalizeForRestore()
|
|
{
|
|
nn::friends::detail::Finalize();
|
|
}
|
|
|
|
void Util::Finalize()
|
|
{
|
|
nn::mcu::CTR::FinalizeHwCheck(&m_McuSession);
|
|
}
|
|
|
|
void Util::ReadIvs(u8 cupMajorVersion)
|
|
{
|
|
if (cupMajorVersion < common::CUP_MAJOR_VER_2ND_NUP)
|
|
{
|
|
nn::Result result;
|
|
// 完全性検証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 = ForceAllocate(fileSize);
|
|
if (addr != NULL)
|
|
{
|
|
mp_Ivs = addr;
|
|
m_SizeofIvs = fileSize;
|
|
result = fis.TryRead(&ret, addr, fileSize);
|
|
if (result.IsSuccess())
|
|
{
|
|
m_CanReadIvs = true;
|
|
}
|
|
// 後でIVSを参照するのでFreeしない
|
|
}
|
|
}
|
|
fis.Finalize();
|
|
}
|
|
// 一旦アンマウントしておく
|
|
nn::fs::Unmount(common::NAND_ARCHIVE_NAME);
|
|
}
|
|
else
|
|
{
|
|
nn::Result result;
|
|
void* pSeed = ForceAllocate(sizeof(nn::fs::CTR::IntegrityVerificationSeed));
|
|
if(pSeed != NULL)
|
|
{
|
|
result = nn::fs::CTR::ExportIntegrityVerificationSeed(
|
|
reinterpret_cast<nn::fs::CTR::IntegrityVerificationSeed*>(pSeed));
|
|
if(result.IsSuccess())
|
|
{
|
|
mp_Ivs = pSeed;
|
|
m_SizeofIvs = sizeof(nn::fs::CTR::IntegrityVerificationSeed);
|
|
m_CanReadIvs = true;
|
|
}
|
|
// 後でIVSを参照するのでFreeしない
|
|
}
|
|
}
|
|
}
|
|
|
|
// NULL終端されたシリアルナンバーを受け取る
|
|
// NULL終端された場所にチェックデジットを付加して新たにNULL終端する
|
|
void Util::AddCheckDigit(char* serial)
|
|
{
|
|
m_SerialNoWithoutCGLen = std::strlen(serial);
|
|
|
|
u8 digit = 0;
|
|
bool odd = true;
|
|
for(u8 i = m_SerialNoWithoutCGLen - 1; i > 0 && std::isdigit(serial[i]); i--)
|
|
{
|
|
if(odd)
|
|
{
|
|
digit += (serial[i] - '0') * 3;
|
|
}
|
|
else
|
|
{
|
|
digit += (serial[i] - '0');
|
|
}
|
|
odd = !odd;
|
|
}
|
|
|
|
if(digit % 10 != 0)
|
|
{
|
|
serial[m_SerialNoWithoutCGLen] = 10 - (digit % 10) + '0';
|
|
}
|
|
else
|
|
{
|
|
serial[m_SerialNoWithoutCGLen] = '0';
|
|
}
|
|
|
|
serial[m_SerialNoWithoutCGLen + 1] = '\0';
|
|
}
|
|
|
|
// /Nintendo 3DS/6ea6b9d6ab70493ea9edd8b947d5d819/853600b24760a87f534430320002544d
|
|
// から、6ea6b9d6ab70493ea9edd8b947d5d819 を取り出す
|
|
void Util::GetSaveDataDirectoryRoot(::std::string& sysSaveRoot)
|
|
{
|
|
nn::Result result;
|
|
|
|
wchar_t path[512];
|
|
result = nn::fs::GetSdmcCtrRootPath(path, sizeof(path));
|
|
COMMON_LOGGER_RETURN_VOID_IF_FAILED(result);
|
|
NN_LOG("%ls\n", path);
|
|
|
|
std::string sdmcRootPath = common::GetCharStr(path);
|
|
sysSaveRoot = sdmcRootPath.substr(sizeof("Nintendo 3DS/"), 32);
|
|
NN_LOG("saveRoot = %s\n", sysSaveRoot.c_str());
|
|
}
|
|
|
|
bool Util::IsAdapterConnected()
|
|
{
|
|
static nn::os::Tick last(0);
|
|
static bool lastResult = false;
|
|
const u8 UPDATE_INTERVAL = 100;
|
|
|
|
nn::os::Tick now = nn::os::Tick::GetSystemCurrent();
|
|
if(last == 0 || (now - last).ToTimeSpan().GetMilliSeconds() > UPDATE_INTERVAL)
|
|
{
|
|
u8 buf;
|
|
nn::Result result = mp_Mcu->ReadByReceive(nn::drivers::mcu::CTR::MCU_PERIPHERAL_STATUS_ADDR, &buf, sizeof(buf));
|
|
if(result.IsSuccess())
|
|
{
|
|
last = now;
|
|
lastResult = buf & nn::drivers::mcu::CTR::MCU_STATUS_ADAPTER_MASK;
|
|
}
|
|
}
|
|
return lastResult;
|
|
|
|
}
|
|
|
|
bool Util::IsBatteryLower()
|
|
{
|
|
m_BatteryRemain = GetBatteryRemain();
|
|
return m_BatteryRemain <= 10;
|
|
}
|
|
|
|
bool Util::CanReadIVS()
|
|
{
|
|
return m_CanReadIvs;
|
|
}
|
|
|
|
bool Util::CanReadSerialNumber()
|
|
{
|
|
return m_CanReadSerialNumber;
|
|
}
|
|
|
|
void Util::GetSerialNumber(u8** serial, size_t* size)
|
|
{
|
|
*serial = m_SerialNo;
|
|
*size = nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN;
|
|
}
|
|
|
|
u8* Util::GetSerialNumber()
|
|
{
|
|
return m_SerialNo;
|
|
}
|
|
|
|
void Util::GetSerialNumberWithoutCD(u8* serial)
|
|
{
|
|
std::memcpy(serial, m_SerialNo, nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN);
|
|
serial[m_SerialNoWithoutCGLen] = '\0';
|
|
}
|
|
|
|
void Util::GetIvs(void** ivs, size_t* size)
|
|
{
|
|
*ivs = mp_Ivs;
|
|
*size = m_SizeofIvs;
|
|
}
|
|
|
|
bit32 Util::GetDeviceId()
|
|
{
|
|
return m_DeviceId;
|
|
}
|
|
|
|
u8 Util::GetCupMajorVersion()
|
|
{
|
|
return m_VerData.cup.majorVersion;
|
|
}
|
|
|
|
u8 Util::GetCupMinorVersion()
|
|
{
|
|
return m_VerData.cup.minorVersion;
|
|
}
|
|
|
|
u8 Util::GetCupMicroVersion()
|
|
{
|
|
return m_VerData.cup.microVersion;
|
|
}
|
|
|
|
u8 Util::GetNupVersion()
|
|
{
|
|
return m_VerData.nup.majorVersion;
|
|
}
|
|
|
|
nn::Handle Util::GetMcuHandle()
|
|
{
|
|
return m_McuSession;
|
|
}
|
|
|
|
u32 Util::GetBatteryRemain()
|
|
{
|
|
u8 remain;
|
|
mp_Mcu->GetBatteryRemain(&remain);
|
|
return remain;
|
|
}
|
|
|
|
u64 Util::GetInfraDeviceId()
|
|
{
|
|
bit64 infraDeviceId;
|
|
infraDeviceId = m_DeviceId + common::INFRA_DEVICE_ID_OFFSET;
|
|
return infraDeviceId;
|
|
}
|
|
|
|
u64 Util::GetFriendcode()
|
|
{
|
|
return m_FriendCode;
|
|
}
|
|
|
|
char8* Util::GetMacAddress()
|
|
{
|
|
return m_MacAddress;
|
|
}
|
|
|
|
nn::cfg::CTR::CfgRegionCode Util::GetRegion()
|
|
{
|
|
return m_Region;
|
|
}
|
|
|
|
const char* Util::GetRegionCodeA3()
|
|
{
|
|
return nn::cfg::GetRegionCodeA3(m_Region);
|
|
}
|
|
|
|
void Util::GetVersionData(common::VerDef* version)
|
|
{
|
|
*version = m_VerData;
|
|
}
|
|
|
|
bool Util::HasReadFriendCode()
|
|
{
|
|
return m_HasReadFriendCode;
|
|
}
|
|
|
|
void Util::SplitDeviceidWithSpace(std::string& deviceIdStr)
|
|
{
|
|
std::string tmp = deviceIdStr;
|
|
deviceIdStr.clear();
|
|
u32 i = 0;
|
|
do
|
|
{
|
|
deviceIdStr.append(tmp.substr(i, 1));
|
|
i++;
|
|
if( i % 4 == 0)
|
|
{
|
|
deviceIdStr.push_back(' ');
|
|
}
|
|
}while( i < tmp.size());
|
|
}
|
|
|
|
u32 Util::GetRenderTarget(u32 target, bool flip)
|
|
{
|
|
if(flip)
|
|
{
|
|
if(target == NN_GX_DISPLAY0)
|
|
{
|
|
return NN_GX_DISPLAY1;
|
|
}
|
|
else
|
|
{
|
|
return NN_GX_DISPLAY0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return target;
|
|
}
|
|
}
|
|
|
|
nn::Result PrintNetworkSetting()
|
|
{
|
|
nn::Result result;
|
|
nn::ac::NetworkSetting networkSetting;
|
|
result = nn::ac::LoadNetworkSetting(0, networkSetting);
|
|
COMMON_LOGGER("SSID: %s\n", networkSetting.wireless.essidSecurity.ssid);
|
|
COMMON_LOGGER("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 result;
|
|
}
|
|
|
|
nn::Result InitializeNetwork(void)
|
|
{
|
|
nn::Result result;
|
|
nn::ac::Config config;
|
|
|
|
// 未初期化の時だけ初期化する
|
|
if(!nn::ac::IsInitializedInternal())
|
|
{
|
|
result = nn::ac::InitializeInternal();
|
|
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
|
|
}
|
|
|
|
// 接続要求用のパラメータを作成
|
|
result = nn::ac::CreateDefaultConfig(&config);
|
|
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
|
|
|
|
// デバッグ用に接続テストを無効化
|
|
nn::ac::DebugSetNetworkArea(&config, nn::ac::NETWORK_AREA_LAN);
|
|
|
|
// 接続要求を発行
|
|
result = nn::ac::ConnectWithoutEula(config);
|
|
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
|
|
|
|
return nn::ResultSuccess();
|
|
}
|
|
|
|
nn::Result FinalizeNetwork(void)
|
|
{
|
|
nn::Result result;
|
|
|
|
// 接続要求用のパラメータを作成
|
|
result = nn::ac::Close();
|
|
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
|
|
|
|
result = nn::ac::FinalizeInternal();
|
|
COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result);
|
|
|
|
return nn::ResultSuccess();
|
|
}
|
|
|
|
}
|