mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-04 03:12:48 -04:00
Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4b3c559df3 | |||
| 30a99c22f1 | |||
| 360cb37028 | |||
| 4b6b41a6aa | |||
| faa8618124 | |||
| 89acf923e0 | |||
| c42a33154c | |||
| a074e30147 | |||
| 2ce272d586 | |||
| e1636e20bd | |||
| 9904720e5a | |||
| 9910320fb4 | |||
| b43a9e2ccc | |||
| 23d81492e6 | |||
| 65b0ec3f90 | |||
| 91248d10db | |||
| f76a4d7087 | |||
| c7b609945b | |||
| 6ca6ea8065 | |||
| 315f621176 | |||
| 10d9a818c2 | |||
| e3761784af | |||
| d85556a063 | |||
| c43f33a5bc | |||
| e63897d1f7 | |||
| 35a69e7ff1 | |||
| 8b9f09bda5 | |||
| 32cddc725b | |||
| 55eec3b0de | |||
| 1cf14f176c | |||
| 74550b031f | |||
| 2f84f0eaa4 | |||
| 3ed7ef1c88 | |||
| eace147652 | |||
| 53c005c4f1 | |||
| a4ff97564c | |||
| c6beeba14f | |||
| e470278717 | |||
| 783230b654 | |||
| 4e7711725a | |||
| e5bf7606ec | |||
| aa377cd5c1 | |||
| bb9a88d7dc | |||
| 341e97ba82 | |||
| 8d3cb51157 | |||
| 7fff3b5ae0 | |||
| 6beb73b7a6 | |||
| c239a5a226 | |||
| b3f8fecfe4 | |||
| 6dcf4942f5 | |||
| cd7e429a66 | |||
| fcfcb35929 | |||
| 82b20be436 | |||
| 33101d8050 | |||
| 05160a968c | |||
| 623f29eb24 | |||
| 0a3833818a | |||
| 4f276252a3 | |||
| d17c629ce0 | |||
| 5bcc969778 |
Vendored
+1
-1
@@ -6,7 +6,7 @@
|
||||
"type": "cppvsdbg",
|
||||
"request": "launch",
|
||||
"program": "${command:cmake.launchTargetPath}",
|
||||
"args": ["-l", "1", "--dvd", "${workspaceRoot}/orig/GZ2E01/GZ2E01.iso"],
|
||||
"args": ["-l", "1", "--dvd", "${workspaceRoot}/orig/GZ2E01/GZ2E01.iso", "--console"],
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "gdb",
|
||||
"symbolSearchPath": "${command:cmake.launchTargetPath}",
|
||||
|
||||
+43
-7
@@ -316,6 +316,48 @@ if (DUSK_MOVIE_SUPPORT)
|
||||
list(APPEND GAME_COMPILE_DEFS MOVIE_SUPPORT=1)
|
||||
endif ()
|
||||
|
||||
option(DUSK_ENABLE_DISCORD_RPC "Enable Discord Rich Presence support" ON)
|
||||
if (DUSK_ENABLE_DISCORD_RPC AND NOT ANDROID AND NOT IOS AND NOT TVOS)
|
||||
|
||||
FetchContent_Populate(discord_rpc
|
||||
URL https://github.com/discord/discord-rpc/archive/refs/tags/v3.4.0.tar.gz
|
||||
URL_HASH SHA256=e13427019027acd187352dacba6c65953af66fdf3c35fcf38fc40b454a9d7855
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
)
|
||||
# RapidJSON is a git submodule absent from the discord-rpc tarball; fetch separately.
|
||||
FetchContent_Populate(rapidjson
|
||||
URL https://github.com/Tencent/rapidjson/archive/refs/tags/v1.1.0.tar.gz
|
||||
URL_HASH SHA256=bf7ced29704a1e696fbccf2a2b4ea068e7774fa37f6d7dd4039d0787f8bed98e
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
)
|
||||
|
||||
if (NOT TARGET discord-rpc)
|
||||
set(_drpc ${discord_rpc_SOURCE_DIR}/src)
|
||||
set(_drpc_src
|
||||
${_drpc}/discord_rpc.cpp
|
||||
${_drpc}/rpc_connection.cpp
|
||||
${_drpc}/serialization.cpp
|
||||
)
|
||||
if (WIN32)
|
||||
list(APPEND _drpc_src ${_drpc}/connection_win.cpp ${_drpc}/discord_register_win.cpp)
|
||||
elseif (APPLE)
|
||||
list(APPEND _drpc_src ${_drpc}/connection_unix.cpp ${_drpc}/discord_register_osx.m)
|
||||
else ()
|
||||
list(APPEND _drpc_src ${_drpc}/connection_unix.cpp ${_drpc}/discord_register_linux.cpp)
|
||||
endif ()
|
||||
add_library(discord-rpc STATIC ${_drpc_src})
|
||||
target_include_directories(discord-rpc PUBLIC
|
||||
${discord_rpc_SOURCE_DIR}/include
|
||||
${rapidjson_SOURCE_DIR}/include
|
||||
)
|
||||
if (UNIX)
|
||||
target_link_libraries(discord-rpc PUBLIC pthread)
|
||||
endif ()
|
||||
endif ()
|
||||
list(APPEND GAME_LIBS discord-rpc)
|
||||
list(APPEND GAME_COMPILE_DEFS DUSK_DISCORD_RPC=1)
|
||||
endif ()
|
||||
|
||||
# Edit & Continue
|
||||
if (MSVC)
|
||||
if ("${CMAKE_MSVC_DEBUG_INFORMATION_FORMAT}" STREQUAL "" AND CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
@@ -357,12 +399,6 @@ target_include_directories(game_base PRIVATE ${GAME_INCLUDE_DIRS})
|
||||
target_link_libraries(game_debug PRIVATE ${GAME_LIBS})
|
||||
target_link_libraries(game_base PRIVATE ${GAME_LIBS})
|
||||
|
||||
# Combined game library
|
||||
add_library(game STATIC
|
||||
$<TARGET_OBJECTS:game_base>
|
||||
$<TARGET_OBJECTS:game_debug>)
|
||||
target_link_libraries(game PUBLIC ${GAME_LIBS})
|
||||
|
||||
if(ANDROID)
|
||||
add_library(dusk SHARED src/dusk/main.cpp)
|
||||
set_target_properties(dusk PROPERTIES OUTPUT_NAME main)
|
||||
@@ -372,7 +408,7 @@ endif ()
|
||||
|
||||
target_compile_definitions(dusk PRIVATE TARGET_PC AVOID_UB=1 VERSION=0)
|
||||
target_include_directories(dusk PRIVATE include)
|
||||
target_link_libraries(dusk PRIVATE game aurora::main)
|
||||
target_link_libraries(dusk PRIVATE game_base game_debug aurora::main)
|
||||
if (TARGET crashpad_handler)
|
||||
add_dependencies(dusk crashpad_handler)
|
||||
endif ()
|
||||
|
||||
+4
-1
@@ -358,7 +358,10 @@
|
||||
"inherits": [
|
||||
"relwithdebinfo",
|
||||
"ci"
|
||||
]
|
||||
],
|
||||
"cacheVariables": {
|
||||
"AURORA_SDL3_PROVIDER": "vendor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x-linux-ci-gcc",
|
||||
|
||||
Vendored
+1
-1
Submodule extern/aurora updated: 672f1e8e5e...5d420c9f73
+1
-3
@@ -15,7 +15,6 @@ set(DOLZEL_FILES
|
||||
src/m_Do/m_Do_DVDError.cpp
|
||||
src/m_Do/m_Do_MemCard.cpp
|
||||
src/m_Do/m_Do_MemCardRWmng.cpp
|
||||
src/m_Do/m_Do_machine_exception.cpp
|
||||
src/m_Do/m_Do_hostIO.cpp
|
||||
src/c/c_damagereaction.cpp
|
||||
src/c/c_dylink.cpp
|
||||
@@ -1366,8 +1365,6 @@ set(DUSK_FILES
|
||||
src/dusk/imgui/ImGuiBloomWindow.hpp
|
||||
src/dusk/imgui/ImGuiMenuTools.cpp
|
||||
src/dusk/imgui/ImGuiMenuTools.hpp
|
||||
src/dusk/imgui/ImGuiMenuEnhancements.cpp
|
||||
src/dusk/imgui/ImGuiMenuEnhancements.hpp
|
||||
src/dusk/imgui/ImGuiPreLaunchWindow.cpp
|
||||
src/dusk/imgui/ImGuiPreLaunchWindow.hpp
|
||||
src/dusk/imgui/ImGuiFirstRunPreset.hpp
|
||||
@@ -1387,4 +1384,5 @@ set(DUSK_FILES
|
||||
src/dusk/OSContext.cpp
|
||||
src/dusk/OSThread.cpp
|
||||
src/dusk/OSMutex.cpp
|
||||
src/dusk/discord_presence.cpp
|
||||
)
|
||||
|
||||
@@ -220,6 +220,15 @@ public:
|
||||
/* 0x17E2 */ s16 wait_roll_angle; ///< @brief Roll angle during wait state.
|
||||
/* 0x17E4 */ u8 field_0x17e4[0x17e8 - 0x17e4];
|
||||
/* 0x17E8 */ f32 ride_speed_max; ///< @brief Speed rate for riding calculations.
|
||||
#if TARGET_PC
|
||||
cXyz himo_mat_interp_prev[2][16];
|
||||
cXyz himo_mat_interp_curr[2][16];
|
||||
cXyz himo_tex_interp_prev[2];
|
||||
cXyz himo_tex_interp_curr[2];
|
||||
bool himo_interp_prev_valid;
|
||||
bool himo_interp_curr_valid;
|
||||
s8 demo_cam_sync_ticks;
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC_ASSERT(sizeof(e_wb_class) == 0x17EC);
|
||||
|
||||
@@ -25,6 +25,9 @@ public:
|
||||
/* 0x164 */ cXyz mMinVal;
|
||||
/* 0x170 */ cXyz mMaxVal;
|
||||
/* 0x17C */ cXyz mViewScale;
|
||||
#if TARGET_PC
|
||||
bool mbReset = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -94,6 +94,12 @@ static void __THPAudioInitialize(THPAudioDecodeInfo* info, u8* ptr);
|
||||
#define THP_TEXTURE_SET_COUNT 3
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
namespace dusk {
|
||||
void MoviePlayerShutdown();
|
||||
}
|
||||
#endif
|
||||
|
||||
struct daMP_THPPlayer {
|
||||
/* 0x000 */ DVDFileInfo fileInfo;
|
||||
/* 0x03C */ THPHeader header;
|
||||
|
||||
@@ -68,10 +68,8 @@ public:
|
||||
/* 0x904 */ cXyz field_0x904[2];
|
||||
/* 0x91C */ int field_0x91c;
|
||||
/* 0x920 */ cXyz field_0x920[63];
|
||||
/* 0xC14 */ f32 field_0xc14[4];
|
||||
/* 0xC24 */ u8 field_0xc24[0xd10 - 0xc24];
|
||||
/* 0xD10 */ s8 field_0xd10[4];
|
||||
/* 0xD14 */ u8 field_0xd14[0xd50 - 0xd14];
|
||||
/* 0xC14 */ f32 field_0xc14[63];
|
||||
/* 0xD10 */ s8 field_0xd10[64];
|
||||
/* 0xD50 */ mDoExt_3DlineMat1_c field_0xd50;
|
||||
/* 0xD8C */ int field_0xd8c;
|
||||
};
|
||||
|
||||
@@ -4834,8 +4834,7 @@ inline void dComIfGd_drawXluListDark() {
|
||||
inline void dComIfGd_drawXluListInvisible() {
|
||||
ZoneScoped;
|
||||
#ifdef TARGET_PC
|
||||
if (dusk::getSettings().game.enableWaterRefraction &&
|
||||
!dusk::getSettings().game.enableFrameInterpolation) {
|
||||
if (!dusk::getSettings().game.disableWaterRefraction) {
|
||||
#endif
|
||||
g_dComIfG_gameInfo.drawlist.drawXluListInvisible();
|
||||
#ifdef TARGET_PC
|
||||
@@ -4846,8 +4845,7 @@ inline void dComIfGd_drawXluListInvisible() {
|
||||
inline void dComIfGd_drawOpaListInvisible() {
|
||||
ZoneScoped;
|
||||
#ifdef TARGET_PC
|
||||
if (dusk::getSettings().game.enableWaterRefraction &&
|
||||
!dusk::getSettings().game.enableFrameInterpolation) {
|
||||
if (!dusk::getSettings().game.disableWaterRefraction) {
|
||||
#endif
|
||||
g_dComIfG_gameInfo.drawlist.drawOpaListInvisible();
|
||||
#ifdef TARGET_PC
|
||||
|
||||
@@ -209,6 +209,10 @@ public:
|
||||
/* 0x04 */ TGXTexObj* mpTexObj;
|
||||
/* 0x08 */ Mtx mVolumeMtx;
|
||||
/* 0x38 */ Mtx mMtx;
|
||||
#if TARGET_PC
|
||||
const void* mVolumeMtxKey;
|
||||
const void* mMtxKey;
|
||||
#endif
|
||||
}; // Size: 0x68
|
||||
|
||||
struct cBgD_Vtx_t;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "JSystem/J3DGraphLoader/J3DAnmLoader.h"
|
||||
|
||||
class dFile_info_c;
|
||||
class J2DPicture;
|
||||
|
||||
class dDlst_FileSel_c : public dDlst_base_c {
|
||||
public:
|
||||
@@ -113,6 +114,14 @@ public:
|
||||
/* 0x04 */ J2DScreen* Scr3m;
|
||||
};
|
||||
|
||||
class dDlst_FileSelFade_c : public dDlst_base_c {
|
||||
public:
|
||||
void draw();
|
||||
virtual ~dDlst_FileSelFade_c() {}
|
||||
|
||||
/* 0x04 */ J2DPicture* mpPict;
|
||||
};
|
||||
|
||||
class dFs_HIO_c : public JORReflexible {
|
||||
public:
|
||||
dFs_HIO_c();
|
||||
@@ -676,6 +685,9 @@ public:
|
||||
#if PLATFORM_GCN
|
||||
/* 0x2378 */ J2DPicture* mpFadePict;
|
||||
#endif
|
||||
#ifdef TARGET_PC
|
||||
dDlst_FileSelFade_c mFadeDlst;
|
||||
#endif
|
||||
|
||||
#if PLATFORM_WII || PLATFORM_SHIELD
|
||||
/* 0x2376 */ u8 field_0x2376[SAVEFILE_SIZE];
|
||||
@@ -684,6 +696,10 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef TARGET_PC
|
||||
STATIC_ASSERT(sizeof(dFile_select_c) == 0x237C + sizeof(dDlst_FileSelFade_c));
|
||||
#else
|
||||
STATIC_ASSERT(sizeof(dFile_select_c) == 0x237C);
|
||||
#endif
|
||||
|
||||
#endif /* D_FILE_D_FILE_SELECT_H */
|
||||
|
||||
@@ -47,6 +47,10 @@ public:
|
||||
mPositionY = y;
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
void refreshAspectScale();
|
||||
#endif
|
||||
|
||||
void onUpdateFlag() { mUpdateFlag = true; }
|
||||
|
||||
void resetUpdateFlag() { mUpdateFlag = false; }
|
||||
@@ -79,6 +83,9 @@ private:
|
||||
/* 0x58 */ f32 mPositionX;
|
||||
/* 0x5C */ f32 mPositionY;
|
||||
/* 0x60 */ f32 mParam1;
|
||||
#ifdef TARGET_PC
|
||||
f32 mBaseParam1;
|
||||
#endif
|
||||
/* 0x64 */ f32 mParam2;
|
||||
/* 0x68 */ f32 mParam3;
|
||||
/* 0x6C */ f32 mParam4;
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace dusk::audio {
|
||||
|
||||
void SetMasterVolume(f32 value);
|
||||
|
||||
void SetPaused(bool paused);
|
||||
|
||||
u32 GetResetCount(int channelIdx);
|
||||
|
||||
f32 VolumeFromU16(u16 value);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef DUSK_DISCORD_RPC
|
||||
|
||||
namespace dusk {
|
||||
namespace discord {
|
||||
|
||||
void Initialize();
|
||||
|
||||
void RunCallbacks();
|
||||
|
||||
void UpdatePresence();
|
||||
|
||||
void Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DUSK_DISCORD_RPC
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "aurora/gfx.h"
|
||||
|
||||
extern AuroraInfo auroraInfo;
|
||||
extern const char* configPath;
|
||||
|
||||
namespace dusk {
|
||||
extern AuroraStats lastFrameAuroraStats;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#ifndef DUSK_FRAME_INTERP_H
|
||||
#define DUSK_FRAME_INTERP_H
|
||||
#pragma once
|
||||
|
||||
#include <dolphin/mtx.h>
|
||||
#include <stdbool.h>
|
||||
@@ -7,6 +6,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
class camera_process_class;
|
||||
class view_class;
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace dusk {
|
||||
@@ -16,40 +16,36 @@ void ensure_initialized();
|
||||
|
||||
void begin_record();
|
||||
void end_record();
|
||||
void interpolate(float step);
|
||||
void begin_frame(bool enabled, bool is_sim_frame, float step);
|
||||
void interpolate();
|
||||
float get_interpolation_step();
|
||||
|
||||
void request_presentation_sync();
|
||||
bool presentation_sync_active();
|
||||
|
||||
bool is_enabled();
|
||||
|
||||
// TODO: These should be phased out as UI is progressively updated to use game_clock
|
||||
void set_ui_tick_pending(bool value);
|
||||
bool get_ui_tick_pending();
|
||||
|
||||
void open_child(const void* key, int32_t id);
|
||||
void close_child();
|
||||
void record_camera(::camera_process_class* cam, int camera_id);
|
||||
void record_final_mtx_raw(const Mtx* dest, const Mtx src);
|
||||
void record_final_mtx_raw_tagged(const Mtx* dest, const Mtx src, uint64_t stable_tag);
|
||||
bool is_sim_frame();
|
||||
|
||||
bool lookup_replacement(const void* source, Mtx out);
|
||||
void record_camera(::camera_process_class* cam, int camera_id);
|
||||
void interp_view(::view_class* view);
|
||||
void record_final_mtx(Mtx m, const void *key);
|
||||
void record_final_mtx(Mtx m);
|
||||
|
||||
bool lookup_replacement(const void* key, Mtx out);
|
||||
bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out);
|
||||
|
||||
typedef void (*InterpolationCallBack)(bool isSimFrame, void* pUserWork);
|
||||
// call on a sim tick, will get called during presentation
|
||||
void add_interpolation_callback(InterpolationCallBack pCallBack, void* pUserWork);
|
||||
|
||||
void begin_presentation_camera();
|
||||
void end_presentation_camera();
|
||||
|
||||
struct PresentationCameraScope {
|
||||
PresentationCameraScope() { begin_presentation_camera(); }
|
||||
~PresentationCameraScope() { end_presentation_camera(); }
|
||||
PresentationCameraScope(const PresentationCameraScope&) = delete;
|
||||
PresentationCameraScope& operator=(const PresentationCameraScope&) = delete;
|
||||
PresentationCameraScope(PresentationCameraScope&&) = delete;
|
||||
PresentationCameraScope& operator=(PresentationCameraScope&&) = delete;
|
||||
};
|
||||
|
||||
uint64_t alloc_simple_shadow_pair_base();
|
||||
} // namespace frame_interp
|
||||
} // namespace dusk
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace game_clock {
|
||||
|
||||
void ensure_initialized();
|
||||
void reset_accumulator();
|
||||
void reset_frame_timer();
|
||||
|
||||
constexpr float sim_pace() { return 1.0f / 30.0f; }
|
||||
constexpr float period_for_original_frames(float frame_count) { return frame_count * sim_pace(); }
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
#include <aurora/aurora.h>
|
||||
#include <aurora/lib/logging.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
void aurora_log_callback(AuroraLogLevel level, const char* module, const char* message, unsigned int len);
|
||||
|
||||
namespace dusk {
|
||||
void InitializeFileLogging(const char* configDir, AuroraLogLevel logLevel);
|
||||
void InitializeFileLogging(const std::filesystem::path& configDir, AuroraLogLevel logLevel);
|
||||
void ShutdownFileLogging();
|
||||
const char* GetLogFilePath();
|
||||
void SendToStubLog(AuroraLogLevel level, const char* module, const char* message);
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
#ifndef DUSK_MAIN_H
|
||||
#define DUSK_MAIN_H
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace dusk {
|
||||
extern bool IsRunning;
|
||||
extern bool IsShuttingDown;
|
||||
extern bool IsGameLaunched;
|
||||
extern bool IsFocusPaused;
|
||||
extern std::filesystem::path ConfigPath;
|
||||
}
|
||||
|
||||
#endif // DUSK_MAIN_H
|
||||
|
||||
@@ -68,11 +68,12 @@ struct UserSettings {
|
||||
ConfigVar<bool> enableMirrorMode;
|
||||
ConfigVar<bool> invertCameraXAxis;
|
||||
ConfigVar<bool> disableMainHUD;
|
||||
ConfigVar<bool> pauseOnFocusLost;
|
||||
|
||||
// Graphics
|
||||
ConfigVar<BloomMode> bloomMode;
|
||||
ConfigVar<float> bloomMultiplier;
|
||||
ConfigVar<bool> enableWaterRefraction;
|
||||
ConfigVar<bool> disableWaterRefraction;
|
||||
ConfigVar<bool> enableFrameInterpolation;
|
||||
ConfigVar<int> internalResolutionScale;
|
||||
ConfigVar<int> shadowResolutionMultiplier;
|
||||
|
||||
@@ -25,7 +25,7 @@ typedef struct leafdraw_class : base_process_class {
|
||||
#endif
|
||||
/* 0xB8 */ leafdraw_method_class* leaf_methods;
|
||||
/* 0xBC */ s8 unk_0xBC;
|
||||
/* 0xBD */ u8 unk_0xBD;
|
||||
/* 0xBD */ u8 draw_interp_frame;
|
||||
/* 0xBE */ draw_priority_class draw_priority;
|
||||
} leafdraw_class;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ typedef struct process_node_class {
|
||||
/* 0x0BC */ layer_class layer;
|
||||
/* 0x0E8 */ node_list_class layer_nodelist[16];
|
||||
/* 0x1A8 */ s8 unk_0x1A8;
|
||||
/* 0x1A9 */ s8 draw_interp_frame;
|
||||
} process_node_class;
|
||||
|
||||
typedef struct node_process_profile_definition {
|
||||
|
||||
@@ -79,6 +79,10 @@ public:
|
||||
virtual void viewCalc();
|
||||
virtual ~J3DModel() {}
|
||||
|
||||
#if TARGET_PC
|
||||
static void interp_callback(bool isSimFrame, void* pUserWork);
|
||||
#endif
|
||||
|
||||
J3DModelData* getModelData() { return mModelData; }
|
||||
|
||||
void onFlag(u32 flag) { mFlags |= flag; }
|
||||
@@ -105,9 +109,7 @@ public:
|
||||
void setAnmMtx(int jointNo, Mtx m) {
|
||||
mMtxBuffer->setAnmMtx(jointNo, m);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(
|
||||
reinterpret_cast<const Mtx*>(mMtxBuffer->getAnmMtx(jointNo)),
|
||||
mMtxBuffer->getAnmMtx(jointNo));
|
||||
dusk::frame_interp::record_final_mtx(mMtxBuffer->getAnmMtx(jointNo));
|
||||
#endif
|
||||
}
|
||||
MtxP getAnmMtx(int jointNo) { return mMtxBuffer->getAnmMtx(jointNo); }
|
||||
|
||||
@@ -23,6 +23,10 @@ public:
|
||||
void syncJ3DSysPointers() const;
|
||||
void syncJ3DSysFlags() const;
|
||||
|
||||
#if TARGET_PC
|
||||
bool needsInterpCallBack() const;
|
||||
#endif
|
||||
|
||||
virtual ~J3DModelData() {}
|
||||
|
||||
void simpleCalcMaterial(Mtx mtx) { simpleCalcMaterial(0, mtx); }
|
||||
|
||||
@@ -33,6 +33,9 @@ public:
|
||||
void copy(J3DMaterial*);
|
||||
s32 newSharedDisplayList(u32);
|
||||
s32 newSingleSharedDisplayList(u32);
|
||||
#if TARGET_PC
|
||||
bool needsInterpCallBack() const;
|
||||
#endif
|
||||
|
||||
virtual void calc(f32 const (*)[4]);
|
||||
virtual void calcDiffTexMtx(f32 const (*)[4]);
|
||||
@@ -46,7 +49,6 @@ public:
|
||||
virtual void change();
|
||||
|
||||
J3DMaterial() { initialize(); }
|
||||
~J3DMaterial() {}
|
||||
J3DMaterial* getNext() { return mNext; }
|
||||
J3DShape* getShape() { return mShape; }
|
||||
J3DTevBlock* getTevBlock() { return mTevBlock; }
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
class JUTFader {
|
||||
public:
|
||||
enum EStatus {
|
||||
UNKSTATUS_M1 = -1,
|
||||
UNKSTATUS_0 = 0,
|
||||
None,
|
||||
Wait,
|
||||
FadeIn,
|
||||
FadeOut,
|
||||
};
|
||||
|
||||
JUTFader(int, int, int, int, JUtility::TColor);
|
||||
@@ -29,12 +31,12 @@ public:
|
||||
void setColor(JUtility::TColor color) { mColor.set(color); }
|
||||
|
||||
/* 0x04 */ s32 mStatus;
|
||||
/* 0x08 */ u16 field_0x8;
|
||||
/* 0x0A */ u16 field_0xa;
|
||||
/* 0x08 */ u16 mDuration;
|
||||
/* 0x0A */ u16 mTimer;
|
||||
/* 0x0C */ JUtility::TColor mColor;
|
||||
/* 0x10 */ JGeometry::TBox2<f32> mBox;
|
||||
/* 0x20 */ int mEStatus;
|
||||
/* 0x24 */ u32 field_0x24;
|
||||
/* 0x20 */ int mStatusTimer;
|
||||
/* 0x24 */ u32 mNextStatus;
|
||||
};
|
||||
|
||||
#endif /* JUTFADER_H */
|
||||
|
||||
@@ -97,6 +97,16 @@ s32 J3DModel::entryModelData(J3DModelData* pModelData, u32 mdlFlags, u32 mtxNum)
|
||||
return kJ3DError_Success;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
void J3DModel::interp_callback(bool isSimFrame, void* pUserWork) {
|
||||
J3DModel* i_this = static_cast<J3DModel*>(pUserWork);
|
||||
if (!isSimFrame) {
|
||||
i_this->calcMaterial();
|
||||
i_this->diff();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
s32 J3DModel::createShapePacket(J3DModelData* pModelData) {
|
||||
J3D_ASSERTMSG(173, pModelData != NULL, "Error : null pointer.");
|
||||
|
||||
@@ -452,11 +462,11 @@ void J3DModel::calc() {
|
||||
|
||||
#ifdef TARGET_PC
|
||||
for (u16 i = 0; i < mModelData->getJointNum(); ++i) {
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(getAnmMtx(i)), getAnmMtx(i));
|
||||
dusk::frame_interp::record_final_mtx(getAnmMtx(i));
|
||||
}
|
||||
|
||||
for (u16 i = 0; i < mModelData->getWEvlpMtxNum(); ++i) {
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(getWeightAnmMtx(i)), getWeightAnmMtx(i));
|
||||
dusk::frame_interp::record_final_mtx(getWeightAnmMtx(i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -485,6 +495,11 @@ void J3DModel::entry() {
|
||||
joint->entryIn();
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
if (mModelData->needsInterpCallBack())
|
||||
dusk::frame_interp::add_interpolation_callback(&J3DModel::interp_callback, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void J3DModel::viewCalc() {
|
||||
@@ -496,7 +511,7 @@ void J3DModel::viewCalc() {
|
||||
J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx,
|
||||
(MtxP)&mInternalView);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(&mInternalView, mInternalView);
|
||||
dusk::frame_interp::record_final_mtx(mInternalView);
|
||||
#endif
|
||||
}
|
||||
} else if (isCpuSkinningOn()) {
|
||||
@@ -504,7 +519,7 @@ void J3DModel::viewCalc() {
|
||||
J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx,
|
||||
(MtxP)&mInternalView);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(&mInternalView, mInternalView);
|
||||
dusk::frame_interp::record_final_mtx(mInternalView);
|
||||
#endif
|
||||
}
|
||||
} else if (checkFlag(J3DMdlFlag_SkinPosCpu)) {
|
||||
@@ -528,7 +543,7 @@ void J3DModel::viewCalc() {
|
||||
|
||||
#ifdef TARGET_PC
|
||||
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
|
||||
dusk::frame_interp::record_final_mtx_raw(&getDrawMtxPtr()[i], getDrawMtxPtr()[i]);
|
||||
dusk::frame_interp::record_final_mtx(getDrawMtxPtr()[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -84,6 +84,15 @@ void J3DModelData::simpleCalcMaterial(u16 idx, Mtx param_1) {
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
bool J3DModelData::needsInterpCallBack() const {
|
||||
for (u16 i = 0, n = getMaterialNum(); i < n; i++)
|
||||
if (getMaterialNodePointer(i)->needsInterpCallBack())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void J3DModelData::syncJ3DSysPointers() const {
|
||||
j3dSys.setTexture(getTexture());
|
||||
j3dSys.setVtxPos(getVtxPosArray(), getVtxNum());
|
||||
|
||||
@@ -265,7 +265,7 @@ void J3DMaterial::diff(u32 diffFlags) {
|
||||
}
|
||||
|
||||
void J3DMaterial::calc(f32 const (*param_0)[4]) {
|
||||
if (j3dSys.checkFlag(0x40000000)) {
|
||||
if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
|
||||
mTexGenBlock->calcPostTexMtx(param_0);
|
||||
} else {
|
||||
mTexGenBlock->calc(param_0);
|
||||
@@ -276,7 +276,7 @@ void J3DMaterial::calc(f32 const (*param_0)[4]) {
|
||||
}
|
||||
|
||||
void J3DMaterial::calcDiffTexMtx(f32 const (*param_0)[4]) {
|
||||
if (j3dSys.checkFlag(0x40000000)) {
|
||||
if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
|
||||
mTexGenBlock->calcPostTexMtxWithoutViewMtx(param_0);
|
||||
} else {
|
||||
mTexGenBlock->calcWithoutViewMtx(param_0);
|
||||
@@ -288,7 +288,7 @@ void J3DMaterial::setCurrentMtx() {
|
||||
}
|
||||
|
||||
void J3DMaterial::calcCurrentMtx() {
|
||||
if (!j3dSys.checkFlag(0x40000000)) {
|
||||
if (!j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
|
||||
mCurrentMtx.setCurrentTexMtx(
|
||||
getTexCoord(0)->getTexGenMtx(),
|
||||
getTexCoord(1)->getTexGenMtx(),
|
||||
@@ -371,6 +371,30 @@ s32 J3DMaterial::newSingleSharedDisplayList(u32 dlSize) {
|
||||
return kJ3DError_Success;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
bool J3DMaterial::needsInterpCallBack() const {
|
||||
for (int i = 0, n = getTexGenNum(); i < n; i++) {
|
||||
J3DTexMtx* pTexMtx = mTexGenBlock->getTexMtx(i);
|
||||
if (pTexMtx != NULL) {
|
||||
u32 texMtxMode = pTexMtx->getTexMtxInfo().mInfo & 0x3f;
|
||||
|
||||
// uses j3dSys.getViewMtx()
|
||||
switch (texMtxMode) {
|
||||
case J3DTexMtxMode_EnvmapBasic:
|
||||
case J3DTexMtxMode_EnvmapOld:
|
||||
case J3DTexMtxMode_Envmap:
|
||||
case J3DTexMtxMode_ProjmapBasic:
|
||||
case J3DTexMtxMode_Projmap:
|
||||
case J3DTexMtxMode_ViewProjmap:
|
||||
case J3DTexMtxMode_ViewProjmapBasic:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void J3DPatchedMaterial::initialize() {
|
||||
J3DMaterial::initialize();
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ void loadTexCoordGens(u32 texGenNum, J3DTexCoord* texCoords) {
|
||||
var_r28 = 61;
|
||||
J3DGDWriteXFCmdHdr(GX_XF_REG_DUALTEX0, texGenNum);
|
||||
|
||||
if (j3dSys.checkFlag(0x40000000)) {
|
||||
if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
|
||||
for (int i = 0; i < texGenNum; i++) {
|
||||
if (texCoords[i].getTexGenMtx() != 60) {
|
||||
if (texCoords[i].getTexGenMtx() != GX_IDENTITY) {
|
||||
var_r28 = i * 3;
|
||||
} else {
|
||||
var_r28 = 61;
|
||||
|
||||
@@ -120,11 +120,19 @@ void JAISeqMgr::mixOut() {
|
||||
}
|
||||
|
||||
JAISeq* JAISeqMgr::beginStartSeq_() {
|
||||
JAISeq* seq = JKR_NEW JAISeq(this, field_0x10);
|
||||
#ifdef TARGET_PC
|
||||
if (JAISeq::getFreeMemCount() == 0) {
|
||||
JUT_WARN(273, "%s", "JASPoolAllocObject::<JAISeq>::operator new failed .\n");
|
||||
return NULL;
|
||||
}
|
||||
return JKR_NEW JAISeq(this, field_0x10);
|
||||
#else
|
||||
JAISeq* seq = new JAISeq(this, field_0x10);
|
||||
if (seq == NULL) {
|
||||
JUT_WARN(273, "%s", "JASPoolAllocObject::<JAISeq>::operator new failed .\n");
|
||||
}
|
||||
return seq;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool JAISeqMgr::endStartSeq_(JAISeq* seq, JAISoundHandle* handle) {
|
||||
|
||||
@@ -219,7 +219,7 @@ void JFWDisplay::endGX() {
|
||||
if (dusk::frame_interp::get_ui_tick_pending()) {
|
||||
mFader->advance();
|
||||
}
|
||||
if (mFader->getStatus() != 1) {
|
||||
if (mFader->getStatus() != JUTFader::Wait) {
|
||||
mFader->draw();
|
||||
}
|
||||
#else
|
||||
@@ -379,6 +379,7 @@ static void waitPrecise(Limiter& limiter, Uint64 targetNs) {
|
||||
static void waitForTick(u32 p1, u16 p2) {
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.enableFrameInterpolation && !dusk::getTransientSettings().skipFrameRateLimit) {
|
||||
dusk::frameUsagePct = 0.f;
|
||||
return;
|
||||
}
|
||||
if (dusk::getTransientSettings().skipFrameRateLimit) {
|
||||
|
||||
@@ -10,51 +10,51 @@
|
||||
|
||||
JUTFader::JUTFader(int x, int y, int width, int height, JUtility::TColor pColor)
|
||||
: mColor(pColor), mBox(x, y, x + width, y + height) {
|
||||
mStatus = 0;
|
||||
field_0x8 = 0;
|
||||
field_0xa = 0;
|
||||
field_0x24 = 0;
|
||||
mEStatus = UNKSTATUS_M1;
|
||||
mStatus = None;
|
||||
mDuration = 0;
|
||||
mTimer = 0;
|
||||
mNextStatus = 0;
|
||||
mStatusTimer = -1;
|
||||
}
|
||||
|
||||
void JUTFader::advance() {
|
||||
if (0 <= mEStatus && mEStatus-- == 0) {
|
||||
mStatus = field_0x24;
|
||||
if (0 <= mStatusTimer && mStatusTimer-- == 0) {
|
||||
mStatus = mNextStatus;
|
||||
}
|
||||
|
||||
if (mStatus == 1) {
|
||||
if (mStatus == Wait) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mStatus) {
|
||||
case 0:
|
||||
case None:
|
||||
mColor.a = 0xFF;
|
||||
break;
|
||||
case 2:
|
||||
case FadeIn:
|
||||
#if AVOID_UB
|
||||
if (field_0x8 == 0) {
|
||||
mStatus = 1;
|
||||
if (mDuration == 0) {
|
||||
mStatus = Wait;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
mColor.a = 0xFF - ((++field_0xa * 0xFF) / field_0x8);
|
||||
mColor.a = 0xFF - ((++mTimer * 0xFF) / mDuration);
|
||||
|
||||
if (field_0xa >= field_0x8) {
|
||||
mStatus = 1;
|
||||
if (mTimer >= mDuration) {
|
||||
mStatus = Wait;
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
case FadeOut:
|
||||
#if AVOID_UB
|
||||
if (field_0x8 == 0) {
|
||||
mStatus = 0;
|
||||
if (mDuration == 0) {
|
||||
mStatus = None;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
mColor.a = ((++field_0xa * 0xFF) / field_0x8);
|
||||
mColor.a = ((++mTimer * 0xFF) / mDuration);
|
||||
|
||||
if (field_0xa >= field_0x8) {
|
||||
mStatus = 0;
|
||||
if (mTimer >= mDuration) {
|
||||
mStatus = None;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -77,53 +77,53 @@ void JUTFader::draw() {
|
||||
}
|
||||
}
|
||||
|
||||
bool JUTFader::startFadeIn(int param_0) {
|
||||
bool JUTFader::startFadeIn(int duration) {
|
||||
bool statusCheck = mStatus == 0;
|
||||
|
||||
if (statusCheck) {
|
||||
mStatus = 2;
|
||||
field_0xa = 0;
|
||||
field_0x8 = param_0;
|
||||
mStatus = FadeIn;
|
||||
mTimer = 0;
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
return statusCheck;
|
||||
}
|
||||
|
||||
bool JUTFader::startFadeOut(int param_0) {
|
||||
bool JUTFader::startFadeOut(int duration) {
|
||||
bool statusCheck = mStatus == 1;
|
||||
|
||||
if (statusCheck) {
|
||||
mStatus = 3;
|
||||
field_0xa = 0;
|
||||
field_0x8 = param_0;
|
||||
mStatus = FadeOut;
|
||||
mTimer = 0;
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
return statusCheck;
|
||||
}
|
||||
|
||||
void JUTFader::setStatus(JUTFader::EStatus i_status, int param_1) {
|
||||
void JUTFader::setStatus(JUTFader::EStatus i_status, int timer) {
|
||||
switch (i_status) {
|
||||
case 0:
|
||||
if (param_1 != 0) {
|
||||
field_0x24 = 0;
|
||||
mEStatus = param_1;
|
||||
case None:
|
||||
if (timer != 0) {
|
||||
mNextStatus = None;
|
||||
mStatusTimer = timer;
|
||||
break;
|
||||
}
|
||||
|
||||
mStatus = 0;
|
||||
field_0x24 = 0;
|
||||
mEStatus = 0;
|
||||
mStatus = None;
|
||||
mNextStatus = None;
|
||||
mStatusTimer = 0;
|
||||
break;
|
||||
case 1:
|
||||
if (param_1 != 0) {
|
||||
field_0x24 = 1;
|
||||
mEStatus = param_1;
|
||||
case Wait:
|
||||
if (timer != 0) {
|
||||
mNextStatus = Wait;
|
||||
mStatusTimer = timer;
|
||||
break;
|
||||
}
|
||||
|
||||
mStatus = 1;
|
||||
field_0x24 = 1;
|
||||
mEStatus = 0;
|
||||
mStatus = Wait;
|
||||
mNextStatus = Wait;
|
||||
mStatusTimer = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,18 +37,40 @@ void daAlink_c::setCrawlMoveDirectionArrow() {
|
||||
}
|
||||
|
||||
if (field_0x3198 & 4) {
|
||||
if (!bvar) {
|
||||
direction |= data_80452F38;
|
||||
} else {
|
||||
direction |= data_80452F39;
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.enableMirrorMode) {
|
||||
if (!bvar) {
|
||||
direction |= data_80452F39;
|
||||
} else {
|
||||
direction |= data_80452F38;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (!bvar) {
|
||||
direction |= data_80452F38;
|
||||
} else {
|
||||
direction |= data_80452F39;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (field_0x3198 & 8) {
|
||||
if (!bvar) {
|
||||
direction |= data_80452F39;
|
||||
} else {
|
||||
direction |= data_80452F38;
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.enableMirrorMode) {
|
||||
if (!bvar) {
|
||||
direction |= data_80452F38;
|
||||
} else {
|
||||
direction |= data_80452F39;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (!bvar) {
|
||||
direction |= data_80452F39;
|
||||
} else {
|
||||
direction |= data_80452F38;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -623,6 +623,11 @@ int daBg_c::create() {
|
||||
|
||||
dComIfGp_roomControl_onStatusFlag(roomNo, 0x10);
|
||||
OS_REPORT("<BG> room%d\n", roomNo);
|
||||
|
||||
#if TARGET_PC
|
||||
draw_interp_frame = true;
|
||||
#endif
|
||||
|
||||
return cPhs_COMPLEATE_e;
|
||||
}
|
||||
|
||||
|
||||
@@ -215,15 +215,14 @@ int daDsh_c::create() {
|
||||
|
||||
mType = getType();
|
||||
|
||||
#ifdef TARGET_PC
|
||||
const char* l_resName[] = {l_arcName[mType], ""};
|
||||
#else
|
||||
// !@bug By making this static, it is only initialized the first time it runs
|
||||
// If gate types that use other arcs are loaded later (without reloading the code)
|
||||
// this array never gets updated and will load the incorrect arc
|
||||
// On GC/Wii, REL loading causes this to reset/reinitialize so the bug is avoided
|
||||
// but TPHD is all statically linked so daDsh_c::CreateHeap fails to get model data and the gate unloads
|
||||
// !@bug Static-init only runs once, so slot 0 keeps the first mType's arc name forever.
|
||||
// GC/Wii dodges this via REL reload; TPHD is statically linked so later gates of a
|
||||
// different type load the wrong arc and CreateHeap fails. The storage must stay static
|
||||
// because mResLoader.load holds the pointer past create(), so we just overwrite slot 0
|
||||
// each call instead.
|
||||
static const char* l_resName[] = {l_arcName[mType], ""};
|
||||
#ifdef TARGET_PC
|
||||
l_resName[0] = l_arcName[mType];
|
||||
#endif
|
||||
|
||||
int phase = mResLoader.load(l_resName, NULL);
|
||||
|
||||
@@ -6601,13 +6601,14 @@ static int daE_RD_Execute(e_rd_class* i_this) {
|
||||
1.2f,
|
||||
};
|
||||
|
||||
#if AVOID_UB
|
||||
s16 x = 0;
|
||||
s16 y = 0;
|
||||
#endif
|
||||
for (int i = 0; i < 2; i++) {
|
||||
MtxPush();
|
||||
#if !AVOID_UB
|
||||
s16 x, y;
|
||||
|
||||
#if AVOID_UB
|
||||
x = 0;
|
||||
y = 0;
|
||||
#endif
|
||||
|
||||
if (i == 0) {
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
#include "res/Object/Always.h"
|
||||
#include "dusk/dusk.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include <cstring>
|
||||
|
||||
|
||||
@@ -184,6 +186,30 @@ static bool hio_set;
|
||||
|
||||
static daE_WB_HIO_c l_HIO;
|
||||
|
||||
#if TARGET_PC
|
||||
static void e_wb_rein_interp_callback(bool isSimFrame, void* pUserWork) {
|
||||
e_wb_class* i_this = (e_wb_class*)pUserWork;
|
||||
if (!i_this->himo_interp_prev_valid || !i_this->himo_interp_curr_valid) {
|
||||
return;
|
||||
}
|
||||
const f32 alpha = dusk::frame_interp::get_interpolation_step();
|
||||
for (int r = 0; r < 2; r++) {
|
||||
cXyz* dst = i_this->himo_mat[r].getPos(0);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
const cXyz& p0 = i_this->himo_mat_interp_prev[r][i];
|
||||
const cXyz& p1 = i_this->himo_mat_interp_curr[r][i];
|
||||
dst[i] = p0 + (p1 - p0) * alpha;
|
||||
}
|
||||
}
|
||||
cXyz* dst = i_this->himo_tex.getPos(0);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
const cXyz& p0 = i_this->himo_tex_interp_prev[i];
|
||||
const cXyz& p1 = i_this->himo_tex_interp_curr[i];
|
||||
dst[i] = p0 + (p1 - p0) * alpha;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void himo_control1(e_wb_class* i_this, cXyz* i_pos, int i_no, s8 param_3) {
|
||||
fopEn_enemy_c* enemy = &i_this->enemy;
|
||||
cXyz mae, ato;
|
||||
@@ -508,6 +534,21 @@ static int daE_WB_Draw(e_wb_class* i_this) {
|
||||
dComIfGd_set3DlineMat(&i_this->himo_mat[1]);
|
||||
i_this->himo_tex.update(2, l_color, &actor->tevStr);
|
||||
dComIfGd_set3DlineMat(&i_this->himo_tex);
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
if (i_this->himo_interp_curr_valid) {
|
||||
memcpy(i_this->himo_mat_interp_prev, i_this->himo_mat_interp_curr, sizeof(i_this->himo_mat_interp_curr));
|
||||
memcpy(i_this->himo_tex_interp_prev, i_this->himo_tex_interp_curr, sizeof(i_this->himo_tex_interp_curr));
|
||||
i_this->himo_interp_prev_valid = true;
|
||||
}
|
||||
for (int r = 0; r < 2; r++) {
|
||||
memcpy(i_this->himo_mat_interp_curr[r], i_this->himo_mat[r].getPos(0), 16 * sizeof(cXyz));
|
||||
}
|
||||
memcpy(i_this->himo_tex_interp_curr, i_this->himo_tex.getPos(0), 2 * sizeof(cXyz));
|
||||
i_this->himo_interp_curr_valid = true;
|
||||
dusk::frame_interp::add_interpolation_callback(&e_wb_rein_interp_callback, i_this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -3726,6 +3767,9 @@ static void demo_camera(e_wb_class* i_this) {
|
||||
boss = (e_rdb_class*)fopAcM_SearchByName(fpcNm_E_RDB_e);
|
||||
}
|
||||
cXyz mae, ato, eye, center;
|
||||
#if TARGET_PC
|
||||
const s16 entry_demo_mode = i_this->demo_mode;
|
||||
#endif
|
||||
|
||||
switch (i_this->demo_mode) {
|
||||
case 1: {
|
||||
@@ -4255,6 +4299,9 @@ static void demo_camera(e_wb_class* i_this) {
|
||||
|
||||
if (i_this->demo_timer == 325) {
|
||||
fpcM_Search(s_wbZrevise_sub, i_this);
|
||||
#if TARGET_PC
|
||||
i_this->demo_cam_sync_ticks = 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (i_this->demo_timer == 335) {
|
||||
@@ -4495,6 +4542,9 @@ static void demo_camera(e_wb_class* i_this) {
|
||||
i_this->demo_cam_way_spd.z = fabsf(i_this->demo_cam_way.z - i_this->demo_cam_ctr.z);
|
||||
i_this->demo_cam_morf = 0;
|
||||
pla->setPlayerPosAndAngle(&pla->current.pos, pla->shape_angle.y - 4000, 0);
|
||||
#if TARGET_PC
|
||||
dusk::frame_interp::request_presentation_sync();
|
||||
#endif
|
||||
}
|
||||
if (i_this->demo_timer == 345) {
|
||||
daPy_getPlayerActorClass()->setThrowDamage(boss->enemy.shape_angle.y - 8000 + TREG_S(8),
|
||||
@@ -4741,6 +4791,9 @@ static void demo_camera(e_wb_class* i_this) {
|
||||
i_this->demo_cam_eye.x += 300.0f + VREG_F(8);
|
||||
i_this->demo_cam_eye.y += 150.0f + VREG_F(9);
|
||||
i_this->demo_cam_eye.z -= 1400.0f + VREG_F(10);
|
||||
#if TARGET_PC
|
||||
dusk::frame_interp::request_presentation_sync();
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
i_this->demo_cam_eye = enemy->current.pos;
|
||||
@@ -4996,6 +5049,15 @@ static void demo_camera(e_wb_class* i_this) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#if TARGET_PC
|
||||
if (entry_demo_mode != i_this->demo_mode) {
|
||||
i_this->demo_cam_sync_ticks = 2;
|
||||
}
|
||||
if (i_this->demo_cam_sync_ticks > 0) {
|
||||
dusk::frame_interp::request_presentation_sync();
|
||||
i_this->demo_cam_sync_ticks--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void anm_se_eff_set(e_wb_class* i_this) {
|
||||
|
||||
@@ -1056,7 +1056,7 @@ void daMidna_c::setBodyPartMatrix() {
|
||||
#ifdef TARGET_PC
|
||||
// FRAME INTERP NOTE: Record weight envelopes for Midna here, as they are otherwise missed causing distortion
|
||||
for (u16 i = 0; i < mpModel->getModelData()->getWEvlpMtxNum(); i++) {
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(mpModel->getWeightAnmMtx(i)), mpModel->getWeightAnmMtx(i));
|
||||
dusk::frame_interp::record_final_mtx(mpModel->getWeightAnmMtx(i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include <gf/GFGeometry.h>
|
||||
#include <gf/GFLight.h>
|
||||
#include "m_Do/m_Do_lib.h"
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
#ifndef __MWERKS__
|
||||
#include "dusk/math.h"
|
||||
@@ -31,7 +34,11 @@ dMirror_packet_c::dMirror_packet_c() {
|
||||
}
|
||||
|
||||
void dMirror_packet_c::reset() {
|
||||
#if TARGET_PC
|
||||
mbReset = true;
|
||||
#else
|
||||
mModelCount = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void dMirror_packet_c::calcMinMax() {
|
||||
@@ -73,6 +80,13 @@ void dMirror_packet_c::calcMinMax() {
|
||||
}
|
||||
|
||||
int dMirror_packet_c::entryModel(J3DModel* i_model) {
|
||||
#if TARGET_PC
|
||||
if (mbReset) {
|
||||
mModelCount = 0;
|
||||
mbReset = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mModelCount >= 0x40) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4378,6 +4378,8 @@ static void daMP_ActivePlayer_Draw() {
|
||||
|
||||
daMP_DrawPosX = static_cast<u32>(rect.PosX);
|
||||
daMP_DrawPosY = static_cast<u32>(rect.PosY);
|
||||
|
||||
daMP_THPPlayerSetVolume((dusk::getSettings().audio.masterVolume / 100.0f) * 127.0f, 0);
|
||||
#endif
|
||||
|
||||
int frame = daMP_THPPlayerDrawCurrentFrame(
|
||||
@@ -4578,3 +4580,12 @@ actor_process_profile_definition g_profile_MOVIE_PLAYER = {
|
||||
};
|
||||
|
||||
AUDIO_INSTANCES;
|
||||
|
||||
#if TARGET_PC
|
||||
void dusk::MoviePlayerShutdown() {
|
||||
// We need to cleanly shut down the threads to avoid crashes on shutdown.
|
||||
if (daMP_c::m_myObj) {
|
||||
daMP_c::m_myObj->daMP_c_Finish();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -170,7 +170,7 @@ void daObjLv5Key_c::Fall(int param_0) {
|
||||
|
||||
OS_REPORT("FALL SPD = %f\n", speed.y);
|
||||
|
||||
if (mAcch.ChkGroundHit()) {
|
||||
if (mAcch.ChkGroundHit() IF_DUSK(|| current.pos.abs(home.pos) > 200.0f)) {
|
||||
fopAcM_GetSpeed(this);
|
||||
fopAcM_SetSpeedF(this, 4.0f);
|
||||
fopAcM_SetSpeed(this, 0.0f, 22.0f, 0.0f);
|
||||
@@ -192,7 +192,7 @@ void daObjLv5Key_c::Fall(int param_0) {
|
||||
mAcch.CrrPos(dComIfG_Bgsp());
|
||||
current.pos.y = prev_y;
|
||||
|
||||
if (mAcch.ChkGroundHit()) {
|
||||
if (mAcch.ChkGroundHit() IF_DUSK(|| current.pos.abs(home.pos) > 200.0f)) {
|
||||
setAction(&daObjLv5Key_c::Land, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -981,9 +981,7 @@ int daObjStone_c::draw() {
|
||||
if (!model) {
|
||||
f32 shadow_size = l_shadow_size[mStoneType];
|
||||
TGXTexObj* pTex = dDlst_shadowControl_c::getSimpleTex();
|
||||
cXyz pos = current.pos;
|
||||
|
||||
dComIfGd_setSimpleShadow(&pos, mChkObj.GetGroundH(), shadow_size, mChkObj.m_gnd, 0,
|
||||
dComIfGd_setSimpleShadow(¤t.pos, mChkObj.GetGroundH(), shadow_size, mChkObj.m_gnd, 0,
|
||||
1.0f, pTex);
|
||||
}
|
||||
return 1;
|
||||
|
||||
@@ -700,13 +700,13 @@ void dFlower_packet_c::draw() {
|
||||
#ifdef TARGET_PC
|
||||
Mtx flower_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(reinterpret_cast<const void*>(&sp44->m_modelMtx), flower_mtx)) {
|
||||
|
||||
GXLoadPosMtxImm(flower_mtx, 0);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GXLoadPosMtxImm(sp44->m_modelMtx, 0);
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
|
||||
|
||||
#if TARGET_PC
|
||||
@@ -855,6 +855,7 @@ void dFlower_packet_c::draw() {
|
||||
#ifdef TARGET_PC
|
||||
Mtx flower_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(reinterpret_cast<const void*>(&sp34->m_modelMtx), flower_mtx)) {
|
||||
cMtx_concat(j3dSys.getViewMtx(), flower_mtx, flower_mtx);
|
||||
GXLoadPosMtxImm(flower_mtx, 0);
|
||||
} else {
|
||||
#endif
|
||||
@@ -994,7 +995,7 @@ void dFlower_packet_c::update() {
|
||||
mDoMtx_stack_c::scaleM(temp_f31, temp_f31, temp_f31);
|
||||
cMtx_concat(j3dSys.getViewMtx(), temp_r28, data_p->m_modelMtx);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(&data_p->m_modelMtx), data_p->m_modelMtx);
|
||||
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), data_p->m_modelMtx);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -756,13 +756,13 @@ void dGrass_packet_c::draw() {
|
||||
#ifdef TARGET_PC
|
||||
Mtx grass_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(reinterpret_cast<const void*>(&var_r29->m_modelMtx), grass_mtx)) {
|
||||
cMtx_concat(j3dSys.getViewMtx(), grass_mtx, grass_mtx);
|
||||
GXLoadPosMtxImm(grass_mtx, 0);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GXLoadPosMtxImm(var_r29->m_modelMtx, 0);
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
|
||||
if (var_r29->field_0x05 <= 3 || var_r29->field_0x05 >= 10) {
|
||||
if (var_r29->field_0x02 < -1) {
|
||||
@@ -1018,7 +1018,7 @@ void dGrass_packet_c::update() {
|
||||
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), data_p->m_modelMtx);
|
||||
}
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(&data_p->m_modelMtx), data_p->m_modelMtx);
|
||||
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), data_p->m_modelMtx);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
+18
-3
@@ -7063,6 +7063,15 @@ bool dCamera_c::subjectCamera(s32 param_0) {
|
||||
}
|
||||
|
||||
cXyz sp1E0(val0, val2, val1);
|
||||
|
||||
#if TARGET_PC
|
||||
f32 aspect = mDoGph_gInf_c::getAspect();
|
||||
f32 baseAspect = FB_WIDTH / FB_HEIGHT;
|
||||
if (aspect > baseAspect) {
|
||||
sp1E0.z += (aspect - baseAspect) * 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
sp1D4 = dCamMath::xyzRotateX(sp1E0, angle_x);
|
||||
sp1E0 = dCamMath::xyzRotateY(sp1D4, angle_y);
|
||||
f32 sp6C = sp12 ? 40.0f : 0.0f;
|
||||
@@ -11009,6 +11018,15 @@ static int camera_execute(camera_process_class* i_this) {
|
||||
i_this->mCamera.CalcTrimSize();
|
||||
|
||||
store(i_this);
|
||||
|
||||
#ifdef TARGET_PC
|
||||
// record new camera for our sim frame
|
||||
dusk::frame_interp::record_camera(i_this, get_camera_id(i_this));
|
||||
// interpolate the view now so that this sim frame's view matrix matches what
|
||||
// we'll be rendering with later
|
||||
dusk::frame_interp::interp_view(&i_this->view);
|
||||
#endif
|
||||
|
||||
view_setup(i_this);
|
||||
return 1;
|
||||
}
|
||||
@@ -11077,9 +11095,6 @@ static int camera_draw(camera_process_class* i_this) {
|
||||
C_MTXPerspective(process->view.projMtx, process->view.fovy, process->view.aspect, process->view.near_, process->view.far_);
|
||||
mDoMtx_lookAt(process->view.viewMtx, &process->view.lookat.eye, &process->view.lookat.center,
|
||||
&process->view.lookat.up, process->view.bank);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_camera(process, camera_id);
|
||||
#endif
|
||||
|
||||
#if WIDESCREEN_SUPPORT
|
||||
mDoGph_gInf_c::setWideZoomProjection(process->view.projMtx);
|
||||
|
||||
+23
-32
@@ -1096,16 +1096,7 @@ void dDlst_shadowReal_c::draw() {
|
||||
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetCurrentMtx(GX_PNMTX0);
|
||||
#ifdef TARGET_PC
|
||||
Mtx receiver_proj_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(&mReceiverProjMtx, receiver_proj_mtx)) {
|
||||
GXLoadTexMtxImm(receiver_proj_mtx, GX_TEXMTX0, GX_MTX3x4);
|
||||
} else {
|
||||
#endif
|
||||
GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4);
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4);
|
||||
mShadowRealPoly.draw();
|
||||
}
|
||||
|
||||
@@ -1263,14 +1254,9 @@ u8 dDlst_shadowReal_c::setShadowRealMtx(cXyz* param_0, cXyz* param_1, f32 param_
|
||||
C_MTXOrtho(mRenderProjMtx, param_2, -param_2, -param_2, param_2, 1.0f, 10000.0f);
|
||||
C_MTXLightOrtho(mReceiverProjMtx, param_2, -param_2, -param_2, param_2, 0.5f, -0.5f, 0.5f, 0.5f);
|
||||
cMtx_concat(mReceiverProjMtx, mViewMtx, mReceiverProjMtx);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(&mViewMtx, mViewMtx);
|
||||
dusk::frame_interp::record_final_mtx_raw(&mReceiverProjMtx, mReceiverProjMtx);
|
||||
#endif
|
||||
return r29;
|
||||
}
|
||||
|
||||
|
||||
u32 dDlst_shadowReal_c::set(u32 i_key, J3DModel* i_model, cXyz* param_2, f32 param_3, f32 param_4,
|
||||
dKy_tevstr_c* param_5, f32 i_cameraZ, f32 param_7) {
|
||||
dScnKy_env_light_c* env_light = dKy_getEnvlight();
|
||||
@@ -1292,6 +1278,7 @@ u32 dDlst_shadowReal_c::set(u32 i_key, J3DModel* i_model, cXyz* param_2, f32 par
|
||||
}
|
||||
|
||||
field_0x1 = setShadowRealMtx(&sp60, param_2, param_3, param_4, param_7, param_5);
|
||||
|
||||
if (!field_0x1) {
|
||||
return 0;
|
||||
}
|
||||
@@ -1331,14 +1318,14 @@ void dDlst_shadowSimple_c::draw() {
|
||||
GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
|
||||
#ifdef TARGET_PC
|
||||
Mtx volume_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(&mVolumeMtx, volume_mtx)) {
|
||||
if (dusk::frame_interp::lookup_replacement(mVolumeMtxKey, volume_mtx)) {
|
||||
cMtx_concat(j3dSys.getViewMtx(), volume_mtx, volume_mtx);
|
||||
GXLoadPosMtxImm(volume_mtx, GX_PNMTX0);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GXLoadPosMtxImm(mVolumeMtx, GX_PNMTX0);
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
GXSetCurrentMtx(GX_PNMTX0);
|
||||
GXCallDisplayList(l_frontMat, 0x40);
|
||||
GXCallDisplayList(l_shadowVolumeDL, 0x40);
|
||||
@@ -1346,14 +1333,14 @@ void dDlst_shadowSimple_c::draw() {
|
||||
GXCallDisplayList(l_shadowVolumeDL, 0x40);
|
||||
#ifdef TARGET_PC
|
||||
Mtx shadow_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(&mMtx, shadow_mtx)) {
|
||||
if (dusk::frame_interp::lookup_replacement(mMtxKey, shadow_mtx)) {
|
||||
cMtx_concat(j3dSys.getViewMtx(), shadow_mtx, shadow_mtx);
|
||||
GXLoadPosMtxImm(shadow_mtx, GX_PNMTX1);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GXLoadPosMtxImm(mMtx, GX_PNMTX1);
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
GXSetCurrentMtx(GX_PNMTX1);
|
||||
|
||||
if (mpTexObj != NULL) {
|
||||
@@ -1383,6 +1370,12 @@ void dDlst_shadowSimple_c::draw() {
|
||||
GXCallDisplayList(l_shadowVolumeDL, 0x40);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
static const void* getInterpKey(const void* base, int idx) {
|
||||
return reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(base) ^ idx);
|
||||
}
|
||||
#endif
|
||||
|
||||
void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* param_3,
|
||||
s16 param_4, f32 param_5, TGXTexObj* param_6) {
|
||||
if (param_5 < 0.0f) {
|
||||
@@ -1406,6 +1399,10 @@ void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* pa
|
||||
mDoMtx_stack_c::transS(param_0->x, param_1 + f30, param_0->z);
|
||||
mDoMtx_stack_c::YrotM(param_4);
|
||||
mDoMtx_stack_c::scaleM(param_2, f30 + f30 + 16.0f, param_2 * param_5);
|
||||
#if TARGET_PC
|
||||
mVolumeMtxKey = getInterpKey(param_0, 0x1);
|
||||
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), mVolumeMtxKey);
|
||||
#endif
|
||||
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mVolumeMtx);
|
||||
f32 f31 = JMAFastSqrt(1.0f - param_3->x * param_3->x);
|
||||
f32 f29;
|
||||
@@ -1431,17 +1428,11 @@ void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* pa
|
||||
mDoMtx_stack_c::get()[2][3] = param_0->z;
|
||||
mDoMtx_stack_c::YrotM(param_4);
|
||||
mDoMtx_stack_c::scaleM(param_2, 1.0f, param_2 * param_5);
|
||||
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mMtx);
|
||||
#ifdef TARGET_PC
|
||||
const uint64_t shadow_tag_base = dusk::frame_interp::alloc_simple_shadow_pair_base();
|
||||
if (shadow_tag_base != 0) {
|
||||
dusk::frame_interp::record_final_mtx_raw_tagged(&mVolumeMtx, mVolumeMtx, shadow_tag_base);
|
||||
dusk::frame_interp::record_final_mtx_raw_tagged(&mMtx, mMtx, shadow_tag_base + 1u);
|
||||
} else {
|
||||
dusk::frame_interp::record_final_mtx_raw(&mVolumeMtx, mVolumeMtx);
|
||||
dusk::frame_interp::record_final_mtx_raw(&mMtx, mMtx);
|
||||
}
|
||||
mMtxKey = getInterpKey(param_0, 0x2);
|
||||
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), mMtxKey);
|
||||
#endif
|
||||
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mMtx);
|
||||
mpTexObj = param_6;
|
||||
}
|
||||
|
||||
|
||||
+24
-24
@@ -2102,11 +2102,7 @@ void dFile_select_c::yesnoCursorShow() {
|
||||
mSelIcon->setPos(pos.x, pos.y, mYnSelPane[field_0x0268]->getPanePtr(), true);
|
||||
mSelIcon->setAlphaRate(1.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f);
|
||||
#else
|
||||
mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2259,11 +2255,7 @@ void dFile_select_c::YesNoCancelMove() {
|
||||
m3mSelPane[mSelectMenuNum]->getPanePtr(), true);
|
||||
mSelIcon->setAlphaRate(1.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f);
|
||||
#else
|
||||
mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f);
|
||||
#endif
|
||||
|
||||
#if PLATFORM_WII || PLATFORM_SHIELD
|
||||
field_0x4333 = mSelectMenuNum;
|
||||
@@ -3147,11 +3139,7 @@ void dFile_select_c::screenSet() {
|
||||
mSelIcon = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL);
|
||||
JUT_ASSERT(5209, mSelIcon != NULL);
|
||||
|
||||
#if TARGET_PC
|
||||
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f);
|
||||
#else
|
||||
mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f);
|
||||
#endif
|
||||
|
||||
Vec vtxCenter;
|
||||
vtxCenter = mSelFilePanes[mSelectNum]->getGlobalVtxCenter(false, 0);
|
||||
@@ -3204,6 +3192,9 @@ void dFile_select_c::screenSet() {
|
||||
timg, NULL);
|
||||
mpFadePict->setBlackWhite(black, white);
|
||||
mpFadePict->setAlpha(0);
|
||||
#ifdef TARGET_PC
|
||||
mFadeDlst.mpPict = mpFadePict;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -3284,11 +3275,7 @@ void dFile_select_c::screenSetCopySel() {
|
||||
mSelIcon2 = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL);
|
||||
JUT_ASSERT(5406, mSelIcon2 != NULL);
|
||||
|
||||
#if TARGET_PC
|
||||
mSelIcon2->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f);
|
||||
#else
|
||||
mSelIcon2->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f);
|
||||
#endif
|
||||
|
||||
Vec center = mCpSelPane[0]->getGlobalVtxCenter(false, 0);
|
||||
mSelIcon2->setPos(center.x, center.y, mCpSelPane[0]->getPanePtr(), true);
|
||||
@@ -3680,11 +3667,7 @@ void dFile_select_c::selFileCursorShow() {
|
||||
mSelIcon->setPos(local_1c.x, local_1c.y, mSelFilePanes[mSelectNum]->getPanePtr(), true);
|
||||
mSelIcon->setAlphaRate(1.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f);
|
||||
#else
|
||||
mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f);
|
||||
#endif
|
||||
}
|
||||
|
||||
void dFile_select_c::menuWakuAlpahAnmInit(u8 i_idx, u8 param_1, u8 param_2, u8 param_3) {
|
||||
@@ -3727,11 +3710,7 @@ void dFile_select_c::menuCursorShow() {
|
||||
mSelIcon->setPos(local_24.x, local_24.y, m3mSelPane[mSelectMenuNum]->getPanePtr(), true);
|
||||
mSelIcon->setAlphaRate(1.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f);
|
||||
#else
|
||||
mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3833,6 +3812,16 @@ void dFile_select_c::fileSelectWide() {
|
||||
fileSel.Scr->search(MULTI_CHAR('w_uzu07'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
fileSel.Scr->search(MULTI_CHAR('w_uzu08'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
fileSel.Scr->search(MULTI_CHAR('w_uzu09'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
if (mSelIcon) {
|
||||
mSelIcon->refreshAspectScale();
|
||||
}
|
||||
|
||||
if (mSelIcon2) {
|
||||
mSelIcon2->refreshAspectScale();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3870,10 +3859,14 @@ void dFile_select_c::_draw() {
|
||||
dComIfGd_set2DOpa(mSelIcon2);
|
||||
|
||||
#if PLATFORM_GCN
|
||||
#if TARGET_PC
|
||||
dComIfGd_set2DOpaTop(&mFadeDlst);
|
||||
#else
|
||||
mpFadePict->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(),
|
||||
mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), false, false,
|
||||
false);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3917,6 +3910,13 @@ void dDlst_FileSel3m_c::draw() {
|
||||
Scr3m->draw(0.0f, 0.0f, graf);
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
void dDlst_FileSelFade_c::draw() {
|
||||
mpPict->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(),
|
||||
mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), false, false, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
void dFile_select_c::errorMoveAnmInitSet(int param_1, int param_2) {
|
||||
mErrorMsgPane->setAnimation(field_0x0090);
|
||||
field_0x0130 = param_1;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#if TARGET_PC
|
||||
#include "dusk/imgui/ImGuiBloomWindow.hpp"
|
||||
#include "dusk/settings.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
static void GxXFog_set();
|
||||
@@ -8251,6 +8252,10 @@ static int dKy_Create(void* i_this) {
|
||||
kankyo_class* kankyo = (kankyo_class*)i_this;
|
||||
BOOL next_time_set = false;
|
||||
|
||||
#if TARGET_PC
|
||||
kankyo->base.draw_interp_frame = true;
|
||||
#endif
|
||||
|
||||
stage_envr_info_class* stage_envr_p = dComIfGp_getStageEnvrInfo();
|
||||
if (stage_envr_p != NULL && dComIfGp_getStartStageRoomNo() != -1) {
|
||||
stage_envr_p += dComIfGp_getStartStageRoomNo();
|
||||
|
||||
+11
-12
@@ -164,11 +164,22 @@ void dMenu_Collect2D_c::menuCollectWide() {
|
||||
|
||||
// Item Description Text
|
||||
mpScreen->search(MULTI_CHAR('infotxtn'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
if (mpDrawCursor) {
|
||||
mpDrawCursor->refreshAspectScale();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void dMenu_Collect2D_c::_create() {
|
||||
mpHeap->getTotalFreeSize();
|
||||
|
||||
#if TARGET_PC
|
||||
mpDrawCursor = NULL;
|
||||
#endif
|
||||
|
||||
mpScreen = JKR_NEW J2DScreen();
|
||||
mpScreen->setPriority("zelda_collect_soubi_screen.blo", 0x1020000,
|
||||
dComIfGp_getCollectResArchive());
|
||||
@@ -1100,23 +1111,11 @@ void dMenu_Collect2D_c::cursorPosSet() {
|
||||
Vec pos = mpSelPm[mCursorX][mCursorY]->getGlobalVtxCenter(false, 0);
|
||||
mpDrawCursor->setPos(pos.x, pos.y, mpSelPm[mCursorX][mCursorY]->getPanePtr(), false);
|
||||
if (mCursorY == 5) {
|
||||
#if TARGET_PC
|
||||
mpDrawCursor->setParam(1.1f * mDoGph_gInf_c::hudAspectScaleUp, 0.85f, 0.05f, 0.5f, 0.5f);
|
||||
#else
|
||||
mpDrawCursor->setParam(1.1f, 0.85f, 0.05f, 0.5f, 0.5f);
|
||||
#endif
|
||||
} else if (mCursorX == 6 && mCursorY == 0) {
|
||||
#if TARGET_PC
|
||||
mpDrawCursor->setParam(0.6f * mDoGph_gInf_c::hudAspectScaleUp, 0.85f, 0.03f, 0.6f, 0.6f);
|
||||
#else
|
||||
mpDrawCursor->setParam(0.6f, 0.85f, 0.03f, 0.6f, 0.6f);
|
||||
#endif
|
||||
} else {
|
||||
#if TARGET_PC
|
||||
mpDrawCursor->setParam(1.0f * mDoGph_gInf_c::hudAspectScaleUp, 1.0f, 0.1f, 0.7f, 0.7f);
|
||||
#else
|
||||
mpDrawCursor->setParam(1.0f, 1.0f, 0.1f, 0.7f, 0.7f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-9
@@ -342,8 +342,13 @@ void dMenu_Fmap2DBack_c::draw() {
|
||||
scrollAreaDraw();
|
||||
}
|
||||
|
||||
blinkMove(30);
|
||||
moveLightDropAnime();
|
||||
#ifdef TARGET_PC
|
||||
if (dusk::frame_interp::get_ui_tick_pending())
|
||||
#endif
|
||||
{
|
||||
blinkMove(30);
|
||||
moveLightDropAnime();
|
||||
}
|
||||
setCenterPosX(field_0x11dc, 1);
|
||||
drawIcon(mTransX, mTransZ, mAlphaRate, field_0xfa8 * mSpotTextureFadeAlpha);
|
||||
|
||||
@@ -1764,14 +1769,19 @@ void dMenu_Fmap2DBack_c::calcBlink() {
|
||||
t * (g_fmapHIO.mMapBlink[i + 1].mUnselectedRegion.mBlinkSpeed -
|
||||
g_fmapHIO.mMapBlink[i].mUnselectedRegion.mBlinkSpeed);
|
||||
|
||||
field_0x1218++;
|
||||
if (field_0x1218 >= selected_blink_speed) {
|
||||
field_0x1218 = 0;
|
||||
}
|
||||
#if TARGET_PC
|
||||
if (dusk::frame_interp::get_ui_tick_pending())
|
||||
#endif
|
||||
{
|
||||
field_0x1218++;
|
||||
if (field_0x1218 >= selected_blink_speed) {
|
||||
field_0x1218 = 0;
|
||||
}
|
||||
|
||||
field_0x121a++;
|
||||
if (field_0x121a >= unselected_blink_speed) {
|
||||
field_0x121a = 0;
|
||||
field_0x121a++;
|
||||
if (field_0x121a >= unselected_blink_speed) {
|
||||
field_0x121a = 0;
|
||||
}
|
||||
}
|
||||
|
||||
f32 t_selected = 0.0f;
|
||||
|
||||
@@ -555,11 +555,23 @@ void dMenu_Option_c::_draw() {
|
||||
#endif
|
||||
|
||||
mpBlackTex->setAlpha(0xff);
|
||||
|
||||
#if TARGET_PC
|
||||
mpBlackTex->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), 0, 0, 0);
|
||||
#else
|
||||
mpBlackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0, 0, 0);
|
||||
#endif
|
||||
|
||||
mpBackScreen->draw(0.0f, 0.0f, ctx);
|
||||
f32 alpha = (f32)g_drawHIO.mOptionScreen.mBackgroundAlpha * (f32)field_0x374;
|
||||
mpBlackTex->setAlpha(alpha);
|
||||
|
||||
#if TARGET_PC
|
||||
mpBlackTex->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), 0, 0, 0);
|
||||
#else
|
||||
mpBlackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0, 0, 0);
|
||||
#endif
|
||||
|
||||
mpScreen->draw(0.0f, 0.0f, ctx);
|
||||
mpClipScreen->draw(0.0f, 0.0f, ctx);
|
||||
#if TARGET_PC
|
||||
|
||||
+43
-33
@@ -18,6 +18,7 @@
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
#include "d/d_msg_scrn_explain.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "JSystem/J2DGraph/J2DAnmLoader.h"
|
||||
#include "f_op/f_op_msg_mng.h"
|
||||
@@ -386,11 +387,7 @@ void dMenu_save_c::screenSet() {
|
||||
mSelectedFile = dComIfGs_getDataNum();
|
||||
mSelIcon = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL);
|
||||
|
||||
#if TARGET_PC
|
||||
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f);
|
||||
#else
|
||||
mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f);
|
||||
#endif
|
||||
|
||||
Vec pos;
|
||||
pos = mpSelData[mSelectedFile]->getGlobalVtxCenter(false, 0);
|
||||
@@ -719,7 +716,9 @@ void dMenu_save_c::_move() {
|
||||
}
|
||||
|
||||
(this->*MenuSaveProc[mMenuProc])();
|
||||
#if !TARGET_PC
|
||||
saveSelAnm();
|
||||
#endif
|
||||
|
||||
if (mWarning != NULL) {
|
||||
mWarning->_move();
|
||||
@@ -736,36 +735,46 @@ void dMenu_save_c::saveSelAnm() {
|
||||
}
|
||||
|
||||
void dMenu_save_c::selFileWakuAnm() {
|
||||
mFileWakuAnmFrame += 2;
|
||||
if (mFileWakuAnmFrame >= mpFileWakuAnm->getFrameMax()) {
|
||||
mFileWakuAnmFrame -= mpFileWakuAnm->getFrameMax();
|
||||
#if TARGET_PC
|
||||
if (dusk::frame_interp::get_ui_tick_pending())
|
||||
#endif
|
||||
{
|
||||
mFileWakuAnmFrame += 2;
|
||||
if (mFileWakuAnmFrame >= mpFileWakuAnm->getFrameMax()) {
|
||||
mFileWakuAnmFrame -= mpFileWakuAnm->getFrameMax();
|
||||
}
|
||||
|
||||
mFileWakuRotAnmFrame += 2;
|
||||
if (mFileWakuRotAnmFrame >= mpFileWakuRotAnm->getFrameMax()) {
|
||||
mFileWakuRotAnmFrame -= mpFileWakuRotAnm->getFrameMax();
|
||||
}
|
||||
}
|
||||
mpFileWakuAnm->setFrame(mFileWakuAnmFrame);
|
||||
|
||||
mFileWakuRotAnmFrame += 2;
|
||||
if (mFileWakuRotAnmFrame >= mpFileWakuRotAnm->getFrameMax()) {
|
||||
mFileWakuRotAnmFrame -= mpFileWakuRotAnm->getFrameMax();
|
||||
}
|
||||
mpFileWakuRotAnm->setFrame(mFileWakuRotAnmFrame);
|
||||
}
|
||||
|
||||
void dMenu_save_c::bookIconAnm() {
|
||||
field_0x154 += 2;
|
||||
if (field_0x154 >= field_0x150->getFrameMax()) {
|
||||
field_0x154 -= field_0x150->getFrameMax();
|
||||
#if TARGET_PC
|
||||
if (dusk::frame_interp::get_ui_tick_pending())
|
||||
#endif
|
||||
{
|
||||
field_0x154 += 2;
|
||||
if (field_0x154 >= field_0x150->getFrameMax()) {
|
||||
field_0x154 -= field_0x150->getFrameMax();
|
||||
}
|
||||
|
||||
field_0x15c += 2;
|
||||
if (field_0x15c >= field_0x158->getFrameMax()) {
|
||||
field_0x15c -= field_0x158->getFrameMax();
|
||||
}
|
||||
|
||||
field_0x164 += 2;
|
||||
if (field_0x164 >= field_0x160->getFrameMax()) {
|
||||
field_0x164 -= field_0x160->getFrameMax();
|
||||
}
|
||||
}
|
||||
field_0x150->setFrame(field_0x154);
|
||||
|
||||
field_0x15c += 2;
|
||||
if (field_0x15c >= field_0x158->getFrameMax()) {
|
||||
field_0x15c -= field_0x158->getFrameMax();
|
||||
}
|
||||
field_0x158->setFrame(field_0x15c);
|
||||
|
||||
field_0x164 += 2;
|
||||
if (field_0x164 >= field_0x160->getFrameMax()) {
|
||||
field_0x164 -= field_0x160->getFrameMax();
|
||||
}
|
||||
field_0x160->setFrame(field_0x164);
|
||||
}
|
||||
|
||||
@@ -2523,11 +2532,7 @@ void dMenu_save_c::yesnoCursorShow() {
|
||||
mSelIcon->setPos(pos.x, pos.y, mpNoYes[mYesNoCursor]->getPanePtr(), true);
|
||||
mSelIcon->setAlphaRate(1.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f);
|
||||
#else
|
||||
mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2676,11 +2681,7 @@ void dMenu_save_c::selFileCursorShow() {
|
||||
mSelIcon->setPos(pos.x, pos.y, mpSelData[mSelectedFile]->getPanePtr(), true);
|
||||
mSelIcon->setAlphaRate(1.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f);
|
||||
#else
|
||||
mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f);
|
||||
#endif
|
||||
}
|
||||
|
||||
void dMenu_save_c::yesnoWakuAlpahAnmInit(u8 yesnoIdx, u8 startAlpha, u8 endAlpha, u8 anmTimer) {
|
||||
@@ -2813,11 +2814,20 @@ void dMenu_save_c::menuSaveWide() {
|
||||
mSaveSel.Scr->search(MULTI_CHAR('w_uzu07'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
mSaveSel.Scr->search(MULTI_CHAR('w_uzu08'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
mSaveSel.Scr->search(MULTI_CHAR('w_uzu09'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
if (mSelIcon) {
|
||||
mSelIcon->refreshAspectScale();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void dMenu_save_c::_draw2() {
|
||||
if (field_0x21a1 == 0) {
|
||||
#if TARGET_PC
|
||||
saveSelAnm();
|
||||
#endif
|
||||
if (mpScrnExplain != NULL) {
|
||||
dComIfGd_set2DOpa(&mMenuSaveExplain);
|
||||
}
|
||||
|
||||
@@ -699,7 +699,7 @@ void dMw_c::collect_open_proc() {
|
||||
dMeter2Info_set2DVibrationM();
|
||||
}
|
||||
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = COLLECT_MOVE;
|
||||
}
|
||||
}
|
||||
@@ -914,7 +914,7 @@ void dMw_c::collect_letter_move_proc() {
|
||||
}
|
||||
|
||||
void dMw_c::collect_letter_close_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = COLLECT_MOVE;
|
||||
}
|
||||
}
|
||||
@@ -946,7 +946,7 @@ void dMw_c::collect_fishing_move_proc() {
|
||||
}
|
||||
|
||||
void dMw_c::collect_fishing_close_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = COLLECT_MOVE;
|
||||
}
|
||||
}
|
||||
@@ -977,7 +977,7 @@ void dMw_c::collect_skill_move_proc() {
|
||||
}
|
||||
|
||||
void dMw_c::collect_skill_close_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = COLLECT_MOVE;
|
||||
}
|
||||
}
|
||||
@@ -1008,13 +1008,13 @@ void dMw_c::collect_insect_move_proc() {
|
||||
}
|
||||
|
||||
void dMw_c::collect_insect_close_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = COLLECT_MOVE;
|
||||
}
|
||||
}
|
||||
|
||||
void dMw_c::insect_open_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
field_0x152 = 0;
|
||||
dComIfGp_setHeapLockFlag(1);
|
||||
dMw_insect_create(1);
|
||||
@@ -1050,7 +1050,7 @@ void dMw_c::insect_move_proc() {
|
||||
}
|
||||
|
||||
void dMw_c::insect_close_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = NO_MENU;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,6 +271,30 @@ void dMsgUnit_c::setTag(int i_type, int i_value, char* o_buffer, bool param_4) {
|
||||
u32 filesize = pHeader->size;
|
||||
u8* pSection = ((u8*)pHeader) + filepos;
|
||||
|
||||
#if TARGET_PC
|
||||
// patch bug in the original game where filepos would be incremented by the next section's size rather than the current section size.
|
||||
// in certain scenarios this would read past the end of the file, incrementing filepos by 0 in an infinite loop
|
||||
while (filepos < filesize) {
|
||||
switch (((bmg_section_t*)pSection)->magic) {
|
||||
case 'FLW1':
|
||||
break;
|
||||
case 'FLI1':
|
||||
break;
|
||||
case 'INF1':
|
||||
pInfoBlock = (bmg_section_t*)pSection;
|
||||
break;
|
||||
case 'DAT1':
|
||||
pMsgDataBlock = pSection;
|
||||
break;
|
||||
case 'STR1':
|
||||
pStrAttributeBlock = (str1_section_t*)pSection;
|
||||
break;
|
||||
}
|
||||
|
||||
filepos += ((bmg_section_t*)pSection)->size;
|
||||
pSection += ((bmg_section_t*)pSection)->size;
|
||||
}
|
||||
#else
|
||||
for (; filepos < filesize; filepos += ((bmg_section_t*)pSection)->size) {
|
||||
switch (((bmg_section_t*)pSection)->magic) {
|
||||
case 'FLW1':
|
||||
@@ -289,6 +313,7 @@ void dMsgUnit_c::setTag(int i_type, int i_value, char* o_buffer, bool param_4) {
|
||||
}
|
||||
pSection += ((bmg_section_t*)pSection)->size;
|
||||
}
|
||||
#endif
|
||||
|
||||
// This section is weird. The debug seems like entriesStr is outside the condition
|
||||
// but the normal build doesn't really work with that. Same for pInfoBlock->entries.
|
||||
|
||||
+5
-5
@@ -1288,7 +1288,11 @@ void dName_c::selectCursorPosSet(int row) {
|
||||
#if TARGET_PC
|
||||
void dName_c::nameWide() {
|
||||
//Resize Select Icon
|
||||
mSelIcon->setParam(0.82f * mDoGph_gInf_c::hudAspectScaleUp, 0.77f, 0.05f, 0.4f, 0.4f);
|
||||
#if TARGET_PC
|
||||
if (mSelIcon) {
|
||||
mSelIcon->refreshAspectScale();
|
||||
}
|
||||
#endif
|
||||
|
||||
// List of Characters Box
|
||||
static u64 l_tagName[65] = {
|
||||
@@ -1540,11 +1544,7 @@ void dName_c::screenSet() {
|
||||
mSelIcon = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL);
|
||||
JUT_ASSERT(0, mSelIcon != NULL);
|
||||
|
||||
#if TARGET_PC
|
||||
mSelIcon->setParam(0.82f * mDoGph_gInf_c::hudAspectScaleUp, 0.77f, 0.05f, 0.4f, 0.4f);
|
||||
#else
|
||||
mSelIcon->setParam(0.82f, 0.77f, 0.05f, 0.4f, 0.4f);
|
||||
#endif
|
||||
|
||||
Vec pos = mMojiIcon[mCharRow + mCharColumn * 5]->getGlobalVtxCenter(false, 0);
|
||||
mSelIcon->setPos(pos.x, pos.y, mMojiIcon[mCharRow + mCharColumn * 5]->getPanePtr(), true);
|
||||
|
||||
@@ -26,8 +26,8 @@ static void dOvlpFd_startFadeIn(int param_0) {
|
||||
JUTFader* fader = JFWDisplay::getManager()->getFader();
|
||||
JUT_ASSERT(0, fader != NULL);
|
||||
|
||||
fader->setStatus(JUTFader::UNKSTATUS_0, 0);
|
||||
fader->setStatus(JUTFader::UNKSTATUS_0, -1);
|
||||
fader->setStatus(JUTFader::None, 0);
|
||||
fader->setStatus(JUTFader::None, -1);
|
||||
fader->startFadeIn(param_0);
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -296,7 +296,11 @@ J3DModelData* dRes_info_c::loaderBasicBmd(u32 i_tag, void* i_data) {
|
||||
addWarpMaterial(modelData);
|
||||
}
|
||||
|
||||
if (i_tag == 'BMDR' || i_tag == 'BMWR') {
|
||||
// FRAME INTERP NOTE: Always create shared DL buffers so we can use J3DMaterial::diff()
|
||||
#ifndef TARGET_PC
|
||||
if (i_tag == 'BMDR' || i_tag == 'BMWR')
|
||||
#endif
|
||||
{
|
||||
s32 result = modelData->newSharedDisplayList(J3DMdlFlag_UseSingleDL);
|
||||
if (result != kJ3DError_Success) {
|
||||
return NULL;
|
||||
|
||||
@@ -69,6 +69,9 @@ dSelect_cursor_c::dSelect_cursor_c(u8 param_0, f32 param_1, JKRArchive* param_2)
|
||||
field_0x84[i] = 0.0f;
|
||||
}
|
||||
mParam1 = mpCursorHIO->mXAxisExpansion;
|
||||
#ifdef TARGET_PC
|
||||
mBaseParam1 = mParam1;
|
||||
#endif
|
||||
mParam2 = mpCursorHIO->mYAxisExpansion;
|
||||
mParam3 = mpCursorHIO->mOscillation;
|
||||
mParam4 = mpCursorHIO->mRatioX;
|
||||
@@ -259,6 +262,13 @@ void dSelect_cursor_c::update() {
|
||||
if (field_0xb6 == 3) {
|
||||
fVar1 = 0.5f;
|
||||
}
|
||||
#ifdef TARGET_PC
|
||||
if (mpPane) {
|
||||
Vec pos = mpPaneMgr->getGlobalVtxCenter(mpPane, false, 0);
|
||||
mPositionX = pos.x;
|
||||
mPositionY = pos.y;
|
||||
}
|
||||
#endif
|
||||
mpPaneMgr->translate(mPositionX, mPositionY);
|
||||
if (mpCursorHIO->mDebugON) {
|
||||
mParam1 = mpCursorHIO->mXAxisExpansion;
|
||||
@@ -404,6 +414,9 @@ void dSelect_cursor_c::setPos(f32 i_posX, f32 i_posY, J2DPane* i_pane, bool i_sc
|
||||
void dSelect_cursor_c::setParam(f32 i_param1, f32 i_param2, f32 i_param3, f32 i_param4,
|
||||
f32 i_param5) {
|
||||
mParam1 = i_param1;
|
||||
#ifdef TARGET_PC
|
||||
mBaseParam1 = i_param1;
|
||||
#endif
|
||||
mParam2 = i_param2;
|
||||
mParam3 = i_param3;
|
||||
mParam4 = i_param4;
|
||||
@@ -562,3 +575,9 @@ void dSelect_cursor_c::setBckAnimation(J2DAnmTransformKey* param_0) {
|
||||
void dSelect_cursor_c::moveCenter(J2DPane* i_pane, f32 i_x, f32 i_y) {
|
||||
i_pane->translate(i_x,i_y);
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
void dSelect_cursor_c::refreshAspectScale() {
|
||||
mParam1 = mBaseParam1 * mDoGph_gInf_c::hudAspectScaleUp;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -77,6 +77,14 @@ void dusk::audio::SetMasterVolume(const f32 value) {
|
||||
MasterVolume = value;
|
||||
}
|
||||
|
||||
void dusk::audio::SetPaused(const bool paused) {
|
||||
if (paused) {
|
||||
SDL_PauseAudioStreamDevice(PlaybackStream);
|
||||
} else {
|
||||
SDL_ResumeAudioStreamDevice(PlaybackStream);
|
||||
}
|
||||
}
|
||||
|
||||
void dusk::audio::SetEnableReverb(const bool value) {
|
||||
JASCriticalSection section;
|
||||
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include "dusk/dusk.h"
|
||||
#include "dusk/main.h"
|
||||
|
||||
using namespace dusk::config;
|
||||
|
||||
@@ -24,7 +24,7 @@ static absl::flat_hash_map<std::string_view, ConfigVarBase*> RegisteredConfigVar
|
||||
static bool RegistrationDone = false;
|
||||
|
||||
static std::string GetConfigJsonPath() {
|
||||
return fmt::format("{}{}", configPath, ConfigFileName);
|
||||
return (dusk::ConfigPath / ConfigFileName).string();
|
||||
}
|
||||
|
||||
ConfigVarBase::ConfigVarBase(const char* name, const ConfigImplBase* impl) : name(name), registered(false), layer(ConfigVarLayer::Default), impl(impl) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "dusk/app_info.hpp"
|
||||
#include "dusk/dusk.h"
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "version.h"
|
||||
|
||||
@@ -66,7 +67,7 @@ std::string GetReleaseName() {
|
||||
}
|
||||
|
||||
std::filesystem::path GetSentryDatabasePath() {
|
||||
return std::filesystem::path(configPath) / "sentry";
|
||||
return dusk::ConfigPath / "sentry";
|
||||
}
|
||||
|
||||
std::filesystem::path GetLogAttachmentPath() {
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
#ifdef DUSK_DISCORD_RPC
|
||||
|
||||
#include "dusk/discord_presence.hpp"
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/map_loader_definitions.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "discord_rpc.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace dusk {
|
||||
namespace discord {
|
||||
|
||||
static int64_t g_startTime = 0;
|
||||
static bool g_initialized = false;
|
||||
static const char* APPLICATION_ID = "1495632471994405035";
|
||||
|
||||
static void OnReady(const DiscordUser* user) {
|
||||
DuskLog.info("Discord: Connected as {}", user->username);
|
||||
}
|
||||
|
||||
static void OnDisconnected(int errorCode, const char* message) {
|
||||
DuskLog.warn("Discord: Disconnected ({}: {})", errorCode, message);
|
||||
}
|
||||
|
||||
static void OnError(int errorCode, const char* message) {
|
||||
DuskLog.warn("Discord: Error ({}: {})", errorCode, message);
|
||||
}
|
||||
|
||||
static const char* LookupMapName(const char* mapFile) {
|
||||
if (!mapFile || mapFile[0] == '\0') return nullptr;
|
||||
for (const auto& region : gameRegions) {
|
||||
for (const auto& map : region.maps) {
|
||||
if (map.mapFile && strcmp(mapFile, map.mapFile) == 0) {
|
||||
return map.mapName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
g_startTime = static_cast<int64_t>(
|
||||
std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()
|
||||
).count()
|
||||
);
|
||||
|
||||
DiscordEventHandlers handlers{};
|
||||
handlers.ready = OnReady;
|
||||
handlers.disconnected = OnDisconnected;
|
||||
handlers.errored = OnError;
|
||||
Discord_Initialize(APPLICATION_ID, &handlers, 0, nullptr);
|
||||
g_initialized = true;
|
||||
|
||||
DuskLog.info("Discord Rich Presence initialized");
|
||||
}
|
||||
|
||||
void RunCallbacks() {
|
||||
if (!g_initialized) return;
|
||||
Discord_RunCallbacks();
|
||||
}
|
||||
|
||||
void UpdatePresence() {
|
||||
if (!g_initialized) return;
|
||||
|
||||
static auto lastUpdate = std::chrono::steady_clock::time_point{};
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
if (now - lastUpdate < std::chrono::seconds(15)) return;
|
||||
lastUpdate = now;
|
||||
|
||||
static std::string detailsBuf;
|
||||
static std::string stateBuf;
|
||||
|
||||
DiscordRichPresence presence{};
|
||||
presence.startTimestamp = g_startTime;
|
||||
presence.largeImageKey = "icon";
|
||||
presence.largeImageText = "Dusk";
|
||||
|
||||
if (dusk::IsGameLaunched) {
|
||||
const char* stageName = dComIfGp_getLastPlayStageName();
|
||||
|
||||
// stageName is empty until a room is actually entered
|
||||
if (stageName[0] != '\0') {
|
||||
const char* locationName = LookupMapName(stageName);
|
||||
|
||||
if (locationName) {
|
||||
detailsBuf = locationName;
|
||||
}
|
||||
else {
|
||||
detailsBuf = "Twilight Princess";
|
||||
}
|
||||
|
||||
presence.details = detailsBuf.c_str();
|
||||
|
||||
stateBuf = fmt::format(FMT_STRING("{}/{} \u2665 | {} Rupees"),
|
||||
dComIfGs_getLife() / 4, dComIfGs_getMaxLife() / 5, dComIfGs_getRupee());
|
||||
|
||||
presence.state = stateBuf.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
Discord_UpdatePresence(&presence);
|
||||
DuskLog.debug("Discord Rich Presence sent");
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
if (!g_initialized) return;
|
||||
Discord_ClearPresence();
|
||||
Discord_Shutdown();
|
||||
g_initialized = false;
|
||||
DuskLog.info("Discord Rich Presence shut down");
|
||||
}
|
||||
|
||||
} // namespace discord
|
||||
} // namespace dusk
|
||||
|
||||
#endif // DUSK_DISCORD_RPC
|
||||
@@ -1,63 +1,16 @@
|
||||
#include "dusk/frame_interpolation.h"
|
||||
|
||||
#include <memory>
|
||||
#include "mtx.h"
|
||||
#include "f_op/f_op_camera_mng.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
|
||||
namespace {
|
||||
enum class Op : uint8_t {
|
||||
OpenChild,
|
||||
FinalMtx,
|
||||
};
|
||||
|
||||
struct Label {
|
||||
const void* key = nullptr;
|
||||
int32_t id = 0;
|
||||
|
||||
bool operator==(const Label& other) const {
|
||||
return key == other.key && id == other.id;
|
||||
}
|
||||
};
|
||||
|
||||
struct Data {
|
||||
Label child_label{};
|
||||
size_t child_index = 0;
|
||||
Mtx matrix{};
|
||||
const Mtx* dest = nullptr;
|
||||
uint64_t stable_tag = 0;
|
||||
};
|
||||
|
||||
struct Path;
|
||||
|
||||
struct ChildBucket {
|
||||
Label label{};
|
||||
std::vector<std::unique_ptr<Path>> nodes;
|
||||
};
|
||||
|
||||
struct OpBucket {
|
||||
Op op = Op::OpenChild;
|
||||
std::vector<Data> values;
|
||||
};
|
||||
|
||||
struct Path {
|
||||
std::vector<ChildBucket> children;
|
||||
std::vector<OpBucket> ops;
|
||||
std::vector<std::pair<Op, size_t>> items;
|
||||
Label draw_scope{};
|
||||
uint32_t simple_shadow_pair_seq = 0;
|
||||
};
|
||||
|
||||
struct Recording {
|
||||
Path root;
|
||||
std::unordered_map<uintptr_t, Mtx> matrix_values;
|
||||
};
|
||||
|
||||
struct MatrixValue {
|
||||
Mtx value;
|
||||
};
|
||||
|
||||
using FinalMtxLookup = std::unordered_map<const Mtx*, const Data*>;
|
||||
using FinalMtxLookupTagged = std::unordered_map<uint64_t, const Data*>;
|
||||
|
||||
bool s_initialized = false;
|
||||
|
||||
bool g_enabled = false;
|
||||
@@ -66,13 +19,13 @@ bool g_interpolating = false;
|
||||
bool g_sync_presentation = false;
|
||||
|
||||
float g_step = 0.0f;
|
||||
bool g_is_sim_frame = false;
|
||||
bool g_ui_tick_pending = false;
|
||||
|
||||
Recording g_current_recording;
|
||||
Recording g_previous_recording;
|
||||
std::vector<Path*> g_current_path;
|
||||
|
||||
std::unordered_map<const Mtx*, MatrixValue> g_replacements;
|
||||
std::unordered_map<uintptr_t, Mtx> g_replacements;
|
||||
|
||||
struct CameraSnapshot {
|
||||
cXyz eye{};
|
||||
@@ -93,6 +46,13 @@ CameraSnapshot s_cam_curr{};
|
||||
view_class s_presentation_view_backup{};
|
||||
int s_presentation_depth = 0;
|
||||
|
||||
struct InterpolationCallBackWork {
|
||||
dusk::frame_interp::InterpolationCallBack pCallBack;
|
||||
void* pUserWork;
|
||||
};
|
||||
|
||||
std::vector<InterpolationCallBackWork> s_interpolationCallBackWork;
|
||||
|
||||
void copy_view_to_snap(CameraSnapshot* dst, const view_class& v) {
|
||||
dst->eye = v.lookat.eye;
|
||||
dst->center = v.lookat.center;
|
||||
@@ -105,14 +65,6 @@ void copy_view_to_snap(CameraSnapshot* dst, const view_class& v) {
|
||||
dst->valid = true;
|
||||
}
|
||||
|
||||
inline void copy_matrix(const Mtx src, Mtx dst) {
|
||||
MTXCopy(src, dst);
|
||||
}
|
||||
|
||||
inline void concat_matrix(const Mtx lhs, const Mtx rhs, Mtx out) {
|
||||
MTXConcat(lhs, rhs, out);
|
||||
}
|
||||
|
||||
inline void lerp_matrix(Mtx out, const Mtx lhs, const Mtx rhs, float step) {
|
||||
const float old_weight = 1.0f - step;
|
||||
for (size_t row = 0; row < 3; ++row) {
|
||||
@@ -146,162 +98,22 @@ inline bool matrix_differs(const Mtx lhs, const Mtx rhs, float epsilon = 0.0001f
|
||||
return false;
|
||||
}
|
||||
|
||||
Data& append_op(Op op) {
|
||||
auto& items = g_current_path.back()->items;
|
||||
auto& buckets = g_current_path.back()->ops;
|
||||
auto it = std::find_if(buckets.begin(), buckets.end(),
|
||||
[op](const OpBucket& bucket) { return bucket.op == op; });
|
||||
if (it == buckets.end()) {
|
||||
buckets.push_back({op, {}});
|
||||
it = buckets.end() - 1;
|
||||
}
|
||||
items.emplace_back(op, it->values.size());
|
||||
return it->values.emplace_back();
|
||||
}
|
||||
|
||||
const Data* find_matching_data(const Path& path, Op op, size_t index) {
|
||||
auto it = std::find_if(path.ops.begin(), path.ops.end(),
|
||||
[op](const OpBucket& bucket) { return bucket.op == op; });
|
||||
if (it == path.ops.end() || index >= it->values.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &it->values[index];
|
||||
}
|
||||
|
||||
const OpBucket* find_op_bucket(const Path& path, Op op) {
|
||||
auto it = std::find_if(path.ops.begin(), path.ops.end(),
|
||||
[op](const OpBucket& bucket) { return bucket.op == op; });
|
||||
if (it == path.ops.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &*it;
|
||||
}
|
||||
|
||||
void build_final_mtx_lookups(const Path& path, FinalMtxLookup& dest_lookup, FinalMtxLookupTagged& tag_lookup) {
|
||||
dest_lookup.clear();
|
||||
tag_lookup.clear();
|
||||
|
||||
const OpBucket* bucket = find_op_bucket(path, Op::FinalMtx);
|
||||
if (bucket == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const Data& data : bucket->values) {
|
||||
if (data.dest != nullptr) {
|
||||
dest_lookup[data.dest] = &data;
|
||||
}
|
||||
if (data.stable_tag != 0) {
|
||||
tag_lookup[data.stable_tag] = &data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Data* find_matching_final_mtx(const FinalMtxLookup& lookup, const Data& new_data) {
|
||||
if (new_data.dest == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto it = lookup.find(new_data.dest);
|
||||
if (it == lookup.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
ChildBucket& get_child_bucket(Path& path, const Label& label) {
|
||||
auto it = std::find_if(path.children.begin(), path.children.end(),
|
||||
[&label](const ChildBucket& bucket) { return bucket.label == label; });
|
||||
if (it == path.children.end()) {
|
||||
path.children.push_back({});
|
||||
it = path.children.end() - 1;
|
||||
it->label = label;
|
||||
}
|
||||
return *it;
|
||||
}
|
||||
|
||||
const ChildBucket* find_child_bucket(const Path& path, const Label& label) {
|
||||
auto it = std::find_if(path.children.begin(), path.children.end(),
|
||||
[&label](const ChildBucket& bucket) { return bucket.label == label; });
|
||||
if (it == path.children.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &*it;
|
||||
}
|
||||
|
||||
void store_replacement(const Data& old_data, const Data& new_data, float step) {
|
||||
if (new_data.dest == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& replacement = g_replacements[new_data.dest];
|
||||
lerp_matrix(replacement.value, old_data.matrix, new_data.matrix, step);
|
||||
}
|
||||
|
||||
void interpolate_branch(const Path& old_path, const Path& new_path, float step) {
|
||||
FinalMtxLookup old_final_mtx_lookup;
|
||||
FinalMtxLookupTagged old_final_mtx_lookup_tagged;
|
||||
build_final_mtx_lookups(old_path, old_final_mtx_lookup, old_final_mtx_lookup_tagged);
|
||||
|
||||
for (const auto& item : new_path.items) {
|
||||
const Op op = item.first;
|
||||
const size_t index = item.second;
|
||||
const Data* new_data = find_matching_data(new_path, op, index);
|
||||
if (new_data == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (op == Op::OpenChild) {
|
||||
const ChildBucket* new_children = find_child_bucket(new_path, new_data->child_label);
|
||||
if (new_children == nullptr || new_data->child_index >= new_children->nodes.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const Path& new_child = *new_children->nodes[new_data->child_index];
|
||||
const ChildBucket* old_children = find_child_bucket(old_path, new_data->child_label);
|
||||
if (old_children != nullptr && new_data->child_index < old_children->nodes.size())
|
||||
{
|
||||
interpolate_branch(*old_children->nodes[new_data->child_index], new_child, step);
|
||||
} else {
|
||||
interpolate_branch(new_child, new_child, step);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const Data* indexed_old_data = find_matching_data(old_path, op, index);
|
||||
const Data* old_data = nullptr;
|
||||
if (op == Op::FinalMtx) {
|
||||
if (new_data->stable_tag != 0) {
|
||||
const auto it = old_final_mtx_lookup_tagged.find(new_data->stable_tag);
|
||||
old_data = it != old_final_mtx_lookup_tagged.end() ? it->second : nullptr;
|
||||
} else {
|
||||
old_data = find_matching_final_mtx(old_final_mtx_lookup, *new_data);
|
||||
}
|
||||
} else {
|
||||
old_data = indexed_old_data;
|
||||
}
|
||||
if (op == Op::FinalMtx) {
|
||||
store_replacement(old_data != nullptr ? *old_data : *new_data, *new_data, step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Mtx* resolve_replacement(const Mtx* source, Mtx* scratch) {
|
||||
if (!g_interpolating || source == nullptr || dusk::frame_interp::presentation_sync_active()) {
|
||||
return source;
|
||||
}
|
||||
|
||||
auto it = g_replacements.find(source);
|
||||
auto it = g_replacements.find(reinterpret_cast<uintptr_t>(source));
|
||||
if (it == g_replacements.end()) {
|
||||
return source;
|
||||
}
|
||||
|
||||
copy_matrix(it->second.value, *scratch);
|
||||
MTXCopy(it->second, *scratch);
|
||||
return scratch;
|
||||
}
|
||||
|
||||
bool has_recording_data(const Recording& recording) {
|
||||
return !recording.root.items.empty() || !recording.root.children.empty();
|
||||
return !recording.matrix_values.empty();
|
||||
}
|
||||
|
||||
void clear_replacements() {
|
||||
@@ -312,10 +124,27 @@ void clear_replacements() {
|
||||
|
||||
namespace dusk::frame_interp {
|
||||
void ensure_initialized() {
|
||||
g_enabled = getSettings().game.enableFrameInterpolation;
|
||||
s_initialized = true;
|
||||
}
|
||||
|
||||
void begin_frame(bool enabled, bool is_sim_frame, float step) {
|
||||
g_enabled = enabled;
|
||||
g_is_sim_frame = is_sim_frame;
|
||||
g_step = std::clamp(step, 0.0f, 1.0f);
|
||||
if (is_sim_frame) {
|
||||
s_interpolationCallBackWork.clear();
|
||||
s_cam_prev = std::move(s_cam_curr);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_enabled() {
|
||||
return g_enabled;
|
||||
}
|
||||
|
||||
bool is_sim_frame() {
|
||||
return g_is_sim_frame;
|
||||
}
|
||||
|
||||
void begin_record() {
|
||||
ensure_initialized();
|
||||
|
||||
@@ -324,7 +153,6 @@ void begin_record() {
|
||||
g_sync_presentation = false;
|
||||
g_previous_recording = {};
|
||||
g_current_recording = {};
|
||||
g_current_path.clear();
|
||||
clear_replacements();
|
||||
s_cam_prev.valid = false;
|
||||
s_cam_curr.valid = false;
|
||||
@@ -334,8 +162,6 @@ void begin_record() {
|
||||
g_sync_presentation = false;
|
||||
g_previous_recording = std::move(g_current_recording);
|
||||
g_current_recording = {};
|
||||
g_current_path.clear();
|
||||
g_current_path.push_back(&g_current_recording.root);
|
||||
g_recording = true;
|
||||
g_interpolating = false;
|
||||
clear_replacements();
|
||||
@@ -345,11 +171,6 @@ void begin_record() {
|
||||
s_cam_prev.valid = false;
|
||||
s_cam_curr.valid = false;
|
||||
return;
|
||||
} else {
|
||||
copy_view_to_snap(&s_cam_prev, cam->view);
|
||||
#if WIDESCREEN_SUPPORT
|
||||
s_cam_prev.wideZoom = s_cam_curr.valid ? s_cam_curr.wideZoom : false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,16 +178,20 @@ void end_record() {
|
||||
g_recording = false;
|
||||
}
|
||||
|
||||
void interpolate(float step) {
|
||||
void interpolate() {
|
||||
ensure_initialized();
|
||||
clear_replacements();
|
||||
g_step = std::clamp(step, 0.0f, 1.0f);
|
||||
g_interpolating = g_enabled && !g_recording && !g_sync_presentation && has_recording_data(g_current_recording);
|
||||
if (!g_interpolating) {
|
||||
return;
|
||||
}
|
||||
const Path& old_root = has_recording_data(g_previous_recording) ? g_previous_recording.root : g_current_recording.root;
|
||||
interpolate_branch(old_root, g_current_recording.root, g_step);
|
||||
for (auto const& old : g_previous_recording.matrix_values) {
|
||||
if (auto it = g_current_recording.matrix_values.find(old.first);
|
||||
it != g_current_recording.matrix_values.end())
|
||||
{
|
||||
lerp_matrix(g_replacements[old.first], old.second, it->second, g_step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void request_presentation_sync() {
|
||||
@@ -399,63 +224,30 @@ bool get_ui_tick_pending() {
|
||||
return g_enabled ? g_ui_tick_pending : true;
|
||||
}
|
||||
|
||||
void open_child(const void* key, int32_t id) {
|
||||
if (!s_initialized || !g_recording) {
|
||||
void record_final_mtx(Mtx m, const void* key) {
|
||||
if (!s_initialized || !g_recording || m == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Label label{key, id};
|
||||
auto& siblings = get_child_bucket(*g_current_path.back(), label).nodes;
|
||||
Data& data = append_op(Op::OpenChild);
|
||||
data.child_label = label;
|
||||
data.child_index = siblings.size();
|
||||
siblings.emplace_back(std::make_unique<Path>());
|
||||
Path* const child = siblings.back().get();
|
||||
child->draw_scope = label;
|
||||
g_current_path.push_back(child);
|
||||
auto& it = g_current_recording.matrix_values[reinterpret_cast<uintptr_t>(key)];
|
||||
MTXCopy(m, it);
|
||||
}
|
||||
|
||||
void close_child() {
|
||||
if (!s_initialized || !g_recording || g_current_path.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_current_path.pop_back();
|
||||
void record_final_mtx(Mtx m) {
|
||||
record_final_mtx(m, m);
|
||||
}
|
||||
|
||||
void record_final_mtx_raw(const Mtx* dest, const Mtx src) {
|
||||
if (!s_initialized || !g_recording || dest == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Data& data = append_op(Op::FinalMtx);
|
||||
data.dest = dest;
|
||||
data.stable_tag = 0;
|
||||
copy_matrix(src, data.matrix);
|
||||
}
|
||||
|
||||
void record_final_mtx_raw_tagged(const Mtx* dest, const Mtx src, uint64_t stable_tag) {
|
||||
if (!s_initialized || !g_recording || dest == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Data& data = append_op(Op::FinalMtx);
|
||||
data.dest = dest;
|
||||
data.stable_tag = stable_tag;
|
||||
copy_matrix(src, data.matrix);
|
||||
}
|
||||
|
||||
bool lookup_replacement(const void* source, Mtx out) {
|
||||
if (presentation_sync_active() || !g_interpolating || source == nullptr) {
|
||||
bool lookup_replacement(const void* key, Mtx out) {
|
||||
if (presentation_sync_active() || !g_interpolating || key == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto it = g_replacements.find(reinterpret_cast<const Mtx*>(source));
|
||||
auto it = g_replacements.find(reinterpret_cast<uintptr_t>(key));
|
||||
if (it == g_replacements.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
copy_matrix(it->second.value, out);
|
||||
MTXCopy(it->second, out);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -472,7 +264,7 @@ bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out) {
|
||||
return false;
|
||||
}
|
||||
|
||||
concat_matrix(*resolved_lhs, *resolved_rhs, out);
|
||||
MTXConcat(*resolved_lhs, *resolved_rhs, out);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -486,25 +278,12 @@ void record_camera(::camera_process_class* cam, int camera_id) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void begin_presentation_camera() {
|
||||
ensure_initialized();
|
||||
if (!g_enabled) {
|
||||
void interp_view(::view_class* view) {
|
||||
if (!g_enabled)
|
||||
return;
|
||||
}
|
||||
if (s_presentation_depth > 0) {
|
||||
s_presentation_depth++;
|
||||
return;
|
||||
}
|
||||
if (!s_cam_prev.valid || !s_cam_curr.valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
view_class* const view = dComIfGd_getView();
|
||||
if (view == nullptr) {
|
||||
if (!s_cam_prev.valid || !s_cam_curr.valid)
|
||||
return;
|
||||
}
|
||||
|
||||
std::memcpy(&s_presentation_view_backup, view, sizeof(view_class));
|
||||
|
||||
const f32 step = get_interpolation_step();
|
||||
cXyz eye;
|
||||
@@ -527,12 +306,52 @@ void begin_presentation_camera() {
|
||||
view->near_ = s_cam_prev.near_ + (s_cam_curr.near_ - s_cam_prev.near_) * step;
|
||||
view->far_ = s_cam_prev.far_ + (s_cam_curr.far_ - s_cam_prev.far_) * step;
|
||||
|
||||
// FRAME INTERP TODO: It might be better if I rewired the game to not clear this flag until the next sim frame, but I don't care enough to right now
|
||||
// FRAME INTERP TODO: It might be better if I rewired the game to not clear this flag until the
|
||||
// next sim frame, but I don't care enough to right now
|
||||
#if WIDESCREEN_SUPPORT
|
||||
if (mDoGph_gInf_c::isWide() && !mDoGph_gInf_c::isWideZoom() && step >= 0.5f ? s_cam_curr.wideZoom : s_cam_prev.wideZoom) {
|
||||
if (mDoGph_gInf_c::isWide() && !mDoGph_gInf_c::isWideZoom() && step >= 0.5f ?
|
||||
s_cam_curr.wideZoom :
|
||||
s_cam_prev.wideZoom)
|
||||
{
|
||||
mDoGph_gInf_c::onWideZoom();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void run_interpolation_callbacks() {
|
||||
for (size_t i = 0; i < s_interpolationCallBackWork.size(); i++) {
|
||||
auto const& work = s_interpolationCallBackWork[i];
|
||||
work.pCallBack(g_is_sim_frame, work.pUserWork);
|
||||
}
|
||||
}
|
||||
|
||||
void add_interpolation_callback(InterpolationCallBack pCallBack, void* pUserWork) {
|
||||
if (!is_enabled() || s_presentation_depth > 0 || !g_is_sim_frame)
|
||||
return;
|
||||
|
||||
s_interpolationCallBackWork.emplace_back(pCallBack, pUserWork);
|
||||
}
|
||||
|
||||
void begin_presentation_camera() {
|
||||
ensure_initialized();
|
||||
if (!g_enabled) {
|
||||
return;
|
||||
}
|
||||
if (s_presentation_depth > 0) {
|
||||
s_presentation_depth++;
|
||||
return;
|
||||
}
|
||||
if (!s_cam_prev.valid || !s_cam_curr.valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
view_class* const view = dComIfGd_getView();
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::memcpy(&s_presentation_view_backup, view, sizeof(view_class));
|
||||
interp_view(view);
|
||||
|
||||
// FRAME INTERP TODO: Largely copied from d_camera's camera_draw function from this point, got any better ideas?
|
||||
C_MTXPerspective(view->projMtx, view->fovy, view->aspect, view->near_, view->far_);
|
||||
@@ -590,11 +409,11 @@ void begin_presentation_camera() {
|
||||
|
||||
mDoLib_clipper::setup(view->fovy, view->aspect, view->near_, far_);
|
||||
|
||||
#if WIDESCREEN_SUPPORT
|
||||
mDoGph_gInf_c::offWideZoom();
|
||||
#endif
|
||||
// FRAME INTERP NOTE: Removed the call to offWideZoom that was here, it causes problems with presentation during cutscenes.
|
||||
|
||||
s_presentation_depth = 1;
|
||||
|
||||
run_interpolation_callbacks();
|
||||
}
|
||||
|
||||
void end_presentation_camera() {
|
||||
@@ -611,20 +430,4 @@ void end_presentation_camera() {
|
||||
std::memcpy(view, &s_presentation_view_backup, sizeof(view_class));
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t alloc_simple_shadow_pair_base() {
|
||||
if (!s_initialized || !g_recording || g_current_path.size() <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Path* const scope = g_current_path.back();
|
||||
const uint64_t h = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(scope->draw_scope.key));
|
||||
const uint32_t lo = scope->simple_shadow_pair_seq;
|
||||
scope->simple_shadow_pair_seq += 2;
|
||||
uint64_t tag0 = (h << 17) ^ (static_cast<uint64_t>(lo) << 1u);
|
||||
if (tag0 == 0) {
|
||||
tag0 = 2;
|
||||
}
|
||||
return tag0;
|
||||
}
|
||||
} // namespace dusk::frame_interp
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace dusk {
|
||||
@@ -26,6 +27,11 @@ void ensure_initialized() {
|
||||
|
||||
void reset_accumulator() {
|
||||
ensure_initialized();
|
||||
s_sim_accumulator = fmodf(s_sim_accumulator, sim_pace());
|
||||
}
|
||||
|
||||
void reset_frame_timer() {
|
||||
s_previous_sample = clock::now();
|
||||
s_sim_accumulator = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,10 @@ namespace dusk {
|
||||
ImGui::SeparatorText("Free-look Data");
|
||||
|
||||
static float eyeYawDeg = 0.0f;
|
||||
static float moveSpeed = 10000.0f;
|
||||
static float moveSpeed = 5000.0f;
|
||||
static float rotSpeed = 5.0f;
|
||||
static cXyz freeLookPos = cXyz::Zero;
|
||||
static bool freeLookActive = false;
|
||||
|
||||
bool changed = false;
|
||||
|
||||
@@ -91,7 +92,17 @@ namespace dusk {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
if (!freeLookActive && changed) {
|
||||
freeLookPos += dCam->Center();
|
||||
freeLookActive = true;
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyDown(ImGuiKey_R)) {
|
||||
freeLookPos = cXyz::Zero;
|
||||
freeLookActive = false;
|
||||
}
|
||||
|
||||
if (freeLookActive) {
|
||||
dCam->Reset(freeLookPos, freeLookPos + (frontDir * 100.0f));
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "dusk/audio/DuskAudioSystem.h"
|
||||
#include "dusk/config.hpp"
|
||||
#include "dusk/dusk.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
@@ -281,7 +282,7 @@ namespace dusk {
|
||||
void ImGuiConsole::UpdateSettings() {
|
||||
getTransientSettings().skipFrameRateLimit = getSettings().game.enableTurboKeybind && ImGui::IsKeyDown(ImGuiKey_Tab);
|
||||
|
||||
if (mDoMain::developmentMode == 1 && (mDoCPd_c::getHold(PAD_1) & (PAD_TRIGGER_R | PAD_TRIGGER_L)) == (PAD_TRIGGER_R | PAD_TRIGGER_L) && mDoCPd_c::getTrigY(PAD_1)) {
|
||||
if (dusk::frame_interp::get_ui_tick_pending() && mDoMain::developmentMode == 1 && (mDoCPd_c::getHold(PAD_1) & (PAD_TRIGGER_R | PAD_TRIGGER_L)) == (PAD_TRIGGER_R | PAD_TRIGGER_L) && mDoCPd_c::getTrigY(PAD_1)) {
|
||||
getTransientSettings().moveLinkActive = !getTransientSettings().moveLinkActive;
|
||||
}
|
||||
if (mDoMain::developmentMode != 1) {
|
||||
@@ -318,9 +319,11 @@ namespace dusk {
|
||||
}
|
||||
}
|
||||
|
||||
// The menu bar renders with ImGuiCol_WindowBg behind it. We just want ImGuiCol_MenuBarBg,
|
||||
// so make the window bg fully transparent temporarily
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
if (showMenu && ImGui::BeginMainMenuBar()) {
|
||||
m_menuGame.draw();
|
||||
m_menuEnhancements.draw();
|
||||
m_menuTools.draw();
|
||||
|
||||
const auto fpsLabel =
|
||||
@@ -335,6 +338,7 @@ namespace dusk {
|
||||
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
if (!getSettings().backend.wasPresetChosen) {
|
||||
m_firstRunPreset.draw();
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <SDL3/SDL_touch.h>
|
||||
|
||||
#include "ImGuiFirstRunPreset.hpp"
|
||||
#include "ImGuiMenuEnhancements.hpp"
|
||||
#include "ImGuiMenuGame.hpp"
|
||||
#include "ImGuiMenuTools.hpp"
|
||||
#include "ImGuiPreLaunchWindow.hpp"
|
||||
@@ -52,7 +51,6 @@ private:
|
||||
|
||||
ImGuiFirstRunPreset m_firstRunPreset;
|
||||
ImGuiMenuGame m_menuGame;
|
||||
ImGuiMenuEnhancements m_menuEnhancements;
|
||||
ImGuiPreLaunchWindow m_preLaunchWindow;
|
||||
|
||||
// Keep always last
|
||||
|
||||
@@ -126,7 +126,7 @@ void ImGuiEngine_Initialize(float scale) {
|
||||
auto* colors = style.Colors;
|
||||
colors[ImGuiCol_Text] = ImVec4(0.95f, 0.96f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_TextDisabled] = ImVec4(0.36f, 0.42f, 0.47f, 1.00f);
|
||||
colors[ImGuiCol_WindowBg] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_WindowBg] = ImVec4(0.11f, 0.15f, 0.17f, 0.98f);
|
||||
colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
|
||||
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
|
||||
colors[ImGuiCol_Border] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
|
||||
@@ -137,7 +137,7 @@ void ImGuiEngine_Initialize(float scale) {
|
||||
colors[ImGuiCol_TitleBg] = ImVec4(0.09f, 0.12f, 0.14f, 0.65f);
|
||||
colors[ImGuiCol_TitleBgActive] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
|
||||
colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
|
||||
colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 0.80f);
|
||||
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f);
|
||||
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.18f, 0.22f, 0.25f, 1.00f);
|
||||
|
||||
@@ -1,248 +0,0 @@
|
||||
#include "imgui.h"
|
||||
|
||||
#include "ImGuiMenuEnhancements.hpp"
|
||||
#include "ImGuiConfig.hpp"
|
||||
#include "dusk/settings.h"
|
||||
|
||||
namespace dusk {
|
||||
ImGuiMenuEnhancements::ImGuiMenuEnhancements() {}
|
||||
|
||||
void ImGuiMenuEnhancements::draw() {
|
||||
if (ImGui::BeginMenu("Enhancements")) {
|
||||
if (ImGui::BeginMenu("Gameplay")) {
|
||||
ImGui::SeparatorText("Preferences");
|
||||
|
||||
config::ImGuiCheckbox("Mirror Mode", getSettings().game.enableMirrorMode);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Mirrors the world horizontally, matching the Wii version of the game.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Disable Main HUD", getSettings().game.disableMainHUD);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Disables the main HUD of the game.\n"
|
||||
"Useful for recording or a more immersive experience!");
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Difficulty");
|
||||
|
||||
config::ImGuiSliderInt("Damage Multiplier", getSettings().game.damageMultiplier, 1, 8, "x%d");
|
||||
|
||||
config::ImGuiCheckbox("Instant Death", getSettings().game.instantDeath);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Any hit will instantly kill you.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Heart Drops", getSettings().game.noHeartDrops);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Hearts will never drop from enemies,\n"
|
||||
"pots and various other places.");
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Quality of Life");
|
||||
|
||||
config::ImGuiCheckbox("Bigger Wallets", getSettings().game.biggerWallets);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Wallet sizes are like in the HD version. (500, 1000, 2000)");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Disable Rupee Cutscenes", getSettings().game.disableRupeeCutscenes);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Rupees won't play cutscenes after you've collected them the first time.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Faster Climbing", getSettings().game.fastClimbing);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Quicker climbing on ladders and vines like the HD version.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Faster Tears of Light", getSettings().game.fastTears);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Tears of Light dropped by Shadow Insects pop out faster like the HD version.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Instant Saves", getSettings().game.instantSaves);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Skip the delay when writing to the Memory Card.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Hold B for Instant Text", getSettings().game.instantText);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Make text scroll immediately by holding B.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Climbing Miss Animation", getSettings().game.noMissClimbing);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Prevents Link from playing a struggle animation\n"
|
||||
"when grabbing ledges or climbing on vines.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Rupee Returns", getSettings().game.noReturnRupees);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Always collect Rupees even if your Wallet is too full.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Sword Recoil", getSettings().game.noSwordRecoil);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Link won't recoil when his sword hits walls.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Skip TV Settings Screen", getSettings().game.hideTvSettingsScreen);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Skip the TV calibration screen shown when loading a save.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Skip Warning Screen", getSettings().game.skipWarningScreen);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Skip the warning screen shown when starting the game.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Sun's Song (R+X)", getSettings().game.sunsSong);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Allows Wolf Link to howl and change the time of day.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Quick Transform (R+Y)", getSettings().game.enableQuickTransform);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Transform instantly by pressing R and Y simultaneously.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Graphics")) {
|
||||
config::ImGuiSliderInt("Shadow Resolution", getSettings().game.shadowResolutionMultiplier, 1, 8, "x%d");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Improves the shadow resolution, making them higher quality.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Unlock Framerate", getSettings().game.enableFrameInterpolation);
|
||||
const bool frameInterpolationHovered = ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.72f, 0.2f, 1.0f));
|
||||
ImGui::TextUnformatted("[EXPERIMENTAL]");
|
||||
ImGui::PopStyleColor();
|
||||
if (frameInterpolationHovered || ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Uses inter-frame interpolation to enable higher frame rates.\nVisual artifacts, animation glitches, or instability may occur.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Audio")) {
|
||||
config::ImGuiCheckbox("No Low HP Sound", getSettings().game.noLowHpSound);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Disable the beeping sound when having low health.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Non-Stop Midna's Lament", getSettings().game.midnasLamentNonStop);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Prevents enemy music while Midna's Lament is playing.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Input")) {
|
||||
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
|
||||
|
||||
ImGui::SeparatorText("Gyro");
|
||||
|
||||
config::ImGuiCheckbox("Gyro Aim", getSettings().game.enableGyroAim);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Enables the gyroscope on supported controllers\n"
|
||||
"while in look mode (C-Up) and while aiming the\n"
|
||||
"Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s),\n"
|
||||
"Ball and Chain, and Dominion Rod.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Gyro Rollgoal", getSettings().game.enableGyroRollgoal);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Enables the gyroscope on supported controllers to\n"
|
||||
"tilt the Rollgoal table in Hena's Cabin.");
|
||||
}
|
||||
|
||||
if (getSettings().game.enableGyroAim || getSettings().game.enableGyroRollgoal) {
|
||||
config::ImGuiSliderFloat("Gyro Pitch Sensitivity", getSettings().game.gyroSensitivityY, 0.25f, 4.0f, "%.2f");
|
||||
config::ImGuiSliderFloat("Gyro Yaw Sensitivity", getSettings().game.gyroSensitivityX, 0.25f, 4.0f, "%.2f");
|
||||
|
||||
if (getSettings().game.enableGyroRollgoal) {
|
||||
config::ImGuiSliderFloat("Rollgoal Sensitivity", getSettings().game.gyroSensitivityRollgoal, 0.25f, 4.0f, "%.2f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Additional multiplier for scaling how strongly\n"
|
||||
"the gyroscope affects the Rollgoal table.");
|
||||
}
|
||||
}
|
||||
|
||||
config::ImGuiSliderFloat("Gyro Deadband", getSettings().game.gyroDeadband, 0.0f, 0.5f, "%.3f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Angular rates below this magnitude are treated as zero,\n"
|
||||
"reducing drift and jitter when the controller is still.");
|
||||
}
|
||||
|
||||
config::ImGuiSliderFloat("Gyro Smoothing", getSettings().game.gyroSmoothing, 0.0f, 1.0f, "%.2f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Low values track raw gyro input more closely,\n"
|
||||
"while higher values smooth out input over time.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Invert Gyro Pitch", getSettings().game.gyroInvertPitch);
|
||||
config::ImGuiCheckbox("Invert Gyro Yaw", getSettings().game.gyroInvertYaw);
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Tools");
|
||||
|
||||
config::ImGuiCheckbox("Turbo Key", getSettings().game.enableTurboKeybind);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Hold TAB to increase game speed by up to 4x.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginMenu("Cheats")) {
|
||||
config::ImGuiCheckbox("Infinite Hearts", getSettings().game.infiniteHearts);
|
||||
config::ImGuiCheckbox("Infinite Arrows", getSettings().game.infiniteArrows);
|
||||
config::ImGuiCheckbox("Infinite Bombs", getSettings().game.infiniteBombs);
|
||||
config::ImGuiCheckbox("Infinite Oil", getSettings().game.infiniteOil);
|
||||
config::ImGuiCheckbox("Infinite Oxygen", getSettings().game.infiniteOxygen);
|
||||
config::ImGuiCheckbox("Infinite Rupees", getSettings().game.infiniteRupees);
|
||||
config::ImGuiCheckbox("Moon Jump (R+A)", getSettings().game.moonJump);
|
||||
config::ImGuiCheckbox("Super Clawshot", getSettings().game.superClawshot);
|
||||
config::ImGuiCheckbox("Always Greatspin", getSettings().game.alwaysGreatspin);
|
||||
|
||||
config::ImGuiCheckbox("Fast Iron Boots", getSettings().game.enableFastIronBoots);
|
||||
|
||||
config::ImGuiCheckbox("Can Transform Anywhere", getSettings().game.canTransformAnywhere);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Allows you to transform even if NPCs are looking.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Fast Spinner", getSettings().game.fastSpinner);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Speeds up Spinner movement when holding R.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Free Magic Armor", getSettings().game.freeMagicArmor);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Makes the magic armor work without rupees.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Technical")) {
|
||||
config::ImGuiCheckbox("Restore Wii 1.0 Glitches", getSettings().game.restoreWiiGlitches);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Restores patched glitches from Wii USA 1.0,\n"
|
||||
"the first released version.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#ifndef DUSK_IMGUI_MENUENHANCEMENTS_HPP
|
||||
#define DUSK_IMGUI_MENUENHANCEMENTS_HPP
|
||||
|
||||
#include <aurora/aurora.h>
|
||||
#include <pad.h>
|
||||
#include <string>
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
namespace dusk {
|
||||
class ImGuiMenuEnhancements {
|
||||
public:
|
||||
ImGuiMenuEnhancements();
|
||||
void draw();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // DUSK_IMGUI_MENUENHANCEMENTS_HPP
|
||||
+385
-170
@@ -5,45 +5,18 @@
|
||||
#include "ImGuiConsole.hpp"
|
||||
#include "ImGuiMenuGame.hpp"
|
||||
#include "ImGuiConfig.hpp"
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include "JSystem/JUtility/JUTGamePad.h"
|
||||
#include "dusk/audio/DuskAudioSystem.h"
|
||||
#include "dusk/audio/DuskDsp.hpp"
|
||||
#include "dusk/dusk.h"
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/hotkeys.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
|
||||
#include <aurora/gfx.h>
|
||||
#include <aurora/lib/logging.hpp>
|
||||
#include <SDL3/SDL_gamepad.h>
|
||||
#include <SDL3/SDL_misc.h>
|
||||
|
||||
#include "dusk/main.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || (defined(__APPLE__) && !TARGET_OS_IOS && !TARGET_OS_MACCATALYST) || (defined(__linux__) && !defined(__ANDROID__))
|
||||
#define DUSK_CAN_OPEN_DATA_FOLDER 1
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static void OpenDataFolder() {
|
||||
const std::string path = fs::absolute(fs::path(aurora::g_config.configPath)).generic_string();
|
||||
#if defined(_WIN32)
|
||||
const std::string url = std::string("file:///") + path;
|
||||
#else
|
||||
const std::string url = std::string("file://") + path;
|
||||
#endif
|
||||
(void)SDL_OpenURL(url.c_str());
|
||||
}
|
||||
#else
|
||||
#define DUSK_CAN_OPEN_DATA_FOLDER 0
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
constexpr int kInternalResolutionScaleMax = 12;
|
||||
@@ -63,148 +36,13 @@ namespace dusk {
|
||||
ImGuiMenuGame::ImGuiMenuGame() {}
|
||||
|
||||
void ImGuiMenuGame::draw() {
|
||||
if (ImGui::BeginMenu("Game")) {
|
||||
if (ImGui::BeginMenu("Graphics")) {
|
||||
if (!IsMobile) {
|
||||
if (ImGui::MenuItem("Toggle Fullscreen", hotkeys::TOGGLE_FULLSCREEN)) {
|
||||
ToggleFullscreen();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Default Window Size")) {
|
||||
getSettings().video.enableFullscreen.setValue(false);
|
||||
VISetWindowFullscreen(false);
|
||||
VISetWindowSize(FB_WIDTH * 2, FB_HEIGHT * 2);
|
||||
VICenterWindow();
|
||||
}
|
||||
}
|
||||
|
||||
bool vsync = getSettings().video.enableVsync;
|
||||
if (ImGui::Checkbox("Enable Vsync", &vsync)) {
|
||||
getSettings().video.enableVsync.setValue(vsync);
|
||||
aurora_enable_vsync(vsync);
|
||||
config::Save();
|
||||
}
|
||||
|
||||
bool lockAspect = getSettings().video.lockAspectRatio;
|
||||
if (ImGui::Checkbox("Force 4:3 Aspect Ratio", &lockAspect)) {
|
||||
getSettings().video.lockAspectRatio.setValue(lockAspect);
|
||||
|
||||
if (lockAspect) {
|
||||
AuroraSetViewportPolicy(AURORA_VIEWPORT_FIT);
|
||||
} else {
|
||||
AuroraSetViewportPolicy(AURORA_VIEWPORT_STRETCH);
|
||||
}
|
||||
|
||||
config::Save();
|
||||
}
|
||||
|
||||
u32 internalResolutionWidth = 0;
|
||||
u32 internalResolutionHeight = 0;
|
||||
AuroraGetRenderSize(&internalResolutionWidth, &internalResolutionHeight);
|
||||
ImGui::TextDisabled("Current internal resolution: %ux%u", internalResolutionWidth,
|
||||
internalResolutionHeight);
|
||||
|
||||
int scale = std::clamp(getSettings().game.internalResolutionScale.getValue(), 0,
|
||||
kInternalResolutionScaleMax);
|
||||
if (ImGui::SliderInt("Internal Resolution", &scale, 0, kInternalResolutionScaleMax,
|
||||
scale == 0 ? "Auto" : "%dx"))
|
||||
{
|
||||
getSettings().game.internalResolutionScale.setValue(scale);
|
||||
VISetFrameBufferScale(static_cast<float>(scale));
|
||||
config::Save();
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Auto renders at the native window resolution.\n"
|
||||
"Higher values scale the game's internal framebuffer.");
|
||||
}
|
||||
|
||||
constexpr const char* bloomModeNames[] = {"Off", "Classic", "Dusk"};
|
||||
int bloomMode = static_cast<int>(getSettings().game.bloomMode.getValue());
|
||||
if (ImGui::BeginCombo("Bloom", bloomModeNames[bloomMode])) {
|
||||
for (int i = 0; i < IM_ARRAYSIZE(bloomModeNames); i++) {
|
||||
const bool selected = bloomMode == i;
|
||||
if (ImGui::Selectable(bloomModeNames[i], selected)) {
|
||||
getSettings().game.bloomMode.setValue(static_cast<BloomMode>(i));
|
||||
config::Save();
|
||||
}
|
||||
if (selected) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
bool bloomOff = bloomMode == static_cast<int>(BloomMode::Off);
|
||||
if (bloomOff) ImGui::BeginDisabled();
|
||||
float mult = getSettings().game.bloomMultiplier.getValue();
|
||||
if (ImGui::SliderFloat("Bloom Brightness", &mult, 0.0f, 1.0f, "%.2f")) {
|
||||
getSettings().game.bloomMultiplier.setValue(mult);
|
||||
config::Save();
|
||||
}
|
||||
if (bloomOff) ImGui::EndDisabled();
|
||||
|
||||
config::ImGuiCheckbox("Enable Water Refraction", getSettings().game.enableWaterRefraction);
|
||||
|
||||
ImGui::Checkbox("Enable LOD Bias", &aurora::gx::enableLodBias);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Audio")) {
|
||||
ImGui::Text("Master Volume");
|
||||
if (config::ImGuiSliderInt("##masterVolume", getSettings().audio.masterVolume, 0, 100)) {
|
||||
dusk::audio::SetMasterVolume(getSettings().audio.masterVolume / 100.0f);
|
||||
}
|
||||
|
||||
if (config::ImGuiCheckbox("Enable Reverb", getSettings().audio.enableReverb)) {
|
||||
dusk::audio::SetEnableReverb(getSettings().audio.enableReverb);
|
||||
}
|
||||
/*
|
||||
// TODO: Implement additional settings
|
||||
ImGui::Text("Main Music Volume");
|
||||
ImGui::SliderFloat("##mainMusicVolume", &getSettings().audio.mainMusicVolume, 0, 100);
|
||||
|
||||
ImGui::Text("Sub Music Volume");
|
||||
ImGui::SliderFloat("##subMusicVolume", &getSettings().audio.subMusicVolume, 0, 100);
|
||||
|
||||
ImGui::Text("Sound Effects Volume");
|
||||
ImGui::SliderFloat("##soundEffectsVolume", &getSettings().audio.soundEffectsVolume, 0, 100);
|
||||
|
||||
ImGui::Text("Fanfare Volume");
|
||||
ImGui::SliderFloat("##fanfareVolume", &getSettings().audio.fanfareVolume, 0, 100);
|
||||
|
||||
Z2AudioMgr* audioMgr = Z2AudioMgr::getInterface();
|
||||
if (audioMgr != nullptr) {
|
||||
}
|
||||
*/
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Controller")) {
|
||||
ImGui::MenuItem("Configure Controller", nullptr, &m_showControllerConfig);
|
||||
ImGui::Checkbox("Show Input Viewer", &m_showInputViewer);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Interface")) {
|
||||
config::ImGuiCheckbox("Skip Pre-Launch UI", getSettings().backend.skipPreLaunchUI);
|
||||
config::ImGuiCheckbox("Show Pipeline Compilation", getSettings().backend.showPipelineCompilation);
|
||||
#if DUSK_ENABLE_SENTRY_NATIVE
|
||||
config::ImGuiCheckbox("Enable Crash Reporting", getSettings().backend.enableCrashReporting);
|
||||
#endif
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
#if DUSK_CAN_OPEN_DATA_FOLDER
|
||||
if (ImGui::MenuItem("Open Data Folder")) {
|
||||
OpenDataFolder();
|
||||
}
|
||||
#endif
|
||||
if (ImGui::BeginMenu("Settings")) {
|
||||
drawAudioMenu();
|
||||
drawCheatsMenu();
|
||||
drawGameplayMenu();
|
||||
drawGraphicsMenu();
|
||||
drawInputMenu();
|
||||
drawInterfaceMenu();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
@@ -220,6 +58,383 @@ namespace dusk {
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawGraphicsMenu() {
|
||||
if (ImGui::BeginMenu("Graphics")) {
|
||||
ImGui::SeparatorText("Display");
|
||||
|
||||
if (!IsMobile) {
|
||||
if (ImGui::MenuItem("Toggle Fullscreen", hotkeys::TOGGLE_FULLSCREEN)) {
|
||||
ToggleFullscreen();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Restore Default Window Size")) {
|
||||
getSettings().video.enableFullscreen.setValue(false);
|
||||
VISetWindowFullscreen(false);
|
||||
VISetWindowSize(FB_WIDTH * 2, FB_HEIGHT * 2);
|
||||
VICenterWindow();
|
||||
}
|
||||
}
|
||||
|
||||
bool vsync = getSettings().video.enableVsync;
|
||||
if (ImGui::Checkbox("Enable VSync", &vsync)) {
|
||||
getSettings().video.enableVsync.setValue(vsync);
|
||||
aurora_enable_vsync(vsync);
|
||||
config::Save();
|
||||
}
|
||||
|
||||
bool lockAspect = getSettings().video.lockAspectRatio;
|
||||
if (ImGui::Checkbox("Force 4:3 Aspect Ratio", &lockAspect)) {
|
||||
getSettings().video.lockAspectRatio.setValue(lockAspect);
|
||||
|
||||
if (lockAspect) {
|
||||
AuroraSetViewportPolicy(AURORA_VIEWPORT_FIT);
|
||||
} else {
|
||||
AuroraSetViewportPolicy(AURORA_VIEWPORT_STRETCH);
|
||||
}
|
||||
|
||||
config::Save();
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Resolution");
|
||||
|
||||
u32 internalResolutionWidth = 0;
|
||||
u32 internalResolutionHeight = 0;
|
||||
AuroraGetRenderSize(&internalResolutionWidth, &internalResolutionHeight);
|
||||
ImGui::TextDisabled("Current internal resolution: %ux%u", internalResolutionWidth,
|
||||
internalResolutionHeight);
|
||||
|
||||
int scale = std::clamp(getSettings().game.internalResolutionScale.getValue(), 0,
|
||||
kInternalResolutionScaleMax);
|
||||
if (ImGui::SliderInt("Internal Resolution", &scale, 0, kInternalResolutionScaleMax,
|
||||
scale == 0 ? "Auto" : "%dx"))
|
||||
{
|
||||
getSettings().game.internalResolutionScale.setValue(scale);
|
||||
VISetFrameBufferScale(static_cast<float>(scale));
|
||||
config::Save();
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Auto renders at the native window resolution.\n"
|
||||
"Higher values scale the game's internal framebuffer.");
|
||||
}
|
||||
|
||||
config::ImGuiSliderInt("Shadow Resolution", getSettings().game.shadowResolutionMultiplier, 1, 8, "x%d");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Improves the shadow resolution, making them higher quality.");
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Post-Processing");
|
||||
|
||||
constexpr const char* bloomModeNames[] = {"Off", "Classic", "Dusk"};
|
||||
int bloomMode = static_cast<int>(getSettings().game.bloomMode.getValue());
|
||||
if (ImGui::BeginCombo("Bloom", bloomModeNames[bloomMode])) {
|
||||
for (int i = 0; i < IM_ARRAYSIZE(bloomModeNames); i++) {
|
||||
const bool selected = bloomMode == i;
|
||||
if (ImGui::Selectable(bloomModeNames[i], selected)) {
|
||||
getSettings().game.bloomMode.setValue(static_cast<BloomMode>(i));
|
||||
config::Save();
|
||||
}
|
||||
if (selected) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
bool bloomOff = bloomMode == static_cast<int>(BloomMode::Off);
|
||||
if (bloomOff) ImGui::BeginDisabled();
|
||||
float mult = getSettings().game.bloomMultiplier.getValue();
|
||||
if (ImGui::SliderFloat("Bloom Brightness", &mult, 0.0f, 1.0f, "%.2f")) {
|
||||
getSettings().game.bloomMultiplier.setValue(mult);
|
||||
config::Save();
|
||||
}
|
||||
if (bloomOff) ImGui::EndDisabled();
|
||||
|
||||
ImGui::SeparatorText("Rendering");
|
||||
|
||||
config::ImGuiCheckbox("Unlock Framerate", getSettings().game.enableFrameInterpolation);
|
||||
const bool frameInterpolationHovered = ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.72f, 0.2f, 1.0f));
|
||||
ImGui::TextUnformatted("[EXPERIMENTAL]");
|
||||
ImGui::PopStyleColor();
|
||||
if (frameInterpolationHovered || ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Uses inter-frame interpolation to enable higher frame rates.\nVisual artifacts, animation glitches, or instability may occur.");
|
||||
}
|
||||
|
||||
ImGui::Checkbox("Enable LOD Bias", &aurora::gx::enableLodBias);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawGameplayMenu() {
|
||||
if (ImGui::BeginMenu("Gameplay")) {
|
||||
ImGui::SeparatorText("General");
|
||||
|
||||
config::ImGuiCheckbox("Mirror Mode", getSettings().game.enableMirrorMode);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Mirrors the world horizontally, matching the Wii version of the game.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Disable Main HUD", getSettings().game.disableMainHUD);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Disables the main HUD of the game.\n"
|
||||
"Useful for recording or a more immersive experience!");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Restore Wii 1.0 Glitches", getSettings().game.restoreWiiGlitches);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Restores patched glitches from Wii USA 1.0,\n"
|
||||
"the first released version.");
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Difficulty");
|
||||
|
||||
config::ImGuiSliderInt("Damage Multiplier", getSettings().game.damageMultiplier, 1, 8, "x%d");
|
||||
|
||||
config::ImGuiCheckbox("Instant Death", getSettings().game.instantDeath);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Any hit will instantly kill you.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Heart Drops", getSettings().game.noHeartDrops);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Hearts will never drop from enemies,\n"
|
||||
"pots and various other places.");
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Quality of Life");
|
||||
|
||||
config::ImGuiCheckbox("Bigger Wallets", getSettings().game.biggerWallets);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Wallet sizes are like in the HD version. (500, 1000, 2000)");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Disable Rupee Cutscenes", getSettings().game.disableRupeeCutscenes);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Rupees won't play cutscenes after you've collected them the first time.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Faster Climbing", getSettings().game.fastClimbing);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Quicker climbing on ladders and vines like the HD version.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Faster Tears of Light", getSettings().game.fastTears);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Tears of Light dropped by Shadow Insects pop out faster like the HD version.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Instant Saves", getSettings().game.instantSaves);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Skip the delay when writing to the Memory Card.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Hold B for Instant Text", getSettings().game.instantText);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Make text scroll immediately by holding B.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Climbing Miss Animation", getSettings().game.noMissClimbing);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Prevents Link from playing a struggle animation\n"
|
||||
"when grabbing ledges or climbing on vines.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Rupee Returns", getSettings().game.noReturnRupees);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Always collect Rupees even if your Wallet is too full.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Sword Recoil", getSettings().game.noSwordRecoil);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Link won't recoil when his sword hits walls.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Skip TV Settings Screen", getSettings().game.hideTvSettingsScreen);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Skip the TV calibration screen shown when loading a save.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Skip Warning Screen", getSettings().game.skipWarningScreen);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Skip the warning screen shown when starting the game.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Sun's Song (R+X)", getSettings().game.sunsSong);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Allows Wolf Link to howl and change the time of day.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Quick Transform (R+Y)", getSettings().game.enableQuickTransform);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Transform instantly by pressing R and Y simultaneously.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawCheatsMenu() {
|
||||
if (ImGui::BeginMenu("Cheats")) {
|
||||
ImGui::SeparatorText("Resources");
|
||||
config::ImGuiCheckbox("Infinite Hearts", getSettings().game.infiniteHearts);
|
||||
config::ImGuiCheckbox("Infinite Arrows", getSettings().game.infiniteArrows);
|
||||
config::ImGuiCheckbox("Infinite Bombs", getSettings().game.infiniteBombs);
|
||||
config::ImGuiCheckbox("Infinite Oil", getSettings().game.infiniteOil);
|
||||
config::ImGuiCheckbox("Infinite Oxygen", getSettings().game.infiniteOxygen);
|
||||
config::ImGuiCheckbox("Infinite Rupees", getSettings().game.infiniteRupees);
|
||||
|
||||
ImGui::SeparatorText("Abilities");
|
||||
config::ImGuiCheckbox("Moon Jump (R+A)", getSettings().game.moonJump);
|
||||
config::ImGuiCheckbox("Super Clawshot", getSettings().game.superClawshot);
|
||||
config::ImGuiCheckbox("Always Greatspin", getSettings().game.alwaysGreatspin);
|
||||
config::ImGuiCheckbox("Fast Iron Boots", getSettings().game.enableFastIronBoots);
|
||||
|
||||
config::ImGuiCheckbox("Can Transform Anywhere", getSettings().game.canTransformAnywhere);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Allows you to transform even if NPCs are looking.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Fast Spinner", getSettings().game.fastSpinner);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Speeds up Spinner movement when holding R.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Free Magic Armor", getSettings().game.freeMagicArmor);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Makes the magic armor work without rupees.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawAudioMenu() {
|
||||
if (ImGui::BeginMenu("Audio")) {
|
||||
ImGui::Text("Master Volume");
|
||||
if (config::ImGuiSliderInt("##masterVolume", getSettings().audio.masterVolume, 0, 100)) {
|
||||
dusk::audio::SetMasterVolume(getSettings().audio.masterVolume / 100.0f);
|
||||
}
|
||||
|
||||
if (config::ImGuiCheckbox("Enable Reverb", getSettings().audio.enableReverb)) {
|
||||
dusk::audio::SetEnableReverb(getSettings().audio.enableReverb);
|
||||
}
|
||||
/*
|
||||
// TODO: Implement additional settings
|
||||
ImGui::Text("Main Music Volume");
|
||||
ImGui::SliderFloat("##mainMusicVolume", &getSettings().audio.mainMusicVolume, 0, 100);
|
||||
|
||||
ImGui::Text("Sub Music Volume");
|
||||
ImGui::SliderFloat("##subMusicVolume", &getSettings().audio.subMusicVolume, 0, 100);
|
||||
|
||||
ImGui::Text("Sound Effects Volume");
|
||||
ImGui::SliderFloat("##soundEffectsVolume", &getSettings().audio.soundEffectsVolume, 0, 100);
|
||||
|
||||
ImGui::Text("Fanfare Volume");
|
||||
ImGui::SliderFloat("##fanfareVolume", &getSettings().audio.fanfareVolume, 0, 100);
|
||||
|
||||
Z2AudioMgr* audioMgr = Z2AudioMgr::getInterface();
|
||||
if (audioMgr != nullptr) {
|
||||
}
|
||||
*/
|
||||
|
||||
ImGui::SeparatorText("Tweaks");
|
||||
|
||||
config::ImGuiCheckbox("No Low HP Sound", getSettings().game.noLowHpSound);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Disable the beeping sound when having low health.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Non-Stop Midna's Lament", getSettings().game.midnasLamentNonStop);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Prevents enemy music while Midna's Lament is playing.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawInputMenu() {
|
||||
if (ImGui::BeginMenu("Input")) {
|
||||
ImGui::SeparatorText("Controller");
|
||||
|
||||
ImGui::MenuItem("Configure Controller", nullptr, &m_showControllerConfig);
|
||||
|
||||
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
|
||||
|
||||
ImGui::SeparatorText("Gyro");
|
||||
|
||||
config::ImGuiCheckbox("Gyro Aim", getSettings().game.enableGyroAim);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Enables the gyroscope on supported controllers\n"
|
||||
"while in look mode (C-Up) and while aiming the\n"
|
||||
"Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s),\n"
|
||||
"Ball and Chain, and Dominion Rod.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Gyro Rollgoal", getSettings().game.enableGyroRollgoal);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Enables the gyroscope on supported controllers to\n"
|
||||
"tilt the Rollgoal table in Hena's Cabin.");
|
||||
}
|
||||
|
||||
if (getSettings().game.enableGyroAim || getSettings().game.enableGyroRollgoal) {
|
||||
config::ImGuiSliderFloat("Gyro Pitch Sensitivity", getSettings().game.gyroSensitivityY, 0.25f, 4.0f, "%.2f");
|
||||
config::ImGuiSliderFloat("Gyro Yaw Sensitivity", getSettings().game.gyroSensitivityX, 0.25f, 4.0f, "%.2f");
|
||||
|
||||
if (getSettings().game.enableGyroRollgoal) {
|
||||
config::ImGuiSliderFloat("Rollgoal Sensitivity", getSettings().game.gyroSensitivityRollgoal, 0.25f, 4.0f, "%.2f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Additional multiplier for scaling how strongly\n"
|
||||
"the gyroscope affects the Rollgoal table.");
|
||||
}
|
||||
}
|
||||
|
||||
config::ImGuiSliderFloat("Gyro Deadband", getSettings().game.gyroDeadband, 0.0f, 0.5f, "%.3f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Angular rates below this magnitude are treated as zero,\n"
|
||||
"reducing drift and jitter when the controller is still.");
|
||||
}
|
||||
|
||||
config::ImGuiSliderFloat("Gyro Smoothing", getSettings().game.gyroSmoothing, 0.0f, 1.0f, "%.2f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Low values track raw gyro input more closely,\n"
|
||||
"while higher values smooth out input over time.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Invert Gyro Pitch", getSettings().game.gyroInvertPitch);
|
||||
config::ImGuiCheckbox("Invert Gyro Yaw", getSettings().game.gyroInvertYaw);
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Tools");
|
||||
|
||||
config::ImGuiCheckbox("Turbo Key", getSettings().game.enableTurboKeybind);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Hold TAB to increase game speed by up to 4x.");
|
||||
}
|
||||
|
||||
ImGui::Checkbox("Show Input Viewer", &m_showInputViewer);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawInterfaceMenu() {
|
||||
if (ImGui::BeginMenu("Interface")) {
|
||||
config::ImGuiCheckbox("Skip Pre-Launch UI", getSettings().backend.skipPreLaunchUI);
|
||||
config::ImGuiCheckbox("Show Pipeline Compilation", getSettings().backend.showPipelineCompilation);
|
||||
#if DUSK_ENABLE_SENTRY_NATIVE
|
||||
config::ImGuiCheckbox("Enable Crash Reporting", getSettings().backend.enableCrashReporting);
|
||||
#endif
|
||||
if (!IsMobile) {
|
||||
config::ImGuiCheckbox("Pause on Focus Lost", getSettings().game.pauseOnFocusLost);
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
static void drawVirtualStick(const char* id, const ImVec2& stick) {
|
||||
float scale = ImGuiScale();
|
||||
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x + 45 * scale, ImGui::GetCursorPos().y + 10));
|
||||
|
||||
@@ -19,6 +19,13 @@ namespace dusk {
|
||||
static void ToggleFullscreen();
|
||||
|
||||
private:
|
||||
void drawAudioMenu();
|
||||
void drawInputMenu();
|
||||
void drawGraphicsMenu();
|
||||
void drawGameplayMenu();
|
||||
void drawCheatsMenu();
|
||||
void drawInterfaceMenu();
|
||||
|
||||
struct {
|
||||
int m_selectedPort = 0;
|
||||
bool m_isReading = false;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "imgui.h"
|
||||
#include "aurora/gfx.h"
|
||||
|
||||
#include "ImGuiConfig.hpp"
|
||||
#include "dusk/hotkeys.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "ImGuiConsole.hpp"
|
||||
@@ -15,10 +16,58 @@
|
||||
#include "dusk/main.h"
|
||||
#include "m_Do/m_Do_main.h"
|
||||
|
||||
#include <aurora/lib/internal.hpp>
|
||||
#include <SDL3/SDL_misc.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || (defined(__APPLE__) && !TARGET_OS_IOS && !TARGET_OS_MACCATALYST) || (defined(__linux__) && !defined(__ANDROID__))
|
||||
#define DUSK_CAN_OPEN_DATA_FOLDER 1
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static void OpenDataFolder() {
|
||||
const std::string path = fs::absolute(dusk::ConfigPath).generic_string();
|
||||
#if defined(_WIN32)
|
||||
const std::string url = std::string("file:///") + path;
|
||||
#else
|
||||
const std::string url = std::string("file://") + path;
|
||||
#endif
|
||||
(void)SDL_OpenURL(url.c_str());
|
||||
}
|
||||
#else
|
||||
#define DUSK_CAN_OPEN_DATA_FOLDER 0
|
||||
#endif
|
||||
|
||||
namespace dusk {
|
||||
ImGuiMenuTools::ImGuiMenuTools() {}
|
||||
|
||||
void ImGuiMenuTools::draw() {
|
||||
if (ImGui::BeginMenu("Tools")) {
|
||||
if (!dusk::IsGameLaunched) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!dusk::IsGameLaunched) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
#if DUSK_CAN_OPEN_DATA_FOLDER
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Open Data Folder")) {
|
||||
OpenDataFolder();
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Debug")) {
|
||||
bool developmentMode = mDoMain::developmentMode == 1;
|
||||
if (ImGui::Checkbox("Development Mode", &developmentMode)) {
|
||||
@@ -28,6 +77,15 @@ namespace dusk {
|
||||
ImGui::Separator();
|
||||
|
||||
auto& collisionView = getTransientSettings().collisionView;
|
||||
if (ImGui::BeginMenu("Graphics Settings")) {
|
||||
bool disableWaterRefraction = getSettings().game.disableWaterRefraction;
|
||||
if (ImGui::Checkbox("Disable Water Refraction", &disableWaterRefraction)) {
|
||||
getSettings().game.disableWaterRefraction.setValue(disableWaterRefraction);
|
||||
config::Save();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Collision View")) {
|
||||
ImGui::Checkbox("Enable Terrain view", &collisionView.enableTerrainView);
|
||||
ImGui::Checkbox("Enable wireframe view", &collisionView.enableWireframe);
|
||||
@@ -49,9 +107,6 @@ namespace dusk {
|
||||
ImGui::MenuItem("Debug Overlay", hotkeys::SHOW_DEBUG_OVERLAY, &m_showDebugOverlay);
|
||||
ImGui::MenuItem("Heap Viewer", hotkeys::SHOW_HEAP_VIEWER, &m_showHeapOverlay);
|
||||
ImGui::MenuItem("Player Info", hotkeys::SHOW_PLAYER_INFO, &m_showPlayerInfo);
|
||||
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("Debug Camera", hotkeys::SHOW_DEBUG_CAMERA, &m_showCameraOverlay);
|
||||
ImGui::MenuItem("Audio Debug", hotkeys::SHOW_AUDIO_DEBUG, &m_showAudioDebug);
|
||||
ImGui::MenuItem("Bloom", nullptr, &m_showBloomWindow);
|
||||
@@ -86,7 +141,9 @@ namespace dusk {
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
if (ImGui::Begin("Debug Overlay", nullptr, windowFlags)) {
|
||||
ImGuiStringViewText(fmt::format(FMT_STRING("FPS: {:.2f}\n"), io.Framerate));
|
||||
ImGuiStringViewText(fmt::format(FMT_STRING("Frame usage: {:.1f}%\n"), frameUsagePct));
|
||||
if (frameUsagePct > 0.f) {
|
||||
ImGuiStringViewText(fmt::format(FMT_STRING("Frame usage: {:.1f}%\n"), frameUsagePct));
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
|
||||
@@ -9,53 +9,109 @@
|
||||
#include "f_pc/f_pc_layer_iter.h"
|
||||
#include "f_pc/f_pc_leaf.h"
|
||||
#include "f_pc/f_pc_node.h"
|
||||
#include "d/d_debug_viewer.h"
|
||||
#include "imgui.h"
|
||||
#include "ImGuiConsole.hpp"
|
||||
#include "ImGuiMenuTools.hpp"
|
||||
#include "imgui_internal.h"
|
||||
|
||||
namespace dusk {
|
||||
bool showTreeRecursive;
|
||||
static bool BeginProcTable() {
|
||||
static ImGuiTableFlags table_flags =
|
||||
ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable |
|
||||
ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
|
||||
|
||||
if (ImGui::BeginTable("proc_table", 7)) {
|
||||
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 128);
|
||||
ImGui::TableSetupColumn("En", ImGuiTableColumnFlags_WidthFixed, 32);
|
||||
ImGui::TableSetupColumn("Vs", ImGuiTableColumnFlags_WidthFixed, 32);
|
||||
ImGui::TableSetupColumn("ProcName");
|
||||
ImGui::TableSetupColumn("Param", ImGuiTableColumnFlags_WidthFixed, 128);
|
||||
ImGui::TableSetupColumn("Pi", ImGuiTableColumnFlags_WidthFixed, 64);
|
||||
ImGui::TableSetupColumn("DwPi", ImGuiTableColumnFlags_WidthFixed, 64);
|
||||
ImGui::TableHeadersRow();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ShowProcess(void* p, void*) {
|
||||
auto proc = static_cast<base_process_class*>(p);
|
||||
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%d", proc->id);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::PushID(proc);
|
||||
bool pending = proc->create_req != nullptr;
|
||||
if (pending)
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, {255, 200, 0, 255});
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImVec2 avail = ImGui::GetContentRegionAvail();
|
||||
char id_buf[32];
|
||||
sprintf(id_buf, "%d", proc->id);
|
||||
|
||||
ImVec2 vec = { avail.x, 0 };
|
||||
if (ImGui::BeginChild(buf, vec, ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY)) {
|
||||
ImGui::Text("[%d] %s", proc->id, GetProcName(proc->profname));
|
||||
ImGui::Text("init_state: %d, create_phase: %d", proc->state.init_state, proc->state.create_phase);
|
||||
int flags = ImGuiTreeNodeFlags_SpanAllColumns;
|
||||
bool isLayer = fpcBs_Is_JustOfType(g_fpcNd_type, proc->subtype);
|
||||
if (isLayer) {
|
||||
flags |= ImGuiTreeNodeFlags_DefaultOpen;
|
||||
} else {
|
||||
flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen;
|
||||
}
|
||||
|
||||
const char* ofTypeName = "unknown";
|
||||
if (proc->subtype == g_fpcNd_type) {
|
||||
ofTypeName = "Node";
|
||||
}
|
||||
else if (proc->subtype == g_fpcLf_type) {
|
||||
ofTypeName = "Leaf";
|
||||
}
|
||||
bool open = ImGui::TreeNodeEx(id_buf, flags);
|
||||
fopAc_ac_c* ac = fopAcM_IsActor(proc) ? (fopAc_ac_c*)proc : nullptr;
|
||||
if (ac != nullptr && ImGui::IsItemHovered()) {
|
||||
fopAcM_DrawCullingBox(ac, {0, 255, 255, 255});
|
||||
}
|
||||
|
||||
ImGui::Text("OfType: %d (%s), layer: %d", proc->subtype, ofTypeName, proc->layer_tag.layer->layer_id);
|
||||
ImGui::TableNextColumn();
|
||||
bool enable = !fpcM_IsPause(proc, 1);
|
||||
if (ImGui::Checkbox("##enable", &enable)) {
|
||||
if (enable)
|
||||
fpcM_PauseDisable(proc, 1);
|
||||
else
|
||||
fpcM_PauseEnable(proc, 1);
|
||||
}
|
||||
|
||||
if (proc->create_req != nullptr) {
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Pending create request");
|
||||
}
|
||||
|
||||
if (showTreeRecursive) {
|
||||
if (fpcBs_Is_JustOfType(g_fpcNd_type, proc->subtype)) {
|
||||
auto procNode = static_cast<process_node_class*>(p);
|
||||
|
||||
ImGui::Text("Owns layer %d", procNode->layer.layer_id);
|
||||
|
||||
fpcLyIt_OnlyHere(&procNode->layer, ShowProcess, nullptr);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
if (fpcBs_Is_JustOfType(g_fpcLf_type, proc->subtype)) {
|
||||
leafdraw_class* lf = (leafdraw_class*)proc;
|
||||
bool vis = lf->unk_0xBC == 0;
|
||||
if (ImGui::Checkbox("##visible", &vis)) {
|
||||
if (vis)
|
||||
lf->unk_0xBC = 0;
|
||||
else
|
||||
lf->unk_0xBC = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", ac != nullptr ? fopAcM_getProcNameString(ac) : GetProcName(proc->profname));
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (proc->profname == fpcNm_ROOM_SCENE_e) {
|
||||
ImGui::Text("Room %d", proc->parameters);
|
||||
} else {
|
||||
ImGui::Text("%08x", proc->parameters);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d", proc->priority.current_info.list_id);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (fpcBs_Is_JustOfType(g_fpcLf_type, proc->subtype)) {
|
||||
ImGui::Text("%d", fpcM_DrawPriority(proc));
|
||||
} else {
|
||||
ImGui::Text("--");
|
||||
}
|
||||
|
||||
if (isLayer && open) {
|
||||
auto procNode = static_cast<process_node_class*>(p);
|
||||
fpcLyIt_OnlyHere(&procNode->layer, ShowProcess, nullptr);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (pending)
|
||||
ImGui::PopStyleColor(1);
|
||||
ImGui::PopID();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -76,15 +132,11 @@ namespace dusk {
|
||||
|
||||
if (ImGui::Begin("Processes", &m_showProcessManagement)) {
|
||||
if (ImGui::BeginTabBar("Tabs")) {
|
||||
showTreeRecursive = true;
|
||||
if (ImGui::BeginTabItem("Tree")) {
|
||||
fpcLyIt_OnlyHere(fpcLy_RootLayer(), ShowProcess, nullptr);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
showTreeRecursive = false;
|
||||
if (ImGui::BeginTabItem("All layers")) {
|
||||
fpcLyIt_All(ShowProcess, nullptr);
|
||||
if (BeginProcTable()) {
|
||||
fpcLyIt_OnlyHere(fpcLy_RootLayer(), ShowProcess, nullptr);
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
|
||||
@@ -168,14 +168,14 @@ void aurora_log_callback(AuroraLogLevel level, const char* module, const char* m
|
||||
|
||||
aurora::Module DuskLog("dusk");
|
||||
|
||||
void dusk::InitializeFileLogging(const char* configDir, AuroraLogLevel logLevel) {
|
||||
void dusk::InitializeFileLogging(const std::filesystem::path& configDir, AuroraLogLevel logLevel) {
|
||||
std::lock_guard lock(g_logMutex);
|
||||
if (g_logFile != nullptr || configDir == nullptr) {
|
||||
if (g_logFile != nullptr || configDir.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
const std::filesystem::path logsDir = std::filesystem::path(configDir) / "logs";
|
||||
const std::filesystem::path logsDir = configDir / "logs";
|
||||
std::filesystem::create_directories(logsDir, ec);
|
||||
if (ec) {
|
||||
std::fprintf(stderr, "[WARNING | dusk] Failed to create log directory '%s': %s\n",
|
||||
|
||||
@@ -42,11 +42,12 @@ UserSettings g_userSettings = {
|
||||
.enableMirrorMode {"game.enableMirrorMode", false},
|
||||
.invertCameraXAxis {"game.invertCameraXAxis", false},
|
||||
.disableMainHUD {"game.disableMainHUD", false},
|
||||
.pauseOnFocusLost {"game.pauseOnFocusLost", false},
|
||||
|
||||
// Graphics
|
||||
.bloomMode {"game.bloomMode", BloomMode::Classic},
|
||||
.bloomMultiplier {"game.bloomMultiplier", 1.0f},
|
||||
.enableWaterRefraction {"game.enableWaterRefraction", true},
|
||||
.disableWaterRefraction {"game.disableWaterRefraction", false},
|
||||
.enableFrameInterpolation = {"game.enableFrameInterpolation", false},
|
||||
.internalResolutionScale {"game.internalResolutionScale", 0},
|
||||
.shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1},
|
||||
@@ -136,9 +137,10 @@ void registerSettings() {
|
||||
Register(g_userSettings.game.enableMirrorMode);
|
||||
Register(g_userSettings.game.invertCameraXAxis);
|
||||
Register(g_userSettings.game.disableMainHUD);
|
||||
Register(g_userSettings.game.pauseOnFocusLost);
|
||||
Register(g_userSettings.game.bloomMode);
|
||||
Register(g_userSettings.game.bloomMultiplier);
|
||||
Register(g_userSettings.game.enableWaterRefraction);
|
||||
Register(g_userSettings.game.disableWaterRefraction);
|
||||
Register(g_userSettings.game.internalResolutionScale);
|
||||
Register(g_userSettings.game.shadowResolutionMultiplier);
|
||||
Register(g_userSettings.game.enableFastIronBoots);
|
||||
|
||||
@@ -26,13 +26,7 @@ int fpcDw_Execute(base_process_class* i_proc) {
|
||||
}
|
||||
|
||||
fpcLy_SetCurrentLayer(i_proc->layer_tag.layer);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::open_child(i_proc, 0);
|
||||
#endif
|
||||
ret = draw_func(i_proc);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::close_child();
|
||||
#endif
|
||||
fpcLy_SetCurrentLayer(save_layer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
#include "f_pc/f_pc_leaf.h"
|
||||
#include "f_pc/f_pc_debug_sv.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
s16 fpcLf_GetPriority(const leafdraw_class* i_leaf) {
|
||||
return fpcDwPi_Get(&i_leaf->draw_priority);
|
||||
}
|
||||
@@ -16,6 +20,11 @@ int fpcLf_DrawMethod(leafdraw_method_class* i_methods, void* i_process) {
|
||||
|
||||
int fpcLf_Draw(leafdraw_class* i_leaf) {
|
||||
int ret = 0;
|
||||
#if TARGET_PC
|
||||
if (!i_leaf->draw_interp_frame && !dusk::frame_interp::is_sim_frame()) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if (i_leaf->unk_0xBC == 0) {
|
||||
ret = fpcLf_DrawMethod(i_leaf->leaf_methods, i_leaf);
|
||||
}
|
||||
@@ -56,6 +65,9 @@ int fpcLf_Create(leafdraw_class* i_leaf) {
|
||||
LEAFDRAW_BASE(i_leaf).subtype = fpcBs_MakeOfType(&g_fpcLf_type);
|
||||
fpcDwPi_Init(&i_leaf->draw_priority, pprofile->priority);
|
||||
i_leaf->unk_0xBC = 0;
|
||||
#if TARGET_PC
|
||||
i_leaf->draw_interp_frame = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ret = fpcMtd_Create(&i_leaf->leaf_methods->base, i_leaf);
|
||||
|
||||
@@ -65,7 +65,7 @@ void fpcM_Management(fpcM_ManagementFunc i_preExecuteFn, fpcM_ManagementFunc i_p
|
||||
|
||||
#ifdef TARGET_PC
|
||||
// FRAME INTERP NOTE: Called in m_Do_main when interp is enabled
|
||||
if (!dusk::getSettings().game.enableFrameInterpolation || dusk::getTransientSettings().skipFrameRateLimit)
|
||||
if (!dusk::frame_interp::is_enabled())
|
||||
#endif
|
||||
{
|
||||
cAPIGph_Painter();
|
||||
|
||||
+18
-1
@@ -7,6 +7,13 @@
|
||||
#include "f_pc/f_pc_layer_iter.h"
|
||||
#include "f_pc/f_pc_debug_sv.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "f_op/f_op_draw_iter.h"
|
||||
#include "f_pc/f_pc_manager.h"
|
||||
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
int fpcNd_DrawMethod(nodedraw_method_class* i_method_class, void* i_data) {
|
||||
return fpcMtd_Method(i_method_class->draw_method, i_data);
|
||||
}
|
||||
@@ -18,7 +25,17 @@ int fpcNd_Draw(process_node_class* i_procNode) {
|
||||
if (i_procNode->unk_0x1A8 == 0) {
|
||||
layer_class* save_layer = fpcLy_CurrentLayer();
|
||||
fpcLy_SetCurrentLayer(&var_r28->layer);
|
||||
ret = fpcNd_DrawMethod(i_procNode->nodedraw_method, i_procNode);
|
||||
#if TARGET_PC
|
||||
if (!i_procNode->draw_interp_frame && !dusk::frame_interp::is_sim_frame()) {
|
||||
for (create_tag_class* i = fopDwIt_Begin(); i != NULL; i = fopDwIt_Next(i)) {
|
||||
void* process = i->mpTagData;
|
||||
fpcM_Draw(process);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = fpcNd_DrawMethod(i_procNode->nodedraw_method, i_procNode);
|
||||
}
|
||||
fpcLy_SetCurrentLayer(save_layer);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,11 +84,12 @@ void mDoMemCd_Ctrl_c::ThdInit() {
|
||||
mProbeStat = 2;
|
||||
mCardState = CARD_STATE_NO_CARD_e;
|
||||
|
||||
#if TARGET_PC
|
||||
mCardState = CARD_STATE_READY_e;
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
mCardCommand = COMM_ATTACH_e;
|
||||
#else
|
||||
mCardCommand = COMM_NONE_e;
|
||||
#endif
|
||||
|
||||
mChannel = SLOT_A;
|
||||
|
||||
OSInitMutex(&mMutex);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
|
||||
u8 mDoExt::CurrentHeapAdjustVerbose;
|
||||
u8 mDoExt::HeapAdjustVerbose;
|
||||
@@ -349,6 +350,11 @@ void mDoExt_modelUpdateDL(J3DModel* i_model) {
|
||||
}
|
||||
|
||||
void mDoExt_modelEntryDL(J3DModel* i_model) {
|
||||
#if TARGET_PC
|
||||
if (!dusk::frame_interp::is_sim_frame())
|
||||
return;
|
||||
#endif
|
||||
|
||||
modelMtxErrorCheck(i_model);
|
||||
|
||||
J3DModelData* model_data = i_model->getModelData();
|
||||
|
||||
+80
-36
@@ -66,9 +66,14 @@
|
||||
|
||||
#include "SDL3/SDL_filesystem.h"
|
||||
#include "cxxopts.hpp"
|
||||
#include "d/actor/d_a_movie_player.h"
|
||||
#include "dusk/audio/DuskAudioSystem.h"
|
||||
#include "dusk/config.hpp"
|
||||
#include "dusk/imgui/ImGuiConsole.hpp"
|
||||
#include "dusk/settings.h"
|
||||
#include "dusk/discord_presence.hpp"
|
||||
#include "tracy/Tracy.hpp"
|
||||
#include "f_pc/f_pc_draw.h"
|
||||
#include "tracy/Tracy.hpp"
|
||||
|
||||
// --- GLOBALS ---
|
||||
@@ -92,6 +97,8 @@ const int audioHeapSize = 0x14D800;
|
||||
bool dusk::IsRunning = true;
|
||||
bool dusk::IsShuttingDown = false;
|
||||
bool dusk::IsGameLaunched = false;
|
||||
bool dusk::IsFocusPaused = false;
|
||||
std::filesystem::path dusk::ConfigPath;
|
||||
#endif
|
||||
|
||||
s32 LOAD_COPYDATE(void*) {
|
||||
@@ -124,7 +131,6 @@ s32 LOAD_COPYDATE(void*) {
|
||||
AuroraInfo auroraInfo;
|
||||
AuroraStats dusk::lastFrameAuroraStats;
|
||||
float dusk::frameUsagePct = 0.0f;
|
||||
const char* configPath;
|
||||
|
||||
bool launchUILoop() {
|
||||
while (dusk::IsRunning && !dusk::IsGameLaunched) {
|
||||
@@ -208,6 +214,16 @@ void main01(void) {
|
||||
goto eventsDone;
|
||||
case AURORA_SDL_EVENT:
|
||||
dusk::g_imguiConsole.HandleSDLEvent(event->sdl);
|
||||
if (event->sdl.type == SDL_EVENT_WINDOW_FOCUS_LOST &&
|
||||
dusk::getSettings().game.pauseOnFocusLost) {
|
||||
dusk::IsFocusPaused = true;
|
||||
dusk::audio::SetPaused(true);
|
||||
} else if (event->sdl.type == SDL_EVENT_WINDOW_FOCUS_GAINED &&
|
||||
dusk::IsFocusPaused) {
|
||||
dusk::IsFocusPaused = false;
|
||||
dusk::audio::SetPaused(false);
|
||||
dusk::game_clock::reset_frame_timer();
|
||||
}
|
||||
break;
|
||||
case AURORA_DISPLAY_SCALE_CHANGED:
|
||||
dusk::ImGuiEngine_Initialize(event->windowSize.scale);
|
||||
@@ -221,6 +237,11 @@ void main01(void) {
|
||||
|
||||
eventsDone:;
|
||||
|
||||
if (dusk::IsFocusPaused) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
||||
continue;
|
||||
}
|
||||
|
||||
const dusk::game_clock::MainLoopPacer pacing = dusk::game_clock::advance_main_loop();
|
||||
|
||||
VIWaitForRetrace();
|
||||
@@ -233,20 +254,26 @@ void main01(void) {
|
||||
|
||||
mDoGph_gInf_c::updateRenderSize();
|
||||
|
||||
dusk::frame_interp::begin_frame(pacing.is_interpolating, pacing.do_sim_tick, pacing.interpolation_step);
|
||||
if (pacing.is_interpolating) {
|
||||
if (pacing.do_sim_tick) {
|
||||
dusk::frame_interp::set_ui_tick_pending(true);
|
||||
mDoCPd_c::read();
|
||||
DuskDebugPad();
|
||||
dusk::gyro::read(pacing.sim_pace);
|
||||
fapGm_Execute();
|
||||
mDoAud_Execute();
|
||||
dusk::game_clock::reset_accumulator();
|
||||
}
|
||||
dusk::frame_interp::interpolate(pacing.interpolation_step);
|
||||
{
|
||||
dusk::frame_interp::PresentationCameraScope presentation_camera;
|
||||
cAPIGph_Painter();
|
||||
dusk::frame_interp::interpolate();
|
||||
dusk::frame_interp::begin_presentation_camera();
|
||||
if (!pacing.do_sim_tick) {
|
||||
// run draw functions for anything specially marked to handle interp on non-sim
|
||||
// ticks
|
||||
fpcM_DrawIterater((fpcM_DrawIteraterFunc)fpcM_Draw);
|
||||
}
|
||||
cAPIGph_Painter();
|
||||
dusk::frame_interp::end_presentation_camera();
|
||||
dusk::frame_interp::set_ui_tick_pending(false);
|
||||
} else {
|
||||
dusk::frame_interp::set_ui_tick_pending(true);
|
||||
@@ -265,6 +292,11 @@ void main01(void) {
|
||||
aurora_end_frame();
|
||||
|
||||
FrameMark;
|
||||
|
||||
#ifdef DUSK_DISCORD_RPC
|
||||
dusk::discord::RunCallbacks();
|
||||
dusk::discord::UpdatePresence();
|
||||
#endif
|
||||
} while (dusk::IsRunning);
|
||||
|
||||
exit:;
|
||||
@@ -347,7 +379,7 @@ static void ApplyCVarOverrides(const cxxopts::OptionValue& option) {
|
||||
}
|
||||
}
|
||||
|
||||
static const char* CalculateConfigPath() {
|
||||
static std::filesystem::path CalculateConfigPath() {
|
||||
const auto result = SDL_GetPrefPath(dusk::OrgName, dusk::AppName);
|
||||
if (!result) {
|
||||
DuskLog.fatal("Unable to get PrefPath: {}", SDL_GetError());
|
||||
@@ -356,13 +388,12 @@ static const char* CalculateConfigPath() {
|
||||
return result;
|
||||
}
|
||||
|
||||
static void EnsureInitialPipelineCache(const char* configDir) {
|
||||
if (configDir == nullptr) {
|
||||
static void EnsureInitialPipelineCache(const std::filesystem::path& configDir) {
|
||||
if (configDir.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::filesystem::path configPathFs(configDir);
|
||||
const std::filesystem::path pipelineCachePath = configPathFs / "pipeline_cache.db";
|
||||
const std::filesystem::path pipelineCachePath = configDir / "pipeline_cache.db";
|
||||
if (std::filesystem::exists(pipelineCachePath)) {
|
||||
return;
|
||||
}
|
||||
@@ -381,10 +412,10 @@ static void EnsureInitialPipelineCache(const char* configDir) {
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(configPathFs, ec);
|
||||
std::filesystem::create_directories(configDir, ec);
|
||||
if (ec) {
|
||||
DuskLog.warn("Failed to create config directory '{}' for pipeline cache: {}",
|
||||
configPathFs.string(), ec.message());
|
||||
configDir.string(), ec.message());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -475,37 +506,42 @@ int game_main(int argc, char* argv[]) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
configPath = CalculateConfigPath();
|
||||
dusk::ConfigPath = CalculateConfigPath();
|
||||
const auto startupLogLevel = static_cast<AuroraLogLevel>(parsed_arg_options["log-level"].as<uint8_t>());
|
||||
dusk::InitializeFileLogging(configPath, startupLogLevel);
|
||||
dusk::InitializeFileLogging(dusk::ConfigPath, startupLogLevel);
|
||||
|
||||
dusk::config::LoadFromUserPreferences();
|
||||
ApplyCVarOverrides(parsed_arg_options["cvar"]);
|
||||
dusk::InitializeCrashReporting();
|
||||
EnsureInitialPipelineCache(configPath);
|
||||
|
||||
AuroraConfig config{};
|
||||
config.appName = dusk::AppName;
|
||||
config.configPath = configPath;
|
||||
config.vsync = dusk::getSettings().video.enableVsync;
|
||||
config.startFullscreen = dusk::getSettings().video.enableFullscreen;
|
||||
config.windowPosX = -1;
|
||||
config.windowPosY = -1;
|
||||
config.windowWidth = defaultWindowWidth * 2;
|
||||
config.windowHeight = defaultWindowHeight * 2;
|
||||
config.desiredBackend = ResolveDesiredBackend(parsed_arg_options);
|
||||
config.logCallback = &aurora_log_callback;
|
||||
config.logLevel = startupLogLevel;
|
||||
config.mem1Size = 256 * 1024 * 1024;
|
||||
config.mem2Size = 24 * 1024 * 1024;
|
||||
config.allowJoystickBackgroundEvents = true;
|
||||
config.imGuiInitCallback = &aurora_imgui_init_callback;
|
||||
config.allowTextureReplacements = true;
|
||||
config.allowTextureDumps = false;
|
||||
|
||||
EnsureInitialPipelineCache(dusk::ConfigPath);
|
||||
PADSetDefaultMapping(&defaultPadMapping);
|
||||
|
||||
auroraInfo = aurora_initialize(argc, argv, &config);
|
||||
{
|
||||
const auto configPathString = dusk::ConfigPath.string();
|
||||
AuroraConfig config{};
|
||||
config.appName = dusk::AppName;
|
||||
config.configPath = configPathString.c_str();
|
||||
config.vsync = dusk::getSettings().video.enableVsync;
|
||||
config.startFullscreen = dusk::getSettings().video.enableFullscreen;
|
||||
config.windowPosX = -1;
|
||||
config.windowPosY = -1;
|
||||
config.windowWidth = defaultWindowWidth * 2;
|
||||
config.windowHeight = defaultWindowHeight * 2;
|
||||
config.desiredBackend = ResolveDesiredBackend(parsed_arg_options);
|
||||
config.logCallback = &aurora_log_callback;
|
||||
config.logLevel = startupLogLevel;
|
||||
config.mem1Size = 256 * 1024 * 1024;
|
||||
config.mem2Size = 24 * 1024 * 1024;
|
||||
config.allowJoystickBackgroundEvents = true;
|
||||
config.imGuiInitCallback = &aurora_imgui_init_callback;
|
||||
config.allowTextureReplacements = true;
|
||||
config.allowTextureDumps = false;
|
||||
auroraInfo = aurora_initialize(argc, argv, &config);
|
||||
}
|
||||
|
||||
#ifdef DUSK_DISCORD_RPC
|
||||
dusk::discord::Initialize();
|
||||
#endif
|
||||
|
||||
VISetWindowTitle(
|
||||
fmt::format("Dusk {} [{}]", DUSK_WC_DESCRIBE, dusk::backend_name(auroraInfo.backend))
|
||||
@@ -540,6 +576,9 @@ int game_main(int argc, char* argv[]) {
|
||||
// pre game launch ui main loop
|
||||
if (!launchUILoop()) {
|
||||
dusk::ShutdownCrashReporting();
|
||||
#ifdef DUSK_DISCORD_RPC
|
||||
dusk::discord::Shutdown();
|
||||
#endif
|
||||
aurora_shutdown();
|
||||
return 0;
|
||||
}
|
||||
@@ -577,6 +616,8 @@ int game_main(int argc, char* argv[]) {
|
||||
|
||||
main01();
|
||||
|
||||
dusk::MoviePlayerShutdown();
|
||||
|
||||
dusk::ShutdownCrashReporting();
|
||||
dusk::ShutdownFileLogging();
|
||||
fflush(stdout);
|
||||
@@ -587,6 +628,9 @@ int game_main(int argc, char* argv[]) {
|
||||
// Notifies all CVs and causes threads to exit
|
||||
OSResetSystem(OS_RESET_SHUTDOWN, 0, 0);
|
||||
|
||||
#ifdef DUSK_DISCORD_RPC
|
||||
dusk::discord::Shutdown();
|
||||
#endif
|
||||
aurora_shutdown();
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user