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
|
// 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 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);
|
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);
|
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;
|
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()
|
u128 get_default_self_klic()
|
||||||
{
|
{
|
||||||
return std::bit_cast<u128>(NP_KLIC_FREE);
|
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);
|
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 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();
|
u128 get_default_self_klic();
|
||||||
|
|
|
@ -608,15 +608,79 @@ error_code sceNpDrmExecuteGamePurchase()
|
||||||
|
|
||||||
error_code sceNpDrmGetTimelimit(vm::cptr<char> path, vm::ptr<u64> time_remain)
|
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)
|
if (!path || !time_remain)
|
||||||
{
|
{
|
||||||
return SCE_NP_DRM_ERROR_INVALID_PARAM;
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue