sceNpTrophy: set timestamps

This commit is contained in:
Megamouse 2023-05-15 23:22:13 +02:00
parent 23c710cf53
commit 1ae3b37fbe
7 changed files with 69 additions and 27 deletions

View File

@ -786,20 +786,8 @@ error_code cellRtcGetTick(vm::cptr<CellRtcDateTime> pTime, vm::ptr<CellRtcTick>
return CELL_OK;
}
error_code cellRtcSetTick(vm::ptr<CellRtcDateTime> pTime, vm::cptr<CellRtcTick> pTick)
CellRtcDateTime tick_to_date_time(u64 tick)
{
cellRtc.todo("cellRtcSetTick(pTime=*0x%x, pTick=*0x%x)", pTime, pTick);
if (!vm::check_addr(pTime.addr()))
{
return CELL_RTC_ERROR_INVALID_POINTER;
}
if (!vm::check_addr(pTick.addr()))
{
return CELL_RTC_ERROR_INVALID_POINTER;
}
/*
u32 microseconds = round((pTick->tick % 1000000ULL));
u16 seconds = round((pTick->tick / (1000000ULL)) % 60);
@ -807,11 +795,11 @@ error_code cellRtcSetTick(vm::ptr<CellRtcDateTime> pTime, vm::cptr<CellRtcTick>
u16 hours = round((pTick->tick / (60ULL * 60ULL * 1000000ULL)) % 24);
u64 days_tmp = round((pTick->tick / (24ULL * 60ULL * 60ULL * 1000000ULL)));*/
u32 microseconds = (pTick->tick % 1000000ULL);
u16 seconds = (pTick->tick / (1000000ULL)) % 60;
u16 minutes = (pTick->tick / (60ULL * 1000000ULL)) % 60;
u16 hours = (pTick->tick / (60ULL * 60ULL * 1000000ULL)) % 24;
u64 days_tmp = (pTick->tick / (24ULL * 60ULL * 60ULL * 1000000ULL));
const u32 microseconds = (tick % 1000000ULL);
const u16 seconds = (tick / (1000000ULL)) % 60;
const u16 minutes = (tick / (60ULL * 1000000ULL)) % 60;
const u16 hours = (tick / (60ULL * 60ULL * 1000000ULL)) % 24;
u64 days_tmp = (tick / (24ULL * 60ULL * 60ULL * 1000000ULL));
u16 months = 1;
u16 years = 1;
@ -842,13 +830,33 @@ error_code cellRtcSetTick(vm::ptr<CellRtcDateTime> pTime, vm::cptr<CellRtcTick>
} while (!exit_while);
pTime->microsecond = microseconds;
pTime->second = seconds;
pTime->minute = minutes;
pTime->hour = hours;
pTime->day = ::narrow<u16>(days_tmp + 1);
pTime->month = months;
pTime->year = years;
CellRtcDateTime date_time{
.year = years,
.month = months,
.day = ::narrow<u16>(days_tmp + 1),
.hour = hours,
.minute = minutes,
.second = seconds,
.microsecond = microseconds
};
return date_time;
}
error_code cellRtcSetTick(vm::ptr<CellRtcDateTime> pTime, vm::cptr<CellRtcTick> pTick)
{
cellRtc.todo("cellRtcSetTick(pTime=*0x%x, pTick=*0x%x)", pTime, pTick);
if (!vm::check_addr(pTime.addr()))
{
return CELL_RTC_ERROR_INVALID_POINTER;
}
if (!vm::check_addr(pTick.addr()))
{
return CELL_RTC_ERROR_INVALID_POINTER;
}
*pTime = tick_to_date_time(pTick->tick);
return CELL_OK;
}

View File

@ -50,3 +50,6 @@ u32 cellRtcGetTickResolution();
error_code cellRtcCheckValid(vm::cptr<CellRtcDateTime> pTime);
error_code cellRtcGetDayOfWeek(s32 year, s32 month, s32 day);
error_code cellRtcGetTick(vm::cptr<CellRtcDateTime> pTime, vm::ptr<CellRtcTick> pTick);
error_code cellRtcGetCurrentTick(vm::ptr<CellRtcTick> pTick);
CellRtcDateTime tick_to_date_time(u64 tick);

View File

@ -991,7 +991,13 @@ error_code sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::pt
return SCE_NP_TROPHY_ERROR_ALREADY_UNLOCKED;
}
ctxt->tropusr->UnlockTrophy(trophyId, 0, 0); // TODO: add timestamps
vm::var<CellRtcTick> tick;
if (error_code error = cellRtcGetCurrentTick(tick))
{
sceNpTrophy.error("sceNpTrophyUnlockTrophy: Failed to get timestamp: 0x%x", +error);
}
ctxt->tropusr->UnlockTrophy(trophyId, tick->tick, tick->tick);
// TODO: Make sure that unlocking platinum trophies is properly implemented and improve upon it
const std::string& config_path = vfs::get("/dev_hdd0/home/" + Emu.GetUsr() + "/trophy/" + ctxt->trp_name + "/TROPCONF.SFM");
@ -1001,7 +1007,7 @@ error_code sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::pt
{
sceNpTrophy.warning("sceNpTrophyUnlockTrophy: All requirements for unlocking the platinum trophy (ID = %d) were met.)", unlocked_platinum_id);
if (ctxt->tropusr->UnlockTrophy(unlocked_platinum_id, 0, 0)) // TODO: add timestamps
if (ctxt->tropusr->UnlockTrophy(unlocked_platinum_id, tick->tick, tick->tick))
{
sceNpTrophy.success("You unlocked a platinum trophy! Hooray!!!");
}

View File

@ -72,6 +72,8 @@ namespace gui
return "trophy_column_id";
case trophy_list_columns::platinum_link:
return "trophy_column_platinum_link";
case trophy_list_columns::time_unlocked:
return "trophy_column_time_unlocked";
case trophy_list_columns::count:
return "";
}

View File

@ -47,6 +47,7 @@ namespace gui
is_unlocked = 4,
id = 5,
platinum_link = 6,
time_unlocked = 7,
count
};

View File

@ -6,6 +6,7 @@
#include "game_list.h"
#include "gui_settings.h"
#include "progress_dialog.h"
#include "persistent_settings.h"
#include "util/logs.hpp"
#include "Utilities/StrUtil.h"
@ -14,6 +15,7 @@
#include "Emu/System.h"
#include "Emu/system_utils.hpp"
#include "Emu/Cell/Modules/sceNpTrophy.h"
#include "Emu/Cell/Modules/cellRtc.h"
#include <QApplication>
#include <QClipboard>
@ -148,6 +150,7 @@ trophy_manager_dialog::trophy_manager_dialog(std::shared_ptr<gui_settings> gui_s
add_trophy_column(gui::trophy_list_columns::is_unlocked, tr("Status"), tr("Show Status"));
add_trophy_column(gui::trophy_list_columns::id, tr("ID"), tr("Show IDs"));
add_trophy_column(gui::trophy_list_columns::platinum_link, tr("Platinum Relevant"), tr("Show Platinum Relevant"));
add_trophy_column(gui::trophy_list_columns::time_unlocked, tr("Time Unlocked"), tr("Show Time Unlocked"));
m_splitter = new QSplitter();
m_splitter->addWidget(m_game_table);
@ -1028,6 +1031,8 @@ void trophy_manager_dialog::PopulateTrophyTable()
QPixmap placeholder(m_icon_height, m_icon_height);
placeholder.fill(Qt::transparent);
const QLocale locale{};
int i = 0;
for (std::shared_ptr<rXmlNode> n = trophy_base->GetChildren(); n; n = n->GetNext())
{
@ -1079,6 +1084,10 @@ void trophy_manager_dialog::PopulateTrophyTable()
}
}
// Get timestamp
const u64 tick = data->trop_usr->GetTrophyTimestamp(trophy_id);
const QString datetime = tick ? locale.toString(TickToDateTime(tick), gui::persistent::last_played_date_with_time_of_day_format) : tr("Unknown");
const QString unlockstate = data->trop_usr->GetTrophyUnlockState(trophy_id) ? tr("Earned") : tr("Not Earned");
custom_table_widget_item* icon_item = new custom_table_widget_item();
@ -1095,6 +1104,7 @@ void trophy_manager_dialog::PopulateTrophyTable()
m_trophy_table->setItem(i, static_cast<int>(gui::trophy_list_columns::is_unlocked), new custom_table_widget_item(unlockstate));
m_trophy_table->setItem(i, static_cast<int>(gui::trophy_list_columns::id), new custom_table_widget_item(QString::number(trophy_id), Qt::UserRole, trophy_id));
m_trophy_table->setItem(i, static_cast<int>(gui::trophy_list_columns::platinum_link), new custom_table_widget_item(platinum_relevant, Qt::UserRole, platinum_link_id));
m_trophy_table->setItem(i, static_cast<int>(gui::trophy_list_columns::time_unlocked), new custom_table_widget_item(datetime, Qt::UserRole, QVariant::fromValue<qulonglong>(tick)));
++i;
}
@ -1225,3 +1235,13 @@ void trophy_manager_dialog::WaitAndAbortTrophyRepaintThreads()
}
}
}
QDateTime trophy_manager_dialog::TickToDateTime(u64 tick)
{
const CellRtcDateTime rtc_date = tick_to_date_time(tick);
const QDateTime datetime(
QDate(rtc_date.year, rtc_date.month, rtc_date.day),
QTime(rtc_date.hour, rtc_date.minute, rtc_date.second, rtc_date.microsecond / 1000),
Qt::TimeSpec::UTC);
return datetime.toLocalTime();
}

View File

@ -80,6 +80,8 @@ private:
void closeEvent(QCloseEvent *event) override;
bool eventFilter(QObject *object, QEvent *event) override;
static QDateTime TickToDateTime(u64 tick);
std::shared_ptr<gui_settings> m_gui_settings;
std::vector<std::unique_ptr<GameTrophiesData>> m_trophies_db; //! Holds all the trophy information.