From e1c1cfe79e025e108715923ec01af06c27ddb067 Mon Sep 17 00:00:00 2001 From: ConorB <11508137+ConorBobbleHat@users.noreply.github.com> Date: Sun, 19 Jun 2022 12:52:59 +0100 Subject: [PATCH] ksys::ProductReporter (#93) Co-authored-by: ConorBobbleHat --- data/uking_functions.csv | 76 +++---- src/KingSystem/Framework/CMakeLists.txt | 2 + src/KingSystem/Framework/Framework.cpp | 1 + src/KingSystem/Framework/Framework.h | 15 ++ src/KingSystem/Sound/CMakeLists.txt | 2 + src/KingSystem/Sound/sndMgr.cpp | 1 + src/KingSystem/Sound/sndMgr.h | 26 +++ src/KingSystem/System/ProductReporter.cpp | 233 ++++++++++++++++++++++ src/KingSystem/System/ProductReporter.h | 108 +++++++++- src/KingSystem/System/VFR.h | 3 + 10 files changed, 428 insertions(+), 39 deletions(-) create mode 100644 src/KingSystem/Framework/Framework.cpp create mode 100644 src/KingSystem/Framework/Framework.h create mode 100644 src/KingSystem/Sound/sndMgr.cpp create mode 100644 src/KingSystem/Sound/sndMgr.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index f5713a6a..92167986 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -84357,11 +84357,11 @@ Address,Quality,Size,Name 0x0000007100fd09d0,U,000076, 0x0000007100fd0a1c,U,000016, 0x0000007100fd0a2c,U,000680, -0x0000007100fd0cd4,U,000036, -0x0000007100fd0cf8,U,000064, -0x0000007100fd0d38,U,000060, -0x0000007100fd0d74,U,000104, -0x0000007100fd0ddc,U,000936, +0x0000007100fd0cd4,U,000036,PlayerTrackReporter::ctor +0x0000007100fd0cf8,U,000064,PlayerTrackReporter::dtor +0x0000007100fd0d38,U,000060,PlayerTrackReporter::dtor2 +0x0000007100fd0d74,U,000104,PlayerTrackReporter::init +0x0000007100fd0ddc,U,000936,PlayerTrackReporter::setPosTrackEnd 0x0000007100fd1184,U,000236, 0x0000007100fd1270,U,000032, 0x0000007100fd1290,O,000432,_ZN4ksys10PlayReport10setEventIdERN4sead22BufferedSafeStringBaseIcEE @@ -84373,34 +84373,34 @@ Address,Quality,Size,Name 0x0000007100fd1670,O,000164,_ZN4ksys10PlayReport4initEiPN4sead4HeapE 0x0000007100fd1714,O,000084,_ZN4ksys10PlayReportD1Ev 0x0000007100fd1768,U,000032, -0x0000007100fd1788,U,000012,playReportGetSomeBool -0x0000007100fd1794,U,000008,ProductReporter::isInitialized -0x0000007100fd179c,U,000116,ProductReporter::x -0x0000007100fd1810,U,000116,ProductReporter::x_0 -0x0000007100fd1884,U,000116,ProductReporter::x_1 -0x0000007100fd18f8,U,000116,ProductReporter::x_2 -0x0000007100fd196c,U,000116,ProductReporter::x_3 -0x0000007100fd19e0,U,000116,ProductReporter::x_4 -0x0000007100fd1a54,U,000116,ProductReporter::x_5 -0x0000007100fd1ac8,U,000116,ProductReporter::x_6 -0x0000007100fd1b3c,U,000116,ProductReporter::x_7 -0x0000007100fd1bb0,U,000116,ProductReporter::x_8 -0x0000007100fd1c24,U,000116,ProductReporter::x_9 -0x0000007100fd1c98,U,000016,ProductReporter::getRomWorkTime -0x0000007100fd1ca8,U,000016,ProductReporter::getSceneWorkTime -0x0000007100fd1cb8,U,000016,ProductReporter::resetSceneWorkTime -0x0000007100fd1cc8,U,000380,ProductReporter::init -0x0000007100fd1e44,U,000060, -0x0000007100fd1e80,U,000280, -0x0000007100fd1f98,U,001672,ProductReporter::incrementSceneAndRomWorkTime +0x0000007100fd1788,U,000012,ProductReporter::getSomeBool +0x0000007100fd1794,O,000008,_ZNK4ksys15ProductReporter9isEnabledEv +0x0000007100fd179c,O,000116,_ZNK4ksys15ProductReporter11getPlayTimeEv +0x0000007100fd1810,O,000116,_ZNK4ksys15ProductReporter14getAllPlayTimeEv +0x0000007100fd1884,O,000116,_ZNK4ksys15ProductReporter15getCtrlModeFreeEv +0x0000007100fd18f8,O,000116,_ZNK4ksys15ProductReporter14getCtrlModeExtEv +0x0000007100fd196c,O,000116,_ZNK4ksys15ProductReporter18getCtrlModeFullKeyEv +0x0000007100fd19e0,O,000116,_ZNK4ksys15ProductReporter19getCtrlModeHandheldEv +0x0000007100fd1a54,O,000116,_ZNK4ksys15ProductReporter22getCtrlModeConsoleFreeEv +0x0000007100fd1ac8,O,000116,_ZNK4ksys15ProductReporter21getCtrlModeConsoleExtEv +0x0000007100fd1b3c,O,000116,_ZNK4ksys15ProductReporter25getCtrlModeConsoleFullKeyEv +0x0000007100fd1bb0,O,000116,_ZNK4ksys15ProductReporter27getCtrlModePlayTimeHandheldEv +0x0000007100fd1c24,O,000116,_ZNK4ksys15ProductReporter18getPlayTimeConsoleEv +0x0000007100fd1c98,O,000016,_ZNK4ksys15ProductReporter14getRomWorkTimeEv +0x0000007100fd1ca8,O,000016,_ZNK4ksys15ProductReporter16getSceneWorkTimeEv +0x0000007100fd1cb8,O,000016,_ZN4ksys15ProductReporter18resetSceneWorkTimeEv +0x0000007100fd1cc8,O,000380,_ZN4ksys15ProductReporter4initEPN4sead4HeapE +0x0000007100fd1e44,O,000060,_ZN4ksys15ProductReporter9terminateEv +0x0000007100fd1e80,O,000280,_ZN4ksys15ProductReporter12updateTimersEv +0x0000007100fd1f98,m,001672,_ZN4ksys15ProductReporter28incrementSceneAndRomWorkTimeEv 0x0000007100fd2620,U,000076, 0x0000007100fd266c,U,000620,playReportEmergencyHeapUse 0x0000007100fd28d8,U,001436,PlayReport::Report::addRomVersions 0x0000007100fd2e74,U,000688,PlayReport::Report::addPlayTimes 0x0000007100fd3124,U,000476,PlayReport::Report::addPosition -0x0000007100fd3300,U,000028,ProductReporter::saveReport -0x0000007100fd331c,U,000112,ProductReporter::initGameDataIterators -0x0000007100fd338c,U,000428,ProductReporter::getReportKey +0x0000007100fd3300,O,000028,_ZNK4ksys15ProductReporter10saveReportEPNS_10PlayReportE +0x0000007100fd331c,O,000112,_ZN4ksys15ProductReporter21initGameDataIteratorsEv +0x0000007100fd338c,O,000428,_ZN4ksys13PlayReportKey5text_Ei 0x0000007100fd3538,U,000004,j__ZdlPv_1017 0x0000007100fd353c,U,000240,_ZN4sead19FixedSafeStringBaseIcLi76EEaSERKNS_14SafeStringBaseIcEE 0x0000007100fd362c,U,000004,j__ZdlPv_1018 @@ -84411,18 +84411,18 @@ Address,Quality,Size,Name 0x0000007100fd381c,O,000156,_ZN4ksys13PlayReportMgr14createInstanceEPN4sead4HeapE 0x0000007100fd38b8,O,000040,_ZN4ksys13PlayReportMgrD1Ev 0x0000007100fd38e0,O,000068,_ZN4ksys13PlayReportMgrD0Ev -0x0000007100fd3924,U,000264,PlayReport::init -0x0000007100fd3a2c,U,000024,PlayReport::calc -0x0000007100fd3a44,U,000008,PlayReport::__auto0 +0x0000007100fd3924,U,000264,PlayReportMgr::init +0x0000007100fd3a2c,U,000024,PlayReportMgr::calc +0x0000007100fd3a44,U,000008,PlayReportMgr::__auto0 0x0000007100fd3a4c,U,000004,nullsub_6149 -0x0000007100fd3a54,U,000004,PlayReport::reportDebug -0x0000007100fd3a58,U,000024,PlayReport::__auto2 -0x0000007100fd3a70,U,000028,PlayReport::__auto1 -0x0000007100fd3a8c,U,000028,PlayReport::__auto3 -0x0000007100fd3aa8,U,000028,PlayReport::x +0x0000007100fd3a54,U,000004,PlayReportMgr::reportDebug +0x0000007100fd3a58,U,000024,PlayReportMgr::__auto2 +0x0000007100fd3a70,U,000028,PlayReportMgr::__auto1 +0x0000007100fd3a8c,U,000028,PlayReportMgr::__auto3 +0x0000007100fd3aa8,U,000028,PlayReportMgr::x 0x0000007100fd3ac4,U,000004,ProductReporter::jInitGameDataIterators -0x0000007100fd3ac8,U,000124, -0x0000007100fd3b44,U,000132, +0x0000007100fd3ac8,O,000124,_ZN4ksys15ProductReporterD1Ev +0x0000007100fd3b44,O,000132,_ZN4ksys15ProductReporterD0Ev 0x0000007100fd3bc8,U,000048, 0x0000007100fd3bf8,U,000092, 0x0000007100fd3c54,U,000156, diff --git a/src/KingSystem/Framework/CMakeLists.txt b/src/KingSystem/Framework/CMakeLists.txt index 622647a3..cbae2e87 100644 --- a/src/KingSystem/Framework/CMakeLists.txt +++ b/src/KingSystem/Framework/CMakeLists.txt @@ -2,4 +2,6 @@ target_sources(uking PRIVATE frmRootTaskParam.h frmWorkerSupportThreadMgr.cpp frmWorkerSupportThreadMgr.h + Framework.cpp + Framework.h ) diff --git a/src/KingSystem/Framework/Framework.cpp b/src/KingSystem/Framework/Framework.cpp new file mode 100644 index 00000000..f11ef44e --- /dev/null +++ b/src/KingSystem/Framework/Framework.cpp @@ -0,0 +1 @@ +#include "KingSystem/Framework/Framework.h" \ No newline at end of file diff --git a/src/KingSystem/Framework/Framework.h b/src/KingSystem/Framework/Framework.h new file mode 100644 index 00000000..aa390f57 --- /dev/null +++ b/src/KingSystem/Framework/Framework.h @@ -0,0 +1,15 @@ +#pragma once +#include +#include + +namespace ksys::frm { + +// FIXME: incomplete +struct Framework { + static Framework* instance(); + + u8 _0[0x278]; + nn::oe::OperationMode mOperationMode; +}; + +} // namespace ksys::frm \ No newline at end of file diff --git a/src/KingSystem/Sound/CMakeLists.txt b/src/KingSystem/Sound/CMakeLists.txt index 3198e338..e86e8ff0 100644 --- a/src/KingSystem/Sound/CMakeLists.txt +++ b/src/KingSystem/Sound/CMakeLists.txt @@ -7,4 +7,6 @@ target_sources(uking PRIVATE sndMusicInfo.h sndResource.cpp sndResource.h + sndMgr.cpp + sndMgr.h ) diff --git a/src/KingSystem/Sound/sndMgr.cpp b/src/KingSystem/Sound/sndMgr.cpp new file mode 100644 index 00000000..18af6b65 --- /dev/null +++ b/src/KingSystem/Sound/sndMgr.cpp @@ -0,0 +1 @@ +#include "KingSystem/Sound/sndMgr.h" \ No newline at end of file diff --git a/src/KingSystem/Sound/sndMgr.h b/src/KingSystem/Sound/sndMgr.h new file mode 100644 index 00000000..4f6c349b --- /dev/null +++ b/src/KingSystem/Sound/sndMgr.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +namespace ksys::snd { + +enum class AudioChannelType { + Mono = 1, + Stereo = 2, + _5_1ch = 6, + Other = -1 // TODO: does Other have a definite value? +}; + +// FIXME: incomplete +struct SoundMgr { + SEAD_SINGLETON_DISPOSER(SoundMgr); + + virtual ~SoundMgr(); + +public: + u8 _28[0x248]; + AudioChannelType mAudioChannelType; +}; + +} // namespace ksys::snd \ No newline at end of file diff --git a/src/KingSystem/System/ProductReporter.cpp b/src/KingSystem/System/ProductReporter.cpp index 92333196..c6589b8b 100644 --- a/src/KingSystem/System/ProductReporter.cpp +++ b/src/KingSystem/System/ProductReporter.cpp @@ -1 +1,234 @@ #include "KingSystem/System/ProductReporter.h" + +#include +#include +#include +#include +#include + +#include "KingSystem/Framework/Framework.h" +#include "KingSystem/Map/mapPlacementMgr.h" +#include "KingSystem/Sound/sndMgr.h" +#include "KingSystem/System/CameraMgr.h" +#include "KingSystem/System/PlayReportMgr.h" +#include "KingSystem/System/VFR.h" + +namespace ksys { + +static WorkTimes sWorkTimes; + +auto& getWorkTimes() { + return sWorkTimes; +}; + +[[gnu::noinline]] void ProductReporter::terminate() { + if (mIsInitalized) { + gdt::Manager::instance()->removeReinitCallback(mSlot); + mIsInitalized = false; + } +} + +ProductReporter::~ProductReporter() { + terminate(); +} + +void ProductReporter::init(sead::Heap* heap) { + if (mIsInitalized) + return; + + mHeap = sead::ExpHeap::create(0x18000, "ProductReporter Heap", heap, sizeof(void*), + sead::Heap::cHeapDirection_Forward, true); + + nn::account::Initialize(); + + s32 listAllUsersRet = -1; + nn::account::Uid uid[8]; + nn::account::ListAllUsers(&listAllUsersRet, uid, 8); + + if (0 < listAllUsersRet) { + for (int i = 0; i < PlayReportKey::size(); i++) + mGameDataHandles[i] = gdt::InvalidHandle; + + mPlayerTrackReporter = new (heap) PlayerTrackReporter; + mPlayerTrackReporter->init(heap); + + mContainer1.init(heap, 0x20, 0x30); + mContainer2.init(heap, 0x20, 0x30); + mContainer3.init(heap, 0x20, 0x30); + mContainer4.init(heap, 0x20, 0x30); + + mIsInitalized = true; + } +} + +void ProductReporter::initGameDataIterators() { + for (int i = 0; i < PlayReportKey::size(); i++) { + mGameDataHandles[i] = gdt::Manager::instance()->getS32Handle(PlayReportKey::text(i)); + } +} + +bool ProductReporter::isEnabled() const { + return mEnabled; +} + +s32 ProductReporter::getRomWorkTime() const { + return sWorkTimes.rom; +} + +s32 ProductReporter::getSceneWorkTime() const { + return sWorkTimes.scene; +} + +void ProductReporter::resetSceneWorkTime() { + sWorkTimes.scene = 0; +} + +void ProductReporter::updateTimers() { + if (!mEnabled) + return; + + mIncrementWorkTimesTimer += VFR::instance()->getIntervalRatio(); + + if (mIncrementWorkTimesTimer >= 30.0f) { + mIncrementWorkTimesTimer -= 30.0f; + if (incrementSceneAndRomWorkTime()) { + mPlayerTrackReporter->setPosTrackEnd(); + } + } + + mNinetyTickTimer += VFR::instance()->getIntervalRatio(); + if (!(90.0f > mNinetyTickTimer)) { + mNinetyTickTimer -= 90.0f; + } +} + +bool ProductReporter::saveReport(PlayReport* playReport) const { + if (playReport != nullptr && mEnabled) { + return playReport->save(); + } + + return false; +} + +// NON_MATCHING: minor reordering & deduplication +bool ProductReporter::incrementSceneAndRomWorkTime() { + if (map::PlacementMgr::instance() == nullptr) + return false; + + s32 value = 0; + sWorkTimes.rom++; + sWorkTimes.scene++; + + auto* camera = CameraMgr::instance()->getLookAtCamera(); + + if (camera != nullptr && mPos != camera->getPos()) { + mCameraIdleTimer = 0.0f; + mPos = camera->getPos(); + } + + if (!(mCameraIdleTimer < 300.0f)) + return false; + + mCameraIdleTimer += 1.0f; + + increment(PlayReportKey::PlayReport_AllPlayTime, &value); + increment(PlayReportKey::PlayReport_PlayTime, &value); + + { + s32 value = 0; + auto* framework = frm::Framework::instance(); + + switch (framework->mOperationMode) { + case nn::oe::OperationMode_Handheld: + increment(PlayReportKey::PlayReport_PlayTime_Handheld, &value); + + switch (mCtrlMode) { + case 1: + increment(PlayReportKey::PlayReport_CtrlMode_Free, &value); + break; + case 2: + increment(PlayReportKey::PlayReport_CtrlMode_Ext, &value); + break; + case 3: + increment(PlayReportKey::PlayReport_CtrlMode_FullKey, &value); + break; + case 4: + increment(PlayReportKey::PlayReport_CtrlMode_Handheld, &value); + break; + default: + break; + } + + break; + + case nn::oe::OperationMode_Docked: + increment(PlayReportKey::PlayReport_PlayTime_Console, &value); + + switch (mCtrlMode) { + case 1: + increment(PlayReportKey::PlayReport_CtrlMode_Console_Free, &value); + break; + case 2: + increment(PlayReportKey::PlayReport_CtrlMode_Console_Ext, &value); + break; + case 3: + increment(PlayReportKey::PlayReport_CtrlMode_Console_FullKey, &value); + break; + default: + break; + } + + break; + } + } + + { + s32 value = 0; + + auto* snd = snd::SoundMgr::instance(); + if (snd == nullptr) + return true; + + switch (snd->mAudioChannelType) { + case snd::AudioChannelType::Mono: + increment(PlayReportKey::PlayReport_AudioChannel_Mono, &value); + break; + case snd::AudioChannelType::Stereo: + increment(PlayReportKey::PlayReport_AudioChannel_Stereo, &value); + break; + case snd::AudioChannelType::_5_1ch: + increment(PlayReportKey::PlayReport_AudioChannel_5_1ch, &value); + break; + default: + increment(PlayReportKey::PlayReport_AudioChannel_Other, &value); + break; + } + } + + return true; +} + +#define PRODUCT_REPORTER_S32_GETTER(NAME, PLAY_REPORT_KEY) \ + s32 ProductReporter::NAME() const { \ + s32 out = 0; \ + gdt::Manager::instance()->getS32(mGameDataHandles[PLAY_REPORT_KEY], &out); \ + return out; \ + } + +PRODUCT_REPORTER_S32_GETTER(getPlayTime, PlayReportKey::PlayReport_PlayTime) +PRODUCT_REPORTER_S32_GETTER(getAllPlayTime, PlayReportKey::PlayReport_AllPlayTime) +PRODUCT_REPORTER_S32_GETTER(getCtrlModeFree, PlayReportKey::PlayReport_CtrlMode_Free) +PRODUCT_REPORTER_S32_GETTER(getCtrlModeExt, PlayReportKey::PlayReport_CtrlMode_Ext) +PRODUCT_REPORTER_S32_GETTER(getCtrlModeFullKey, PlayReportKey::PlayReport_CtrlMode_FullKey) +PRODUCT_REPORTER_S32_GETTER(getCtrlModeHandheld, PlayReportKey::PlayReport_CtrlMode_Handheld) +PRODUCT_REPORTER_S32_GETTER(getCtrlModeConsoleFree, PlayReportKey::PlayReport_CtrlMode_Console_Free) +PRODUCT_REPORTER_S32_GETTER(getCtrlModeConsoleExt, PlayReportKey::PlayReport_CtrlMode_Console_Ext) +PRODUCT_REPORTER_S32_GETTER(getCtrlModeConsoleFullKey, + PlayReportKey::PlayReport_CtrlMode_Console_FullKey) +PRODUCT_REPORTER_S32_GETTER(getCtrlModePlayTimeHandheld, + PlayReportKey::PlayReport_PlayTime_Handheld) +PRODUCT_REPORTER_S32_GETTER(getPlayTimeConsole, PlayReportKey::PlayReport_PlayTime_Console) + +#undef PRODUCT_REPORTER_S32_GETTER + +} // namespace ksys \ No newline at end of file diff --git a/src/KingSystem/System/ProductReporter.h b/src/KingSystem/System/ProductReporter.h index a797af8b..3bd27c3a 100644 --- a/src/KingSystem/System/ProductReporter.h +++ b/src/KingSystem/System/ProductReporter.h @@ -1,14 +1,120 @@ #pragma once +#include +#include +#include "KingSystem/GameData/gdtFlagHandle.h" +#include "KingSystem/GameData/gdtManager.h" +#include "KingSystem/Utils/InitTimeInfo.h" + +namespace sead { +class Heap; +} + namespace ksys { -// FIXME: incomplete; requires GameData +class PlayReport; + +SEAD_ENUM(PlayReportKey, PlayReport_PlayTime , PlayReport_AllPlayTime , PlayReport_CtrlMode_Free , PlayReport_CtrlMode_Ext , PlayReport_CtrlMode_FullKey , PlayReport_CtrlMode_Handheld , PlayReport_CtrlMode_Console_Free , PlayReport_CtrlMode_Console_Ext , PlayReport_CtrlMode_Console_FullKey , PlayReport_PlayTime_Handheld , PlayReport_PlayTime_Console , PlayReport_AudioChannel_Mono , PlayReport_AudioChannel_Stereo , PlayReport_AudioChannel_5_1ch , PlayReport_AudioChannel_Other , PosTrackEndPointBlockNumber , PosTrackEndPointRecordIndex , PosTrackEndPointPosIndex) + +struct WorkTimes { + util::InitConstants _0; + u32 rom; + u32 scene; +}; + +// TODO +class PlayerTrackReporter { +public: + PlayerTrackReporter(); + void init(sead::Heap* heap); + void setPosTrackEnd(); + +private: + u8 _0[48]; +}; + class ProductReporter { public: ProductReporter() = default; virtual ~ProductReporter(); + void init(sead::Heap* heap); + void initGameDataIterators(); + void terminate(); + static bool getSomeBool(); + bool isEnabled() const; + + s32 getRomWorkTime() const; + s32 getSceneWorkTime() const; + void resetSceneWorkTime(); + + void updateTimers(); + bool saveReport(PlayReport* playReport) const; + bool incrementSceneAndRomWorkTime(); + + s32 getPlayTime() const; + s32 getAllPlayTime() const; + s32 getCtrlModeFree() const; + s32 getCtrlModeExt() const; + s32 getCtrlModeFullKey() const; + s32 getCtrlModeHandheld() const; + s32 getCtrlModeConsoleFree() const; + s32 getCtrlModeConsoleExt() const; + s32 getCtrlModeConsoleFullKey() const; + s32 getCtrlModePlayTimeHandheld() const; + s32 getPlayTimeConsole() const; + + void getFlag(u32 key, s32* value) { + gdt::Manager::instance()->getS32(mGameDataHandles[key], value); + } + + void setFlag(u32 key, s32 value) { + gdt::Manager::instance()->setS32(value, mGameDataHandles[key]); + } + + void increment(u32 key, s32* value) { + getFlag(key, value); + setFlag(key, *value + 1); + } + + class Container { + public: + void init(sead::Heap* heap, u64 capacity, u64 itemSize) { + auto* dataPointer = new (heap, 8, std::nothrow) u8[capacity * itemSize]; + if (dataPointer != nullptr) { + mBuffer = dataPointer; + mBufferLength = 0; + mBufferCapacity = capacity; + } + } + + private: + void* mBuffer; + u64 mBufferCapacity; + u32 mBufferLength; + }; + +private: + u8 _0[8]; + + Container mContainer1; + Container mContainer2; + Container mContainer3; + Container mContainer4; + + f32 mNinetyTickTimer; + f32 mIncrementWorkTimesTimer; + f32 mCameraIdleTimer; + + sead::Vector3f mPos; + sead::Heap* mHeap; + bool mIsInitalized; + bool mEnabled; + u32 mCtrlMode; // TODO: very likely an enum member + PlayerTrackReporter* mPlayerTrackReporter; + gdt::FlagHandle mGameDataHandles[PlayReportKey::size()]; + gdt::Manager::ReinitSignal::Slot mSlot; }; } // namespace ksys diff --git a/src/KingSystem/System/VFR.h b/src/KingSystem/System/VFR.h index 2bdf581e..945072ce 100644 --- a/src/KingSystem/System/VFR.h +++ b/src/KingSystem/System/VFR.h @@ -72,6 +72,9 @@ public: f32 getDeltaTime(u32 core) const { return *mDeltaFrames[core]; } f32 getDeltaTime() const { return getDeltaTime(sead::CoreInfo::getCurrentCoreId()); } + f32 getIntervalRatio(u32 core) const { return *mIntervalRatios[core]; } + f32 getIntervalRatio() const { return getIntervalRatio(sead::CoreInfo::getCurrentCoreId()); } + template static inline void add(T* value, const T& v) { *value += v * instance()->getDeltaTime();