Compare commits

...

22 Commits

Author SHA1 Message Date
MelonSpeedruns 0cdcd71b6a fix spinner on z 2026-05-14 10:19:19 -04:00
MelonSpeedruns 318ad2a00f third item, missing visuals 2026-05-14 10:14:35 -04:00
TakaRikka a913f1699f Merge pull request #1252 from TwilitRealm/erd
clear e_rd static boss ptr on delete
2026-05-13 19:31:35 -07:00
TakaRikka 01b4eaa2fa clear e_rd static boss ptr on delete 2026-05-13 19:27:39 -07:00
SuperDude88 9d2ba3eb49 Rename Settings Preset (#1233)
To match the bloom preset, since that name was updated in #1211
2026-05-13 20:26:30 -04:00
JaxonWasTaken 6026b4bb9b Apply rebrand to bloom setting value name (#1211)
The display name for BloomSetting::Dusk was unchanged in the rebranding
process, and still shows up as "Dusk" in the settings menu. Rename it to
"Dusklight" to bring it in line with the rebrand.
2026-05-13 16:34:14 -04:00
Luke Street 7a77d48954 Use legacy path if migration fails 2026-05-13 09:08:41 -06:00
qwertyquerty 4ee0d8ed4b 1.1.1 fixes (#1168)
* fix keyboard npe

* fix autosave NPE

* hintTalkEvCamera UB

* fix UB in f_pc_base logging

* fix NPE in karg carry logic

* fix link model dangling pointers

* exponential audio slider and better audio default

* fix speedrun mode defaullt layer restore issue
2026-05-13 08:56:16 -06:00
qwertyquerty ce554a107d speedrun mode hotfixes (#1160) 2026-05-13 01:10:25 -06:00
Luke Street 9ce1ab7d5a Migrate only user files 2026-05-13 00:47:29 -06:00
Luke Street 8830760d34 BUILD_SHARED_LIBS=OFF for Android 2026-05-12 23:04:13 -06:00
SuperDude88 9abe89f47f Oops (#1156)
Forgot one
2026-05-12 22:57:42 -06:00
Loïs 3e62c1e96e Add Invincible Enemies cheat (#1123) 2026-05-12 22:52:35 -06:00
Irastris d9bbea300d Add map loader to RmlUi (#1147)
* Add Warp to RmlUi

* Remove ImGui map loader
2026-05-12 22:52:02 -06:00
Luke Street 1a951511be Merge pull request #1153 from TwilitRealm/slingshot-ammo-cheat
Infinite Slingshot Seeds
2026-05-12 22:51:23 -06:00
Luke Street ab0efb7a3b CI fixes and enable mobile THP support 2026-05-12 22:33:12 -06:00
Luke Street 5fdc3c7a54 Merge pull request #875 from Krutonium/flake-desktop-icon 2026-05-12 22:10:53 -06:00
SuperDude88 2978ae145d Infinite Slingshot Seeds 2026-05-13 00:04:58 -04:00
Krutonium e93773757f Edit CMakeLists to add Nix Version 2026-05-12 23:35:54 -04:00
Krutonium 6be742b15f Merge branch 'main' into flake-desktop-icon 2026-05-12 23:34:10 -04:00
Krutonium d6cbc9b6d5 Set Version String to be NixOS-<short git hash> OR dirty 2026-05-10 14:21:03 -04:00
Krutonium b10211c4c2 Add Desktop Icon 2026-05-10 13:25:43 -04:00
51 changed files with 917 additions and 418 deletions
+17 -7
View File
@@ -5,8 +5,19 @@ if (NOT CMAKE_BUILD_TYPE)
"Build type options: Debug Release RelWithDebInfo MinSizeRel" FORCE) "Build type options: Debug Release RelWithDebInfo MinSizeRel" FORCE)
endif () endif ()
# obtain revision info from git set(DUSK_VERSION_OVERRIDE "" CACHE STRING "Override version string (skips git detection and format validation)")
find_package(Git)
if (DUSK_VERSION_OVERRIDE)
set(DUSK_WC_DESCRIBE "${DUSK_VERSION_OVERRIDE}")
set(DUSK_VERSION_STRING "0.0.0.0")
set(DUSK_SHORT_VERSION_STRING "0.0.0")
set(DUSK_WC_REVISION "")
set(DUSK_WC_BRANCH "")
set(DUSK_WC_DATE "")
message(STATUS "Dusklight version overridden to ${DUSK_WC_DESCRIBE}")
else ()
# obtain revision info from git
find_package(Git)
if (GIT_FOUND) if (GIT_FOUND)
# make sure version information gets re-run when the current Git HEAD changes # make sure version information gets re-run when the current Git HEAD changes
execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --git-path HEAD execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --git-path HEAD
@@ -63,6 +74,8 @@ else ()
set(DUSK_SHORT_VERSION_STRING "0.0.0") set(DUSK_SHORT_VERSION_STRING "0.0.0")
endif () endif ()
endif ()
# Add version information to CI environment variables # Add version information to CI environment variables
if(DEFINED ENV{GITHUB_ENV}) if(DEFINED ENV{GITHUB_ENV})
file(APPEND "$ENV{GITHUB_ENV}" "DUSK_VERSION=${DUSK_WC_DESCRIBE}\n") file(APPEND "$ENV{GITHUB_ENV}" "DUSK_VERSION=${DUSK_WC_DESCRIBE}\n")
@@ -112,11 +125,6 @@ option(DUSK_BUILD_WARNINGS "Enable compiler warnings (off by default)")
option(DUSK_SELECTED_OPT "If on, selected parts of the project will be compiled with optimizations on Debug, intending to make the game run at 30 FPS. Note for MSVC: you will need to remove '/RTC1' from your debug flags in CMake.") option(DUSK_SELECTED_OPT "If on, selected parts of the project will be compiled with optimizations on Debug, intending to make the game run at 30 FPS. Note for MSVC: you will need to remove '/RTC1' from your debug flags in CMake.")
option(DUSK_MOVIE_SUPPORT "If on, compile against libjpeg-turbo to enable THP file decoding" ON) option(DUSK_MOVIE_SUPPORT "If on, compile against libjpeg-turbo to enable THP file decoding" ON)
option(DUSK_ENABLE_UPDATE_CHECKER "Enable update checking support" ON) option(DUSK_ENABLE_UPDATE_CHECKER "Enable update checking support" ON)
if(ANDROID)
set(DUSK_MOVIE_SUPPORT OFF)
endif ()
option(DUSK_ENABLE_SENTRY_NATIVE "Enable sentry-native crash reporting support" OFF) option(DUSK_ENABLE_SENTRY_NATIVE "Enable sentry-native crash reporting support" OFF)
set(DUSK_SENTRY_DSN "" CACHE STRING "Sentry DSN") set(DUSK_SENTRY_DSN "" CACHE STRING "Sentry DSN")
set(DUSK_SENTRY_ENVIRONMENT "development" CACHE STRING "Sentry environment") set(DUSK_SENTRY_ENVIRONMENT "development" CACHE STRING "Sentry environment")
@@ -155,6 +163,8 @@ if (DUSK_MOVIE_SUPPORT)
list(APPEND _jpeg_cmake_args -DCMAKE_TOOLCHAIN_FILE=${_jpeg_toolchain_file}) list(APPEND _jpeg_cmake_args -DCMAKE_TOOLCHAIN_FILE=${_jpeg_toolchain_file})
endif () endif ()
set(_jpeg_passthrough_vars set(_jpeg_passthrough_vars
ANDROID_ABI
ANDROID_PLATFORM
CMAKE_BUILD_TYPE CMAKE_BUILD_TYPE
CMAKE_C_COMPILER CMAKE_C_COMPILER
CMAKE_C_COMPILER_LAUNCHER CMAKE_C_COMPILER_LAUNCHER
+10 -25
View File
@@ -249,22 +249,11 @@
"type": "BOOL", "type": "BOOL",
"value": false "value": false
}, },
"CMAKE_DISABLE_FIND_PACKAGE_BZip2": { "CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL", "type": "BOOL",
"value": true "value": true
}, },
"CMAKE_DISABLE_FIND_PACKAGE_LibLZMA": { "CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew"
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_zstd": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_Freetype": {
"type": "BOOL",
"value": true
}
}, },
"vendor": { "vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": { "microsoft.com/VisualStudioSettings/CMake/1.0": {
@@ -329,7 +318,11 @@
"cacheVariables": { "cacheVariables": {
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install", "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install",
"CMAKE_TOOLCHAIN_FILE": "$env{ANDROID_HOME}/ndk/$env{ANDROID_NDK_VERSION}/build/cmake/android.toolchain.cmake", "CMAKE_TOOLCHAIN_FILE": "$env{ANDROID_HOME}/ndk/$env{ANDROID_NDK_VERSION}/build/cmake/android.toolchain.cmake",
"ANDROID_PLATFORM": "android-28" "ANDROID_PLATFORM": "android-28",
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
}
} }
}, },
{ {
@@ -416,7 +409,7 @@
}, },
"CMAKE_OSX_DEPLOYMENT_TARGET": "11.0", "CMAKE_OSX_DEPLOYMENT_TARGET": "11.0",
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew", "CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew",
"DUSK_MOVIE_SUPPORT": { "BUILD_SHARED_LIBS": {
"type": "BOOL", "type": "BOOL",
"value": false "value": false
} }
@@ -449,11 +442,7 @@
], ],
"cacheVariables": { "cacheVariables": {
"CMAKE_C_COMPILER_LAUNCHER": "sccache", "CMAKE_C_COMPILER_LAUNCHER": "sccache",
"CMAKE_CXX_COMPILER_LAUNCHER": "sccache", "CMAKE_CXX_COMPILER_LAUNCHER": "sccache"
"DUSK_MOVIE_SUPPORT": {
"type": "BOOL",
"value": false
}
} }
}, },
{ {
@@ -463,11 +452,7 @@
], ],
"cacheVariables": { "cacheVariables": {
"CMAKE_C_COMPILER_LAUNCHER": "sccache", "CMAKE_C_COMPILER_LAUNCHER": "sccache",
"CMAKE_CXX_COMPILER_LAUNCHER": "sccache", "CMAKE_CXX_COMPILER_LAUNCHER": "sccache"
"DUSK_MOVIE_SUPPORT": {
"type": "BOOL",
"value": false
}
} }
}, },
{ {
+1 -1
+2 -1
View File
@@ -1458,7 +1458,6 @@ set(DUSK_FILES
src/dusk/imgui/ImGuiHeapOverlay.cpp src/dusk/imgui/ImGuiHeapOverlay.cpp
src/dusk/imgui/ImGuiControllerOverlay.cpp src/dusk/imgui/ImGuiControllerOverlay.cpp
src/dusk/imgui/ImGuiStubLog.cpp src/dusk/imgui/ImGuiStubLog.cpp
src/dusk/imgui/ImGuiMapLoader.cpp
src/dusk/imgui/ImGuiSaveEditor.cpp src/dusk/imgui/ImGuiSaveEditor.cpp
src/dusk/imgui/ImGuiStateShare.hpp src/dusk/imgui/ImGuiStateShare.hpp
src/dusk/imgui/ImGuiStateShare.cpp src/dusk/imgui/ImGuiStateShare.cpp
@@ -1509,6 +1508,8 @@ set(DUSK_FILES
src/dusk/ui/tab_bar.hpp src/dusk/ui/tab_bar.hpp
src/dusk/ui/ui.cpp src/dusk/ui/ui.cpp
src/dusk/ui/ui.hpp src/dusk/ui/ui.hpp
src/dusk/ui/warp.cpp
src/dusk/ui/warp.hpp
src/dusk/ui/window.cpp src/dusk/ui/window.cpp
src/dusk/ui/window.hpp src/dusk/ui/window.hpp
src/dusk/achievements.cpp src/dusk/achievements.cpp
+14 -1
View File
@@ -50,7 +50,11 @@
# Dusklight Actual (Linux x86_64 only — relies on prebuilt dawn/nod binaries) # Dusklight Actual (Linux x86_64 only — relies on prebuilt dawn/nod binaries)
mkDusklight = pkgs: mkDusklight = pkgs:
let srcs = buildSources pkgs; in let srcs = buildSources pkgs;
versionSuffix = if self ? shortRev && self.shortRev != null
then "nix-${self.shortRev}"
else "nix-dirty";
in
pkgs.stdenv.mkDerivation { pkgs.stdenv.mkDerivation {
name = "dusklight"; name = "dusklight";
src = ./.; src = ./.;
@@ -62,6 +66,7 @@
''; '';
# Remove last line to re-enable tests # Remove last line to re-enable tests
cmakeFlags = [ cmakeFlags = [
"-DDUSK_VERSION_OVERRIDE=${versionSuffix}"
"-DFETCHCONTENT_FULLY_DISCONNECTED=ON" "-DFETCHCONTENT_FULLY_DISCONNECTED=ON"
"-DFETCHCONTENT_SOURCE_DIR_CXXOPTS=${pkgs.cxxopts.src}" "-DFETCHCONTENT_SOURCE_DIR_CXXOPTS=${pkgs.cxxopts.src}"
"-DFETCHCONTENT_SOURCE_DIR_JSON=${pkgs.nlohmann_json.src}" "-DFETCHCONTENT_SOURCE_DIR_JSON=${pkgs.nlohmann_json.src}"
@@ -83,6 +88,14 @@
mkdir -p $out/bin mkdir -p $out/bin
cp dusklight $out/bin/dusklight cp dusklight $out/bin/dusklight
cp -r ./res $out/bin/res cp -r ./res $out/bin/res
mkdir -p $out/share/applications
cp $src/platforms/freedesktop/dusklight.desktop $out/share/applications/dusklight.desktop
for size in 16 32 48 64 128 256 512 1024; do
install -Dm644 $src/platforms/freedesktop/''${size}x''${size}/apps/dusklight.png \
$out/share/icons/hicolor/''${size}x''${size}/apps/dusklight.png
done
''; '';
nativeBuildInputs = [ nativeBuildInputs = [
pkgs.cmake pkgs.cmake
+1 -1
View File
@@ -4059,7 +4059,7 @@ public:
/* 0x02180 */ daAlink_matAnm_c* field_0x2180[2]; /* 0x02180 */ daAlink_matAnm_c* field_0x2180[2];
/* 0x02188 */ dEyeHL_c mEyeHL1; /* 0x02188 */ dEyeHL_c mEyeHL1;
/* 0x0219C */ dEyeHL_c mEyeHL2; /* 0x0219C */ dEyeHL_c mEyeHL2;
/* 0x021B0 */ daPy_anmHeap_c mItemHeap[2]; /* 0x021B0 */ daPy_anmHeap_c mItemHeap[3];
/* 0x021D8 */ daPy_anmHeap_c mAnmHeap9; /* 0x021D8 */ daPy_anmHeap_c mAnmHeap9;
/* 0x021EC */ daAlinkHIO_c* mpHIO; /* 0x021EC */ daAlinkHIO_c* mpHIO;
/* 0x021F0 */ daAlink_blur_c m_swordBlur; /* 0x021F0 */ daAlink_blur_c m_swordBlur;
+1
View File
@@ -47,6 +47,7 @@ enum dEvt_type_e {
/* 0x5 */ dEvt_type_ITEM_e, /* 0x5 */ dEvt_type_ITEM_e,
/* 0x6 */ dEvt_type_SHOWITEM_X_e, /* 0x6 */ dEvt_type_SHOWITEM_X_e,
/* 0x7 */ dEvt_type_SHOWITEM_Y_e, /* 0x7 */ dEvt_type_SHOWITEM_Y_e,
/* 0x8 */ dEvt_type_SHOWITEM_Z_e,
/* 0xA */ dEvt_type_CATCH_e = 10, /* 0xA */ dEvt_type_CATCH_e = 10,
/* 0xB */ dEvt_type_TREASURE_e, /* 0xB */ dEvt_type_TREASURE_e,
}; };
+1 -1
View File
@@ -172,7 +172,7 @@ private:
/* 0x6A9 */ u8 field_0x6a9; // unused /* 0x6A9 */ u8 field_0x6a9; // unused
/* 0x6AA */ u8 mXButtonSlot; /* 0x6AA */ u8 mXButtonSlot;
/* 0x6AB */ u8 mYButtonSlot; /* 0x6AB */ u8 mYButtonSlot;
/* 0x6AC */ u8 field_0x6ac; /* 0x6AC */ u8 mZButtonSlot;
/* 0x6AD */ u8 field_0x6ad; /* 0x6AD */ u8 field_0x6ad;
/* 0x6AE */ u8 mItemsTotal; // Contains the amount of items which are actually obtained and in /* 0x6AE */ u8 mItemsTotal; // Contains the amount of items which are actually obtained and in
// the item wheel // the item wheel
+1 -1
View File
@@ -160,7 +160,7 @@ private:
/* 0x078 */ J2DScreen* mpScreen; /* 0x078 */ J2DScreen* mpScreen;
/* 0x07C */ J2DScreen* mpKanteraScreen; /* 0x07C */ J2DScreen* mpKanteraScreen;
/* 0x080 */ J2DScreen* mpPikariScreen; /* 0x080 */ J2DScreen* mpPikariScreen;
/* 0x084 */ J2DPicture* mpItemNumTex[2][3]; /* 0x084 */ J2DPicture* mpItemNumTex[3][3];
/* 0x09C */ CPaneMgr* field_0x9c[3]; /* 0x09C */ CPaneMgr* field_0x9c[3];
/* 0x0A8 */ int field_0xa8; /* 0x0A8 */ int field_0xa8;
/* 0x0AC */ dKantera_icon_c* mpKanteraMeter[2]; /* 0x0AC */ dKantera_icon_c* mpKanteraMeter[2];
+2 -1
View File
@@ -12,7 +12,7 @@
static const int DEFAULT_SELECT_ITEM_INDEX = 0; static const int DEFAULT_SELECT_ITEM_INDEX = 0;
static const int MAX_SELECT_ITEM = 4; static const int MAX_SELECT_ITEM = 4;
static const int SELECT_ITEM_NUM = 2; static const int SELECT_ITEM_NUM = 3;
static const int MAX_EQUIPMENT = 6; static const int MAX_EQUIPMENT = 6;
static const int MAX_EVENTS = 256; static const int MAX_EVENTS = 256;
static const int MAX_ITEM_SLOTS = 24; static const int MAX_ITEM_SLOTS = 24;
@@ -123,6 +123,7 @@ enum {
/* 0x3 */ SELECT_ITEM_B, /* 0x3 */ SELECT_ITEM_B,
/* 0x0 */ SELECT_ITEM_X = SELECT_ITEM_LEFT, /* 0x0 */ SELECT_ITEM_X = SELECT_ITEM_LEFT,
/* 0x1 */ SELECT_ITEM_Y = SELECT_ITEM_RIGHT, /* 0x1 */ SELECT_ITEM_Y = SELECT_ITEM_RIGHT,
/* 0x2 */ SELECT_ITEM_Z = SELECT_ITEM_DOWN,
}; };
enum { enum {
+11
View File
@@ -1,8 +1,19 @@
#pragma once #pragma once
#include <cmath>
#include <dolphin/types.h> #include <dolphin/types.h>
namespace dusk::audio { namespace dusk::audio {
// Converts a 0-1 volume to a linear amplitude multiplier.
// The curve is -4 dB per 10% step: 100% = 0 dB, 90% = -4 dB, ..., 0% = -inf dB
inline f32 MasterVolumeToLinear(f32 v) {
if (v <= 0.0f) {
return 0.0f;
}
return std::pow(10.0f, (v - 1.0f) * 2.0f);
}
/** /**
* Initialize the audio system and start playing audio. * Initialize the audio system and start playing audio.
*/ */
+14 -1
View File
@@ -175,6 +175,7 @@ class ConfigVar : public ConfigVarBase {
T defaultValue; T defaultValue;
T value; T value;
T overrideValue; T overrideValue;
ConfigVarLayer priorLayer = ConfigVarLayer::Default;
public: public:
/** /**
@@ -265,6 +266,7 @@ public:
void setSpeedrunValue(T newValue) { void setSpeedrunValue(T newValue) {
checkRegistered(); checkRegistered();
if (layer != ConfigVarLayer::Override) { if (layer != ConfigVarLayer::Override) {
priorLayer = layer;
overrideValue = std::move(newValue); overrideValue = std::move(newValue);
layer = ConfigVarLayer::Speedrun; layer = ConfigVarLayer::Speedrun;
} }
@@ -282,9 +284,20 @@ public:
checkRegistered(); checkRegistered();
if (layer == ConfigVarLayer::Speedrun) { if (layer == ConfigVarLayer::Speedrun) {
overrideValue = {}; overrideValue = {};
layer = ConfigVarLayer::Value; layer = priorLayer;
} }
} }
/**
* \brief Get the user-persisted value, ignoring any temporary overrides.
*
* Used by Save() to write the correct value even when a speedrun override is active.
*/
[[nodiscard]] constexpr const T& getValueForSave() const noexcept {
checkRegistered();
const ConfigVarLayer effectiveLayer = (layer == ConfigVarLayer::Speedrun) ? priorLayer : layer;
return effectiveLayer == ConfigVarLayer::Default ? defaultValue : value;
}
}; };
using ActionBindConfigVar = ConfigVar<int>; using ActionBindConfigVar = ConfigVar<int>;
-1
View File
@@ -14,7 +14,6 @@ constexpr const char* SHOW_DEBUG_OVERLAY = "F3";
constexpr const char* SHOW_HEAP_VIEWER = "F4"; constexpr const char* SHOW_HEAP_VIEWER = "F4";
constexpr const char* SHOW_PLAYER_INFO = "F5"; constexpr const char* SHOW_PLAYER_INFO = "F5";
constexpr const char* SHOW_SAVE_EDITOR = "F6"; constexpr const char* SHOW_SAVE_EDITOR = "F6";
constexpr const char* SHOW_MAP_LOADER = "F7";
constexpr const char* SHOW_STATE_SHARE = "F8"; constexpr const char* SHOW_STATE_SHARE = "F8";
constexpr const char* SHOW_DEBUG_CAMERA = "F9"; constexpr const char* SHOW_DEBUG_CAMERA = "F9";
constexpr const char* SHOW_AUDIO_DEBUG = "F10"; constexpr const char* SHOW_AUDIO_DEBUG = "F10";
+1
View File
@@ -10,6 +10,7 @@ extern bool IsShuttingDown;
extern bool IsGameLaunched; extern bool IsGameLaunched;
extern bool RestartRequested; extern bool RestartRequested;
extern std::filesystem::path ConfigPath; extern std::filesystem::path ConfigPath;
extern std::filesystem::path CachePath;
#if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS) || \ #if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS) || \
(defined(TARGET_OS_TV) && TARGET_OS_TV) (defined(TARGET_OS_TV) && TARGET_OS_TV)
+2
View File
@@ -158,6 +158,7 @@ struct UserSettings {
// Cheats // Cheats
ConfigVar<bool> infiniteHearts; ConfigVar<bool> infiniteHearts;
ConfigVar<bool> infiniteArrows; ConfigVar<bool> infiniteArrows;
ConfigVar<bool> infiniteSeeds;
ConfigVar<bool> infiniteBombs; ConfigVar<bool> infiniteBombs;
ConfigVar<bool> infiniteOil; ConfigVar<bool> infiniteOil;
ConfigVar<bool> infiniteOxygen; ConfigVar<bool> infiniteOxygen;
@@ -171,6 +172,7 @@ struct UserSettings {
ConfigVar<bool> fastRoll; ConfigVar<bool> fastRoll;
ConfigVar<bool> fastSpinner; ConfigVar<bool> fastSpinner;
ConfigVar<bool> freeMagicArmor; ConfigVar<bool> freeMagicArmor;
ConfigVar<bool> invincibleEnemies;
// Technical // Technical
ConfigVar<bool> restoreWiiGlitches; ConfigVar<bool> restoreWiiGlitches;
+20 -20
View File
@@ -4552,7 +4552,7 @@ void daAlink_c::playerInit() {
PLAYER_CREATE_ANM_HEAP(mFaceBtkHeap, daPy_anmHeap_c::HEAP_TYPE_2, "daAlink_c::mFaceBtkHeap"); PLAYER_CREATE_ANM_HEAP(mFaceBtkHeap, daPy_anmHeap_c::HEAP_TYPE_2, "daAlink_c::mFaceBtkHeap");
PLAYER_CREATE_ANM_HEAP(mFaceBckHeap, daPy_anmHeap_c::HEAP_TYPE_3, "daAlink_c::mFaceBckHeap"); PLAYER_CREATE_ANM_HEAP(mFaceBckHeap, daPy_anmHeap_c::HEAP_TYPE_3, "daAlink_c::mFaceBckHeap");
for (i = 0; i < 2; i++) { for (i = 0; i < SELECT_ITEM_NUM; i++) {
mItemHeap[i].setBufferSize(0x13200); mItemHeap[i].setBufferSize(0x13200);
PLAYER_CREATE_ANM_HEAP_F(mItemHeap[i], daPy_anmHeap_c::HEAP_TYPE_4, "daAlink_c::mItemHeap[%d]", i); PLAYER_CREATE_ANM_HEAP_F(mItemHeap[i], daPy_anmHeap_c::HEAP_TYPE_4, "daAlink_c::mItemHeap[%d]", i);
} }
@@ -9494,7 +9494,7 @@ void daAlink_c::setStickData() {
if (mDoCPd_c::getTrigY(PAD_1)) { if (mDoCPd_c::getTrigY(PAD_1)) {
mItemTrigger |= (daAlink_ITEM_BTN)BTN_Y; mItemTrigger |= (daAlink_ITEM_BTN)BTN_Y;
} }
if (mDoCPd_c::getTrigZ(PAD_1)) { if (mDoCPd_c::getTrigZ(PAD_1) && !mDoCPd_c::getHoldR(PAD_1)) {
mItemTrigger |= (daAlink_ITEM_BTN)BTN_Z; mItemTrigger |= (daAlink_ITEM_BTN)BTN_Z;
} }
if (mDoCPd_c::getTrigL(PAD_1)) { if (mDoCPd_c::getTrigL(PAD_1)) {
@@ -11297,8 +11297,8 @@ BOOL daAlink_c::checkUpperItemActionFly() {
void daAlink_c::checkItemButtonChange() { void daAlink_c::checkItemButtonChange() {
if (mProcID != PROC_CANOE_PADDLE_PUT && mEquipItem != dItemNo_NONE_e && !checkEquipAnime()) { if (mProcID != PROC_CANOE_PADDLE_PUT && mEquipItem != dItemNo_NONE_e && !checkEquipAnime()) {
u8 temp_r0; u8 temp_r0;
for (u8 i = 0; i < 2; i++) { for (u8 i = 0; i < SELECT_ITEM_NUM; i++) {
temp_r0 = (i + 1) % 2; temp_r0 = (i + 1) % SELECT_ITEM_NUM;
if (mEquipItem == dComIfGp_getSelectItem(i) && if (mEquipItem == dComIfGp_getSelectItem(i) &&
(mEquipItem != dComIfGp_getSelectItem(temp_r0) || mSelectItemId != temp_r0)) (mEquipItem != dComIfGp_getSelectItem(temp_r0) || mSelectItemId != temp_r0))
{ {
@@ -11468,8 +11468,8 @@ int daAlink_c::orderTalk(int i_checkZTalk) {
} }
if (!checkWolf() && checkRequestTalkActor(mAttList2, field_0x27f8)) { if (!checkWolf() && checkRequestTalkActor(mAttList2, field_0x27f8)) {
for (int i = 0; i < 2; i++) { for (int i = 0; i < 3; i++) {
// check if pressed X or Y and if item on button is a trade item // check if pressed X or Y or Z and if item on button is a trade item
if (checkTradeItem(dComIfGp_getSelectItem(i)) && itemTriggerCheck(1 << i)) { if (checkTradeItem(dComIfGp_getSelectItem(i)) && itemTriggerCheck(1 << i)) {
fopAcM_orderTalkItemBtnEvent(itemTalkType[i], this, field_0x27f8, 0, 0); fopAcM_orderTalkItemBtnEvent(itemTalkType[i], this, field_0x27f8, 0, 0);
return 1; return 1;
@@ -12107,7 +12107,7 @@ void daAlink_c::allUnequip(BOOL param_0) {
if (checkNoResetFlg2(FLG2_UNK_1) && param_0 && !checkCanoeRide() && if (checkNoResetFlg2(FLG2_UNK_1) && param_0 && !checkCanoeRide() &&
mEquipItem != dItemNo_KANTERA_e) mEquipItem != dItemNo_KANTERA_e)
{ {
for (u8 i = 0; i < 2; i++) { for (u8 i = 0; i < SELECT_ITEM_NUM; i++) {
if (dComIfGp_getSelectItem(i) == dItemNo_KANTERA_e) { if (dComIfGp_getSelectItem(i) == dItemNo_KANTERA_e) {
mSelectItemId = i; mSelectItemId = i;
} }
@@ -12159,7 +12159,7 @@ BOOL daAlink_c::checkItemChangeFromButton() {
itemEquip(0x105); itemEquip(0x105);
} else { } else {
u8 i; u8 i;
for (i = 0; i < 2; i++) { for (i = 0; i < SELECT_ITEM_NUM; i++) {
int proc_type = checkNewItemChange(i); int proc_type = checkNewItemChange(i);
if (proc_type != 0 && itemTriggerCheck(1 << i)) { if (proc_type != 0 && itemTriggerCheck(1 << i)) {
BOOL var_r27 = changeItemTriggerKeepProc(i, proc_type); BOOL var_r27 = changeItemTriggerKeepProc(i, proc_type);
@@ -12180,7 +12180,7 @@ BOOL daAlink_c::checkItemChangeFromButton() {
} else if (mEquipItem == dItemNo_NONE_e && mThrowBoomerangAcKeep.getActor() == NULL && } else if (mEquipItem == dItemNo_NONE_e && mThrowBoomerangAcKeep.getActor() == NULL &&
!checkCanoeRide() && checkNoUpperAnime() && checkNoResetFlg2(FLG2_UNK_1)) !checkCanoeRide() && checkNoUpperAnime() && checkNoResetFlg2(FLG2_UNK_1))
{ {
for (i = 0; i < 2; i++) { for (i = 0; i < SELECT_ITEM_NUM; i++) {
if (dComIfGp_getSelectItem(i) == dItemNo_KANTERA_e) { if (dComIfGp_getSelectItem(i) == dItemNo_KANTERA_e) {
mSelectItemId = i; mSelectItemId = i;
} }
@@ -12192,7 +12192,7 @@ BOOL daAlink_c::checkItemChangeFromButton() {
mEquipItem != 0x102 && (!checkCanoeRide() || !checkFisingRodLure())) mEquipItem != 0x102 && (!checkCanoeRide() || !checkFisingRodLure()))
{ {
if (!checkEventRun() || strcmp(dComIfGp_getEventManager().getRunEventName(), "ANGER") != 0) { if (!checkEventRun() || strcmp(dComIfGp_getEventManager().getRunEventName(), "ANGER") != 0) {
if (strcmp(dComIfGp_getEventManager().getRunEventName(), "ANGER2") != 0 && checkItemSetButton(mEquipItem) == 2) { if (strcmp(dComIfGp_getEventManager().getRunEventName(), "ANGER2") != 0 && checkItemSetButton(mEquipItem) == 3) {
allUnequip(1); allUnequip(1);
} }
} }
@@ -14386,7 +14386,7 @@ BOOL daAlink_c::checkGroupItem(int i_itemNo, int i_selItem) const {
} }
int daAlink_c::checkSetItemTrigger(int i_itemNo) { int daAlink_c::checkSetItemTrigger(int i_itemNo) {
for (u8 i = 0; i < 2; i++) { for (u8 i = 0; i < SELECT_ITEM_NUM; i++) {
if (checkGroupItem(i_itemNo, dComIfGp_getSelectItem(i)) && itemTriggerCheck(1 << i)) { if (checkGroupItem(i_itemNo, dComIfGp_getSelectItem(i)) && itemTriggerCheck(1 << i)) {
if (i_itemNo != dItemNo_HVY_BOOTS_e) { if (i_itemNo != dItemNo_HVY_BOOTS_e) {
mSelectItemId = i; mSelectItemId = i;
@@ -14399,13 +14399,13 @@ int daAlink_c::checkSetItemTrigger(int i_itemNo) {
} }
int daAlink_c::checkItemSetButton(int i_itemNo) { int daAlink_c::checkItemSetButton(int i_itemNo) {
for (u8 i = 0; i < 2; i++) { for (u8 i = 0; i < SELECT_ITEM_NUM; i++) {
if (checkGroupItem(i_itemNo, dComIfGp_getSelectItem(i))) { if (checkGroupItem(i_itemNo, dComIfGp_getSelectItem(i))) {
return i; return i;
} }
} }
return 2; return 3;
} }
bool daAlink_c::checkField() { bool daAlink_c::checkField() {
@@ -14605,7 +14605,7 @@ int daAlink_c::checkNewItemChange(u8 i_selItemIdx) {
return ITEM_PROC_BOTTLE_DRINK; return ITEM_PROC_BOTTLE_DRINK;
} }
if (checkOilBottleItem(sel_item) && checkItemSetButton(dItemNo_KANTERA_e) != 2) { if (checkOilBottleItem(sel_item) && checkItemSetButton(dItemNo_KANTERA_e) != 3) {
return ITEM_PROC_KANDELAAR_POUR; return ITEM_PROC_KANDELAAR_POUR;
} }
} else if (sel_item == dItemNo_HVY_BOOTS_e) { } else if (sel_item == dItemNo_HVY_BOOTS_e) {
@@ -14650,7 +14650,7 @@ int daAlink_c::checkNewItemChange(u8 i_selItemIdx) {
return ITEM_PROC_SPINNER_READY; return ITEM_PROC_SPINNER_READY;
} else if (checkDungeonWarpItem(sel_item)) { } else if (checkDungeonWarpItem(sel_item)) {
return ITEM_PROC_DUNGEON_WARP_READY; return ITEM_PROC_DUNGEON_WARP_READY;
} else if (checkItemSetButton(0x108) != 2 && } else if (checkItemSetButton(0x108) != 3 &&
(sel_item == dItemNo_WORM_e || sel_item == dItemNo_BEE_CHILD_e)) (sel_item == dItemNo_WORM_e || sel_item == dItemNo_BEE_CHILD_e))
{ {
int itemNo = dComIfGp_getSelectItem(checkItemSetButton(0x108)); int itemNo = dComIfGp_getSelectItem(checkItemSetButton(0x108));
@@ -14674,7 +14674,7 @@ int daAlink_c::checkNewItemChange(u8 i_selItemIdx) {
return ITEM_PROC_NOT_USE_ITEM; return ITEM_PROC_NOT_USE_ITEM;
} else if (sel_item == dItemNo_HORSE_FLUTE_e) { } else if (sel_item == dItemNo_HORSE_FLUTE_e) {
return ITEM_PROC_GRASS_WHISTLE; return ITEM_PROC_GRASS_WHISTLE;
} else if (checkOilBottleItem(sel_item) && checkItemSetButton(0x48) != 2) { } else if (checkOilBottleItem(sel_item) && checkItemSetButton(0x48) != 3) {
return ITEM_PROC_KANDELAAR_POUR; return ITEM_PROC_KANDELAAR_POUR;
} else if (sel_item == dItemNo_HAWK_EYE_e) { } else if (sel_item == dItemNo_HAWK_EYE_e) {
if (acceptSubjectModeChange()) { if (acceptSubjectModeChange()) {
@@ -17826,7 +17826,7 @@ int daAlink_c::execute() {
if (checkNoResetFlg2(FLG2_UNK_1) != FALSE && if (checkNoResetFlg2(FLG2_UNK_1) != FALSE &&
mEquipItem != dItemNo_KANTERA_e && mEquipItem != dItemNo_KANTERA_e &&
checkItemSetButton(dItemNo_KANTERA_e) == 2) { checkItemSetButton(dItemNo_KANTERA_e) == 3) {
offKandelaarModel(); offKandelaarModel();
} }
@@ -18215,7 +18215,7 @@ int daAlink_c::execute() {
if (checkEquipHeavyBoots()) { if (checkEquipHeavyBoots()) {
int itemButton = checkItemSetButton(dItemNo_HVY_BOOTS_e); int itemButton = checkItemSetButton(dItemNo_HVY_BOOTS_e);
if (itemButton == 2 || checkNotHeavyBootsStage()) { if (itemButton == 3 || checkNotHeavyBootsStage()) {
if (!dComIfGp_checkPlayerStatus1(0, 0x10000) || !checkHookshotRoofLv7Boss()) { if (!dComIfGp_checkPlayerStatus1(0, 0x10000) || !checkHookshotRoofLv7Boss()) {
setHeavyBoots(0); setHeavyBoots(0);
} }
@@ -18737,7 +18737,7 @@ int daAlink_c::execute() {
if (!checkWolf()) { if (!checkWolf()) {
u8 tmp; u8 tmp;
for (u8 i = 0; i < 2; i++) { for (u8 i = 0; i < SELECT_ITEM_NUM; i++) {
tmp = (i + 1) % 2; tmp = (i + 1) % 2;
if (dComIfGp_getSelectItem(i) == dItemNo_EMPTY_BOTTLE_e && (mUseButtonFlags & (1 << i)) && if (dComIfGp_getSelectItem(i) == dItemNo_EMPTY_BOTTLE_e && (mUseButtonFlags & (1 << i)) &&
dComIfGp_getSelectItem(tmp) == dItemNo_EMPTY_BOTTLE_e) dComIfGp_getSelectItem(tmp) == dItemNo_EMPTY_BOTTLE_e)
@@ -18747,7 +18747,7 @@ int daAlink_c::execute() {
} }
} }
for (int i = 0; i < 2; i++) { for (int i = 0; i < SELECT_ITEM_NUM; i++) {
if (!(mUseButtonFlags & (1 << i)) && !(field_0x2faf & (1 << i))) { if (!(mUseButtonFlags & (1 << i)) && !(field_0x2faf & (1 << i))) {
dMeter2Info_offUseButton(METER2_USEBUTTON_X << i); dMeter2Info_offUseButton(METER2_USEBUTTON_X << i);
} }
+1 -1
View File
@@ -4121,7 +4121,7 @@ int daAlink_c::procDungeonWarpReadyInit() {
} }
fpc_ProcID id; fpc_ProcID id;
if (checkItemSetButton(dItemNo_DUNGEON_EXIT_e) != 2) { if (checkItemSetButton(dItemNo_DUNGEON_EXIT_e) != 3) {
id = fopAcM_create(fpcNm_OBJ_TKS_e, 0, &current.pos, fopAcM_GetRoomNo(this), &shape_angle, id = fopAcM_create(fpcNm_OBJ_TKS_e, 0, &current.pos, fopAcM_GetRoomNo(this), &shape_angle,
NULL, -1); NULL, -1);
} else { } else {
+1 -1
View File
@@ -211,7 +211,7 @@ int daAlink_c::procSpinnerWait() {
mProcVar3.field_0x300e = shape_angle.y; mProcVar3.field_0x300e = shape_angle.y;
} }
} else { } else {
if (checkSetItemTrigger(dItemNo_SPINNER_e) || swordSwingTrigger() || itemSetBtn == 2) { if (checkSetItemTrigger(dItemNo_SPINNER_e) || swordSwingTrigger() || itemSetBtn == SELECT_ITEM_NUM) {
if (swordSwingTrigger()) { if (swordSwingTrigger()) {
swordEquip(0); swordEquip(0);
} }
+6 -1
View File
@@ -77,7 +77,12 @@ int daAlink_c::loadModelDVD() {
mpWlMidnaHairModel = NULL; mpWlMidnaHairModel = NULL;
if (!checkNoResetFlg2(FLG2_UNK_280000)) { if (!checkNoResetFlg2(FLG2_UNK_280000)) {
dComIfG_resDelete(&mPhaseReq, mArcName); if (!dComIfG_resDelete(&mPhaseReq, mArcName)) {
#if TARGET_PC
// resDelete no-ops if load was in-progress; force-unregister before freeAll
dComIfG_deleteObjectResMain(mArcName);
#endif
}
cPhs_Reset(&mPhaseReq); cPhs_Reset(&mPhaseReq);
mpArcHeap->freeAll(); mpArcHeap->freeAll();
+6
View File
@@ -8723,6 +8723,12 @@ int daAlink_c::procWolfCargoCarry() {
return checkNextActionWolf(0); return checkNextActionWolf(0);
} }
#if TARGET_PC
if (field_0x280c.getActor() == NULL) {
return checkNextActionWolf(0);
}
#endif
mDoMtx_stack_c::copy(((e_yc_class*)field_0x280c.getActor())->getLegR3Mtx()); mDoMtx_stack_c::copy(((e_yc_class*)field_0x280c.getActor())->getLegR3Mtx());
mDoMtx_stack_c::transM(-9.0f, -7.0f, -30.0f); mDoMtx_stack_c::transM(-9.0f, -7.0f, -30.0f);
mDoMtx_stack_c::multVecZero(&current.pos); mDoMtx_stack_c::multVecZero(&current.pos);
+6
View File
@@ -7053,6 +7053,12 @@ static int daE_RD_IsDelete(e_rd_class*) {
} }
static int daE_RD_Delete(e_rd_class* i_this) { static int daE_RD_Delete(e_rd_class* i_this) {
#if TARGET_PC
if (boss == i_this) {
boss = NULL;
}
#endif
fopEn_enemy_c* enemy = (fopEn_enemy_c*)&i_this->enemy; fopEn_enemy_c* enemy = (fopEn_enemy_c*)&i_this->enemy;
fopAcM_RegisterDeleteID(i_this, "E_RD"); fopAcM_RegisterDeleteID(i_this, "E_RD");
+8
View File
@@ -15,6 +15,7 @@
#include "f_op/f_op_actor_mng.h" #include "f_op/f_op_actor_mng.h"
#if TARGET_PC #if TARGET_PC
#include "dusk/achievements.h" #include "dusk/achievements.h"
#include "dusk/settings.h"
#endif #endif
static int plCutLRC[58] = { static int plCutLRC[58] = {
@@ -429,6 +430,13 @@ fopAc_ac_c* cc_at_check(fopAc_ac_c* i_enemy, dCcU_AtInfo* i_AtInfo) {
} }
} }
#if TARGET_PC
if (dusk::getSettings().game.invincibleEnemies &&
fopAcM_GetGroup(i_enemy) == fopAc_ENEMY_e) {
i_AtInfo->mAttackPower = 0;
}
#endif
if (i_AtInfo->mAttackPower != 0) { if (i_AtInfo->mAttackPower != 0) {
i_enemy->health -= i_AtInfo->mAttackPower; i_enemy->health -= i_AtInfo->mAttackPower;
} }
+3 -13
View File
@@ -1952,18 +1952,7 @@ u8 dComIfGs_getMixItemIndex(int i_no) {
} }
void dComIfGp_setSelectItem(int i_selItemIdx) { void dComIfGp_setSelectItem(int i_selItemIdx) {
if (i_selItemIdx == SELECT_ITEM_DOWN) { if (dComIfGs_getSelectItemIndex(i_selItemIdx) != 0xFF) {
if (dComIfGs_getSelectItemIndex(i_selItemIdx) != 0xFF) {
u8 selItem_slotNo = dComIfGs_getSelectItemIndex(i_selItemIdx);
g_dComIfG_gameInfo.play.setSelectItem(i_selItemIdx, selItem_slotNo);
if (selItem_slotNo == 0xFF) {
dComIfGs_setSelectItemIndex(i_selItemIdx, 0xFF);
}
} else {
g_dComIfG_gameInfo.play.setSelectItem(i_selItemIdx, dItemNo_NONE_e);
}
} else if (dComIfGs_getSelectItemIndex(i_selItemIdx) != 0xFF) {
u8 item = dComIfGs_getItem(dComIfGs_getSelectItemIndex(i_selItemIdx), false); u8 item = dComIfGs_getItem(dComIfGs_getSelectItemIndex(i_selItemIdx), false);
g_dComIfG_gameInfo.play.setSelectItem(i_selItemIdx, item); g_dComIfG_gameInfo.play.setSelectItem(i_selItemIdx, item);
@@ -1978,7 +1967,8 @@ void dComIfGp_setSelectItem(int i_selItemIdx) {
u8 dComIfGp_getSelectItem(int i_selItemIdx) { u8 dComIfGp_getSelectItem(int i_selItemIdx) {
u8 playItem = g_dComIfG_gameInfo.play.getSelectItem(i_selItemIdx); u8 playItem = g_dComIfG_gameInfo.play.getSelectItem(i_selItemIdx);
if ((i_selItemIdx == SELECT_ITEM_X || i_selItemIdx == SELECT_ITEM_Y) && if ((i_selItemIdx == SELECT_ITEM_X || i_selItemIdx == SELECT_ITEM_Y ||
i_selItemIdx == SELECT_ITEM_Z) &&
dComIfGs_getMixItemIndex(i_selItemIdx) != 0xFF) dComIfGs_getMixItemIndex(i_selItemIdx) != 0xFF)
{ {
u8 saveItem = dComIfGs_getItem(dComIfGs_getMixItemIndex(i_selItemIdx), false); u8 saveItem = dComIfGs_getItem(dComIfGs_getMixItemIndex(i_selItemIdx), false);
+4
View File
@@ -3882,7 +3882,11 @@ bool dCamera_c::hintTalkEvCamera() {
cSAngle acStack_1fc(20.0f); cSAngle acStack_1fc(20.0f);
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
#if AVOID_UB
for (j = 0; j < 10; j++) {
#else
for (j = 0; j < 12; j++) { for (j = 0; j < 12; j++) {
#endif
cSAngle acStack_200(local_b0[j] * fVar22); cSAngle acStack_200(local_b0[j] * fVar22);
hintTalk->mDirection.U(acStack_1f8 + acStack_200); hintTalk->mDirection.U(acStack_1f8 + acStack_200);
hintTalk->mDirection.V(((hintTalk->field_0x28.V() * acStack_200.Cos()) * 0.2f) + acStack_1fc); hintTalk->mDirection.V(((hintTalk->field_0x28.V() * acStack_200.Cos()) * 0.2f) + acStack_1fc);
+4
View File
@@ -287,6 +287,10 @@ int dEvt_control_c::talkXyCheck(dEvt_order_c* order) {
mTalkXyType = 2; mTalkXyType = 2;
itemIndex = SELECT_ITEM_Y; itemIndex = SELECT_ITEM_Y;
break; break;
case dEvt_type_SHOWITEM_Z_e:
mTalkXyType = 3;
itemIndex = SELECT_ITEM_Z;
break;
#if PLATFORM_WII || PLATFORM_SHIELD #if PLATFORM_WII || PLATFORM_SHIELD
case 8: case 8:
mTalkXyType = 3; mTalkXyType = 3;
+3 -1
View File
@@ -446,7 +446,7 @@ void dMenu_ItemExplain_c::move_proc() {
if (field_0xe7 == 0) { if (field_0xe7 == 0) {
return; return;
} }
if (!mDoCPd_c::getTrigX(PAD_1) && !mDoCPd_c::getTrigY(PAD_1)) { if (!mDoCPd_c::getTrigX(PAD_1) && !mDoCPd_c::getTrigY(PAD_1) && !mDoCPd_c::getTrigZ(PAD_1)) {
return; return;
} }
} }
@@ -460,6 +460,8 @@ void dMenu_ItemExplain_c::move_proc() {
mEndButton = 3; mEndButton = 3;
} else if (mDoCPd_c::getTrigY(PAD_1)) { } else if (mDoCPd_c::getTrigY(PAD_1)) {
mEndButton = 4; mEndButton = 4;
} else if (mDoCPd_c::getTrigZ(PAD_1)) {
mEndButton = 5;
} }
mStatus = 5; mStatus = 5;
Z2GetAudioMgr()->seStart(Z2SE_SY_EXP_WIN_CLOSE, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0); Z2GetAudioMgr()->seStart(Z2SE_SY_EXP_WIN_CLOSE, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
+45 -15
View File
@@ -134,7 +134,7 @@ dMenu_Ring_c::dMenu_Ring_c(JKRExpHeap* i_heap, STControl* i_stick, CSTControl* i
field_0x6a9 = 0; field_0x6a9 = 0;
mXButtonSlot = 0xff; mXButtonSlot = 0xff;
mYButtonSlot = 0xff; mYButtonSlot = 0xff;
field_0x6ac = 0xff; mZButtonSlot = 0xff;
field_0x6ad = 0xff; field_0x6ad = 0xff;
field_0x670 = 0; field_0x670 = 0;
field_0x67e = 0; field_0x67e = 0;
@@ -244,8 +244,8 @@ dMenu_Ring_c::dMenu_Ring_c(JKRExpHeap* i_heap, STControl* i_stick, CSTControl* i
if (dComIfGs_getSelectItemIndex(1) == dComIfGs_getLineUpItem(i)) { if (dComIfGs_getSelectItemIndex(1) == dComIfGs_getLineUpItem(i)) {
mYButtonSlot = i; mYButtonSlot = i;
} }
if (dComIfGs_getSelectItemIndex(2) == dComIfGs_getWolfAbility(i)) { if (dComIfGs_getSelectItemIndex(2) == dComIfGs_getLineUpItem(i)) {
field_0x6ac = i; mZButtonSlot = i;
} }
} }
mRingRadiusH = g_ringHIO.mRingRadiusH; mRingRadiusH = g_ringHIO.mRingRadiusH;
@@ -259,7 +259,7 @@ dMenu_Ring_c::dMenu_Ring_c(JKRExpHeap* i_heap, STControl* i_stick, CSTControl* i
} }
} }
field_0x6be[i] = 0; field_0x6be[i] = 0;
if (i == 2) { if (i == MAX_SELECT_ITEM) {
setSelectItem(i, 0); setSelectItem(i, 0);
} else { } else {
setSelectItem(i, 0x43); setSelectItem(i, 0x43);
@@ -977,8 +977,8 @@ void dMenu_Ring_c::setItem() {
} else { } else {
uVar2 = dItemNo_NONE_e; uVar2 = dItemNo_NONE_e;
} }
if (field_0x6ac != dItemNo_NONE_e) { if (mZButtonSlot != dItemNo_NONE_e) {
uVar3 = mItemSlots[field_0x6ac]; uVar3 = mItemSlots[mZButtonSlot];
} else { } else {
uVar3 = dItemNo_NONE_e; uVar3 = dItemNo_NONE_e;
} }
@@ -1058,6 +1058,9 @@ void dMenu_Ring_c::setItem() {
mixItemIndex1 = dItemNo_NONE_e; mixItemIndex1 = dItemNo_NONE_e;
} }
} }
} else if (field_0x6b3 == 2) {
mZButtonSlot = mCurrentSlot;
uVar3 = mItemSlots[mZButtonSlot];
} }
field_0x6b4[0] = uVar1; field_0x6b4[0] = uVar1;
field_0x6b4[1] = uVar2; field_0x6b4[1] = uVar2;
@@ -1073,7 +1076,7 @@ void dMenu_Ring_c::setItem() {
void dMenu_Ring_c::setJumpItem(bool i_useVibrationM) { void dMenu_Ring_c::setJumpItem(bool i_useVibrationM) {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (i == 2) { if (i == 4) {
setSelectItem(i, field_0x6b4[i]); setSelectItem(i, field_0x6b4[i]);
} else if (i == field_0x6cd) { } else if (i == field_0x6cd) {
setSelectItem(i, getItem(field_0x6cb, 0)); setSelectItem(i, getItem(field_0x6cb, 0));
@@ -1089,9 +1092,9 @@ void dMenu_Ring_c::setJumpItem(bool i_useVibrationM) {
field_0x518[1] = mItemSlotPosX[mYButtonSlot]; field_0x518[1] = mItemSlotPosX[mYButtonSlot];
field_0x528[1] = mItemSlotPosY[mYButtonSlot]; field_0x528[1] = mItemSlotPosY[mYButtonSlot];
} }
if (field_0x6ac != dItemNo_NONE_e) { if (mZButtonSlot != dItemNo_NONE_e) {
field_0x518[2] = mItemSlotPosX[field_0x6ac]; field_0x518[2] = mItemSlotPosX[mZButtonSlot];
field_0x528[2] = mItemSlotPosY[field_0x6ac]; field_0x528[2] = mItemSlotPosY[mZButtonSlot];
} }
if (field_0x6ad != dItemNo_NONE_e) { if (field_0x6ad != dItemNo_NONE_e) {
field_0x518[3] = mItemSlotPosX[field_0x6ad]; field_0x518[3] = mItemSlotPosX[field_0x6ad];
@@ -1117,9 +1120,21 @@ void dMenu_Ring_c::setJumpItem(bool i_useVibrationM) {
field_0x674[1] = 1; field_0x674[1] = 1;
#if TARGET_PC #if TARGET_PC
mSelectItemSlideElapsed[1] = 0.0f; mSelectItemSlideElapsed[1] = 0.0f;
#endif
}
} else if (field_0x6b3 == 2) {
field_0x538[0] = g_ringHIO.mUnselectItemScale;
field_0x538[1] = g_ringHIO.mSelectItemScale;
if (field_0x6b4[2] != dComIfGs_getSelectItemIndex(2) ||
field_0x6b8[2] != dComIfGs_getMixItemIndex(2))
{
field_0x674[2] = 1;
#if TARGET_PC
mSelectItemSlideElapsed[2] = 0.0f;
#endif #endif
} }
} }
if (field_0x674[0] == 1) { if (field_0x674[0] == 1) {
if (i_useVibrationM) { if (i_useVibrationM) {
dMeter2Info_set2DVibrationM(); dMeter2Info_set2DVibrationM();
@@ -1160,7 +1175,7 @@ void dMenu_Ring_c::setScale() {
} }
setNameString(itemId); setNameString(itemId);
setItemScale(i, g_ringHIO.mUnselectItemScale); setItemScale(i, g_ringHIO.mUnselectItemScale);
for (int j = 0; j < 2; j++) { for (int j = 0; j < SELECT_ITEM_NUM; j++) {
if (j == field_0x6cf) { if (j == field_0x6cf) {
setButtonScale(j, g_ringHIO.mSelectButtonScale); setButtonScale(j, g_ringHIO.mSelectButtonScale);
} else { } else {
@@ -1180,7 +1195,7 @@ void dMenu_Ring_c::setScale() {
} else { } else {
setItemScale(i, g_ringHIO.mUnselectItemScale); setItemScale(i, g_ringHIO.mUnselectItemScale);
} }
for (int j = 0; j < 2; j++) { for (int j = 0; j < SELECT_ITEM_NUM; j++) {
setButtonScale(j, g_ringHIO.mUnselectButtonScale); setButtonScale(j, g_ringHIO.mUnselectButtonScale);
} }
} }
@@ -1214,6 +1229,7 @@ void dMenu_Ring_c::setNameString(u32 i_stringID) {
void dMenu_Ring_c::setActiveCursor() { void dMenu_Ring_c::setActiveCursor() {
u8 item = dComIfGs_getItem(mItemSlots[mCurrentSlot], false); u8 item = dComIfGs_getItem(mItemSlots[mCurrentSlot], false);
if (mStatus == STATUS_WAIT && mOldStatus != STATUS_EXPLAIN_FORCE && mOldStatus != STATUS_EXPLAIN && mpItemExplain->getStatus() == 0) { if (mStatus == STATUS_WAIT && mOldStatus != STATUS_EXPLAIN_FORCE && mOldStatus != STATUS_EXPLAIN && mpItemExplain->getStatus() == 0) {
if (mDoCPd_c::getTrigR(PAD_1) && !mPlayerIsWolf && item != dItemNo_NONE_e) { if (mDoCPd_c::getTrigR(PAD_1) && !mPlayerIsWolf && item != dItemNo_NONE_e) {
for (int i = 0; i < MAX_SELECT_ITEM; i++) { for (int i = 0; i < MAX_SELECT_ITEM; i++) {
@@ -1244,7 +1260,21 @@ void dMenu_Ring_c::setActiveCursor() {
(this->*stick_init[mStatus])(); (this->*stick_init[mStatus])();
} }
} }
} else if (mDoCPd_c::getTrigX(PAD_1) || mDoCPd_c::getTrigY(PAD_1)) { } else if (mDoCPd_c::getTrigZ(PAD_1) && !mPlayerIsWolf && item != dItemNo_NONE_e) {
for (int i = 0; i < MAX_SELECT_ITEM; i++) {
setSelectItemForce(i);
}
field_0x6b3 = 2;
if (!checkCombineBomb(field_0x6b3)) {
setItem();
if (mpItemExplain->getStatus() == 0) {
setStatus(STATUS_WAIT);
(this->*stick_init[mStatus])();
}
}
} else if (mDoCPd_c::getTrigX(PAD_1) || mDoCPd_c::getTrigY(PAD_1) ||
mDoCPd_c::getTrigZ(PAD_1))
{
// If the player is a wolf or somehow manages to access an item slot with no item, error // If the player is a wolf or somehow manages to access an item slot with no item, error
Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0); Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
} }
@@ -1660,7 +1690,7 @@ void dMenu_Ring_c::drawSelectItem() {
} }
void dMenu_Ring_c::setSelectItemForce(int i_idx) { void dMenu_Ring_c::setSelectItemForce(int i_idx) {
if (i_idx == 2) { if (i_idx == SELECT_ITEM_NUM) {
if (field_0x674[i_idx] != 0) { if (field_0x674[i_idx] != 0) {
dComIfGs_setSelectItemIndex(i_idx, field_0x6b4[i_idx]); dComIfGs_setSelectItemIndex(i_idx, field_0x6b4[i_idx]);
field_0x674[i_idx] = 0; field_0x674[i_idx] = 0;
@@ -1669,7 +1699,7 @@ void dMenu_Ring_c::setSelectItemForce(int i_idx) {
#endif #endif
} }
} else if (field_0x674[i_idx] != 0) { } else if (field_0x674[i_idx] != 0) {
for (int i = 0; i < 2; i++) { for (int i = 0; i < SELECT_ITEM_NUM; i++) {
dComIfGs_setMixItemIndex(i, field_0x6b8[i]); dComIfGs_setMixItemIndex(i, field_0x6b8[i]);
dComIfGs_setSelectItemIndex(i, field_0x6b4[i]); dComIfGs_setSelectItemIndex(i, field_0x6b4[i]);
} }
+2
View File
@@ -1533,6 +1533,8 @@ void dMeter2Info_c::setMiniGameItem(u8 i_minigameFlag) {
if (mMiniGameItemSetFlag != 3) { if (mMiniGameItemSetFlag != 3) {
dComIfGs_setItem(SLOT_4, dItemNo_BOW_e); dComIfGs_setItem(SLOT_4, dItemNo_BOW_e);
dComIfGp_setItem(SLOT_4, dItemNo_BOW_e); dComIfGp_setItem(SLOT_4, dItemNo_BOW_e);
dComIfGs_setMixItemIndex(SELECT_ITEM_Z, 0xFF);
dComIfGs_setSelectItemIndex(SELECT_ITEM_Z, 0xFF);
dComIfGs_setMixItemIndex(SELECT_ITEM_Y, 0xFF); dComIfGs_setMixItemIndex(SELECT_ITEM_Y, 0xFF);
dComIfGs_setSelectItemIndex(SELECT_ITEM_Y, 0xFF); dComIfGs_setSelectItemIndex(SELECT_ITEM_Y, 0xFF);
dComIfGs_setMixItemIndex(SELECT_ITEM_X, SLOT_4); dComIfGs_setMixItemIndex(SELECT_ITEM_X, SLOT_4);
+10 -4
View File
@@ -26,8 +26,12 @@ void updateAutoSave() {
(AutoSaveFuncsProc[mAutoSaveProc])(); (AutoSaveFuncsProc[mAutoSaveProc])();
} }
void writeAutoSave() { bool writeAutoSave() {
int stageNo = dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo()); stage_stag_info_class* stagInfo = dComIfGp_getStageStagInfo();
if (stagInfo == nullptr) {
return false;
}
int stageNo = dStage_stagInfo_GetSaveTbl(stagInfo);
dComIfGs_putSave(stageNo); dComIfGs_putSave(stageNo);
dComIfGs_setMemoryToCard(mSaveBuffer, dComIfGs_getDataNum()); dComIfGs_setMemoryToCard(mSaveBuffer, dComIfGs_getDataNum());
@@ -40,6 +44,7 @@ void writeAutoSave() {
} }
g_mDoMemCd_control.save(mSaveBuffer, sizeof(mSaveBuffer), 0); g_mDoMemCd_control.save(mSaveBuffer, sizeof(mSaveBuffer), 0);
return true;
} }
void autoSaving() { void autoSaving() {
@@ -48,8 +53,9 @@ void autoSaving() {
if (cardState == 2) { if (cardState == 2) {
mAutoSaveProc = 1; mAutoSaveProc = 1;
} else if (cardState == 1) { } else if (cardState == 1) {
writeAutoSave(); if (writeAutoSave()) {
mAutoSaveProc = 3; mAutoSaveProc = 3;
}
} }
} }
} }
+3 -2
View File
@@ -61,7 +61,7 @@ void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) {
template<ConfigValue T> template<ConfigValue T>
nlohmann::json ConfigImpl<T>::dumpToJson(const ConfigVar<T>& cVar) { nlohmann::json ConfigImpl<T>::dumpToJson(const ConfigVar<T>& cVar) {
return cVar.getValue(); return cVar.getValueForSave();
} }
template<ConfigValue T> requires std::is_integral_v<T> && std::is_signed_v<T> template<ConfigValue T> requires std::is_integral_v<T> && std::is_signed_v<T>
@@ -249,7 +249,8 @@ void dusk::config::Save() {
json j; json j;
for (const auto& pair : RegisteredConfigVars) { for (const auto& pair : RegisteredConfigVars) {
if (pair.second->getLayer() == ConfigVarLayer::Value) { const auto layer = pair.second->getLayer();
if (layer == ConfigVarLayer::Value || layer == ConfigVarLayer::Speedrun) {
j[pair.first] = pair.second->getImpl()->dumpToJson(*pair.second); j[pair.first] = pair.second->getImpl()->dumpToJson(*pair.second);
} }
} }
+1 -1
View File
@@ -61,7 +61,7 @@ std::string release_name() {
} }
std::filesystem::path sentry_database_path() { std::filesystem::path sentry_database_path() {
return dusk::ConfigPath / "sentry"; return dusk::CachePath / "sentry";
} }
std::filesystem::path log_attachment_path() { std::filesystem::path log_attachment_path() {
+222 -93
View File
@@ -6,6 +6,7 @@
#include "dusk/main.h" #include "dusk/main.h"
#include <array> #include <array>
#include <chrono>
#include <filesystem> #include <filesystem>
#include <optional> #include <optional>
#include <ranges> #include <ranges>
@@ -30,6 +31,21 @@ constexpr auto kLocationDescriptorName = "data_location.json";
constexpr auto kPipelineCacheName = "pipeline_cache.db"; constexpr auto kPipelineCacheName = "pipeline_cache.db";
constexpr auto kInitialPipelineCacheName = "initial_pipeline_cache.db"; constexpr auto kInitialPipelineCacheName = "initial_pipeline_cache.db";
constexpr std::array<std::string_view, 4> kUserDataDirectories = {
"texture_replacements",
"USA",
"EUR",
"JAP",
};
constexpr std::array<std::string_view, 6> kUserDataFiles = {
"achievements.json",
"config.json",
"controller_ports.dat",
"imgui.ini",
"keyboard_bindings.dat",
"states.json",
};
enum class LocationMode { enum class LocationMode {
Default, Default,
Portable, Portable,
@@ -62,6 +78,7 @@ struct MigrationStats {
std::optional<std::filesystem::path> sConfiguredDataPath; std::optional<std::filesystem::path> sConfiguredDataPath;
std::optional<std::filesystem::path> sActiveDescriptorPath; std::optional<std::filesystem::path> sActiveDescriptorPath;
std::optional<std::filesystem::path> sActivePrefPath;
std::filesystem::path path_from_utf8(std::string_view value) { std::filesystem::path path_from_utf8(std::string_view value) {
return std::filesystem::path{ return std::filesystem::path{
@@ -70,19 +87,22 @@ std::filesystem::path path_from_utf8(std::string_view value) {
}; };
} }
std::filesystem::path get_legacy_path() { std::filesystem::path legacy_path_for_pref_path(const std::filesystem::path& prefPath) {
if (std::string_view{LegacyAppName}.empty()) { if (std::string_view{LegacyAppName}.empty() || prefPath.empty()) {
return {}; return {};
} }
char* prefPath = SDL_GetPrefPath(OrgName, LegacyAppName); auto normalizedPrefPath = prefPath;
if (!prefPath) { if (normalizedPrefPath.filename().empty()) {
Log.fatal("Unable to get PrefPath: {}", SDL_GetError()); normalizedPrefPath = normalizedPrefPath.parent_path();
} }
std::filesystem::path result{reinterpret_cast<const char8_t*>(prefPath)}; const auto parentPath = normalizedPrefPath.parent_path();
SDL_free(prefPath); if (parentPath.empty()) {
return result; return {};
}
return parentPath / LegacyAppName;
} }
std::filesystem::path get_pref_path() { std::filesystem::path get_pref_path() {
@@ -96,6 +116,13 @@ std::filesystem::path get_pref_path() {
return result; return result;
} }
std::filesystem::path active_pref_path() {
if (sActivePrefPath) {
return *sActivePrefPath;
}
return get_pref_path();
}
std::filesystem::path base_path_relative(const std::filesystem::path& path) { std::filesystem::path base_path_relative(const std::filesystem::path& path) {
const auto* basePath = SDL_GetBasePath(); const auto* basePath = SDL_GetBasePath();
if (!basePath) { if (!basePath) {
@@ -249,6 +276,69 @@ std::filesystem::path absolute_path(const std::filesystem::path& path) {
return absolute.lexically_normal(); return absolute.lexically_normal();
} }
std::filesystem::path rename_legacy_pref_path(
const std::filesystem::path& legacyPath, const std::filesystem::path& prefPath) {
if (legacyPath.empty() || prefPath.empty() ||
normalized_path(legacyPath) == normalized_path(prefPath))
{
return prefPath;
}
std::error_code ec;
if (!std::filesystem::exists(legacyPath, ec)) {
if (ec) {
Log.warn("Failed to inspect legacy data directory '{}': {}",
io::fs_path_to_string(legacyPath), ec.message());
}
return prefPath;
}
const bool prefExists = std::filesystem::exists(prefPath, ec);
if (ec) {
Log.warn("Failed to inspect data directory '{}': {}", io::fs_path_to_string(prefPath),
ec.message());
return prefPath;
}
if (prefExists) {
if (!std::filesystem::is_directory(prefPath, ec) ||
!std::filesystem::is_empty(prefPath, ec))
{
if (ec) {
Log.warn("Failed to inspect data directory '{}': {}",
io::fs_path_to_string(prefPath), ec.message());
} else {
Log.info("Skipping legacy data directory rename because '{}' is not empty",
io::fs_path_to_string(prefPath));
}
return prefPath;
}
std::filesystem::remove(prefPath, ec);
if (ec) {
Log.warn("Failed to remove empty data directory '{}' before legacy rename: {}",
io::fs_path_to_string(prefPath), ec.message());
return prefPath;
}
}
std::filesystem::rename(legacyPath, prefPath, ec);
if (ec) {
Log.warn("Failed to rename legacy data directory '{}' to '{}': {}",
io::fs_path_to_string(legacyPath), io::fs_path_to_string(prefPath), ec.message());
ec.clear();
if (!std::filesystem::exists(prefPath, ec) && !ec) {
Log.info("Using legacy data directory '{}' because the new data directory is absent",
io::fs_path_to_string(legacyPath));
return legacyPath;
}
return prefPath;
}
Log.info("Renamed legacy data directory '{}' to '{}'", io::fs_path_to_string(legacyPath),
io::fs_path_to_string(prefPath));
return prefPath;
}
bool is_same_or_inside(const std::filesystem::path& root, const std::filesystem::path& path) { bool is_same_or_inside(const std::filesystem::path& root, const std::filesystem::path& path) {
const auto normalizedRoot = normalized_path(root); const auto normalizedRoot = normalized_path(root);
const auto normalizedPath = normalized_path(path); const auto normalizedPath = normalized_path(path);
@@ -283,85 +373,46 @@ bool should_skip_migration_path(const std::filesystem::path& path,
return false; return false;
} }
bool has_location_descriptor(const std::filesystem::path& path) { bool matches_name(std::string_view name, const auto& names) {
std::error_code ec; return std::ranges::find(names, name) != names.end();
return std::filesystem::exists(path / kLocationDescriptorName, ec);
} }
bool remove_empty_destination_for_rename(const std::filesystem::path& path) { bool should_migrate_user_data_path(
std::error_code ec; const std::filesystem::path& sourcePath, const std::filesystem::path& from) {
const bool exists = std::filesystem::exists(path, ec); const auto relativePath = sourcePath.lexically_relative(from);
if (ec) { if (relativePath.empty() || relativePath.is_absolute()) {
Log.debug("Could not inspect migration destination '{}': {}", io::fs_path_to_string(path),
ec.message());
return false; return false;
} }
if (!exists) {
auto it = relativePath.begin();
if (it == relativePath.end() || *it == "..") {
return false;
}
const auto first = io::fs_path_to_string(*it);
if (matches_name(first, kUserDataDirectories)) {
return true; return true;
} }
const bool canRemove = std::filesystem::is_directory(path, ec) && ++it;
std::filesystem::is_empty(path, ec) && !has_location_descriptor(path); if (it != relativePath.end()) {
if (ec || !canRemove) {
if (ec) {
Log.debug("Could not inspect migration destination '{}': {}",
io::fs_path_to_string(path), ec.message());
}
return false; return false;
} }
std::filesystem::remove(path, ec); const auto filename = io::fs_path_to_string(relativePath.filename());
if (ec) { if (matches_name(filename, kUserDataFiles)) {
Log.debug("Could not remove empty migration destination '{}': {}", return true;
io::fs_path_to_string(path), ec.message());
return false;
} }
return true; return relativePath.extension() == ".controller" || relativePath.extension() == ".gci" ||
} (filename.starts_with("MemoryCard") && filename.ends_with(".raw"));
bool try_rename_directory_migration(
const std::filesystem::path& from, const std::filesystem::path& to) {
std::error_code ec;
if (!std::filesystem::is_directory(from, ec)) {
return false;
}
if (ec) {
Log.debug("Could not inspect migration source '{}': {}", io::fs_path_to_string(from),
ec.message());
return false;
}
if (has_location_descriptor(from)) {
return false;
}
if (!remove_empty_destination_for_rename(to)) {
return false;
}
std::filesystem::create_directories(to.parent_path(), ec);
if (ec) {
Log.debug("Could not create migration destination parent '{}': {}",
io::fs_path_to_string(to.parent_path()), ec.message());
return false;
}
std::filesystem::rename(from, to, ec);
if (ec) {
Log.debug("Could not rename data directory '{}' to '{}': {}", io::fs_path_to_string(from),
io::fs_path_to_string(to), ec.message());
return false;
}
Log.info("Renamed data directory '{}' to '{}'", io::fs_path_to_string(from),
io::fs_path_to_string(to));
return true;
} }
std::filesystem::path current_data_path() { std::filesystem::path current_data_path() {
if (!ConfigPath.empty()) { if (!ConfigPath.empty()) {
return ConfigPath; return ConfigPath;
} }
const auto prefPath = get_pref_path(); const auto prefPath = active_pref_path();
const auto descriptor = read_location_descriptor(prefPath); const auto descriptor = read_location_descriptor(prefPath);
if (descriptor) { if (descriptor) {
sActiveDescriptorPath = descriptor->path; sActiveDescriptorPath = descriptor->path;
@@ -427,7 +478,7 @@ bool write_location_descriptor(LocationMode mode, const std::filesystem::path& t
json["previousPath"] = io::fs_path_to_string(descriptor.previousPath); json["previousPath"] = io::fs_path_to_string(descriptor.previousPath);
} }
const auto prefPath = get_pref_path(); const auto prefPath = active_pref_path();
for (const auto& path : descriptor_write_paths(prefPath)) { for (const auto& path : descriptor_write_paths(prefPath)) {
if (write_descriptor_json(path, json)) { if (write_descriptor_json(path, json)) {
sActiveDescriptorPath = path; sActiveDescriptorPath = path;
@@ -439,6 +490,61 @@ bool write_location_descriptor(LocationMode mode, const std::filesystem::path& t
return false; return false;
} }
void set_error(std::string* errorOut, std::string error) {
if (errorOut != nullptr) {
*errorOut = std::move(error);
}
}
bool validate_writable_data_path(const std::filesystem::path& path, std::string* errorOut) {
if (path.empty()) {
set_error(errorOut, "Choose a folder.");
return false;
}
std::error_code ec;
std::filesystem::create_directories(path, ec);
if (ec) {
set_error(errorOut, fmt::format("{} could not create the selected folder.", AppName));
Log.warn("Failed to create custom data folder '{}': {}", io::fs_path_to_string(path),
ec.message());
return false;
}
if (!std::filesystem::is_directory(path, ec)) {
set_error(errorOut, "The selected path is not a folder.");
if (ec) {
Log.warn("Failed to inspect custom data folder '{}': {}", io::fs_path_to_string(path),
ec.message());
}
return false;
}
const auto probePath = path / fmt::format(".write-probe-{}.tmp",
std::chrono::steady_clock::now().time_since_epoch().count());
try {
io::FileStream::WriteAllText(probePath, "dusk");
} catch (const std::exception& e) {
set_error(errorOut, fmt::format("{} could not write to the selected folder.", AppName));
Log.warn("Failed write probe for custom data folder '{}': {}", io::fs_path_to_string(path),
e.what());
return false;
}
std::filesystem::remove(probePath, ec);
if (ec) {
set_error(
errorOut, fmt::format("{} could write to the selected folder, but could not remove "
"the test file it created.",
AppName));
Log.warn("Failed to remove custom data folder write probe '{}': {}",
io::fs_path_to_string(probePath), ec.message());
return false;
}
return true;
}
std::uintmax_t remove_empty_directories(const std::filesystem::path& root, bool includeRoot) { std::uintmax_t remove_empty_directories(const std::filesystem::path& root, bool includeRoot) {
std::error_code ec; std::error_code ec;
std::vector<std::filesystem::path> directories; std::vector<std::filesystem::path> directories;
@@ -647,14 +753,6 @@ void migrate_directory(const std::filesystem::path& from, const std::filesystem:
return; return;
} }
if (try_rename_directory_migration(from, to)) {
return;
}
if (try_rename_directory_migration(from, to)) {
return;
}
std::filesystem::create_directories(to, ec); std::filesystem::create_directories(to, ec);
if (ec) { if (ec) {
++stats.failures; ++stats.failures;
@@ -700,6 +798,16 @@ void migrate_directory(const std::filesystem::path& from, const std::filesystem:
continue; continue;
} }
if (!should_migrate_user_data_path(sourcePath, from)) {
++stats.skippedUnsupportedEntries;
if (std::filesystem::is_directory(status)) {
it.disable_recursion_pending();
}
ec.clear();
it.increment(ec);
continue;
}
const auto relativePath = sourcePath.lexically_relative(from); const auto relativePath = sourcePath.lexically_relative(from);
if (relativePath.empty() || relativePath.is_absolute()) { if (relativePath.empty() || relativePath.is_absolute()) {
++stats.failures; ++stats.failures;
@@ -761,8 +869,6 @@ void migrate_data(const std::filesystem::path& prefPath, const std::filesystem::
const LocationDescriptor* descriptor) { const LocationDescriptor* descriptor) {
if (descriptor && !descriptor->previousPath.empty()) { if (descriptor && !descriptor->previousPath.empty()) {
migrate_directory(descriptor->previousPath, dataPath, prefPath); migrate_directory(descriptor->previousPath, dataPath, prefPath);
} else if (const auto legacyPath = get_legacy_path(); !legacyPath.empty()) {
migrate_directory(legacyPath, dataPath, prefPath);
} }
} }
@@ -899,17 +1005,25 @@ bool open_data_path() {
#endif #endif
} }
bool set_custom_data_path(const std::filesystem::path& path) { bool set_custom_data_path(const std::filesystem::path& path, std::string* errorOut) {
if (path.empty()) { if (!validate_writable_data_path(path, errorOut)) {
Log.warn("Ignoring empty custom data path");
return false; return false;
} }
return write_location_descriptor(LocationMode::Custom, path); if (!write_location_descriptor(LocationMode::Custom, path)) {
set_error(errorOut, fmt::format("{} could not save the data folder setting.", AppName));
return false;
}
return true;
} }
bool set_custom_data_path(const char* path) { bool set_custom_data_path(const char* path, std::string* errorOut) {
return set_custom_data_path(path_from_utf8(path)); if (path == nullptr) {
set_error(errorOut, "Choose a folder.");
return false;
}
return set_custom_data_path(path_from_utf8(path), errorOut);
} }
bool set_portable_data_path() { bool set_portable_data_path() {
@@ -917,12 +1031,12 @@ bool set_portable_data_path() {
} }
bool reset_data_path() { bool reset_data_path() {
const auto prefPath = get_pref_path(); const auto prefPath = active_pref_path();
return write_location_descriptor(LocationMode::Default, default_data_path(prefPath)); return write_location_descriptor(LocationMode::Default, default_data_path(prefPath));
} }
bool is_default_data_path() { bool is_default_data_path() {
const auto prefPath = get_pref_path(); const auto prefPath = active_pref_path();
return normalized_path(configured_data_path()) == normalized_path(default_data_path(prefPath)); return normalized_path(configured_data_path()) == normalized_path(default_data_path(prefPath));
} }
@@ -931,7 +1045,7 @@ std::filesystem::path configured_data_path() {
return *sConfiguredDataPath; return *sConfiguredDataPath;
} }
const auto prefPath = get_pref_path(); const auto prefPath = active_pref_path();
const auto descriptor = read_location_descriptor(prefPath); const auto descriptor = read_location_descriptor(prefPath);
if (descriptor) { if (descriptor) {
sActiveDescriptorPath = descriptor->path; sActiveDescriptorPath = descriptor->path;
@@ -941,6 +1055,13 @@ std::filesystem::path configured_data_path() {
return *sConfiguredDataPath; return *sConfiguredDataPath;
} }
std::filesystem::path cache_path() {
if (!CachePath.empty()) {
return CachePath;
}
return active_pref_path();
}
bool is_data_path_restart_pending() { bool is_data_path_restart_pending() {
if (ConfigPath.empty()) { if (ConfigPath.empty()) {
return false; return false;
@@ -949,8 +1070,12 @@ bool is_data_path_restart_pending() {
return normalized_path(ConfigPath) != normalized_path(configured_data_path()); return normalized_path(ConfigPath) != normalized_path(configured_data_path());
} }
std::filesystem::path initialize_data() { Paths initialize_data() {
const auto prefPath = get_pref_path(); const auto preferredPrefPath = get_pref_path();
const auto prefPath =
rename_legacy_pref_path(legacy_path_for_pref_path(preferredPrefPath), preferredPrefPath);
sActivePrefPath = prefPath;
const auto descriptor = read_location_descriptor(prefPath); const auto descriptor = read_location_descriptor(prefPath);
if (descriptor) { if (descriptor) {
sActiveDescriptorPath = descriptor->path; sActiveDescriptorPath = descriptor->path;
@@ -963,9 +1088,13 @@ std::filesystem::path initialize_data() {
migrate_data(prefPath, dataPath, descriptor ? &descriptor->descriptor : nullptr); migrate_data(prefPath, dataPath, descriptor ? &descriptor->descriptor : nullptr);
ensure_data_directory(dataPath); ensure_data_directory(dataPath);
ensure_initial_pipeline_cache(dataPath); ensure_data_directory(prefPath);
ensure_initial_pipeline_cache(prefPath);
return dataPath; return Paths{
.userPath = dataPath,
.cachePath = prefPath,
};
} }
} // namespace dusk::data } // namespace dusk::data
+11 -4
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <filesystem> #include <filesystem>
#include <string>
#if defined(__APPLE__) #if defined(__APPLE__)
#include <TargetConditionals.h> #include <TargetConditionals.h>
@@ -14,7 +15,7 @@
#define DUSK_CAN_OPEN_DATA_FOLDER 0 #define DUSK_CAN_OPEN_DATA_FOLDER 0
#endif #endif
#if defined(__APPLE__) && TARGET_OS_IOS && !TARGET_OS_MACCATALYST #if (defined(__APPLE__) && TARGET_OS_IOS && !TARGET_OS_MACCATALYST) || defined(__ANDROID__)
#define DUSK_CAN_CHANGE_DATA_FOLDER 0 #define DUSK_CAN_CHANGE_DATA_FOLDER 0
#else #else
#define DUSK_CAN_CHANGE_DATA_FOLDER 1 #define DUSK_CAN_CHANGE_DATA_FOLDER 1
@@ -22,11 +23,17 @@
namespace dusk::data { namespace dusk::data {
std::filesystem::path initialize_data(); struct Paths {
std::filesystem::path userPath;
std::filesystem::path cachePath;
};
Paths initialize_data();
std::filesystem::path configured_data_path(); std::filesystem::path configured_data_path();
std::filesystem::path cache_path();
bool open_data_path(); bool open_data_path();
bool set_custom_data_path(const char* path); bool set_custom_data_path(const char* path, std::string* errorOut);
bool set_custom_data_path(const std::filesystem::path& path); bool set_custom_data_path(const std::filesystem::path& path, std::string* errorOut);
bool set_portable_data_path(); bool set_portable_data_path();
bool reset_data_path(); bool reset_data_path();
bool is_default_data_path(); bool is_default_data_path();
-1
View File
@@ -368,7 +368,6 @@ namespace dusk {
m_menuTools.ShowProcessManager(); m_menuTools.ShowProcessManager();
m_menuTools.ShowHeapOverlay(); m_menuTools.ShowHeapOverlay();
m_menuTools.ShowStubLog(); m_menuTools.ShowStubLog();
m_menuTools.ShowMapLoader();
m_menuTools.ShowBloomWindow(); m_menuTools.ShowBloomWindow();
m_menuTools.ShowPlayerInfo(); m_menuTools.ShowPlayerInfo();
m_menuTools.ShowAudioDebug(); m_menuTools.ShowAudioDebug();
-149
View File
@@ -1,149 +0,0 @@
#include "d/d_com_inf_game.h"
#include "imgui.h"
#include <imgui_internal.h>
#include "ImGuiConsole.hpp"
#include "ImGuiMenuTools.hpp"
#include "dusk/map_loader_definitions.h"
#include "fmt/format.h"
namespace dusk {
void ImGuiMenuTools::ShowMapLoader() {
if (!getSettings().backend.enableAdvancedSettings ||
!ImGuiConsole::CheckMenuViewToggle(ImGuiKey_F7, m_showMapLoader))
{
return;
}
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
// ImGui::SetNextWindowBgAlpha(0.65f);
if (!ImGui::Begin("Map Loader", &m_showMapLoader, windowFlags)) {
ImGui::End();
return;
}
ImGui::Checkbox("Show Internal Names", &m_mapLoaderInfo.showInternalNames);
const char* previewRegion = "None";
if (m_mapLoaderInfo.regionIdx != -1) {
previewRegion = gameRegions[m_mapLoaderInfo.regionIdx].regionName;
}
if (ImGui::BeginCombo("Select Region", previewRegion)) {
int idx = 0;
for (const auto& region : gameRegions) {
if (ImGui::Selectable(region.regionName)) {
if (m_mapLoaderInfo.regionIdx != idx) {
m_mapLoaderInfo.mapIdx = 0;
m_mapLoaderInfo.roomNoIdx = 0;
m_mapLoaderInfo.pointNoIdx = 0;
}
m_mapLoaderInfo.regionIdx = idx;
}
idx++;
}
ImGui::EndCombo();
}
if (m_mapLoaderInfo.regionIdx != -1) {
const auto& region = gameRegions[m_mapLoaderInfo.regionIdx];
std::string previewMap = "None";
if (m_mapLoaderInfo.mapIdx != -1) {
const auto& map = region.maps[m_mapLoaderInfo.mapIdx];
previewMap = m_mapLoaderInfo.showInternalNames ? fmt::format("{} ({})", map.mapName, map.mapFile) : map.mapName;
}
if (ImGui::BeginCombo("Select Map", previewMap.data())) {
int prevMapIdx = m_mapLoaderInfo.mapIdx;
for (int i = 0; i < region.maps.size(); ++i) {
const auto& map = region.maps[i];
std::string label = m_mapLoaderInfo.showInternalNames ? fmt::format("{} ({})", map.mapName, map.mapFile) : map.mapName;
if (ImGui::Selectable(label.data())) {
m_mapLoaderInfo.mapIdx = i;
}
}
ImGui::EndCombo();
if (m_mapLoaderInfo.mapIdx != prevMapIdx) {
m_mapLoaderInfo.roomNoIdx = 0;
m_mapLoaderInfo.pointNoIdx = 0;
}
}
} else {
ImGui::Text("No region selected.");
}
if (m_mapLoaderInfo.regionIdx != -1 && m_mapLoaderInfo.mapIdx != -1) {
const auto& region = gameRegions[m_mapLoaderInfo.regionIdx];
const auto& map = region.maps[m_mapLoaderInfo.mapIdx];
const auto& room = map.mapRooms[m_mapLoaderInfo.roomNoIdx];
if (map.mapRooms.size() > 1) {
ImGui::Text("Selected Room: %2d", room.roomNo);
ImGui::SameLine();
if (ImGui::Button("-###RoomNoIdxDec")) {
m_mapLoaderInfo.roomNoIdx--;
if (m_mapLoaderInfo.roomNoIdx < 0) {
m_mapLoaderInfo.roomNoIdx = map.mapRooms.size() - 1;
}
m_mapLoaderInfo.pointNoIdx = 0;
}
ImGui::SameLine();
if (ImGui::Button("+###RoomNoIdxInc")) {
m_mapLoaderInfo.roomNoIdx++;
if (m_mapLoaderInfo.roomNoIdx >= map.mapRooms.size()) {
m_mapLoaderInfo.roomNoIdx = 0;
}
m_mapLoaderInfo.pointNoIdx = 0;
}
}
constexpr int MAX_LAYER = 14;
ImGui::Text("Selected Layer: %3d", m_mapLoaderInfo.layer);
ImGui::SameLine();
if (ImGui::Button("-###layerDec")) {
m_mapLoaderInfo.layer--;
if (m_mapLoaderInfo.layer < -1) {
m_mapLoaderInfo.layer = MAX_LAYER;
}
}
ImGui::SameLine();
if (ImGui::Button("+###layerInc")) {
m_mapLoaderInfo.layer++;
if (m_mapLoaderInfo.layer > MAX_LAYER) {
m_mapLoaderInfo.layer = -1;
}
}
if (room.roomPoints.size() > 1) {
ImGui::Text("Selected Point: %3d", room.roomPoints[m_mapLoaderInfo.pointNoIdx]);
ImGui::SameLine();
if (ImGui::Button("-###PointNoIdxDec")) {
m_mapLoaderInfo.pointNoIdx--;
if (m_mapLoaderInfo.pointNoIdx < 0) {
m_mapLoaderInfo.pointNoIdx = room.roomPoints.size() - 1;
}
}
ImGui::SameLine();
if (ImGui::Button("+###PointNoIdxInc")) {
m_mapLoaderInfo.pointNoIdx++;
if (m_mapLoaderInfo.pointNoIdx >= room.roomPoints.size()) {
m_mapLoaderInfo.pointNoIdx = 0;
}
}
}
if (ImGui::Button("Warp")) {
dComIfGp_setNextStage(map.mapFile, room.roomPoints[m_mapLoaderInfo.pointNoIdx], room.roomNo, m_mapLoaderInfo.layer);
}
}
ImGui::End();
}
} // namespace dusk
-1
View File
@@ -40,7 +40,6 @@ namespace dusk {
ImGui::BeginDisabled(getSettings().game.speedrunMode); ImGui::BeginDisabled(getSettings().game.speedrunMode);
ImGui::MenuItem("Save Editor", hotkeys::SHOW_SAVE_EDITOR, &m_showSaveEditor); ImGui::MenuItem("Save Editor", hotkeys::SHOW_SAVE_EDITOR, &m_showSaveEditor);
ImGui::MenuItem("Map Loader", hotkeys::SHOW_MAP_LOADER, &m_showMapLoader);
ImGui::MenuItem("State Share", hotkeys::SHOW_STATE_SHARE, &m_showStateShare); ImGui::MenuItem("State Share", hotkeys::SHOW_STATE_SHARE, &m_showStateShare);
ImGui::EndDisabled(); ImGui::EndDisabled();
-14
View File
@@ -21,7 +21,6 @@ namespace dusk {
void ShowProcessManager(); void ShowProcessManager();
void ShowHeapOverlay(); void ShowHeapOverlay();
void ShowStubLog(); void ShowStubLog();
void ShowMapLoader();
void ShowBloomWindow(); void ShowBloomWindow();
void ShowPlayerInfo(); void ShowPlayerInfo();
void ShowAudioDebug(); void ShowAudioDebug();
@@ -43,22 +42,9 @@ namespace dusk {
bool m_showStubLog = false; bool m_showStubLog = false;
bool m_showMapLoader = false;
bool m_showBloomWindow = false; bool m_showBloomWindow = false;
bool m_showAudioDebug = false; bool m_showAudioDebug = false;
struct {
int mapIdx = -1;
int regionIdx = -1;
int roomNoIdx = 0;
int pointNoIdx = 0;
int roomNo = -1;
int pointNo = -1;
int spawnId = 0;
int layer = -1;
bool showInternalNames = false;
} m_mapLoaderInfo;
bool m_showPlayerInfo = false; bool m_showPlayerInfo = false;
int m_playerInfoOverlayCorner = 1; // top-right int m_playerInfoOverlayCorner = 1; // top-right
+5 -1
View File
@@ -13,7 +13,7 @@ UserSettings g_userSettings = {
}, },
.audio = { .audio = {
.masterVolume {"audio.masterVolume", 80}, .masterVolume {"audio.masterVolume", 60},
.mainMusicVolume {"audio.mainMusicVolume", 100}, .mainMusicVolume {"audio.mainMusicVolume", 100},
.subMusicVolume {"audio.subMusicVolume", 100}, .subMusicVolume {"audio.subMusicVolume", 100},
.soundEffectsVolume {"audio.soundEffectsVolume", 100}, .soundEffectsVolume {"audio.soundEffectsVolume", 100},
@@ -93,6 +93,7 @@ UserSettings g_userSettings = {
// Cheats // Cheats
.infiniteHearts {"game.infiniteHearts", false}, .infiniteHearts {"game.infiniteHearts", false},
.infiniteArrows {"game.infiniteArrows", false}, .infiniteArrows {"game.infiniteArrows", false},
.infiniteSeeds {"game.infiniteSeeds", false},
.infiniteBombs {"game.infiniteBombs", false}, .infiniteBombs {"game.infiniteBombs", false},
.infiniteOil {"game.infiniteOil", false}, .infiniteOil {"game.infiniteOil", false},
.infiniteOxygen {"game.infiniteOxygen", false}, .infiniteOxygen {"game.infiniteOxygen", false},
@@ -106,6 +107,7 @@ UserSettings g_userSettings = {
.fastRoll {"game.fastRoll", false}, .fastRoll {"game.fastRoll", false},
.fastSpinner {"game.fastSpinner", false}, .fastSpinner {"game.fastSpinner", false},
.freeMagicArmor {"game.freeMagicArmor", false}, .freeMagicArmor {"game.freeMagicArmor", false},
.invincibleEnemies {"game.invincibleEnemies", false},
// Technical // Technical
.restoreWiiGlitches {"game.restoreWiiGlitches", false}, .restoreWiiGlitches {"game.restoreWiiGlitches", false},
@@ -243,6 +245,7 @@ void registerSettings() {
Register(g_userSettings.game.fastSpinner); Register(g_userSettings.game.fastSpinner);
Register(g_userSettings.game.infiniteHearts); Register(g_userSettings.game.infiniteHearts);
Register(g_userSettings.game.infiniteArrows); Register(g_userSettings.game.infiniteArrows);
Register(g_userSettings.game.infiniteSeeds);
Register(g_userSettings.game.infiniteBombs); Register(g_userSettings.game.infiniteBombs);
Register(g_userSettings.game.infiniteOil); Register(g_userSettings.game.infiniteOil);
Register(g_userSettings.game.infiniteOxygen); Register(g_userSettings.game.infiniteOxygen);
@@ -251,6 +254,7 @@ void registerSettings() {
Register(g_userSettings.game.moonJump); Register(g_userSettings.game.moonJump);
Register(g_userSettings.game.superClawshot); Register(g_userSettings.game.superClawshot);
Register(g_userSettings.game.alwaysGreatspin); Register(g_userSettings.game.alwaysGreatspin);
Register(g_userSettings.game.invincibleEnemies);
Register(g_userSettings.game.enableFrameInterpolation); Register(g_userSettings.game.enableFrameInterpolation);
Register(g_userSettings.game.gyroMode); Register(g_userSettings.game.gyroMode);
Register(g_userSettings.game.enableGyroAim); Register(g_userSettings.game.enableGyroAim);
+1
View File
@@ -20,6 +20,7 @@ void resetForSpeedrunMode() {
getSettings().game.infiniteHearts.setSpeedrunValue(false); getSettings().game.infiniteHearts.setSpeedrunValue(false);
getSettings().game.infiniteArrows.setSpeedrunValue(false); getSettings().game.infiniteArrows.setSpeedrunValue(false);
getSettings().game.infiniteSeeds.setSpeedrunValue(false);
getSettings().game.infiniteBombs.setSpeedrunValue(false); getSettings().game.infiniteBombs.setSpeedrunValue(false);
getSettings().game.infiniteOil.setSpeedrunValue(false); getSettings().game.infiniteOil.setSpeedrunValue(false);
getSettings().game.infiniteOxygen.setSpeedrunValue(false); getSettings().game.infiniteOxygen.setSpeedrunValue(false);
+37 -38
View File
@@ -26,6 +26,43 @@
#include <vector> #include <vector>
namespace dusk::ui { namespace dusk::ui {
Rml::String stage_option_label(const MapEntry& map, bool showInternalNames) {
return showInternalNames ? fmt::format("{} ({})", map.mapName, map.mapFile) : map.mapName;
}
Rml::String stage_label_for_file(const Rml::String& stageFile, bool showInternalNames) {
for (const auto& region : gameRegions) {
for (const auto& map : region.maps) {
if (stageFile == map.mapFile) {
return stage_option_label(map, showInternalNames);
}
}
}
return stageFile;
}
void populate_stage_picker(Pane& pane, std::function<Rml::String()> getStageFile,
std::function<void(const char*)> setStageFile, bool showInternalNames) {
pane.clear();
for (const auto& region : gameRegions) {
pane.add_section(region.regionName);
for (const auto& map : region.maps) {
pane.add_button({
.text = stage_option_label(map, showInternalNames),
.isSelected =
[getStageFile, stageFile = map.mapFile] {
return getStageFile() == stageFile;
},
})
.on_pressed([setStageFile, stageFile = map.mapFile] {
mDoAud_seStartMenu(kSoundItemChange);
setStageFile(stageFile);
});
}
}
}
namespace { namespace {
bool has_save_data() { bool has_save_data() {
@@ -155,44 +192,6 @@ bool parse_vec3(const Rml::String& value, float& x, float& y, float& z) {
return *cursor == '\0'; return *cursor == '\0';
} }
Rml::String stage_option_label(const MapEntry& map) {
// TODO: option to show internal name?
// return fmt::format("{} ({})", map.mapName, map.mapFile);
return map.mapName;
}
Rml::String stage_label_for_file(const Rml::String& stageFile) {
for (const auto& region : gameRegions) {
for (const auto& map : region.maps) {
if (stageFile == map.mapFile) {
return stage_option_label(map);
}
}
}
return stageFile;
}
void populate_stage_picker(Pane& pane, std::function<Rml::String()> getStageFile,
std::function<void(const char*)> setStageFile) {
pane.clear();
for (const auto& region : gameRegions) {
pane.add_section(region.regionName);
for (const auto& map : region.maps) {
pane.add_button({
.text = stage_option_label(map),
.isSelected =
[getStageFile, stageFile = map.mapFile] {
return getStageFile() == stageFile;
},
})
.on_pressed([setStageFile, stageFile = map.mapFile] {
mDoAud_seStartMenu(kSoundItemChange);
setStageFile(stageFile);
});
}
}
}
Rml::String get_player_name() { Rml::String get_player_name() {
if (!has_save_data()) { if (!has_save_data()) {
return ""; return "";
+11
View File
@@ -1,8 +1,19 @@
#pragma once #pragma once
#include "window.hpp" #include "window.hpp"
struct MapEntry;
namespace dusk::ui { namespace dusk::ui {
class Pane;
Rml::String stage_option_label(const MapEntry& map, bool showInternalNames = false);
Rml::String stage_label_for_file(const Rml::String& stageFile, bool showInternalNames = false);
void populate_stage_picker(Pane& pane, std::function<Rml::String()> getStageFile,
std::function<void(const char*)> setStageFile,
bool showInternalNames = false);
class EditorWindow : public Window { class EditorWindow : public Window {
public: public:
EditorWindow(); EditorWindow();
+1 -1
View File
@@ -184,7 +184,7 @@ Rml::String format_graphics_setting_value(GraphicsOption option, int value) {
case BloomMode::Classic: case BloomMode::Classic:
return "Classic"; return "Classic";
case BloomMode::Dusk: case BloomMode::Dusk:
return "Dusk"; return "Dusklight";
} }
break; break;
case GraphicsOption::BloomMultiplier: case GraphicsOption::BloomMultiplier:
+2 -3
View File
@@ -18,6 +18,7 @@
#include "modal.hpp" #include "modal.hpp"
#include "settings.hpp" #include "settings.hpp"
#include "ui.hpp" #include "ui.hpp"
#include "warp.hpp"
#include "window.hpp" #include "window.hpp"
#include <chrono> #include <chrono>
@@ -51,11 +52,9 @@ MenuBar::MenuBar() : Document(kDocumentSource), mRoot(mDocument->GetElementById(
.autoSelect = false, .autoSelect = false,
}); });
mTabBar->add_tab("Settings", [this] { push(std::make_unique<SettingsWindow>()); }); mTabBar->add_tab("Settings", [this] { push(std::make_unique<SettingsWindow>()); });
// mTabBar->add_tab("Warp", [] {
// // TODO
// });
if (getSettings().backend.enableAdvancedSettings) { if (getSettings().backend.enableAdvancedSettings) {
mTabBar->add_tab("Warp", [this] { push(std::make_unique<WarpWindow>()); });
mTabBar->add_tab("Editor", [this] { push(std::make_unique<EditorWindow>()); }); mTabBar->add_tab("Editor", [this] { push(std::make_unique<EditorWindow>()); });
} }
+2 -1
View File
@@ -354,8 +354,9 @@ void Overlay::update() {
} }
} }
u32 count = 0;
const bool showControllerWarning = PADGetIndexForPort(PAD_CHAN0) < 0 && const bool showControllerWarning = PADGetIndexForPort(PAD_CHAN0) < 0 &&
PADGetKeyButtonBindings(PAD_CHAN0, nullptr) == nullptr && PADGetKeyButtonBindings(PAD_CHAN0, &count) == nullptr &&
dynamic_cast<Window*>(top_document()) == nullptr && dynamic_cast<Window*>(top_document()) == nullptr &&
dynamic_cast<WindowSmall*>(top_document()) == nullptr; dynamic_cast<WindowSmall*>(top_document()) == nullptr;
if (showControllerWarning && mControllerWarning == nullptr) { if (showControllerWarning && mControllerWarning == nullptr) {
+1 -1
View File
@@ -83,7 +83,7 @@ PresetWindow::PresetWindow() : WindowSmall("modal", "modal-dialog") {
"Enhancements disabled to match the GameCube version. " "Enhancements disabled to match the GameCube version. "
"Good for speedrunning or simple nostalgia!", "Good for speedrunning or simple nostalgia!",
applyPresetClassic}, applyPresetClassic},
{"Dusk", {"Dusklight",
"Graphics & quality of life tweaks, including some from the Wii U version. " "Graphics & quality of life tweaks, including some from the Wii U version. "
"Our recommended way to play!", "Our recommended way to play!",
applyPresetDusk}, applyPresetDusk},
+48 -4
View File
@@ -3,6 +3,7 @@
#include "aurora/gfx.h" #include "aurora/gfx.h"
#include "bool_button.hpp" #include "bool_button.hpp"
#include "controller_config.hpp" #include "controller_config.hpp"
#include "dusk/app_info.hpp"
#include "dusk/audio/DuskAudioSystem.h" #include "dusk/audio/DuskAudioSystem.h"
#include "dusk/audio/DuskDsp.hpp" #include "dusk/audio/DuskDsp.hpp"
#include "dusk/config.hpp" #include "dusk/config.hpp"
@@ -17,6 +18,7 @@
#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"
#include "modal.hpp"
#include "number_button.hpp" #include "number_button.hpp"
#include "menu_bar.hpp" #include "menu_bar.hpp"
#include "pane.hpp" #include "pane.hpp"
@@ -25,6 +27,7 @@
#include <aurora/lib/window.hpp> #include <aurora/lib/window.hpp>
#include <SDL3/SDL_filesystem.h> #include <SDL3/SDL_filesystem.h>
#include <fmt/format.h>
#if DUSK_ENABLE_SENTRY_NATIVE #if DUSK_ENABLE_SENTRY_NATIVE
#include "dusk/crash_reporting.h" #include "dusk/crash_reporting.h"
@@ -184,6 +187,7 @@ void reset_for_speedrun_mode() {
getSettings().game.infiniteHearts.setSpeedrunValue(false); getSettings().game.infiniteHearts.setSpeedrunValue(false);
getSettings().game.infiniteArrows.setSpeedrunValue(false); getSettings().game.infiniteArrows.setSpeedrunValue(false);
getSettings().game.infiniteSeeds.setSpeedrunValue(false);
getSettings().game.infiniteBombs.setSpeedrunValue(false); getSettings().game.infiniteBombs.setSpeedrunValue(false);
getSettings().game.infiniteOil.setSpeedrunValue(false); getSettings().game.infiniteOil.setSpeedrunValue(false);
getSettings().game.infiniteOxygen.setSpeedrunValue(false); getSettings().game.infiniteOxygen.setSpeedrunValue(false);
@@ -197,6 +201,7 @@ void reset_for_speedrun_mode() {
getSettings().game.fastRoll.setSpeedrunValue(false); getSettings().game.fastRoll.setSpeedrunValue(false);
getSettings().game.fastSpinner.setSpeedrunValue(false); getSettings().game.fastSpinner.setSpeedrunValue(false);
getSettings().game.freeMagicArmor.setSpeedrunValue(false); getSettings().game.freeMagicArmor.setSpeedrunValue(false);
getSettings().game.invincibleEnemies.setSpeedrunValue(false);
getSettings().game.pauseOnFocusLost.setSpeedrunValue(false); getSettings().game.pauseOnFocusLost.setSpeedrunValue(false);
aurora_set_pause_on_focus_lost(false); aurora_set_pause_on_focus_lost(false);
@@ -295,13 +300,49 @@ private:
Rml::String mCurrentRml; Rml::String mCurrentRml;
}; };
void show_data_folder_error_modal(std::string_view message) {
auto dismiss = [](Modal& modal) {
mDoAud_seStartMenu(kSoundWindowClose);
modal.pop();
};
push_document(std::make_unique<Modal>(Modal::Props{
.title = "Data Folder Not Changed",
.bodyRml = escape(message),
.actions =
{
ModalAction{
.label = "OK",
.onPressed = dismiss,
},
},
.onDismiss = dismiss,
.icon = "warning",
}));
if (auto* doc = top_document()) {
doc->focus();
}
}
void data_folder_dialog_callback(void*, const char* path, const char* error) { void data_folder_dialog_callback(void*, const char* path, const char* error) {
if (error != nullptr || path == nullptr) { if (error != nullptr) {
show_data_folder_error_modal(error);
return; return;
} }
if (data::set_custom_data_path(path)) { if (path == nullptr) {
mDoAud_seStartMenu(kSoundItemChange); return;
} }
std::string dataPathError;
if (data::set_custom_data_path(path, &dataPathError)) {
mDoAud_seStartMenu(kSoundItemChange);
return;
}
if (dataPathError.empty()) {
dataPathError =
fmt::format("{} could not use the selected folder as its data folder.", AppName);
}
show_data_folder_error_modal(dataPathError);
} }
const Rml::String kInternalResolutionHelpText = const Rml::String kInternalResolutionHelpText =
@@ -912,7 +953,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
[](int value) { [](int value) {
getSettings().audio.masterVolume.setValue(value); getSettings().audio.masterVolume.setValue(value);
config::Save(); config::Save();
audio::SetMasterVolume(value / 100.f); audio::SetMasterVolume(audio::MasterVolumeToLinear(value / 100.0f));
}, },
.isModified = .isModified =
[] { [] {
@@ -1107,6 +1148,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
addCheat("Infinite Hearts", getSettings().game.infiniteHearts, "Keeps your health full."); addCheat("Infinite Hearts", getSettings().game.infiniteHearts, "Keeps your health full.");
addCheat( addCheat(
"Infinite Arrows", getSettings().game.infiniteArrows, "Keeps your arrow count full."); "Infinite Arrows", getSettings().game.infiniteArrows, "Keeps your arrow count full.");
addCheat("Infinite Seeds", getSettings().game.infiniteSeeds, "Keeps your slingshot pellets (seeds) full.");
addCheat("Infinite Bombs", getSettings().game.infiniteBombs, "Keeps all bomb bags full."); addCheat("Infinite Bombs", getSettings().game.infiniteBombs, "Keeps all bomb bags full.");
addCheat("Infinite Oil", getSettings().game.infiniteOil, "Keeps your lantern oil full."); addCheat("Infinite Oil", getSettings().game.infiniteOil, "Keeps your lantern oil full.");
addCheat("Infinite Oxygen", getSettings().game.infiniteOxygen, addCheat("Infinite Oxygen", getSettings().game.infiniteOxygen,
@@ -1133,6 +1175,8 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
"Speeds up Spinner movement while holding R."); "Speeds up Spinner movement while holding R.");
addCheat("Free Magic Armor", getSettings().game.freeMagicArmor, addCheat("Free Magic Armor", getSettings().game.freeMagicArmor,
"Lets the magic armor work without consuming rupees."); "Lets the magic armor work without consuming rupees.");
addCheat("Invincible Enemies", getSettings().game.invincibleEnemies,
"Prevents enemies from taking damage.");
}); });
add_tab("Interface", [this](Rml::Element* content) { add_tab("Interface", [this](Rml::Element* content) {
+334
View File
@@ -0,0 +1,334 @@
#include "warp.hpp"
#include "editor.hpp"
#include "pane.hpp"
#include "dusk/map_loader_definitions.h"
#include "fmt/format.h"
namespace dusk::ui {
namespace {
constexpr int kMinLayer = -1;
constexpr int kMaxLayer = 14;
struct WarpSelectionState {
int regionIdx = 0;
int mapIdx = 0;
int roomIdx = 0;
int pointIdx = 0;
int layer = -1;
bool showInternalNames = false;
};
WarpSelectionState& selection_state() {
static WarpSelectionState state;
return state;
}
const RegionEntry* selected_region(const WarpSelectionState& state) {
if (state.regionIdx < 0 || state.regionIdx >= static_cast<int>(gameRegions.size())) {
return nullptr;
}
return &gameRegions[state.regionIdx];
}
const MapEntry* selected_map(const WarpSelectionState& state) {
const auto* region = selected_region(state);
if (region == nullptr || state.mapIdx < 0 || state.mapIdx >= static_cast<int>(region->maps.size())) {
return nullptr;
}
return &region->maps[state.mapIdx];
}
const RoomEntry* selected_room(const WarpSelectionState& state) {
const auto* map = selected_map(state);
if (map == nullptr || state.roomIdx < 0 || state.roomIdx >= static_cast<int>(map->mapRooms.size())) {
return nullptr;
}
return &map->mapRooms[state.roomIdx];
}
const s16* selected_point(const WarpSelectionState& state) {
const auto* room = selected_room(state);
if (room == nullptr || state.pointIdx < 0 ||
state.pointIdx >= static_cast<int>(room->roomPoints.size()))
{
return nullptr;
}
return &room->roomPoints[state.pointIdx];
}
void clamp_indices(WarpSelectionState& state) {
if (gameRegions.empty()) {
state.regionIdx = -1;
state.mapIdx = -1;
state.roomIdx = -1;
state.pointIdx = -1;
state.layer = std::clamp(state.layer, kMinLayer, kMaxLayer);
return;
}
state.regionIdx = std::clamp(state.regionIdx, 0, static_cast<int>(gameRegions.size()) - 1);
const auto& region = gameRegions[state.regionIdx];
if (region.maps.empty()) {
state.mapIdx = -1;
state.roomIdx = -1;
state.pointIdx = -1;
state.layer = std::clamp(state.layer, kMinLayer, kMaxLayer);
return;
}
state.mapIdx = std::clamp(state.mapIdx, 0, static_cast<int>(region.maps.size()) - 1);
const auto& map = region.maps[state.mapIdx];
if (map.mapRooms.empty()) {
state.roomIdx = -1;
state.pointIdx = -1;
state.layer = std::clamp(state.layer, kMinLayer, kMaxLayer);
return;
}
state.roomIdx = std::clamp(state.roomIdx, 0, static_cast<int>(map.mapRooms.size()) - 1);
const auto& room = map.mapRooms[state.roomIdx];
if (room.roomPoints.empty()) {
state.pointIdx = -1;
} else {
state.pointIdx = std::clamp(state.pointIdx, 0, static_cast<int>(room.roomPoints.size()) - 1);
}
state.layer = std::clamp(state.layer, kMinLayer, kMaxLayer);
}
bool can_warp(const WarpSelectionState& state) {
return selected_point(state) != nullptr;
}
void reset_selection(WarpSelectionState& state) {
state.roomIdx = 0;
state.pointIdx = 0;
state.layer = kMinLayer;
clamp_indices(state);
}
void populate_map_picker(Pane& pane, WarpSelectionState& state) {
pane.clear();
clamp_indices(state);
if (state.regionIdx < 0 || state.regionIdx >= static_cast<int>(gameRegions.size())) {
return;
}
pane.add_button({
.text = "Show Internal Names",
.isSelected = [&state] { return state.showInternalNames; },
})
.on_pressed([&pane, &state] {
mDoAud_seStartMenu(kSoundItemChange);
state.showInternalNames = !state.showInternalNames;
populate_map_picker(pane, state);
});
pane.add_section("Maps");
const auto& region = gameRegions[state.regionIdx];
for (int i = 0; i < static_cast<int>(region.maps.size()); ++i) {
pane.add_button({
.text = stage_option_label(region.maps[i], state.showInternalNames),
.isSelected = [i, &state] { return state.mapIdx == i; },
})
.on_pressed([i, &state] {
mDoAud_seStartMenu(kSoundItemChange);
if (state.mapIdx != i) {
state.mapIdx = i;
reset_selection(state);
}
});
}
}
} // namespace
WarpWindow::WarpWindow() {
add_tab("Warp", [this](Rml::Element* content) {
auto& leftPane = add_child<Pane>(content, Pane::Type::Controlled);
auto& rightPane = add_child<Pane>(content, Pane::Type::Uncontrolled);
auto& state = selection_state();
clamp_indices(state);
leftPane.add_section("Destination");
leftPane.register_control(
leftPane.add_select_button({
.key = "Region",
.getValue =
[&state] {
clamp_indices(state);
const auto* region = selected_region(state);
return region == nullptr ? Rml::String{"None"} :
Rml::String{region->regionName};
},
}),
rightPane, [&state](Pane& pane) {
pane.clear();
for (int i = 0; i < static_cast<int>(gameRegions.size()); ++i) {
pane.add_button({
.text = gameRegions[i].regionName,
.isSelected = [i, &state] { return state.regionIdx == i; },
})
.on_pressed([i, &state] {
mDoAud_seStartMenu(kSoundItemChange);
if (state.regionIdx != i) {
state.regionIdx = i;
state.mapIdx = 0;
reset_selection(state);
}
});
}
});
leftPane.register_control(
leftPane.add_select_button({
.key = "Map",
.getValue =
[&state] {
clamp_indices(state);
const auto* map = selected_map(state);
return map == nullptr ? Rml::String{"None"} :
stage_option_label(*map, state.showInternalNames);
},
}),
rightPane, [&state](Pane& pane) { populate_map_picker(pane, state); });
leftPane.register_control(
leftPane.add_select_button({
.key = "Room",
.getValue = [&state] {
clamp_indices(state);
const auto* room = selected_room(state);
return room == nullptr ? Rml::String{"None"} :
fmt::format("{}", room->roomNo);
},
.isDisabled = [&state] {
clamp_indices(state);
const auto* map = selected_map(state);
return map == nullptr || map->mapRooms.size() <= 1;
},
}),
rightPane, [&state](Pane& pane) {
pane.clear();
clamp_indices(state);
if (state.regionIdx < 0 || state.regionIdx >= static_cast<int>(gameRegions.size())) {
return;
}
const auto& region = gameRegions[state.regionIdx];
if (state.mapIdx < 0 || state.mapIdx >= static_cast<int>(region.maps.size())) {
return;
}
const auto& map = region.maps[state.mapIdx];
for (int i = 0; i < static_cast<int>(map.mapRooms.size()); ++i) {
pane.add_button({
.text = fmt::format("{}", map.mapRooms[i].roomNo),
.isSelected = [i, &state] { return state.roomIdx == i; },
})
.on_pressed([i, &state] {
mDoAud_seStartMenu(kSoundItemChange);
if (state.roomIdx != i) {
state.roomIdx = i;
state.pointIdx = 0;
clamp_indices(state);
}
});
}
});
leftPane.register_control(
leftPane.add_select_button({
.key = "Point",
.getValue = [&state] {
clamp_indices(state);
const auto* point = selected_point(state);
return point == nullptr ? Rml::String{"None"} : fmt::format("{}", *point);
},
.isDisabled = [&state] {
clamp_indices(state);
const auto* room = selected_room(state);
return room == nullptr || room->roomPoints.size() <= 1;
},
}),
rightPane, [&state](Pane& pane) {
pane.clear();
clamp_indices(state);
if (state.regionIdx < 0 || state.regionIdx >= static_cast<int>(gameRegions.size())) {
return;
}
const auto& region = gameRegions[state.regionIdx];
if (state.mapIdx < 0 || state.mapIdx >= static_cast<int>(region.maps.size())) {
return;
}
const auto& map = region.maps[state.mapIdx];
if (state.roomIdx < 0 || state.roomIdx >= static_cast<int>(map.mapRooms.size())) {
return;
}
const auto& room = map.mapRooms[state.roomIdx];
for (int i = 0; i < static_cast<int>(room.roomPoints.size()); ++i) {
pane.add_button({
.text = fmt::format("{}", room.roomPoints[i]),
.isSelected = [i, &state] { return state.pointIdx == i; },
})
.on_pressed([i, &state] {
if (state.pointIdx != i) {
mDoAud_seStartMenu(kSoundItemChange);
state.pointIdx = i;
clamp_indices(state);
}
});
}
});
leftPane.register_control(
leftPane.add_select_button({
.key = "Layer",
.getValue = [&state] { return fmt::format("{}", state.layer); },
}),
rightPane, [&state](Pane& pane) {
pane.clear();
for (int layer = kMinLayer; layer <= kMaxLayer; ++layer) {
pane.add_button({
.text = fmt::format("{}", layer),
.isSelected = [layer, &state] { return state.layer == layer; },
})
.on_pressed([layer, &state] {
if (state.layer != layer) {
mDoAud_seStartMenu(kSoundItemChange);
state.layer = layer;
}
});
}
});
leftPane.add_section("Action");
leftPane.register_control(
leftPane.add_button({
.text = "Warp",
.isDisabled = [&state] {
clamp_indices(state);
return !can_warp(state);
},
})
.on_pressed([&state] {
clamp_indices(state);
if (!can_warp(state)) {
return;
}
mDoAud_seStartMenu(kSoundClick);
const auto& region = gameRegions[state.regionIdx];
const auto& map = region.maps[state.mapIdx];
const auto& room = map.mapRooms[state.roomIdx];
dComIfGp_setNextStage( map.mapFile, room.roomPoints[state.pointIdx], room.roomNo, state.layer);
}),
rightPane, [](Pane& pane) {
pane.clear();
pane.add_text("Warp to the selected destination.");
});
});
}
} // namespace dusk::ui
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include "window.hpp"
namespace dusk::ui {
class WarpWindow : public Window {
public:
WarpWindow();
};
} // namespace dusk::ui
+4
View File
@@ -792,6 +792,10 @@ static void duskExecute() {
dComIfGs_setArrowNum(dComIfGs_getArrowMax()); dComIfGs_setArrowNum(dComIfGs_getArrowMax());
} }
if (dusk::getSettings().game.infiniteSeeds) {
dComIfGs_setPachinkoNum(dComIfGs_getPachinkoMax());
}
if (dusk::getSettings().game.infiniteBombs) { if (dusk::getSettings().game.infiniteBombs) {
dComIfGs_setBombNum(0, 99); dComIfGs_setBombNum(0, 99);
dComIfGs_setBombNum(1, 99); dComIfGs_setBombNum(1, 99);
+10 -1
View File
@@ -136,8 +136,17 @@ base_process_class* fpcBs_Create(s16 i_profname, fpc_ProcID i_procID, void* i_ap
u32 size; u32 size;
pprofile = (process_profile_definition*)fpcPf_Get(i_profname); pprofile = (process_profile_definition*)fpcPf_Get(i_profname);
if (pprofile == NULL) {
#if TARGET_PC
DuskLog.debug("fpcBs_Create: profile not found for profname={}", i_profname);
#endif
return NULL;
}
#if TARGET_PC
const char* procName = getProcName(i_profname);
DuskLog.debug("fpcBs_Create: pid={} profname={} ({}) profile={} procSize={} unkSize={}", DuskLog.debug("fpcBs_Create: pid={} profname={} ({}) profile={} procSize={} unkSize={}",
i_procID, getProcName(i_profname), i_profname, (void*)pprofile, pprofile->process_size, pprofile->unk_size); i_procID, procName ? procName : "(unknown)", i_profname, (void*)pprofile, pprofile->process_size, pprofile->unk_size);
#endif
size = pprofile->process_size + pprofile->unk_size; size = pprofile->process_size + pprofile->unk_size;
pprocess = (base_process_class*)cMl::memalignB(-4, size); pprocess = (base_process_class*)cMl::memalignB(-4, size);
+14 -5
View File
@@ -80,6 +80,7 @@
#include "dusk/audio/DuskAudioSystem.h" #include "dusk/audio/DuskAudioSystem.h"
#include "dusk/audio/DuskDsp.hpp" #include "dusk/audio/DuskDsp.hpp"
#include "dusk/config.hpp" #include "dusk/config.hpp"
#include "dusk/speedrun.h"
#include "dusk/settings.h" #include "dusk/settings.h"
#include "dusk/io.hpp" #include "dusk/io.hpp"
#include "dusk/version.hpp" #include "dusk/version.hpp"
@@ -119,6 +120,7 @@ bool dusk::IsShuttingDown = false;
bool dusk::IsGameLaunched = false; bool dusk::IsGameLaunched = false;
bool dusk::RestartRequested = false; bool dusk::RestartRequested = false;
std::filesystem::path dusk::ConfigPath; std::filesystem::path dusk::ConfigPath;
std::filesystem::path dusk::CachePath;
#endif #endif
void dusk::RequestRestart() noexcept { void dusk::RequestRestart() noexcept {
@@ -513,12 +515,17 @@ int game_main(int argc, char* argv[]) {
const auto startupLogLevel = const auto startupLogLevel =
static_cast<AuroraLogLevel>(parsed_arg_options["log-level"].as<uint8_t>()); static_cast<AuroraLogLevel>(parsed_arg_options["log-level"].as<uint8_t>());
dusk::ConfigPath = dusk::data::initialize_data(); const auto dataPaths = dusk::data::initialize_data();
dusk::InitializeFileLogging(dusk::ConfigPath, startupLogLevel); dusk::ConfigPath = dataPaths.userPath;
dusk::CachePath = dataPaths.cachePath;
dusk::InitializeFileLogging(dusk::CachePath, startupLogLevel);
log_build_info(); log_build_info();
dusk::config::LoadFromUserPreferences(); dusk::config::LoadFromUserPreferences();
if (dusk::getSettings().game.speedrunMode) {
dusk::resetForSpeedrunMode();
}
ApplyCVarOverrides(parsed_arg_options["cvar"]); ApplyCVarOverrides(parsed_arg_options["cvar"]);
dusk::crash_reporting::initialize(); dusk::crash_reporting::initialize();
// TODO: How to handle this? // TODO: How to handle this?
@@ -536,10 +543,12 @@ int game_main(int argc, char* argv[]) {
SDL_SetAppMetadata("Dusklight", DUSK_VERSION_STRING, "dev.twilitrealm.dusk"); SDL_SetAppMetadata("Dusklight", DUSK_VERSION_STRING, "dev.twilitrealm.dusk");
{ {
const auto configPathString = dusk::ConfigPath.u8string(); const auto userPathString = dusk::ConfigPath.u8string();
const auto cachePathString = dusk::CachePath.u8string();
AuroraConfig config{}; AuroraConfig config{};
config.appName = dusk::AppName; config.appName = dusk::AppName;
config.configPath = reinterpret_cast<const char*>(configPathString.c_str()); config.userPath = reinterpret_cast<const char*>(userPathString.c_str());
config.cachePath = reinterpret_cast<const char*>(cachePathString.c_str());
config.vsync = dusk::getSettings().video.enableVsync; config.vsync = dusk::getSettings().video.enableVsync;
config.startFullscreen = dusk::getSettings().video.enableFullscreen; config.startFullscreen = dusk::getSettings().video.enableFullscreen;
config.windowPosX = -1; config.windowPosX = -1;
@@ -576,7 +585,7 @@ int game_main(int argc, char* argv[]) {
} }
VISetFrameBufferScale(dusk::getSettings().game.internalResolutionScale.getValue()); VISetFrameBufferScale(dusk::getSettings().game.internalResolutionScale.getValue());
dusk::audio::SetMasterVolume(dusk::getSettings().audio.masterVolume / 100.0f); dusk::audio::SetMasterVolume(dusk::audio::MasterVolumeToLinear(dusk::getSettings().audio.masterVolume / 100.0f));
dusk::audio::SetEnableReverb(dusk::getSettings().audio.enableReverb); dusk::audio::SetEnableReverb(dusk::getSettings().audio.enableReverb);
dusk::audio::EnableHrtf = dusk::getSettings().audio.enableHrtf; dusk::audio::EnableHrtf = dusk::getSettings().audio.enableHrtf;