Compare commits

..

1 Commits

Author SHA1 Message Date
madeline 99ea28e9f7 maybe fix ook crash 2026-05-20 14:33:48 -07:00
49 changed files with 150 additions and 405 deletions
+1
View File
@@ -1,6 +1,7 @@
# IDE folders
.idea/
.vs/
.zed/
# Caches
__pycache__
+10 -10
View File
@@ -4,10 +4,10 @@
- A Windows, Linux, or macOS device
- iOS device connected to computer via USB
- Dusklight IPA file (download the latest `Dusklight-vX.X.X-ios-arm64.ipa` from the [releases page](https://github.com/TwilitRealm/dusklight/releases))
- Legally acquired game disc - `GZ2E01` (Gamecube USA) or `GZ2PE01` (Gamecube PAL)
- Dusklight IPA file (download the latest `Dusklight-vX.X.X-ios-arm64.ipa` from the [releases page](https://github.com/TwilitRealm/dusk/releases))
- Game disc - `GZ2E01` (Gamecube USA) or `GZ2PE01` (Gamecube PAL)
## 1. Install iloader
## 1. Install AltServer
- Executable bundles can be installed from [iloader's main page](https://iloader.app/) or [their GitHub](https://github.com/nab138/iloader) for Windows, Linux, and macOS.
- Windows WILL require iTunes to be installed
@@ -16,21 +16,21 @@
## 2. Enable Developer Mode (iOS 16+)
- On your iPhone, go to **Settings > Privacy & Security > Developer Mode**
- Toggle it on, put in your device passcode, and restart when prompted
- Toggle it on and restart when prompted
## 3. Install Dusklight on Your iPhone
1. Sign into your Apple ID (this is required for registering app IDs, it is sent securely directly to Apple and not stored by iloader)
* You may be prompted to put in a code from your iOS device if you have 2FA enabled, do so
1. Sign into your Apple ID (this is required for registering app IDs, it is sent securely and not stored by iloader)
* You may be prompted to put in a code from your iOS device, do so
2. Plug in your iOS device via USB into your PC. If you're missing a dependency, an error pop-up will tell you to install it
* You will need to hit `Refresh` after plugging it in at this stage so that it can be detected, it does not automatically refresh
3. Leave settings unchanged (the Anisette server should stay Sidestore (.io))
3.(a) Installing SideStore directly is not required, but provides you a way to install Dusklight on your phone without being plugged into a computer later
4. Press `Import IPA` and choose your downloaded `Dusklight-v.X.X.X-ios-arm64.ipa`, it will begin installing on your device
4. Press `Import IPA` and choose your downloaded `Dusk-v.X.X.X-ios-arm64.ipa`, it will begin installing on your device
**NOTE:** *At various stages, you may be prompted to trust your device, do so*
## 3. Getting Dusklight trusted
## 3. Getting Dusk trusted
When installing sideloaded iOS applications, at first you will need to manually trust the app due to Apple's security policies
* Go to **Settings > General > VPN & Device Management**
* Tap the Apple ID you signed into iloader with under "Developer App" and tap **Trust**
@@ -38,11 +38,11 @@ When installing sideloaded iOS applications, at first you will need to manually
## 4. Copy Files to Your iPhone
Transfer the game disc (and optionally, the Dusklight IPA) to your iPhone so they are accessible in the Files app. A few ways to do this:
Transfer the IPA and game disc to your iPhone so they're accessible in the Files app. A few ways to do this:
- **AirDrop** - Right-click the files on your Mac and choose Share > AirDrop
- **iCloud Drive** - Place files in iCloud Drive on your Mac and they'll sync to Files on your iPhone
- **USB transfer** - Connect your iPhone and drag files via Finder's sidebar
- **Cloud storage** - Upload to Google Drive, Dropbox, etc. and download on your iPhone
You may now use Dusklight on iOS and iPadOS!
You may now use Dusklight on iOS, iPadOS!
+1 -1
-22
View File
@@ -227,28 +227,6 @@ struct BE<Mtx> {
}
};
typedef f32 Mtx23[2][3];
template <>
struct BE<Mtx23> {
BE<f32> contents[2][3];
auto& operator[](int x) {
return contents[x];
}
auto& operator[](int x) const {
return contents[x];
}
void to_host(Mtx23& mtx) const {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
mtx[i][j] = contents[i][j];
}
}
}
};
template<typename T>
void be_swap(T& val) {
val = BE<T>::swap(val);
+1 -2
View File
@@ -4,7 +4,6 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "settings.h"
class camera_process_class;
class view_class;
@@ -19,7 +18,7 @@ void begin_record();
void end_record();
void begin_sim_tick();
uint64_t sim_tick_seq();
void begin_frame(FrameInterpMode mode, bool is_sim_frame, float step);
void begin_frame(bool enabled, bool is_sim_frame, float step);
void interpolate();
float get_interpolation_step();
+6 -27
View File
@@ -15,11 +15,6 @@ enum class BloomMode : int {
Dusk = 2,
};
enum class Resampler : int {
Bilinear = 0,
Area = 1,
};
enum class GameLanguage : u8 {
English = OS_LANGUAGE_ENGLISH,
German = OS_LANGUAGE_GERMAN,
@@ -39,12 +34,6 @@ enum class GyroMode : u8 {
Mouse = 1,
};
enum class FrameInterpMode : u8 {
Off = 0,
Capped = 1,
Unlimited = 2,
};
namespace config {
template <>
struct ConfigEnumRange<BloomMode> {
@@ -52,12 +41,6 @@ struct ConfigEnumRange<BloomMode> {
static constexpr auto max = BloomMode::Dusk;
};
template <>
struct ConfigEnumRange<Resampler> {
static constexpr auto min = Resampler::Bilinear;
static constexpr auto max = Resampler::Area;
};
template <>
struct ConfigEnumRange<GameLanguage> {
static constexpr auto min = GameLanguage::English;
@@ -75,13 +58,7 @@ struct ConfigEnumRange<GyroMode> {
static constexpr auto min = GyroMode::Sensor;
static constexpr auto max = GyroMode::Mouse;
};
template <>
struct ConfigEnumRange<FrameInterpMode> {
static constexpr auto min = FrameInterpMode::Off;
static constexpr auto max = FrameInterpMode::Unlimited;
};
} // namespace config
}
// Persistent user settings
@@ -95,7 +72,10 @@ struct UserSettings {
ConfigVar<bool> lockAspectRatio;
ConfigVar<bool> enableFpsOverlay;
ConfigVar<int> fpsOverlayCorner;
ConfigVar<int> maxFrameRate;
ConfigVar<int> windowPositionX;
ConfigVar<int> windowPositionY;
ConfigVar<int> windowWidth;
ConfigVar<int> windowHeight;
} video;
struct {
@@ -148,10 +128,9 @@ struct UserSettings {
ConfigVar<float> bloomMultiplier;
ConfigVar<bool> disableWaterRefraction;
ConfigVar<bool> enableTextureReplacements;
ConfigVar<FrameInterpMode> enableFrameInterpolation;
ConfigVar<bool> enableFrameInterpolation;
ConfigVar<int> internalResolutionScale;
ConfigVar<int> shadowResolutionMultiplier;
ConfigVar<Resampler> resampler;
ConfigVar<bool> enableDepthOfField;
ConfigVar<bool> enableMapBackground;
ConfigVar<bool> disableCutscenePillarboxing;
+4 -40
View File
@@ -17,24 +17,16 @@
#include <shellapi.h>
#include <intrin.h>
#endif
#ifdef __APPLE__
#include <mach/mach_time.h>
#if defined(__x86_64__) || defined(__i386__)
#include <immintrin.h>
#endif
#endif
class Limiter {
public:
using duration_t = Uint64;
void Reset() {
m_oldTime = SDL_GetTicksNS();
}
void Reset() { m_oldTime = SDL_GetTicksNS(); }
duration_t Sleep(duration_t targetFrameTime) {
void Sleep(duration_t targetFrameTime) {
if (targetFrameTime == 0) {
return 0;
return;
}
const Uint64 start = SDL_GetTicksNS();
@@ -49,8 +41,6 @@ public:
}
}
Reset();
return adjustedSleepTime;
}
duration_t SleepTime(duration_t targetFrameTime) {
@@ -84,6 +74,7 @@ private:
if (!initialized || numSleeps++ % 1000 == 0) {
LARGE_INTEGER freq;
if (QueryPerformanceFrequency(&freq) == 0) {
DuskLog.warn("QueryPerformanceFrequency failed: {}", GetLastError());
return;
}
countPerNs = static_cast<double>(freq.QuadPart) / 1e9;
@@ -107,33 +98,6 @@ private:
#endif
} while (current.QuadPart - start.QuadPart < ticksToWait);
}
#elif defined (__APPLE__)
void NanoSleep(const duration_t duration) {
// Hybrid approach using Apple Mach
uint64_t start_mach = mach_absolute_time();
mach_timebase_info_data_t timebase_info;
mach_timebase_info(&timebase_info);
uint64_t total_mach_ticks = (duration * timebase_info.denom) / timebase_info.numer;
uint64_t target_mach = start_mach + total_mach_ticks;
uint64_t buffer_ns = 2'000'000ULL;
uint64_t buffer_mach_ticks = (buffer_ns * timebase_info.denom) / timebase_info.numer;
if (total_mach_ticks > buffer_mach_ticks) {
uint64_t sleep_until_mach = target_mach - buffer_mach_ticks;
mach_wait_until(sleep_until_mach);
}
while (mach_absolute_time() < target_mach) {
#if defined(__aarch64__) || defined(__arm__)
asm volatile("yield" ::: "memory"); // Hardware hint, not a scheduler hint.
#else
_mm_pause();
#endif
}
}
#else
void NanoSleep(const duration_t duration) { SDL_DelayPrecise(duration); }
#endif
@@ -116,7 +116,7 @@ private:
*
*/
struct J2DIndTexMtxInfo {
/* 0x00 */ BE(Mtx23) mMtx;
/* 0x00 */ Mtx23 mMtx;
/* 0x18 */ s8 mScaleExp;
J2DIndTexMtxInfo& operator=(const J2DIndTexMtxInfo& other) {
@@ -287,28 +287,28 @@ template <typename T>
class JASPoolAllocObject {
public:
#if TARGET_PC
static void* operator new(size_t n, JKRHeapToken) IF_DUSK(noexcept) {
static void* operator new(size_t n, JKRHeapToken) {
return operator new(n);
}
#endif
static void* operator new(size_t n) IF_DUSK(noexcept) {
static void* operator new(size_t n) {
#if PLATFORM_GCN
JASMemPool<T>& memPool_ = getMemPool_();
#endif
return memPool_.alloc(n);
}
static void* operator new(size_t n, void* ptr) IF_DUSK(noexcept) {
static void* operator new(size_t n, void* ptr) {
return ptr;
}
#if TARGET_PC
static void operator delete(void* ptr, size_t n, JKRHeapToken) IF_DUSK(noexcept) {
static void operator delete(void* ptr, size_t n, JKRHeapToken) {
operator delete(ptr, n);
}
#endif
static void operator delete(void* ptr, size_t n) IF_DUSK(noexcept) {
static void operator delete(void* ptr, size_t n) {
#if PLATFORM_GCN
JASMemPool<T>& memPool_ = getMemPool_();
#endif
@@ -402,28 +402,28 @@ template <typename T>
class JASPoolAllocObject_MultiThreaded {
public:
#if TARGET_PC
static void* operator new(size_t n, JKRHeapToken) IF_DUSK(noexcept) {
static void* operator new(size_t n, JKRHeapToken) {
return operator new(n);
}
#endif
static void* operator new(size_t n) IF_DUSK(noexcept) {
static void* operator new(size_t n) {
#if PLATFORM_GCN
JASMemPool_MultiThreaded<T>& memPool_ = getMemPool();
#endif
return memPool_.alloc(n);
}
static void* operator new(size_t n, void* ptr) IF_DUSK(noexcept) {
static void* operator new(size_t n, void* ptr) {
return ptr;
}
#if TARGET_PC
static void operator delete(void* ptr, size_t n, JKRHeapToken) IF_DUSK(noexcept) {
static void operator delete(void* ptr, size_t n, JKRHeapToken) {
return operator delete(ptr, n);
}
#endif
static void operator delete(void* ptr, size_t n) IF_DUSK(noexcept) {
static void operator delete(void* ptr, size_t n) {
#if PLATFORM_GCN
JASMemPool_MultiThreaded<T>& memPool_ = getMemPool();
#endif
+15 -19
View File
@@ -237,11 +237,11 @@ enum class JKRHeapToken {
Dummy
};
inline void* operator new(size_t, JKRHeapToken, void* where) noexcept {
inline void* operator new(size_t, JKRHeapToken, void* where) {
return where;
}
inline void* operator new[](size_t, JKRHeapToken, void* where) noexcept {
inline void* operator new[](size_t, JKRHeapToken, void* where) {
return where;
}
@@ -264,21 +264,21 @@ inline void* operator new[](size_t, JKRHeapToken, void* where) noexcept {
#define JKR_HEAP_TOKEN_PARAM
#endif
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM) IF_DUSK(noexcept);
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, int alignment) IF_DUSK(noexcept);
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment) IF_DUSK(noexcept);
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM);
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, int alignment);
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment);
// On PC, these new[] overloads are only used to catch usages of JKR_NEW with [].
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM) IF_DUSK(noexcept);
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM, int alignment) IF_DUSK(noexcept);
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment) IF_DUSK(noexcept);
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM);
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM, int alignment);
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment);
void operator delete(void* ptr JKR_HEAP_TOKEN_PARAM) IF_DUSK(noexcept);
void operator delete[](void* ptr JKR_HEAP_TOKEN_PARAM) IF_DUSK(noexcept);
void operator delete(void* ptr JKR_HEAP_TOKEN_PARAM);
void operator delete[](void* ptr JKR_HEAP_TOKEN_PARAM);
#if TARGET_PC
template<typename T>
void jkrDelete(T* ptr) IF_DUSK(noexcept) {
void jkrDelete(T* ptr) {
if (ptr == nullptr) {
return;
}
@@ -298,7 +298,7 @@ void jkrDelete(T* ptr) IF_DUSK(noexcept) {
}
template<>
inline void jkrDelete(void* ptr) IF_DUSK(noexcept) {
inline void jkrDelete(void* ptr) {
if (ptr == nullptr) {
return;
}
@@ -322,7 +322,7 @@ constexpr bool newArgsHasCustomAlignment() {
}
template<typename T, typename... Args>
T* jkrNewArray(size_t count, std::in_place_type_t<T>, Args&&... args) IF_DUSK(noexcept) {
T* jkrNewArray(size_t count, std::in_place_type_t<T>, Args&&... args) {
size_t allocSize = count * sizeof(T);
if constexpr (!std::is_trivially_destructible<T>()) {
static_assert(
@@ -333,10 +333,6 @@ T* jkrNewArray(size_t count, std::in_place_type_t<T>, Args&&... args) IF_DUSK(no
}
void* ptr = operator new(allocSize, JKRHeapToken::Dummy, args...);
if (!ptr) {
return nullptr;
}
T* dataPtr;
if constexpr (!std::is_trivially_destructible<T>()) {
auto length = static_cast<size_t*>(ptr);
@@ -356,7 +352,7 @@ T* jkrNewArray(size_t count, std::in_place_type_t<T>, Args&&... args) IF_DUSK(no
}
template<typename T>
void jkrDeleteArray(T* pointer) IF_DUSK(noexcept) {
void jkrDeleteArray(T* pointer) {
if (pointer == nullptr) {
return;
}
@@ -376,7 +372,7 @@ void jkrDeleteArray(T* pointer) IF_DUSK(noexcept) {
}
template<>
inline void jkrDeleteArray(void* pointer) IF_DUSK(noexcept) {
inline void jkrDeleteArray(void* pointer) {
if (pointer == nullptr) {
return;
}
-6
View File
@@ -68,14 +68,8 @@ void J2DIndTevStage::load(u8 tevStage) {
}
void J2DIndTexMtx::load(u8 indTexMtx) {
#ifdef TARGET_PC
Mtx23 mtx;
mIndTexMtxInfo.mMtx.to_host(mtx);
GXSetIndTexMtx((GXIndTexMtxID)(GX_ITM_0 + indTexMtx), mtx, mIndTexMtxInfo.mScaleExp);
#else
GXSetIndTexMtx((GXIndTexMtxID)(GX_ITM_0 + indTexMtx), mIndTexMtxInfo.mMtx,
mIndTexMtxInfo.mScaleExp);
#endif
}
void J2DIndTexCoordScale::load(u8 indTexStage) {
+7 -7
View File
@@ -370,28 +370,28 @@ constexpr auto FRAME_PERIOD = std::chrono::duration_cast<std::chrono::nanosecond
constexpr auto RETRACE_PERIOD = FRAME_PERIOD / 2;
static void waitPrecise(Limiter& limiter, Limiter::duration_t targetNs) {
const auto sleepTime = limiter.Sleep(targetNs);
const auto sleepTime = limiter.SleepTime(targetNs);
dusk::frameUsagePct =
100.0f * (1.0f - static_cast<float>(sleepTime) / static_cast<float>(targetNs));
limiter.Sleep(targetNs);
}
#endif
static void waitForTick(u32 p1, u16 p2) {
#if TARGET_PC
static Limiter limiter;
if (dusk::frame_interp::is_enabled() && !dusk::getTransientSettings().skipFrameRateLimit) {
dusk::frameUsagePct = 0.f;
return;
if (dusk::getSettings().game.enableFrameInterpolation && !dusk::getTransientSettings().skipFrameRateLimit) {
dusk::frameUsagePct = 0.f;
return;
}
if (dusk::getTransientSettings().skipFrameRateLimit) {
p1 = OS_TIMER_CLOCK / 120;
}
#if TARGET_PC
if (fopOvlpM_IsPeek() && dusk::getTransientSettings().stateShareLoadActive) {
return;
}
#endif
ZoneScopedC(tracy::Color::DimGray);
#endif
+8 -8
View File
@@ -559,7 +559,7 @@ void* operator new(size_t size) {
return JKRHeap::alloc(size, 4, NULL);
}
#else
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM) noexcept {
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM) {
if (sCurrentHeap == NULL) {
return fallback_alloc(size, 0, false);
}
@@ -576,7 +576,7 @@ void* operator new(size_t size, int alignment) {
return JKRHeap::alloc(size, alignment, NULL);
}
#else
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, int alignment) noexcept {
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, int alignment) {
void* mem = JKRHeap::alloc(size, alignment, nullptr);
if (mem == nullptr) {
return fallback_alloc(size, abs(alignment), true);
@@ -585,7 +585,7 @@ void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, int alignment) noexcept {
}
#endif
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment) IF_DUSK(noexcept) {
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment) {
void* mem = JKRHeap::alloc(size, alignment, heap);
#if TARGET_PC
if (mem == nullptr) {
@@ -600,7 +600,7 @@ void* operator new[](size_t size) {
return JKRHeap::alloc(size, 4, NULL);
}
#else
void* operator new[](size_t JKR_HEAP_TOKEN_PARAM) IF_DUSK(noexcept) {
void* operator new[](size_t JKR_HEAP_TOKEN_PARAM) {
OSPanic(__FILE__, __LINE__, "Allocation should go through JKR_NEW_ARRAY instead");
}
#endif
@@ -610,12 +610,12 @@ void* operator new[](size_t size, int alignment) {
return JKRHeap::alloc(size, alignment, NULL);
}
#else
void* operator new[](size_t JKR_HEAP_TOKEN_PARAM, int) IF_DUSK(noexcept) {
void* operator new[](size_t JKR_HEAP_TOKEN_PARAM, int) {
OSPanic(__FILE__, __LINE__, "Allocation should go through JKR_NEW_ARRAY instead");
}
#endif
void* operator new[](size_t JKR_HEAP_TOKEN_PARAM, JKRHeap*, int) IF_DUSK(noexcept) {
void* operator new[](size_t JKR_HEAP_TOKEN_PARAM, JKRHeap*, int) {
OSPanic(__FILE__, __LINE__, "Allocation should go through JKR_NEW_ARRAY instead");
}
@@ -624,7 +624,7 @@ void operator delete(void* ptr) {
JKRHeap::free(ptr, NULL);
}
#else
void operator delete(void* ptr JKR_HEAP_TOKEN_PARAM) IF_DUSK(noexcept) {
void operator delete(void* ptr JKR_HEAP_TOKEN_PARAM) {
if (ptr == NULL)
return;
JKRHeap* heap = JKRHeap::findFromRoot(ptr);
@@ -645,7 +645,7 @@ void operator delete[](void* ptr) {
JKRHeap::free(ptr, NULL);
}
#else
void operator delete[](void* ptr JKR_HEAP_TOKEN_PARAM) IF_DUSK(noexcept) {
void operator delete[](void* ptr JKR_HEAP_TOKEN_PARAM) {
if (ptr == NULL)
return;
JKRHeap* heap = JKRHeap::findFromRoot(ptr);
@@ -655,7 +655,7 @@ value_or_fun:
value:
#if TARGET_PC
if (dusk::frame_interp::is_enabled() && u <= 5 &&
if (dusk::getSettings().game.enableFrameInterpolation && u <= 5 &&
(operation == data::UNK_0x2 || operation == data::UNK_0x3 || operation == data::UNK_0x12))
{
dusk::frame_interp::request_presentation_sync();
@@ -666,7 +666,7 @@ value:
value_n:
#if TARGET_PC
if (dusk::frame_interp::is_enabled() &&
if (dusk::getSettings().game.enableFrameInterpolation &&
(pN == TAdaptor_camera::sauVariableValue_3_POSITION_XYZ || pN == TAdaptor_camera::sauVariableValue_3_TARGET_POSITION_XYZ) &&
(operation == data::UNK_0x2 || operation == data::UNK_0x3 || operation == data::UNK_0x12))
{
+2 -2
View File
@@ -5990,7 +5990,7 @@ void daAlink_c::setItemMatrix(int param_0) {
mDoMtx_stack_c::XrotS(-0x8000);
#ifdef TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
Mtx boot_mtx;
mDoMtx_concat(mpLinkModel->getAnmMtx(0x18), mDoMtx_stack_c::get(), boot_mtx);
mpLinkBootModels[1]->setAnmMtx(1, boot_mtx);
@@ -19767,7 +19767,7 @@ int daAlink_c::draw() {
dComIfGd_getOpaListDark()->entryImm(mpHookChain, 0);
#if TARGET_PC
if (dusk::frame_interp::is_enabled() &&
if (dusk::getSettings().game.enableFrameInterpolation &&
mEquipItem == dItemNo_IRONBALL_e &&
mIronBallChainPos != NULL && mIronBallChainAngle != NULL)
{
+1 -1
View File
@@ -397,7 +397,7 @@ static int daB_GND_Draw(b_gnd_class* i_this) {
i_this->field_0x21e8.update(2, l_color, &a_this->tevStr);
dComIfGd_set3DlineMat(&i_this->field_0x21e8);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mReinsInterpCurrValid) {
memcpy(i_this->mReinsInterpPrev, i_this->mReinsInterpCurr, sizeof(i_this->mReinsInterpCurr));
memcpy(i_this->mReinsTexInterpPrev, i_this->mReinsTexInterpCurr, sizeof(i_this->mReinsTexInterpCurr));
-22
View File
@@ -674,29 +674,7 @@ static int daE_ARROW_Create(fopAc_ac_c* i_this) {
}
int phase_state = dComIfG_resLoad(&a_this->mPhase, a_this->mResName);
#if TARGET_PC
static int s_create_frames = 0;
static bool s_first_arrow = true;
static fpc_ProcID s_last_scene_id = 0;
s_create_frames++;
fpc_ProcID cur_scene_id = dStage_roomControl_c::getProcID();
if (cur_scene_id != s_last_scene_id) {
s_first_arrow = true;
s_last_scene_id = cur_scene_id;
}
if (phase_state == cPhs_COMPLEATE_e && s_first_arrow && s_create_frames < 4) {
return cPhs_INIT_e;
}
#endif
if (phase_state == cPhs_COMPLEATE_e) {
#if TARGET_PC
s_create_frames = 0;
s_first_arrow = false;
#endif
a_this->mArrowType = fopAcM_GetParam(a_this) & 0xF;
a_this->mFlags = fopAcM_GetParam(a_this) & 0xF0;
+1 -1
View File
@@ -116,7 +116,7 @@ static int daE_DB_Draw(e_db_class* i_this) {
i_this->stalkLine.update(12, l_color, &actor->tevStr);
dComIfGd_set3DlineMat(&i_this->stalkLine);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mStalkLineInterpCurrValid) {
memcpy(i_this->mStalkLineInterpPrev, i_this->mStalkLineInterpCurr, sizeof(i_this->mStalkLineInterpCurr));
i_this->mStalkLineInterpPrevValid = true;
+1 -1
View File
@@ -103,7 +103,7 @@ static int daE_HB_Draw(e_hb_class* i_this) {
i_this->stalkLine.update(12, l_color, &actor->tevStr);
dComIfGd_set3DlineMat(&i_this->stalkLine);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mStalkLineInterpCurrValid) {
memcpy(i_this->mStalkLineInterpPrev, i_this->mStalkLineInterpCurr, sizeof(i_this->mStalkLineInterpCurr));
i_this->mStalkLineInterpPrevValid = true;
+1 -1
View File
@@ -105,7 +105,7 @@ static int daE_MB_Draw(e_mb_class* i_this) {
i_this->mRopeMat.update(16, l_color, &a_this->tevStr);
dComIfGd_set3DlineMat(&i_this->mRopeMat);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mRopeInterpCurrValid) {
memcpy(i_this->mRopeInterpPrev, i_this->mRopeInterpCurr, sizeof(i_this->mRopeInterpCurr));
i_this->mRopeInterpPrevValid = true;
+1 -8
View File
@@ -117,13 +117,6 @@ static void daE_S1_interp_callback(bool isSimFrame, void* pUserWork) {
dst[i] = p0 + (p1 - p0) * alpha;
}
}
GXColor line_color;
line_color.r = JREG_S(0) + 5;
line_color.g = JREG_S(1) + 10;
line_color.b = JREG_S(2) + 10;
line_color.a = 0xFF;
i_this->mLineMat.update(16, line_color, &i_this->tevStr);
}
#endif
@@ -161,7 +154,7 @@ static int daE_S1_Draw(e_s1_class* i_this) {
dComIfGd_set3DlineMatDark(&i_this->mLineMat);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mHairInterpCurrValid) {
memcpy(i_this->mHairInterpPrev, i_this->mHairInterpCurr, sizeof(i_this->mHairInterpCurr));
i_this->mHairInterpPrevValid = true;
+1 -1
View File
@@ -535,7 +535,7 @@ static int daE_WB_Draw(e_wb_class* i_this) {
i_this->himo_tex.update(2, l_color, &actor->tevStr);
dComIfGd_set3DlineMat(&i_this->himo_tex);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->himo_interp_curr_valid) {
memcpy(i_this->himo_mat_interp_prev, i_this->himo_mat_interp_curr, sizeof(i_this->himo_mat_interp_curr));
memcpy(i_this->himo_tex_interp_prev, i_this->himo_tex_interp_curr, sizeof(i_this->himo_tex_interp_curr));
+1 -1
View File
@@ -107,7 +107,7 @@ static s32 daE_YD_Draw(e_yd_class* i_this) {
i_this->mLineMat.update(12, l_color, &i_this->actor.tevStr);
dComIfGd_set3DlineMat(&i_this->mLineMat);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mLineMatInterpCurrValid) {
memcpy(i_this->mLineMatInterpPrev, i_this->mLineMatInterpCurr, sizeof(i_this->mLineMatInterpCurr));
i_this->mLineMatInterpPrevValid = true;
+1 -9
View File
@@ -139,7 +139,6 @@ static BOOL pl_check(e_yg_class* i_this, f32 i_dist) {
#if TARGET_PC
static void daE_YG_interp_callback(bool isSimFrame, void* pUserWork) {
e_yg_class* i_this = (e_yg_class*)pUserWork;
fopAc_ac_c* actor = (fopAc_ac_c*)&i_this->actor;
if (!i_this->mTentacleInterpPrevValid || !i_this->mTentacleInterpCurrValid) {
return;
}
@@ -153,13 +152,6 @@ static void daE_YG_interp_callback(bool isSimFrame, void* pUserWork) {
dst[i] = p0 + (p1 - p0) * alpha;
}
}
GXColor color;
color.r = JREG_S(0) + 20;
color.g = JREG_S(1) + 20;
color.b = JREG_S(2) + 20;
color.a = 0xFF;
i_this->mLineMat.update(10, color, &actor->tevStr);
}
#endif
@@ -191,7 +183,7 @@ static int daE_YG_Draw(e_yg_class* i_this) {
dComIfGd_set3DlineMatDark(&i_this->mLineMat);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mTentacleInterpCurrValid) {
memcpy(i_this->mTentacleInterpPrev, i_this->mTentacleInterpCurr, sizeof(i_this->mTentacleInterpCurr));
i_this->mTentacleInterpPrevValid = true;
+1 -1
View File
@@ -135,7 +135,7 @@ static int daE_YH_Draw(e_yh_class* i_this) {
i_this->mLine.update(12, l_color, &a_this->tevStr);
dComIfGd_set3DlineMat(&i_this->mLine);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mLineInterpCurrValid) {
memcpy(i_this->mLineInterpPrev, i_this->mLineInterpCurr, sizeof(i_this->mLineInterpCurr));
i_this->mLineInterpPrevValid = true;
+1 -1
View File
@@ -3165,7 +3165,7 @@ void daHorse_c::setReinPosNormalSubstance() {
#if TARGET_PC
void daHorse_c::lerpControlPoints(f32 alpha) {
// FRAME INTERP NOTE: Currently only lerping points for Epona's reins. Need a more global solution.
if (!dusk::frame_interp::is_enabled() || !s_horseReinSimPrevValid || !s_horseReinSimCurrValid) {
if (!dusk::getSettings().game.enableFrameInterpolation || !s_horseReinSimPrevValid || !s_horseReinSimCurrValid) {
return;
}
const int nCurr = s_horseReinSimNumCurr;
+1 -1
View File
@@ -325,7 +325,7 @@ int daObjFchain_c::draw() {
dComIfGd_getOpaListDark()->entryImm(&mShape, 0);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
if (mChainInterpCurrValid) {
memcpy(mChainInterpPrev, mChainInterpCurr, sizeof(mChainInterpCurr));
mChainInterpPrevValid = true;
+1 -1
View File
@@ -493,7 +493,7 @@ int daObjKLift00_c::Draw() {
dComIfGd_setList();
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
if (mChainInterpCurrValid) {
memcpy(mChainInterpPrev, mChainInterpCurr, mNumChains * sizeof(cXyz));
mChainInterpPrevValid = true;
+2 -2
View File
@@ -170,7 +170,7 @@ int daTitle_c::Execute() {
}
#ifdef TARGET_PC
if (!dusk::frame_interp::is_enabled()) {
if (!dusk::getSettings().game.enableFrameInterpolation) {
#endif
dMenu_Collect3D_c::setViewPortOffsetY(0.0f);
#ifdef TARGET_PC
@@ -354,7 +354,7 @@ void daTitle_c::fastLogoDispInit() {
mProcID = 5;
#ifdef TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
dusk::frame_interp::request_presentation_sync();
}
#endif
+2 -2
View File
@@ -10431,7 +10431,7 @@ bool dCamera_c::eventCamera(s32 param_0) {
#endif
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
switch (var_r29) {
case 3:
case 4:
@@ -11322,7 +11322,7 @@ static int camera_execute(camera_process_class* i_this) {
#ifdef TARGET_PC
widezoom_correction(i_this, i_this->mCamera.TrimHeight());
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
dusk::frame_interp::add_interpolation_callback([](bool _, void* pUserWork) {
const auto i_this = static_cast<camera_process_class*>(pUserWork);
const auto camera = &i_this->mCamera;
+2 -2
View File
@@ -991,7 +991,7 @@ void dMenu_DmapBg_c::draw() {
-35.0f + (local_224.x - local_218.x),
-35.0f + (local_224.y - local_218.y));
#if TARGET_PC
if (!dusk::frame_interp::is_enabled()) {
if (!dusk::getSettings().game.enableFrameInterpolation) {
field_0xdda = 0;
}
#else
@@ -2624,7 +2624,7 @@ void dMenu_Dmap_c::zoomIn_proc() {
void dMenu_Dmap_c::zoomOut_init_proc() {
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
mpDrawBg->resetScrollArrowMask();
}
#endif
+1 -1
View File
@@ -1146,7 +1146,7 @@ void dMenu_Fmap_c::zoom_spot_to_region_init() {
field_0x1ec = 1.0f;
#if TARGET_PC
// Frame interp note: field_0x122d used to be set every draw, causing flickering. Do it here instead.
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
mpDraw2DBack->resetScrollArrowMask();
}
#endif
+1 -1
View File
@@ -437,7 +437,7 @@ void dMenu_Fmap2DBack_c::draw() {
if (field_0x122d) {
mpMeterHaihai->drawHaihai(field_0x122d);
#if TARGET_PC
if (!dusk::frame_interp::is_enabled()) {
if (!dusk::getSettings().game.enableFrameInterpolation) {
field_0x122d = 0;
}
#else
-8
View File
@@ -188,14 +188,6 @@ void dMsgScrnTree_c::exec() {
fukiAlpha(1.0f);
}
mpPmP_c->scale(g_MsgObject_HIO_c.mBoxWoodScaleX, g_MsgObject_HIO_c.mBoxWoodScaleY);
#if TARGET_PC
const f32 hudScale = mDoGph_gInf_c::hudAspectScaleUp;
if (hudScale > 1.0f) {
field_0xc4->getPanePtr()->setBasePosition(J2DBasePosition_4);
field_0xc4->getPanePtr()->scale(hudScale, 1.0f);
}
#endif
}
void dMsgScrnTree_c::draw() {
-19
View File
@@ -56,23 +56,6 @@ static T sanitizeEnumValue(const ConfigVar<T>& cVar, T value) {
template<ConfigValue T>
void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) {
if constexpr (std::is_enum_v<T>) {
if (jsonValue.is_boolean()) {
using Underlying = std::underlying_type_t<T>;
const bool b = jsonValue.get<bool>();
Underlying raw;
if constexpr (std::is_same_v<T, dusk::FrameInterpMode>) {
raw = b ? static_cast<Underlying>(2) : static_cast<Underlying>(0);
} else {
raw = b ? static_cast<Underlying>(1) : static_cast<Underlying>(0);
}
cVar.setValue(sanitizeEnumValue(cVar, static_cast<T>(raw)), false);
return;
}
}
cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<T>()), false);
}
@@ -175,8 +158,6 @@ namespace dusk::config {
template class ConfigImpl<dusk::DiscVerificationState>;
template class ConfigImpl<dusk::GameLanguage>;
template class ConfigImpl<dusk::GyroMode>;
template class ConfigImpl<dusk::FrameInterpMode>;
template class ConfigImpl<dusk::Resampler>;
}
void dusk::config::Register(ConfigVarBase& configVar) {
+2 -2
View File
@@ -142,8 +142,8 @@ uint64_t sim_tick_seq() {
return g_sim_tick_seq;
}
void begin_frame(FrameInterpMode mode, bool is_sim_frame, float step) {
g_enabled = mode != FrameInterpMode::Off;
void begin_frame(bool enabled, bool is_sim_frame, float step) {
g_enabled = enabled;
g_is_sim_frame = is_sim_frame;
g_step = std::clamp(step, 0.0f, 1.0f);
}
+1 -3
View File
@@ -4,7 +4,6 @@
#include <chrono>
#include <cmath>
#include <unordered_map>
#include <dusk/frame_interpolation.h>
namespace dusk::game_clock {
@@ -46,8 +45,7 @@ MainLoopPacer advance_main_loop() {
MainLoopPacer out{};
out.presentation_dt_seconds = presentation_dt;
const bool should_interpolate = dusk::getSettings().game.enableFrameInterpolation.getValue() !=
dusk::FrameInterpMode::Off &&
const bool should_interpolate = dusk::getSettings().game.enableFrameInterpolation &&
!dusk::getTransientSettings().skipFrameRateLimit;
out.is_interpolating = should_interpolate;
out.sim_pace = sim_pace();
+1 -1
View File
@@ -713,7 +713,7 @@ namespace dusk {
transformLevel++;
}
}
if (ImGui::SliderInt("Transform Level", &transformLevel, 0, 4)) {
if (ImGui::SliderInt("Transform Level", &transformLevel, 0, 3)) {
u8 newFlags = 0;
for (int i = 0; i < transformLevel; i++) {
newFlags |= (1 << i);
+12 -5
View File
@@ -1,5 +1,8 @@
#include "dusk/settings.h"
#include "dusk/config.hpp"
#include "dusk/dusk.h"
#include <SDL3/SDL_video.h>
namespace dusk {
@@ -10,7 +13,10 @@ UserSettings g_userSettings = {
.lockAspectRatio {"video.lockAspectRatio", false},
.enableFpsOverlay {"game.enableFpsOverlay", false},
.fpsOverlayCorner {"game.fpsOverlayCorner", 0},
.maxFrameRate {"video.maxFrameRate", 240},
.windowPositionX {"video.windowPositionX", SDL_WINDOWPOS_UNDEFINED},
.windowPositionY {"video.windowPositionY", SDL_WINDOWPOS_UNDEFINED},
.windowWidth {"video.windowWidth", defaultWindowWidth * 2},
.windowHeight {"video.windowHeight", defaultWindowHeight * 2},
},
.audio = {
@@ -60,10 +66,9 @@ UserSettings g_userSettings = {
.bloomMultiplier {"game.bloomMultiplier", 1.0f},
.disableWaterRefraction {"game.disableWaterRefraction", false},
.enableTextureReplacements {"game.enableTextureReplacements", true},
.enableFrameInterpolation {"game.enableFrameInterpolation", FrameInterpMode::Off},
.enableFrameInterpolation {"game.enableFrameInterpolation", false},
.internalResolutionScale {"game.internalResolutionScale", 0},
.shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1},
.resampler {"game.resampler", Resampler::Bilinear},
.enableDepthOfField {"game.enableDepthOfField", true},
.enableMapBackground {"game.enableMapBackground", true},
.disableCutscenePillarboxing {"game.disableCutscenePillarboxing", false},
@@ -180,7 +185,10 @@ void registerSettings() {
Register(g_userSettings.video.lockAspectRatio);
Register(g_userSettings.video.enableFpsOverlay);
Register(g_userSettings.video.fpsOverlayCorner);
Register(g_userSettings.video.maxFrameRate);
Register(g_userSettings.video.windowPositionX);
Register(g_userSettings.video.windowPositionY);
Register(g_userSettings.video.windowWidth);
Register(g_userSettings.video.windowHeight);
// Audio
Register(g_userSettings.audio.masterVolume);
@@ -224,7 +232,6 @@ void registerSettings() {
Register(g_userSettings.game.disableWaterRefraction);
Register(g_userSettings.game.enableTextureReplacements);
Register(g_userSettings.game.internalResolutionScale);
Register(g_userSettings.game.resampler);
Register(g_userSettings.game.shadowResolutionMultiplier);
Register(g_userSettings.game.enableDepthOfField);
Register(g_userSettings.game.enableMapBackground);
+2 -2
View File
@@ -1501,14 +1501,14 @@ EditorWindow::EditorWindow() {
.getValue =
[] {
return std::popcount(static_cast<unsigned>(
get_player_status_b()->mTransformLevelFlag & 0xF));
get_player_status_b()->mTransformLevelFlag & 0x7));
},
.setValue =
[](int value) {
get_player_status_b()->mTransformLevelFlag =
static_cast<u8>((1u << value) - 1u);
},
.max = 4,
.max = 3,
}),
rightPane, {});
leftPane.register_control(
-27
View File
@@ -3,7 +3,6 @@
#include "Z2AudioLib/Z2SeMgr.h"
#include "m_Do/m_Do_audio.h"
#include <aurora/aurora.h>
#include <dolphin/gx/GXAurora.h>
#include <dolphin/vi.h>
#include <fmt/format.h>
@@ -44,8 +43,6 @@ int get_value(GraphicsOption option) {
return getSettings().game.internalResolutionScale.getValue();
case GraphicsOption::ShadowResolution:
return getSettings().game.shadowResolutionMultiplier.getValue();
case GraphicsOption::Resampler:
return static_cast<int>(getSettings().game.resampler.getValue());
case GraphicsOption::BloomMode:
return static_cast<int>(getSettings().game.bloomMode.getValue());
case GraphicsOption::BloomMultiplier:
@@ -65,22 +62,6 @@ void set_value(GraphicsOption option, int value) {
case GraphicsOption::ShadowResolution:
getSettings().game.shadowResolutionMultiplier.setValue(value);
break;
case GraphicsOption::Resampler: {
const auto sampler = static_cast<Resampler>(std::clamp(value,
static_cast<int>(Resampler::Bilinear),
static_cast<int>(Resampler::Area)));
getSettings().game.resampler.setValue(sampler);
switch (sampler) {
case Resampler::Area:
aurora_set_resampler(SAMPLER_AREA);
break;
case Resampler::Bilinear:
default:
aurora_set_resampler(SAMPLER_BILINEAR);
break;
}
break;
}
case GraphicsOption::BloomMode:
getSettings().game.bloomMode.setValue(static_cast<BloomMode>(std::clamp(
value, static_cast<int>(BloomMode::Off), static_cast<int>(BloomMode::Dusk))));
@@ -196,14 +177,6 @@ Rml::String format_graphics_setting_value(GraphicsOption option, int value) {
}
case GraphicsOption::ShadowResolution:
return fmt::format("{}×", value);
case GraphicsOption::Resampler:
switch (static_cast<Resampler>(value)) {
case Resampler::Bilinear:
return "Bilinear";
case Resampler::Area:
return "Area";
}
break;
case GraphicsOption::BloomMode:
switch (static_cast<BloomMode>(value)) {
case BloomMode::Off:
-1
View File
@@ -42,7 +42,6 @@ private:
enum class GraphicsOption {
InternalResolution,
ShadowResolution,
Resampler,
BloomMode,
BloomMultiplier,
};
+1 -1
View File
@@ -40,7 +40,7 @@ void applyPresetDusk() {
s.game.enableQuickTransform.setValue(true);
s.game.instantSaves.setValue(true);
s.game.midnasLamentNonStop.setValue(true);
s.game.enableFrameInterpolation.setValue(FrameInterpMode::Unlimited);
s.game.enableFrameInterpolation.setValue(true);
s.game.sunsSong.setValue(true);
s.game.bloomMode.setValue(BloomMode::Dusk);
s.game.internalResolutionScale.setValue(0);
+6 -76
View File
@@ -59,12 +59,6 @@ constexpr std::array kFpsOverlayCornerNames = {
"Bottom Right",
};
constexpr std::array kInterpolationModes = {
"Off",
"Capped",
"Unlimited",
};
constexpr std::array kGyroInputModeLabels = {
"Sensor",
"Mouse",
@@ -163,8 +157,8 @@ std::vector<AuroraBackend> available_backends() {
size_t backendCount = 0;
const AuroraBackend* raw = aurora_get_available_backends(&backendCount);
for (size_t i = 0; i < backendCount; ++i) {
// Do not expose NULL
if (raw[i] != BACKEND_NULL) {
// Do not expose NULL or D3D11
if (raw[i] != BACKEND_NULL && raw[i] != BACKEND_D3D11) {
backends.emplace_back(raw[i]);
}
}
@@ -357,15 +351,13 @@ const Rml::String kInternalResolutionHelpText =
const Rml::String kShadowResolutionHelpText =
"Configure the shadow-map resolution. Higher values improve shadow quality but increase GPU "
"and memory usage.";
const Rml::String kResamplerHelpText =
"Configure the sampling method used when scaling the internal resolution for final presentation.";
const Rml::String kBloomHelpText =
"Configure the post-processing bloom effect. Classic uses the original bloom pass; Dusklight uses "
"a higher-quality bloom pass.";
const Rml::String kBloomBrightnessHelpText =
"Configure bloom intensity. Higher values make bright areas glow more strongly.";
const Rml::String kUnlockFramerateHelpText =
"<br/>Uses inter-frame interpolation to enable higher frame rates.<br/><br/>May introduce minor "
"Uses inter-frame interpolation to enable higher frame rates.<br/><br/>May introduce minor "
"visual artifacts or animation glitches.";
int float_setting_percent(ConfigVar<float>& var) {
@@ -448,31 +440,6 @@ SelectButton& config_percent_select(Pane& leftPane, Pane& rightPane, ConfigVar<f
return button;
}
SelectButton& config_int_select(Pane& leftPane, Pane& rightPane, ConfigVar<int>& var,
Rml::String key, Rml::String helpText, int min, int max, int step = 5,
std::function<bool()> isDisabled = {}, std::string suffix = "") {
auto& button = leftPane.add_child<NumberButton>(NumberButton::Props{
.key = std::move(key),
.getValue = [&var] { return var; },
.setValue =
[&var, min, max](int value) {
var.setValue(std::clamp(value, min, max));
config::Save();
},
.isDisabled = std::move(isDisabled),
.isModified = [&var] { return var.getValue() != var.getDefaultValue(); },
.min = min,
.max = max,
.step = step,
.suffix = suffix,
});
leftPane.register_control(button, rightPane, [helpText = std::move(helpText)](Pane& pane) {
pane.clear();
pane.add_text(helpText);
});
return button;
}
template <typename T>
void graphics_tuner_control(Window& window, Pane& leftPane, Pane& rightPane, ConfigVar<T>& var,
const GraphicsTunerProps& props, bool prelaunch) {
@@ -807,15 +774,6 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
.valueMax = 8,
.defaultValue = 1,
}, mPrelaunch);
graphics_tuner_control(*this, leftPane, rightPane, getSettings().game.resampler,
GraphicsTunerProps{
.option = GraphicsOption::Resampler,
.title = "Output Resampling",
.helpText = kResamplerHelpText,
.valueMin = static_cast<int>(Resampler::Bilinear),
.valueMax = static_cast<int>(Resampler::Area),
.defaultValue = static_cast<int>(Resampler::Bilinear),
}, mPrelaunch);
leftPane.add_section("Post-Processing");
graphics_tuner_control(*this, leftPane, rightPane, getSettings().game.bloomMode,
@@ -845,39 +803,11 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
.helpText = "Enable installed texture replacements.",
.onChange = [](bool value) { aurora_set_texture_replacements_enabled(value); },
});
leftPane.register_control(
leftPane.add_select_button({
config_bool_select(leftPane, rightPane, getSettings().game.enableFrameInterpolation,
{
.key = "Unlock Framerate",
.getValue =
[] {
return kInterpolationModes[static_cast<u8>(getSettings().game.enableFrameInterpolation.getValue())];
},
.isModified =
[] {
return getSettings().game.enableFrameInterpolation.getValue() !=
getSettings().game.enableFrameInterpolation.getDefaultValue();
},
}),
rightPane, [](Pane& pane) {
for (int i = 0; i < kInterpolationModes.size(); i++) {
pane.add_button({
.text = kInterpolationModes[i],
.isSelected =
[i] {
return getSettings().game.enableFrameInterpolation.getValue() == static_cast<FrameInterpMode>(i);
},
})
.on_pressed([i] {
mDoAud_seStartMenu(kSoundItemChange);
getSettings().game.enableFrameInterpolation.setValue(static_cast<FrameInterpMode>(i));
config::Save();
});
}
pane.add_rml(kUnlockFramerateHelpText);
.helpText = kUnlockFramerateHelpText,
});
config_int_select(leftPane, rightPane, getSettings().video.maxFrameRate,
"Framerate Cap", "Limit the framerate to the specified value.", 30, 540, 1,
[] { return getSettings().game.enableFrameInterpolation.getValue() != FrameInterpMode::Capped; });
config_bool_select(leftPane, rightPane, getSettings().game.enableDepthOfField,
{
.key = "Enable Depth of Field",
+14
View File
@@ -11,7 +11,9 @@
#include <ranges>
#include "aurora/lib/window.hpp"
#include "dusk/dusk.h"
#include "dusk/io.hpp"
#include "dusk/config.hpp"
#include "input.hpp"
#include "prelaunch.hpp"
#include "window.hpp"
@@ -169,6 +171,18 @@ void handle_event(const SDL_Event& event) noexcept {
});
}
sConnectedGamepads.erase(event.gdevice.which);
} else if (event.type == SDL_EVENT_WINDOW_MOVED || event.type == SDL_EVENT_WINDOW_RESIZED) {
int x, y;
if (SDL_GetWindowPosition(aurora::window::get_sdl_window(), &x, &y)) {
getSettings().video.windowPositionX.setValue(x);
getSettings().video.windowPositionY.setValue(y);
}
int width, height;
if (SDL_GetWindowSize(aurora::window::get_sdl_window(), &width, &height)) {
getSettings().video.windowWidth.setValue(width);
getSettings().video.windowHeight.setValue(height);
}
config::Save();
}
input::handle_event(event);
}
+6
View File
@@ -12,6 +12,12 @@
static int fpcLnIt_MethodCall(create_tag_class* i_createTag, method_filter* i_filter) {
#ifdef TARGET_PC
// on init_state==3 fpcEx_ExecuteQTo already ran (layer_tag.layer is NULL)
if (static_cast<base_process_class*>(i_createTag->mpTagData)->state.init_state == 3) {
return 0;
}
#endif
layer_class* layer = static_cast<base_process_class*>(i_createTag->mpTagData)->layer_tag.layer;
layer_class* save_layer = fpcLy_CurrentLayer();
int ret;
+6 -6
View File
@@ -2410,7 +2410,7 @@ void mDoExt_3DlineMat0_c::draw() {
}
#if TARGET_PC
if (!dusk::frame_interp::is_enabled())
if (!dusk::getSettings().game.enableFrameInterpolation)
#endif
{
field_0x16 ^= (u8)1;
@@ -2740,7 +2740,7 @@ void mDoExt_3DlineMat1_c::draw() {
}
GXSetTexCoordScaleManually(GX_TEXCOORD0, 0, 0, 0);
#if TARGET_PC
if (!dusk::frame_interp::is_enabled())
if (!dusk::getSettings().game.enableFrameInterpolation)
#endif
{
mIsDrawn ^= (u8)1;
@@ -2822,7 +2822,7 @@ void mDoExt_3DlineMat1_c::update(int param_0, f32 param_1, GXColor& param_2, u16
}
#if TARGET_PC
const cXyz& lineEye = (presentationEye != nullptr && dusk::frame_interp::is_enabled()) ? *presentationEye : sp_3c->lookat.eye;
const cXyz& lineEye = (presentationEye != nullptr && dusk::getSettings().game.enableFrameInterpolation) ? *presentationEye : sp_3c->lookat.eye;
sp_13c = *local_r27 - lineEye;
#else
sp_13c = *local_r27 - sp_3c->lookat.eye;
@@ -2982,7 +2982,7 @@ void mDoExt_3DlineMat1_c::update(int param_0, GXColor& param_2, dKy_tevstr_c* pa
local_r27 = sp_38[0].field_0x0;
size_p = sp_38->field_0x4;
#if TARGET_PC
if (presentationEye != nullptr && dusk::frame_interp::is_enabled() && size_p == NULL) {
if (presentationEye != nullptr && dusk::getSettings().game.enableFrameInterpolation && size_p == NULL) {
sp_38 += 1;
continue;
}
@@ -3001,7 +3001,7 @@ void mDoExt_3DlineMat1_c::update(int param_0, GXColor& param_2, dKy_tevstr_c* pa
local_f30 = sp_130.abs();
local_f31 += local_f30 * 0.1f;
#if TARGET_PC
const cXyz& lineEye = (presentationEye != nullptr && dusk::frame_interp::is_enabled()) ? *presentationEye : stack_3c->lookat.eye;
const cXyz& lineEye = (presentationEye != nullptr && dusk::getSettings().game.enableFrameInterpolation) ? *presentationEye : stack_3c->lookat.eye;
sp_13c = local_r27[0] - lineEye;
#else
sp_13c = local_r27[0] - stack_3c->lookat.eye;
@@ -3077,7 +3077,7 @@ void mDoExt_3DlineMat1_c::update(int param_0, GXColor& param_2, dKy_tevstr_c* pa
#if TARGET_PC
void mDoExt_3DlineMat1_c::refreshGeometryForPresentationEye(const cXyz& eye) {
if (!dusk::frame_interp::is_enabled()) {
if (!dusk::getSettings().game.enableFrameInterpolation) {
return;
}
if (mInterpLineKind == 1) {
+3 -3
View File
@@ -2063,7 +2063,7 @@ static void captureScreenPerspDrawInfo(JPADrawInfo& info) {
static void drawItem3D() {
ZoneScoped;
#ifdef TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
// FRAME INTERP NOTE: Title screen needs 0.0f while everything else that runs through this is -100.0f.
if (fopAcM_SearchByName(fpcNm_TITLE_e) != nullptr) {
dMenu_Collect3D_c::setViewPortOffsetY(0.0f);
@@ -2241,7 +2241,7 @@ int mDoGph_Painter() {
#endif
dKy_setLight();
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
dKy_setLight_again();
}
#endif
@@ -2296,7 +2296,7 @@ int mDoGph_Painter() {
}
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (dusk::getSettings().game.enableFrameInterpolation) {
// FRAME INTERP NOTE: Currently only recalculating points for Epona's reins. Need a more global solution.
if (daHorse_c* horse = dComIfGp_getHorseActor()) {
horse->lerpControlPoints(dusk::frame_interp::get_interpolation_step());
+8 -37
View File
@@ -28,7 +28,6 @@
#include "d/d_s_logo.h"
#include "d/d_s_menu.h"
#include "d/d_s_play.h"
#include "dusk/time.h"
#include "f_ap/f_ap_game.h"
#include "f_op/f_op_msg.h"
#include "m_Do/m_Do_MemCard.h"
@@ -280,9 +279,8 @@ void main01(void) {
const auto pacing = dusk::game_clock::advance_main_loop();
if (pacing.is_interpolating) {
if (pacing.sim_ticks_to_run > 0) {
dusk::frame_interp::begin_frame(dusk::getSettings().game.enableFrameInterpolation, true, 0.0f);
dusk::frame_interp::begin_frame(true, true, 0.0f);
dusk::frame_interp::set_ui_tick_pending(true);
for (int sim_tick = 0; sim_tick < pacing.sim_ticks_to_run; ++sim_tick) {
dusk::frame_interp::begin_sim_tick();
mDoCPd_c::read();
@@ -293,7 +291,7 @@ void main01(void) {
}
}
dusk::frame_interp::begin_frame(dusk::getSettings().game.enableFrameInterpolation, false,
dusk::frame_interp::begin_frame(true, false,
dusk::game_clock::sample_interpolation_step());
dusk::frame_interp::interpolate();
dusk::frame_interp::begin_presentation_camera();
@@ -303,7 +301,7 @@ void main01(void) {
dusk::frame_interp::end_presentation_camera();
dusk::frame_interp::set_ui_tick_pending(false);
} else {
dusk::frame_interp::begin_frame(dusk::FrameInterpMode::Off, true, 0.0f);
dusk::frame_interp::begin_frame(false, true, 0.0f);
dusk::frame_interp::set_ui_tick_pending(true);
// Game Inputs
@@ -317,26 +315,8 @@ void main01(void) {
mDoAud_Execute();
}
static Limiter main_loop_limiter;
static double last_fps_setting = 0.0;
static Limiter::duration_t target_ns = 0;
if (dusk::getSettings().game.enableFrameInterpolation.getValue() == dusk::FrameInterpMode::Capped && !dusk::getTransientSettings().skipFrameRateLimit) {
double current_fps = dusk::getSettings().video.maxFrameRate.getValue();
if (current_fps != last_fps_setting) {
last_fps_setting = current_fps;
target_ns = static_cast<Limiter::duration_t>(1'000'000'000.0 / current_fps);
}
Limiter::duration_t sleepTime = main_loop_limiter.Sleep(target_ns);
dusk::frameUsagePct = 100.0f * (1.0f - static_cast<float>(sleepTime) / static_cast<float>(target_ns));
} else {
main_loop_limiter.Reset();
}
aurora_end_frame();
FrameMark;
#ifdef DUSK_DISCORD
@@ -513,7 +493,7 @@ int game_main(int argc, char* argv[]) {
("h,help", "Print usage")
("console", "Show the Windows console window for logs", cxxopts::value<bool>()->default_value("false")->implicit_value("true"))
("dvd", "Path to DVD image file", cxxopts::value<std::string>())
("backend", "Graphics API backend to use (auto, d3d12, d3d11, metal, vulkan, null)", cxxopts::value<std::string>())
("backend", "Graphics API backend to use (auto, d3d12, metal, vulkan, null)", cxxopts::value<std::string>())
("cvar", "Override configuration variables without modifying config", cxxopts::value<std::vector<std::string>>());
arg_options.parse_positional({"dvd"});
@@ -571,10 +551,10 @@ int game_main(int argc, char* argv[]) {
config.cachePath = reinterpret_cast<const char*>(cachePathString.c_str());
config.vsync = dusk::getSettings().video.enableVsync;
config.startFullscreen = dusk::getSettings().video.enableFullscreen;
config.windowPosX = -1;
config.windowPosY = -1;
config.windowWidth = defaultWindowWidth * 2;
config.windowHeight = defaultWindowHeight * 2;
config.windowPosX = dusk::getSettings().video.windowPositionX;
config.windowPosY = dusk::getSettings().video.windowPositionY;
config.windowWidth = dusk::getSettings().video.windowWidth;
config.windowHeight = dusk::getSettings().video.windowHeight;
config.desiredBackend = ResolveDesiredBackend(parsed_arg_options);
config.logCallback = &aurora_log_callback;
config.logLevel = startupLogLevel;
@@ -604,15 +584,6 @@ int game_main(int argc, char* argv[]) {
AuroraSetViewportPolicy(AURORA_VIEWPORT_STRETCH);
}
VISetFrameBufferScale(dusk::getSettings().game.internalResolutionScale.getValue());
switch (dusk::getSettings().game.resampler.getValue()) {
case dusk::Resampler::Area:
aurora_set_resampler(SAMPLER_AREA);
break;
case dusk::Resampler::Bilinear:
default:
aurora_set_resampler(SAMPLER_BILINEAR);
break;
}
dusk::audio::SetMasterVolume(dusk::audio::MasterVolumeToLinear(dusk::getSettings().audio.masterVolume / 100.0f));
dusk::audio::SetEnableReverb(dusk::getSettings().audio.enableReverb);