mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-26 07:45:33 +01:00
IOS/ES: Keep track of the active title properly
This changes ES to keep track of the active title properly, just like IOS: * It is NOT changed on resource manager open/close. * It is reset on IOS reload. * It is changed by ES_DIVerify and ES_Launch. IOS stores the active title in a structure like this: struct ESTitleContext { Ticket* ticket; TMD* tmd; u32 active; }; With this commit, we also do keep the Ticket and TMD around. This makes some of the DI ioctlvs (which return data about the current active title) trivial to implement in the future. This fixes the System Menu not being able to see update partitions and also allows us to change Dolphin's active game info in the future.
This commit is contained in:
parent
78e7f4aae3
commit
4d776ffa8f
@ -278,8 +278,6 @@ bool CBoot::BootUp()
|
|||||||
PanicAlertT("Warning - starting ISO in wrong console mode!");
|
PanicAlertT("Warning - starting ISO in wrong console mode!");
|
||||||
}
|
}
|
||||||
|
|
||||||
IOS::HLE::ES_DIVerify(pVolume.GetTMD());
|
|
||||||
|
|
||||||
_StartupPara.bWii = pVolume.GetVolumeType() == DiscIO::Platform::WII_DISC;
|
_StartupPara.bWii = pVolume.GetVolumeType() == DiscIO::Platform::WII_DISC;
|
||||||
|
|
||||||
// HLE BS2 or not
|
// HLE BS2 or not
|
||||||
|
@ -311,6 +311,11 @@ bool CBoot::EmulatedBS2_Wii()
|
|||||||
if (DVDInterface::GetVolume().GetVolumeType() != DiscIO::Platform::WII_DISC)
|
if (DVDInterface::GetVolume().GetVolumeType() != DiscIO::Platform::WII_DISC)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
const IOS::ES::TMDReader tmd = DVDInterface::GetVolume().GetTMD();
|
||||||
|
|
||||||
|
if (!SetupWiiMemory(tmd.GetIOSId()))
|
||||||
|
return false;
|
||||||
|
|
||||||
// This is some kind of consistency check that is compared to the 0x00
|
// This is some kind of consistency check that is compared to the 0x00
|
||||||
// values as the game boots. This location keeps the 4 byte ID for as long
|
// values as the game boots. This location keeps the 4 byte ID for as long
|
||||||
// as the game is running. The 6 byte ID at 0x00 is overwritten sometime
|
// as the game is running. The 6 byte ID at 0x00 is overwritten sometime
|
||||||
@ -346,11 +351,6 @@ bool CBoot::EmulatedBS2_Wii()
|
|||||||
|
|
||||||
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
|
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
|
||||||
|
|
||||||
IOS::ES::TMDReader tmd = DVDInterface::GetVolume().GetTMD();
|
|
||||||
|
|
||||||
if (!SetupWiiMemory(tmd.GetIOSId()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Execute the apploader
|
// Execute the apploader
|
||||||
const u32 apploader_offset = 0x2440; // 0x1c40;
|
const u32 apploader_offset = 0x2440; // 0x1c40;
|
||||||
|
|
||||||
@ -383,11 +383,7 @@ bool CBoot::EmulatedBS2_Wii()
|
|||||||
PowerPC::ppcState.gpr[3] = 0x81300000;
|
PowerPC::ppcState.gpr[3] = 0x81300000;
|
||||||
RunFunction(iAppLoaderInit);
|
RunFunction(iAppLoaderInit);
|
||||||
|
|
||||||
// Let the apploader load the exe to memory. At this point I get an unknown IPC command
|
// Let the apploader load the exe to memory
|
||||||
// (command zero) when I load Wii Sports or other games a second time. I don't notice
|
|
||||||
// any side effects however. It's a little disconcerting however that Start after Stop
|
|
||||||
// behaves differently than the first Start after starting Dolphin. It means something
|
|
||||||
// was not reset correctly.
|
|
||||||
DEBUG_LOG(BOOT, "Run iAppLoaderMain");
|
DEBUG_LOG(BOOT, "Run iAppLoaderMain");
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -413,6 +409,8 @@ bool CBoot::EmulatedBS2_Wii()
|
|||||||
// Load patches and run startup patches
|
// Load patches and run startup patches
|
||||||
PatchEngine::LoadPatches();
|
PatchEngine::LoadPatches();
|
||||||
|
|
||||||
|
IOS::HLE::ES_DIVerify(tmd, DVDInterface::GetVolume().GetTicket());
|
||||||
|
|
||||||
// return
|
// return
|
||||||
PC = PowerPC::ppcState.gpr[3];
|
PC = PowerPC::ppcState.gpr[3];
|
||||||
return true;
|
return true;
|
||||||
|
@ -109,7 +109,7 @@ IPCCommandResult DI::IOCtlV(const IOCtlVRequest& request)
|
|||||||
const ES::TMDReader tmd = DVDInterface::GetVolume().GetTMD();
|
const ES::TMDReader tmd = DVDInterface::GetVolume().GetTMD();
|
||||||
const std::vector<u8> raw_tmd = tmd.GetRawTMD();
|
const std::vector<u8> raw_tmd = tmd.GetRawTMD();
|
||||||
Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
|
Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
|
||||||
ES_DIVerify(tmd);
|
ES_DIVerify(tmd, DVDInterface::GetVolume().GetTicket());
|
||||||
|
|
||||||
return_value = 1;
|
return_value = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -39,6 +39,7 @@ namespace HLE
|
|||||||
namespace Device
|
namespace Device
|
||||||
{
|
{
|
||||||
std::string ES::m_ContentFile;
|
std::string ES::m_ContentFile;
|
||||||
|
ES::TitleContext ES::m_title_context;
|
||||||
|
|
||||||
constexpr u8 s_key_sd[0x10] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08,
|
constexpr u8 s_key_sd[0x10] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08,
|
||||||
0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d};
|
0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d};
|
||||||
@ -65,11 +66,58 @@ constexpr const u8* s_key_table[11] = {
|
|||||||
|
|
||||||
ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
|
ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
|
||||||
{
|
{
|
||||||
|
m_title_context.Clear();
|
||||||
|
|
||||||
|
m_TitleIDs.clear();
|
||||||
|
DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
|
||||||
|
uid_sys.GetTitleIDs(m_TitleIDs);
|
||||||
|
|
||||||
|
// uncomment if ES_GetOwnedTitlesCount / ES_GetOwnedTitles is implemented
|
||||||
|
// m_TitleIDsOwned.clear();
|
||||||
|
// DiscIO::cUIDsys::AccessInstance().GetTitleIDs(m_TitleIDsOwned, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ES::TitleContext::Clear()
|
||||||
|
{
|
||||||
|
ticket.SetBytes({});
|
||||||
|
tmd.SetBytes({});
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ES::TitleContext::DoState(PointerWrap& p)
|
||||||
|
{
|
||||||
|
ticket.DoState(p);
|
||||||
|
tmd.DoState(p);
|
||||||
|
p.Do(active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ES::TitleContext::Update(const DiscIO::CNANDContentLoader& content_loader)
|
||||||
|
{
|
||||||
|
if (!content_loader.IsValid())
|
||||||
|
return;
|
||||||
|
Update(content_loader.GetTMD(), content_loader.GetTicket());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ES::TitleContext::Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_)
|
||||||
|
{
|
||||||
|
if (!tmd_.IsValid() || !ticket_.IsValid())
|
||||||
|
{
|
||||||
|
ERROR_LOG(IOS_ES, "TMD or ticket is not valid -- refusing to update title context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ticket = ticket_;
|
||||||
|
tmd = tmd_;
|
||||||
|
active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ES::LoadWAD(const std::string& _rContentFile)
|
void ES::LoadWAD(const std::string& _rContentFile)
|
||||||
{
|
{
|
||||||
m_ContentFile = _rContentFile;
|
m_ContentFile = _rContentFile;
|
||||||
|
// XXX: Ideally, this should be done during a launch, but because we support launching WADs
|
||||||
|
// without installing them (which is a bit of a hack), we have to do this manually here.
|
||||||
|
const auto& content_loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile);
|
||||||
|
m_title_context.Update(content_loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ES::DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output)
|
void ES::DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output)
|
||||||
@ -82,6 +130,8 @@ void ES::DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv,
|
|||||||
|
|
||||||
bool ES::LaunchTitle(u64 title_id, bool skip_reload) const
|
bool ES::LaunchTitle(u64 title_id, bool skip_reload) const
|
||||||
{
|
{
|
||||||
|
m_title_context.Clear();
|
||||||
|
|
||||||
NOTICE_LOG(IOS_ES, "Launching title %016" PRIx64 "...", title_id);
|
NOTICE_LOG(IOS_ES, "Launching title %016" PRIx64 "...", title_id);
|
||||||
|
|
||||||
// ES_Launch should probably reset the whole state, which at least means closing all open files.
|
// ES_Launch should probably reset the whole state, which at least means closing all open files.
|
||||||
@ -120,47 +170,18 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) const
|
|||||||
return LaunchTitle(required_ios);
|
return LaunchTitle(required_ios);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_title_context.Update(content_loader);
|
||||||
SetDefaultContentFile(Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT));
|
SetDefaultContentFile(Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT));
|
||||||
return BootstrapPPC(content_loader);
|
return BootstrapPPC(content_loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ES::OpenInternal()
|
|
||||||
{
|
|
||||||
auto& contentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile);
|
|
||||||
|
|
||||||
// check for cd ...
|
|
||||||
if (contentLoader.IsValid())
|
|
||||||
{
|
|
||||||
m_TitleID = contentLoader.GetTMD().GetTitleId();
|
|
||||||
|
|
||||||
m_TitleIDs.clear();
|
|
||||||
DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
|
|
||||||
uid_sys.GetTitleIDs(m_TitleIDs);
|
|
||||||
// uncomment if ES_GetOwnedTitlesCount / ES_GetOwnedTitles is implemented
|
|
||||||
// m_TitleIDsOwned.clear();
|
|
||||||
// DiscIO::cUIDsys::AccessInstance().GetTitleIDs(m_TitleIDsOwned, true);
|
|
||||||
}
|
|
||||||
else if (DVDInterface::VolumeIsValid())
|
|
||||||
{
|
|
||||||
// blindly grab the titleID from the disc - it's unencrypted at:
|
|
||||||
// offset 0x0F8001DC and 0x0F80044C
|
|
||||||
DVDInterface::GetVolume().GetTitleID(&m_TitleID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_TitleID = ((u64)0x00010000 << 32) | 0xF00DBEEF;
|
|
||||||
}
|
|
||||||
|
|
||||||
INFO_LOG(IOS_ES, "Set default title to %08x/%08x", (u32)(m_TitleID >> 32), (u32)m_TitleID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ES::DoState(PointerWrap& p)
|
void ES::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
Device::DoState(p);
|
Device::DoState(p);
|
||||||
p.Do(m_ContentFile);
|
p.Do(m_ContentFile);
|
||||||
OpenInternal();
|
|
||||||
p.Do(m_AccessIdentID);
|
p.Do(m_AccessIdentID);
|
||||||
p.Do(m_TitleIDs);
|
p.Do(m_TitleIDs);
|
||||||
|
m_title_context.DoState(p);
|
||||||
|
|
||||||
m_addtitle_tmd.DoState(p);
|
m_addtitle_tmd.DoState(p);
|
||||||
p.Do(m_addtitle_content_id);
|
p.Do(m_addtitle_content_id);
|
||||||
@ -197,8 +218,6 @@ void ES::DoState(PointerWrap& p)
|
|||||||
|
|
||||||
ReturnCode ES::Open(const OpenRequest& request)
|
ReturnCode ES::Open(const OpenRequest& request)
|
||||||
{
|
{
|
||||||
OpenInternal();
|
|
||||||
|
|
||||||
if (m_is_active)
|
if (m_is_active)
|
||||||
INFO_LOG(IOS_ES, "Device was re-opened.");
|
INFO_LOG(IOS_ES, "Device was re-opened.");
|
||||||
return Device::Open(request);
|
return Device::Open(request);
|
||||||
@ -206,9 +225,8 @@ ReturnCode ES::Open(const OpenRequest& request)
|
|||||||
|
|
||||||
void ES::Close()
|
void ES::Close()
|
||||||
{
|
{
|
||||||
|
// XXX: does IOS really clear the content access map here?
|
||||||
m_ContentAccessMap.clear();
|
m_ContentAccessMap.clear();
|
||||||
m_TitleIDs.clear();
|
|
||||||
m_TitleID = -1;
|
|
||||||
m_AccessIdentID = 0;
|
m_AccessIdentID = 0;
|
||||||
|
|
||||||
INFO_LOG(IOS_ES, "ES: Close");
|
INFO_LOG(IOS_ES, "ES: Close");
|
||||||
@ -628,7 +646,10 @@ IPCCommandResult ES::OpenContent(const IOCtlVRequest& request)
|
|||||||
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||||
u32 Index = Memory::Read_U32(request.in_vectors[0].address);
|
u32 Index = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
|
|
||||||
s32 CFD = OpenTitleContent(m_AccessIdentID++, m_TitleID, Index);
|
if (!m_title_context.active)
|
||||||
|
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||||
|
|
||||||
|
s32 CFD = OpenTitleContent(m_AccessIdentID++, m_title_context.tmd.GetTitleId(), Index);
|
||||||
INFO_LOG(IOS_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
|
INFO_LOG(IOS_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
|
||||||
|
|
||||||
return GetDefaultReply(CFD);
|
return GetDefaultReply(CFD);
|
||||||
@ -771,8 +792,13 @@ IPCCommandResult ES::GetTitleID(const IOCtlVRequest& request)
|
|||||||
if (!request.HasNumberOfValidVectors(0, 1))
|
if (!request.HasNumberOfValidVectors(0, 1))
|
||||||
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||||
|
|
||||||
Memory::Write_U64(m_TitleID, request.io_vectors[0].address);
|
if (!m_title_context.active)
|
||||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLEID: %08x/%08x", (u32)(m_TitleID >> 32), (u32)m_TitleID);
|
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||||
|
|
||||||
|
const u64 title_id = m_title_context.tmd.GetTitleId();
|
||||||
|
Memory::Write_U64(title_id, request.io_vectors[0].address);
|
||||||
|
INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLEID: %08x/%08x", static_cast<u32>(title_id >> 32),
|
||||||
|
static_cast<u32>(title_id));
|
||||||
return GetDefaultReply(IPC_SUCCESS);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1327,8 +1353,12 @@ IPCCommandResult ES::Sign(const IOCtlVRequest& request)
|
|||||||
u32 data_size = request.in_vectors[0].size;
|
u32 data_size = request.in_vectors[0].size;
|
||||||
u8* sig_out = Memory::GetPointer(request.io_vectors[0].address);
|
u8* sig_out = Memory::GetPointer(request.io_vectors[0].address);
|
||||||
|
|
||||||
|
if (!m_title_context.active)
|
||||||
|
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||||
|
|
||||||
const EcWii& ec = EcWii::GetInstance();
|
const EcWii& ec = EcWii::GetInstance();
|
||||||
MakeAPSigAndCert(sig_out, ap_cert_out, m_TitleID, data, data_size, ec.GetNGPriv(), ec.GetNGID());
|
MakeAPSigAndCert(sig_out, ap_cert_out, m_title_context.tmd.GetTitleId(), data, data_size,
|
||||||
|
ec.GetNGPriv(), ec.GetNGID());
|
||||||
|
|
||||||
return GetDefaultReply(IPC_SUCCESS);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
@ -1373,28 +1403,27 @@ const DiscIO::CNANDContentLoader& ES::AccessContentDevice(u64 title_id) const
|
|||||||
// the WAD
|
// the WAD
|
||||||
// need not be installed in the NAND, but it could be opened directly from a WAD file anywhere on
|
// need not be installed in the NAND, but it could be opened directly from a WAD file anywhere on
|
||||||
// disk.
|
// disk.
|
||||||
if (m_TitleID == title_id && !m_ContentFile.empty())
|
if (m_title_context.active && m_title_context.tmd.GetTitleId() == title_id &&
|
||||||
|
!m_ContentFile.empty())
|
||||||
return DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile);
|
return DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile);
|
||||||
|
|
||||||
return DiscIO::CNANDContentManager::Access().GetNANDLoader(title_id, Common::FROM_SESSION_ROOT);
|
return DiscIO::CNANDContentManager::Access().GetNANDLoader(title_id, Common::FROM_SESSION_ROOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ES::ES_DIVerify(const IOS::ES::TMDReader& tmd)
|
s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket)
|
||||||
{
|
{
|
||||||
if (!tmd.IsValid())
|
m_title_context.Clear();
|
||||||
return -1;
|
|
||||||
|
|
||||||
u64 title_id = 0xDEADBEEFDEADBEEFull;
|
if (!tmd.IsValid() || !ticket.IsValid())
|
||||||
u64 tmd_title_id = tmd.GetTitleId();
|
return ES_PARAMETER_SIZE_OR_ALIGNMENT;
|
||||||
|
|
||||||
DVDInterface::GetVolume().GetTitleID(&title_id);
|
if (tmd.GetTitleId() != ticket.GetTitleId())
|
||||||
if (title_id != tmd_title_id)
|
return ES_PARAMETER_SIZE_OR_ALIGNMENT;
|
||||||
return -1;
|
|
||||||
|
|
||||||
std::string tmd_path = Common::GetTMDFileName(tmd_title_id, Common::FROM_SESSION_ROOT);
|
std::string tmd_path = Common::GetTMDFileName(tmd.GetTitleId(), Common::FROM_SESSION_ROOT);
|
||||||
|
|
||||||
File::CreateFullPath(tmd_path);
|
File::CreateFullPath(tmd_path);
|
||||||
File::CreateFullPath(Common::GetTitleDataPath(tmd_title_id, Common::FROM_SESSION_ROOT));
|
File::CreateFullPath(Common::GetTitleDataPath(tmd.GetTitleId(), Common::FROM_SESSION_ROOT));
|
||||||
|
|
||||||
if (!File::Exists(tmd_path))
|
if (!File::Exists(tmd_path))
|
||||||
{
|
{
|
||||||
@ -1404,11 +1433,13 @@ u32 ES::ES_DIVerify(const IOS::ES::TMDReader& tmd)
|
|||||||
ERROR_LOG(IOS_ES, "DIVerify failed to write disc TMD to NAND.");
|
ERROR_LOG(IOS_ES, "DIVerify failed to write disc TMD to NAND.");
|
||||||
}
|
}
|
||||||
DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
|
DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
|
||||||
uid_sys.AddTitle(tmd_title_id);
|
uid_sys.AddTitle(tmd.GetTitleId());
|
||||||
// DI_VERIFY writes to title.tmd, which is read and cached inside the NAND Content Manager.
|
// DI_VERIFY writes to title.tmd, which is read and cached inside the NAND Content Manager.
|
||||||
// clear the cache to avoid content access mismatches.
|
// clear the cache to avoid content access mismatches.
|
||||||
DiscIO::CNANDContentManager::Access().ClearCache();
|
DiscIO::CNANDContentManager::Access().ClearCache();
|
||||||
return 0;
|
|
||||||
|
m_title_context.Update(tmd, ticket);
|
||||||
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
} // namespace Device
|
} // namespace Device
|
||||||
} // namespace HLE
|
} // namespace HLE
|
||||||
|
@ -40,15 +40,13 @@ public:
|
|||||||
// Internal implementation of the ES_DECRYPT ioctlv.
|
// Internal implementation of the ES_DECRYPT ioctlv.
|
||||||
void DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output);
|
void DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output);
|
||||||
|
|
||||||
void OpenInternal();
|
|
||||||
|
|
||||||
void DoState(PointerWrap& p) override;
|
void DoState(PointerWrap& p) override;
|
||||||
|
|
||||||
ReturnCode Open(const OpenRequest& request) override;
|
ReturnCode Open(const OpenRequest& request) override;
|
||||||
void Close() override;
|
void Close() override;
|
||||||
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
|
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
|
||||||
|
|
||||||
static u32 ES_DIVerify(const IOS::ES::TMDReader& tmd);
|
static s32 DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket);
|
||||||
|
|
||||||
// This should only be cleared on power reset
|
// This should only be cleared on power reset
|
||||||
static std::string m_ContentFile;
|
static std::string m_ContentFile;
|
||||||
@ -211,9 +209,21 @@ private:
|
|||||||
ContentAccessMap m_ContentAccessMap;
|
ContentAccessMap m_ContentAccessMap;
|
||||||
|
|
||||||
std::vector<u64> m_TitleIDs;
|
std::vector<u64> m_TitleIDs;
|
||||||
u64 m_TitleID = -1;
|
|
||||||
u32 m_AccessIdentID = 0;
|
u32 m_AccessIdentID = 0;
|
||||||
|
|
||||||
|
// Shared across all ES instances.
|
||||||
|
static struct TitleContext
|
||||||
|
{
|
||||||
|
void Clear();
|
||||||
|
void DoState(PointerWrap& p);
|
||||||
|
void Update(const DiscIO::CNANDContentLoader& content_loader);
|
||||||
|
void Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_);
|
||||||
|
|
||||||
|
IOS::ES::TicketReader ticket;
|
||||||
|
IOS::ES::TMDReader tmd;
|
||||||
|
bool active = false;
|
||||||
|
} m_title_context;
|
||||||
|
|
||||||
// For title installation (ioctls IOCTL_ES_ADDTITLE*).
|
// For title installation (ioctls IOCTL_ES_ADDTITLE*).
|
||||||
IOS::ES::TMDReader m_addtitle_tmd;
|
IOS::ES::TMDReader m_addtitle_tmd;
|
||||||
u32 m_addtitle_content_id = 0xFFFFFFFF;
|
u32 m_addtitle_content_id = 0xFFFFFFFF;
|
||||||
|
@ -212,6 +212,11 @@ bool TicketReader::IsValid() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TicketReader::DoState(PointerWrap& p)
|
||||||
|
{
|
||||||
|
p.Do(m_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
u32 TicketReader::GetNumberOfTickets() const
|
u32 TicketReader::GetNumberOfTickets() const
|
||||||
{
|
{
|
||||||
return static_cast<u32>(m_bytes.size() / (GetOffset() + sizeof(Ticket)));
|
return static_cast<u32>(m_bytes.size() / (GetOffset() + sizeof(Ticket)));
|
||||||
|
@ -160,6 +160,7 @@ public:
|
|||||||
void SetBytes(std::vector<u8>&& bytes);
|
void SetBytes(std::vector<u8>&& bytes);
|
||||||
|
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
|
void DoState(PointerWrap& p);
|
||||||
|
|
||||||
const std::vector<u8>& GetRawTicket() const;
|
const std::vector<u8>& GetRawTicket() const;
|
||||||
u32 GetNumberOfTickets() const;
|
u32 GetNumberOfTickets() const;
|
||||||
|
@ -752,13 +752,13 @@ bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader)
|
|||||||
void SetDefaultContentFile(const std::string& file_name)
|
void SetDefaultContentFile(const std::string& file_name)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(s_device_map_mutex);
|
std::lock_guard<std::mutex> lock(s_device_map_mutex);
|
||||||
for (const auto& es : s_es_handles)
|
s_es_handles[0]->LoadWAD(file_name);
|
||||||
es->LoadWAD(file_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ES_DIVerify(const ES::TMDReader& tmd)
|
// XXX: also pass certificate chains?
|
||||||
|
void ES_DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket)
|
||||||
{
|
{
|
||||||
Device::ES::ES_DIVerify(tmd);
|
Device::ES::DIVerify(tmd, ticket);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDIO_EventNotify()
|
void SDIO_EventNotify()
|
||||||
|
@ -24,6 +24,7 @@ namespace IOS
|
|||||||
namespace ES
|
namespace ES
|
||||||
{
|
{
|
||||||
class TMDReader;
|
class TMDReader;
|
||||||
|
class TicketReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace HLE
|
namespace HLE
|
||||||
@ -75,7 +76,7 @@ void DoState(PointerWrap& p);
|
|||||||
|
|
||||||
// Set default content file
|
// Set default content file
|
||||||
void SetDefaultContentFile(const std::string& file_name);
|
void SetDefaultContentFile(const std::string& file_name);
|
||||||
void ES_DIVerify(const ES::TMDReader& tmd);
|
void ES_DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket);
|
||||||
|
|
||||||
void SDIO_EventNotify();
|
void SDIO_EventNotify();
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
|
|||||||
static std::thread g_save_thread;
|
static std::thread g_save_thread;
|
||||||
|
|
||||||
// Don't forget to increase this after doing changes on the savestate system
|
// Don't forget to increase this after doing changes on the savestate system
|
||||||
static const u32 STATE_VERSION = 78; // Last changed in PR 49XX
|
static const u32 STATE_VERSION = 79; // Last changed in PR 4981
|
||||||
|
|
||||||
// Maps savestate versions to Dolphin versions.
|
// Maps savestate versions to Dolphin versions.
|
||||||
// Versions after 42 don't need to be added to this list,
|
// Versions after 42 don't need to be added to this list,
|
||||||
|
@ -37,6 +37,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual bool GetTitleID(u64*) const { return false; }
|
virtual bool GetTitleID(u64*) const { return false; }
|
||||||
|
virtual IOS::ES::TicketReader GetTicket() const { return {}; }
|
||||||
virtual IOS::ES::TMDReader GetTMD() const { return {}; }
|
virtual IOS::ES::TMDReader GetTMD() const { return {}; }
|
||||||
virtual u64 PartitionOffsetToRawOffset(u64 offset) const { return offset; }
|
virtual u64 PartitionOffsetToRawOffset(u64 offset) const { return offset; }
|
||||||
virtual std::string GetGameID() const = 0;
|
virtual std::string GetGameID() const = 0;
|
||||||
|
@ -114,6 +114,13 @@ bool CVolumeWiiCrypted::GetTitleID(u64* buffer) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IOS::ES::TicketReader CVolumeWiiCrypted::GetTicket() const
|
||||||
|
{
|
||||||
|
std::vector<u8> buffer(0x2a4);
|
||||||
|
Read(m_VolumeOffset, buffer.size(), buffer.data(), false);
|
||||||
|
return IOS::ES::TicketReader{std::move(buffer)};
|
||||||
|
}
|
||||||
|
|
||||||
IOS::ES::TMDReader CVolumeWiiCrypted::GetTMD() const
|
IOS::ES::TMDReader CVolumeWiiCrypted::GetTMD() const
|
||||||
{
|
{
|
||||||
u32 tmd_size;
|
u32 tmd_size;
|
||||||
|
@ -33,6 +33,7 @@ public:
|
|||||||
~CVolumeWiiCrypted();
|
~CVolumeWiiCrypted();
|
||||||
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const override;
|
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const override;
|
||||||
bool GetTitleID(u64* buffer) const override;
|
bool GetTitleID(u64* buffer) const override;
|
||||||
|
IOS::ES::TicketReader GetTicket() const override;
|
||||||
IOS::ES::TMDReader GetTMD() const override;
|
IOS::ES::TMDReader GetTMD() const override;
|
||||||
u64 PartitionOffsetToRawOffset(u64 offset) const override;
|
u64 PartitionOffsetToRawOffset(u64 offset) const override;
|
||||||
std::string GetGameID() const override;
|
std::string GetGameID() const override;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user