2014-02-16 02:51:04 +01:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "Emu/SysCalls/SysCalls.h"
|
|
|
|
|
#include "Emu/SysCalls/SC_FUNC.h"
|
|
|
|
|
|
|
|
|
|
#include "sceNp.h"
|
2014-03-06 01:52:23 +01:00
|
|
|
#include "sceNpTrophy.h"
|
2014-03-17 20:34:19 +01:00
|
|
|
|
2014-02-16 02:51:04 +01:00
|
|
|
#include "Loader/TRP.h"
|
|
|
|
|
|
|
|
|
|
void sceNpTrophy_unload();
|
|
|
|
|
void sceNpTrophy_init();
|
|
|
|
|
Module sceNpTrophy(0xf035, sceNpTrophy_init, nullptr, sceNpTrophy_unload);
|
|
|
|
|
|
2014-03-06 01:52:23 +01:00
|
|
|
// Internal Structs
|
2014-02-16 02:51:04 +01:00
|
|
|
struct sceNpTrophyInternalContext
|
|
|
|
|
{
|
|
|
|
|
// TODO
|
|
|
|
|
std::string trp_name;
|
|
|
|
|
vfsStream* trp_stream;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct sceNpTrophyInternal
|
|
|
|
|
{
|
|
|
|
|
bool m_bInitialized;
|
|
|
|
|
std::vector<sceNpTrophyInternalContext> contexts;
|
|
|
|
|
|
|
|
|
|
sceNpTrophyInternal()
|
|
|
|
|
: m_bInitialized(false)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2014-02-16 09:28:32 +01:00
|
|
|
sceNpTrophyInternal s_npTrophyInstance;
|
2014-02-16 02:51:04 +01:00
|
|
|
|
|
|
|
|
// Functions
|
|
|
|
|
int sceNpTrophyInit(u32 pool_addr, u32 poolSize, u32 containerId, u64 options)
|
|
|
|
|
{
|
|
|
|
|
sceNpTrophy.Log("sceNpTrophyInit(pool_addr=0x%x, poolSize=%d, containerId=%d, options=0x%llx)", pool_addr, poolSize, containerId, options);
|
|
|
|
|
|
2014-02-16 09:28:32 +01:00
|
|
|
if (s_npTrophyInstance.m_bInitialized)
|
2014-02-16 02:51:04 +01:00
|
|
|
return SCE_NP_TROPHY_ERROR_ALREADY_INITIALIZED;
|
|
|
|
|
if (options)
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_NOT_SUPPORTED;
|
|
|
|
|
|
2014-02-16 09:28:32 +01:00
|
|
|
s_npTrophyInstance.m_bInitialized = true;
|
2014-02-16 02:51:04 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyCreateContext(mem32_t context, mem_ptr_t<SceNpCommunicationId> commID, mem_ptr_t<SceNpCommunicationSignature> commSign, u64 options)
|
|
|
|
|
{
|
|
|
|
|
sceNpTrophy.Warning("sceNpTrophyCreateContext(context_addr=0x%x, commID_addr=0x%x, commSign_addr=0x%x, options=0x%llx)",
|
|
|
|
|
context.GetAddr(), commID.GetAddr(), commSign.GetAddr(), options);
|
|
|
|
|
|
2014-02-16 09:28:32 +01:00
|
|
|
if (!s_npTrophyInstance.m_bInitialized)
|
2014-02-16 02:51:04 +01:00
|
|
|
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
|
|
|
|
if (!context.IsGood())
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT;
|
|
|
|
|
if (options & (~(u64)1))
|
|
|
|
|
SCE_NP_TROPHY_ERROR_NOT_SUPPORTED;
|
|
|
|
|
// TODO: There are other possible errors
|
|
|
|
|
|
|
|
|
|
// TODO: Is the TROPHY.TRP file necessarily located in this path?
|
2014-02-16 16:19:06 +01:00
|
|
|
vfsDir dir("/app_home/TROPDIR/");
|
2014-02-16 09:28:32 +01:00
|
|
|
if(!dir.IsOpened())
|
2014-02-16 02:51:04 +01:00
|
|
|
return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST;
|
|
|
|
|
|
|
|
|
|
// TODO: Following method will retrieve the TROPHY.TRP of the first folder that contains such file
|
2014-02-16 09:28:32 +01:00
|
|
|
for(const DirEntryInfo* entry = dir.Read(); entry; entry = dir.Read())
|
2014-02-16 02:51:04 +01:00
|
|
|
{
|
2014-02-16 09:28:32 +01:00
|
|
|
if (entry->flags & DirEntry_TypeDir)
|
2014-02-16 02:51:04 +01:00
|
|
|
{
|
2014-03-06 01:52:23 +01:00
|
|
|
vfsStream* stream = Emu.GetVFS().OpenFile("/app_home/TROPDIR/" + entry->name + "/TROPHY.TRP", vfsRead);
|
2014-02-16 16:37:32 +01:00
|
|
|
|
2014-03-06 01:52:23 +01:00
|
|
|
if (stream && stream->IsOpened())
|
2014-02-16 02:51:04 +01:00
|
|
|
{
|
|
|
|
|
sceNpTrophyInternalContext ctxt;
|
2014-03-06 01:52:23 +01:00
|
|
|
ctxt.trp_stream = stream;
|
2014-02-16 02:51:04 +01:00
|
|
|
ctxt.trp_name = entry->name;
|
2014-02-16 09:28:32 +01:00
|
|
|
s_npTrophyInstance.contexts.push_back(ctxt);
|
2014-03-06 01:52:23 +01:00
|
|
|
stream = nullptr;
|
2014-02-16 02:51:04 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyCreateHandle(mem32_t handle)
|
|
|
|
|
{
|
|
|
|
|
sceNpTrophy.Warning("sceNpTrophyCreateHandle(handle_addr=0x%x)", handle.GetAddr());
|
|
|
|
|
|
2014-02-16 09:28:32 +01:00
|
|
|
if (!s_npTrophyInstance.m_bInitialized)
|
2014-02-16 02:51:04 +01:00
|
|
|
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
|
|
|
|
if (!handle.IsGood())
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT;
|
|
|
|
|
// TODO: There are other possible errors
|
|
|
|
|
|
|
|
|
|
// TODO: ?
|
|
|
|
|
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyRegisterContext(u32 context, u32 handle, u32 statusCb_addr, u32 arg_addr, u64 options)
|
|
|
|
|
{
|
|
|
|
|
sceNpTrophy.Warning("sceNpTrophyRegisterContext(context=%d, handle=%d, statusCb_addr=0x%x, arg_addr=0x%x, options=0x%llx)",
|
|
|
|
|
context, handle, statusCb_addr, arg_addr, options);
|
|
|
|
|
|
2014-02-16 09:28:32 +01:00
|
|
|
if (!(s_npTrophyInstance.m_bInitialized))
|
2014-02-16 02:51:04 +01:00
|
|
|
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
|
|
|
|
if (!Memory.IsGoodAddr(statusCb_addr))
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT;
|
|
|
|
|
if (options & (~(u64)1))
|
2014-03-09 04:57:19 +01:00
|
|
|
return SCE_NP_TROPHY_ERROR_NOT_SUPPORTED;
|
2014-03-06 13:27:58 +01:00
|
|
|
if (context >= s_npTrophyInstance.contexts.size())
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT;
|
2014-02-16 02:51:04 +01:00
|
|
|
// TODO: There are other possible errors
|
|
|
|
|
|
2014-02-16 09:28:32 +01:00
|
|
|
sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
|
2014-03-06 13:27:58 +01:00
|
|
|
if (!ctxt.trp_stream)
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST;
|
|
|
|
|
|
2014-02-16 02:51:04 +01:00
|
|
|
TRPLoader trp(*(ctxt.trp_stream));
|
2014-03-17 20:34:19 +01:00
|
|
|
if (!trp.LoadHeader())
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE;
|
|
|
|
|
|
|
|
|
|
// Rename or discard certain entries based on the files found
|
|
|
|
|
char target [32];
|
|
|
|
|
sprintf(target, "TROP_%02d.SFM", Ini.SysLanguage.GetValue());
|
|
|
|
|
|
|
|
|
|
if (trp.ContainsEntry(target)) {
|
|
|
|
|
trp.RemoveEntry("TROPCONF.SFM");
|
|
|
|
|
trp.RemoveEntry("TROP.SFM");
|
|
|
|
|
trp.RenameEntry(target, "TROPCONF.SFM");
|
|
|
|
|
}
|
|
|
|
|
else if (trp.ContainsEntry("TROP.SFM")) {
|
|
|
|
|
trp.RemoveEntry("TROPCONF.SFM");
|
|
|
|
|
trp.RenameEntry("TROP.SFM", "TROPCONF.SFM");
|
|
|
|
|
}
|
|
|
|
|
else if (!trp.ContainsEntry("TROPCONF.SFM")) {
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Discard unnecessary TROP_XX.SFM files
|
|
|
|
|
for (int i=0; i<=18; i++) {
|
|
|
|
|
sprintf(target, "TROP_%02d.SFM", i);
|
|
|
|
|
if (i != Ini.SysLanguage.GetValue())
|
|
|
|
|
trp.RemoveEntry(target);
|
|
|
|
|
}
|
2014-02-16 02:51:04 +01:00
|
|
|
|
|
|
|
|
// TODO: Get the path of the current user
|
2014-03-17 20:34:19 +01:00
|
|
|
if (!trp.Install("/dev_hdd0/home/00000001/trophy/" + ctxt.trp_name))
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE;
|
2014-02-16 02:51:04 +01:00
|
|
|
|
|
|
|
|
// TODO: Callbacks
|
|
|
|
|
|
2014-03-17 20:34:19 +01:00
|
|
|
return CELL_OK;
|
2014-02-16 02:51:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyGetGameProgress()
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophySetSoundLevel()
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-27 04:21:08 +01:00
|
|
|
int sceNpTrophyGetRequiredDiskSpace(u32 context, u32 handle, mem64_t reqspace, u64 options)
|
2014-02-16 02:51:04 +01:00
|
|
|
{
|
2014-02-27 04:21:08 +01:00
|
|
|
sceNpTrophy.Warning("sceNpTrophyGetRequiredDiskSpace(context=%d, handle=%d, reqspace_addr=0x%x, options=0x%llx)",
|
|
|
|
|
context, handle, reqspace.GetAddr(), options);
|
|
|
|
|
|
|
|
|
|
if (!s_npTrophyInstance.m_bInitialized)
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
|
|
|
|
if (!reqspace.IsGood())
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT;
|
2014-03-06 13:27:58 +01:00
|
|
|
if (context >= s_npTrophyInstance.contexts.size())
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT;
|
2014-02-27 04:21:08 +01:00
|
|
|
// TODO: There are other possible errors
|
|
|
|
|
|
|
|
|
|
sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
|
|
|
|
|
|
2014-03-06 13:27:58 +01:00
|
|
|
if (!ctxt.trp_stream)
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST;
|
|
|
|
|
|
|
|
|
|
reqspace = ctxt.trp_stream->GetSize(); // TODO: This is not accurate. It's just an approximation of the real value
|
2014-02-16 02:51:04 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyDestroyContext()
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyAbortHandle()
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-09 04:57:19 +01:00
|
|
|
int sceNpTrophyGetGameInfo(u32 context, u32 handle, mem_ptr_t<SceNpTrophyGameDetails> details, mem_ptr_t<SceNpTrophyGameData> data)
|
2014-02-16 02:51:04 +01:00
|
|
|
{
|
2014-03-09 04:57:19 +01:00
|
|
|
sceNpTrophy.Warning("sceNpTrophyGetGameInfo(context=%d, handle=%d, details_addr=0x%x, data_addr=0x%x)",
|
|
|
|
|
context, handle, details.GetAddr(), data.GetAddr());
|
|
|
|
|
|
|
|
|
|
if (!s_npTrophyInstance.m_bInitialized)
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
|
|
|
|
if (!details.IsGood() || !data.IsGood())
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT;
|
|
|
|
|
// TODO: There are other possible errors
|
|
|
|
|
|
|
|
|
|
// sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
|
|
|
|
|
|
|
|
|
|
// TODO: This data is faked, implement a XML reader and get it from TROP.SFM
|
|
|
|
|
memcpy(details->title, "Trophy Set", SCE_NP_TROPHY_NAME_MAX_SIZE);
|
|
|
|
|
memcpy(details->description, "Hey! Implement a XML reader, and load the description from TROP.SFM", SCE_NP_TROPHY_DESCR_MAX_SIZE);
|
|
|
|
|
details->numTrophies = 0;
|
|
|
|
|
details->numPlatinum = 0;
|
|
|
|
|
details->numGold = 0;
|
|
|
|
|
details->numSilver = 0;
|
|
|
|
|
details->numBronze = 0;
|
|
|
|
|
data->unlockedTrophies = 0;
|
|
|
|
|
data->unlockedPlatinum = 0;
|
|
|
|
|
data->unlockedGold = 0;
|
|
|
|
|
data->unlockedSilver = 0;
|
|
|
|
|
data->unlockedBronze = 0;
|
2014-02-16 02:51:04 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyDestroyHandle()
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyUnlockTrophy()
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyTerm()
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyGetTrophyUnlockState()
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyGetTrophyIcon()
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-06 01:52:23 +01:00
|
|
|
int sceNpTrophyGetTrophyInfo(u32 context, u32 handle, s32 trophyId, mem_ptr_t<SceNpTrophyDetails> details, mem_ptr_t<SceNpTrophyData> data)
|
2014-02-16 02:51:04 +01:00
|
|
|
{
|
2014-03-06 01:52:23 +01:00
|
|
|
sceNpTrophy.Warning("sceNpTrophyGetTrophyInfo(context=%u, handle=%u, trophyId=%d, details_addr=0x%x, data_addr=0x%x)",
|
|
|
|
|
context, handle, trophyId, details.GetAddr(), data.GetAddr());
|
|
|
|
|
|
|
|
|
|
if (!s_npTrophyInstance.m_bInitialized)
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
|
|
|
|
if (!details.IsGood() || !data.IsGood())
|
|
|
|
|
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT;
|
|
|
|
|
// TODO: There are other possible errors
|
|
|
|
|
|
|
|
|
|
// sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
|
2014-03-09 04:57:19 +01:00
|
|
|
|
|
|
|
|
// TODO: This data is faked, implement a XML reader and get it from TROP.SFM
|
2014-03-06 01:52:23 +01:00
|
|
|
memcpy(details->name, "Some Trophy", SCE_NP_TROPHY_NAME_MAX_SIZE);
|
|
|
|
|
memcpy(details->description, "Hey! Implement a XML reader, and load the description from TROP.SFM", SCE_NP_TROPHY_DESCR_MAX_SIZE);
|
|
|
|
|
details->hidden = false;
|
|
|
|
|
details->trophyId = trophyId;
|
|
|
|
|
details->trophyGrade = SCE_NP_TROPHY_GRADE_GOLD;
|
2014-02-16 02:51:04 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sceNpTrophyGetGameIcon()
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sceNpTrophy_unload()
|
|
|
|
|
{
|
2014-02-16 09:28:32 +01:00
|
|
|
s_npTrophyInstance.m_bInitialized = false;
|
2014-02-16 02:51:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sceNpTrophy_init()
|
|
|
|
|
{
|
|
|
|
|
sceNpTrophy.AddFunc(0x079f0e87, sceNpTrophyGetGameProgress);
|
|
|
|
|
sceNpTrophy.AddFunc(0x1197b52c, sceNpTrophyRegisterContext);
|
|
|
|
|
sceNpTrophy.AddFunc(0x1c25470d, sceNpTrophyCreateHandle);
|
|
|
|
|
sceNpTrophy.AddFunc(0x27deda93, sceNpTrophySetSoundLevel);
|
|
|
|
|
sceNpTrophy.AddFunc(0x370136fe, sceNpTrophyGetRequiredDiskSpace);
|
|
|
|
|
sceNpTrophy.AddFunc(0x3741ecc7, sceNpTrophyDestroyContext);
|
|
|
|
|
sceNpTrophy.AddFunc(0x39567781, sceNpTrophyInit);
|
|
|
|
|
sceNpTrophy.AddFunc(0x48bd97c7, sceNpTrophyAbortHandle);
|
|
|
|
|
sceNpTrophy.AddFunc(0x49d18217, sceNpTrophyGetGameInfo);
|
|
|
|
|
sceNpTrophy.AddFunc(0x623cd2dc, sceNpTrophyDestroyHandle);
|
|
|
|
|
sceNpTrophy.AddFunc(0x8ceedd21, sceNpTrophyUnlockTrophy);
|
|
|
|
|
sceNpTrophy.AddFunc(0xa7fabf4d, sceNpTrophyTerm);
|
|
|
|
|
sceNpTrophy.AddFunc(0xb3ac3478, sceNpTrophyGetTrophyUnlockState);
|
|
|
|
|
sceNpTrophy.AddFunc(0xbaedf689, sceNpTrophyGetTrophyIcon);
|
|
|
|
|
sceNpTrophy.AddFunc(0xe3bf9a28, sceNpTrophyCreateContext);
|
|
|
|
|
sceNpTrophy.AddFunc(0xfce6d30a, sceNpTrophyGetTrophyInfo);
|
|
|
|
|
sceNpTrophy.AddFunc(0xff299e03, sceNpTrophyGetGameIcon);
|
|
|
|
|
}
|