+ sceNpTrophyGetTrophyInfo implementation and cleanup

This commit is contained in:
igor725 2024-05-04 12:47:55 +03:00
parent 26c9b07a7d
commit 4cef994c97
No known key found for this signature in database
GPG Key ID: 46F13BBE46F8569D
5 changed files with 98 additions and 41 deletions

View File

@ -165,7 +165,9 @@ class Trophies: public ITrophies {
if (((ent.flag >> 24) & 0x03) == 0) {
ctx->pngim.data.pngsize = ent.len;
ctx->pngim.data.pngname.assign(ent.name);
ctx->pngim.data.pngdata = ::calloc(ent.len, 1); // Developer should free this memory manually
if ((ctx->pngim.data.pngdata = ::calloc(ent.len, 1)) == nullptr) { // Developer should free this memory manually
return ErrCodes::OUT_OF_MEMORY;
}
trfile.seekg(ent.pos);
if (trfile.read((char*)ctx->pngim.data.pngdata, ent.len)) {
ctx->pngim.cancelled = ctx->pngim.func(&ctx->pngim.data);
@ -428,6 +430,7 @@ class Trophies: public ITrophies {
switch (ec) {
case ErrCodes::SUCCESS: return "No errors";
case ErrCodes::INVALID_CONTEXT: return "Passed context is nullptr";
case ErrCodes::OUT_OF_MEMORY: return "Failed to allocate data array";
case ErrCodes::NO_ITROP: return "Invalid combination: trying to parse extended trophyset info from lightweight file";
case ErrCodes::NO_KEY_SET: return "Invalid trophy key, decrypting is impossible";
case ErrCodes::INVALID_MAGIC: return "Invalid trophy file magic, trophy00.trp is likely corruted";
@ -439,6 +442,7 @@ class Trophies: public ITrophies {
case ErrCodes::NO_CALLBACKS: return "No callbacks passed to parser";
case ErrCodes::DECRYPT: return "Trophy file decryption failed";
case ErrCodes::NO_TROPHIES: return "Trophy file is likely missing or does not contain requested esfm file";
case ErrCodes::MAX_TROPHY_REACHED: return "The game hit the hard limit of 128 trophies";
default: return "Unknown error code!";
}
}
@ -449,6 +453,8 @@ class Trophies: public ITrophies {
bool getProgress(int32_t userId, uint32_t progress[4], uint32_t* count) final { return false; }
uint64_t getUnlockTime(int32_t userId, int32_t trophyId) final { return 0ull; }
bool unlockTrophy(int32_t userId, int32_t trophyId) final { return false; }
bool resetUserInfo(int32_t userId) final { return false; }

View File

@ -19,6 +19,7 @@ class ITrophies {
enum class ErrCodes {
SUCCESS = 0, // No errors, we're fine
INVALID_CONTEXT, // Context is nullptr
OUT_OF_MEMORY, // Failed to allocate data array
NO_ITROP, // There are no trophyset info in lightweight file
CONTINUE, // Not an actual error code. For internal usage only!
NO_KEY_SET, // No root key installed
@ -97,11 +98,12 @@ class ITrophies {
virtual ErrCodes parseTRP(trp_context* context) = 0;
virtual const char* getError(ErrCodes ec) = 0;
virtual bool createContext(int32_t userId, uint32_t label) = 0;
virtual bool destroyContext(int32_t userId) = 0;
virtual bool getProgress(int32_t userId, uint32_t progress[4], uint32_t* count) = 0;
virtual bool unlockTrophy(int32_t userId, int32_t trophyId) = 0;
virtual bool resetUserInfo(int32_t userId) = 0;
virtual bool createContext(int32_t userId, uint32_t label) = 0;
virtual bool destroyContext(int32_t userId) = 0;
virtual bool getProgress(int32_t userId, uint32_t progress[4], uint32_t* count) = 0;
virtual uint64_t getUnlockTime(int32_t userId, int32_t trophyId) = 0;
virtual bool unlockTrophy(int32_t userId, int32_t trophyId) = 0;
virtual bool resetUserInfo(int32_t userId) = 0;
};
#if defined(__APICALL_EXTERN)

View File

@ -3,10 +3,11 @@
namespace Err {
namespace NpTrophy {
constexpr int32_t EXCEEDS_MAX = -2141907422;
constexpr int32_t ALREADY_EXISTS = -2141907437;
constexpr int32_t INVALID_CONTEXT = -2141907447;
constexpr int32_t INVALID_ARGUMENT = -2141907452;
constexpr int32_t EXCEEDS_MAX = -2141907422;
constexpr int32_t ALREADY_EXISTS = -2141907437;
constexpr int32_t INVALID_CONTEXT = -2141907447;
constexpr int32_t INVALID_ARGUMENT = -2141907452;
constexpr int32_t SCREENSHOT_DISABLED = -2141907413;
} // namespace NpTrophy
} // namespace Err

View File

@ -15,19 +15,23 @@ extern "C" {
EXPORT const char* MODULE_NAME = "libSceNpTrophy";
// Unused handles API
EXPORT SYSV_ABI int sceNpTrophyCreateHandle(SceNpTrophyHandle* handle) {
*handle = 1;
return Ok;
}
EXPORT SYSV_ABI int sceNpTrophyDestroyHandle(SceNpTrophyHandle handle) {
EXPORT SYSV_ABI int sceNpTrophyDestroyHandle(SceNpTrophyHandle) {
return Ok;
}
EXPORT SYSV_ABI int sceNpTrophyAbortHandle(SceNpTrophyHandle handle) {
EXPORT SYSV_ABI int sceNpTrophyAbortHandle(SceNpTrophyHandle) {
return Ok;
}
//- Unused handles API
EXPORT SYSV_ABI int sceNpTrophyCreateContext(SceNpTrophyContext* context, int32_t userId, SceNpServiceLabel serviceLabel, uint64_t options) {
return accessTrophies().createContext(userId, (uint32_t)serviceLabel) ? Ok : Err::NpTrophy::ALREADY_EXISTS;
}
@ -36,20 +40,21 @@ EXPORT SYSV_ABI int sceNpTrophyDestroyContext(SceNpTrophyContext context) {
return accessTrophies().destroyContext(context) ? Ok : Err::NpTrophy::INVALID_ARGUMENT;
}
EXPORT SYSV_ABI int sceNpTrophyRegisterContext(SceNpTrophyContext context, SceNpTrophyHandle handle, uint64_t options) {
// We don't need any registration
EXPORT SYSV_ABI int sceNpTrophyRegisterContext(SceNpTrophyContext context, SceNpTrophyHandle, uint64_t options) {
return Ok;
}
EXPORT SYSV_ABI int sceNpTrophyUnlockTrophy(SceNpTrophyContext context, SceNpTrophyHandle handle, SceNpTrophyId trophyId, SceNpTrophyId* platinumId) {
EXPORT SYSV_ABI int sceNpTrophyUnlockTrophy(SceNpTrophyContext context, SceNpTrophyHandle, SceNpTrophyId trophyId, SceNpTrophyId* platinumId) {
*platinumId = NpTrophy::INVALID_TROPHY_ID;
return Ok;
}
EXPORT SYSV_ABI int sceNpTrophyGetTrophyUnlockState(SceNpTrophyContext context, SceNpTrophyHandle handle, SceNpTrophyFlagArray* flags, uint32_t* count) {
EXPORT SYSV_ABI int sceNpTrophyGetTrophyUnlockState(SceNpTrophyContext context, SceNpTrophyHandle, SceNpTrophyFlagArray* flags, uint32_t* count) {
return accessTrophies().getProgress(context, flags->flagBits, count);
}
EXPORT SYSV_ABI int sceNpTrophyGetGameInfo(SceNpTrophyContext context, SceNpTrophyHandle handle, SceNpTrophyGameDetails* details, SceNpTrophyGameData* gdata) {
EXPORT SYSV_ABI int sceNpTrophyGetGameInfo(SceNpTrophyContext context, SceNpTrophyHandle, SceNpTrophyGameDetails* details, SceNpTrophyGameData* gdata) {
LOG_USE_MODULE(libSceNpTrophy);
SceNpTrophyFlagArray unlock_progr = {0};
uint32_t unlock_count = 0;
@ -111,7 +116,7 @@ EXPORT SYSV_ABI int sceNpTrophyGetGameInfo(SceNpTrophyContext context, SceNpTrop
return Ok;
}
EXPORT SYSV_ABI int sceNpTrophyGetGroupInfo(SceNpTrophyContext context, SceNpTrophyHandle handle, SceNpTrophyGroupId groupId, SceNpTrophyGroupDetails* details,
EXPORT SYSV_ABI int sceNpTrophyGetGroupInfo(SceNpTrophyContext context, SceNpTrophyHandle, SceNpTrophyGroupId groupId, SceNpTrophyGroupDetails* details,
SceNpTrophyGroupData* grdata) {
LOG_USE_MODULE(libSceNpTrophy);
SceNpTrophyFlagArray unlock_progr = {0};
@ -154,7 +159,7 @@ EXPORT SYSV_ABI int sceNpTrophyGetGroupInfo(SceNpTrophyContext context, SceNpTro
++trophy_count;
}
return false; // todo: Find trophies of specific group
return false;
},
},
.group =
@ -188,27 +193,70 @@ EXPORT SYSV_ABI int sceNpTrophyGetGroupInfo(SceNpTrophyContext context, SceNpTro
return Ok;
}
EXPORT SYSV_ABI int sceNpTrophyGetTrophyInfo(SceNpTrophyContext context, SceNpTrophyHandle handle, SceNpTrophyId trophyId, SceNpTrophyDetails* details,
SceNpTrophyData* data) {
if (details != nullptr) {
details->trophyId = trophyId;
details->trophyGrade = SceNpTrophyGrade::GRADE_BRONZE;
details->groupId = -1;
details->hidden = false;
EXPORT SYSV_ABI int sceNpTrophyGetTrophyInfo(SceNpTrophyContext context, SceNpTrophyHandle, SceNpTrophyId trophyId, SceNpTrophyDetails* details,
SceNpTrophyData* tdata) {
LOG_USE_MODULE(libSceNpTrophy);
SceNpTrophyFlagArray unlock_progr = {0};
uint32_t unlock_count = 0;
uint32_t trophy_count = 0;
strcpy_s(details->name, "tropyName");
strcpy_s(details->description, "tropyDesc");
if (!accessTrophies().getProgress(context, unlock_progr.flagBits, nullptr)) return Err::NpTrophy::INVALID_CONTEXT;
ITrophies::trp_context ctx = {
.lightweight = false,
.entry =
{
.func = [context, trophyId, details, tdata, unlock_progr](ITrophies::trp_ent_cb::data_t* data) -> bool {
if (data->id == trophyId) {
bool unlocked = SCE_NP_TROPHY_FLAG_ISSET(data->id, (&unlock_progr));
if (details != nullptr) {
details->trophyId = trophyId;
details->groupId = data->group;
details->hidden = data->hidden;
data->name.copy(details->name, sizeof(details->name));
data->detail.copy(details->description, sizeof(details->description));
switch (data->grade) {
case 'b': // Bronze trophy
details->trophyGrade = SceNpTrophyGrade::BRONZE;
break;
case 's': // Silver trophy
details->trophyGrade = SceNpTrophyGrade::SILVER;
break;
case 'g': // Gold trophy
details->trophyGrade = SceNpTrophyGrade::GOLD;
break;
case 'p': // Platinum trophy
details->trophyGrade = SceNpTrophyGrade::PLATINUM;
break;
}
}
if (tdata != nullptr) {
tdata->trophyId = trophyId;
tdata->timestamp = (tdata->unlocked = unlocked) ? accessTrophies().getUnlockTime(context, trophyId) : 0ull;
}
return true; // We found our trophy, the rest of data is useless
}
return false;
},
},
};
ITrophies::ErrCodes ec;
if ((ec = accessTrophies().parseTRP(&ctx)) != ITrophies::ErrCodes::SUCCESS) {
LOG_ERR(L"Failed to parse trophy data: %S", accessTrophies().getError(ec));
return ec == ITrophies::ErrCodes::MAX_TROPHY_REACHED ? Err::NpTrophy::EXCEEDS_MAX : Err::NpTrophy::INVALID_ARGUMENT;
}
if (data != nullptr) {
data->trophyId = trophyId;
data->unlocked = false;
data->timestamp = 0;
}
return Ok;
}
EXPORT SYSV_ABI int sceNpTrophyGetGameIcon(SceNpTrophyContext context, SceNpTrophyHandle handle, void* buffer, size_t* size) {
EXPORT SYSV_ABI int sceNpTrophyGetGameIcon(SceNpTrophyContext context, SceNpTrophyHandle, void* buffer, size_t* size) {
ITrophies::trp_context ctx = {
.pngim =
{
@ -234,7 +282,7 @@ EXPORT SYSV_ABI int sceNpTrophyGetGameIcon(SceNpTrophyContext context, SceNpTrop
return accessTrophies().parseTRP(&ctx) == ITrophies::ErrCodes::SUCCESS;
}
EXPORT SYSV_ABI int sceNpTrophyGetGroupIcon(SceNpTrophyContext context, SceNpTrophyHandle handle, SceNpTrophyGroupId groupId, void* buffer, size_t* size) {
EXPORT SYSV_ABI int sceNpTrophyGetGroupIcon(SceNpTrophyContext context, SceNpTrophyHandle, SceNpTrophyGroupId groupId, void* buffer, size_t* size) {
auto name = std::format("GR{:3}.PNG", groupId);
ITrophies::trp_context ctx = {
@ -262,7 +310,7 @@ EXPORT SYSV_ABI int sceNpTrophyGetGroupIcon(SceNpTrophyContext context, SceNpTro
return accessTrophies().parseTRP(&ctx) == ITrophies::ErrCodes::SUCCESS;
}
EXPORT SYSV_ABI int sceNpTrophyGetTrophyIcon(SceNpTrophyContext context, SceNpTrophyHandle handle, SceNpTrophyId trophyId, void* buffer, size_t* size) {
EXPORT SYSV_ABI int sceNpTrophyGetTrophyIcon(SceNpTrophyContext context, SceNpTrophyHandle, SceNpTrophyId trophyId, void* buffer, size_t* size) {
auto name = std::format("TROP{:3}.PNG", trophyId);
ITrophies::trp_context ctx = {
@ -290,11 +338,11 @@ EXPORT SYSV_ABI int sceNpTrophyGetTrophyIcon(SceNpTrophyContext context, SceNpTr
return accessTrophies().parseTRP(&ctx) == ITrophies::ErrCodes::SUCCESS;
}
EXPORT SYSV_ABI int sceNpTrophyShowTrophyList(SceNpTrophyContext context, SceNpTrophyHandle handle) {
EXPORT SYSV_ABI int sceNpTrophyShowTrophyList(SceNpTrophyContext context, SceNpTrophyHandle) {
return Ok;
}
EXPORT SYSV_ABI int sceNpTrophyCaptureScreenshot(SceNpTrophyHandle handle, const SceNpTrophyScreenshotTarget* targets, uint32_t numTargets) {
return Ok;
return Err::NpTrophy::SCREENSHOT_DISABLED;
}
}

View File

@ -7,10 +7,10 @@ typedef int32_t SceNpTrophyId;
typedef int32_t SceNpTrophyGroupId;
enum class SceNpTrophyGrade : unsigned int {
GRADE_PLATINUM = 1, // PLATINUM
GRADE_GOLD = 2, // GOLD
GRADE_SILVER = 3, // SILVER
GRADE_BRONZE = 4, // BRONZE
PLATINUM = 1, // PLATINUM
GOLD = 2, // GOLD
SILVER = 3, // SILVER
BRONZE = 4, // BRONZE
};