ctr_Repair/trunk/ConsoleDataMigration/sources/common/Util.cpp
N2614 46af748d2f CTR、SPRより後のモデルではXボタンで無線ON/OFFを切り替えられるように。ビルドにはnwm_ExtAPI.cppを差し替える必要がある
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@731 385bec56-5757-e545-9c3a-d8741f4650f1
2013-03-28 06:29:41 +00:00

528 lines
13 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 <nn/nwm/CTR/nwm_ExtAPI.h>
#include <nn/nwm/CTR/nwm_ExtHwAPI.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);
// モデルの取得
GetModel();
// nwmの初期化
nn::nwm::InitializeExtControl();
// 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::nwm::FinalizeExtControl();
nn::mcu::CTR::FinalizeHwCheck(&m_McuSession);
}
void Util::ToggleWifiStatus()
{
if(!CanChangeWifi())
{
return;
}
if(nn::nwm::IsWifiOn())
{
COMMON_LOGGER_RESULT_IF_FAILED(
nn::nwm::Ext::SetWifiOff()
);
}
else
{
COMMON_LOGGER_RESULT_IF_FAILED(
nn::nwm::Ext::SetWifiOn()
);
}
}
// 無線状態を取得する
bool Util::IsWifiOn()
{
return nn::nwm::IsWifiOn();
}
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しない
}
}
}
void Util::GetModel()
{
nn::mcu::CTR::HwCheck mcu(m_McuSession);
u8 buf[10];
const u8 RETRY = 10;
for(u8 i = 0; i < RETRY; i++)
{
nn::Result result = mcu.GetInfoRegisters(buf, sizeof(buf));
if(result.IsSuccess())
{
break;
}
nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(16));
}
// 機種情報を cfg に反映
m_Model= buf[9];
}
bool Util::CanChangeWifi()
{
if(m_Model == TARGET_MODEL_CTR || m_Model == TARGET_MODEL_SPR)
{
return false;
}
return true;
}
// 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();
}
}