Merge remote-tracking branch 'origin/randomizer' into rando-archi

This commit is contained in:
CraftyBoss
2026-06-09 01:14:16 -07:00
45 changed files with 960 additions and 2757 deletions
+48 -7
View File
@@ -126,6 +126,33 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "_cmake")
option(ENABLE_ASAN "Enable AddressSanitizer" OFF)
if (ENABLE_ASAN)
if (CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" AND
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/fsanitize=address>)
add_link_options(/fsanitize=address /INCREMENTAL:NO)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "ProgramDatabase")
foreach (_lang C CXX)
foreach (_rtc_flag /RTC1 /RTCc /RTCs /RTCu)
string(REPLACE "${_rtc_flag}" "" CMAKE_${_lang}_FLAGS_DEBUG "${CMAKE_${_lang}_FLAGS_DEBUG}")
endforeach ()
endforeach ()
elseif (CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "GNU" AND
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
add_compile_options(
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fsanitize=address>
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fno-omit-frame-pointer>
)
add_link_options(-fsanitize=address)
else ()
message(FATAL_ERROR "ENABLE_ASAN requires GNU-like or MSVC-like C/C++ compiler frontends")
endif ()
add_compile_definitions(NDEBUG_SANITIZER) # Avoids absl issue with SwissTable debug code
message(STATUS "dusklight: Enabled AddressSanitizer")
endif ()
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
set(DAWN_USE_WAYLAND ON CACHE BOOL "Enable support for Wayland surface" FORCE)
endif ()
@@ -148,6 +175,7 @@ option(DUSK_SELECTED_OPT "If on, selected parts of the project will be compiled
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_SENTRY_NATIVE "Enable sentry-native crash reporting support" OFF)
option(DUSK_PACKAGE_INSTALL "Install Dusklight with a Linux-native file structure" OFF)
option(DUSK_GFX_DEBUG_GROUPS "Report debug groups to the native graphics API" ${DUSK_GFX_DEBUG_GROUPS_DEFAULT})
set(DUSK_SENTRY_DSN "" CACHE STRING "Sentry DSN")
set(DUSK_SENTRY_ENVIRONMENT "development" CACHE STRING "Sentry environment")
@@ -256,7 +284,6 @@ elseif (MSVC)
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/utf-8>)
endif ()
include(FetchContent)
# Declare all dependencies first so CMake can download them in parallel
@@ -351,9 +378,7 @@ set(GAME_INCLUDE_DIRS
find_package(Threads REQUIRED)
set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd
aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt
Threads::Threads)
list(APPEND GAME_LIBS zstd::libzstd)
Threads::Threads zstd::libzstd)
if (DUSK_ENABLE_SENTRY_NATIVE)
list(APPEND GAME_LIBS sentry)
@@ -427,6 +452,11 @@ if(ANDROID)
list(APPEND GAME_COMPILE_DEFS TARGET_ANDROID=1)
endif ()
if (DUSK_PACKAGE_INSTALL)
include(GNUInstallDirs)
list(APPEND GAME_COMPILE_DEFS DUSK_ASSET_DIR="${CMAKE_INSTALL_FULL_DATADIR}/dusklight/")
endif ()
if (DUSK_GFX_DEBUG_GROUPS)
list(APPEND GAME_COMPILE_DEFS DUSK_GFX_DEBUG_GROUPS=1)
target_compile_definitions(aurora_gx PRIVATE AURORA_GFX_DEBUG_GROUPS)
@@ -488,6 +518,9 @@ if(ANDROID)
else ()
add_executable(dusklight ${DUSK_FILES})
endif ()
if (ENABLE_ASAN)
target_sources(dusklight PRIVATE src/dusk/asan_options.c)
endif ()
# Add embedded data to target
@@ -666,12 +699,20 @@ set(EXTRA_TARGETS "")
if (TARGET crashpad_handler)
list(APPEND EXTRA_TARGETS crashpad_handler)
endif ()
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX})
if (DUSK_PACKAGE_INSTALL)
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_BINDIR})
else()
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX})
endif()
aurora_install_runtime_dlls(dusklight ${CMAKE_INSTALL_PREFIX})
if (NOT APPLE)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_PREFIX})
if (DUSK_PACKAGE_INSTALL)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/dusklight)
else()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_PREFIX})
endif()
endif ()
if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo AND NOT DUSK_PACKAGE_INSTALL)
set(DEBUG_FILES_LIST "")
foreach (target IN LISTS BINARY_TARGETS EXTRA_TARGETS)
get_target_output_name(${target} output_name)
+70
View File
@@ -52,6 +52,16 @@
}
}
},
{
"name": "asan",
"hidden": true,
"cacheVariables": {
"ENABLE_ASAN": {
"type": "BOOL",
"value": true
}
}
},
{
"name": "linux-default",
"displayName": "Linux (default)",
@@ -83,6 +93,15 @@
"linux-default"
]
},
{
"name": "linux-default-debug-asan",
"displayName": "Linux (default) Debug ASan",
"inherits": [
"debug",
"linux-default",
"asan"
]
},
{
"name": "linux-default-relwithdebinfo",
"displayName": "Linux (default) RelWithDebInfo",
@@ -110,6 +129,15 @@
"linux-clang"
]
},
{
"name": "linux-clang-debug-asan",
"displayName": "Linux (Clang) Debug ASan",
"inherits": [
"debug",
"linux-clang",
"asan"
]
},
{
"name": "linux-clang-relwithdebinfo",
"displayName": "Linux (Clang) RelWithDebInfo",
@@ -148,6 +176,15 @@
"windows-msvc"
]
},
{
"name": "windows-msvc-debug-asan",
"displayName": "Windows (MSVC) Debug ASan",
"inherits": [
"debug",
"windows-msvc",
"asan"
]
},
{
"name": "windows-msvc-relwithdebinfo",
"displayName": "Windows (MSVC) RelWithDebInfo",
@@ -239,6 +276,15 @@
"macos-default"
]
},
{
"name": "macos-default-debug-asan",
"displayName": "macOS (default) Debug ASan",
"inherits": [
"debug",
"macos-default",
"asan"
]
},
{
"name": "macos-default-relwithdebinfo",
"displayName": "macOS (default) RelWithDebInfo",
@@ -529,6 +575,12 @@
"description": "Linux (default) debug build",
"displayName": "Linux (default) Debug"
},
{
"name": "linux-default-debug-asan",
"configurePreset": "linux-default-debug-asan",
"description": "Linux (default) debug build with AddressSanitizer",
"displayName": "Linux (default) Debug ASan"
},
{
"name": "linux-default-relwithdebinfo",
"configurePreset": "linux-default-relwithdebinfo",
@@ -541,6 +593,12 @@
"description": "Linux (Clang) debug build",
"displayName": "Linux (Clang) Debug"
},
{
"name": "linux-clang-debug-asan",
"configurePreset": "linux-clang-debug-asan",
"description": "Linux (Clang) debug build with AddressSanitizer",
"displayName": "Linux (Clang) Debug ASan"
},
{
"name": "linux-clang-relwithdebinfo",
"configurePreset": "linux-clang-relwithdebinfo",
@@ -553,6 +611,12 @@
"description": "macOS debug build",
"displayName": "macOS Debug"
},
{
"name": "macos-default-debug-asan",
"configurePreset": "macos-default-debug-asan",
"description": "macOS debug build with AddressSanitizer",
"displayName": "macOS Debug ASan"
},
{
"name": "macos-default-relwithdebinfo",
"configurePreset": "macos-default-relwithdebinfo",
@@ -610,6 +674,12 @@
"description": "Windows (MSVC) debug build",
"displayName": "Windows (MSVC) Debug"
},
{
"name": "windows-msvc-debug-asan",
"configurePreset": "windows-msvc-debug-asan",
"description": "Windows (MSVC) debug build with AddressSanitizer",
"displayName": "Windows (MSVC) Debug ASan"
},
{
"name": "windows-msvc-relwithdebinfo",
"configurePreset": "windows-msvc-relwithdebinfo",
+4
View File
@@ -180,6 +180,7 @@ cmake --build --preset macos-default-relwithdebinfo
Alternate presets available:
* `macos-default-debug`: Clang, Debug
* `macos-default-debug-asan`: Clang, Debug, AddressSanitizer
**ninja (Linux)**
@@ -191,8 +192,10 @@ cmake --build --preset linux-default-relwithdebinfo
Alternate presets available:
* `linux-default-debug`: GCC, Debug
* `linux-default-debug-asan`: GCC, Debug, AddressSanitizer
* `linux-clang-relwithdebinfo`: Clang, RelWithDebInfo
* `linux-clang-debug`: Clang, Debug
* `linux-clang-debug-asan`: Clang, Debug, AddressSanitizer
**ninja (Windows)**
@@ -204,6 +207,7 @@ cmake --build --preset windows-msvc-relwithdebinfo
Alternate presets available:
* `windows-msvc-debug`: MSVC, Debug
* `windows-msvc-debug-asan`: MSVC, Debug, AddressSanitizer
* `windows-clang-relwithdebinfo`: Clang-cl, RelWithDebInfo
* `windows-clang-debug`: Clang-cl, Debug
+1 -1
+2
View File
@@ -1522,6 +1522,8 @@ set(DUSK_FILES
src/dusk/ui/window.hpp
src/dusk/ui/rando_config.cpp
src/dusk/ui/rando_config.hpp
src/dusk/ui/rando_seed_generation.cpp
src/dusk/ui/rando_seed_generation.hpp
src/dusk/achievements.cpp
src/dusk/iso_validate.cpp
src/dusk/livesplit.cpp
+12
View File
@@ -4574,6 +4574,18 @@ public:
cXyz mIBChainInterpCurrHandRoot;
bool mIBChainInterpPrevValid;
bool mIBChainInterpCurrValid;
cXyz mHsChainInterpPrevTop;
cXyz mHsChainInterpCurrTop;
cXyz mHsChainInterpPrevRoot;
cXyz mHsChainInterpCurrRoot;
cXyz mHsChainInterpPrevSubRoot;
cXyz mHsChainInterpCurrSubRoot;
cXyz mHsChainInterpPrevSubTop;
cXyz mHsChainInterpCurrSubTop;
bool mHsChainInterpPrevValid;
bool mHsChainInterpCurrValid;
bool mIsRollstab = false;
#endif
}; // Size: 0x385C
+7 -2
View File
@@ -299,8 +299,13 @@ public:
/* 0x168C */ u8 field_0x168c;
/* 0x168D */ u8 field_0x168d;
/* 0x168E */ u8 HIOInit;
#if TARGET_PC
cXyz mLineInterpPrev[MG_ROD_LURE_LINE_LEN];
cXyz mLineInterpCurr[MG_ROD_LURE_LINE_LEN];
bool mLineInterpPrevValid;
bool mLineInterpCurrValid;
#endif
};
STATIC_ASSERT(sizeof(dmg_rod_class) == 0x1690);
#endif /* D_A_MG_ROD_H */
+9
View File
@@ -66,9 +66,18 @@ public:
/* 0x2CA7 */ s8 hide_lock;
/* 0x2CA8 */ cXyz field_0x2ca8;
/* 0x2CB4 */ u8 field_0x2cb4;
#if TARGET_PC
Mtx mChainInterpPrev[6][16];
Mtx mChainInterpCurr[6][16];
bool mChainInterpPrevValid;
bool mChainInterpCurrValid;
#endif
};
#if !TARGET_PC
STATIC_ASSERT(sizeof(obj_keyhole_class) == 0x2CB8);
#endif
class daObj_Keyhole_HIO_c : public JORReflexible {
public:
+15 -1
View File
@@ -57,6 +57,14 @@ enum class MenuScaling : u8 {
Dusklight = 2,
};
enum class MagicArmorMode : u8 {
NORMAL = 0,
ON_DAMAGE = 1,
DOUBLE_DEFENSE = 2,
INVINCIBLE = 3,
COSMETIC = 4,
};
namespace config {
template <>
struct ConfigEnumRange<BloomMode> {
@@ -105,6 +113,12 @@ struct ConfigEnumRange<MenuScaling> {
static constexpr auto min = MenuScaling::GameCube;
static constexpr auto max = MenuScaling::Dusklight;
};
template <>
struct ConfigEnumRange<MagicArmorMode> {
static constexpr auto min = MagicArmorMode::NORMAL;
static constexpr auto max = MagicArmorMode::COSMETIC;
};
} // namespace config
// Persistent user settings
@@ -234,7 +248,7 @@ struct UserSettings {
ConfigVar<bool> canTransformAnywhere;
ConfigVar<bool> fastRoll;
ConfigVar<bool> fastSpinner;
ConfigVar<bool> freeMagicArmor;
ConfigVar<MagicArmorMode> armorRupeeDrain;
ConfigVar<bool> invincibleEnemies;
// Technical
@@ -542,8 +542,11 @@ void J3DModel::viewCalc() {
}
#ifdef TARGET_PC
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
dusk::frame_interp::record_final_mtx(getDrawMtxPtr()[i]);
Mtx* drawMtx = getDrawMtxPtr();
if (drawMtx != J3DMtxBuffer::sNoUseDrawMtxPtr) {
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
dusk::frame_interp::record_final_mtx(drawMtx[i]);
}
}
#endif
File diff suppressed because it is too large Load Diff
+46 -18
View File
@@ -12764,7 +12764,19 @@ void daAlink_c::setMagicArmorBrk(int i_status) {
BOOL daAlink_c::checkMagicArmorHeavy() const {
#if TARGET_PC
return checkMagicArmorWearAbility() && (dComIfGs_getRupee() == 0 && !dusk::getSettings().game.freeMagicArmor);
if(!checkMagicArmorWearAbility()) {
return false;
}
switch(dusk::getSettings().game.armorRupeeDrain) {
case dusk::MagicArmorMode::NORMAL:
return dComIfGs_getRupee() == 0;
case dusk::MagicArmorMode::ON_DAMAGE:
case dusk::MagicArmorMode::DOUBLE_DEFENSE:
case dusk::MagicArmorMode::INVINCIBLE:
case dusk::MagicArmorMode::COSMETIC:
return false;
}
#else
return checkMagicArmorWearAbility() && dComIfGs_getRupee() == 0;
#endif
@@ -14826,6 +14838,8 @@ void daAlink_c::deleteEquipItem(BOOL i_isPlaySound, BOOL i_isDeleteKantera) {
#if TARGET_PC
mIBChainInterpPrevValid = false;
mIBChainInterpCurrValid = false;
mHsChainInterpPrevValid = false;
mHsChainInterpCurrValid = false;
#endif
field_0x0774 = NULL;
field_0x0778 = NULL;
@@ -18737,7 +18751,7 @@ int daAlink_c::execute() {
#if TARGET_PC
// This handles rupee drain and transitions between rupees/no rupees
// We can skip all of that if the magic armor doesn't use rupees
if (!dusk::getSettings().game.freeMagicArmor && checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
if (dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::NORMAL && checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
#else
if (checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
#endif
@@ -19798,23 +19812,37 @@ int daAlink_c::draw() {
dComIfGd_getOpaListDark()->entryImm(mpHookChain, 0);
#if TARGET_PC
if (dusk::frame_interp::is_enabled() &&
mEquipItem == dItemNo_IRONBALL_e &&
mIronBallChainPos != NULL && mIronBallChainAngle != NULL)
{
if (mIBChainInterpCurrValid) {
memcpy(mIBChainInterpPrevPos, mIBChainInterpCurrPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpPrevAngle, mIBChainInterpCurrAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpPrevHandRoot = mIBChainInterpCurrHandRoot;
mIBChainInterpPrevValid = true;
if (dusk::frame_interp::is_enabled()) {
if (mEquipItem == dItemNo_IRONBALL_e &&
mIronBallChainPos != NULL && mIronBallChainAngle != NULL)
{
if (mIBChainInterpCurrValid) {
memcpy(mIBChainInterpPrevPos, mIBChainInterpCurrPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpPrevAngle, mIBChainInterpCurrAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpPrevHandRoot = mIBChainInterpCurrHandRoot;
mIBChainInterpPrevValid = true;
}
memcpy(mIBChainInterpCurrPos, mIronBallChainPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpCurrAngle, mIronBallChainAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpCurrHandRoot = mHookshotTopPos;
mIBChainInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&ironBallChainInterpCallback, this);
} else {
if (mHsChainInterpCurrValid) {
mHsChainInterpPrevTop = mHsChainInterpCurrTop;
mHsChainInterpPrevRoot = mHsChainInterpCurrRoot;
mHsChainInterpPrevSubRoot = mHsChainInterpCurrSubRoot;
mHsChainInterpPrevSubTop = mHsChainInterpCurrSubTop;
mHsChainInterpPrevValid = true;
}
mHsChainInterpCurrTop = mHookshotTopPos;
mHsChainInterpCurrRoot = mHeldItemRootPos;
mHsChainInterpCurrSubRoot = field_0x3810;
mHsChainInterpCurrSubTop = mIronBallBgChkPos;
mHsChainInterpCurrValid = true;
}
memcpy(mIBChainInterpCurrPos, mIronBallChainPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpCurrAngle, mIronBallChainAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpCurrHandRoot = mHookshotTopPos;
mIBChainInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&ironBallChainInterpCallback, this);
}
#endif
}
+25 -1
View File
@@ -192,7 +192,7 @@ int daAlink_c::setDamagePoint(int i_dmgAmount, BOOL i_checkZoraMag, BOOL i_setDm
if (checkMagicArmorNoDamage()) {
#if TARGET_PC
if(dusk::getSettings().game.freeMagicArmor) {
if(dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::INVINCIBLE) {
i_dmgAmount = 0;
}
#endif
@@ -202,6 +202,11 @@ int daAlink_c::setDamagePoint(int i_dmgAmount, BOOL i_checkZoraMag, BOOL i_setDm
if (!mpHIO->mDamage.m.mInvincible && g_debugHpMode == 0)
#endif
{
#if TARGET_PC
if(checkMagicArmorWearAbility() && dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::DOUBLE_DEFENSE) {
i_dmgAmount /= 2;
}
#endif
dComIfGp_setItemLifeCount(-i_dmgAmount, 0);
}
@@ -281,7 +286,26 @@ BOOL daAlink_c::checkIcePolygonDamage(cBgS_PolyInfo* i_poly) {
}
BOOL daAlink_c::checkMagicArmorNoDamage() {
#ifdef TARGET_PC
if (!checkMagicArmorWearAbility()) {
return false;
}
switch(dusk::getSettings().game.armorRupeeDrain) {
case dusk::MagicArmorMode::NORMAL:
return !checkMagicArmorHeavy();
case dusk::MagicArmorMode::ON_DAMAGE:
return dComIfGs_getRupee() != 0;
case dusk::MagicArmorMode::DOUBLE_DEFENSE:
return false;
case dusk::MagicArmorMode::INVINCIBLE:
return true;
case dusk::MagicArmorMode::COSMETIC:
return false;
}
#else
return checkMagicArmorWearAbility() && !checkMagicArmorHeavy();
#endif
}
int daAlink_c::checkPolyDamage() {
+23
View File
@@ -136,8 +136,26 @@ void daAlink_c::hsChainShape_c::draw() {
}
}
} else {
#if TARGET_PC
cXyz hsInterpTop, hsInterpRoot, hsInterpSubRoot, hsInterpSubTop;
if (dusk::frame_interp::is_enabled() && alink->mHsChainInterpPrevValid && alink->mHsChainInterpCurrValid) {
const f32 alpha = dusk::frame_interp::get_interpolation_step();
hsInterpTop = alink->mHsChainInterpPrevTop + (alink->mHsChainInterpCurrTop - alink->mHsChainInterpPrevTop) * alpha;
hsInterpRoot = alink->mHsChainInterpPrevRoot + (alink->mHsChainInterpCurrRoot - alink->mHsChainInterpPrevRoot) * alpha;
hsInterpSubRoot = alink->mHsChainInterpPrevSubRoot + (alink->mHsChainInterpCurrSubRoot - alink->mHsChainInterpPrevSubRoot) * alpha;
hsInterpSubTop = alink->mHsChainInterpPrevSubTop + (alink->mHsChainInterpCurrSubTop - alink->mHsChainInterpPrevSubTop) * alpha;
} else {
hsInterpTop = alink->getHsChainTopPos();
hsInterpRoot = alink->getHsChainRootPos();
hsInterpSubRoot = alink->getHsSubChainRootPos();
hsInterpSubTop = alink->getHsSubChainTopPos();
}
const cXyz& chainRootPos = hsInterpRoot;
const cXyz& chainTopPos = hsInterpTop;
#else
const cXyz& chainRootPos = alink->getHsChainRootPos();
const cXyz& chainTopPos = alink->getHsChainTopPos();
#endif
cXyz maxDistance = chainRootPos - chainTopPos;
f32 maxDistanceF = maxDistance.abs();
@@ -200,8 +218,13 @@ void daAlink_c::hsChainShape_c::draw() {
}
}
#if TARGET_PC
const cXyz& subChainRootPos = hsInterpSubRoot;
const cXyz& subChainTopPos = hsInterpSubTop;
#else
const cXyz& subChainRootPos = alink->getHsSubChainRootPos();
const cXyz& subChainTopPos = alink->getHsSubChainTopPos();
#endif
maxDistance = subChainRootPos - subChainTopPos;
maxDistanceF = maxDistance.abs();
+2 -2
View File
@@ -348,7 +348,7 @@ void daAlink_c::changeLink(int param_0) {
initModel(static_cast<J3DModelData*>(dComIfG_getObjectRes(l_mArcName, "al_hands.bmd")), 0);
#if TARGET_PC
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.freeMagicArmor)
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.armorRupeeDrain.getValue() != dusk::MagicArmorMode::NORMAL)
#else
if (dComIfGs_getRupee() != 0)
#endif
@@ -458,7 +458,7 @@ void daAlink_c::changeLink(int param_0) {
field_0x06f0 = field_0x064C->getMaterialNodePointer(2)->getShape();
#if TARGET_PC
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.freeMagicArmor) {
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.armorRupeeDrain.getValue() != dusk::MagicArmorMode::NORMAL) {
#else
if (dComIfGs_getRupee() != 0) {
#endif
+9
View File
@@ -5472,6 +5472,15 @@ int daB_ZANT_c::create() {
fopAcM_ct(this, daB_ZANT_c);
OS_REPORT("B_ZANT PARAM %x\n", fopAcM_GetParam(this));
#if TARGET_PC
// Due to our loads being so much faster, Zant can initialize *before* the player
// This breaks respawning in the final phase of the fight when it tries
// to load the player's position
if (daPy_getPlayerActorClass() == NULL) {
return cPhs_INIT_e;
}
#endif
mSwbit = fopAcM_GetParam(this);
if (mSwbit != 0xFF) {
if (dComIfGs_isSwitch(mSwbit, fopAcM_GetRoomNo(this))) {
+8
View File
@@ -923,6 +923,14 @@ static void damage_check(e_sm2_class* i_this) {
sm_hit_actor->mode = 10;
u8 new_color_type = new_col_d[(sm_hit_actor->type * 7) + i_this->type];
#if TARGET_PC
if (dusk::getSettings().game.restoreWiiGlitches &&
((sm_hit_actor->type == TYPE_BLUE && i_this->type == TYPE_YELLOW) ||
(sm_hit_actor->type == TYPE_YELLOW && i_this->type == TYPE_BLUE)))
{
new_color_type = TYPE_GREEN;
}
#endif
i_this->type = new_color_type;
sm_hit_actor->type = new_color_type;
+37 -231
View File
@@ -16,12 +16,30 @@
using GameVersion = dusk::version::GameVersion;
static u8* l_Egnd_mantTEX_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x1C00}, {GameVersion::GcnPal, 0x1C00}}, 0x4000), true); return buf; }
// keep the original version of the cape texture const so we don't need to reload the file
static u8 const * l_Egnd_mantTEX_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x1C00}, {GameVersion::GcnPal, 0x1C00}}, 0x4000), true); return buf; }
static u8* l_Egnd_mantTEX_U_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x5C00}, {GameVersion::GcnPal, 0x5C00}}, 0x4000), true); return buf; }
static u8* l_Egnd_mantPAL_get() { alignas(32) static u8 buf[0x60]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x9C00}, {GameVersion::GcnPal, 0x9C00}}, 0x60), true); return buf; }
#define l_Egnd_mantTEX (l_Egnd_mantTEX_get())
#define l_Egnd_mantTEX_U (l_Egnd_mantTEX_U_get())
#define l_Egnd_mantPAL (l_Egnd_mantPAL_get())
// make a copy of the cape texture that can be overwritten with the tears
static u8 l_Egnd_mantTEX_copy[0x4000];
// keep our cached texture objects out here so that we can update them from multiple places
static bool textureObjsInitialized = false;
static TGXTlutObj tlutObj;
static TGXTexObj mainTexObj;
static TGXTexObj undersideTexObj;
// l_pos is unused
//static f32* l_pos_get() { alignas(32) static f32 buf[507]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0xA44C}, {GameVersion::GcnPal, 0xA44C}}, sizeof(buf)), true); return buf; }
static f32* l_normal_get() { alignas(32) static f32 buf[3]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x9C60}, {GameVersion::GcnPal, 0x9C60}}, sizeof(buf)), true); return buf; }
static f32* l_texCoord_get() { alignas(32) static f32 buf[338]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0xA458}, {GameVersion::GcnPal, 0xA458}}, sizeof(buf)), true); return buf; }
//#define l_pos (l_pos_get())
#define l_normal (l_normal_get())
#define l_texCoord (l_texCoord_get())
#else
#include "assets/l_Egnd_mantTEX.h"
@@ -31,228 +49,6 @@ static u8* l_Egnd_mantPAL_get() { alignas(32) static u8 buf[0x60]; static bo
#endif
#include "d/d_s_play.h"
static u32 l_pos[507] = {
0x42480000, 0x3F5CFC93, 0xC365BD9C, 0x4226AAAA,
0x3F5CFC93, 0xC365BD9C, 0x42055556, 0x3F5CFC93,
0xC365BD9C, 0x41C80000, 0x3F5CFC93, 0xC365BD9C,
0x41855556, 0x3F5CFC93, 0xC365BD9C, 0x41055556,
0x3F5CFC93, 0xC365BD9C, 0x358637BD, 0x3F5CFC93,
0xC365BD9C, 0xC1055554, 0x3F5CFC93, 0xC365BD9C,
0xC1855554, 0x3F5CFC93, 0xC365BD9C, 0xC1C7FFFF,
0x3F5CFC93, 0xC365BD9C, 0xC2055554, 0x3F5CFC93,
0xC365BD9C, 0xC226AAAA, 0x3F5CFC93, 0xC365BD9C,
0xC2480000, 0x3F5CFC93, 0xC365BD9C, 0x42480000,
0x3F5CFC93, 0xC35292F0, 0x4226AAAA, 0x3F5CFC93,
0xC35292F0, 0x42055556, 0x3F5CFC93, 0xC35292F0,
0x41C80000, 0x3F5CFC93, 0xC35292F0, 0x41855556,
0x3F5CFC93, 0xC35292F0, 0x41055556, 0x3F5CFC93,
0xC35292F0, 0x358637BD, 0x3F5CFC93, 0xC35292F0,
0xC1055554, 0x3F5CFC93, 0xC35292F0, 0xC1855554,
0x3F5CFC93, 0xC35292F0, 0xC1C7FFFF, 0x3F5CFC93,
0xC35292F0, 0xC2055554, 0x3F5CFC93, 0xC35292F0,
0xC226AAAA, 0x3F5CFC93, 0xC35292F0, 0xC2480000,
0x3F5CFC93, 0xC35292F0, 0x42480000, 0x3F5CFC93,
0xC33F6846, 0x4226AAAA, 0x3F5CFC93, 0xC33F6846,
0x42055556, 0x3F5CFC93, 0xC33F6846, 0x41C80000,
0x3F5CFC93, 0xC33F6846, 0x41855556, 0x3F5CFC93,
0xC33F6846, 0x41055556, 0x3F5CFC93, 0xC33F6846,
0x358637BD, 0x3F5CFC93, 0xC33F6846, 0xC1055554,
0x3F5CFC93, 0xC33F6846, 0xC1855554, 0x3F5CFC93,
0xC33F6846, 0xC1C7FFFF, 0x3F5CFC93, 0xC33F6846,
0xC2055554, 0x3F5CFC93, 0xC33F6846, 0xC226AAAA,
0x3F5CFC93, 0xC33F6846, 0xC2480000, 0x3F5CFC93,
0xC33F6846, 0x42480000, 0x3F5CFC93, 0xC32C3D9C,
0x4226AAAA, 0x3F5CFC93, 0xC32C3D9C, 0x42055556,
0x3F5CFC93, 0xC32C3D9C, 0x41C80000, 0x3F5CFC93,
0xC32C3D9C, 0x41855556, 0x3F5CFC93, 0xC32C3D9C,
0x41055556, 0x3F5CFC93, 0xC32C3D9C, 0x358637BD,
0x3F5CFC93, 0xC32C3D9C, 0xC1055554, 0x3F5CFC93,
0xC32C3D9C, 0xC1855554, 0x3F5CFC93, 0xC32C3D9C,
0xC1C7FFFF, 0x3F5CFC93, 0xC32C3D9C, 0xC2055554,
0x3F5CFC93, 0xC32C3D9C, 0xC226AAAA, 0x3F5CFC93,
0xC32C3D9C, 0xC2480000, 0x3F5CFC93, 0xC32C3D9C,
0x42480000, 0x3F5CFC93, 0xC31912F1, 0x4226AAAA,
0x3F5CFC93, 0xC31912F1, 0x42055556, 0x3F5CFC93,
0xC31912F1, 0x41C80000, 0x3F5CFC93, 0xC31912F1,
0x41855556, 0x3F5CFC93, 0xC31912F1, 0x41055556,
0x3F5CFC93, 0xC31912F1, 0x358637BD, 0x3F5CFC93,
0xC31912F1, 0xC1055554, 0x3F5CFC93, 0xC31912F1,
0xC1855554, 0x3F5CFC93, 0xC31912F1, 0xC1C7FFFF,
0x3F5CFC93, 0xC31912F1, 0xC2055554, 0x3F5CFC93,
0xC31912F1, 0xC226AAAA, 0x3F5CFC93, 0xC31912F1,
0xC2480000, 0x3F5CFC93, 0xC31912F1, 0x42480000,
0x3F5CFC93, 0xC305E846, 0x4226AAAA, 0x3F5CFC93,
0xC305E846, 0x42055556, 0x3F5CFC93, 0xC305E846,
0x41C80000, 0x3F5CFC93, 0xC305E846, 0x41855556,
0x3F5CFC93, 0xC305E846, 0x41055556, 0x3F5CFC93,
0xC305E846, 0x358637BD, 0x3F5CFC93, 0xC305E846,
0xC1055554, 0x3F5CFC93, 0xC305E846, 0xC1855554,
0x3F5CFC93, 0xC305E846, 0xC1C7FFFF, 0x3F5CFC93,
0xC305E846, 0xC2055554, 0x3F5CFC93, 0xC305E846,
0xC226AAAA, 0x3F5CFC93, 0xC305E846, 0xC2480000,
0x3F5CFC93, 0xC305E846, 0x42480000, 0x3F5CFC93,
0xC2E57B38, 0x4226AAAA, 0x3F5CFC93, 0xC2E57B38,
0x42055556, 0x3F5CFC93, 0xC2E57B38, 0x41C80000,
0x3F5CFC93, 0xC2E57B38, 0x41855556, 0x3F5CFC93,
0xC2E57B38, 0x41055556, 0x3F5CFC93, 0xC2E57B38,
0x358637BD, 0x3F5CFC93, 0xC2E57B38, 0xC1055554,
0x3F5CFC93, 0xC2E57B38, 0xC1855554, 0x3F5CFC93,
0xC2E57B38, 0xC1C7FFFF, 0x3F5CFC93, 0xC2E57B38,
0xC2055554, 0x3F5CFC93, 0xC2E57B38, 0xC226AAAA,
0x3F5CFC93, 0xC2E57B38, 0xC2480000, 0x3F5CFC93,
0xC2E57B38, 0x42480000, 0x3F5CFC93, 0xC2BF25E2,
0x4226AAAA, 0x3F5CFC93, 0xC2BF25E2, 0x42055556,
0x3F5CFC93, 0xC2BF25E2, 0x41C80000, 0x3F5CFC93,
0xC2BF25E2, 0x41855556, 0x3F5CFC93, 0xC2BF25E2,
0x41055556, 0x3F5CFC93, 0xC2BF25E2, 0x358637BD,
0x3F5CFC93, 0xC2BF25E2, 0xC1055554, 0x3F5CFC93,
0xC2BF25E2, 0xC1855554, 0x3F5CFC93, 0xC2BF25E2,
0xC1C7FFFF, 0x3F5CFC93, 0xC2BF25E2, 0xC2055554,
0x3F5CFC93, 0xC2BF25E2, 0xC226AAAA, 0x3F5CFC93,
0xC2BF25E2, 0xC2480000, 0x3F5CFC93, 0xC2BF25E2,
0x42480000, 0x3F5CFC93, 0xC298D08D, 0x4226AAAA,
0x3F5CFC93, 0xC298D08D, 0x42055556, 0x3F5CFC93,
0xC298D08D, 0x41C80000, 0x3F5CFC93, 0xC298D08D,
0x41855556, 0x3F5CFC93, 0xC298D08D, 0x41055556,
0x3F5CFC93, 0xC298D08D, 0x358637BD, 0x3F5CFC93,
0xC298D08D, 0xC1055554, 0x3F5CFC93, 0xC298D08D,
0xC1855554, 0x3F5CFC93, 0xC298D08D, 0xC1C7FFFF,
0x3F5CFC93, 0xC298D08D, 0xC2055554, 0x3F5CFC93,
0xC298D08D, 0xC226AAAA, 0x3F5CFC93, 0xC298D08D,
0xC2480000, 0x3F5CFC93, 0xC298D08D, 0x42480000,
0x3F5CFC93, 0xC264F66F, 0x4226AAAA, 0x3F5CFC93,
0xC264F66F, 0x42055556, 0x3F5CFC93, 0xC264F66F,
0x41C80000, 0x3F5CFC93, 0xC264F66F, 0x41855556,
0x3F5CFC93, 0xC264F66F, 0x41055556, 0x3F5CFC93,
0xC264F66F, 0x358637BD, 0x3F5CFC93, 0xC264F66F,
0xC1055554, 0x3F5CFC93, 0xC264F66F, 0xC1855554,
0x3F5CFC93, 0xC264F66F, 0xC1C7FFFF, 0x3F5CFC93,
0xC264F66F, 0xC2055554, 0x3F5CFC93, 0xC264F66F,
0xC226AAAA, 0x3F5CFC93, 0xC264F66F, 0xC2480000,
0x3F5CFC93, 0xC264F66F, 0x42480000, 0x3F5CFC93,
0xC2184BC4, 0x4226AAAA, 0x3F5CFC93, 0xC2184BC4,
0x42055556, 0x3F5CFC93, 0xC2184BC4, 0x41C80000,
0x3F5CFC93, 0xC2184BC4, 0x41855556, 0x3F5CFC93,
0xC2184BC4, 0x41055556, 0x3F5CFC93, 0xC2184BC4,
0x358637BD, 0x3F5CFC93, 0xC2184BC4, 0xC1055554,
0x3F5CFC93, 0xC2184BC4, 0xC1855554, 0x3F5CFC93,
0xC2184BC4, 0xC1C7FFFF, 0x3F5CFC93, 0xC2184BC4,
0xC2055554, 0x3F5CFC93, 0xC2184BC4, 0xC226AAAA,
0x3F5CFC93, 0xC2184BC4, 0xC2480000, 0x3F5CFC93,
0xC2184BC4, 0x42480000, 0x3F5CFC93, 0xC1974231,
0x4226AAAA, 0x3F5CFC93, 0xC1974231, 0x42055556,
0x3F5CFC93, 0xC1974231, 0x41C80000, 0x3F5CFC93,
0xC1974231, 0x41855556, 0x3F5CFC93, 0xC1974231,
0x41055556, 0x3F5CFC93, 0xC1974231, 0x358637BD,
0x3F5CFC93, 0xC1974231, 0xC1055554, 0x3F5CFC93,
0xC1974231, 0xC1855554, 0x3F5CFC93, 0xC1974231,
0xC1C7FFFF, 0x3F5CFC93, 0xC1974231, 0xC2055554,
0x3F5CFC93, 0xC1974231, 0xC226AAAA, 0x3F5CFC93,
0xC1974231, 0xC2480000, 0x3F5CFC93, 0xC1974231,
0x42480000, 0x3F5CFC93, 0x3E84C964, 0x4226AAAA,
0x3F5CFC93, 0x3E84C964, 0x42055556, 0x3F5CFC93,
0x3E84C964, 0x41C80000, 0x3F5CFC93, 0x3E84C964,
0x41855556, 0x3F5CFC93, 0x3E84C964, 0x41055556,
0x3F5CFC93, 0x3E84C964, 0x358637BD, 0x3F5CFC93,
0x3E84C964, 0xC1055554, 0x3F5CFC93, 0x3E84C964,
0xC1855554, 0x3F5CFC93, 0x3E84C964, 0xC1C7FFFF,
0x3F5CFC93, 0x3E84C964, 0xC2055554, 0x3F5CFC93,
0x3E84C964, 0xC226AAAA, 0x3F5CFC93, 0x3E84C964,
0xC2480000, 0x3F5CFC93, 0x3E84C964,
};
static u32 l_normal[3] = {
0x00000000, 0x3F800000, 0x00000000,
};
static u32 l_texCoord[338] = {
0x00000000, 0x3F6AAAB0, 0x3DAAAA7E, 0x3F6AAAB0,
0x3DAAAA7E, 0x3F800000, 0x00000000, 0x3F800000,
0x3E2AAAC1, 0x3F6AAAB0, 0x3E2AAAC1, 0x3F800000,
0x3E800000, 0x3F6AAAB0, 0x3E800000, 0x3F800000,
0x3EAAAA9F, 0x3F6AAAB0, 0x3EAAAA9F, 0x3F800000,
0x3ED55561, 0x3F6AAAB0, 0x3ED55561, 0x3F800000,
0x3F000000, 0x3F6AAAB0, 0x3F000000, 0x3F800000,
0x3F155550, 0x3F6AAAB0, 0x3F155550, 0x3F800000,
0x3F2AAAB0, 0x3F6AAAB0, 0x3F2AAAB0, 0x3F800000,
0x3F400000, 0x3F6AAAB0, 0x3F400000, 0x3F800000,
0x3F555550, 0x3F6AAAB0, 0x3F555550, 0x3F800000,
0x3F6AAAB0, 0x3F6AAAB0, 0x3F6AAAB0, 0x3F800000,
0x3F800000, 0x3F6AAAB0, 0x3F800000, 0x3F800000,
0x00000000, 0x3F555550, 0x3DAAAA7E, 0x3F555550,
0x3E2AAAC1, 0x3F555550, 0x3E800000, 0x3F555550,
0x3EAAAA9F, 0x3F555550, 0x3ED55561, 0x3F555550,
0x3F000000, 0x3F555550, 0x3F155550, 0x3F555550,
0x3F2AAAB0, 0x3F555550, 0x3F400000, 0x3F555550,
0x3F555550, 0x3F555550, 0x3F6AAAB0, 0x3F555550,
0x3F800000, 0x3F555550, 0x00000000, 0x3F400000,
0x3DAAAA7E, 0x3F400000, 0x3E2AAAC1, 0x3F400000,
0x3E800000, 0x3F400000, 0x3EAAAA9F, 0x3F400000,
0x3ED55561, 0x3F400000, 0x3F000000, 0x3F400000,
0x3F155550, 0x3F400000, 0x3F2AAAB0, 0x3F400000,
0x3F400000, 0x3F400000, 0x3F555550, 0x3F400000,
0x3F6AAAB0, 0x3F400000, 0x3F800000, 0x3F400000,
0x00000000, 0x3F2AAAB0, 0x3DAAAA7E, 0x3F2AAAB0,
0x3E2AAAC1, 0x3F2AAAB0, 0x3E800000, 0x3F2AAAB0,
0x3EAAAA9F, 0x3F2AAAB0, 0x3ED55561, 0x3F2AAAB0,
0x3F000000, 0x3F2AAAB0, 0x3F155550, 0x3F2AAAB0,
0x3F2AAAB0, 0x3F2AAAB0, 0x3F400000, 0x3F2AAAB0,
0x3F555550, 0x3F2AAAB0, 0x3F6AAAB0, 0x3F2AAAB0,
0x3F800000, 0x3F2AAAB0, 0x00000000, 0x3F155550,
0x3DAAAA7E, 0x3F155550, 0x3E2AAAC1, 0x3F155550,
0x3E800000, 0x3F155550, 0x3EAAAA9F, 0x3F155550,
0x3ED55561, 0x3F155550, 0x3F000000, 0x3F155550,
0x3F155550, 0x3F155550, 0x3F2AAAB0, 0x3F155550,
0x3F400000, 0x3F155550, 0x3F555550, 0x3F155550,
0x3F6AAAB0, 0x3F155550, 0x3F800000, 0x3F155550,
0x00000000, 0x3F000000, 0x3DAAAA7E, 0x3F000000,
0x3E2AAAC1, 0x3F000000, 0x3E800000, 0x3F000000,
0x3EAAAA9F, 0x3F000000, 0x3ED55561, 0x3F000000,
0x3F000000, 0x3F000000, 0x3F155550, 0x3F000000,
0x3F2AAAB0, 0x3F000000, 0x3F400000, 0x3F000000,
0x3F555550, 0x3F000000, 0x3F6AAAB0, 0x3F000000,
0x3F800000, 0x3F000000, 0x00000000, 0x3ED55561,
0x3DAAAA7E, 0x3ED55561, 0x3E2AAAC1, 0x3ED55561,
0x3E800000, 0x3ED55561, 0x3EAAAA9F, 0x3ED55561,
0x3ED55561, 0x3ED55561, 0x3F000000, 0x3ED55561,
0x3F155550, 0x3ED55561, 0x3F2AAAB0, 0x3ED55561,
0x3F400000, 0x3ED55561, 0x3F555550, 0x3ED55561,
0x3F6AAAB0, 0x3ED55561, 0x3F800000, 0x3ED55561,
0x00000000, 0x3EAAAA9F, 0x3DAAAA7E, 0x3EAAAA9F,
0x3E2AAAC1, 0x3EAAAA9F, 0x3E800000, 0x3EAAAA9F,
0x3EAAAA9F, 0x3EAAAA9F, 0x3ED55561, 0x3EAAAA9F,
0x3F000000, 0x3EAAAA9F, 0x3F155550, 0x3EAAAA9F,
0x3F2AAAB0, 0x3EAAAA9F, 0x3F400000, 0x3EAAAA9F,
0x3F555550, 0x3EAAAA9F, 0x3F6AAAB0, 0x3EAAAA9F,
0x3F800000, 0x3EAAAA9F, 0x00000000, 0x3E800000,
0x3DAAAA7E, 0x3E800000, 0x3E2AAAC1, 0x3E800000,
0x3E800000, 0x3E800000, 0x3EAAAA9F, 0x3E800000,
0x3ED55561, 0x3E800000, 0x3F000000, 0x3E800000,
0x3F155550, 0x3E800000, 0x3F2AAAB0, 0x3E800000,
0x3F400000, 0x3E800000, 0x3F555550, 0x3E800000,
0x3F6AAAB0, 0x3E800000, 0x3F800000, 0x3E800000,
0x00000000, 0x3E2AAAC1, 0x3DAAAA7E, 0x3E2AAAC1,
0x3E2AAAC1, 0x3E2AAAC1, 0x3E800000, 0x3E2AAAC1,
0x3EAAAA9F, 0x3E2AAAC1, 0x3ED55561, 0x3E2AAAC1,
0x3F000000, 0x3E2AAAC1, 0x3F155550, 0x3E2AAAC1,
0x3F2AAAB0, 0x3E2AAAC1, 0x3F400000, 0x3E2AAAC1,
0x3F555550, 0x3E2AAAC1, 0x3F6AAAB0, 0x3E2AAAC1,
0x3F800000, 0x3E2AAAC1, 0x00000000, 0x3DAAAA7E,
0x3DAAAA7E, 0x3DAAAA7E, 0x3E2AAAC1, 0x3DAAAA7E,
0x3E800000, 0x3DAAAA7E, 0x3EAAAA9F, 0x3DAAAA7E,
0x3ED55561, 0x3DAAAA7E, 0x3F000000, 0x3DAAAA7E,
0x3F155550, 0x3DAAAA7E, 0x3F2AAAB0, 0x3DAAAA7E,
0x3F400000, 0x3DAAAA7E, 0x3F555550, 0x3DAAAA7E,
0x3F6AAAB0, 0x3DAAAA7E, 0x3F800000, 0x3DAAAA7E,
0x00000000, 0x00000000, 0x3DAAAA7E, 0x00000000,
0x3E2AAAC1, 0x00000000, 0x3E800000, 0x00000000,
0x3EAAAA9F, 0x00000000, 0x3ED55561, 0x00000000,
0x3F000000, 0x00000000, 0x3F155550, 0x00000000,
0x3F2AAAB0, 0x00000000, 0x3F400000, 0x00000000,
0x3F555550, 0x00000000, 0x3F6AAAB0, 0x00000000,
0x3F800000, 0x00000000,
};
#if TARGET_PC
using GameVersion = dusk::version::GameVersion;
@@ -307,7 +103,7 @@ static void mant_build_anchor_frame(const cXyz& anchor_a, const cXyz& anchor_b,
void daMant_packet_c::draw() {
ZoneScoped;
#if TARGET_PC
void* image = l_Egnd_mantTEX;
void* image = l_Egnd_mantTEX_copy;
void* lut = l_Egnd_mantPAL;
#else
void* image = tex_d[0];
@@ -389,12 +185,12 @@ void daMant_packet_c::draw() {
}
}
GXSETARRAY(GX_VA_POS, draw_pos, sizeof(mNrm[0]), 12, true);
GXSETARRAY(GX_VA_NRM, &l_normal, sizeof(l_normal), 12, false);
GXSETARRAY(GX_VA_NRM, l_normal, sizeof(f32) * 3, 12, false);
#else
GXSETARRAY(GX_VA_POS, this->getPos(), sizeof(mPos[0]), 12, true);
GXSETARRAY(GX_VA_NRM, this->getNrm(), sizeof(mNrm[0]), 12, true);
#endif
GXSETARRAY(GX_VA_TEX0, &l_texCoord, sizeof(l_texCoord), 8, false); // TODO: set to true when converted to float literals
GXSETARRAY(GX_VA_TEX0, l_texCoord, sizeof(f32) * 338, 8, false);
GXSetZCompLoc(0);
GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_ENABLE);
@@ -420,10 +216,6 @@ void daMant_packet_c::draw() {
GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
#if TARGET_PC
static bool textureObjsInitialized = false;
static TGXTlutObj tlutObj;
static TGXTexObj mainTexObj;
static TGXTexObj undersideTexObj;
if (!textureObjsInitialized) {
GXInitTlutObj(&tlutObj, lut, GX_TL_RGB5A3, 0x100);
GXInitTexObjCI(&mainTexObj, image, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
@@ -917,8 +709,14 @@ static int daMant_Execute(mant_class* i_this) {
if (0 <= uVar1 && uVar1 < 0x4000) {
int iVar5 = (uVar1 & 7) + (uVar1 & 0x78) * 4 + (uVar1 >> 4 & 0x18) + (uVar1 & 0x3e00);
l_Egnd_mantTEX[iVar5] = l_Egnd_mantTEX_U[iVar5] = 0;
DUSK_IF_ELSE(l_Egnd_mantTEX_copy[iVar5], l_Egnd_mantTEX[iVar5]) = l_Egnd_mantTEX_U[iVar5] = 0;
}
#if TARGET_PC
if(textureObjsInitialized) {
GXInitTlutObjData(&tlutObj, l_Egnd_mantPAL); // make sure the cached textures are updated
}
#endif
}
}
@@ -956,6 +754,14 @@ static int daMant_Create(fopAc_ac_c* i_this) {
l_Egnd_mantTEX_U[i] = 6;
}
#if TARGET_PC
memcpy(l_Egnd_mantTEX_copy, l_Egnd_mantTEX, sizeof(l_Egnd_mantTEX_copy));
if(textureObjsInitialized) {
GXInitTlutObjData(&tlutObj, l_Egnd_mantPAL); // make sure the cached textures are updated
}
#endif
lbl_277_bss_0 = 0;
daMant_Execute(m_this);
return 4;
+49
View File
@@ -26,6 +26,7 @@
#include <cstring>
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
#include "dusk/version.hpp"
#include "dusk/randomizer/game/randomizer_context.hpp"
@@ -181,6 +182,25 @@ static int Worm_nodeCallBack(J3DJoint* i_joint, int param_1) {
return 1;
}
#if TARGET_PC
static void dmg_rod_interp_callback(bool isSimFrame, void* pUserWork) {
dmg_rod_class* i_this = (dmg_rod_class*)pUserWork;
if (!i_this->mLineInterpPrevValid || !i_this->mLineInterpCurrValid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
const int count = i_this->kind == MG_ROD_KIND_LURE ? MG_ROD_LURE_LINE_LEN : MG_ROD_UKI_LINE_LEN;
cXyz* dst = i_this->linemat.getPos(0);
for (int i = 0; i < count; i++) {
const cXyz& p0 = i_this->mLineInterpPrev[i];
const cXyz& p1 = i_this->mLineInterpCurr[i];
dst[i] = p0 + (p1 - p0) * alpha;
}
static GXColor l_color = {0xFF, 0xFF, 0x96, 0xFF};
i_this->linemat.update(count, l_color, &i_this->actor.tevStr);
}
#endif
static int dmg_rod_Draw(dmg_rod_class* i_this) {
int unused;
fopAc_ac_c* actor = &i_this->actor;
@@ -221,6 +241,18 @@ static int dmg_rod_Draw(dmg_rod_class* i_this) {
i_this->linemat.update(MG_ROD_LURE_LINE_LEN, l_color, &i_this->actor.tevStr);
dComIfGd_set3DlineMat(&i_this->linemat);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (i_this->mLineInterpCurrValid) {
memcpy(i_this->mLineInterpPrev, i_this->mLineInterpCurr, MG_ROD_LURE_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpPrevValid = true;
}
memcpy(i_this->mLineInterpCurr, i_this->linemat.getPos(0), MG_ROD_LURE_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&dmg_rod_interp_callback, i_this);
}
#endif
model = i_this->rod_modelMorf->getModel();
g_env_light.setLightTevColorType_MAJI(model, &i_this->actor.tevStr);
i_this->rod_modelMorf->entryDL();
@@ -245,6 +277,18 @@ static int dmg_rod_Draw(dmg_rod_class* i_this) {
i_this->linemat.update(MG_ROD_UKI_LINE_LEN, l_color, &i_this->actor.tevStr);
dComIfGd_set3DlineMat(&i_this->linemat);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (i_this->mLineInterpCurrValid) {
memcpy(i_this->mLineInterpPrev, i_this->mLineInterpCurr, MG_ROD_UKI_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpPrevValid = true;
}
memcpy(i_this->mLineInterpCurr, i_this->linemat.getPos(0), MG_ROD_UKI_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&dmg_rod_interp_callback, i_this);
}
#endif
for (int i = 0; i < 15; i++) {
g_env_light.setLightTevColorType_MAJI(i_this->rod_uki_model[i], &actor->tevStr);
mDoExt_modelUpdateDL(i_this->rod_uki_model[i]);
@@ -6415,6 +6459,11 @@ static int dmg_rod_Create(fopAc_ac_c* i_this) {
return cPhs_ERROR_e;
}
#if TARGET_PC
rod->mLineInterpPrevValid = false;
rod->mLineInterpCurrValid = false;
#endif
OS_REPORT("//////////////MG_ROD SET 2 !!\n");
if (!hio_set) {
rod->HIOInit = TRUE;
+4 -4
View File
@@ -332,13 +332,13 @@ int daNpcImpal_c::step(s16 i_angle, int i_animate) {
}
void daNpcImpal_c::playExpression() {
daNpcF_anmPlayData dat0 = {ANM_1, mpHIO->m.common.morf_frame, 1};
daNpcF_anmPlayData dat0 = {ANM_1, mpHIO->m.common.morf_frame, DUSK_IF_ELSE(0, 1)};
daNpcF_anmPlayData* pDat0[1] = {&dat0};
daNpcF_anmPlayData dat1 = {ANM_5, mpHIO->m.common.morf_frame, 1};
daNpcF_anmPlayData dat1 = {ANM_5, mpHIO->m.common.morf_frame, DUSK_IF_ELSE(0, 1)};
daNpcF_anmPlayData* pDat1[1] = {&dat1};
daNpcF_anmPlayData dat2 = {ANM_4, mpHIO->m.common.morf_frame, 1};
daNpcF_anmPlayData dat2 = {ANM_4, mpHIO->m.common.morf_frame, DUSK_IF_ELSE(0, 1)};
daNpcF_anmPlayData* pDat2[1] = {&dat2};
daNpcF_anmPlayData dat3 = {ANM_6, mpHIO->m.common.morf_frame, 1};
daNpcF_anmPlayData dat3 = {ANM_6, mpHIO->m.common.morf_frame, DUSK_IF_ELSE(0, 1)};
daNpcF_anmPlayData* pDat3[1] = {&dat3};
daNpcF_anmPlayData dat4 = {ANM_8, mpHIO->m.common.morf_frame, 0};
daNpcF_anmPlayData* pDat4[1] = {&dat4};
+38
View File
@@ -10,6 +10,9 @@
#include "d/d_s_play.h"
#include "d/actor/d_a_player.h"
#include "Z2AudioLib/Z2Instances.h"
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#endif
daObj_Keyhole_HIO_c::daObj_Keyhole_HIO_c() {
id = -1;
@@ -53,6 +56,21 @@ static int daObj_Keyhole_Draw(obj_keyhole_class* i_this) {
for (int i = 0; i < 6; i++) {
kh_chain_s* chain_s = &i_this->chain_s[i];
for (int j = 0; j < i_this->chain_num; j++) {
#if TARGET_PC
if (dusk::frame_interp::is_enabled() && i_this->mChainInterpPrevValid && i_this->mChainInterpCurrValid) {
const f32 alpha = dusk::frame_interp::get_interpolation_step();
Mtx mtx;
const f32* p0 = (const f32*)i_this->mChainInterpPrev[i][j];
const f32* p1 = (const f32*)i_this->mChainInterpCurr[i][j];
f32* dst = (f32*)mtx;
for (int k = 0; k < 12; k++) {
dst[k] = p0[k] + (p1[k] - p0[k]) * alpha;
}
chain_s->model[j]->setBaseTRMtx(mtx);
g_env_light.setLightTevColorType_MAJI(chain_s->model[j], &actor->tevStr);
mDoExt_modelUpdateDL(chain_s->model[j]);
} else
#endif
dComIfGp_entrySimpleModel(chain_s->model[j], fopAcM_GetRoomNo(actor));
}
}
@@ -370,6 +388,21 @@ static void chain_move(obj_keyhole_class* i_this) {
ANGLE_ADD(sp8, TREG_S(0) + 0x3D00);
}
}
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (i_this->mChainInterpCurrValid) {
memcpy(i_this->mChainInterpPrev, i_this->mChainInterpCurr, sizeof(i_this->mChainInterpCurr));
i_this->mChainInterpPrevValid = true;
}
for (int i = 0; i < 6; i++) {
for (int j = 0; j < i_this->chain_num; j++) {
MTXCopy(i_this->chain_s[i].model[j]->getBaseTRMtx(), i_this->mChainInterpCurr[i][j]);
}
}
i_this->mChainInterpCurrValid = true;
}
#endif
}
static void open(obj_keyhole_class* i_this) {
@@ -750,6 +783,11 @@ static int daObj_Keyhole_Create(fopAc_ac_c* a_this) {
return cPhs_ERROR_e;
}
#if TARGET_PC
i_this->mChainInterpPrevValid = false;
i_this->mChainInterpCurrValid = false;
#endif
OS_REPORT("//////////////OBJ_KEYHOLE SET 2 !!\n");
if (i_this->arg0 == 3) {
+10 -1
View File
@@ -499,7 +499,16 @@ int daObjLife_c::initActionOrderGetDemo() {
int daObjLife_c::actionOrderGetDemo() {
if (eventInfo.checkCommandItem()) {
setStatus(STATUS_GET_DEMO_e);
#if TARGET_PC
// Set the tracker flag for rando now. The flag doesn't normally
// get set until after execItemGive runs
if (randomizer_IsActive()) {
g_randomizerState.mTrackerTempItemFlag.flag = getSaveBitNo();
g_randomizerState.mTrackerTempItemFlag.stage = getStageSaveId(getStageID());
}
#endif
if (mItemId != fpcM_ERROR_PROCESS_ID_e) {
dComIfGp_event_setItemPartnerId(mItemId);
}
+29 -11
View File
@@ -19,12 +19,30 @@
#include <numbers>
#include <array>
constexpr u16 kMapResolutionMultiplier = 4;
constexpr u16 kMapImageSide = 16 * kMapResolutionMultiplier;
constexpr u16 kPreferredMapResolutionMultiplier = 4;
constexpr u32 kMaxMapRenderPixels = 4096 * 4096;
constexpr u16 kMapImageSide = 16 * kPreferredMapResolutionMultiplier;
constexpr u32 kMapImageTotalPixels = kMapImageSide * kMapImageSide;
typedef std::function<u8(size_t, size_t)> PaintI8Fn;
u16 map_resolution_multiplier(u16 width, u16 height) {
const u32 basePixels = static_cast<u32>(width) * height;
if (basePixels == 0) {
return 1;
}
u16 scale = kPreferredMapResolutionMultiplier;
while (scale > 1) {
const u32 scalePixels = static_cast<u32>(scale) * scale;
if (basePixels <= kMaxMapRenderPixels / scalePixels) {
break;
}
scale--;
}
return scale;
}
void paint_i8(std::span<u8> dst, size_t width, PaintI8Fn paint) {
const auto blocksAcross = width >> 3;
@@ -478,9 +496,9 @@ void dRenderingMap_c::makeResTIMG(ResTIMG* p_image, u16 width, u16 height, u8* p
p_image->format = GX_TF_C8;
p_image->alphaEnabled = 2;
#ifdef TARGET_PC
// Increase map render resolution
p_image->width = width * kMapResolutionMultiplier;
p_image->height = height * kMapResolutionMultiplier;
const u16 scale = map_resolution_multiplier(width, height);
p_image->width = width * scale;
p_image->height = height * scale;
#else
p_image->width = width;
p_image->height = height;
@@ -563,9 +581,9 @@ void dRenderingFDAmap_c::drawBack() const {
void dRenderingFDAmap_c::preRenderingMap() {
#ifdef TARGET_PC
// Increase map render resolution
const u16 w = mTexWidth * kMapResolutionMultiplier;
const u16 h = mTexHeight * kMapResolutionMultiplier;
const u16 scale = map_resolution_multiplier(mTexWidth, mTexHeight);
const u16 w = mTexWidth * scale;
const u16 h = mTexHeight * scale;
GXCreateFrameBuffer(w, h);
// Set logical viewport dimensions
GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f);
@@ -610,9 +628,9 @@ void dRenderingFDAmap_c::preRenderingMap() {
void dRenderingFDAmap_c::postRenderingMap() {
GXSetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL);
#ifdef TARGET_PC
// Increase map render resolution
const u16 w = mTexWidth * kMapResolutionMultiplier;
const u16 h = mTexHeight * kMapResolutionMultiplier;
const u16 scale = map_resolution_multiplier(mTexWidth, mTexHeight);
const u16 w = mTexWidth * scale;
const u16 h = mTexHeight * scale;
GXSetTexCopySrc(0, 0, w, h);
GXSetTexCopyDst(w, h, GX_CTF_R8, GX_FALSE);
GXCopyTex(field_0x4, GX_TRUE);
+6
View File
@@ -1943,6 +1943,12 @@ void dMenu_Fmap2DBack_c::regionMapMove(STControl* i_stick) {
calcAllMapPos2D(mArrowPos3DX + control_xpos - mStageTransX,
mArrowPos3DZ + control_ypos - mStageTransZ, &pos_x, &pos_y);
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
pos_x = getMirrorPosX(pos_x, 0.0f);
}
#endif
mSelectRegion = 0xff;
int region = mRegionCursor;
if (region != 0xff && region != 7) {
+72 -3
View File
@@ -609,6 +609,70 @@ int dMsgObject_c::_delete() {
return 1;
}
#if TARGET_PC
struct MirrorMsgOverride {
u32 gcMsgId;
u32 wiiMsgId;
};
static const MirrorMsgOverride mirrorMsgOverrides[] = {
{0x153a, 0x3c4a},
{0x1553, 0x3c63},
{0x1558, 0x3c68},
{0x155c, 0x3c6c},
{0x1569, 0x3c79},
{0x156f, 0x3c7f},
{0x1f81, 0x4691},
{0x232a, 0x4a3a},
{0x13f2, 0x3b02},
{0x1416, 0x3b26},
{0x1417, 0x3b27},
{0x1419, 0x3b29},
{0x1521, 0x3c31},
{0x1614, 0x3d24},
{0x1626, 0x3d36},
{0x1628, 0x3d38},
{0x16aa, 0x3dba},
{0x16b8, 0x3dc8},
{0x16b9, 0x3dc9},
{0x1904, 0x4014},
{0x1919, 0x4029},
{0x19cd, 0x40dd},
{0x19d3, 0x40e3},
{0x19d6, 0x40e6},
{0x19e6, 0x40f6},
{0x19eb, 0x40fb},
{0x14b6, 0x3bc6},
{0x151a, 0x3c2a},
{0x1530, 0x3c40},
{0x1532, 0x3c42},
{0x2726, 0x4e36},
{0x2736, 0x4e46},
{0x2739, 0x4e49},
{0x274c, 0x4e5c},
{0x24da, 0x4bea},
{0x24db, 0x4beb},
{0x13d8, 0x3ae8},
{0x13dc, 0x3aec},
{0x13eb, 0x3afb},
{0x17df, 0x3eef},
{0x17e2, 0x3ef2},
{0x1dae, 0x44be},
{0x14ca, 0x3bda},
{0x470, 0x493},
{0x473, 0x492},
};
static u32 getMirrorMsgOverride(u32 msgId) {
for (size_t i = 0; i < sizeof(mirrorMsgOverrides) / sizeof(mirrorMsgOverrides[0]); i++) {
if (mirrorMsgOverrides[i].gcMsgId == msgId) {
return mirrorMsgOverrides[i].wiiMsgId;
}
}
return msgId;
}
#endif
void dMsgObject_c::setMessageIndex(u32 revoIndex, u32 param_2, bool param_3) {
field_0x158 = revoIndex;
revoIndex = getRevoMessageIndex(revoIndex);
@@ -735,9 +799,14 @@ u32 dMsgObject_c::getRevoMessageIndex(u32 param_1) {
}
#endif
if (!g_MsgObject_HIO_c.mMessageDisplay) {
return param_1;
}
#if TARGET_PC
if (!dusk::getSettings().game.enableMirrorMode) {
if (!g_MsgObject_HIO_c.mMessageDisplay) { return param_1; } }
if (param_1 == getMirrorMsgOverride(param_1)) { return param_1; }
#else
if (!g_MsgObject_HIO_c.mMessageDisplay) { return param_1; }
#endif
u32 msgIndexCount;
JMSMesgInfo_c* pMsg;
int i = 0;
+3
View File
@@ -0,0 +1,3 @@
const char* __asan_default_options(void) {
return "abort_on_error=1:symbolize=1:intercept_memcmp=0:detect_leaks=0";
}
+26 -22
View File
@@ -23,13 +23,9 @@ using json = nlohmann::json;
aurora::Module DuskConfigLog("dusk::config");
static absl::flat_hash_map<std::string_view, ConfigVarBase*> RegisteredConfigVars;
static bool RegistrationDone = false;
static absl::flat_hash_map<std::string_view, ConfigVarBase*>& registered_config_vars() {
static absl::flat_hash_map<std::string_view, ConfigVarBase*> vars;
return vars;
}
static std::filesystem::path GetConfigJsonPath() {
return dusk::ConfigPath / ConfigFileName;
}
@@ -80,15 +76,12 @@ template<ConfigValue T>
void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) {
if constexpr (std::is_enum_v<T>) {
if (jsonValue.is_boolean()) {
DuskConfigLog.error("Doing default migration of CVar {} from bool, enum values may not be what is expected!", cVar.getName());
using Underlying = std::underlying_type_t<T>;
const bool b = jsonValue.get<bool>();
Underlying raw;
if constexpr (std::is_same_v<T, dusk::FrameInterpMode>) {
raw = b ? static_cast<Underlying>(2) : static_cast<Underlying>(0);
} else {
raw = b ? static_cast<Underlying>(1) : static_cast<Underlying>(0);
}
const Underlying raw = b ? static_cast<Underlying>(1) : static_cast<Underlying>(0);
cVar.setValue(sanitizeEnumValue(cVar, static_cast<T>(raw)), false);
return;
@@ -198,23 +191,36 @@ namespace dusk::config {
template class ConfigImpl<dusk::DiscVerificationState>;
template class ConfigImpl<dusk::GameLanguage>;
template class ConfigImpl<dusk::GyroMode>;
template<> void ConfigImpl<FrameInterpMode>::loadFromJson(ConfigVar<FrameInterpMode>& cVar, const json& jsonValue) {
if (jsonValue.is_boolean()) {
const bool b = jsonValue.get<bool>();
const FrameInterpMode mode = b ? FrameInterpMode::Unlimited : FrameInterpMode::Off;
cVar.setValue(sanitizeEnumValue(cVar, mode), false);
return;
}
cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<FrameInterpMode>()), false);
}
template class ConfigImpl<dusk::FrameInterpMode>;
template class ConfigImpl<dusk::MenuScaling>;
template class ConfigImpl<dusk::Resampler>;
template class ConfigImpl<dusk::MagicArmorMode>;
}
void dusk::config::Register(ConfigVarBase& configVar) {
auto& registeredConfigVars = registered_config_vars();
const auto& name = configVar.getName();
if (RegistrationDone) {
DuskConfigLog.fatal("Tried to register CVar {} after registrations closed!", name);
}
if (registeredConfigVars.contains(name)) {
if (RegisteredConfigVars.contains(name)) {
DuskConfigLog.fatal("Tried to register CVar {} twice!", name);
}
registeredConfigVars[name] = &configVar;
RegisteredConfigVars[name] = &configVar;
configVar.markRegistered();
}
@@ -239,7 +245,6 @@ void dusk::config::LoadFromUserPreferences() {
}
static void LoadFromPath(const char* path) {
auto& registeredConfigVars = registered_config_vars();
auto data = dusk::io::FileStream::ReadAllBytes(path);
json j = json::parse(data);
@@ -250,8 +255,8 @@ static void LoadFromPath(const char* path) {
for (const auto& el : j.items()) {
const auto& key = el.key();
auto configVar = registeredConfigVars.find(key);
if (configVar == registeredConfigVars.end()) {
auto configVar = RegisteredConfigVars.find(key);
if (configVar == RegisteredConfigVars.end()) {
DuskConfigLog.error("Unknown key '{}' found in config!", key);
continue;
}
@@ -299,7 +304,7 @@ void dusk::config::Save() {
json j;
for (const auto& pair : registered_config_vars()) {
for (const auto& pair : RegisteredConfigVars) {
const auto layer = pair.second->getLayer();
if (layer == ConfigVarLayer::Value || layer == ConfigVarLayer::Speedrun) {
j[pair.first] = pair.second->getImpl()->dumpToJson(*pair.second);
@@ -323,9 +328,8 @@ void dusk::config::ClearAllActionBindings(int port) {
}
ConfigVarBase* dusk::config::GetConfigVar(std::string_view name) {
auto& registeredConfigVars = registered_config_vars();
const auto configVar = registeredConfigVars.find(name);
if (configVar != registeredConfigVars.end()) {
const auto configVar = RegisteredConfigVars.find(name);
if (configVar != RegisteredConfigVars.end()) {
return configVar->second;
}
@@ -333,7 +337,7 @@ ConfigVarBase* dusk::config::GetConfigVar(std::string_view name) {
}
void dusk::config::EnumerateRegistered(std::function<void(ConfigVarBase&)> callback) {
for (auto& pair : registered_config_vars()) {
for (auto& pair : RegisteredConfigVars) {
callback(*pair.second);
}
}
+2 -1
View File
@@ -34,10 +34,11 @@ constexpr std::array<std::string_view, 4> kUserDataDirectories = {
"EUR",
"JAP",
};
constexpr std::array<std::string_view, 6> kUserDataFiles = {
constexpr std::array<std::string_view, 7> kUserDataFiles = {
"achievements.json",
"config.json",
"controller_ports.dat",
"gamecontrollerdb.txt",
"imgui.ini",
"keyboard_bindings.dat",
"states.json",
+4
View File
@@ -20,7 +20,11 @@
namespace dusk {
namespace {
std::string GetAssetPath(const char* assetName) {
#ifdef DUSK_ASSET_DIR
const char* basePath = DUSK_ASSET_DIR;
#else
const char* basePath = SDL_GetBasePath();
#endif
if (basePath != nullptr && basePath[0] != '\0') {
return std::string(basePath) + "res/" + assetName;
}
@@ -69,6 +69,8 @@ std::optional<std::string> RandomizerContext::WriteToFile() {
const std::unordered_map<u16, u16> u16ShopOverrides(this->mShopOverrides.begin(), this->mShopOverrides.end());
out["mShopOverrides"] = u16ShopOverrides;
out["mTwilitInsectOverrides"] = mTwilitInsectOverrides;
for (const auto& [key, data] : this->mFlowItemMessageOverrides) {
auto node = out["mFlowItemMessageOverrides"][key];
node["itemId"] = data.itemId;
@@ -210,6 +212,12 @@ std::optional<std::string> RandomizerContext::LoadFromHash(const std::string& ha
this->mShopOverrides[key] = itemId;
}
for (const auto& twilitInsectNode : in["mTwilitInsectOverrides"]) {
u16 key = twilitInsectNode.first.as<u16>();
u16 itemId = twilitInsectNode.second.as<u16>();
this->mTwilitInsectOverrides[key] = itemId;
}
// Helper function for getting the item data out of a YAML node
auto retrieveItemData = [](auto& itemData, const YAML::Node& node) {
itemData.itemId = node["itemId"].as<int>();
@@ -1071,6 +1079,18 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
}
}
// Twilit Insect Overrides
// Keyed by u16 of 0xFF00 (stage index) and 0x00FF (flag, which is a tbox id)
if (location->HasCategories("Twilit Insect")) {
for (const auto& twilitInsectNode : metaData["Twilit Insect"]) {
u8 stage = twilitInsectNode["Stage"].as<u8>();
u8 tboxId = twilitInsectNode["Flag"].as<u8>();
u16 itemId = location->GetCurrentItem()->GetID();
u16 key = (stage << 8) | tboxId;
randoData.mTwilitInsectOverrides[key] = itemId;
}
}
// Helper function for getting flag values
auto getNodeFlags = [](auto& itemData, const YAML::Node& metaData) {
if (metaData["Event Flag"]) {
@@ -51,6 +51,7 @@ public:
std::unordered_map<u16, u8> mSkyCharacterOverrides{};
std::unordered_map<u16, u8> mGoldenWolfOverrides{};
std::unordered_map<u16, u8> mShopOverrides{};
std::unordered_map<u16, u16> mTwilitInsectOverrides{}; // Just used in tracker for now
std::unordered_map<u32, itemLocationData> mFlowItemMessageOverrides{};
std::unordered_map<std::string, itemLocationData> mItemLocations{};
@@ -190,6 +191,10 @@ public:
int stage{-1};
int flag{-1};
} mTrackerTempSwitchFlag;
struct {
int stage{-1};
int flag{-1};
} mTrackerTempItemFlag;
};
extern RandomizerState g_randomizerState;
+36 -10
View File
@@ -477,6 +477,17 @@ randomizer::logic::item_pool::ItemPool getSaveItemPool(randomizer::logic::world:
break;
}
// Twilight Tears
for (int i = 0; i < dComIfGs_getLightDropNum(0); ++i) {
pool.push_back(world->GetItem("Faron Twilight Tear", true));
}
for (int i = 0; i < dComIfGs_getLightDropNum(1); ++i) {
pool.push_back(world->GetItem("Eldin Twilight Tear", true));
}
for (int i = 0; i < dComIfGs_getLightDropNum(2); ++i) {
pool.push_back(world->GetItem("Lanayru Twilight Tear", true));
}
return pool;
}
@@ -520,6 +531,11 @@ bool isLocationObtained(randomizer::logic::location::Location* location) {
auto stageId = getStageSaveId(itemFlagNode["Stage"].as<u8>());
return tracker_isStageItem(stageId, flag);
}
if (auto& twilitInsectNode = locationMeta["Twilit Insect"]) {
auto flag = twilitInsectNode[0]["Flag"].as<u8>();
auto stageId = getStageSaveId(twilitInsectNode[0]["Stage"].as<u8>());
return dComIfGs_isStageTbox(stageId, flag);
}
return false;
}
@@ -545,6 +561,16 @@ int getLocationItem(randomizer::logic::location::Location* location) {
auto key = (stage << 8) | flag;
return context.mFreestandingItemOverrides[key];
}
if (auto& bugRewardNode = locationMeta["Bug Reward"]) {
u8 bugItemId = bugRewardNode[0]["Item Id"].as<u8>();
return context.mBugRewardOverrides[bugItemId];
}
if (auto& skyCharacterNode = locationMeta["Sky Character"]) {
u8 stageIdx = skyCharacterNode[0]["Stage"].as<u8>();
u8 roomNo = skyCharacterNode[0]["Room"].as<u8>();
u16 key = (stageIdx << 8) | roomNo;
return context.mSkyCharacterOverrides[key];
}
if (auto& wolfNode = locationMeta["Golden Wolf"]) {
auto flag = wolfNode[0]["Flag"].as<u16>();
return context.mGoldenWolfOverrides[flag];
@@ -555,17 +581,12 @@ int getLocationItem(randomizer::logic::location::Location* location) {
u16 key = (stage << 8) | originalItem;
return context.mShopOverrides[key];
}
if (auto& skyCharacterNode = locationMeta["Sky Character"]) {
u8 stageIdx = skyCharacterNode[0]["Stage"].as<u8>();
u8 roomNo = skyCharacterNode[0]["Room"].as<u8>();
u16 key = (stageIdx << 8) | roomNo;
return context.mSkyCharacterOverrides[key];
if (auto& twilitInsectNode = locationMeta["Twilit Insect"]) {
auto flag = twilitInsectNode[0]["Flag"].as<u8>();
auto stage = twilitInsectNode[0]["Stage"].as<u8>();
auto key = (stage << 8) | flag;
return context.mTwilitInsectOverrides[key];
}
if (auto& bugRewardNode = locationMeta["Bug Reward"]) {
u8 bugItemId = bugRewardNode[0]["Item Id"].as<u8>();
return context.mBugRewardOverrides[bugItemId];
}
if (auto& flwNode = locationMeta["FLW Message"]) {
auto group = flwNode[0]["Group"].as<u16>();
auto messageId = flwNode[0]["Message Id"].as<u16>();
@@ -703,6 +724,11 @@ bool tracker_isStageSwitch(int stage, int flag) {
}
bool tracker_isStageItem(int stage, int flag) {
if (g_randomizerState.mTrackerTempItemFlag.flag == flag &&
g_randomizerState.mTrackerTempItemFlag.stage == stage) {
return true;
}
if (dComIfGp_getStageStagInfo() && stage == dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo())) {
return dComIfGs_isItem(flag, -1);
} else {
+146 -95
View File
@@ -319,126 +319,140 @@
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0x1
- Name: South Faron Woods Twilit Insect in Tunnel 2
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0x6
- Name: Faron Woods Coros House Interior Twilit Insect 1
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 67
Flag: 0x9
- Name: Faron Woods Coros House Interior Twilit Insect 2
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 67
Flag: 0x4
- Name: South Faron Woods Coros House Exterior Twilit Insect
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0x0
- Name: South Faron Woods Twilit Insect Behind Gate 1
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0xB
- Name: South Faron Woods Twilit Insect Behind Gate 2
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0x5
- Name: Faron Mist Twilit Insect on Wall 1
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0x12
- Name: Faron Mist Twilit Insect on Wall 2
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0x11
- Name: Faron Mist Twilit Insect on Center Stump 1
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0xE
- Name: Faron Mist Twilit Insect on Center Stump 2
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0xD
- Name: Faron Mist Twilit Insect on Center Stump 3
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0xC
- Name: Faron Mist Burrowing Twilit Insect 1
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0x17
- Name: Faron Mist Burrowing Twilit Insect 2
Original Item: Faron Twilight Tear
Categories:
- Overworld
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0x8
- Name: North Faron Woods Twilit Insect 1
Original Item: Faron Twilight Tear
@@ -447,7 +461,9 @@
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0x15
- Name: North Faron Woods Twilit Insect 2
Original Item: Faron Twilight Tear
@@ -456,7 +472,9 @@
- Faron Woods
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 45
Flag: 0x14
- Name: South Faron Warp Portal
Original Item: South Faron Portal
@@ -713,7 +731,7 @@
Metadata:
Freestanding Item:
- Stage: 56
Flag: 0x9F
Flag: 0x9E
- Name: Faron Field Male Beetle
Original Item: Male Beetle
@@ -725,7 +743,7 @@
Metadata:
Freestanding Item:
- Stage: 56
Flag: 0x9E
Flag: 0x9F
- Name: Faron Field Poe
Original Item: Poe Soul
@@ -900,144 +918,160 @@
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 75
Flag: 0x2
- Name: Sanctuary Basement Twilit Insect 2
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 75
Flag: 0x3
- Name: Sanctuary Basement Twilit Insect 3
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 75
Flag: 0xC
- Name: Kakariko Graveyard Twilit Insect
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 48
Flag: 0x6
- Name: Kakariko Malo Mart Twilit Insect
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 68
Flag: 0x9
- Name: Kakariko Inn Pipe Twilit Insect
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 68
Flag: 0x8
- Name: Kakariko Inn Bedroom Twilit Insect
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 68
Flag: 0x0
- Name: Kakariko Bug House Twilit Insect
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 68
Flag: 0x1
- Name: Barnes Bomb Shop Twilit Insect
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 68
Flag: 0x7
- Name: Kakariko Destroyed Building Twilit Insect 1
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 46
Flag: 0x4
- Name: Kakariko Destroyed Building Twilit Insect 2
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 46
Flag: 0x5
- Name: Kakariko Destroyed Building Twilit Insect 3
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 46
Flag: 0xB
- Name: Kakariko Watchtower Twilit Insect
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 68
Flag: 0xA
- Name: Death Mountain Trail Twilit Insect Near Howling Stone
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 47
Flag: 0xF
- Name: Death Mountain Trail Twilit Insect on Wall
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 47
Flag: 0xE
- Name: Death Mountain Trail Twilit Insect in Hot Spring
Original Item: Eldin Twilight Tear
Categories:
- Overworld
- Eldin Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 47
Flag: 0x10
- Name: Kakariko Gorge Warp Portal
Original Item: Kakariko Gorge Portal
@@ -1895,135 +1929,150 @@
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 53
Flag: 0x2C
- Name: Lake Hylia Twilit Insect Between Bridges
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 52
Flag: 0x2F
- Name: Lake Hylia Burrowing Twilit Insect
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 52
Flag: 0x30
- Name: Lake Hylia Twilit Insect Behind Canon
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 52
Flag: 0x32
- Name: Lake Hylia Twilit Insect on Docks
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 52
Flag: 0x31
- Name: Lake Hylia Twilit Bloat
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 52
Flag: 0x35
- Name: Zoras River Twilit Insect 1
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 49
Flag: 0x3D
- Name: Zoras River Twilit Insect 2
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 49
Flag: 0x36
- Name: Zoras River Twilit Insect 3
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 49
Flag: 0x3A
- Name: Zoras River Twilit Insect 4
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 49
Flag: 0x39
- Name: Upper Zoras River Twilit Insect
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 61
Flag: 0x37
- Name: Zoras Domain Twilit Insect near Lilypads 1
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 50
Flag: 0x3B
- Name: Zoras Domain Twilit Insect near Lilypads 2
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 50
Flag: 0x2E
- Name: Zoras Domain Burrowing Twilit Insect
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 50
Flag: 0x2D
- Name: Zoras Domain Twilit Insect on West Ledge
Original Item: Lanayru Twilight Tear
Categories:
- Overworld
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 50
Flag: 0x3C
- Name: Zoras Domain Throne Room Twilit Insect
Original Item: Lanayru Twilight Tear
@@ -2032,7 +2081,9 @@
- Lanayru Province
- Twilit Insect
Metadata:
- None
Twilit Insect:
- Stage: 50
Flag: 0x3E
- Name: Lanayru Field Behind Gate Underwater Chest
Original Item: Orange Rupee
@@ -1107,7 +1107,7 @@ namespace randomizer::logic::world
return this->_itemTable.at(name).get();
}
item::Item* World::GetItem(uint8_t id, const bool& ignoreError /*= false*/) {
item::Item* World::GetItem(uint16_t id, const bool& ignoreError /*= false*/) {
if (!this->_itemIdTable.contains(id))
{
if (!ignoreError)
@@ -124,7 +124,7 @@ namespace randomizer::logic::world
dungeon::Dungeon* GetDungeon(const std::string& name);
const std::map<std::string, std::unique_ptr<dungeon::Dungeon>>& GetDungeonTable() const;
item::Item* GetItem(const std::string& name, const bool& ignoreError = false);
item::Item* GetItem(uint8_t id, const bool& ignoreError = false);
item::Item* GetItem(uint16_t id, const bool& ignoreError = false);
item::Item* GetShadowCrystal();
item::Item* GetGameWinningItem() const;
item_pool::ItemPool& GetItemPool();
@@ -6,7 +6,7 @@
namespace randomizer::seedgen::seed
{
static constexpr std::array nouns = {
static constexpr const char* nouns[] = {
"Aeralfos", "Agitha", "Ant", "Argorok", "Armos", "Ashei", "Auru", "BackSlice", "Bari",
"Barnes", "Beamos", "Beth", "BigBaba", "Blizzeta", "Bo", "Bokoblin", "Bombfish", "Borville",
"Bulblin", "Butterfly", "CastleTown", "Charlo", "Cheese", "Chilfos", "Chu", "Chudley", "Clawshot",
@@ -21,9 +21,10 @@ namespace randomizer::seedgen::seed
"Rutela", "Sage", "Sera", "Shad", "ShellBlade", "Sketch", "SkullKid", "Skulltula", "SkyBook",
"Snail", "Snowpeak", "Soal", "Soldier", "Spinner", "Stalfos", "Stallord", "Talo", "Tektite",
"Telma", "Temple", "TileWorm", "Toadpoli", "Trill", "Twilight", "Uli", "WolfLink", "Zant",
"Zelda", "Zora"};
"Zelda", "Zora"
};
static constexpr std::array adjectives = {
static constexpr const char* adjectives[] = {
"Abnormal", "Absent", "Absolute", "Abstract", "Absurd", "Accurate", "Active", "Actual",
"Adjacent", "Aesthetic", "Aggressive", "Alert", "Alien", "Alternate", "Amazing", "Ambitious",
"Amusing", "Ancient", "Angry", "Anxious", "Apparent", "Artistic", "Astute", "Atomic",
@@ -87,7 +88,8 @@ namespace randomizer::seedgen::seed
"Unlikely", "Unreal", "Upbeat", "Upset", "Urban", "Useful", "Usual", "Vague",
"Valid", "Verbal", "Vertical", "Vicious", "Vigorous", "Villainous", "Virtual", "Visible",
"Vital", "Vivid", "Warm", "Weekly", "Weird", "Wholesome", "Wicked", "Wise",
"Wistful", "Witty", "Wonderful", "Wooden", "Worried", "Wrong", "Young", "Zany"};
"Wistful", "Witty", "Wonderful", "Wooden", "Worried", "Wrong", "Young", "Zany"
};
int GetRandValue(int min, int max) {
std::uniform_int_distribution<int> distribution(min, max);
@@ -98,9 +100,9 @@ namespace randomizer::seedgen::seed
std::string GenerateSeed()
{
const std::string adjective1 = adjectives[GetRandValue(0, adjectives.size() - 1)];
const std::string adjective2 = adjectives[GetRandValue(0, adjectives.size() - 1)];
const std::string noun = nouns[GetRandValue(0, nouns.size() - 1)];
const std::string adjective1 = adjectives[GetRandValue(0, std::size(adjectives) - 1)];
const std::string adjective2 = adjectives[GetRandValue(0, std::size(adjectives) - 1)];
const std::string noun = nouns[GetRandValue(0, std::size(nouns) - 1)];
return adjective1 + adjective2 + noun;
}
@@ -2,7 +2,9 @@
#include "../utility/log.hpp"
#include "../utility/path.hpp"
#include "../utility/platform.hpp"
#ifdef DEVKITPRO
#include "../utility/thread_local.hpp"
#endif
#include <cstring>
#include <regex>
@@ -31,6 +33,7 @@ namespace randomizer::utility::file
return false;
};
#ifdef DEVKITPRO
static constexpr int FILE_BUF_SIZE = 25 * 1024 * 1024;
class AlignedBufferWrapper
{
@@ -41,6 +44,7 @@ namespace randomizer::utility::file
char* getBuffer() { return buffer; }
};
static ThreadLocal<AlignedBufferWrapper, DataIDs::FILE_OP_BUFFER> buf;
#endif
bool copy_file(const fspath& from, const fspath& to)
{
@@ -189,11 +193,15 @@ namespace randomizer::utility::file
return 1;
}
#ifdef DEVKITPRO
while (file)
{
file.read(buf.get().getBuffer(), FILE_BUF_SIZE);
fileContents.write(buf.get().getBuffer(), file.gcount());
}
#else
fileContents << file.rdbuf();
#endif
return 0;
}
+2 -2
View File
@@ -127,7 +127,7 @@ UserSettings g_userSettings = {
.canTransformAnywhere {"game.canTransformAnywhere", false},
.fastRoll {"game.fastRoll", false},
.fastSpinner {"game.fastSpinner", false},
.freeMagicArmor {"game.freeMagicArmor", false},
.armorRupeeDrain {"game.armorRupeeDrain", MagicArmorMode::NORMAL},
.invincibleEnemies {"game.invincibleEnemies", false},
// Technical
@@ -257,7 +257,7 @@ void registerSettings() {
Register(g_userSettings.game.enableFastIronBoots);
Register(g_userSettings.game.canTransformAnywhere);
Register(g_userSettings.game.fastRoll);
Register(g_userSettings.game.freeMagicArmor);
Register(g_userSettings.game.armorRupeeDrain);
Register(g_userSettings.game.restoreWiiGlitches);
Register(g_userSettings.game.enableLinkDollRotation);
Register(g_userSettings.game.enableAchievementToasts);
+1 -1
View File
@@ -33,7 +33,7 @@ void resetForSpeedrunMode() {
getSettings().game.canTransformAnywhere.setSpeedrunValue(false);
getSettings().game.fastRoll.setSpeedrunValue(false);
getSettings().game.fastSpinner.setSpeedrunValue(false);
getSettings().game.freeMagicArmor.setSpeedrunValue(false);
getSettings().game.armorRupeeDrain.setSpeedrunValue(MagicArmorMode::NORMAL);
getSettings().game.pauseOnFocusLost.setSpeedrunValue(false);
aurora_set_pause_on_focus_lost(false);
+2 -67
View File
@@ -13,6 +13,7 @@
#include "modal.hpp"
#include "number_button.hpp"
#include "pane.hpp"
#include "rando_seed_generation.hpp"
#include "string_button.hpp"
namespace dusk::ui {
@@ -24,18 +25,7 @@ struct ConfigBoolProps {
std::function<bool()> isDisabled;
};
static std::atomic seedGenStatus = SeedGenerateStatus::Ready;
static std::string generationStatusMsg{};
static void StartSeedGeneration() {
if (GenerateAndWriteSeed(generationStatusMsg)) {
seedGenStatus.store(SeedGenerateStatus::Success);
} else {
seedGenStatus.store(SeedGenerateStatus::Error);
}
DuskLog.debug("{}", generationStatusMsg);
}
randomizer::seedgen::settings::Setting* FindSetting(const std::string& key) {
if (key.empty()) {
@@ -410,27 +400,6 @@ void rando_starting_item_number_toggle(Pane& leftPane, Pane& rightPane, std::str
});
}
Modal* RandomizerWindow::show_seed_gen_modal(std::string_view message) {
auto* modal = dynamic_cast<Modal*>(&push_document(std::make_unique<Modal>(Modal::Props{
.title = "Randomizer",
.bodyRml = escape(message),
.onDismiss = [this](Modal& modal) {
mDoAud_seStartMenu(kSoundWindowClose);
modal.pop();
m_genSeedModal = nullptr;
},
.icon = "verifying",
})));
// Allow manual line breaks in this modal for error messages
modal->root()->SetProperty("white-space", "pre-line");
if (auto* doc = top_document()) {
doc->focus();
}
return modal;
}
struct ExcludedTabLocData {
std::string name {};
std::string lowercaseName{};
@@ -822,11 +791,7 @@ RandomizerWindow::RandomizerWindow() {
DuskLog.info("Created new Seed for generator.");
}
seedGenStatus.store(SeedGenerateStatus::Generating);
std::thread randoGenerationThread(StartSeedGeneration);
randoGenerationThread.detach();
m_genSeedModal = show_seed_gen_modal("Generating Seed...");
GenerateRandomizerSeed();
}),rightPane, [](Pane& pane) {
pane.clear();
@@ -1176,36 +1141,6 @@ RandomizerWindow::RandomizerWindow() {
}
}
void RandomizerWindow::update() {
Window::update();
auto curSeedGenStatus = seedGenStatus.load();
if (curSeedGenStatus == SeedGenerateStatus::Success ||
curSeedGenStatus == SeedGenerateStatus::Error)
{
if (curSeedGenStatus == SeedGenerateStatus::Success) {
mDoAud_seStartMenu(kSoundSeedGenerateSuccess);
m_genSeedModal->set_icon("celebration");
} else {
mDoAud_seStartMenu(kSoundSeedGenerateError);
m_genSeedModal->set_icon("error");
}
m_genSeedModal->set_body(escape(generationStatusMsg));
m_genSeedModal->add_action({
.label = "OK",
.onPressed = [this](Modal& modal) {
mDoAud_seStartMenu(kSoundWindowClose);
modal.pop();
m_genSeedModal = nullptr;
}
});
m_genSeedModal->focus();
seedGenStatus.store(SeedGenerateStatus::Ready);
}
}
std::filesystem::path GetRandomizerPath() {
return data::configured_data_path() / "randomizer";
}
-11
View File
@@ -7,7 +7,6 @@ namespace randomizer::seedgen::config {
}
namespace dusk::ui {
class Modal;
class Pane;
std::filesystem::path GetRandomizerPath();
@@ -16,24 +15,14 @@ class Pane;
std::filesystem::path GetRandomizerSeedsPath();
randomizer::seedgen::config::Config& GetRandomizerConfig();
enum class SeedGenerateStatus {
Ready,
Generating,
Success,
Error,
};
class RandomizerWindow : public Window {
public:
RandomizerWindow();
void update() override;
Modal* show_seed_gen_modal(std::string_view message);
void rando_excluded_locations_update_left_pane(Pane& innerLeftPane, Pane& rightPane, bool forceUpdate = false);
auto& get_locations_for_left_pane();
private:
Modal* m_genSeedModal = nullptr;
std::string m_excludedLocationsFilter{};
};
}
+93
View File
@@ -0,0 +1,93 @@
#include "rando_seed_generation.hpp"
#include "modal.hpp"
#include "dusk/logging.h"
#include "dusk/randomizer/game/randomizer_context.hpp"
#include "m_Do/m_Do_audio.h"
#include <thread>
namespace dusk::ui {
enum class SeedGenerateStatus {
Ready,
Generating,
Success,
Error,
};
static std::atomic seedGenStatus = SeedGenerateStatus::Ready;
static std::string generationStatusMsg{};
RandomizerGenerationModal::RandomizerGenerationModal() :
Modal({
.title = "Randomizer",
.bodyRml = "Generating Seed...",
.onDismiss = [this](Modal& modal) {
mDoAud_seStartMenu(kSoundWindowClose);
modal.pop();
},
.icon = "verifying",
}) {
mRoot->SetProperty("white-space", "pre-line");
}
void RandomizerGenerationModal::update() {
Document::update();
auto curSeedGenStatus = seedGenStatus.load();
// Change the modal text if we've finished attempting to generate
if (curSeedGenStatus == SeedGenerateStatus::Success ||
curSeedGenStatus == SeedGenerateStatus::Error)
{
if (curSeedGenStatus == SeedGenerateStatus::Success) {
mDoAud_seStartMenu(kSoundSeedGenerateSuccess);
set_icon("celebration");
} else {
mDoAud_seStartMenu(kSoundSeedGenerateError);
set_icon("error");
}
set_body(escape(generationStatusMsg));
add_action({
.label = "OK",
.onPressed = [this](Modal& modal) {
mDoAud_seStartMenu(kSoundWindowClose);
modal.pop();
}
});
// Refocus so that we focus the new button
focus();
seedGenStatus.store(SeedGenerateStatus::Ready);
}
}
static void StartSeedGeneration() {
if (GenerateAndWriteSeed(generationStatusMsg)) {
seedGenStatus.store(SeedGenerateStatus::Success);
} else {
seedGenStatus.store(SeedGenerateStatus::Error);
}
DuskLog.debug("{}", generationStatusMsg);
}
void GenerateRandomizerSeed() {
// Start Generation Thread
seedGenStatus.store(SeedGenerateStatus::Generating);
std::thread randoGenerationThread(StartSeedGeneration);
randoGenerationThread.detach();
// Create Seed Generation Modal
push_document(std::make_unique<RandomizerGenerationModal>());
// Focus Modal
if (auto* doc = top_document()) {
doc->focus();
}
}
}
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include "modal.hpp"
namespace dusk::ui {
class RandomizerGenerationModal : public Modal {
public:
explicit RandomizerGenerationModal();
void update() override;
};
void GenerateRandomizerSeed();
}
+41 -3
View File
@@ -75,6 +75,14 @@ constexpr std::array kMenuScalingModeLabels = {
"Dusklight",
};
constexpr std::array kMagicArmorModes = {
"Normal",
"On Damage",
"Double Defense",
"Invincible",
"Cosmetic",
};
bool try_parse_backend(std::string_view backend, AuroraBackend& outBackend) {
if (backend == "auto") {
outBackend = BACKEND_AUTO;
@@ -211,7 +219,7 @@ void reset_for_speedrun_mode() {
getSettings().game.canTransformAnywhere.setSpeedrunValue(false);
getSettings().game.fastRoll.setSpeedrunValue(false);
getSettings().game.fastSpinner.setSpeedrunValue(false);
getSettings().game.freeMagicArmor.setSpeedrunValue(false);
getSettings().game.armorRupeeDrain.setSpeedrunValue(MagicArmorMode::NORMAL);
getSettings().game.invincibleEnemies.setSpeedrunValue(false);
getSettings().game.pauseOnFocusLost.setSpeedrunValue(false);
@@ -1272,8 +1280,38 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
"Makes Link's roll animation and movement twice as fast.");
addCheat("Fast Spinner", getSettings().game.fastSpinner,
"Speeds up Spinner movement while holding R.");
addCheat("Free Magic Armor", getSettings().game.freeMagicArmor,
"Lets the magic armor work without consuming rupees.");
leftPane.register_control(
leftPane.add_select_button({
.key = "Magic Armor Behavior",
.getValue =
[] {
return kMagicArmorModes[static_cast<u8>(getSettings().game.armorRupeeDrain.getValue())];
},
.isDisabled = [] { return getSettings().game.speedrunMode; },
.isModified =
[] {
return getSettings().game.armorRupeeDrain.getValue() !=
getSettings().game.armorRupeeDrain.getDefaultValue();
},
}),
rightPane, [](Pane& pane) {
for (int i = 0; i < kMagicArmorModes.size(); i++) {
pane.add_button({
.text = kMagicArmorModes[i],
.isSelected =
[i] {
return getSettings().game.armorRupeeDrain.getValue() == static_cast<MagicArmorMode>(i);
},
})
.on_pressed([i] {
mDoAud_seStartMenu(kSoundItemChange);
getSettings().game.armorRupeeDrain.setValue(static_cast<MagicArmorMode>(i));
config::Save();
});
}
pane.add_rml(
"<br/>Control the behavior of the Magic Armor.");
});
addCheat("Invincible Enemies", getSettings().game.invincibleEnemies,
"Prevents enemies from taking damage.");
});
+14 -13
View File
@@ -76,7 +76,6 @@
#include <dolphin/dvd.h>
#include "SDL3/SDL_init.h"
#include "SDL3/SDL_filesystem.h"
#include "SDL3/SDL_iostream.h"
#include "SDL3/SDL_misc.h"
#include "cxxopts.hpp"
@@ -491,14 +490,6 @@ static void LanguageInit() {
selectedLanguage = static_cast<u8>(dusk::getSettings().game.language.getValue());
}
static std::string asset_path(const char* assetName) {
const char* basePath = SDL_GetBasePath();
if (basePath != nullptr && basePath[0] != '\0') {
return std::string(basePath) + "res/" + assetName;
}
return std::string("res/") + assetName;
}
static void log_build_info() {
DuskLog.info("Build: {} (rev {}, built {}, type {})", DUSK_WC_DESCRIBE, DUSK_WC_REVISION, DUSK_WC_DATE, DUSK_BUILD_TYPE);
DuskLog.info("Platform: {}", DUSK_PLATFORM_NAME);
@@ -579,10 +570,17 @@ int game_main(int argc, char* argv[]) {
// PADSetDefaultMapping(&defaultPadMapping, PAD_TYPE_STANDARD);
{
// Load mappings from https://github.com/mdqinc/SDL_GameControllerDB
const auto mappingsPath = asset_path("gamecontrollerdb.txt");
if (SDL_AddGamepadMappingsFromFile(mappingsPath.c_str()) < 0) {
DuskLog.warn("Failed to load gamecontrollerdb.txt: {}", SDL_GetError());
const auto mappingsPath = dusk::ConfigPath / "gamecontrollerdb.txt";
std::error_code ec;
if (std::filesystem::exists(mappingsPath, ec)) {
const auto mappingsPathString = dusk::io::fs_path_to_string(mappingsPath);
if (SDL_AddGamepadMappingsFromFile(mappingsPathString.c_str()) < 0) {
DuskLog.warn("Failed to load gamecontrollerdb.txt from '{}': {}",
mappingsPathString, SDL_GetError());
}
} else if (ec) {
DuskLog.warn("Failed to inspect gamecontrollerdb.txt in data folder '{}': {}",
dusk::io::fs_path_to_string(mappingsPath), ec.message());
}
}
@@ -596,6 +594,9 @@ int game_main(int argc, char* argv[]) {
config.appName = dusk::AppName;
config.userPath = reinterpret_cast<const char*>(userPathString.c_str());
config.cachePath = reinterpret_cast<const char*>(cachePathString.c_str());
#ifdef DUSK_ASSET_DIR
config.resourcesPath = DUSK_ASSET_DIR;
#endif
config.vsync = dusk::getSettings().video.enableVsync;
config.startFullscreen = dusk::getSettings().video.enableFullscreen;
config.windowPosX = -1;