Merge remote-tracking branch 'origin/main' into feature/autosave

# Conflicts:
#	src/dusk/imgui/ImGuiMenuEnhancements.cpp
#	src/dusk/settings.cpp
#	src/f_ap/f_ap_game.cpp
This commit is contained in:
MelonSpeedruns
2026-04-24 12:54:40 -04:00
77 changed files with 2163 additions and 929 deletions
+6
View File
@@ -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;
+4
View File
@@ -103,6 +103,10 @@ public:
field_0xd98 = param_1;
}
#if TARGET_PC
void resetScrollArrowMask() { field_0xdda = 0; }
#endif
/* 0xC98 */ JKRExpHeap* mpHeap;
/* 0xC9C */ JKRExpHeap* mpTalkHeap;
/* 0xCA0 */ STControl* mpStick;
+3 -1
View File
@@ -75,7 +75,9 @@ public:
/* 0x8 */ BE(u16) mAreaName;
/* 0xA */ u8 mCount;
#ifdef _MSVC_LANG
u8* __get_mRoomNos() const { return (u8*)(this + 1); }
// Room numbers start at offset 0xB (right after mCount), NOT at sizeof(data)=12.
// (u8*)(this+1) would give offset 12 because MSVC sizeof=12; use &mCount+1 instead.
u8* __get_mRoomNos() const { return (u8*)&mCount + 1; }
__declspec(property(get = __get_mRoomNos)) u8* mRoomNos;
#else
/* 0xB */ u8 mRoomNos[0];
+9
View File
@@ -206,6 +206,15 @@ private:
/* 0x6D3 */ u8 field_0x6d3;
#if TARGET_PC
f32 mSelectItemSlideElapsed[4];
f32 mCursorInterpPrevX;
f32 mCursorInterpPrevY;
f32 mCursorInterpCurrX;
f32 mCursorInterpCurrY;
s16 mCursorInterpPrevAngle;
s16 mCursorInterpCurrAngle;
bool mCursorInterpPrevAngular;
bool mCursorInterpCurrAngular;
bool mCursorInterpInit;
#endif
};
+3
View File
@@ -48,6 +48,9 @@ public:
}
#ifdef TARGET_PC
f32 getPositionX() const { return mPositionX; }
f32 getPositionY() const { return mPositionY; }
void refreshAspectScale();
#endif
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#ifndef AUTOSAVE_H
#define AUTOSAVE_H
#include <m_Do/m_Do_MemCardRWmng.h>
#include <m_Do/m_Do_MemCard.h>
void noAutoSave();
void triggerAutoSave();
void updateAutoSave();
void enterAutoSave();
void autoSaving();
void waitingForWrite();
void endAutoSave();
#endif
-1
View File
@@ -6,7 +6,6 @@
#include "aurora/gfx.h"
extern AuroraInfo auroraInfo;
extern const char* configPath;
namespace dusk {
extern AuroraStats lastFrameAuroraStats;
+1
View File
@@ -16,6 +16,7 @@ void ensure_initialized();
void begin_record();
void end_record();
void begin_sim_tick();
void begin_frame(bool enabled, bool is_sim_frame, float step);
void interpolate();
float get_interpolation_step();
+6 -13
View File
@@ -1,13 +1,8 @@
#ifndef DUSK_GAME_CLOCK_H
#define DUSK_GAME_CLOCK_H
#pragma once
#include <stddef.h>
namespace dusk {
namespace game_clock {
namespace dusk::game_clock {
void ensure_initialized();
void reset_accumulator();
void reset_frame_timer();
constexpr float sim_pace() { return 1.0f / 30.0f; }
@@ -18,16 +13,14 @@ constexpr float ui_initial_dt() { return 1.0f / 60.0f; }
struct MainLoopPacer {
float presentation_dt_seconds;
bool is_interpolating;
bool do_sim_tick;
float interpolation_step;
int sim_ticks_to_run;
float sim_pace;
};
MainLoopPacer advance_main_loop();
void commit_sim_tick();
float sample_interpolation_step();
float consume_interval(const void* consumer);
} // namespace game_clock
} // namespace dusk
#endif // DUSK_GAME_CLOCK_H
} // namespace dusk::game_clock
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#ifndef GAMEPAD_COLOR_H
#define GAMEPAD_COLOR_H
void handleGamepadColor();
#endif
+3 -1
View File
@@ -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);
+3
View File
@@ -1,11 +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
+6
View File
@@ -70,6 +70,8 @@ struct UserSettings {
ConfigVar<bool> invertCameraXAxis;
ConfigVar<bool> disableMainHUD;
ConfigVar<bool> pauseOnFocusLost;
ConfigVar<bool> enableLinkDollRotation;
// Graphics
ConfigVar<BloomMode> bloomMode;
@@ -78,6 +80,7 @@ struct UserSettings {
ConfigVar<bool> enableFrameInterpolation;
ConfigVar<int> internalResolutionScale;
ConfigVar<int> shadowResolutionMultiplier;
ConfigVar<bool> enableDepthOfField;
// Audio
ConfigVar<bool> noLowHpSound;
@@ -101,6 +104,7 @@ struct UserSettings {
ConfigVar<bool> infiniteOil;
ConfigVar<bool> infiniteOxygen;
ConfigVar<bool> infiniteRupees;
ConfigVar<bool> enableIndefiniteItemDrops;
ConfigVar<bool> moonJump;
ConfigVar<bool> superClawshot;
ConfigVar<bool> alwaysGreatspin;
@@ -124,6 +128,7 @@ struct UserSettings {
ConfigVar<bool> wasPresetChosen;
ConfigVar<bool> enableCrashReporting;
ConfigVar<bool> duskMenuOpen;
ConfigVar<int> cardFileType;
} backend;
};
@@ -148,6 +153,7 @@ struct TransientSettings {
CollisionViewSettings collisionView;
bool skipFrameRateLimit;
bool moveLinkActive;
bool stateShareLoadActive;
};
TransientSettings& getTransientSettings();
+25 -25
View File
@@ -1,9 +1,10 @@
#ifndef DUSK_TIME_H
#define DUSK_TIME_H
#include <chrono>
#include <numeric>
#include <array>
#include <numeric>
#include "SDL3/SDL_timer.h"
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
@@ -15,28 +16,26 @@
#include <Windows.h>
#include <shellapi.h>
#include <intrin.h>
#else
#include "SDL3/SDL_timer.h"
#endif
class Limiter {
using delta_clock = std::chrono::high_resolution_clock;
using duration_t = std::chrono::nanoseconds;
public:
void Reset() { m_oldTime = delta_clock::now(); }
using duration_t = Uint64;
void Reset() { m_oldTime = SDL_GetTicksNS(); }
void Sleep(duration_t targetFrameTime) {
if (targetFrameTime.count() == 0) {
if (targetFrameTime == 0) {
return;
}
auto start = delta_clock::now();
const Uint64 start = SDL_GetTicksNS();
duration_t adjustedSleepTime = SleepTime(targetFrameTime);
if (adjustedSleepTime.count() > 0) {
if (adjustedSleepTime > 0) {
NanoSleep(adjustedSleepTime);
duration_t overslept = TimeSince(start) - adjustedSleepTime;
if (overslept < duration_t{targetFrameTime}) {
const duration_t elapsed = TimeSince(start);
const duration_t overslept = elapsed > adjustedSleepTime ? elapsed - adjustedSleepTime : 0;
if (overslept < targetFrameTime) {
m_overheadTimes[m_overheadTimeIdx] = overslept;
m_overheadTimeIdx = (m_overheadTimeIdx + 1) % m_overheadTimes.size();
}
@@ -45,23 +44,23 @@ public:
}
duration_t SleepTime(duration_t targetFrameTime) {
const auto sleepTime = duration_t{targetFrameTime} - TimeSince(m_oldTime);
m_overhead = std::accumulate(m_overheadTimes.begin(), m_overheadTimes.end(), duration_t{}) / m_overheadTimes.size();
const duration_t elapsed = TimeSince(m_oldTime);
const duration_t sleepTime = elapsed < targetFrameTime ? targetFrameTime - elapsed : 0;
m_overhead = std::accumulate(m_overheadTimes.begin(), m_overheadTimes.end(), duration_t{0}) /
m_overheadTimes.size();
if (sleepTime > m_overhead) {
return sleepTime - m_overhead;
}
return duration_t{0};
return 0;
}
private:
delta_clock::time_point m_oldTime;
Uint64 m_oldTime = 0;
std::array<duration_t, 4> m_overheadTimes{};
size_t m_overheadTimeIdx = 0;
duration_t m_overhead = duration_t{0};
duration_t m_overhead = 0;
duration_t TimeSince(delta_clock::time_point start) {
return std::chrono::duration_cast<duration_t>(delta_clock::now() - start);
}
duration_t TimeSince(Uint64 start) const { return SDL_GetTicksNS() - start; }
#if _WIN32
void NanoSleep(const duration_t duration) {
@@ -85,9 +84,10 @@ private:
LARGE_INTEGER start, current;
QueryPerformanceCounter(&start);
LONGLONG ticksToWait = static_cast<LONGLONG>(duration.count() * countPerNs);
if (DWORD ms = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); ms > 1) {
::Sleep(ms - 1);
const LONGLONG ticksToWait = static_cast<LONGLONG>(duration * countPerNs);
const Uint64 ms = duration / 1'000'000ULL;
if (ms > 1) {
::Sleep(static_cast<DWORD>(ms - 1));
}
do {
QueryPerformanceCounter(&current);
@@ -99,7 +99,7 @@ private:
} while (current.QuadPart - start.QuadPart < ticksToWait);
}
#else
void NanoSleep(const duration_t duration) { SDL_DelayPrecise(duration.count()); }
void NanoSleep(const duration_t duration) { SDL_DelayPrecise(duration); }
#endif
};
-10
View File
@@ -14,16 +14,6 @@ void fapGm_After();
void fapGm_Create();
void fapGm_Execute();
#if TARGET_PC
void noAutoSave();
void triggerAutoSave();
void updateAutoSave();
void enterAutoSave();
void autoSaving();
void waitingForWrite();
void endAutoSave();
#endif
class fapGm_HIO_c : public JORReflexible {
public:
fapGm_HIO_c();
+11 -1
View File
@@ -73,6 +73,9 @@
#endif
#ifndef __MWERKS__
#ifdef __cplusplus
extern "C" {
#endif
// Silence clangd errors about MWCC PPC intrinsics by declaring them here.
extern int __cntlzw(unsigned int);
extern int __rlwimi(int, int, int, int, int);
@@ -80,7 +83,14 @@ extern void __dcbf(void*, int);
extern void __dcbz(void*, int);
extern void __sync();
extern int __abs(int);
void* __memcpy(void*, const void*, int);
#if defined(__has_builtin) && __has_builtin(__builtin_memcpy)
#define __memcpy __builtin_memcpy
#else
#define __memcpy memcpy
#endif
#ifdef __cplusplus
}
#endif
#endif
#ifndef M_PI