mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 16:31:28 +12:00
Implemented sceNpDrmGetTimelimit
This commit is contained in:
parent
e4225cbab8
commit
1df47352cc
4 changed files with 101 additions and 2 deletions
|
@ -57,6 +57,7 @@ struct EDAT_HEADER
|
|||
// Decrypts full file, or null/empty file
|
||||
extern fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8 *custom_klic, bool verbose);
|
||||
|
||||
extern void read_npd_edat_header(const fs::file* input, NPD_HEADER& NPD, EDAT_HEADER& EDAT);
|
||||
extern bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& input_file_name, const u8* custom_klic, NPD_HEADER *npd_out = nullptr);
|
||||
|
||||
u128 GetEdatRifKeyFromRapFile(const fs::file& rap_file);
|
||||
|
|
|
@ -1497,9 +1497,42 @@ bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key, NPD_HEADER* n
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_npdrm_self_header(const fs::file& self, NPD_HEADER &npd_out)
|
||||
{
|
||||
if (!self)
|
||||
return false;
|
||||
|
||||
self.seek(0);
|
||||
|
||||
if (self.size() >= 4 && self.read<u32>() == "SCE\0"_u32 && !IsDebugSelf(self))
|
||||
{
|
||||
// Check the ELF file class (32 or 64 bit).
|
||||
const bool isElf32 = IsSelfElf32(self);
|
||||
|
||||
// Start the decrypter on this SELF file.
|
||||
SELFDecrypter self_dec(self);
|
||||
|
||||
// Load the SELF file headers.
|
||||
if (!self_dec.LoadHeaders(isElf32))
|
||||
{
|
||||
self_log.error("Failed to load SELF file headers!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (const NPD_HEADER* npd = self_dec.GetNPDHeader())
|
||||
{
|
||||
memcpy(&npd_out, npd, sizeof(NPD_HEADER));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
u128 get_default_self_klic()
|
||||
{
|
||||
return std::bit_cast<u128>(NP_KLIC_FREE);
|
||||
|
|
|
@ -498,5 +498,6 @@ private:
|
|||
|
||||
fs::file decrypt_self(fs::file elf_or_self, u8* klic_key = nullptr, SelfAdditionalInfo* additional_info = nullptr);
|
||||
bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key = nullptr, NPD_HEADER* npd_out = nullptr);
|
||||
bool get_npdrm_self_header(const fs::file& self, NPD_HEADER& npd);
|
||||
|
||||
u128 get_default_self_klic();
|
||||
|
|
|
@ -608,15 +608,79 @@ error_code sceNpDrmExecuteGamePurchase()
|
|||
|
||||
error_code sceNpDrmGetTimelimit(vm::cptr<char> path, vm::ptr<u64> time_remain)
|
||||
{
|
||||
sceNp.todo("sceNpDrmGetTimelimit(path=%s, time_remain=*0x%x)", path, time_remain);
|
||||
sceNp.warning("sceNpDrmGetTimelimit(path=%s, time_remain=*0x%x)", path, time_remain);
|
||||
|
||||
if (!path || !time_remain)
|
||||
{
|
||||
return SCE_NP_DRM_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
*time_remain = SCE_NP_DRM_TIME_INFO_ENDLESS;
|
||||
vm::var<s64> sec;
|
||||
vm::var<s64> nsec;
|
||||
|
||||
// Get system time (real or fake) to compare to
|
||||
error_code ret = sys_time_get_current_time(sec, nsec);
|
||||
if (ret != CELL_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
const std::string enc_drm_path(path.get_ptr(), std::find(path.get_ptr(), path.get_ptr() + 0x100, '\0'));
|
||||
const auto [fs_error, ppath, real_path, enc_file, type] = lv2_file::open(enc_drm_path, 0, 0);
|
||||
|
||||
if (fs_error)
|
||||
{
|
||||
return {fs_error, enc_drm_path};
|
||||
}
|
||||
|
||||
u32 magic;
|
||||
NPD_HEADER npd;
|
||||
|
||||
enc_file.read<u32>(magic);
|
||||
enc_file.seek(0);
|
||||
|
||||
// Read expiration time from NPD header which is Unix timestamp in milliseconds
|
||||
if (magic == "SCE\0"_u32)
|
||||
{
|
||||
if (!get_npdrm_self_header(enc_file, npd))
|
||||
{
|
||||
sceNp.error("sceNpDrmGetTimelimit(): Failed to read NPD header from sce file '%s'", enc_drm_path);
|
||||
return {SCE_NP_DRM_ERROR_BAD_FORMAT, enc_drm_path};
|
||||
}
|
||||
}
|
||||
else if (magic == "NPD\0"_u32)
|
||||
{
|
||||
// edata / sdata files
|
||||
EDAT_HEADER edat;
|
||||
read_npd_edat_header(&enc_file, npd, edat);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown file type
|
||||
return {SCE_NP_DRM_ERROR_BAD_FORMAT, enc_drm_path};
|
||||
}
|
||||
|
||||
// Convert time to milliseconds
|
||||
s64 msec = *sec * 1000ll + *nsec / 1000ll;
|
||||
|
||||
// Return the remaining time in microseconds
|
||||
if (npd.activate_time != 0 && msec < npd.activate_time)
|
||||
{
|
||||
return SCE_NP_DRM_ERROR_SERVICE_NOT_STARTED;
|
||||
}
|
||||
|
||||
if (npd.expire_time == 0)
|
||||
{
|
||||
*time_remain = SCE_NP_DRM_TIME_INFO_ENDLESS;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
if (msec >= npd.expire_time)
|
||||
{
|
||||
return SCE_NP_DRM_ERROR_TIME_LIMIT;
|
||||
}
|
||||
|
||||
*time_remain = (npd.expire_time - msec) * 1000ll;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue