mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-22 09:09:18 +01:00
nn_pdm: Refactor code to use new module structure
This commit is contained in:
parent
9398c0ca6b
commit
67f7ce815c
@ -530,7 +530,8 @@ namespace CafeSystem
|
|||||||
{
|
{
|
||||||
// entries in this list are ordered by initialization order. Shutdown in reverse order
|
// entries in this list are ordered by initialization order. Shutdown in reverse order
|
||||||
iosu::kernel::GetModule(),
|
iosu::kernel::GetModule(),
|
||||||
iosu::fpd::GetModule()
|
iosu::fpd::GetModule(),
|
||||||
|
iosu::pdm::GetModule(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// initialize all subsystems which are persistent and don't depend on a game running
|
// initialize all subsystems which are persistent and don't depend on a game running
|
||||||
@ -571,7 +572,6 @@ namespace CafeSystem
|
|||||||
iosu::iosuAcp_init();
|
iosu::iosuAcp_init();
|
||||||
iosu::boss_init();
|
iosu::boss_init();
|
||||||
iosu::nim::Initialize();
|
iosu::nim::Initialize();
|
||||||
iosu::pdm::Initialize();
|
|
||||||
iosu::odm::Initialize();
|
iosu::odm::Initialize();
|
||||||
// init Cafe OS
|
// init Cafe OS
|
||||||
avm::Initialize();
|
avm::Initialize();
|
||||||
@ -840,7 +840,6 @@ namespace CafeSystem
|
|||||||
coreinit::OSSchedulerBegin(3);
|
coreinit::OSSchedulerBegin(3);
|
||||||
else
|
else
|
||||||
coreinit::OSSchedulerBegin(1);
|
coreinit::OSSchedulerBegin(1);
|
||||||
iosu::pdm::StartTrackingTime(GetForegroundTitleId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LaunchForegroundTitle()
|
void LaunchForegroundTitle()
|
||||||
@ -970,8 +969,6 @@ namespace CafeSystem
|
|||||||
RPLLoader_ResetState();
|
RPLLoader_ResetState();
|
||||||
for(auto it = s_iosuModules.rbegin(); it != s_iosuModules.rend(); ++it)
|
for(auto it = s_iosuModules.rbegin(); it != s_iosuModules.rend(); ++it)
|
||||||
(*it)->TitleStop();
|
(*it)->TitleStop();
|
||||||
// stop time tracking
|
|
||||||
iosu::pdm::Stop();
|
|
||||||
// reset Cemu subsystems
|
// reset Cemu subsystems
|
||||||
PPCRecompiler_Shutdown();
|
PPCRecompiler_Shutdown();
|
||||||
GraphicPack2::Reset();
|
GraphicPack2::Reset();
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "iosu_pdm.h"
|
#include "iosu_pdm.h"
|
||||||
|
#include "Cafe/CafeSystem.h"
|
||||||
#include "config/ActiveSettings.h"
|
#include "config/ActiveSettings.h"
|
||||||
#include "Common/FileStream.h"
|
#include "Common/FileStream.h"
|
||||||
#include "util/helpers/Semaphore.h"
|
#include "util/helpers/Semaphore.h"
|
||||||
@ -17,7 +18,8 @@ namespace iosu
|
|||||||
{
|
{
|
||||||
namespace pdm
|
namespace pdm
|
||||||
{
|
{
|
||||||
std::mutex sDiaryLock;
|
std::recursive_mutex sPlaystatsLock;
|
||||||
|
std::recursive_mutex sDiaryLock;
|
||||||
|
|
||||||
fs::path GetPDFile(const char* filename)
|
fs::path GetPDFile(const char* filename)
|
||||||
{
|
{
|
||||||
@ -80,14 +82,16 @@ namespace iosu
|
|||||||
static_assert((NUM_PLAY_STATS_ENTRIES * sizeof(PlayStatsEntry)) == 0x1400);
|
static_assert((NUM_PLAY_STATS_ENTRIES * sizeof(PlayStatsEntry)) == 0x1400);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadPlaystats()
|
void OpenPlaystats()
|
||||||
{
|
{
|
||||||
|
std::unique_lock _l(sPlaystatsLock);
|
||||||
PlayStats.numEntries = 0;
|
PlayStats.numEntries = 0;
|
||||||
for (size_t i = 0; i < NUM_PLAY_STATS_ENTRIES; i++)
|
for (size_t i = 0; i < NUM_PLAY_STATS_ENTRIES; i++)
|
||||||
{
|
{
|
||||||
auto& e = PlayStats.entry[i];
|
auto& e = PlayStats.entry[i];
|
||||||
memset(&e, 0, sizeof(PlayStatsEntry));
|
memset(&e, 0, sizeof(PlayStatsEntry));
|
||||||
}
|
}
|
||||||
|
cemu_assert_debug(!PlayStats.fs);
|
||||||
PlayStats.fs = FileStream::openFile2(GetPDFile("PlayStats.dat"), true);
|
PlayStats.fs = FileStream::openFile2(GetPDFile("PlayStats.dat"), true);
|
||||||
if (!PlayStats.fs)
|
if (!PlayStats.fs)
|
||||||
{
|
{
|
||||||
@ -98,18 +102,39 @@ namespace iosu
|
|||||||
{
|
{
|
||||||
delete PlayStats.fs;
|
delete PlayStats.fs;
|
||||||
PlayStats.fs = nullptr;
|
PlayStats.fs = nullptr;
|
||||||
cemuLog_log(LogType::Force, "PlayStats.dat malformed");
|
cemuLog_log(LogType::Force, "PlayStats.dat malformed. Time tracking wont be used");
|
||||||
// dont delete the existing file in case it could still be salvaged (todo) and instead just dont track play time
|
// dont delete the existing file in case it could still be salvaged (todo) and instead just dont track play time
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
PlayStats.numEntries = 0;
|
||||||
PlayStats.fs->readData(&PlayStats.numEntries, sizeof(uint32be));
|
PlayStats.fs->readData(&PlayStats.numEntries, sizeof(uint32be));
|
||||||
if (PlayStats.numEntries > NUM_PLAY_STATS_ENTRIES)
|
if (PlayStats.numEntries > NUM_PLAY_STATS_ENTRIES)
|
||||||
PlayStats.numEntries = NUM_PLAY_STATS_ENTRIES;
|
PlayStats.numEntries = NUM_PLAY_STATS_ENTRIES;
|
||||||
PlayStats.fs->readData(PlayStats.entry, NUM_PLAY_STATS_ENTRIES * 20);
|
PlayStats.fs->readData(PlayStats.entry, NUM_PLAY_STATS_ENTRIES * 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClosePlaystats()
|
||||||
|
{
|
||||||
|
std::unique_lock _l(sPlaystatsLock);
|
||||||
|
if (PlayStats.fs)
|
||||||
|
{
|
||||||
|
delete PlayStats.fs;
|
||||||
|
PlayStats.fs = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadPlaystats()
|
||||||
|
{
|
||||||
|
std::unique_lock _l(sPlaystatsLock);
|
||||||
|
cemu_assert_debug(!PlayStats.fs); // unloading expects that file is closed
|
||||||
|
PlayStats.numEntries = 0;
|
||||||
|
for(auto& it : PlayStats.entry)
|
||||||
|
it = PlayStatsEntry{};
|
||||||
|
}
|
||||||
|
|
||||||
PlayStatsEntry* PlayStats_GetEntry(uint64 titleId)
|
PlayStatsEntry* PlayStats_GetEntry(uint64 titleId)
|
||||||
{
|
{
|
||||||
|
std::unique_lock _l(sPlaystatsLock);
|
||||||
uint32be titleIdHigh = (uint32)(titleId>>32);
|
uint32be titleIdHigh = (uint32)(titleId>>32);
|
||||||
uint32be titleIdLow = (uint32)(titleId & 0xFFFFFFFF);
|
uint32be titleIdLow = (uint32)(titleId & 0xFFFFFFFF);
|
||||||
size_t numEntries = PlayStats.numEntries;
|
size_t numEntries = PlayStats.numEntries;
|
||||||
@ -121,7 +146,7 @@ namespace iosu
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayStats_WriteEntry(PlayStatsEntry* entry, bool writeEntryCount = false)
|
void PlayStats_WriteEntryNoLock(PlayStatsEntry* entry, bool writeEntryCount = false)
|
||||||
{
|
{
|
||||||
if (!PlayStats.fs)
|
if (!PlayStats.fs)
|
||||||
return;
|
return;
|
||||||
@ -141,8 +166,15 @@ namespace iosu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayStats_WriteEntry(PlayStatsEntry* entry, bool writeEntryCount = false)
|
||||||
|
{
|
||||||
|
std::unique_lock _l(sPlaystatsLock);
|
||||||
|
PlayStats_WriteEntryNoLock(entry, writeEntryCount);
|
||||||
|
}
|
||||||
|
|
||||||
PlayStatsEntry* PlayStats_CreateEntry(uint64 titleId)
|
PlayStatsEntry* PlayStats_CreateEntry(uint64 titleId)
|
||||||
{
|
{
|
||||||
|
std::unique_lock _l(sPlaystatsLock);
|
||||||
bool entryCountChanged = false;
|
bool entryCountChanged = false;
|
||||||
PlayStatsEntry* newEntry;
|
PlayStatsEntry* newEntry;
|
||||||
if(PlayStats.numEntries < NUM_PLAY_STATS_ENTRIES)
|
if(PlayStats.numEntries < NUM_PLAY_STATS_ENTRIES)
|
||||||
@ -168,7 +200,7 @@ namespace iosu
|
|||||||
newEntry->numTimesLaunched = 1;
|
newEntry->numTimesLaunched = 1;
|
||||||
newEntry->totalMinutesPlayed = 0;
|
newEntry->totalMinutesPlayed = 0;
|
||||||
newEntry->ukn12 = 0;
|
newEntry->ukn12 = 0;
|
||||||
PlayStats_WriteEntry(newEntry, entryCountChanged);
|
PlayStats_WriteEntryNoLock(newEntry, entryCountChanged);
|
||||||
return newEntry;
|
return newEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,6 +208,7 @@ namespace iosu
|
|||||||
// if it does not exist it creates a new entry with first and last played set to today
|
// if it does not exist it creates a new entry with first and last played set to today
|
||||||
PlayStatsEntry* PlayStats_BeginNewTracking(uint64 titleId)
|
PlayStatsEntry* PlayStats_BeginNewTracking(uint64 titleId)
|
||||||
{
|
{
|
||||||
|
std::unique_lock _l(sPlaystatsLock);
|
||||||
PlayStatsEntry* entry = PlayStats_GetEntry(titleId);
|
PlayStatsEntry* entry = PlayStats_GetEntry(titleId);
|
||||||
if (entry)
|
if (entry)
|
||||||
{
|
{
|
||||||
@ -189,11 +222,12 @@ namespace iosu
|
|||||||
|
|
||||||
void PlayStats_CountAdditionalMinutes(PlayStatsEntry* entry, uint32 additionalMinutes)
|
void PlayStats_CountAdditionalMinutes(PlayStatsEntry* entry, uint32 additionalMinutes)
|
||||||
{
|
{
|
||||||
|
std::unique_lock _l(sPlaystatsLock);
|
||||||
if (additionalMinutes == 0)
|
if (additionalMinutes == 0)
|
||||||
return;
|
return;
|
||||||
entry->totalMinutesPlayed += additionalMinutes;
|
entry->totalMinutesPlayed += additionalMinutes;
|
||||||
entry->mostRecentDayIndex = GetTodaysDayIndex();
|
entry->mostRecentDayIndex = GetTodaysDayIndex();
|
||||||
PlayStats_WriteEntry(entry);
|
PlayStats_WriteEntryNoLock(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PlayDiaryHeader
|
struct PlayDiaryHeader
|
||||||
@ -218,6 +252,7 @@ namespace iosu
|
|||||||
void CreatePlayDiary()
|
void CreatePlayDiary()
|
||||||
{
|
{
|
||||||
MakeDirectory();
|
MakeDirectory();
|
||||||
|
cemu_assert_debug(!PlayDiaryData.fs);
|
||||||
PlayDiaryData.fs = FileStream::createFile2(GetPDFile("PlayDiary.dat"));
|
PlayDiaryData.fs = FileStream::createFile2(GetPDFile("PlayDiary.dat"));
|
||||||
if (!PlayDiaryData.fs)
|
if (!PlayDiaryData.fs)
|
||||||
{
|
{
|
||||||
@ -230,7 +265,7 @@ namespace iosu
|
|||||||
PlayDiaryData.fs->writeData(&PlayDiaryData.header, sizeof(PlayDiaryHeader));
|
PlayDiaryData.fs->writeData(&PlayDiaryData.header, sizeof(PlayDiaryHeader));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadPlayDiary()
|
void OpenPlayDiary()
|
||||||
{
|
{
|
||||||
std::unique_lock _lock(sDiaryLock);
|
std::unique_lock _lock(sDiaryLock);
|
||||||
cemu_assert_debug(!PlayDiaryData.fs);
|
cemu_assert_debug(!PlayDiaryData.fs);
|
||||||
@ -268,6 +303,26 @@ namespace iosu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClosePlayDiary()
|
||||||
|
{
|
||||||
|
std::unique_lock _lock(sDiaryLock);
|
||||||
|
if (PlayDiaryData.fs)
|
||||||
|
{
|
||||||
|
delete PlayDiaryData.fs;
|
||||||
|
PlayDiaryData.fs = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadDiaryData()
|
||||||
|
{
|
||||||
|
std::unique_lock _lock(sDiaryLock);
|
||||||
|
cemu_assert_debug(!PlayDiaryData.fs); // unloading expects that file is closed
|
||||||
|
PlayDiaryData.header.readIndex = 0;
|
||||||
|
PlayDiaryData.header.writeIndex = 0;
|
||||||
|
for (auto& it : PlayDiaryData.entry)
|
||||||
|
it = PlayDiaryEntry{};
|
||||||
|
}
|
||||||
|
|
||||||
uint32 GetDiaryEntries(uint8 accountSlot, PlayDiaryEntry* diaryEntries, uint32 maxEntries)
|
uint32 GetDiaryEntries(uint8 accountSlot, PlayDiaryEntry* diaryEntries, uint32 maxEntries)
|
||||||
{
|
{
|
||||||
std::unique_lock _lock(sDiaryLock);
|
std::unique_lock _lock(sDiaryLock);
|
||||||
@ -352,25 +407,59 @@ namespace iosu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialize()
|
class : public ::IOSUModule
|
||||||
{
|
{
|
||||||
// todo - add support for per-account handling
|
void PDMLoadAll()
|
||||||
LoadPlaystats();
|
{
|
||||||
LoadPlayDiary();
|
OpenPlaystats();
|
||||||
}
|
OpenPlayDiary();
|
||||||
|
}
|
||||||
void StartTrackingTime(uint64 titleId)
|
|
||||||
{
|
|
||||||
sPDMRequestExitThread = false;
|
|
||||||
sPDMTimeTrackingThread = std::thread(TimeTrackingThread, titleId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Stop()
|
void PDMUnloadAll()
|
||||||
|
{
|
||||||
|
UnloadPlaystats();
|
||||||
|
UnloadDiaryData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDMCloseAll()
|
||||||
|
{
|
||||||
|
ClosePlaystats();
|
||||||
|
ClosePlayDiary();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLaunch() override
|
||||||
|
{
|
||||||
|
// todo - add support for per-account handling
|
||||||
|
PDMLoadAll();
|
||||||
|
PDMCloseAll(); // close the files again, user may mess with MLC files or change MLC path while no game is running
|
||||||
|
}
|
||||||
|
void SystemExit() override
|
||||||
|
{
|
||||||
|
PDMCloseAll();
|
||||||
|
PDMUnloadAll();
|
||||||
|
}
|
||||||
|
void TitleStart() override
|
||||||
|
{
|
||||||
|
// reload data and keep files open
|
||||||
|
PDMUnloadAll();
|
||||||
|
PDMLoadAll();
|
||||||
|
auto titleId = CafeSystem::GetForegroundTitleId();
|
||||||
|
sPDMRequestExitThread = false;
|
||||||
|
sPDMTimeTrackingThread = std::thread(TimeTrackingThread, titleId);
|
||||||
|
}
|
||||||
|
void TitleStop() override
|
||||||
|
{
|
||||||
|
sPDMRequestExitThread.store(true);
|
||||||
|
sPDMSem.increment();
|
||||||
|
if(sPDMTimeTrackingThread.joinable())
|
||||||
|
sPDMTimeTrackingThread.join();
|
||||||
|
PDMCloseAll();
|
||||||
|
}
|
||||||
|
}sIOSUModuleNNPDM;
|
||||||
|
|
||||||
|
IOSUModule* GetModule()
|
||||||
{
|
{
|
||||||
sPDMRequestExitThread.store(true);
|
return static_cast<IOSUModule*>(&sIOSUModuleNNPDM);
|
||||||
sPDMSem.increment();
|
|
||||||
if(sPDMTimeTrackingThread.joinable())
|
|
||||||
sPDMTimeTrackingThread.join();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "Cafe/IOSU/iosu_types_common.h"
|
||||||
|
|
||||||
namespace iosu
|
namespace iosu
|
||||||
{
|
{
|
||||||
namespace pdm
|
namespace pdm
|
||||||
{
|
{
|
||||||
void Initialize();
|
|
||||||
void StartTrackingTime(uint64 titleId);
|
|
||||||
void Stop();
|
|
||||||
|
|
||||||
inline constexpr size_t NUM_PLAY_STATS_ENTRIES = 256;
|
inline constexpr size_t NUM_PLAY_STATS_ENTRIES = 256;
|
||||||
inline constexpr size_t NUM_PLAY_DIARY_ENTRIES_MAX = 18250; // 0x474A
|
inline constexpr size_t NUM_PLAY_DIARY_ENTRIES_MAX = 18250; // 0x474A
|
||||||
|
|
||||||
@ -34,5 +31,7 @@ namespace iosu
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool GetStatForGamelist(uint64 titleId, GameListStat& stat);
|
bool GetStatForGamelist(uint64 titleId, GameListStat& stat);
|
||||||
|
|
||||||
|
IOSUModule* GetModule();
|
||||||
};
|
};
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user