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@219 385bec56-5757-e545-9c3a-d8741f4650f1
230 lines
6.5 KiB
C++
230 lines
6.5 KiB
C++
/*---------------------------------------------------------------------------*
|
|
Project: Horizon
|
|
File: TitleDownloader.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/am.h>
|
|
#include <nn/nim.h>
|
|
#include <nn/CTR/CTR_ProgramId.h>
|
|
|
|
#include "CommonLogger.h"
|
|
#include "HeapManager.h"
|
|
#include "TitleDownloader.h"
|
|
#include "Shop.h"
|
|
|
|
|
|
namespace
|
|
{
|
|
|
|
bit8 s_buffer1[400 * 1024];
|
|
|
|
const size_t TITLE_DOWNLOADER_STACK_SIZE = 0x1000;
|
|
nn::os::Thread s_TitleDownloaderThread;
|
|
nn::os::StackBuffer<TITLE_DOWNLOADER_STACK_SIZE> s_TitleDownloaderThreadStack;
|
|
|
|
nn::fs::MediaType GetMediaType(const ES_NAMESPACE::ESTitleId titleId)
|
|
{
|
|
return (nn::CTR::IsTwlApp(titleId)) ?
|
|
nn::fs::MEDIA_TYPE_NAND : nn::fs::MEDIA_TYPE_SDMC;
|
|
}
|
|
|
|
const char *GetAttribute(EC_NAMESPACE::ECNameValuePair *attributes, u32 nAttributes, const char *attributeName)
|
|
{
|
|
for(int i=0; i<nAttributes; i++)
|
|
{
|
|
if(std::strcmp(attributes[i].name, attributeName)==0)
|
|
{
|
|
return attributes[i].value;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
nn::Result GetEntry(ES_NAMESPACE::ESTitleId titleId, EC_NAMESPACE::ECTitleCatalogEntry **entry)
|
|
{
|
|
nn::nim::AttributeName returnAttribute[] =
|
|
{"Version", "TitleName", "TitleType", "TitleDescription", "Category", "Publisher", "MaxUserFileSize", "ReleaseDate"};
|
|
nn::nim::AttributeFilter attributeFilter[] = {
|
|
{"==", "string", "PricingSelection", "RELEASED"}
|
|
};
|
|
|
|
NN_LOG("ID: %016llx\n", titleId);
|
|
|
|
EC_NAMESPACE::ECTitleCatalog *titleCatalog;
|
|
nn::Result result = nn::nim::Shop::ListTitles(0, 1,
|
|
returnAttribute, sizeof(returnAttribute)/sizeof(returnAttribute[0]),
|
|
attributeFilter, sizeof(attributeFilter)/sizeof(attributeFilter[0]),
|
|
&(titleId), 1,
|
|
NULL, 0,
|
|
&titleCatalog, s_buffer1, sizeof(s_buffer1));
|
|
|
|
*entry = &(titleCatalog->entries[0]);
|
|
|
|
return result;
|
|
}
|
|
|
|
nn::Result GetTitleConfig(const ES_NAMESPACE::ESTitleId titleId, nn::nim::TitleConfig *titleConfig)
|
|
{
|
|
EC_NAMESPACE::ECTitleCatalogEntry *entry;
|
|
NN_UTIL_RETURN_IF_FAILED(GetEntry(titleId, &entry));
|
|
|
|
titleConfig->titleId=titleId;
|
|
titleConfig->version=std::strtoull(GetAttribute(entry->attributes, entry->nAttributes, "Version"), NULL, 10);
|
|
titleConfig->ratingAge=0;
|
|
titleConfig->media=GetMediaType(titleId);
|
|
|
|
NN_LOG("titleId : 0x%016llx\n", titleConfig->titleId);
|
|
NN_LOG("version : %lld\n" , titleConfig->version);
|
|
NN_LOG("ratingAge : %d\n" , titleConfig->ratingAge);
|
|
NN_LOG("media : %d\n" , titleConfig->media);
|
|
|
|
|
|
return nn::ResultSuccess();
|
|
}
|
|
|
|
|
|
} // namespace <unnamed>
|
|
|
|
namespace ConsoleRestore
|
|
{
|
|
|
|
nn::Result TitleDownloader::m_Result = nn::ResultSuccess();
|
|
|
|
void TitleDownloaderThreadFunc()
|
|
{
|
|
TitleDownloader TwlTitleDownloader;
|
|
|
|
TwlTitleDownloader.Start();
|
|
}
|
|
|
|
void StartTitleDownload()
|
|
{
|
|
s_TitleDownloaderThread.Start(TitleDownloaderThreadFunc, s_TitleDownloaderThreadStack);
|
|
}
|
|
|
|
bool DownloadTitleFinished()
|
|
{
|
|
return s_TitleDownloaderThread.IsValid() && !s_TitleDownloaderThread.IsAlive();
|
|
}
|
|
|
|
bool DownloadTitleSucceeded()
|
|
{
|
|
return TitleDownloader::m_Result.IsSuccess() && GetShopOperationSingleResult().IsSuccess();
|
|
}
|
|
|
|
|
|
|
|
TitleDownloader::TitleDownloader() : m_TwlTiteNum(0)
|
|
{
|
|
// TODO 自動生成されたコンストラクター・スタブ
|
|
for(u32 i = 0; i < TWL_IMPORTABLE_TITLE_MAX; i++)
|
|
{
|
|
m_ProgramIdList[i] = 0;
|
|
}
|
|
|
|
}
|
|
|
|
TitleDownloader::~TitleDownloader()
|
|
{
|
|
// TODO Auto-generated destructor stub
|
|
}
|
|
|
|
|
|
nn::Result WaitCancelled()
|
|
{
|
|
nn::nim::TitleProgress progress;
|
|
while(true)
|
|
{
|
|
// キャンセルがResultとして返ってくる / ダウンロード終了まで待つ
|
|
NN_UTIL_RETURN_IF_FAILED(nn::nim::Shop::GetProgress(&progress));
|
|
if(progress.lastResult==nn::nim::ResultCancelRequested() || progress.state==nn::nim::TITLE_STATE_FINISHED)
|
|
{
|
|
break;
|
|
}
|
|
nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(100));
|
|
}
|
|
return nn::ResultSuccess();
|
|
}
|
|
|
|
void WaitShopOperationAndFinalize()
|
|
{
|
|
while (!IsShopOperationSingleFinished())
|
|
{
|
|
nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(100));
|
|
}
|
|
|
|
FinalizeShopOperationSingle();
|
|
}
|
|
|
|
void TitleDownloader::Start()
|
|
{
|
|
nn::Result result;
|
|
|
|
result = ListUp();
|
|
if(result.IsFailure())
|
|
{
|
|
return;
|
|
}
|
|
|
|
for(u8 i = 0; i < m_TwlTiteNum; i++)
|
|
{
|
|
StartShopOperationSingle(SHOP_OPERATION_CONNECT_WITHOUT_CLOSE);
|
|
WaitShopOperationAndFinalize();
|
|
|
|
nn::nim::TitleConfig config;
|
|
result = GetTitleConfig(m_ProgramIdList[i], &config);
|
|
if (result.IsSuccess())
|
|
{
|
|
StartShopOperationSingle(SHOP_OPERATION_DOWNLOAD_TITLE, config);
|
|
WaitShopOperationAndFinalize();
|
|
}
|
|
}
|
|
}
|
|
|
|
nn::Result TitleDownloader::ListUp()
|
|
{
|
|
const u32 AM_TICKET_MAX = 7168;
|
|
|
|
s32 personalizedTicketNum;
|
|
|
|
nn::am::TicketInfo *ticketInfoBuffer =
|
|
reinterpret_cast<nn::am::TicketInfo*> (common::HeapManager::GetHeap()->Allocate(
|
|
sizeof(nn::am::TicketInfo) * AM_TICKET_MAX));
|
|
if(ticketInfoBuffer == NULL)
|
|
{
|
|
COMMON_LOGGER("Failed Allocate Heap!!\n");
|
|
m_Result = nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON,
|
|
nn::Result::DESCRIPTION_OUT_OF_MEMORY);
|
|
return m_Result;
|
|
}
|
|
|
|
m_Result=nn::am::GetPersonalizedTicketInfoList(&personalizedTicketNum, ticketInfoBuffer, AM_TICKET_MAX); // 全部
|
|
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(m_Result);
|
|
|
|
for (u32 i = 0; i < personalizedTicketNum; i++)
|
|
{
|
|
if (nn::CTR::IsTwlApp(ticketInfoBuffer[i].titleId))
|
|
{
|
|
m_ProgramIdList[m_TwlTiteNum] = ticketInfoBuffer[i].titleId;
|
|
m_TwlTiteNum++;
|
|
NN_LOG("%016llx\n", m_ProgramIdList[m_TwlTiteNum - 1]);
|
|
}
|
|
}
|
|
|
|
return m_Result;
|
|
}
|
|
|
|
|
|
}
|