Compare commits

..

2 Commits

Author SHA1 Message Date
SuperDude88 a01c01b582 Move restore_from_speedrun_mode
I think it makes more sense to have this in the same place the overrides are set
2026-07-06 20:29:39 -04:00
SuperDude88 552b3ad353 Deduplicate Speedrun Overrides
Avoids issues where only one is updated + makes sense organizationally
2026-07-06 19:59:43 -04:00
54 changed files with 372 additions and 738 deletions
+4 -5
View File
@@ -363,8 +363,7 @@ set(DUSK_COPYRIGHT "Copyright (C) Twilit Realm contributors")
source_group("dolzel" FILES ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${REL_FILES}) source_group("dolzel" FILES ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${REL_FILES})
source_group("dusklight" FILES ${DUSK_FILES} ${DUSK_HTTP_BACKEND_FILES}) source_group("dusklight" FILES ${DUSK_FILES} ${DUSK_HTTP_BACKEND_FILES})
# PARTIAL_DEBUG makes debug and release share one struct/vtable ABI so a mod binary loads into either set(GAME_COMPILE_DEFS TARGET_PC WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0 MTX_USE_PS=1)
set(GAME_COMPILE_DEFS TARGET_PC WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0 MTX_USE_PS=1 PARTIAL_DEBUG=1)
set(GAME_INCLUDE_DIRS set(GAME_INCLUDE_DIRS
include include
@@ -475,7 +474,7 @@ set(GAME_DEBUG_FILES
set_source_files_properties( set_source_files_properties(
${GAME_DEBUG_FILES} ${GAME_DEBUG_FILES}
PROPERTIES PROPERTIES
COMPILE_DEFINITIONS "$<$<CONFIG:Debug>:DEBUG=1>;PARTIAL_DEBUG=1" COMPILE_DEFINITIONS "$<$<CONFIG:Debug>:DEBUG=1>;$<$<CONFIG:Debug>:PARTIAL_DEBUG=1>"
) )
# game_base is for all other game code files # game_base is for all other game code files
@@ -489,14 +488,14 @@ set(GAME_BASE_FILES
set_source_files_properties( set_source_files_properties(
${GAME_BASE_FILES} ${GAME_BASE_FILES}
PROPERTIES PROPERTIES
COMPILE_DEFINITIONS "NDEBUG=1;NDEBUG_DEFINED=1;DEBUG_DEFINED=0;PARTIAL_DEBUG=1" COMPILE_DEFINITIONS "NDEBUG=1;NDEBUG_DEFINED=1;DEBUG_DEFINED=0;$<$<CONFIG:Debug>:PARTIAL_DEBUG=1>"
) )
foreach(jsystem_lib IN LISTS JSYSTEM_LIBRARIES) foreach(jsystem_lib IN LISTS JSYSTEM_LIBRARIES)
target_compile_definitions(${jsystem_lib} PRIVATE target_compile_definitions(${jsystem_lib} PRIVATE
${GAME_COMPILE_DEFS} ${GAME_COMPILE_DEFS}
$<$<CONFIG:Debug>:DEBUG=1> $<$<CONFIG:Debug>:DEBUG=1>
PARTIAL_DEBUG=1 $<$<CONFIG:Debug>:PARTIAL_DEBUG=1>
) )
target_include_directories(${jsystem_lib} PRIVATE ${GAME_INCLUDE_DIRS}) target_include_directories(${jsystem_lib} PRIVATE ${GAME_INCLUDE_DIRS})
target_link_libraries(${jsystem_lib} PRIVATE ${GAME_LIBS}) target_link_libraries(${jsystem_lib} PRIVATE ${GAME_LIBS})
+1 -1
@@ -20,7 +20,7 @@ public:
/* 0x14 */ cM3dGAab mM3dGAab; /* 0x14 */ cM3dGAab mM3dGAab;
/* 0x30 */ cBgS_ShdwDraw_Callback mCallbackFun; /* 0x30 */ cBgS_ShdwDraw_Callback mCallbackFun;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x34 */ int field_0x34; /* 0x34 */ int field_0x34;
#endif #endif
}; };
-2
View File
@@ -48,8 +48,6 @@ public:
/* 0x1370 */ Z2FxLineMgr mFxLineMgr; /* 0x1370 */ Z2FxLineMgr mFxLineMgr;
#if DEBUG #if DEBUG
/* 0x13BC */ Z2DebugSys mDebugSys; /* 0x13BC */ Z2DebugSys mDebugSys;
#elif PARTIAL_DEBUG
alignas(Z2DebugSys) u8 mDebugSys[sizeof(Z2DebugSys)];
#endif #endif
}; // Size: 0x138C }; // Size: 0x138C
+1 -1
View File
@@ -194,7 +194,7 @@ public:
JAISoundHandle* getMainBgmHandle() { return &mMainBgmHandle; } JAISoundHandle* getMainBgmHandle() { return &mMainBgmHandle; }
JAISoundHandle* getSubBgmHandle() { return &mSubBgmHandle; } JAISoundHandle* getSubBgmHandle() { return &mSubBgmHandle; }
#if PARTIAL_DEBUG || DEBUG #if DEBUG
f32 field_0x00_debug; f32 field_0x00_debug;
u8 field_0x04_debug; u8 field_0x04_debug;
#endif #endif
+2 -2
View File
@@ -100,13 +100,13 @@ public:
bool isForceBattle() { return forceBattle_; } bool isForceBattle() { return forceBattle_; }
JSUList<Z2CreatureEnemy>* getEnemyList() { return &field_0x0; } JSUList<Z2CreatureEnemy>* getEnemyList() { return &field_0x0; }
#if PARTIAL_DEBUG || DEBUG #if DEBUG
JSUList<Z2SoundObjBase>* getAllList() { return &allList_; } JSUList<Z2SoundObjBase>* getAllList() { return &allList_; }
#endif #endif
private: private:
/* 0x00 */ JSUList<Z2CreatureEnemy> field_0x0; /* 0x00 */ JSUList<Z2CreatureEnemy> field_0x0;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x0C */ JSUList<Z2SoundObjBase> allList_; /* 0x0C */ JSUList<Z2SoundObjBase> allList_;
#endif #endif
/* 0x0C */ Z2EnemyArea enemyArea_; /* 0x0C */ Z2EnemyArea enemyArea_;
+1 -1
View File
@@ -7,7 +7,7 @@
struct Z2SoundStarter; struct Z2SoundStarter;
class Z2SoundObjBase : public Z2SoundHandles class Z2SoundObjBase : public Z2SoundHandles
#if PARTIAL_DEBUG || DEBUG #if DEBUG
, public JSULink<Z2SoundObjBase> , public JSULink<Z2SoundObjBase>
#endif #endif
{ {
+2 -2
View File
@@ -45,7 +45,7 @@ private:
class dAttParam_c : public JORReflexible { class dAttParam_c : public JORReflexible {
public: public:
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x04 */ s8 mHIOChildNo; /* 0x04 */ s8 mHIOChildNo;
#endif #endif
@@ -66,7 +66,7 @@ public:
/* 0x35 */ u8 mAttnCursorDisappearFrames; /* 0x35 */ u8 mAttnCursorDisappearFrames;
/* 0x38 */ f32 field_0x38; /* 0x38 */ f32 field_0x38;
/* 0x3C */ f32 field_0x3c; /* 0x3C */ f32 field_0x3c;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x44 */ s32 mDebugDispPosX; /* 0x44 */ s32 mDebugDispPosX;
/* 0x48 */ s32 mDebugDispPosY; /* 0x48 */ s32 mDebugDispPosY;
#endif #endif
+2 -2
View File
@@ -201,7 +201,7 @@ private:
/* 0x02C */ u32 m_flags; /* 0x02C */ u32 m_flags;
/* 0x030 */ cXyz* pm_pos; /* 0x030 */ cXyz* pm_pos;
/* 0x034 */ cXyz* pm_old_pos; /* 0x034 */ cXyz* pm_old_pos;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x038 */ cXyz unk_0x38; /* 0x038 */ cXyz unk_0x38;
#endif #endif
/* 0x038 */ cXyz* pm_speed; /* 0x038 */ cXyz* pm_speed;
@@ -229,7 +229,7 @@ private:
/* 0x0CC */ f32 field_0xcc; /* 0x0CC */ f32 field_0xcc;
/* 0x0D0 */ f32 m_wtr_chk_offset; /* 0x0D0 */ f32 m_wtr_chk_offset;
/* 0x0D4 */ cBgS_PolyInfo* pm_out_poly_info; /* 0x0D4 */ cBgS_PolyInfo* pm_out_poly_info;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x0E4 */ cXyz unk_0xe4; /* 0x0E4 */ cXyz unk_0xe4;
#endif #endif
/* 0x0D8 */ f32 field_0xd8; /* 0x0D8 */ f32 field_0xd8;
+1 -1
View File
@@ -79,7 +79,7 @@ public:
// /* 0x0000 */ cCcS mCCcS; // /* 0x0000 */ cCcS mCCcS;
/* 0x284C */ dCcMassS_Mng mMass_Mng; /* 0x284C */ dCcMassS_Mng mMass_Mng;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x2AD0 */ u8 m_is_mass_all_timer; /* 0x2AD0 */ u8 m_is_mass_all_timer;
#endif #endif
}; // Size = 0x2AC4 }; // Size = 0x2AC4
+1 -1
View File
@@ -1037,7 +1037,7 @@ public:
/* 0x1DE09 */ u8 field_0x1de09; /* 0x1DE09 */ u8 field_0x1de09;
/* 0x1DE0A */ u8 field_0x1de0a; /* 0x1DE0A */ u8 field_0x1de0a;
/* 0x1DE0B */ u8 mIsDebugMode; /* 0x1DE0B */ u8 mIsDebugMode;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x1DE0C */ OSStopwatch mStopwatch; /* 0x1DE0C */ OSStopwatch mStopwatch;
#endif #endif
+1 -1
View File
@@ -41,7 +41,7 @@ public:
BASE_ROOM5, BASE_ROOM5,
BASE_DEMO, BASE_DEMO,
#if PARTIAL_DEBUG || DEBUG #if DEBUG
BASE_DEBUG, BASE_DEBUG,
#endif #endif
+1 -1
View File
@@ -259,7 +259,7 @@ public:
/* 0x09B8 */ DUNGEON_LIGHT dungeonlight[8]; /* 0x09B8 */ DUNGEON_LIGHT dungeonlight[8];
/* 0x0C18 */ BOSS_LIGHT field_0x0c18[8]; /* 0x0C18 */ BOSS_LIGHT field_0x0c18[8];
/* 0x0D58 */ BOSS_LIGHT field_0x0d58[6]; /* 0x0D58 */ BOSS_LIGHT field_0x0d58[6];
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x0E48 */ NAVYCHAN navy; /* 0x0E48 */ NAVYCHAN navy;
/* 0x0E58 */ u8 field_0xe58[0xE68 - 0xE58]; // part of NAVYCHAN? /* 0x0E58 */ u8 field_0xe58[0xE68 - 0xE58]; // part of NAVYCHAN?
#endif #endif
+2 -2
View File
@@ -521,13 +521,13 @@ private:
/* 0x019 */ u8 field_0x19; /* 0x019 */ u8 field_0x19;
/* 0x01A */ u8 field_0x1a; /* 0x01A */ u8 field_0x1a;
/* 0x01B */ u8 field_0x1b; /* 0x01B */ u8 field_0x1b;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x01C */ dPa_simpleEcallBack field_0x1c[48]; /* 0x01C */ dPa_simpleEcallBack field_0x1c[48];
#else #else
/* 0x01C */ dPa_simpleEcallBack field_0x1c[25]; /* 0x01C */ dPa_simpleEcallBack field_0x1c[25];
#endif #endif
/* 0x210 */ level_c field_0x210; /* 0x210 */ level_c field_0x210;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
u8 mSceneCount; u8 mSceneCount;
#endif #endif
}; };
+1 -1
View File
@@ -59,7 +59,7 @@ private:
/* 0x18 */ JKRHeap* heap; /* 0x18 */ JKRHeap* heap;
/* 0x1C */ JKRSolidHeap* mDataHeap; /* 0x1C */ JKRSolidHeap* mDataHeap;
/* 0x20 */ void** mRes; /* 0x20 */ void** mRes;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x24 */ int mSize; /* 0x24 */ int mSize;
#endif #endif
}; // Size: 0x24 }; // Size: 0x24
+1 -4
View File
@@ -1008,7 +1008,7 @@ public:
static const int ZONE_MAX = 0x20; static const int ZONE_MAX = 0x20;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x000 */ u8 unk_0x0; /* 0x000 */ u8 unk_0x0;
/* 0x001 */ char unk_0x1; /* 0x001 */ char unk_0x1;
/* 0x000 */ u8 unk_0x2[0x48 - 0x2]; /* 0x000 */ u8 unk_0x2[0x48 - 0x2];
@@ -1029,9 +1029,6 @@ public:
/* 0xF30 */ s64 mSaveTotalTime; /* 0xF30 */ s64 mSaveTotalTime;
#if DEBUG #if DEBUG
/* 0xF80 */ flagFile_c mFlagFile; /* 0xF80 */ flagFile_c mFlagFile;
#elif PARTIAL_DEBUG
// flagFile_c's ctor/virtuals are only defined under #if DEBUG (d_save.cpp)
alignas(flagFile_c) u8 mFlagFile[sizeof(flagFile_c)];
#endif #endif
}; // Size: 0xF38 }; // Size: 0xF38
+4 -4
View File
@@ -538,7 +538,7 @@ public:
/* vt[86] */ virtual stage_tgsc_class* getDrTg(void) const = 0; /* vt[86] */ virtual stage_tgsc_class* getDrTg(void) const = 0;
/* vt[87] */ virtual void setDoor(stage_tgsc_class*) = 0; /* vt[87] */ virtual void setDoor(stage_tgsc_class*) = 0;
/* vt[88] */ virtual stage_tgsc_class* getDoor(void) const = 0; /* vt[88] */ virtual stage_tgsc_class* getDoor(void) const = 0;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
virtual void setUnit(void*) = 0; virtual void setUnit(void*) = 0;
virtual void* getUnit() = 0; virtual void* getUnit() = 0;
#endif #endif
@@ -796,7 +796,7 @@ public:
virtual stage_tgsc_class* getDrTg(void) const { return mDrTg; } virtual stage_tgsc_class* getDrTg(void) const { return mDrTg; }
virtual void setDoor(stage_tgsc_class* i_Door) { mDoor = i_Door; } virtual void setDoor(stage_tgsc_class* i_Door) { mDoor = i_Door; }
virtual stage_tgsc_class* getDoor(void) const { return mDoor; } virtual stage_tgsc_class* getDoor(void) const { return mDoor; }
#if PARTIAL_DEBUG || DEBUG #if DEBUG
virtual void setUnit(void* i_Unit) { mUnit = i_Unit; } virtual void setUnit(void* i_Unit) { mUnit = i_Unit; }
virtual void* getUnit() { return mUnit; } virtual void* getUnit() { return mUnit; }
#endif #endif
@@ -845,7 +845,7 @@ public:
/* 0x54 */ stage_tgsc_class* mDrTg; /* 0x54 */ stage_tgsc_class* mDrTg;
/* 0x58 */ stage_tgsc_class* mDoor; /* 0x58 */ stage_tgsc_class* mDoor;
/* 0x5C */ dStage_FloorInfo_c* mFloorInfo; /* 0x5C */ dStage_FloorInfo_c* mFloorInfo;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x60 */ void* mUnit; /* 0x60 */ void* mUnit;
#endif #endif
/* 0x60 */ u16 mPlayerNum; /* 0x60 */ u16 mPlayerNum;
@@ -990,7 +990,7 @@ public:
/* vt[86] */ virtual stage_tgsc_class* getDrTg(void) const { return mDrTg; } /* vt[86] */ virtual stage_tgsc_class* getDrTg(void) const { return mDrTg; }
/* vt[87] */ virtual void setDoor(stage_tgsc_class* i_Door) { mDoor = i_Door; } /* vt[87] */ virtual void setDoor(stage_tgsc_class* i_Door) { mDoor = i_Door; }
/* vt[88] */ virtual stage_tgsc_class* getDoor(void) const { return mDoor; } /* vt[88] */ virtual stage_tgsc_class* getDoor(void) const { return mDoor; }
#if PARTIAL_DEBUG || DEBUG #if DEBUG
virtual void setUnit(void* i_Unit) { virtual void setUnit(void* i_Unit) {
UNUSED(i_Unit); UNUSED(i_Unit);
OSReport("stage non unit list data !!\n"); OSReport("stage non unit list data !!\n");
-3
View File
@@ -97,9 +97,6 @@ public:
private: private:
#if DEBUG #if DEBUG
/* 0x00 */ dVibTest_c mVibTest; /* 0x00 */ dVibTest_c mVibTest;
#elif PARTIAL_DEBUG
// dVibTest_c's ctor/virtuals are only defined under #if DEBUG (d_vibration.cpp)
alignas(dVibTest_c) u8 mVibTest[sizeof(dVibTest_c)];
#endif #endif
class { class {
+7 -70
View File
@@ -1,11 +1,9 @@
#ifndef DUSK_CONFIG_HPP #ifndef DUSK_CONFIG_HPP
#define DUSK_CONFIG_HPP #define DUSK_CONFIG_HPP
#include <concepts>
#include <functional> #include <functional>
#include <nlohmann/json.hpp>
#include <stdexcept> #include <stdexcept>
#include "nlohmann/json.hpp"
#include "config_var.hpp" #include "config_var.hpp"
namespace dusk::config { namespace dusk::config {
@@ -42,7 +40,7 @@ public:
[[nodiscard]] virtual nlohmann::json dumpToJson(const ConfigVarBase& cVar) const = 0; [[nodiscard]] virtual nlohmann::json dumpToJson(const ConfigVarBase& cVar) const = 0;
}; };
template <ConfigValue T> template<ConfigValue T>
class ConfigImpl : public ConfigImplBase { class ConfigImpl : public ConfigImplBase {
// Just downcasting the references... // Just downcasting the references...
void loadFromJson(ConfigVarBase& cVar, const nlohmann::json& jsonValue) const final { void loadFromJson(ConfigVarBase& cVar, const nlohmann::json& jsonValue) const final {
@@ -92,28 +90,20 @@ public:
void Register(ConfigVarBase& configVar); void Register(ConfigVarBase& configVar);
/** /**
* \brief Unregister a CVar, detaching it from the config system. * \brief Indicate that all registrations have happened and everything should lock in.
*
* If the CVar carries a user-set value (Value or Speedrun layer), it is stashed as an
* unregistered key: Save() keeps writing it, and a later Register() of the same name restores
* it through the normal back-fill path. The CVar may be destroyed after this returns.
*/ */
void unregister(ConfigVarBase& configVar); void FinishRegistration();
/** /**
* \brief Load config from the standard user preferences location. * \brief Load config from the standard user preferences location.
*/ */
void load_from_user_preferences(); void LoadFromUserPreferences();
void load_from_file_name(const char* path); void LoadFromFileName(const char* path);
void load_arg_override(std::string_view name, std::string_view value);
void shutdown();
/** /**
* \brief Save the config to file. * \brief Save the config to file.
*/ */
void save(); void Save();
/** /**
* \brief Get a registered CVar by name. * \brief Get a registered CVar by name.
@@ -134,59 +124,6 @@ void ClearAllActionBindings(int port);
*/ */
void EnumerateRegistered(std::function<void(ConfigVarBase&)> callback); void EnumerateRegistered(std::function<void(ConfigVarBase&)> callback);
/**
* \brief Type-erased change callback. previousValue points at the value before the mutation
* (a `const T*` for a `ConfigVar<T>`) and is valid only for the duration of the call.
*/
using ChangeCallback = std::function<void(ConfigVarBase& cVar, const void* previousValue)>;
/**
* \brief Token identifying a change subscription. 0 is never a valid token.
*/
using Subscription = u64;
/**
* \brief Subscribe to changes of the named CVar (registered or not yet registered).
*
* Fired synchronously on the mutating thread (in practice the game thread) whenever the CVar's
* effective value changes at runtime: setValue, override/speedrun setters and clears. Values
* applied by config load or launch arguments do *not* notify: loads happen during startup
* before the subsystems callbacks push values into are initialized, and each subsystem reads
* its initial value itself at its own init. Callbacks may mutate other CVars; a nested
* mutation of the same CVar applies but does not re-notify.
*/
Subscription subscribe(std::string_view name, ChangeCallback callback);
/**
* \brief Typed convenience overload: the callback receives the current and previous values.
*/
template <ConfigValue T, typename Callback>
requires std::invocable<Callback, const T&, const T&> Subscription subscribe(
ConfigVar<T>& cVar, Callback&& callback) {
return subscribe(cVar.getName(),
[&cVar, cb = std::forward<Callback>(callback)](ConfigVarBase&, const void* previousValue) {
cb(cVar.getValue(), *static_cast<const T*>(previousValue));
});
}
void unsubscribe(Subscription token);
/**
* \brief Register a CVar and attach a change callback in one step.
*
* Useful for pushing settings into external systems (e.g. aurora) from one place instead of
* every UI setter. The callback fires only for runtime changes (see subscribe); the value
* loaded from config or launch arguments does not fire it the external system reads its
* initial value itself at its own initialization.
*/
template <ConfigValue T, typename Callback>
requires std::invocable<Callback, const T&, const T&> Subscription Register(
ConfigVar<T>& cVar, Callback&& onChange) {
auto subscription = subscribe(cVar, std::forward<Callback>(onChange));
Register(static_cast<ConfigVarBase&>(cVar));
return subscription;
}
template <ConfigValue T> template <ConfigValue T>
const ConfigImplBase* GetConfigImpl() { const ConfigImplBase* GetConfigImpl() {
static ConfigImpl<T> config; static ConfigImpl<T> config;
+6 -82
View File
@@ -2,12 +2,10 @@
#define DUSK_CONFIG_VAR_HPP #define DUSK_CONFIG_VAR_HPP
#include "dolphin/types.h" #include "dolphin/types.h"
#include <concepts> #include <type_traits>
#include <cstdlib> #include <cstdlib>
#include <limits> #include <limits>
#include <optional>
#include <string> #include <string>
#include <type_traits>
/** /**
* The configuration system. * The configuration system.
@@ -71,7 +69,7 @@ protected:
/** /**
* The name of this CVar, used in the configuration file. * The name of this CVar, used in the configuration file.
*/ */
std::string name; const char* name;
/** /**
* Whether this CVar has been registered with the global managing logic. * Whether this CVar has been registered with the global managing logic.
@@ -89,8 +87,8 @@ protected:
*/ */
const ConfigImplBase* impl; const ConfigImplBase* impl;
ConfigVarBase(const ConfigVarBase&) = delete; ConfigVarBase(const char* name, const ConfigImplBase* impl);
ConfigVarBase(std::string name, const ConfigImplBase* impl); virtual ~ConfigVarBase() = default;
/** /**
* Check that the CVar is registered, aborting if this is not the case. * Check that the CVar is registered, aborting if this is not the case.
@@ -100,22 +98,7 @@ protected:
abort(); abort();
} }
/**
* Whether any change subscriber (see config::subscribe) is attached to this CVar's name.
*/
[[nodiscard]] bool has_subscribers() const;
/**
* Notify change subscribers (see config::subscribe) that the effective value of this CVar
* changed. Called by mutators after the change has been applied; previousValue points at
* the old value (a `const T*` for a `ConfigVar<T>`), valid only for the duration of the
* call.
*/
void notify_changed(const void* previousValue);
public: public:
virtual ~ConfigVarBase();
/** /**
* Get the name of this CVar, used in the configuration file. * Get the name of this CVar, used in the configuration file.
*/ */
@@ -138,7 +121,6 @@ public:
* This is necessary to make it legal to access. * This is necessary to make it legal to access.
*/ */
void markRegistered(); void markRegistered();
void unmarkRegistered();
/** /**
* Clear a speedrun-mode override if one is active on this CVar. * Clear a speedrun-mode override if one is active on this CVar.
@@ -173,7 +155,6 @@ template <typename T>
concept ConfigValue = concept ConfigValue =
!std::is_const_v<T> !std::is_const_v<T>
&& !std::is_volatile_v<T> && !std::is_volatile_v<T>
&& std::equality_comparable<T>
&& (std::is_same_v<T, bool> && (std::is_same_v<T, bool>
|| ConfigValueInteger<T> || ConfigValueInteger<T>
|| std::is_same_v<T, f32> || std::is_same_v<T, f32>
@@ -185,9 +166,6 @@ concept ConfigValue =
template <ConfigValue T> template <ConfigValue T>
const ConfigImplBase* GetConfigImpl(); const ConfigImplBase* GetConfigImpl();
template <ConfigValue T>
class ConfigImpl;
template <typename T> template <typename T>
struct ConfigEnumRange { struct ConfigEnumRange {
static constexpr auto min = std::numeric_limits<std::underlying_type_t<T>>::min(); static constexpr auto min = std::numeric_limits<std::underlying_type_t<T>>::min();
@@ -214,12 +192,10 @@ public:
* @param arg Arguments to forward to construct the default value. * @param arg Arguments to forward to construct the default value.
*/ */
template <typename... Args> template <typename... Args>
ConfigVar(std::string name, Args&&... arg) ConfigVar(const char* name, Args&&... arg)
: ConfigVarBase(std::move(name), GetConfigImpl<T>()), defaultValue(std::forward<Args>(arg)...), : ConfigVarBase(name, GetConfigImpl<T>()), defaultValue(std::forward<Args>(arg)...),
value(), overrideValue() {} value(), overrideValue() {}
ConfigVar(ConfigVar const&) = delete;
/** /**
* \brief Get the current value of the CVar. * \brief Get the current value of the CVar.
* *
@@ -258,7 +234,6 @@ public:
*/ */
void setValue(T newValue, bool replaceOverride = true) { void setValue(T newValue, bool replaceOverride = true) {
checkRegistered(); checkRegistered();
const auto previous = previous_for_notify();
value = std::move(newValue); value = std::move(newValue);
if (replaceOverride) { if (replaceOverride) {
@@ -267,7 +242,6 @@ public:
} else if (layer != ConfigVarLayer::Override) { } else if (layer != ConfigVarLayer::Override) {
layer = ConfigVarLayer::Value; layer = ConfigVarLayer::Value;
} }
notify_if_changed(previous);
} }
operator const T&() { operator const T&() {
@@ -284,10 +258,8 @@ public:
*/ */
void setOverrideValue(T newValue) { void setOverrideValue(T newValue) {
checkRegistered(); checkRegistered();
const auto previous = previous_for_notify();
overrideValue = std::move(newValue); overrideValue = std::move(newValue);
layer = ConfigVarLayer::Override; layer = ConfigVarLayer::Override;
notify_if_changed(previous);
} }
/** /**
@@ -301,31 +273,25 @@ public:
void setSpeedrunValue(T newValue) { void setSpeedrunValue(T newValue) {
checkRegistered(); checkRegistered();
if (layer != ConfigVarLayer::Override) { if (layer != ConfigVarLayer::Override) {
const auto previous = previous_for_notify();
priorLayer = layer; priorLayer = layer;
overrideValue = std::move(newValue); overrideValue = std::move(newValue);
layer = ConfigVarLayer::Speedrun; layer = ConfigVarLayer::Speedrun;
notify_if_changed(previous);
} }
} }
void clearOverride() { void clearOverride() {
checkRegistered(); checkRegistered();
if (layer == ConfigVarLayer::Override) { if (layer == ConfigVarLayer::Override) {
const auto previous = previous_for_notify();
overrideValue = {}; overrideValue = {};
layer = ConfigVarLayer::Value; layer = ConfigVarLayer::Value;
notify_if_changed(previous);
} }
} }
void clearSpeedrunOverride() override { void clearSpeedrunOverride() override {
checkRegistered(); checkRegistered();
if (layer == ConfigVarLayer::Speedrun) { if (layer == ConfigVarLayer::Speedrun) {
const auto previous = previous_for_notify();
overrideValue = {}; overrideValue = {};
layer = priorLayer; layer = priorLayer;
notify_if_changed(previous);
} }
} }
@@ -339,48 +305,6 @@ public:
const ConfigVarLayer effectiveLayer = (layer == ConfigVarLayer::Speedrun) ? priorLayer : layer; const ConfigVarLayer effectiveLayer = (layer == ConfigVarLayer::Speedrun) ? priorLayer : layer;
return effectiveLayer == ConfigVarLayer::Default ? defaultValue : value; return effectiveLayer == ConfigVarLayer::Default ? defaultValue : value;
} }
private:
// The config loader applies values through the silent load_* methods below.
friend class ConfigImpl<T>;
/**
* Copy of the effective value before a mutation, taken only when someone is subscribed.
*/
[[nodiscard]] std::optional<T> previous_for_notify() const {
return has_subscribers() ? std::optional<T>{getValue()} : std::nullopt;
}
/**
* Notify subscribers if the effective value actually changed across a mutation.
*/
void notify_if_changed(const std::optional<T>& previous) {
if (previous.has_value() && !(getValue() == *previous)) {
notify_changed(&*previous);
}
}
/**
* setValue(newValue, false) without notifying change subscribers. Used when loading config:
* loads happen during startup before the subsystems change callbacks push values into are
* initialized, and each subsystem applies the loaded value itself at its own init.
*/
void load_value(T newValue) {
checkRegistered();
value = std::move(newValue);
if (layer != ConfigVarLayer::Override) {
layer = ConfigVarLayer::Value;
}
}
/**
* setOverrideValue without notifying change subscribers (see load_value).
*/
void load_override_value(T newValue) {
checkRegistered();
overrideValue = std::move(newValue);
layer = ConfigVarLayer::Override;
}
}; };
using ActionBindConfigVar = ConfigVar<int>; using ActionBindConfigVar = ConfigVar<int>;
+1 -2
View File
@@ -7,8 +7,7 @@
namespace dusk { namespace dusk {
using config::ConfigVar; using namespace config;
using config::ActionBindConfigVar;
enum class BloomMode : int { enum class BloomMode : int {
Off = 0, Off = 0,
+1
View File
@@ -37,5 +37,6 @@ struct SpeedrunInfo {
extern SpeedrunInfo m_speedrunInfo; extern SpeedrunInfo m_speedrunInfo;
void resetForSpeedrunMode(); void resetForSpeedrunMode();
void restoreFromSpeedrunMode();
} // namespace dusk } // namespace dusk
+1 -1
View File
@@ -36,7 +36,7 @@ typedef struct node_create_request {
/* 0x58 */ s16 name; /* 0x58 */ s16 name;
/* 0x5C */ void* data; /* 0x5C */ void* data;
/* 0x60 */ s16 unk_0x60; /* 0x60 */ s16 unk_0x60;
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x64 */ int unk_0x64; /* 0x64 */ int unk_0x64;
/* 0x68 */ int unk_0x68; /* 0x68 */ int unk_0x68;
#endif #endif
+2 -2
View File
@@ -11,13 +11,13 @@ class mDoAud_zelAudio_c : public Z2AudioMgr {
public: public:
void reset(); void reset();
mDoAud_zelAudio_c() { mDoAud_zelAudio_c() {
#if PARTIAL_DEBUG || DEBUG #if DEBUG
setMode(2); setMode(2);
#endif #endif
} }
~mDoAud_zelAudio_c() {} ~mDoAud_zelAudio_c() {}
#if PARTIAL_DEBUG || DEBUG #if DEBUG
u8 getMode() { return field_0x13bd; } u8 getMode() { return field_0x13bd; }
void setMode(u8 mode) { field_0x13bd = mode; } void setMode(u8 mode) { field_0x13bd = mode; }
-5
View File
@@ -35,11 +35,6 @@ public:
/* 0x4 */ s8 mNo; /* 0x4 */ s8 mNo;
/* 0x5 */ u8 mCount; /* 0x5 */ u8 mCount;
#else #else
#if PARTIAL_DEBUG
// Initialized here since the DEBUG ctor doesn't run.
/* 0x4 */ s8 mNo = -1;
/* 0x5 */ u8 mCount = 0;
#endif
virtual ~mDoHIO_entry_c() {} virtual ~mDoHIO_entry_c() {}
#endif #endif
}; };
@@ -12,23 +12,12 @@ struct JORNodeEvent;
class JORMContext; class JORMContext;
class JORServer; class JORServer;
// NOTE (stable game ABI): these classes stay non-polymorphic outside DEBUG
// on purpose. Making them polymorphic under PARTIAL_DEBUG would give every one of the ~250
// derived HIO classes a vptr and turn their plain `void genMessage(JORMContext*);`
// declarations into implicit virtual overrides whose definitions are #if DEBUG-gated; every
// instantiated one then fails to link (missing vtable). Closure types shared with DEBUG TUs
// either declare their own unconditional virtuals (vptr in all TUs anyway) or add a
// PARTIAL_DEBUG-only virtual dtor for vptr parity (see dAttParam_c).
class JOREventListener { class JOREventListener {
public: public:
#if DEBUG #if DEBUG
JOREventListener() {} JOREventListener() {}
#if TARGET_PC
virtual void listenPropertyEvent(const JORPropertyEvent*) {}
#else
virtual void listenPropertyEvent(const JORPropertyEvent*) = 0; virtual void listenPropertyEvent(const JORPropertyEvent*) = 0;
#endif #endif
#endif
}; };
class JORReflexible : public JOREventListener { class JORReflexible : public JOREventListener {
@@ -41,11 +30,7 @@ public:
virtual void listenPropertyEvent(const JORPropertyEvent*); virtual void listenPropertyEvent(const JORPropertyEvent*);
virtual void listen(u32, const JOREvent*); virtual void listen(u32, const JOREvent*);
virtual void genObjectInfo(const JORGenEvent*); virtual void genObjectInfo(const JORGenEvent*);
#if TARGET_PC
virtual void genMessage(JORMContext*) {}
#else
virtual void genMessage(JORMContext*) = 0; virtual void genMessage(JORMContext*) = 0;
#endif
virtual void listenNodeEvent(const JORNodeEvent*); virtual void listenNodeEvent(const JORNodeEvent*);
#endif #endif
}; };
@@ -314,7 +314,7 @@ public:
> >
{ {
TIterator_data_(const TFunctionValue_list_parameter& rParent, const f32* value) { TIterator_data_(const TFunctionValue_list_parameter& rParent, const f32* value) {
#if PARTIAL_DEBUG || DEBUG #if DEBUG
pOwn_ = &rParent; pOwn_ = &rParent;
#endif #endif
pf_ = value; pf_ = value;
@@ -372,7 +372,7 @@ public:
return (r1.pf_ - r2.pf_) / suData_size; return (r1.pf_ - r2.pf_) / suData_size;
} }
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x00 */ const TFunctionValue_list_parameter* pOwn_; /* 0x00 */ const TFunctionValue_list_parameter* pOwn_;
#endif #endif
/* 0x00 */ const f32* pf_; /* 0x00 */ const f32* pf_;
@@ -425,7 +425,7 @@ public:
> >
{ {
TIterator_data_(const TFunctionValue_hermite& rParent, const f32* value) { TIterator_data_(const TFunctionValue_hermite& rParent, const f32* value) {
#if PARTIAL_DEBUG || DEBUG #if DEBUG
pOwn_ = &rParent; pOwn_ = &rParent;
#endif #endif
pf_ = value; pf_ = value;
@@ -491,7 +491,7 @@ public:
return (r1.pf_ - r2.pf_) / r1.uSize_; return (r1.pf_ - r2.pf_) / r1.uSize_;
} }
#if PARTIAL_DEBUG || DEBUG #if DEBUG
/* 0x00 */ const TFunctionValue_hermite* pOwn_; /* 0x00 */ const TFunctionValue_hermite* pOwn_;
/* 0x04 */ const f32* pf_; /* 0x04 */ const f32* pf_;
/* 0x08 */ u32 uSize_; /* 0x08 */ u32 uSize_;
+1 -1
View File
@@ -22,7 +22,7 @@
#include "os_report.h" #include "os_report.h"
Z2SoundObjBase::Z2SoundObjBase() Z2SoundObjBase::Z2SoundObjBase()
#if PARTIAL_DEBUG || DEBUG #if DEBUG
: JSULink<Z2SoundObjBase>(this) : JSULink<Z2SoundObjBase>(this)
#endif #endif
{ {
+1 -1
View File
@@ -118,7 +118,7 @@ static int dKyeff_Create(kankyo_class* i_this) {
if (strcmp(dComIfGp_getStartStageName(), "Name") == 0) { if (strcmp(dComIfGp_getStartStageName(), "Name") == 0) {
camera_process_class* camera = dComIfGp_getCamera(0); camera_process_class* camera = dComIfGp_getCamera(0);
OSTime time = DUSK_IF_ELSE(OSGetSystemTime(), OSGetTime()); OSTime time = OSGetTime();
OSTicksToCalendarTime(time, &calendar); OSTicksToCalendarTime(time, &calendar);
g_env_light.global_wind_influence.vec.x = 1.0f; g_env_light.global_wind_influence.vec.x = 1.0f;
+1 -6
View File
@@ -1640,7 +1640,7 @@ void dMap_c::_move(f32 i_centerX, f32 i_centerZ, int i_roomNo, f32 param_3) {
mCenterX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -mPackX :) mPackX; mCenterX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -mPackX :) mPackX;
mCenterZ -= mPackZ; mCenterZ -= mPackZ;
mCenterX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -field_0x64 : ) field_0x64; mCenterX += field_0x64;
mCenterZ += mPackPlusZ; mCenterZ += mPackPlusZ;
} }
@@ -1649,8 +1649,6 @@ void dMap_c::_move(f32 i_centerX, f32 i_centerZ, int i_roomNo, f32 param_3) {
{ {
#if DEBUG #if DEBUG
field_0x64 = 33830.0f; field_0x64 = 33830.0f;
#elif TARGET_PC
field_0x64 = dusk::getSettings().game.enableMirrorMode ? 33830.0f : 0.0f;
#else #else
field_0x64 = 0.0f; field_0x64 = 0.0f;
#endif #endif
@@ -1659,9 +1657,6 @@ void dMap_c::_move(f32 i_centerX, f32 i_centerZ, int i_roomNo, f32 param_3) {
f32 temp = (field_0x58 * (f32)(field_0x74 + 4)) * 0.5f; f32 temp = (field_0x58 * (f32)(field_0x74 + 4)) * 0.5f;
#if DEBUG #if DEBUG
mRightEdgePlus = -(((dMpath_c::getMinZ() - (-127103.67f)) - temp) / field_0x58); mRightEdgePlus = -(((dMpath_c::getMinZ() - (-127103.67f)) - temp) / field_0x58);
#elif TARGET_PC
mRightEdgePlus = dusk::getSettings().game.enableMirrorMode ? -(((dMpath_c::getMinX() - (-127103.67f)) - temp) / field_0x58) : 0.0f;
#else #else
mRightEdgePlus = 0.0f; mRightEdgePlus = 0.0f;
#endif #endif
+1 -24
View File
@@ -914,20 +914,6 @@ void dMenu_DmapBg_c::dMapBgWide() {
void dMenu_DmapBg_c::draw() { void dMenu_DmapBg_c::draw() {
#if TARGET_PC #if TARGET_PC
dMapBgWide(); dMapBgWide();
static bool prevMirror = false; // default state of panes is not mirrored
if(prevMirror != dusk::getSettings().game.enableMirrorMode) {
if(dusk::getSettings().game.enableMirrorMode) {
static_cast<J2DPicture*>(mFloorScreen->search(MULTI_CHAR('rink')))->setMirror(J2DMirror_X);
static_cast<J2DPicture*>(mBaseScreen->search(MULTI_CHAR('map000')))->setMirror(J2DMirror_X);
}
else {
static_cast<J2DPicture*>(mFloorScreen->search(MULTI_CHAR('rink')))->setMirror(MIRROR0);
static_cast<J2DPicture*>(mBaseScreen->search(MULTI_CHAR('map000')))->setMirror(MIRROR0);
}
prevMirror = dusk::getSettings().game.enableMirrorMode;
}
#endif #endif
u32 scissor_left; u32 scissor_left;
@@ -974,15 +960,6 @@ void dMenu_DmapBg_c::draw() {
mpBackTexture->setAlpha(dVar17 * (field_0xdbc * field_0xd9c)); mpBackTexture->setAlpha(dVar17 * (field_0xdbc * field_0xd9c));
f32 local_28c = mpBackTexture->getBounds().i.x; f32 local_28c = mpBackTexture->getBounds().i.x;
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
CPaneMgr mgr;
Vec local_94 = mgr.getGlobalVtxCenter(mMapPane, true, 0);
local_28c = (local_94.x * 2.0f) - (local_28c + 0.5f * mpBackTexture->getWidth()) - 0.5f * mpBackTexture->getWidth();
}
#endif
mpBackTexture->setBlackWhite(color_black, color_white); mpBackTexture->setBlackWhite(color_black, color_white);
mpBackTexture->draw(local_28c, field_0xd94 + mpBackTexture->getBounds().i.y, mpBackTexture->getWidth(), mpBackTexture->draw(local_28c, field_0xd94 + mpBackTexture->getBounds().i.y, mpBackTexture->getWidth(),
mpBackTexture->getHeight(), mpBackTexture->getHeight(),
@@ -2004,7 +1981,7 @@ void dMenu_Dmap_c::mapControl() {
f32 temp_f28 = (var_f29 / 100.0f) * var_f31; f32 temp_f28 = (var_f29 / 100.0f) * var_f31;
f32 sp18 = temp_f28 * cM_ssin(stick_angle); f32 sp18 = temp_f28 * cM_ssin(stick_angle);
f32 sp14 = temp_f28 * cM_scos(stick_angle); f32 sp14 = temp_f28 * cM_scos(stick_angle);
mMapCtrl->setPlusZoomCenterX(IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -sp18 :) sp18); mMapCtrl->setPlusZoomCenterX(sp18);
mMapCtrl->setPlusZoomCenterZ(sp14); mMapCtrl->setPlusZoomCenterZ(sp14);
} }
+20 -1
View File
@@ -359,7 +359,14 @@ f32 dMenu_StageMapCtrl_c::getPixelStageSizeZ() const {
f32 dMenu_StageMapCtrl_c::getPixelCenterX() const { f32 dMenu_StageMapCtrl_c::getPixelCenterX() const {
f32 var_f31 = dMpath_c::getCenterX(); f32 var_f31 = dMpath_c::getCenterX();
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
return (1.0f / field_0xbc) * (field_0x9c + var_f31);
}
else return (1.0f / field_0xbc) * (field_0x9c - var_f31);
#else
return (1.0f / field_0xbc) * (field_0x9c - var_f31); return (1.0f / field_0xbc) * (field_0x9c - var_f31);
#endif
} }
f32 dMenu_StageMapCtrl_c::getPixelCenterZ() const { f32 dMenu_StageMapCtrl_c::getPixelCenterZ() const {
@@ -418,7 +425,18 @@ inline static f32 rightModeCnvPos(f32 param_0) {
void dMenu_StageMapCtrl_c::cnvPosTo2Dpos(f32 param_0, f32 param_1, f32* param_2, void dMenu_StageMapCtrl_c::cnvPosTo2Dpos(f32 param_0, f32 param_1, f32* param_2,
f32* param_3) const { f32* param_3) const {
if (param_2 != NULL) { if (param_2 != NULL) {
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
*param_2 =
(0.5f * field_0x94) + rightModeCnvPos((1.0f / field_0xbc) * (field_0x9c + param_0));
} else {
*param_2 =
(0.5f * field_0x94) + rightModeCnvPos((1.0f / field_0xbc) * (param_0 - field_0x9c));
}
#else
*param_2 = (0.5f * field_0x94) + rightModeCnvPos((1.0f / field_0xbc) * (param_0 - field_0x9c)); *param_2 = (0.5f * field_0x94) + rightModeCnvPos((1.0f / field_0xbc) * (param_0 - field_0x9c));
#endif
} }
if (param_3 != NULL) { if (param_3 != NULL) {
@@ -915,7 +933,8 @@ void dMenu_StageMapCtrl_c::move() {
void dMenu_DmapMapCtrl_c::draw() { void dMenu_DmapMapCtrl_c::draw() {
if (field_0xef != 0) { if (field_0xef != 0) {
setPos(field_0xeb, field_0xec, field_0x9c, setPos(field_0xeb, field_0xec,
IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -field_0x9c :) field_0x9c,
field_0xa0, field_0xbc, true, field_0xd8); field_0xa0, field_0xbc, true, field_0xd8);
} }
} }
+15 -10
View File
@@ -931,8 +931,17 @@ void dMenu_Fmap_c::region_map_proc() {
mpDraw2DBack->regionMapMove(mpStick); mpDraw2DBack->regionMapMove(mpStick);
int stage_no, room_no; int stage_no, room_no;
#if TARGET_PC
f32 arrow_pos_x = mpDraw2DBack->getArrowPos2DX();
if (dusk::getSettings().game.enableMirrorMode) {
arrow_pos_x = mpDraw2DBack->getMirrorPosX(arrow_pos_x, 0.0f);
}
f32 pos_x = arrow_pos_x - mDoGph_gInf_c::getMinXF() - mDoGph_gInf_c::getWidthF() * 0.5f;
#else
f32 pos_x = mpDraw2DBack->getArrowPos2DX() - mDoGph_gInf_c::getMinXF() f32 pos_x = mpDraw2DBack->getArrowPos2DX() - mDoGph_gInf_c::getMinXF()
- mDoGph_gInf_c::getWidthF() * 0.5f; - mDoGph_gInf_c::getWidthF() * 0.5f;
#endif
f32 pos_y = mpDraw2DBack->getArrowPos2DY() - mDoGph_gInf_c::getHeightF() * 0.5f; f32 pos_y = mpDraw2DBack->getArrowPos2DY() - mDoGph_gInf_c::getHeightF() * 0.5f;
mpMenuFmapMap->getPointStagePathInnerNo(getNowFmapRegionData(), pos_x, pos_y, mpMenuFmapMap->getPointStagePathInnerNo(getNowFmapRegionData(), pos_x, pos_y,
@@ -2477,6 +2486,12 @@ void dMenu_Fmap_c::portalWarpMapMove(STControl* i_stick) {
f32 arrow_y = mpDraw2DBack->getArrowPos2DY(); f32 arrow_y = mpDraw2DBack->getArrowPos2DY();
u8 uVar6 = 0xff; u8 uVar6 = 0xff;
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
arrow_x = mpDraw2DBack->getMirrorPosX(arrow_x, 0.0f);
}
#endif
for (int i = 0; i < portal_dat->mCount; i++) { for (int i = 0; i < portal_dat->mCount; i++) {
if (portals[i].mRegionNo == mpDraw2DBack->getRegionCursor() + 1 if (portals[i].mRegionNo == mpDraw2DBack->getRegionCursor() + 1
@@ -2546,11 +2561,6 @@ void dMenu_Fmap_c::drawIcon(f32 param_0, bool param_1) {
if (mProcess == PROC_PORTAL_DEMO1) { if (mProcess == PROC_PORTAL_DEMO1) {
is_portal_demo1 = 1; is_portal_demo1 = 1;
} }
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
angle = 0x10000 - angle;
}
#endif
mpDraw2DBack->setIcon2DPos(0x11, stage_name, pos.x, pos.z, cM_sht2d(angle), mpDraw2DBack->setIcon2DPos(0x11, stage_name, pos.x, pos.z, cM_sht2d(angle),
is_portal_demo1, param_1); is_portal_demo1, param_1);
@@ -2639,11 +2649,6 @@ void dMenu_Fmap_c::drawPlayEnterIcon() {
angle = dComIfGs_getPlayerFieldLastStayAngleY(); angle = dComIfGs_getPlayerFieldLastStayAngleY();
SAFE_STRCPY(stage_name, dComIfGs_getPlayerFieldLastStayName()); SAFE_STRCPY(stage_name, dComIfGs_getPlayerFieldLastStayName());
} }
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
angle = 0x10000 - angle;
}
#endif
mpDraw2DBack->setIcon2DPos(0x15, stage_name, pos.x, pos.z, cM_sht2d(angle), 0, false); mpDraw2DBack->setIcon2DPos(0x15, stage_name, pos.x, pos.z, cM_sht2d(angle), 0, false);
} }
} }
+17 -63
View File
@@ -1013,6 +1013,11 @@ void dMenu_Fmap2DBack_c::allmap_move2(STControl* param_0) {
f32 stickValue = param_0->getValueStick(); f32 stickValue = param_0->getValueStick();
if (stickValue >= spC) { if (stickValue >= spC) {
s16 angle = param_0->getAngleStick(); s16 angle = param_0->getAngleStick();
#ifdef TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
angle = -angle;
}
#endif
f32 local_68 = (mTexMaxX - mTexMinX); f32 local_68 = (mTexMaxX - mTexMinX);
f32 zoomRate = local_68 / getAllMapZoomRate(); f32 zoomRate = local_68 / getAllMapZoomRate();
f32 sp24; f32 sp24;
@@ -1026,11 +1031,6 @@ void dMenu_Fmap2DBack_c::allmap_move2(STControl* param_0) {
f32 delta_y = speed * cM_ssin(angle); f32 delta_y = speed * cM_ssin(angle);
f32 delta_x = speed * cM_scos(angle); f32 delta_x = speed * cM_scos(angle);
#ifdef TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
delta_y = -delta_y;
}
#endif
control_xpos = control_xpos + delta_y; control_xpos = control_xpos + delta_y;
control_ypos = control_ypos + delta_x; control_ypos = control_ypos + delta_x;
} }
@@ -1473,12 +1473,6 @@ void dMenu_Fmap2DBack_c::worldGridDraw() {
f32 dVar8 = -mStageTransZ; f32 dVar8 = -mStageTransZ;
calcAllMapPos2D(dVar9, dVar8, &local_74, &local_78); calcAllMapPos2D(dVar9, dVar8, &local_74, &local_78);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_74 = getMirrorPosX(local_74, 0.0f);
}
#endif
J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74, J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74,
mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(), mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(),
JUtility::TColor(255, 255, 255, 255), 6); JUtility::TColor(255, 255, 255, 255), 6);
@@ -1487,11 +1481,6 @@ void dMenu_Fmap2DBack_c::worldGridDraw() {
while (true) { while (true) {
calcAllMapPos2D(xPos, dVar8, &local_74, &local_78); calcAllMapPos2D(xPos, dVar8, &local_74, &local_78);
if (local_74 >= getMapScissorAreaLX()) { if (local_74 >= getMapScissorAreaLX()) {
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_74 = getMirrorPosX(local_74, 0.0f);
}
#endif
J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74, J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74,
mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(), mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(),
JUtility::TColor(255, 255, 255, 255), 6); JUtility::TColor(255, 255, 255, 255), 6);
@@ -1553,12 +1542,6 @@ void dMenu_Fmap2DBack_c::regionGridDraw() {
f32 dVar8 = mRegionOriginZ[mRegionCursor] - mStageTransZ; f32 dVar8 = mRegionOriginZ[mRegionCursor] - mStageTransZ;
calcAllMapPos2D(dVar9, dVar8, &local_74, &local_78); calcAllMapPos2D(dVar9, dVar8, &local_74, &local_78);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_74 = getMirrorPosX(local_74, 0.0f);
}
#endif
J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74, J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74,
mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(), mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(),
JUtility::TColor(180, 0, 0, 255), 6); JUtility::TColor(180, 0, 0, 255), 6);
@@ -1567,12 +1550,6 @@ void dMenu_Fmap2DBack_c::regionGridDraw() {
while (true) { while (true) {
calcAllMapPos2D(xPos, dVar8, &local_74, &local_78); calcAllMapPos2D(xPos, dVar8, &local_74, &local_78);
if (local_74 >= getMapScissorAreaLX()) { if (local_74 >= getMapScissorAreaLX()) {
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_74 = getMirrorPosX(local_74, 0.0f);
}
#endif
J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74, J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74,
mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(), mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(),
JUtility::TColor(180, 0, 0, 255), 6); JUtility::TColor(180, 0, 0, 255), 6);
@@ -1635,12 +1612,6 @@ void dMenu_Fmap2DBack_c::worldOriginDraw() {
f32 local_44, local_48; f32 local_44, local_48;
calcAllMapPos2D(-mStageTransX, -mStageTransZ, &local_44, &local_48); calcAllMapPos2D(-mStageTransX, -mStageTransZ, &local_44, &local_48);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_44 = getMirrorPosX(local_44, 0.0f);
}
#endif
J2DDrawLine(mDoGph_gInf_c::getMinXF(), local_48 - local_44 + mDoGph_gInf_c::getMinXF(), J2DDrawLine(mDoGph_gInf_c::getMinXF(), local_48 - local_44 + mDoGph_gInf_c::getMinXF(),
mDoGph_gInf_c::getMinXF() + mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getMinXF() + mDoGph_gInf_c::getWidthF(),
local_48 - local_44 + (mDoGph_gInf_c::getMinXF() + mDoGph_gInf_c::getWidthF()), local_48 - local_44 + (mDoGph_gInf_c::getMinXF() + mDoGph_gInf_c::getWidthF()),
@@ -1675,13 +1646,6 @@ void dMenu_Fmap2DBack_c::scrollAreaDraw() {
calcAllMapPos2D(x_min - mStageTransX, z_min - mStageTransZ, &local_4c, &local_50); calcAllMapPos2D(x_min - mStageTransX, z_min - mStageTransZ, &local_4c, &local_50);
calcAllMapPos2D(x_max - mStageTransX, z_max - mStageTransZ, &local_54, &local_58); calcAllMapPos2D(x_max - mStageTransX, z_max - mStageTransZ, &local_54, &local_58);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_4c = getMirrorPosX(local_4c, 0.0f);
local_54 = getMirrorPosX(local_54, 0.0f);
}
#endif
J2DDrawLine(local_4c, local_50, local_4c, local_58, J2DDrawLine(local_4c, local_50, local_4c, local_58,
JUtility::TColor(255, 255, 255, 255), 6); JUtility::TColor(255, 255, 255, 255), 6);
J2DDrawLine(local_54, local_50, local_54, local_58, J2DDrawLine(local_54, local_50, local_54, local_58,
@@ -1702,11 +1666,6 @@ void dMenu_Fmap2DBack_c::regionOriginDraw() {
f32 center_x, center_y; f32 center_x, center_y;
calcAllMapPos2D(mRegionOriginX[i] - mStageTransX, mRegionOriginZ[i] - mStageTransZ, calcAllMapPos2D(mRegionOriginX[i] - mStageTransX, mRegionOriginZ[i] - mStageTransZ,
&center_x, &center_y); &center_x, &center_y);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
center_x = getMirrorPosX(center_x - 3.0f, 3.0f);
}
#endif
J2DFillBox(center_x - 3.0f, center_y - 3.0f, 6.0f, 6.0f, JUtility::TColor(255, 0, 0, 255)); J2DFillBox(center_x - 3.0f, center_y - 3.0f, 6.0f, 6.0f, JUtility::TColor(255, 0, 0, 255));
} }
} }
@@ -1724,11 +1683,6 @@ void dMenu_Fmap2DBack_c::stageOriginDraw() {
f32 v1 = mRegionOriginX[mRegionCursor] + stage_data[i].mOffsetX - mStageTransX; f32 v1 = mRegionOriginX[mRegionCursor] + stage_data[i].mOffsetX - mStageTransX;
f32 v2 = mRegionOriginZ[mRegionCursor] + stage_data[i].mOffsetZ - mStageTransZ; f32 v2 = mRegionOriginZ[mRegionCursor] + stage_data[i].mOffsetZ - mStageTransZ;
calcAllMapPos2D(v1, v2, &center_x, &center_y); calcAllMapPos2D(v1, v2, &center_x, &center_y);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
center_x = getMirrorPosX(center_x - 3.0f, 3.0f);
}
#endif
J2DFillBox(center_x - 3.0f, center_y - 3.0f, 6.0f, 6.0f, J2DFillBox(center_x - 3.0f, center_y - 3.0f, 6.0f, 6.0f,
JUtility::TColor(0, 0, 255, 255)); JUtility::TColor(0, 0, 255, 255));
} }
@@ -1961,6 +1915,11 @@ void dMenu_Fmap2DBack_c::regionMapMove(STControl* i_stick) {
f32 stick_value = i_stick->getValueStick(); f32 stick_value = i_stick->getValueStick();
if (stick_value >= slow_bound) { if (stick_value >= slow_bound) {
s16 angle = i_stick->getAngleStick(); s16 angle = i_stick->getAngleStick();
#ifdef TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
angle = -angle;
}
#endif
f32 local_68 = mTexMaxX - mTexMinX; f32 local_68 = mTexMaxX - mTexMinX;
f32 spot_zoom = getSpotMapZoomRate(); f32 spot_zoom = getSpotMapZoomRate();
f32 region_zoom = getRegionMapZoomRate(mRegionCursor); f32 region_zoom = getRegionMapZoomRate(mRegionCursor);
@@ -1975,7 +1934,7 @@ void dMenu_Fmap2DBack_c::regionMapMove(STControl* i_stick) {
f32 speed = base_speed / 100.0f * local_78; f32 speed = base_speed / 100.0f * local_78;
f32 speed_y = speed * cM_ssin(angle); f32 speed_y = speed * cM_ssin(angle);
f32 speed_x = speed * cM_scos(angle); f32 speed_x = speed * cM_scos(angle);
control_xpos += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -speed_y :) speed_y; control_xpos += speed_y;
control_ypos += speed_x; control_ypos += speed_x;
} }
} }
@@ -2031,6 +1990,11 @@ void dMenu_Fmap2DBack_c::stageMapMove(STControl* i_stick, u8 param_1, bool param
if (stick_value >= slow_bound && param_2 && field_0x1238 != 2) { if (stick_value >= slow_bound && param_2 && field_0x1238 != 2) {
bVar6 = true; bVar6 = true;
s16 angle = i_stick->getAngleStick(); s16 angle = i_stick->getAngleStick();
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
angle = -angle;
}
#endif
f32 local_68 = mTexMaxX - mTexMinX; f32 local_68 = mTexMaxX - mTexMinX;
f32 spot_zoom = getSpotMapZoomRate(); f32 spot_zoom = getSpotMapZoomRate();
f32 region_zoom = getRegionMapZoomRate(mRegionCursor); f32 region_zoom = getRegionMapZoomRate(mRegionCursor);
@@ -2045,7 +2009,7 @@ void dMenu_Fmap2DBack_c::stageMapMove(STControl* i_stick, u8 param_1, bool param
f32 speed = base_speed / 100.0f * local_78; f32 speed = base_speed / 100.0f * local_78;
f32 speed_x = speed * cM_ssin(angle); f32 speed_x = speed * cM_ssin(angle);
f32 speed_z = speed * cM_scos(angle); f32 speed_z = speed * cM_scos(angle);
mStageTransX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -speed_x :) speed_x; mStageTransX += speed_x;
mStageTransZ += speed_z; mStageTransZ += speed_z;
} else if (!param_2) { } else if (!param_2) {
return; return;
@@ -2139,11 +2103,6 @@ void dMenu_Fmap2DBack_c::drawDebugStageArea() {
if (stage_no >= 0) { if (stage_no >= 0) {
f32 v = i + mDoGph_gInf_c::getMinXF(); f32 v = i + mDoGph_gInf_c::getMinXF();
f32 v2 = j; f32 v2 = j;
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
v = getMirrorPosX(v - 3.0f, 3.0f);
}
#endif
J2DFillBox(v - 3.0f, v2 - 3.0f, 6.0f, 6.0f, colors[stage_no % 6]); J2DFillBox(v - 3.0f, v2 - 3.0f, 6.0f, 6.0f, colors[stage_no % 6]);
} }
} }
@@ -2179,11 +2138,6 @@ void dMenu_Fmap2DBack_c::drawDebugRegionArea() {
mRegionMapSizeX[region] * mZoom, mRegionMapSizeY[region] * mZoom, mRegionMapSizeX[region] * mZoom, mRegionMapSizeY[region] * mZoom,
mpAreaTex[region]->getTexture(0)->getTexInfo()); mpAreaTex[region]->getTexture(0)->getTexInfo());
if (u) { if (u) {
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
pos_x = getMirrorPosX(pos_x - 3.0f, 3.0f);
}
#endif
J2DFillBox(pos_x - 3.0f, pos_y - 3.0f, 6.0f, 6.0f, colors[region]); J2DFillBox(pos_x - 3.0f, pos_y - 3.0f, 6.0f, 6.0f, colors[region]);
break; break;
} }
+15 -7
View File
@@ -394,8 +394,21 @@ void dMenuMapCommon_c::drawIcon(f32 i_posX, f32 i_posY, f32 param_3, f32 param_4
icon_size_y *= _c7c; icon_size_y *= _c7c;
} }
#if TARGET_PC
f32 rotation = mIconInfo[info_idx].rotation;
if (dusk::getSettings().game.enableMirrorMode &&
(mIconInfo[info_idx].icon_no == ICON_LINK_e ||
mIconInfo[info_idx].icon_no == ICON_LINK_ENTER_e))
{
rotation = -rotation;
}
mPictures[mIconInfo[info_idx].icon_no]->rotate(icon_size_x / 2, icon_size_y / 2, ROTATE_Z,
rotation);
#else
mPictures[mIconInfo[info_idx].icon_no]->rotate(icon_size_x / 2, icon_size_y / 2, ROTATE_Z, mPictures[mIconInfo[info_idx].icon_no]->rotate(icon_size_x / 2, icon_size_y / 2, ROTATE_Z,
mIconInfo[info_idx].rotation); mIconInfo[info_idx].rotation);
#endif
if (mIconInfo[info_idx].icon_no == ICON_LIGHT_DROP_e) { if (mIconInfo[info_idx].icon_no == ICON_LIGHT_DROP_e) {
mPictures[mIconInfo[info_idx].icon_no]->setAlpha((180.0f * _c80) / 255.0f); mPictures[mIconInfo[info_idx].icon_no]->setAlpha((180.0f * _c80) / 255.0f);
@@ -410,15 +423,10 @@ void dMenuMapCommon_c::drawIcon(f32 i_posX, f32 i_posY, f32 param_3, f32 param_4
} }
f32 pos_x = i_posX + (icon_pos_x - (icon_size_x / 2)); f32 pos_x = i_posX + (icon_pos_x - (icon_size_x / 2));
bool r4 = false;
#if TARGET_PC #if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) { if (dusk::getSettings().game.enableMirrorMode) {
pos_x = getMirrorCenterPosX(i_posX + (icon_pos_x - (icon_size_x / 2)), icon_size_x / 2); pos_x = getMirrorCenterPosX(i_posX + (icon_pos_x - (icon_size_x / 2)), icon_size_x / 2);
} }
if(mIconInfo[info_idx].icon_no == ICON_GOLD_WOLF_e) {
r4 = true;
}
#endif #endif
mPictures[mIconInfo[info_idx].icon_no]->draw(pos_x, (i_posY + (icon_pos_y - icon_size_y / 2)), mPictures[mIconInfo[info_idx].icon_no]->draw(pos_x, (i_posY + (icon_pos_y - icon_size_y / 2)),
@@ -427,7 +435,7 @@ void dMenuMapCommon_c::drawIcon(f32 i_posX, f32 i_posY, f32 param_3, f32 param_4
if (mIconInfo[info_idx].icon_no == ICON_LIGHT_DROP_e) { if (mIconInfo[info_idx].icon_no == ICON_LIGHT_DROP_e) {
mLightDropPic->draw((pos_x + (icon_size_x / 2)) - (var_f29 / 2), mLightDropPic->draw((pos_x + (icon_size_x / 2)) - (var_f29 / 2),
((icon_size_y / 2) + (i_posY + (icon_pos_y - icon_size_y / 2))) - (var_f28 / 2), ((icon_size_y / 2) + (i_posY + (icon_pos_y - icon_size_y / 2))) - (var_f28 / 2),
var_f29, var_f28, r4, false, false); var_f29, var_f28, false, false, false);
} }
} }
} }
@@ -861,4 +869,4 @@ void dMenuMapCommon_c::getFmapPoeCount(const int regionNo, int& nowCount, int& t
} }
} }
} }
#endif #endif
+11
View File
@@ -428,6 +428,17 @@ static void dummyStrings() {
dMsgObject_HIO_c g_MsgObject_HIO_c; dMsgObject_HIO_c g_MsgObject_HIO_c;
int dMsgObject_c::_execute() { int dMsgObject_c::_execute() {
// TODO: enabling wii message overrides fixes direction text, but gives wrong item control text
/*#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
// enable wii message index override
g_MsgObject_HIO_c.mMessageDisplay = 1;
} else if (!dusk::getSettings().game.enableMirrorMode && g_MsgObject_HIO_c.mMessageDisplay == 1) {
g_MsgObject_HIO_c.mMessageDisplay = 0;
}
#endif*/
field_0x4c7 = 0; field_0x4c7 = 0;
if (mpTalkHeap != NULL) { if (mpTalkHeap != NULL) {
field_0x148 = mDoExt_setCurrentHeap(mpTalkHeap); field_0x148 = mDoExt_setCurrentHeap(mpTalkHeap);
+1 -1
View File
@@ -1823,7 +1823,7 @@ int dSv_info_c::memory_to_card(char* card_ptr, int dataNum) {
savedata->getPlayer().getPlayerInfo().setTotalTime(play_time); savedata->getPlayer().getPlayerInfo().setTotalTime(play_time);
} }
savedata->getPlayer().getPlayerStatusB().setDateIpl(DUSK_IF_ELSE(OSGetSystemTime(), OSGetTime())); savedata->getPlayer().getPlayerStatusB().setDateIpl(OSGetTime());
memcpy(card_ptr, savedata, sizeof(dSv_save_c)); memcpy(card_ptr, savedata, sizeof(dSv_save_c));
card_ptr += 0x958; card_ptr += 0x958;
+151 -280
View File
@@ -7,7 +7,6 @@
#include "dusk/io.hpp" #include "dusk/io.hpp"
#include "dusk/settings.h" #include "dusk/settings.h"
#include <algorithm>
#include <cmath> #include <cmath>
#include <filesystem> #include <filesystem>
#include <limits> #include <limits>
@@ -16,90 +15,77 @@
#include <string_view> #include <string_view>
#include <system_error> #include <system_error>
#include <utility> #include <utility>
#include <vector>
#include "dusk/action_bindings.h" #include "dusk/action_bindings.h"
#include "dusk/logging.h"
#include "dusk/main.h" #include "dusk/main.h"
namespace dusk::config { using namespace dusk::config;
namespace {
constexpr auto ConfigFileName = "config.json"; constexpr auto ConfigFileName = "config.json";
using json = nlohmann::json; using json = nlohmann::json;
aurora::Module DuskConfigLog("dusk::config"); aurora::Module DuskConfigLog("dusk::config");
absl::flat_hash_map<std::string, ConfigVarBase*> RegisteredConfigVars; static absl::flat_hash_map<std::string_view, ConfigVarBase*> RegisteredConfigVars;
absl::flat_hash_map<std::string, nlohmann::json> UnregisteredConfigVars; static bool RegistrationDone = false;
absl::flat_hash_map<std::string, std::string> UnregisteredConfigVarOverrides;
struct ChangeSubscription { static std::optional<dusk::ui::ControlAnchor> parse_control_anchor(std::string_view value) {
Subscription token;
ChangeCallback callback;
};
absl::flat_hash_map<std::string, std::vector<ChangeSubscription> > s_changeSubscriptions;
absl::flat_hash_map<Subscription, std::string> s_changeTokenNames;
Subscription s_nextChangeToken = 1;
// Names currently being notified; guards against a callback re-notifying its own CVar.
std::vector<std::string> s_activeChangeNotifications;
std::optional<ui::ControlAnchor> parse_control_anchor(std::string_view value) {
if (value == "none") { if (value == "none") {
return ui::ControlAnchor::None; return dusk::ui::ControlAnchor::None;
} }
if (value == "top") { if (value == "top") {
return ui::ControlAnchor::Top; return dusk::ui::ControlAnchor::Top;
} }
if (value == "left") { if (value == "left") {
return ui::ControlAnchor::Left; return dusk::ui::ControlAnchor::Left;
} }
if (value == "bottom") { if (value == "bottom") {
return ui::ControlAnchor::Bottom; return dusk::ui::ControlAnchor::Bottom;
} }
if (value == "right") { if (value == "right") {
return ui::ControlAnchor::Right; return dusk::ui::ControlAnchor::Right;
} }
if (value == "topLeft") { if (value == "topLeft") {
return ui::ControlAnchor::TopLeft; return dusk::ui::ControlAnchor::TopLeft;
} }
if (value == "topRight") { if (value == "topRight") {
return ui::ControlAnchor::TopRight; return dusk::ui::ControlAnchor::TopRight;
} }
if (value == "bottomLeft") { if (value == "bottomLeft") {
return ui::ControlAnchor::BottomLeft; return dusk::ui::ControlAnchor::BottomLeft;
} }
if (value == "bottomRight") { if (value == "bottomRight") {
return ui::ControlAnchor::BottomRight; return dusk::ui::ControlAnchor::BottomRight;
} }
return std::nullopt; return std::nullopt;
} }
const char* control_anchor_value(ui::ControlAnchor anchor) { static const char* control_anchor_value(dusk::ui::ControlAnchor anchor) {
switch (anchor) { switch (anchor) {
case ui::ControlAnchor::None: case dusk::ui::ControlAnchor::None:
return "none"; return "none";
case ui::ControlAnchor::Top: case dusk::ui::ControlAnchor::Top:
return "top"; return "top";
case ui::ControlAnchor::Left: case dusk::ui::ControlAnchor::Left:
return "left"; return "left";
case ui::ControlAnchor::Bottom: case dusk::ui::ControlAnchor::Bottom:
return "bottom"; return "bottom";
case ui::ControlAnchor::Right: case dusk::ui::ControlAnchor::Right:
return "right"; return "right";
case ui::ControlAnchor::TopLeft: case dusk::ui::ControlAnchor::TopLeft:
return "topLeft"; return "topLeft";
case ui::ControlAnchor::TopRight: case dusk::ui::ControlAnchor::TopRight:
return "topRight"; return "topRight";
case ui::ControlAnchor::BottomLeft: case dusk::ui::ControlAnchor::BottomLeft:
return "bottomLeft"; return "bottomLeft";
case ui::ControlAnchor::BottomRight: case dusk::ui::ControlAnchor::BottomRight:
return "bottomRight"; return "bottomRight";
} }
return "none"; return "none";
} }
std::optional<float> json_finite_float(const json& object, const char* key) { static std::optional<float> json_finite_float(const json& object, const char* key) {
const auto iter = object.find(key); const auto iter = object.find(key);
if (iter == object.end() || !iter->is_number()) { if (iter == object.end() || !iter->is_number()) {
return std::nullopt; return std::nullopt;
@@ -113,7 +99,7 @@ std::optional<float> json_finite_float(const json& object, const char* key) {
return value; return value;
} }
std::optional<ui::ControlProps> parse_control_props(const json& value) { static std::optional<dusk::ui::ControlProps> parse_control_props(const json& value) {
if (!value.is_object()) { if (!value.is_object()) {
return std::nullopt; return std::nullopt;
} }
@@ -132,7 +118,7 @@ std::optional<ui::ControlProps> parse_control_props(const json& value) {
if (!anchor || *w <= 0.0f || *h <= 0.0f || *scale <= 0.0f) { if (!anchor || *w <= 0.0f || *h <= 0.0f || *scale <= 0.0f) {
return std::nullopt; return std::nullopt;
} }
return ui::ControlProps{ return dusk::ui::ControlProps{
.x = *x, .x = *x,
.y = *y, .y = *y,
.w = *w, .w = *w,
@@ -142,17 +128,17 @@ std::optional<ui::ControlProps> parse_control_props(const json& value) {
}; };
} }
std::filesystem::path GetConfigJsonPath() { static std::filesystem::path GetConfigJsonPath() {
return ConfigPath / ConfigFileName; return dusk::ConfigPath / ConfigFileName;
} }
std::filesystem::path GetTempConfigJsonPath(const std::filesystem::path& configJsonPath) { static std::filesystem::path GetTempConfigJsonPath(const std::filesystem::path& configJsonPath) {
auto tempPath = configJsonPath; auto tempPath = configJsonPath;
tempPath.replace_filename(fmt::format(".{}.tmp", configJsonPath.filename().string())); tempPath.replace_filename(fmt::format(".{}.tmp", configJsonPath.filename().string()));
return tempPath; return tempPath;
} }
void ReplaceFile(const std::filesystem::path& source, const std::filesystem::path& target) { static void ReplaceFile(const std::filesystem::path& source, const std::filesystem::path& target) {
std::error_code ec; std::error_code ec;
std::filesystem::rename(source, target, ec); std::filesystem::rename(source, target, ec);
if (ec) { if (ec) {
@@ -162,8 +148,19 @@ void ReplaceFile(const std::filesystem::path& source, const std::filesystem::pat
} }
} }
ConfigVarBase::ConfigVarBase(const char* name, const ConfigImplBase* impl)
: name(name), registered(false), layer(ConfigVarLayer::Default), impl(impl) {}
const char* ConfigVarBase::getName() const noexcept {
return name;
}
const ConfigImplBase* ConfigVarBase::getImpl() const noexcept {
return impl;
}
template <typename T> template <typename T>
T sanitizeEnumValue(const ConfigVar<T>& cVar, T value) { static T sanitizeEnumValue(const ConfigVar<T>& cVar, T value) {
if constexpr (std::is_enum_v<T>) { if constexpr (std::is_enum_v<T>) {
using Underlying = std::underlying_type_t<T>; using Underlying = std::underlying_type_t<T>;
const Underlying raw = static_cast<Underlying>(value); const Underlying raw = static_cast<Underlying>(value);
@@ -177,83 +174,6 @@ T sanitizeEnumValue(const ConfigVar<T>& cVar, T value) {
return value; return value;
} }
template <ConfigValue T>
requires std::is_integral_v<T>&& std::is_signed_v<T> T parse_arg_value(
const ConfigVar<T>&, const std::string_view stringValue) {
const std::string str(stringValue);
const auto result = std::stoll(str);
if (result >= std::numeric_limits<T>::min() && result <= std::numeric_limits<T>::max()) {
return static_cast<T>(result);
}
throw std::out_of_range("Value is too large");
}
template <ConfigValue T>
requires std::is_integral_v<T>&& std::is_unsigned_v<T> T parse_arg_value(
const ConfigVar<T>&, const std::string_view stringValue) {
const std::string str(stringValue);
const auto result = std::stoull(str);
if (result <= std::numeric_limits<T>::max()) {
return static_cast<T>(result);
}
throw std::out_of_range("Value is too large");
}
f32 parse_arg_value(const ConfigVar<f32>&, const std::string_view stringValue) {
const std::string str(stringValue);
return std::stof(str);
}
f64 parse_arg_value(const ConfigVar<f64>&, const std::string_view stringValue) {
const std::string str(stringValue);
return std::stod(str);
}
std::string parse_arg_value(const ConfigVar<std::string>&, const std::string_view stringValue) {
return std::string(stringValue);
}
template <ConfigValue T>
requires std::is_enum_v<T> T parse_arg_value(
const ConfigVar<T>& cVar, const std::string_view stringValue) {
using Underlying = std::underlying_type_t<T>;
const std::string str(stringValue);
if constexpr (std::is_signed_v<Underlying>) {
const auto result = std::stoll(str);
if (result >= std::numeric_limits<Underlying>::min() &&
result <= std::numeric_limits<Underlying>::max())
{
return sanitizeEnumValue(cVar, static_cast<T>(result));
}
throw std::out_of_range("Value is too large");
} else {
const auto result = std::stoull(str);
if (result <= std::numeric_limits<Underlying>::max()) {
return sanitizeEnumValue(cVar, static_cast<T>(result));
}
throw std::out_of_range("Value is too large");
}
}
} // namespace
ConfigVarBase::ConfigVarBase(std::string name, const ConfigImplBase* impl)
: name(std::move(name)), registered(false), layer(ConfigVarLayer::Default), impl(impl) {}
const char* ConfigVarBase::getName() const noexcept {
return name.c_str();
}
const ConfigImplBase* ConfigVarBase::getImpl() const noexcept {
return impl;
}
ConfigVarBase::~ConfigVarBase() {
if (registered) {
DuskLog.fatal("CVar '{}' was destroyed while still registered!", name);
}
}
template <ConfigValue T> template <ConfigValue T>
void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) { void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) {
if constexpr (std::is_enum_v<T>) { if constexpr (std::is_enum_v<T>) {
@@ -267,12 +187,12 @@ void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) {
const Underlying raw = b ? static_cast<Underlying>(1) : static_cast<Underlying>(0); const Underlying raw = b ? static_cast<Underlying>(1) : static_cast<Underlying>(0);
cVar.load_value(sanitizeEnumValue(cVar, static_cast<T>(raw))); cVar.setValue(sanitizeEnumValue(cVar, static_cast<T>(raw)), false);
return; return;
} }
} }
cVar.load_value(sanitizeEnumValue(cVar, jsonValue.get<T>())); cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<T>()), false);
} }
template <ConfigValue T> template <ConfigValue T>
@@ -280,9 +200,74 @@ nlohmann::json ConfigImpl<T>::dumpToJson(const ConfigVar<T>& cVar) {
return cVar.getValueForSave(); return cVar.getValueForSave();
} }
template <ConfigValue T>
requires std::is_integral_v<T>&& std::is_signed_v<T> static void loadFromArgImpl(
ConfigVar<T>& cVar, const std::string_view stringValue) {
const std::string str(stringValue);
const auto result = std::stoll(str);
if (result >= std::numeric_limits<T>::min() && result <= std::numeric_limits<T>::max()) {
cVar.setOverrideValue(result);
} else {
throw std::out_of_range("Value is too large");
}
}
template <ConfigValue T>
requires std::is_integral_v<T>&& std::is_unsigned_v<T> static void loadFromArgImpl(
ConfigVar<T>& cVar, const std::string_view stringValue) {
const std::string str(stringValue);
const auto result = std::stoull(str);
if (result <= std::numeric_limits<T>::max()) {
cVar.setOverrideValue(result);
} else {
throw std::out_of_range("Value is too large");
}
}
static void loadFromArgImpl(ConfigVar<f32>& cVar, const std::string_view stringValue) {
const std::string str(stringValue);
const auto result = std::stof(str);
cVar.setOverrideValue(result);
}
static void loadFromArgImpl(ConfigVar<f64>& cVar, const std::string_view stringValue) {
const std::string str(stringValue);
const auto result = std::stod(str);
cVar.setOverrideValue(result);
}
static void loadFromArgImpl(ConfigVar<std::string>& cVar, const std::string_view stringValue) {
cVar.setOverrideValue(std::string(stringValue));
}
template <ConfigValue T>
requires std::is_enum_v<T> static void loadFromArgImpl(
ConfigVar<T>& cVar, const std::string_view stringValue) {
using Underlying = std::underlying_type_t<T>;
const std::string str(stringValue);
if constexpr (std::is_signed_v<Underlying>) {
const auto result = std::stoll(str);
if (result >= std::numeric_limits<Underlying>::min() &&
result <= std::numeric_limits<Underlying>::max())
{
cVar.setOverrideValue(sanitizeEnumValue(cVar, static_cast<T>(result)));
} else {
throw std::out_of_range("Value is too large");
}
} else {
const auto result = std::stoull(str);
if (result <= std::numeric_limits<Underlying>::max()) {
cVar.setOverrideValue(sanitizeEnumValue(cVar, static_cast<T>(result)));
} else {
throw std::out_of_range("Value is too large");
}
}
}
template <ConfigValue T> template <ConfigValue T>
void ConfigImpl<T>::loadFromArg(ConfigVar<T>& cVar, const std::string_view stringValue) { void ConfigImpl<T>::loadFromArg(ConfigVar<T>& cVar, const std::string_view stringValue) {
cVar.load_override_value(parse_arg_value(cVar, stringValue)); loadFromArgImpl(cVar, stringValue);
} }
template <> template <>
@@ -290,16 +275,18 @@ void ConfigImpl<bool>::loadFromArg(ConfigVar<bool>& cVar, const std::string_view
if (stringValue == "1" || stringValue == "TRUE" || stringValue == "true" || if (stringValue == "1" || stringValue == "TRUE" || stringValue == "true" ||
stringValue == "True") stringValue == "True")
{ {
cVar.load_override_value(true); cVar.setOverrideValue(true);
} else if (stringValue == "0" || stringValue == "FALSE" || stringValue == "false" || } else if (stringValue == "0" || stringValue == "FALSE" || stringValue == "false" ||
stringValue == "False") stringValue == "False")
{ {
cVar.load_override_value(false); cVar.setOverrideValue(false);
} else { } else {
throw InvalidConfigError("Value cannot be parsed as boolean"); throw InvalidConfigError("Value cannot be parsed as boolean");
} }
} }
// My IDE is convinced this namespace is necessary. It shouldn't be AFAICT?
namespace dusk::config {
template class ConfigImpl<bool>; template class ConfigImpl<bool>;
template class ConfigImpl<s8>; template class ConfigImpl<s8>;
template class ConfigImpl<u8>; template class ConfigImpl<u8>;
@@ -312,10 +299,10 @@ template class ConfigImpl<u64>;
template class ConfigImpl<f32>; template class ConfigImpl<f32>;
template class ConfigImpl<f64>; template class ConfigImpl<f64>;
template class ConfigImpl<std::string>; template class ConfigImpl<std::string>;
template class ConfigImpl<BloomMode>; template class ConfigImpl<dusk::BloomMode>;
template class ConfigImpl<DepthOfFieldMode>; template class ConfigImpl<dusk::DepthOfFieldMode>;
template class ConfigImpl<DiscVerificationState>; template class ConfigImpl<dusk::DiscVerificationState>;
template class ConfigImpl<GameLanguage>; template class ConfigImpl<dusk::GameLanguage>;
template <> template <>
void ConfigImpl<FrameInterpMode>::loadFromJson( void ConfigImpl<FrameInterpMode>::loadFromJson(
@@ -325,11 +312,11 @@ void ConfigImpl<FrameInterpMode>::loadFromJson(
const FrameInterpMode mode = b ? FrameInterpMode::Unlimited : FrameInterpMode::Off; const FrameInterpMode mode = b ? FrameInterpMode::Unlimited : FrameInterpMode::Off;
cVar.load_value(sanitizeEnumValue(cVar, mode)); cVar.setValue(sanitizeEnumValue(cVar, mode), false);
return; return;
} }
cVar.load_value(sanitizeEnumValue(cVar, jsonValue.get<FrameInterpMode>())); cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<FrameInterpMode>()), false);
} }
template <> template <>
@@ -360,7 +347,7 @@ void ConfigImpl<ui::ControlLayout>::loadFromJson(
} }
} }
cVar.load_value(std::move(layout)); cVar.setValue(std::move(layout), false);
} }
template <> template <>
@@ -390,59 +377,26 @@ nlohmann::json ConfigImpl<ui::ControlLayout>::dumpToJson(const ConfigVar<ui::Con
}; };
} }
template class ConfigImpl<FrameInterpMode>; template class ConfigImpl<dusk::FrameInterpMode>;
template class ConfigImpl<TouchTargeting>; template class ConfigImpl<dusk::TouchTargeting>;
template class ConfigImpl<MenuScaling>; template class ConfigImpl<dusk::MenuScaling>;
template class ConfigImpl<Resampler>; template class ConfigImpl<dusk::Resampler>;
template class ConfigImpl<MagicArmorMode>; template class ConfigImpl<dusk::MagicArmorMode>;
template class ConfigImpl<ui::ControlLayout>; template class ConfigImpl<dusk::ui::ControlLayout>;
} // namespace dusk::config
void dusk::config::Register(ConfigVarBase& configVar) {
const auto& name = configVar.getName();
if (RegistrationDone) {
DuskConfigLog.fatal("Tried to register CVar {} after registrations closed!", name);
}
void Register(ConfigVarBase& configVar) {
const std::string_view name = configVar.getName();
if (RegisteredConfigVars.contains(name)) { if (RegisteredConfigVars.contains(name)) {
DuskConfigLog.fatal("Tried to register CVar {} twice!", name); DuskConfigLog.fatal("Tried to register CVar {} twice!", name);
} }
RegisteredConfigVars[name] = &configVar; RegisteredConfigVars[name] = &configVar;
configVar.markRegistered(); configVar.markRegistered();
const auto unregPair = UnregisteredConfigVars.find(name);
if (unregPair != UnregisteredConfigVars.end()) {
const auto value = std::move(unregPair->second);
UnregisteredConfigVars.erase(name);
try {
configVar.getImpl()->loadFromJson(configVar, value);
} catch (std::exception& e) {
DuskConfigLog.error("Failed to load key '{}' from config value: {}", name, e.what());
}
}
const auto overridePair = UnregisteredConfigVarOverrides.find(name);
if (overridePair != UnregisteredConfigVarOverrides.end()) {
try {
configVar.getImpl()->loadFromArg(configVar, overridePair->second);
} catch (std::exception& e) {
DuskConfigLog.error("Failed to load key '{}' from override arg: {}", name, e.what());
}
}
}
void unregister(ConfigVarBase& configVar) {
const std::string_view name = configVar.getName();
const auto it = RegisteredConfigVars.find(name);
if (it == RegisteredConfigVars.end() || it->second != &configVar) {
DuskConfigLog.fatal("Tried to unregister CVar '{}' that is not registered!", name);
}
const auto layer = configVar.getLayer();
if (layer == ConfigVarLayer::Value || layer == ConfigVarLayer::Speedrun) {
UnregisteredConfigVars.insert_or_assign(
std::string{name}, configVar.getImpl()->dumpToJson(configVar));
}
RegisteredConfigVars.erase(it);
configVar.unmarkRegistered();
} }
void ConfigVarBase::markRegistered() { void ConfigVarBase::markRegistered() {
@@ -452,24 +406,21 @@ void ConfigVarBase::markRegistered() {
registered = true; registered = true;
} }
void ConfigVarBase::unmarkRegistered() { void dusk::config::FinishRegistration() {
if (!registered) RegistrationDone = true;
abort();
registered = false;
} }
void load_from_user_preferences() { void dusk::config::LoadFromUserPreferences() {
const auto configJsonPath = GetConfigJsonPath(); const auto configJsonPath = GetConfigJsonPath();
if (configJsonPath.empty()) { if (configJsonPath.empty()) {
return; return;
} }
const auto configPathString = io::fs_path_to_string(configJsonPath); const auto configPathString = io::fs_path_to_string(configJsonPath);
load_from_file_name(configPathString.c_str()); LoadFromFileName(configPathString.c_str());
} }
static void LoadFromPath(const char* path) { static void LoadFromPath(const char* path) {
auto data = io::FileStream::ReadAllBytes(path); auto data = dusk::io::FileStream::ReadAllBytes(path);
json j = json::parse(data); json j = json::parse(data);
if (!j.is_object()) { if (!j.is_object()) {
@@ -477,16 +428,11 @@ static void LoadFromPath(const char* path) {
return; return;
} }
UnregisteredConfigVars.clear();
for (const auto& el : j.items()) { for (const auto& el : j.items()) {
const auto& key = el.key(); const auto& key = el.key();
auto configVar = RegisteredConfigVars.find(key); auto configVar = RegisteredConfigVars.find(key);
if (configVar == RegisteredConfigVars.end()) { if (configVar == RegisteredConfigVars.end()) {
DuskConfigLog.debug("Unknown key '{}' found in config! If this gets registered later, " DuskConfigLog.error("Unknown key '{}' found in config!", key);
"that's acceptable!",
key);
UnregisteredConfigVars.emplace(key, el.value());
continue; continue;
} }
@@ -498,7 +444,11 @@ static void LoadFromPath(const char* path) {
} }
} }
void load_from_file_name(const char* path) { void dusk::config::LoadFromFileName(const char* path) {
if (!RegistrationDone) {
DuskConfigLog.fatal("Registration not finished yet!");
}
DuskConfigLog.info("Loading config from '{}'", path); DuskConfigLog.info("Loading config from '{}'", path);
try { try {
@@ -516,21 +466,7 @@ void load_from_file_name(const char* path) {
} }
} }
void load_arg_override(std::string_view name, std::string_view value) { void dusk::config::Save() {
const auto cVar = GetConfigVar(name);
if (!cVar) {
UnregisteredConfigVarOverrides.emplace(name, value);
return;
}
try {
cVar->getImpl()->loadFromArg(*cVar, value);
} catch (const std::exception& e) {
DuskLog.fatal("Unable to parse: '{}': {}", value, e.what());
}
}
void save() {
const auto configJsonPath = GetConfigJsonPath(); const auto configJsonPath = GetConfigJsonPath();
if (configJsonPath.empty()) { if (configJsonPath.empty()) {
return; return;
@@ -548,10 +484,6 @@ void save() {
} }
} }
for (const auto& pair : UnregisteredConfigVars) {
j[pair.first] = pair.second;
}
try { try {
const auto tempConfigJsonPath = GetTempConfigJsonPath(configJsonPath); const auto tempConfigJsonPath = GetTempConfigJsonPath(configJsonPath);
io::FileStream::WriteAllText(tempConfigJsonPath, j.dump(4)); io::FileStream::WriteAllText(tempConfigJsonPath, j.dump(4));
@@ -561,14 +493,14 @@ void save() {
} }
} }
void ClearAllActionBindings(int port) { void dusk::config::ClearAllActionBindings(int port) {
for (auto& actionBinding : getActionBinds() | std::views::values) { for (auto& actionBinding : getActionBinds() | std::views::values) {
actionBinding.configVars->at(port).setValue(PAD_NATIVE_BUTTON_INVALID); actionBinding.configVars->at(port).setValue(PAD_NATIVE_BUTTON_INVALID);
} }
save(); Save();
} }
ConfigVarBase* GetConfigVar(std::string_view name) { ConfigVarBase* dusk::config::GetConfigVar(std::string_view name) {
const auto configVar = RegisteredConfigVars.find(name); const auto configVar = RegisteredConfigVars.find(name);
if (configVar != RegisteredConfigVars.end()) { if (configVar != RegisteredConfigVars.end()) {
return configVar->second; return configVar->second;
@@ -577,69 +509,8 @@ ConfigVarBase* GetConfigVar(std::string_view name) {
return nullptr; return nullptr;
} }
void EnumerateRegistered(std::function<void(ConfigVarBase&)> callback) { void dusk::config::EnumerateRegistered(std::function<void(ConfigVarBase&)> callback) {
for (auto& pair : RegisteredConfigVars) { for (auto& pair : RegisteredConfigVars) {
callback(*pair.second); callback(*pair.second);
} }
} }
Subscription subscribe(std::string_view name, ChangeCallback callback) {
const auto token = s_nextChangeToken++;
s_changeSubscriptions[std::string{name}].push_back({token, std::move(callback)});
s_changeTokenNames.emplace(token, std::string{name});
return token;
}
void unsubscribe(Subscription token) {
const auto nameIt = s_changeTokenNames.find(token);
if (nameIt == s_changeTokenNames.end()) {
DuskConfigLog.fatal("Tried to unsubscribe unknown change token {}!", token);
}
const auto subsIt = s_changeSubscriptions.find(nameIt->second);
auto& subscriptions = subsIt->second;
std::erase_if(
subscriptions, [token](const ChangeSubscription& sub) { return sub.token == token; });
if (subscriptions.empty()) {
s_changeSubscriptions.erase(subsIt);
}
s_changeTokenNames.erase(nameIt);
}
bool ConfigVarBase::has_subscribers() const {
return s_changeSubscriptions.contains(name);
}
void ConfigVarBase::notify_changed(const void* previousValue) {
const auto subsIt = s_changeSubscriptions.find(name);
if (subsIt == s_changeSubscriptions.end()) {
return;
}
if (std::ranges::find(s_activeChangeNotifications, name) != s_activeChangeNotifications.end()) {
DuskConfigLog.error("Recursive change notification for CVar '{}' suppressed", name);
return;
}
s_activeChangeNotifications.push_back(name);
// Copied so callbacks can subscribe/unsubscribe safely.
const auto subscriptions = subsIt->second;
for (const auto& sub : subscriptions) {
sub.callback(*this, previousValue);
}
s_activeChangeNotifications.pop_back();
}
void shutdown() {
for (auto& pair : RegisteredConfigVars) {
pair.second->unmarkRegistered();
}
RegisteredConfigVars.clear();
UnregisteredConfigVars.clear();
UnregisteredConfigVarOverrides.clear();
s_changeSubscriptions.clear();
s_changeTokenNames.clear();
s_activeChangeNotifications.clear();
}
} // namespace dusk::config
+4 -4
View File
@@ -9,7 +9,7 @@ namespace dusk::config {
bool copy = var.getValue(); bool copy = var.getValue();
if (ImGui::Checkbox(title, &copy)) { if (ImGui::Checkbox(title, &copy)) {
var.setValue(copy); var.setValue(copy);
save(); Save();
return true; return true;
} }
@@ -20,7 +20,7 @@ namespace dusk::config {
float val = var; float val = var;
if (ImGui::SliderFloat(label, &val, v_min, v_max, format, flags)) { if (ImGui::SliderFloat(label, &val, v_min, v_max, format, flags)) {
var.setValue(val); var.setValue(val);
save(); Save();
return true; return true;
} }
@@ -31,7 +31,7 @@ namespace dusk::config {
int val = var; int val = var;
if (ImGui::SliderInt(label, &val, v_min, v_max, format, flags)) { if (ImGui::SliderInt(label, &val, v_min, v_max, format, flags)) {
var.setValue(val); var.setValue(val);
save(); Save();
return true; return true;
} }
@@ -42,7 +42,7 @@ namespace dusk::config {
bool copy = p_selected.getValue(); bool copy = p_selected.getValue();
if (ImGui::MenuItem(label, shortcut, &copy, enabled)) { if (ImGui::MenuItem(label, shortcut, &copy, enabled)) {
p_selected.setValue(copy); p_selected.setValue(copy);
save(); Save();
return true; return true;
} }
+2 -2
View File
@@ -254,7 +254,7 @@ namespace dusk {
if (ImGui::IsKeyPressed(ImGuiKey_F11)) { if (ImGui::IsKeyPressed(ImGuiKey_F11)) {
getSettings().video.enableFullscreen.setValue(!getSettings().video.enableFullscreen); getSettings().video.enableFullscreen.setValue(!getSettings().video.enableFullscreen);
VISetWindowFullscreen(getSettings().video.enableFullscreen); VISetWindowFullscreen(getSettings().video.enableFullscreen);
config::save(); config::Save();
} }
if (getSettings().game.enableResetKeybind && ImGui::GetIO().KeyCtrl && if (getSettings().game.enableResetKeybind && ImGui::GetIO().KeyCtrl &&
@@ -336,7 +336,7 @@ namespace dusk {
if constexpr (SupportsProcessRestart) { if constexpr (SupportsProcessRestart) {
if (ImGui::Button("Retry (Auto backend)")) { if (ImGui::Button("Retry (Auto backend)")) {
getSettings().backend.graphicsBackend.setValue("auto"); getSettings().backend.graphicsBackend.setValue("auto");
config::save(); config::Save();
RestartRequested = true; RestartRequested = true;
IsRunning = false; IsRunning = false;
} }
+1 -1
View File
@@ -73,7 +73,7 @@ namespace dusk {
bool disableWaterRefraction = getSettings().game.disableWaterRefraction; bool disableWaterRefraction = getSettings().game.disableWaterRefraction;
if (ImGui::Checkbox("Disable Water Refraction", &disableWaterRefraction)) { if (ImGui::Checkbox("Disable Water Refraction", &disableWaterRefraction)) {
getSettings().game.disableWaterRefraction.setValue(disableWaterRefraction); getSettings().game.disableWaterRefraction.setValue(disableWaterRefraction);
config::save(); config::Save();
} }
ImGui::Checkbox("Enable LOD Bias", &aurora::gx::enableLodBias); ImGui::Checkbox("Enable LOD Bias", &aurora::gx::enableLodBias);
ImGui::EndMenu(); ImGui::EndMenu();
+1 -3
View File
@@ -1,6 +1,5 @@
#include "dusk/settings.h" #include "dusk/settings.h"
#include "dusk/config.hpp" #include "dusk/config.hpp"
#include <aurora/aurora.h>
namespace dusk { namespace dusk {
@@ -268,8 +267,7 @@ void registerSettings() {
Register(g_userSettings.game.touchCameraYSensitivity); Register(g_userSettings.game.touchCameraYSensitivity);
Register(g_userSettings.game.minimalHUD); Register(g_userSettings.game.minimalHUD);
Register(g_userSettings.game.hudScale); Register(g_userSettings.game.hudScale);
Register(g_userSettings.game.pauseOnFocusLost, Register(g_userSettings.game.pauseOnFocusLost);
[](const bool& value, const bool&) { aurora_set_pause_on_focus_lost(value); });
Register(g_userSettings.game.enableDiscordPresence); Register(g_userSettings.game.enableDiscordPresence);
Register(g_userSettings.game.bloomMode); Register(g_userSettings.game.bloomMode);
Register(g_userSettings.game.bloomMultiplier); Register(g_userSettings.game.bloomMultiplier);
+13
View File
@@ -1,5 +1,6 @@
#include "dusk/speedrun.h" #include "dusk/speedrun.h"
#include "dusk/settings.h" #include "dusk/settings.h"
#include "dusk/config.hpp"
#include "m_Do/m_Do_main.h" #include "m_Do/m_Do_main.h"
#include <aurora/aurora.h> #include <aurora/aurora.h>
@@ -37,10 +38,22 @@ void resetForSpeedrunMode() {
getSettings().game.invincibleEnemies.setSpeedrunValue(false); getSettings().game.invincibleEnemies.setSpeedrunValue(false);
getSettings().game.pauseOnFocusLost.setSpeedrunValue(false); getSettings().game.pauseOnFocusLost.setSpeedrunValue(false);
aurora_set_pause_on_focus_lost(false);
getSettings().backend.enableAdvancedSettings.setSpeedrunValue(false); getSettings().backend.enableAdvancedSettings.setSpeedrunValue(false);
getSettings().game.recordingMode.setSpeedrunValue(false); getSettings().game.recordingMode.setSpeedrunValue(false);
getSettings().game.debugFlyCam.setSpeedrunValue(false); getSettings().game.debugFlyCam.setSpeedrunValue(false);
} }
static void clear_speedrun_overrides() {
config::EnumerateRegistered([](config::ConfigVarBase& cvar) {
cvar.clearSpeedrunOverride();
});
}
void restoreFromSpeedrunMode() {
clear_speedrun_overrides();
aurora_set_pause_on_focus_lost(getSettings().game.pauseOnFocusLost.getValue());
}
} // namespace dusk } // namespace dusk
+5 -5
View File
@@ -278,7 +278,7 @@ ControllerConfigWindow::ControllerConfigWindow(bool prelaunch) {
void ControllerConfigWindow::hide(bool close) { void ControllerConfigWindow::hide(bool close) {
stop_rumble_test(); stop_rumble_test();
cancel_pending_binding(); cancel_pending_binding();
config::save(); config::Save();
Window::hide(close); Window::hide(close);
} }
@@ -403,7 +403,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
PADClearPort(port); PADClearPort(port);
PADSetKeyboardActive(static_cast<u32>(port), FALSE); PADSetKeyboardActive(static_cast<u32>(port), FALSE);
PADSerializeMappings(); PADSerializeMappings();
config::ClearAllActionBindings(port); ClearAllActionBindings(port);
refresh_controller_page(); refresh_controller_page();
}); });
@@ -417,7 +417,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
PADClearPort(port); PADClearPort(port);
PADSetKeyboardActive(static_cast<u32>(port), TRUE); PADSetKeyboardActive(static_cast<u32>(port), TRUE);
PADSerializeMappings(); PADSerializeMappings();
config::ClearAllActionBindings(port); ClearAllActionBindings(port);
}); });
const u32 controllerCount = PADCount(); const u32 controllerCount = PADCount();
@@ -439,7 +439,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
PADSetKeyboardActive(static_cast<u32>(port), FALSE); PADSetKeyboardActive(static_cast<u32>(port), FALSE);
PADSetPortForIndex(i, port); PADSetPortForIndex(i, port);
PADSerializeMappings(); PADSerializeMappings();
config::ClearAllActionBindings(port); ClearAllActionBindings(port);
}); });
} }
break; break;
@@ -1125,7 +1125,7 @@ void ControllerConfigWindow::poll_pending_binding() {
return; return;
} }
mPendingActionBinding->setValue(button); mPendingActionBinding->setValue(button);
config::save(); config::Save();
finish_pending_binding(completedPort); finish_pending_binding(completedPort);
} }
return; return;
-4
View File
@@ -51,8 +51,6 @@ struct ControlProps {
float h = 0.0f; float h = 0.0f;
float scale = 1.0f; float scale = 1.0f;
ControlAnchor anchor = ControlAnchor::None; ControlAnchor anchor = ControlAnchor::None;
bool operator==(const ControlProps&) const = default;
}; };
struct ControlRect { struct ControlRect {
@@ -78,8 +76,6 @@ struct ControlLayout {
int version = Version; int version = Version;
std::map<std::string, ControlProps, std::less<> > controls; std::map<std::string, ControlProps, std::less<> > controls;
bool operator==(const ControlLayout&) const = default;
}; };
constexpr std::array<std::string_view, 9> kControlLayoutIds = { constexpr std::array<std::string_view, 9> kControlLayoutIds = {
+1 -1
View File
@@ -300,7 +300,7 @@ void GraphicsTuner::show() {
} }
void GraphicsTuner::hide(bool close) { void GraphicsTuner::hide(bool close) {
config::save(); config::Save();
mRoot->RemoveAttribute("open"); mRoot->RemoveAttribute("open");
if (close) { if (close) {
mPendingClose = true; mPendingClose = true;
+6 -15
View File
@@ -197,19 +197,10 @@ void remove_element(Rml::Element*& elem) noexcept {
} // namespace } // namespace
static std::string FormatElapsedTime(OSTime ticksElapsed) { static std::string FormatTime(OSTime ticks) {
using namespace std::chrono; OSCalendarTime t;
OSTicksToCalendarTime(ticks, &t);
milliseconds ms{OSTicksToMilliseconds(ticksElapsed)}; return fmt::format("{0:02}:{1:02}:{2:02}.{3:03}", t.hour, t.min, t.sec, t.msec);
const hours hr = duration_cast<hours>(ms);
ms -= hr;
const minutes min = duration_cast<minutes>(ms);
ms -= min;
const seconds sec = duration_cast<seconds>(ms);
ms -= sec;
return fmt::format("{0:02}:{1:02}:{2:02}.{3:03}", hr.count(), min.count(), sec.count(), ms.count());
} }
Overlay::Overlay() : Document(kDocumentSource, true) { Overlay::Overlay() : Document(kDocumentSource, true) {
@@ -326,13 +317,13 @@ void Overlay::update() {
if (getSettings().game.showSpeedrunRTATimer) { if (getSettings().game.showSpeedrunRTATimer) {
mSpeedrunRta->SetAttribute("open", ""); mSpeedrunRta->SetAttribute("open", "");
mSpeedrunRta->SetInnerRML(escape(fmt::format("RTA {}", FormatElapsedTime(elapsedTime)))); mSpeedrunRta->SetInnerRML(escape(fmt::format("RTA {}", FormatTime(elapsedTime))));
} else { } else {
mSpeedrunRta->RemoveAttribute("open"); mSpeedrunRta->RemoveAttribute("open");
} }
mSpeedrunIgt->SetInnerRML( mSpeedrunIgt->SetInnerRML(
escape(fmt::format("IGT {}", FormatElapsedTime(m_speedrunInfo.m_igtTimer)))); escape(fmt::format("IGT {}", FormatTime(m_speedrunInfo.m_igtTimer))));
} else { } else {
mSpeedrunTimer->RemoveAttribute("open"); mSpeedrunTimer->RemoveAttribute("open");
} }
+1 -1
View File
@@ -309,7 +309,7 @@ void persist_disc_choice(const std::string& path, iso::ValidationError validatio
getSettings().backend.isoPath.setValue(path); getSettings().backend.isoPath.setValue(path);
getSettings().backend.isoVerification.setValue(verification); getSettings().backend.isoVerification.setValue(verification);
config::save(); config::Save();
if (previousPath != path || previousVerification != verification) { if (previousPath != path || previousVerification != verification) {
iso::log_verification_state(path, verification); iso::log_verification_state(path, verification);
+1 -1
View File
@@ -106,7 +106,7 @@ PresetWindow::PresetWindow() : WindowSmall("modal", "modal-dialog") {
if (cmd == NavCommand::Confirm) { if (cmd == NavCommand::Confirm) {
apply(); apply();
getSettings().backend.wasPresetChosen.setValue(true); getSettings().backend.wasPresetChosen.setValue(true);
config::save(); config::Save();
hide(true); hide(true);
return true; return true;
} }
+33 -75
View File
@@ -15,6 +15,7 @@
#include "dusk/io.hpp" #include "dusk/io.hpp"
#include "dusk/livesplit.h" #include "dusk/livesplit.h"
#include "dusk/discord_presence.hpp" #include "dusk/discord_presence.hpp"
#include "dusk/speedrun.h"
#include "graphics_tuner.hpp" #include "graphics_tuner.hpp"
#include "m_Do/m_Do_main.h" #include "m_Do/m_Do_main.h"
#include "menu_bar.hpp" #include "menu_bar.hpp"
@@ -218,52 +219,6 @@ AuroraBackend configured_backend() {
return configuredBackend; return configuredBackend;
} }
void reset_for_speedrun_mode() {
mDoMain::developmentMode = -1;
getSettings().game.enableTurboKeybind.setSpeedrunValue(false);
getSettings().game.damageMultiplier.setSpeedrunValue(1);
getSettings().game.instantDeath.setSpeedrunValue(false);
getSettings().game.noHeartDrops.setSpeedrunValue(false);
getSettings().game.autoSave.setSpeedrunValue(false);
getSettings().game.sunsSong.setSpeedrunValue(false);
getSettings().game.infiniteHearts.setSpeedrunValue(false);
getSettings().game.infiniteArrows.setSpeedrunValue(false);
getSettings().game.infiniteSeeds.setSpeedrunValue(false);
getSettings().game.infiniteBombs.setSpeedrunValue(false);
getSettings().game.infiniteOil.setSpeedrunValue(false);
getSettings().game.infiniteOxygen.setSpeedrunValue(false);
getSettings().game.infiniteRupees.setSpeedrunValue(false);
getSettings().game.enableIndefiniteItemDrops.setSpeedrunValue(false);
getSettings().game.moonJump.setSpeedrunValue(false);
getSettings().game.superClawshot.setSpeedrunValue(false);
getSettings().game.alwaysGreatspin.setSpeedrunValue(false);
getSettings().game.enableFastIronBoots.setSpeedrunValue(false);
getSettings().game.canTransformAnywhere.setSpeedrunValue(false);
getSettings().game.fastRoll.setSpeedrunValue(false);
getSettings().game.fastSpinner.setSpeedrunValue(false);
getSettings().game.armorRupeeDrain.setSpeedrunValue(MagicArmorMode::NORMAL);
getSettings().game.invincibleEnemies.setSpeedrunValue(false);
getSettings().game.pauseOnFocusLost.setSpeedrunValue(false);
getSettings().backend.enableAdvancedSettings.setSpeedrunValue(false);
getSettings().game.recordingMode.setSpeedrunValue(false);
getSettings().game.debugFlyCam.setSpeedrunValue(false);
}
void clear_speedrun_overrides() {
config::EnumerateRegistered([](config::ConfigVarBase& cvar) {
cvar.clearSpeedrunOverride();
});
}
void restore_from_speedrun_mode() {
clear_speedrun_overrides();
}
std::filesystem::path normalized_display_path(const std::filesystem::path& path) { std::filesystem::path normalized_display_path(const std::filesystem::path& path) {
std::error_code ec; std::error_code ec;
auto normalized = std::filesystem::weakly_canonical(path, ec); auto normalized = std::filesystem::weakly_canonical(path, ec);
@@ -445,7 +400,7 @@ SelectButton& config_bool_select(
return; return;
} }
var.setValue(value); var.setValue(value);
config::save(); config::Save();
if (callback) { if (callback) {
callback(value); callback(value);
} }
@@ -466,7 +421,7 @@ void add_speedrun_disabled_option(Pane& leftPane, Pane& rightPane, ConfigVar<boo
config_bool_select(leftPane, rightPane, var, { config_bool_select(leftPane, rightPane, var, {
.key = key, .key = key,
.helpText = helpText, .helpText = helpText,
.isDisabled = [] { return getSettings().game.speedrunMode.getValue(); }, .isDisabled = [] { return getSettings().game.speedrunMode; },
}); });
} }
@@ -479,7 +434,7 @@ SelectButton& config_percent_select(Pane& leftPane, Pane& rightPane, ConfigVar<f
.setValue = .setValue =
[&var, min, max](int value) { [&var, min, max](int value) {
var.setValue(std::clamp(value, min, max) / 100.0f); var.setValue(std::clamp(value, min, max) / 100.0f);
config::save(); config::Save();
}, },
.isDisabled = std::move(isDisabled), .isDisabled = std::move(isDisabled),
.isModified = [&var] { return var.getValue() != var.getDefaultValue(); }, .isModified = [&var] { return var.getValue() != var.getDefaultValue(); },
@@ -501,12 +456,12 @@ SelectButton& config_int_select(Pane& leftPane, Pane& rightPane, ConfigVar<int>&
std::string suffix = "") { std::string suffix = "") {
auto& button = leftPane.add_child<NumberButton>(NumberButton::Props{ auto& button = leftPane.add_child<NumberButton>(NumberButton::Props{
.key = std::move(key), .key = std::move(key),
.getValue = [&var] { return var.getValue(); }, .getValue = [&var] { return var; },
.setValue = .setValue =
[&var, min, max, callback = std::move(onChange)](int value) { [&var, min, max, callback = std::move(onChange)](int value) {
const int clampedValue = std::clamp(value, min, max); const int clampedValue = std::clamp(value, min, max);
var.setValue(clampedValue); var.setValue(clampedValue);
config::save(); config::Save();
if (callback) { if (callback) {
callback(clampedValue); callback(clampedValue);
} }
@@ -678,7 +633,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
.on_pressed([i] { .on_pressed([i] {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().game.language.setValue(static_cast<GameLanguage>(i)); getSettings().game.language.setValue(static_cast<GameLanguage>(i));
config::save(); config::Save();
}); });
} }
pane.add_rml("<br/>Changes require a restart."); pane.add_rml("<br/>Changes require a restart.");
@@ -705,7 +660,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().backend.graphicsBackend.setValue( getSettings().backend.graphicsBackend.setValue(
std::string{backend_id(backend)}); std::string{backend_id(backend)});
config::save(); config::Save();
}); });
} }
pane.add_rml("<br/>Changes require a restart."); pane.add_rml("<br/>Changes require a restart.");
@@ -736,7 +691,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
.on_pressed([i] { .on_pressed([i] {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().backend.cardFileType.setValue(i); getSettings().backend.cardFileType.setValue(i);
config::save(); config::Save();
}); });
} }
}); });
@@ -753,7 +708,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().video.enableFullscreen.setValue(!getSettings().video.enableFullscreen); getSettings().video.enableFullscreen.setValue(!getSettings().video.enableFullscreen);
VISetWindowFullscreen(getSettings().video.enableFullscreen); VISetWindowFullscreen(getSettings().video.enableFullscreen);
config::save(); config::Save();
}), }),
rightPane, [](Pane& pane) { pane.clear(); }); rightPane, [](Pane& pane) { pane.clear(); });
leftPane.register_control(leftPane.add_button("Restore Default Window Size").on_pressed([] { leftPane.register_control(leftPane.add_button("Restore Default Window Size").on_pressed([] {
@@ -784,6 +739,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
{ {
.key = "Pause on Focus Lost", .key = "Pause on Focus Lost",
.helpText = "Pause the game when window focus is lost.", .helpText = "Pause the game when window focus is lost.",
.onChange = [](bool value) { aurora_set_pause_on_focus_lost(value); },
.isDisabled = [] { return IsMobile || getSettings().game.speedrunMode; }, .isDisabled = [] { return IsMobile || getSettings().game.speedrunMode; },
}); });
leftPane.register_control( leftPane.register_control(
@@ -815,7 +771,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
.on_pressed([] { .on_pressed([] {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().video.enableFpsOverlay.setValue(false); getSettings().video.enableFpsOverlay.setValue(false);
config::save(); config::Save();
}); });
for (int i = 0; i < static_cast<int>(kFpsOverlayCornerNames.size()); ++i) { for (int i = 0; i < static_cast<int>(kFpsOverlayCornerNames.size()); ++i) {
pane.add_button( pane.add_button(
@@ -831,7 +787,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().video.enableFpsOverlay.setValue(true); getSettings().video.enableFpsOverlay.setValue(true);
getSettings().video.fpsOverlayCorner.setValue(i); getSettings().video.fpsOverlayCorner.setValue(i);
config::save(); config::Save();
}); });
} }
pane.add_rml( pane.add_rml(
@@ -847,7 +803,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
const auto windowSize = aurora::window::get_window_size(); const auto windowSize = aurora::window::get_window_size();
dusk::getSettings().video.lastWindowWidth.setValue(windowSize.width); dusk::getSettings().video.lastWindowWidth.setValue(windowSize.width);
dusk::getSettings().video.lastWindowHeight.setValue(windowSize.height); dusk::getSettings().video.lastWindowHeight.setValue(windowSize.height);
dusk::config::save(); dusk::config::Save();
} }
}, },
.isDisabled = [] { return IsMobile; }, .isDisabled = [] { return IsMobile; },
@@ -953,7 +909,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().game.enableFrameInterpolation.setValue(static_cast<FrameInterpMode>(i)); getSettings().game.enableFrameInterpolation.setValue(static_cast<FrameInterpMode>(i));
android::update_surface_frame_rate(); android::update_surface_frame_rate();
config::save(); config::Save();
}); });
} }
pane.add_rml(kUnlockFramerateHelpText); pane.add_rml(kUnlockFramerateHelpText);
@@ -1052,7 +1008,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().game.touchTargeting.setValue( getSettings().game.touchTargeting.setValue(
static_cast<TouchTargeting>(i)); static_cast<TouchTargeting>(i));
config::save(); config::Save();
}); });
} }
pane.add_rml(fmt::format("<br/>Hybrid: {}<br/>Hold: {}<br/>Switch: {}", pane.add_rml(fmt::format("<br/>Hybrid: {}<br/>Hold: {}<br/>Switch: {}",
@@ -1148,7 +1104,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
leftPane.add_section("Tools"); leftPane.add_section("Tools");
addOption("Turbo Key", getSettings().game.enableTurboKeybind, addOption("Turbo Key", getSettings().game.enableTurboKeybind,
"Hold Tab to increase game speed by up to 4x.", "Hold Tab to increase game speed by up to 4x.",
[] { return getSettings().game.speedrunMode.getValue(); }); [] { return getSettings().game.speedrunMode; });
addOption("Reset Key (" + Rml::String{hotkeys::DO_RESET} + ")", addOption("Reset Key (" + Rml::String{hotkeys::DO_RESET} + ")",
getSettings().game.enableResetKeybind, getSettings().game.enableResetKeybind,
"Press " + Rml::String{hotkeys::DO_RESET} + " to reset the game."); "Press " + Rml::String{hotkeys::DO_RESET} + " to reset the game.");
@@ -1167,7 +1123,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
.setValue = .setValue =
[](int value) { [](int value) {
getSettings().audio.masterVolume.setValue(value); getSettings().audio.masterVolume.setValue(value);
config::save(); config::Save();
audio::SetMasterVolume(audio::MasterVolumeToLinear(value / 100.0f)); audio::SetMasterVolume(audio::MasterVolumeToLinear(value / 100.0f));
}, },
.isModified = .isModified =
@@ -1259,9 +1215,9 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
.setValue = .setValue =
[](int value) { [](int value) {
getSettings().game.damageMultiplier.setValue(value); getSettings().game.damageMultiplier.setValue(value);
config::save(); config::Save();
}, },
.isDisabled = [] { return getSettings().game.speedrunMode.getValue(); }, .isDisabled = [] { return getSettings().game.speedrunMode; },
.isModified = .isModified =
[] { [] {
return getSettings().game.damageMultiplier.getValue() != return getSettings().game.damageMultiplier.getValue() !=
@@ -1322,9 +1278,9 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
.onChange = .onChange =
[](bool enabled) { [](bool enabled) {
if (enabled) { if (enabled) {
reset_for_speedrun_mode(); resetForSpeedrunMode();
} else { } else {
restore_from_speedrun_mode(); restoreFromSpeedrunMode();
if (getSettings().game.liveSplitEnabled) { if (getSettings().game.liveSplitEnabled) {
speedrun::disconnectLiveSplit(); speedrun::disconnectLiveSplit();
} }
@@ -1405,7 +1361,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
[] { [] {
return kMagicArmorModes[static_cast<u8>(getSettings().game.armorRupeeDrain.getValue())]; return kMagicArmorModes[static_cast<u8>(getSettings().game.armorRupeeDrain.getValue())];
}, },
.isDisabled = [] { return getSettings().game.speedrunMode.getValue(); }, .isDisabled = [] { return getSettings().game.speedrunMode; },
.isModified = .isModified =
[] { [] {
return getSettings().game.armorRupeeDrain.getValue() != return getSettings().game.armorRupeeDrain.getValue() !=
@@ -1424,7 +1380,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
.on_pressed([i] { .on_pressed([i] {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().game.armorRupeeDrain.setValue(static_cast<MagicArmorMode>(i)); getSettings().game.armorRupeeDrain.setValue(static_cast<MagicArmorMode>(i));
config::save(); config::Save();
}); });
} }
pane.add_rml( pane.add_rml(
@@ -1477,13 +1433,13 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().game.enableAchievementToasts.setValue(true); getSettings().game.enableAchievementToasts.setValue(true);
getSettings().game.enableControllerToasts.setValue(true); getSettings().game.enableControllerToasts.setValue(true);
config::save(); config::Save();
}); });
pane.add_button("Select None").on_pressed([] { pane.add_button("Select None").on_pressed([] {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().game.enableAchievementToasts.setValue(false); getSettings().game.enableAchievementToasts.setValue(false);
getSettings().game.enableControllerToasts.setValue(false); getSettings().game.enableControllerToasts.setValue(false);
config::save(); config::Save();
}); });
pane.add_section("Types"); pane.add_section("Types");
@@ -1499,7 +1455,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
auto& v = getSettings().game.enableAchievementToasts; auto& v = getSettings().game.enableAchievementToasts;
v.setValue(!v.getValue()); v.setValue(!v.getValue());
config::save(); config::Save();
}); });
pane.add_button( pane.add_button(
{ {
@@ -1511,7 +1467,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
auto& v = getSettings().game.enableControllerToasts; auto& v = getSettings().game.enableControllerToasts;
v.setValue(!v.getValue()); v.setValue(!v.getValue());
config::save(); config::Save();
}); });
pane.add_rml("<br/>Choose which notifications can be displayed."); pane.add_rml("<br/>Choose which notifications can be displayed.");
}); });
@@ -1577,7 +1533,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
} }
} }
}, },
.isDisabled = [] { return getSettings().game.speedrunMode.getValue(); }, .isDisabled = [] { return getSettings().game.speedrunMode; },
}); });
config_bool_select(leftPane, rightPane, getSettings().game.showInputViewer, config_bool_select(leftPane, rightPane, getSettings().game.showInputViewer,
{ {
@@ -1614,13 +1570,15 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
[i] { [i] {
return getSettings().game.menuScalingMode.getValue() == return getSettings().game.menuScalingMode.getValue() ==
static_cast<MenuScaling>(i); static_cast<MenuScaling>(i);
;
}, },
}) })
.on_pressed([i] { .on_pressed([i] {
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
getSettings().game.menuScalingMode.setValue( getSettings().game.menuScalingMode.setValue(
static_cast<MenuScaling>(i)); static_cast<MenuScaling>(i));
config::save(); ;
config::Save();
}); });
} }
pane.add_rml("<br/>Changes how the Collection and File Select menus scale to your " pane.add_rml("<br/>Changes how the Collection and File Select menus scale to your "
@@ -1646,7 +1604,7 @@ void SettingsWindow::update() {
} }
void SettingsWindow::hide(bool close) { void SettingsWindow::hide(bool close) {
config::save(); config::Save();
Window::hide(close); Window::hide(close);
} }
+1 -1
View File
@@ -585,7 +585,7 @@ bool TouchControlsEditor::handle_nav_command(Rml::Event& event, NavCommand cmd)
void TouchControlsEditor::save_layout() { void TouchControlsEditor::save_layout() {
mWorkingLayout.version = ControlLayout::Version; mWorkingLayout.version = ControlLayout::Version;
getSettings().game.touchControlsLayout.setValue(mWorkingLayout); getSettings().game.touchControlsLayout.setValue(mWorkingLayout);
config::save(); config::Save();
mDoAud_seStartMenu(kSoundItemChange); mDoAud_seStartMenu(kSoundItemChange);
pop(); pop();
} }
+1 -1
View File
@@ -320,7 +320,7 @@ static void mDoMemCdRWm_BuildHeader(mDoMemCdRWm_HeaderData* header) {
#endif #endif
OSCalendarTime time; OSCalendarTime time;
OSTicksToCalendarTime(DUSK_IF_ELSE(OSGetSystemTime(), OSGetTime()), &time); OSTicksToCalendarTime(OSGetTime(), &time);
#if TARGET_PC #if TARGET_PC
if (dusk::version::isRegionPal()) { if (dusk::version::isRegionPal()) {
+1 -1
View File
@@ -527,7 +527,7 @@ void myExceptionCallback(u16, OSContext*, u32, u32) {
u32 btnHold; u32 btnHold;
u32 btnTrig; u32 btnTrig;
mDoMain::sHungUpTime = DUSK_IF_ELSE(OSGetSystemTime(), OSGetTime()); mDoMain::sHungUpTime = OSGetTime();
OSReportEnable(); OSReportEnable();
cAPICPad_recalibrate(); cAPICPad_recalibrate();
// "Vibration stopping & resetting to default\n" // "Vibration stopping & resetting to default\n"
+19 -13
View File
@@ -265,7 +265,7 @@ void main01(void) {
if (dusk::getSettings().video.rememberWindowSize && !dusk::getSettings().video.enableFullscreen) { if (dusk::getSettings().video.rememberWindowSize && !dusk::getSettings().video.enableFullscreen) {
dusk::getSettings().video.lastWindowWidth.setValue(event->windowSize.width); dusk::getSettings().video.lastWindowWidth.setValue(event->windowSize.width);
dusk::getSettings().video.lastWindowHeight.setValue(event->windowSize.height); dusk::getSettings().video.lastWindowHeight.setValue(event->windowSize.height);
dusk::config::save(); dusk::config::Save();
} }
break; break;
case AURORA_DISPLAY_SCALE_CHANGED: case AURORA_DISPLAY_SCALE_CHANGED:
@@ -430,7 +430,16 @@ static void ApplyCVarOverrides(const cxxopts::OptionValue& option) {
const auto name = std::string_view(cvarArg).substr(0, sep); const auto name = std::string_view(cvarArg).substr(0, sep);
const auto value = std::string_view(cvarArg).substr(sep + 1); const auto value = std::string_view(cvarArg).substr(sep + 1);
dusk::config::load_arg_override(name, value); const auto cVar = dusk::config::GetConfigVar(name);
if (!cVar) {
DuskLog.fatal("Unknown --cvar name: '{}'", name);
}
try {
cVar->getImpl()->loadFromArg(*cVar, value);
} catch (const std::exception& e) {
DuskLog.fatal("Unable to parse: '{}': {}", value, e.what());
}
} }
} }
@@ -501,6 +510,7 @@ int game_main(int argc, char* argv[]) {
mainCalled = true; mainCalled = true;
dusk::registerSettings(); dusk::registerSettings();
dusk::config::FinishRegistration();
cxxopts::ParseResult parsed_arg_options; cxxopts::ParseResult parsed_arg_options;
@@ -541,7 +551,10 @@ int game_main(int argc, char* argv[]) {
log_build_info(); log_build_info();
dusk::config::load_from_user_preferences(); dusk::config::LoadFromUserPreferences();
if (dusk::getSettings().game.speedrunMode) {
dusk::resetForSpeedrunMode();
}
ApplyCVarOverrides(parsed_arg_options["cvar"]); ApplyCVarOverrides(parsed_arg_options["cvar"]);
dusk::android::update_surface_frame_rate(); dusk::android::update_surface_frame_rate();
dusk::crash_reporting::initialize(); dusk::crash_reporting::initialize();
@@ -605,12 +618,6 @@ int game_main(int argc, char* argv[]) {
auroraInfo = aurora_initialize(argc, argv, &config); auroraInfo = aurora_initialize(argc, argv, &config);
} }
// Apply after aurora_initialize: speedrun mode mutates cvars whose change callbacks push
// values into aurora.
if (dusk::getSettings().game.speedrunMode) {
dusk::resetForSpeedrunMode();
}
#ifdef DUSK_DISCORD #ifdef DUSK_DISCORD
if (dusk::getSettings().game.enableDiscordPresence) { if (dusk::getSettings().game.enableDiscordPresence) {
dusk::discord::initialize(); dusk::discord::initialize();
@@ -693,7 +700,7 @@ int game_main(int argc, char* argv[]) {
dusk::getSettings().backend.isoPath.setValue(dvd_path); dusk::getSettings().backend.isoPath.setValue(dvd_path);
dusk::getSettings().backend.isoVerification.setValue( dusk::getSettings().backend.isoVerification.setValue(
dusk::DiscVerificationState::Unknown); dusk::DiscVerificationState::Unknown);
dusk::config::save(); dusk::config::Save();
dusk::IsGameLaunched = true; dusk::IsGameLaunched = true;
} }
} else { } else {
@@ -716,7 +723,7 @@ int game_main(int argc, char* argv[]) {
saveConfigBeforePrelaunch = true; saveConfigBeforePrelaunch = true;
} }
if (saveConfigBeforePrelaunch) { if (saveConfigBeforePrelaunch) {
dusk::config::save(); dusk::config::Save();
} }
if (!dusk::getSettings().backend.skipPreLaunchUI) { if (!dusk::getSettings().backend.skipPreLaunchUI) {
@@ -770,7 +777,7 @@ int game_main(int argc, char* argv[]) {
OSInit(); OSInit();
mDoMain::sPowerOnTime = DUSK_IF_ELSE(OSGetSystemTime(), OSGetTime()); mDoMain::sPowerOnTime = OSGetTime();
// Reset Data // Reset Data
static mDoRstData sResetData = {0}; static mDoRstData sResetData = {0};
@@ -807,7 +814,6 @@ int game_main(int argc, char* argv[]) {
#endif #endif
dusk::ui::shutdown(); dusk::ui::shutdown();
dusk::texture_replacements::shutdown(); dusk::texture_replacements::shutdown();
dusk::config::shutdown();
aurora_shutdown(); aurora_shutdown();
return 0; return 0;