mirror of https://github.com/zeldaret/botw.git
ksys: Start adding VFR
This commit is contained in:
parent
0bb9f8ffde
commit
a3892c0f59
|
@ -91875,28 +91875,28 @@
|
||||||
0x00000071011c0b30,TimerSimple::update,128,
|
0x00000071011c0b30,TimerSimple::update,128,
|
||||||
0x00000071011c0bb0,Timer::update,136,
|
0x00000071011c0bb0,Timer::update,136,
|
||||||
0x00000071011c0c38,Timer::ended,48,
|
0x00000071011c0c38,Timer::ended,48,
|
||||||
0x00000071011c0c68,sub_71011C0C68,100,
|
0x00000071011c0c68,sub_71011C0C68,100,_ZN4ksys3VFR18SingletonDisposer_D2Ev
|
||||||
0x00000071011c0ccc,sub_71011C0CCC,108,
|
0x00000071011c0ccc,sub_71011C0CCC,108,_ZN4ksys3VFR18SingletonDisposer_D0Ev
|
||||||
0x00000071011c0d38,VFR::createInstance,332,
|
0x00000071011c0d38,VFR::createInstance,332,_ZN4ksys3VFR14createInstanceEPN4sead4HeapE
|
||||||
0x00000071011c0e84,sub_71011C0E84,68,
|
0x00000071011c0e84,sub_71011C0E84,68,_ZN4ksys3VFRD1Ev
|
||||||
0x00000071011c0ec8,sub_71011C0EC8,64,
|
0x00000071011c0ec8,sub_71011C0EC8,64,_ZN4ksys3VFRD0Ev
|
||||||
0x00000071011c0f08,VFR::init,468,
|
0x00000071011c0f08,VFR::init,468,_ZN4ksys3VFR4initEjiPN4sead4HeapEj
|
||||||
0x00000071011c10dc,VFR::__auto1,24,
|
0x00000071011c10dc,VFR::__auto1,24,_ZN4ksys3VFR19setIntervalOverrideEj
|
||||||
0x00000071011c10f4,VFR::clearField29,8,
|
0x00000071011c10f4,VFR::clearField29,8,_ZN4ksys3VFR21clearIntervalOverrideEv
|
||||||
0x00000071011c10fc,sub_71011C10FC,544,
|
0x00000071011c10fc,sub_71011C10FC,544,_ZN4ksys3VFR14updateIntervalEj
|
||||||
0x00000071011c131c,VFR::x_0,132,
|
0x00000071011c131c,VFR::x_0,132,_ZN4ksys3VFR10useBufferBEv
|
||||||
0x00000071011c13a0,sub_71011C13A0,132,
|
0x00000071011c13a0,sub_71011C13A0,132,_ZN4ksys3VFR10useBufferAEv
|
||||||
0x00000071011c1424,sub_71011C1424,328,
|
0x00000071011c1424,sub_71011C1424,328,_ZN4ksys3VFR27setDeltaFromTimeMultipliersEPfjj
|
||||||
0x00000071011c156c,VFR::initBeforeStageGenB,316,
|
0x00000071011c156c,VFR::initBeforeStageGenB,316,_ZN4ksys3VFR20resetTimeMultipliersEv
|
||||||
0x00000071011c16a8,VFR::isSlowTime,68,
|
0x00000071011c16a8,VFR::isSlowTime,68,_ZNK4ksys3VFR23hasCustomTimeMultiplierEv
|
||||||
0x00000071011c16ec,VFR::setSlowTime,136,
|
0x00000071011c16ec,VFR::setSlowTime,136,
|
||||||
0x00000071011c1774,VFR::endSlowTime,120,
|
0x00000071011c1774,VFR::endSlowTime,120,
|
||||||
0x00000071011c17ec,sub_71011C17EC,12,
|
0x00000071011c17ec,sub_71011C17EC,12,
|
||||||
0x00000071011c17f8,sub_71011C17F8,184,
|
0x00000071011c17f8,sub_71011C17F8,184,
|
||||||
0x00000071011c18b0,sub_71011C18B0,176,
|
0x00000071011c18b0,sub_71011C18B0,176,
|
||||||
0x00000071011c1960,sub_71011C1960,200,
|
0x00000071011c1960,sub_71011C1960,200,
|
||||||
0x00000071011c1a28,VFR::isField29Set,8,
|
0x00000071011c1a28,VFR::isField29Set,8,_ZNK4ksys3VFR19hasIntervalOverrideEv
|
||||||
0x00000071011c1a30,VFR::x,8,
|
0x00000071011c1a30,VFR::x,8,_ZNK4ksys3VFR19getIntervalOverrideEv
|
||||||
0x00000071011c1a38,sub_71011C1A38,44,
|
0x00000071011c1a38,sub_71011C1A38,44,
|
||||||
0x00000071011c1a64,sub_71011C1A64,12,
|
0x00000071011c1a64,sub_71011C1A64,12,
|
||||||
0x00000071011c1a70,sub_71011C1A70,28,
|
0x00000071011c1a70,sub_71011C1A70,28,
|
||||||
|
|
Can't render this file because it is too large.
|
2
lib/sead
2
lib/sead
|
@ -1 +1 @@
|
||||||
Subproject commit ed983cc42dee614eb4fbc8d71303acec1c7b2c84
|
Subproject commit bb92e59f569bf8e865a9710b03015352c137cc29
|
|
@ -17,4 +17,6 @@ target_sources(uking PRIVATE
|
||||||
SystemPauseMgr.h
|
SystemPauseMgr.h
|
||||||
Timer.cpp
|
Timer.cpp
|
||||||
Timer.h
|
Timer.h
|
||||||
|
VFR.cpp
|
||||||
|
VFR.h
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
#include "KingSystem/System/VFR.h"
|
||||||
|
#include <mc/seadCoreInfo.h>
|
||||||
|
|
||||||
|
namespace ksys {
|
||||||
|
|
||||||
|
SEAD_SINGLETON_DISPOSER_IMPL(VFR)
|
||||||
|
|
||||||
|
VFR::VFR() {
|
||||||
|
for (int i = 0; i < NumCores; ++i) {
|
||||||
|
mPtrs1[i] = &mFloats1a[i];
|
||||||
|
mDeltaTimes[i] = &mFloats2a[i];
|
||||||
|
mPtrs3[i] = &mFloats3a[i];
|
||||||
|
mDeltaFrames[i] = &mFloats4a[i];
|
||||||
|
mIntervals[i] = &mIntervalA;
|
||||||
|
mIntervalRatios[i] = &mIntervalRatioA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VFR::~VFR() {
|
||||||
|
mTimeSpeedMultipliers.freeBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFR::setDelta(u32 core, f32 delta) {
|
||||||
|
delta = sead::Mathf::max(delta, 0.01f);
|
||||||
|
*mPtrs1[core] = delta;
|
||||||
|
*mDeltaTimes[core] = delta * *mIntervalRatios[core];
|
||||||
|
*mPtrs3[core] = delta * mFrameTime;
|
||||||
|
*mDeltaFrames[core] = *mDeltaTimes[core] * mFrameTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFR::setDeltaFromTimeMultipliers(u32 core, const sead::BitFlag32& mask) {
|
||||||
|
f32 min = 1.0;
|
||||||
|
for (s32 i = 0; i < mTimeSpeedMultipliers.size(); ++i) {
|
||||||
|
if (mask.isOnBit(i))
|
||||||
|
min = sead::Mathf::min(min, mTimeSpeedMultipliers[i].value);
|
||||||
|
}
|
||||||
|
setDelta(core, min);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFR::resetTimeMultipliers() {
|
||||||
|
for (auto& entry : mTimeSpeedMultipliers) {
|
||||||
|
entry.value = 1.0;
|
||||||
|
entry.target_value = 1.0;
|
||||||
|
entry.is_custom = false;
|
||||||
|
}
|
||||||
|
x_1();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFR::x_1() {
|
||||||
|
setDeltaFromTimeMultipliers(0, mMask);
|
||||||
|
|
||||||
|
for (s32 i = 0; i < NumCores; ++i) {
|
||||||
|
mFloats2a[i] = mFloats2a[0];
|
||||||
|
mFloats3a[i] = mFloats3a[0];
|
||||||
|
mFloats4a[i] = mFloats4a[0];
|
||||||
|
mFloats1a[i] = mFloats1a[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFR::copyAtoB() {
|
||||||
|
for (s32 i = 0; i < NumCores; ++i) {
|
||||||
|
mFloats1b[i] = mFloats1a[i];
|
||||||
|
mFloats2b[i] = mFloats2a[i];
|
||||||
|
mFloats3b[i] = mFloats3a[i];
|
||||||
|
mFloats4b[i] = mFloats4a[i];
|
||||||
|
mIntervalB = mIntervalA;
|
||||||
|
mIntervalRatioB = mIntervalRatioA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFR::init(u32 interval, int num_speed_multipliers, sead::Heap* heap, u32 mask) {
|
||||||
|
mInterval = interval;
|
||||||
|
mFrameRate = 60 / interval;
|
||||||
|
mIntervalA = interval;
|
||||||
|
mIntervalB = interval;
|
||||||
|
mFrameTime = 1.0f / mFrameRate;
|
||||||
|
mTimeSpeedMultipliers.allocBufferAssert(num_speed_multipliers, heap);
|
||||||
|
mMask = mask;
|
||||||
|
x_1();
|
||||||
|
copyAtoB();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFR::setIntervalOverride(u32 interval) {
|
||||||
|
if (!mHasIntervalOverride) {
|
||||||
|
mHasIntervalOverride = true;
|
||||||
|
mIntervalOverride = interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFR::clearIntervalOverride() {
|
||||||
|
mHasIntervalOverride = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VFR::hasIntervalOverride() const {
|
||||||
|
return mHasIntervalOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 VFR::getIntervalOverride() const {
|
||||||
|
return mIntervalOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
VFR::TimeSpeedMultiplier::TimeSpeedMultiplier() = default;
|
||||||
|
|
||||||
|
VFR::TimeSpeedMultiplier::~TimeSpeedMultiplier() = default;
|
||||||
|
|
||||||
|
void VFR::TimeSpeedMultiplier::update(f32 multiplier) {
|
||||||
|
if (target_value == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
is_custom = target_value != 1.0;
|
||||||
|
if (target_value < value) {
|
||||||
|
value = target_value;
|
||||||
|
} else {
|
||||||
|
sead::Mathf::chase(&value, target_value, sead::Mathf::max(value * multiplier, 0.01));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFR::updateInterval(u32 new_interval) {
|
||||||
|
copyAtoB();
|
||||||
|
|
||||||
|
if (mHasIntervalOverride)
|
||||||
|
new_interval = mIntervalOverride;
|
||||||
|
|
||||||
|
if (new_interval != 0 && mIntervalA != new_interval) {
|
||||||
|
mIntervalA = new_interval;
|
||||||
|
mHasIntervalChanged = true;
|
||||||
|
mNewIntervalRatio = f32(new_interval) * (1.0f / mInterval);
|
||||||
|
} else {
|
||||||
|
mHasIntervalChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mNewIntervalRatio != mIntervalRatioA)
|
||||||
|
mIntervalRatioA = mNewIntervalRatio;
|
||||||
|
|
||||||
|
for (s32 i = 0; i < mTimeSpeedMultipliers.size(); ++i) {
|
||||||
|
mTimeSpeedMultipliers[i].update(mIntervalRatioA);
|
||||||
|
}
|
||||||
|
|
||||||
|
x_1();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFR::useBufferB() {
|
||||||
|
const u32 core = sead::CoreInfo::getCurrentCoreId();
|
||||||
|
mPtrs1[core] = &mFloats1b[core];
|
||||||
|
mDeltaTimes[core] = &mFloats2b[core];
|
||||||
|
mPtrs3[core] = &mFloats3b[core];
|
||||||
|
mDeltaFrames[core] = &mFloats4b[core];
|
||||||
|
mIntervals[core] = &mIntervalB;
|
||||||
|
mIntervalRatios[core] = &mIntervalRatioB;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFR::useBufferA() {
|
||||||
|
const u32 core = sead::CoreInfo::getCurrentCoreId();
|
||||||
|
mPtrs1[core] = &mFloats1a[core];
|
||||||
|
mDeltaTimes[core] = &mFloats2a[core];
|
||||||
|
mPtrs3[core] = &mFloats3a[core];
|
||||||
|
mDeltaFrames[core] = &mFloats4a[core];
|
||||||
|
mIntervals[core] = &mIntervalA;
|
||||||
|
mIntervalRatios[core] = &mIntervalRatioA;
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 VFR::setDeltaFromTimeMultipliers(f32* value, u32 include_mask, u32 exclude_mask) {
|
||||||
|
const u32 core = sead::CoreInfo::getCurrentCoreId();
|
||||||
|
*value = *mPtrs1[core];
|
||||||
|
const f32 delta = *mDeltaTimes[core];
|
||||||
|
setDeltaFromTimeMultipliers(core, (mMask.getDirect() | include_mask) & ~exclude_mask);
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VFR::hasCustomTimeMultiplier() const {
|
||||||
|
for (const auto& entry : mTimeSpeedMultipliers) {
|
||||||
|
if (entry.value != 1.0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ksys
|
|
@ -0,0 +1,106 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <basis/seadTypes.h>
|
||||||
|
#include <container/seadBuffer.h>
|
||||||
|
#include <container/seadSafeArray.h>
|
||||||
|
#include <heap/seadDisposer.h>
|
||||||
|
#include <prim/seadBitFlag.h>
|
||||||
|
#include "KingSystem/Utils/Types.h"
|
||||||
|
|
||||||
|
namespace ksys {
|
||||||
|
|
||||||
|
class VFR {
|
||||||
|
SEAD_SINGLETON_DISPOSER(VFR)
|
||||||
|
VFR();
|
||||||
|
virtual ~VFR();
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct TimeSpeedMultiplier {
|
||||||
|
TimeSpeedMultiplier();
|
||||||
|
~TimeSpeedMultiplier();
|
||||||
|
TimeSpeedMultiplier(const TimeSpeedMultiplier&) = default;
|
||||||
|
TimeSpeedMultiplier(TimeSpeedMultiplier&&) = default;
|
||||||
|
TimeSpeedMultiplier& operator=(const TimeSpeedMultiplier&) = default;
|
||||||
|
TimeSpeedMultiplier& operator=(TimeSpeedMultiplier&&) = default;
|
||||||
|
|
||||||
|
void update(f32 multiplier);
|
||||||
|
|
||||||
|
bool is_custom = false;
|
||||||
|
f32 value = 1.0;
|
||||||
|
f32 target_value = 1.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void init(u32 interval, int num_speed_multipliers, sead::Heap* heap, u32 mask);
|
||||||
|
|
||||||
|
void setIntervalOverride(u32 interval);
|
||||||
|
void clearIntervalOverride();
|
||||||
|
bool hasIntervalOverride() const;
|
||||||
|
u32 getIntervalOverride() const;
|
||||||
|
|
||||||
|
void updateInterval(u32 new_interval);
|
||||||
|
|
||||||
|
void useBufferB();
|
||||||
|
void useBufferA();
|
||||||
|
|
||||||
|
f32 setDeltaFromTimeMultipliers(f32* value, u32 include_mask, u32 exclude_mask);
|
||||||
|
void resetTimeMultipliers();
|
||||||
|
bool hasCustomTimeMultiplier() const;
|
||||||
|
// TODO: requires ksys::Sound
|
||||||
|
void setTimeMultiplier(u32 idx, f32 multiplier);
|
||||||
|
// TODO: requires ksys::Sound
|
||||||
|
void resetTimeMultiplier(u32 idx);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct TimeSpeedMultipliers : sead::Buffer<TimeSpeedMultiplier> {
|
||||||
|
TimeSpeedMultipliers() {
|
||||||
|
mBuffer = nullptr;
|
||||||
|
mSize = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void setDelta(u32 core, f32 delta);
|
||||||
|
void setDeltaFromTimeMultipliers(u32 core, const sead::BitFlag32& mask);
|
||||||
|
void x_1();
|
||||||
|
void copyAtoB();
|
||||||
|
|
||||||
|
bool mHasIntervalChanged = false;
|
||||||
|
bool mHasIntervalOverride = false;
|
||||||
|
u32 mIntervalOverride = 1;
|
||||||
|
f32 mNewIntervalRatio = 1.0;
|
||||||
|
u32 mIntervalA = 1;
|
||||||
|
u32 mIntervalB = 1;
|
||||||
|
f32 mIntervalRatioA = 1.0;
|
||||||
|
f32 mIntervalRatioB = 1.0;
|
||||||
|
|
||||||
|
static constexpr int NumCores = 3;
|
||||||
|
|
||||||
|
sead::SafeArray<u32*, NumCores> mIntervals;
|
||||||
|
sead::SafeArray<f32*, NumCores> mIntervalRatios;
|
||||||
|
|
||||||
|
TimeSpeedMultipliers mTimeSpeedMultipliers;
|
||||||
|
sead::BitFlag32 mMask = 0xffffffff;
|
||||||
|
|
||||||
|
sead::SafeArray<f32, NumCores> mFloats1a{};
|
||||||
|
sead::SafeArray<f32, NumCores> mFloats2a{};
|
||||||
|
sead::SafeArray<f32, NumCores> mFloats3a{};
|
||||||
|
sead::SafeArray<f32, NumCores> mFloats4a{};
|
||||||
|
|
||||||
|
sead::SafeArray<f32, NumCores> mFloats1b{};
|
||||||
|
sead::SafeArray<f32, NumCores> mFloats2b{};
|
||||||
|
sead::SafeArray<f32, NumCores> mFloats3b{};
|
||||||
|
sead::SafeArray<f32, NumCores> mFloats4b{};
|
||||||
|
|
||||||
|
sead::SafeArray<f32*, NumCores> mPtrs1;
|
||||||
|
sead::SafeArray<f32*, NumCores> mDeltaTimes;
|
||||||
|
sead::SafeArray<f32*, NumCores> mPtrs3;
|
||||||
|
sead::SafeArray<f32*, NumCores> mDeltaFrames;
|
||||||
|
/// Present interval.
|
||||||
|
u32 mInterval = 1;
|
||||||
|
/// Frames per second.
|
||||||
|
u32 mFrameRate = 60;
|
||||||
|
/// Second per frame.
|
||||||
|
f32 mFrameTime = 1.0 / 60.0;
|
||||||
|
};
|
||||||
|
KSYS_CHECK_SIZE_NX150(VFR, 0x160);
|
||||||
|
|
||||||
|
} // namespace ksys
|
Loading…
Reference in New Issue