Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer

This commit is contained in:
gymnast86
2026-04-11 23:01:58 -07:00
39 changed files with 1007 additions and 109 deletions
+2
View File
@@ -1363,6 +1363,8 @@ set(DUSK_FILES
src/dusk/imgui/ImGuiMenuEnhancements.hpp
src/dusk/imgui/ImGuiPreLaunchWindow.cpp
src/dusk/imgui/ImGuiPreLaunchWindow.hpp
src/dusk/imgui/ImGuiFirstRunPreset.hpp
src/dusk/imgui/ImGuiFirstRunPreset.cpp
src/dusk/imgui/ImGuiProcessOverlay.cpp
src/dusk/imgui/ImGuiCameraOverlay.cpp
src/dusk/imgui/ImGuiHeapOverlay.cpp
+3
View File
@@ -196,6 +196,9 @@ public:
void copyReinPos();
void setReinPosHandSubstance(int);
void setReinPosNormalSubstance();
#if TARGET_PC
void lerpControlPoints(f32 alpha);
#endif
void bgCheck();
bool checkSpecialWallHitSubstance(cXyz const&) const;
void setServiceWaitTimer();
+10 -3
View File
@@ -4848,8 +4848,8 @@ inline void dComIfGd_drawXluListDark() {
inline void dComIfGd_drawXluListInvisible() {
ZoneScoped;
#ifdef TARGET_PC
// FIXME: Water rendering hack for frame interpolation
if (!dusk::getSettings().game.enableFrameInterpolation) {
if (dusk::getSettings().game.enableWaterRefraction &&
!dusk::getSettings().game.enableFrameInterpolation) {
#endif
g_dComIfG_gameInfo.drawlist.drawXluListInvisible();
#ifdef TARGET_PC
@@ -4859,7 +4859,14 @@ inline void dComIfGd_drawXluListInvisible() {
inline void dComIfGd_drawOpaListInvisible() {
ZoneScoped;
g_dComIfG_gameInfo.drawlist.drawOpaListInvisible();
#ifdef TARGET_PC
if (dusk::getSettings().game.enableWaterRefraction &&
!dusk::getSettings().game.enableFrameInterpolation) {
#endif
g_dComIfG_gameInfo.drawlist.drawOpaListInvisible();
#ifdef TARGET_PC
}
#endif
}
inline void dComIfGd_drawXluListZxlu() {
+4
View File
@@ -435,6 +435,10 @@ public:
m3DLineMatSortPacket[param_1->getMaterialID()].setMatDark(param_1);
}
#if TARGET_PC
void refresh3DlineMats(const cXyz& eye);
#endif
void peekZdata() { mPeekZ.peekData(); }
void entryZSortListZxlu(J3DPacket* i_packet, cXyz& param_1) {
entryZSortXluDrawList(mDrawBuffers[DB_LIST_Z_XLU], i_packet, param_1);
+3
View File
@@ -152,6 +152,9 @@ public:
void setRegionCursor(u8 i_value) { mRegionCursor = i_value; }
void setMapDrawFlag(bool i_flag) { mMapDrawFlag = i_flag; }
void resetDrug() { field_0x1238 = 0; }
#if TARGET_PC
void resetScrollArrowMask() { field_0x122d = 0; }
#endif
void offArrowDrawFlag() { mArrowDrawFlag = false; }
void onArrowDrawFlag() { mArrowDrawFlag = true; }
+5
View File
@@ -6,6 +6,8 @@
#include <stddef.h>
#include <stdint.h>
struct cXyz;
#ifdef __cplusplus
namespace dusk {
namespace frame_interp {
@@ -15,6 +17,7 @@ void ensure_initialized();
void begin_record();
void end_record();
void interpolate(float step);
float get_interpolation_step();
void notify_sim_tick_complete();
uint32_t begin_presentation_ui_pass();
uint32_t get_presentation_ui_advance_ticks();
@@ -27,6 +30,8 @@ void record_final_mtx_raw(const Mtx* dest, const Mtx src);
bool lookup_replacement(const void* source, Mtx out);
bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out);
void camera_eye_from_view_mtx(MtxP view_mtx, cXyz* o_eye);
} // namespace frame_interp
} // namespace dusk
#endif
+3 -1
View File
@@ -52,8 +52,9 @@ struct UserSettings {
// Graphics
ConfigVar<bool> enableBloom;
ConfigVar<bool> useWaterProjectionOffset;
ConfigVar<bool> enableWaterRefraction;
ConfigVar<bool> enableFrameInterpolation;
ConfigVar<int> shadowResolutionMultiplier;
// Audio
ConfigVar<bool> noLowHpSound;
@@ -77,6 +78,7 @@ struct UserSettings {
ConfigVar<std::string> graphicsBackend;
ConfigVar<bool> skipPreLaunchUI;
ConfigVar<bool> showPipelineCompilation;
ConfigVar<bool> wasPresetChosen;
} backend;
};
+3 -5
View File
@@ -15,12 +15,10 @@
#include <Windows.h>
#include <shellapi.h>
#include <intrin.h>
#else
#include "SDL3/SDL_timer.h"
#endif
#include "dusk/logging.h"
constexpr auto DUSK_FRAME_PERIOD = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double>(1001.0 / 30000.0));
class Limiter {
using delta_clock = std::chrono::high_resolution_clock;
using duration_t = std::chrono::nanoseconds;
@@ -101,7 +99,7 @@ private:
} while (current.QuadPart - start.QuadPart < ticksToWait);
}
#else
void NanoSleep(const duration_t duration) { std::this_thread::sleep_for(duration); }
void NanoSleep(const duration_t duration) { SDL_DelayPrecise(duration.count()); }
#endif
};
+19
View File
@@ -541,6 +541,9 @@ public:
virtual int getMaterialID() = 0;
virtual void setMaterial() = 0;
virtual void draw() = 0;
#if TARGET_PC
virtual void refreshGeometryForPresentationEye(const cXyz& eye) {}
#endif
/* 0x4 */ mDoExt_3DlineMat_c* field_0x4;
};
@@ -582,11 +585,19 @@ class dKy_tevstr_c;
class mDoExt_3DlineMat1_c : public mDoExt_3DlineMat_c {
public:
int init(u16, u16, ResTIMG*, int);
#if TARGET_PC
void update(int, GXColor&, dKy_tevstr_c*, const cXyz* presentationEye = nullptr);
void update(int, f32, GXColor&, u16, dKy_tevstr_c*, const cXyz* presentationEye = nullptr);
#else
void update(int, GXColor&, dKy_tevstr_c*);
void update(int, f32, GXColor&, u16, dKy_tevstr_c*);
#endif
int getMaterialID() { return 1; }
void setMaterial();
void draw();
#if TARGET_PC
void refreshGeometryForPresentationEye(const cXyz& eye) override;
#endif
cXyz* getPos(int i_idx) { return mpLines[i_idx].field_0x0; }
f32* getSize(int i_idx) { return mpLines[i_idx].field_0x4; }
@@ -600,6 +611,11 @@ private:
/* 0x34 */ u16 field_0x34;
/* 0x36 */ u8 mIsDrawn;
/* 0x38 */ mDoExt_3Dline_c* mpLines;
#if TARGET_PC
u8 mInterpLineKind;
f32 mInterpLineF;
u16 mInterpLineU16;
#endif
};
class mDoExt_3DlineMat2_c : public mDoExt_3DlineMat1_c {
@@ -616,6 +632,9 @@ public:
void setMatDark(mDoExt_3DlineMat_c* i_mat) { setMat(i_mat); }
void setMat(mDoExt_3DlineMat_c*);
#if TARGET_PC
mDoExt_3DlineMat_c* getFirstMat() const { return mp3DlineMat; }
#endif
virtual void draw();
virtual ~mDoExt_3DlineMatSortPacket() {}
@@ -113,9 +113,6 @@ struct J3DFogInfo {
bool operator==(J3DFogInfo&) const;
J3DFogInfo& operator=(const J3DFogInfo&);
// TODO: Fog data should be converted from big endian (probably?)
// Not sure TP uses it.
/* 0x00 */ u8 mType;
/* 0x01 */ u8 mAdjEnable;
/* 0x02 */ u16 mCenter;
@@ -9,6 +9,7 @@
#include "JSystem/JMath/JMath.h"
#include "JSystem/JSupport/JSupport.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "dusk/logging.h"
J3DMaterialFactory::J3DMaterialFactory(J3DMaterialBlock const& i_block) {
mMaterialNum = i_block.mMaterialNum;
@@ -656,7 +657,13 @@ J3DIndTexOrder J3DMaterialFactory::newIndTexOrder(int i_idx, int i_no) const {
J3DIndTexMtx J3DMaterialFactory::newIndTexMtx(int i_idx, int i_no) const {
J3DIndTexMtx dflt;
if (mpIndInitData[i_idx].mEnabled == true) {
#if TARGET_LITTLE_ENDIAN
J3DIndTexMtxInfo indTexMtxInfo = mpIndInitData[i_idx].mIndTexMtxInfo[i_no];
be_swap(indTexMtxInfo.field_0x0);
return indTexMtxInfo;
#else
return J3DIndTexMtx(mpIndInitData[i_idx].mIndTexMtxInfo[i_no]);
#endif
} else {
return dflt;
}
@@ -684,7 +691,19 @@ J3DFog J3DMaterialFactory::newFog(int i_idx) const {
J3DFog fog;
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
if (mtl_init_data->mFogIdx != 0xffff) {
#if TARGET_LITTLE_ENDIAN
J3DFogInfo fogInfo = mpFogInfo[mtl_init_data->mFogIdx];
be_swap(fogInfo.mCenter);
be_swap(fogInfo.mStartZ);
be_swap(fogInfo.mEndZ);
be_swap(fogInfo.mNearZ);
be_swap(fogInfo.mFarZ);
for (int i = 0; i < 10; i++)
be_swap(fogInfo.mFogAdjTable.r[i]);
fog.setFogInfo(fogInfo);
#else
fog.setFogInfo(mpFogInfo[mtl_init_data->mFogIdx]);
#endif
}
return fog;
}
+41 -27
View File
@@ -1,26 +1,30 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include <dolphin/gx.h>
#include <dolphin/vi.h>
#include <gx.h>
#include <stdint.h>
#include <vi.h>
#include "SDL3/SDL_timer.h"
#include "JSystem/J2DGraph/J2DOrthoGraph.h"
#include "JSystem/JFramework/JFWDisplay.h"
#include "JSystem/J2DGraph/J2DOrthoGraph.h"
#include "JSystem/JKernel/JKRHeap.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/JUtility/JUTConsole.h"
#include "JSystem/JUtility/JUTDbPrint.h"
#include "JSystem/JUtility/JUTProcBar.h"
#include "aurora/aurora.h"
#include <gx.h>
#include <vi.h>
#include "global.h"
#include <stdint.h>
#ifdef TARGET_PC
#include "dusk/dusk.h"
#include "dusk/gx_helper.h"
#include "dusk/logging.h"
#include "dusk/settings.h"
#include "global.h"
#include "dusk/time.h"
#include "SDL3/SDL_timer.h"
#include "tracy/Tracy.hpp"
#include <chrono>
#endif
void JFWDisplay::ctor_subroutine(bool enableAlpha) {
mEnableAlpha = enableAlpha;
mClamp = GX_CLAMP_TOP | GX_CLAMP_BOTTOM;
@@ -377,6 +381,19 @@ void JFWDisplay::waitBlanking(int param_0) {
}
}
#if TARGET_PC
constexpr auto FRAME_PERIOD = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::duration<double>(1001.0 / 30000.0));
constexpr auto RETRACE_PERIOD = FRAME_PERIOD / 2;
static void waitPrecise(Limiter& limiter, Uint64 targetNs) {
const auto sleepTime = limiter.SleepTime(std::chrono::nanoseconds(targetNs));
dusk::frameUsagePct =
100.0f * (1.0f - static_cast<float>(sleepTime.count()) / static_cast<float>(targetNs));
limiter.Sleep(std::chrono::nanoseconds(targetNs));
}
#endif
static void waitForTick(u32 p1, u16 p2) {
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
@@ -385,44 +402,42 @@ static void waitForTick(u32 p1, u16 p2) {
if (dusk::getTransientSettings().skipFrameRateLimit) {
p1 = OS_TIMER_CLOCK / 120;
}
ZoneScopedC(tracy::Color::DimGray);
#endif
ZoneScopedC(tracy::Color::DimGray);
if (p1 != 0)
{
if (p1 != 0) {
#if TARGET_PC
static Limiter limiter;
waitPrecise(limiter, static_cast<Uint64>(OSTicksToMicroseconds(p1)) * 1000ULL);
#else
static OSTime nextTick = OSGetTime();
OSTime time = OSGetTime();
OSTime waitTime = (nextTick > time) ? (nextTick - time) : 0;
while (time < nextTick) {
JFWDisplay::getManager()->threadSleep((nextTick - time));
time = OSGetTime();
}
dusk::frameUsagePct = 100.0f * (1.0f - (float)waitTime / (float)p1);
nextTick = time + p1;
#endif
} else {
static u32 nextCount = VIGetRetraceCount();
u32 uVar1 = (p2 == 0) ? 1 : p2;
#if TARGET_PC
static Limiter limiter;
waitPrecise(limiter, static_cast<Uint64>((RETRACE_PERIOD * uVar1).count()));
#else
static u32 nextCount = VIGetRetraceCount();
OSMessage msg;
do {
if (!OSReceiveMessage(JUTVideo::getManager()->getMessageQueue(), &msg,
OS_MESSAGE_BLOCK))
{
OS_MESSAGE_BLOCK)) {
msg = 0;
}
} while (((intptr_t)msg - (intptr_t)nextCount) < 0);
dusk::frameUsagePct = 100.0f;
nextCount = (intptr_t)msg + uVar1;
#endif
}
}
JSUList<JFWAlarm> JFWAlarm::sList(false);
#if TARGET_PC
void JFWDisplay::threadSleep(s64 time) {
SDL_DelayNS(OSTicksToMicroseconds(time) * 1'000);
}
#else
static void JFWThreadAlarmHandler(OSAlarm* p_alarm, OSContext* p_ctx) {
JFWAlarm* alarm = static_cast<JFWAlarm*>(p_alarm);
alarm->removeLink();
@@ -440,7 +455,6 @@ void JFWDisplay::threadSleep(s64 time) {
OSSuspendThread(alarm.getThread());
OSRestoreInterrupts(status);
}
#endif
static void dummy() {
JUTXfb::getManager()->setDisplayingXfbIndex(0);
@@ -480,7 +494,7 @@ void JFWDisplay::clearEfb(GXColor color) {
void JFWDisplay::clearEfb(int param_0, int param_1, int param_2, int param_3, GXColor color) {
STUB_RET();
u16 width;
u16 height;
Mtx44 mtx;
+2
View File
@@ -182,7 +182,9 @@ void JUTVideo::postRetraceProc(u32 retrace_count) {
sManager->mPostCallback(retrace_count);
}
#ifndef TARGET_PC // Not read by JFWDisplay waitForTick
OSSendMessage(&sManager->mMessageQueue, (OSMessage)(uintptr_t)VIGetRetraceCount(), OS_MESSAGE_NOBLOCK);
#endif
}
void JUTVideo::setRenderMode(GXRenderModeObj const* pObj) {
+53
View File
@@ -20,6 +20,21 @@
#include <cmath>
#include <cstring>
#if TARGET_PC
#include "dusk/dusk.h"
namespace {
// FRAME INTERP NOTE: Sim tick control point snapshots for interpolation
constexpr int kHorseReinSimMax = 75;
cXyz s_horseReinSimPrev[kHorseReinSimMax];
cXyz s_horseReinSimCurr[kHorseReinSimMax];
int s_horseReinSimNumPrev;
int s_horseReinSimNumCurr;
bool s_horseReinSimPrevValid;
bool s_horseReinSimCurrValid;
} // namespace
#endif
#define ANM_HS_BACK_WALK 6
#define ANM_HS_WALK_START 7
#define ANM_HS_EXCITEMENT 8
@@ -3016,6 +3031,20 @@ void daHorse_c::copyReinPos() {
for (i = rein->field_0x8[0] - 1; i >= 0; i--, pos_p++) {
*pos_p = rein->field_0x0[0][i];
}
#if TARGET_PC
if (field_0x1204 > 0) {
if (s_horseReinSimCurrValid && s_horseReinSimNumCurr > 0) {
memcpy(s_horseReinSimPrev, s_horseReinSimCurr, s_horseReinSimNumCurr * sizeof(cXyz));
s_horseReinSimNumPrev = s_horseReinSimNumCurr;
s_horseReinSimPrevValid = true;
}
memcpy(s_horseReinSimCurr, m_reinLine.getPos(0), field_0x1204 * sizeof(cXyz));
s_horseReinSimNumCurr = field_0x1204;
s_horseReinSimCurrValid = true;
} else {
s_horseReinSimCurrValid = false;
}
#endif
}
void daHorse_c::setReinPosHandSubstance(int param_0) {
@@ -3127,6 +3156,30 @@ void daHorse_c::setReinPosNormalSubstance() {
copyReinPos();
}
#if TARGET_PC
void daHorse_c::lerpControlPoints(f32 alpha) {
// FRAME INTERP NOTE: Currently only lerping points for Epona's reins. Need a more global solution.
if (!dusk::getSettings().game.enableFrameInterpolation || !s_horseReinSimPrevValid || !s_horseReinSimCurrValid) {
return;
}
const int nCurr = s_horseReinSimNumCurr;
const int nPrev = s_horseReinSimNumPrev;
if (nCurr <= 0) {
return;
}
int n = nPrev < nCurr ? nPrev : nCurr;
if (n <= 0 || n > kHorseReinSimMax) {
return;
}
cXyz* dst = m_reinLine.getPos(0);
for (int i = 0; i < n; i++) {
const cXyz& p0 = s_horseReinSimPrev[i];
const cXyz& p1 = s_horseReinSimCurr[i];
dst[i] = p0 + (p1 - p0) * alpha;
}
}
#endif
void daHorse_c::bgCheck() {
if (m_procID != PROC_LARGE_DAMAGE_e) {
static cXyz localCenterPos(0.0f, 100.0f, 0.0f);
-8
View File
@@ -300,19 +300,11 @@ int daGrdWater_c::Draw() {
J3DTexMtxInfo* mtxInfo = &material->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo();
if (mtxInfo != NULL) {
Mtx afStack_50;
#if TARGET_PC
C_MTXLightPerspective(afStack_50, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect,
1.0f, 1.0f, dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0.0f);
#else
C_MTXLightPerspective(afStack_50, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect,
1.0f, 1.0f, -0.01f, 0.0f);
#endif
#if WIDESCREEN_SUPPORT
mDoGph_gInf_c::setWideZoomLightProjection(afStack_50);
#endif
mtxInfo->setEffectMtx(afStack_50);
modelData2->simpleCalcMaterial(0, (MtxP)j3dDefaultMtx);
}
-7
View File
@@ -371,15 +371,8 @@ int daLv3Water_c::Draw() {
texMtxInfo = &material->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo();
if (texMtxInfo != NULL) {
Mtx lightProjMtx;
#if TARGET_PC
C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy,
dComIfGd_getView()->aspect, 1.0f, 1.0f, dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0.0f);
#else
C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy,
dComIfGd_getView()->aspect, 1.0f, 1.0f, -0.01f, 0.0f);
#endif
#if WIDESCREEN_SUPPORT
mDoGph_gInf_c::setWideZoomLightProjection(lightProjMtx);
#endif
-7
View File
@@ -197,14 +197,7 @@ int daLv3Water2_c::Draw() {
texMtxInfo = &btkMaterial->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo();
if(texMtxInfo) {
Mtx lightProjMtx;
#if TARGET_PC
C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy,
dComIfGd_getView()->aspect, 1.0f, 1.0f, dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0);
#else
C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect, 1.0f, 1.0f, -0.01f, 0);
#endif
#if WIDESCREEN_SUPPORT
mDoGph_gInf_c::setWideZoomLightProjection(lightProjMtx);
#endif
-7
View File
@@ -27,15 +27,8 @@ static int daObj_Lv3waterB_Draw(obj_lv3WaterB_class* i_this) {
J3DTexMtxInfo* tex_mtx_info = &material_p->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo();
if (tex_mtx_info != NULL) {
Mtx m;
#if TARGET_PC
C_MTXLightPerspective(m, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect, 1.0f, 1.0f,
dusk::getSettings().game.useWaterProjectionOffset ? -0.015f : 0.0f, 0.0f);
#else
C_MTXLightPerspective(m, dComIfGd_getView()->fovy, dComIfGd_getView()->aspect, 1.0f,
1.0f, -0.015f, 0.0f);
#endif
#if WIDESCREEN_SUPPORT
mDoGph_gInf_c::setWideZoomLightProjection(m);
#endif
-7
View File
@@ -313,15 +313,8 @@ int daObjRotStair_c::Draw() {
J3DTexMtxInfo* texMtxInfo = &material->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo();
if (texMtxInfo != NULL) {
Mtx lightMtx;
#if TARGET_PC
C_MTXLightPerspective(lightMtx, dComIfGd_getView()->fovy,
dComIfGd_getView()->aspect, 1.0f, 1.0f, dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0);
#else
C_MTXLightPerspective(lightMtx, dComIfGd_getView()->fovy,
dComIfGd_getView()->aspect, 1.0f, 1.0f, -0.01f, 0);
#endif
#if WIDESCREEN_SUPPORT
mDoGph_gInf_c::setWideZoomLightProjection(lightMtx);
#endif
-7
View File
@@ -36,15 +36,8 @@ static int daObj_Tp_Draw(obj_tp_class* i_this) {
&material->getTexGenBlock()->getTexMtx(0)->getTexMtxInfo();
if (texMtxInfo != NULL) {
Mtx lightProjMtx;
#if TARGET_PC
C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy,
dComIfGd_getView()->aspect, 1.0f, 1.0f, dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0);
#else
C_MTXLightPerspective(lightProjMtx, dComIfGd_getView()->fovy,
dComIfGd_getView()->aspect, 1.0f, 1.0f, -0.01f, 0);
#endif
#if WIDESCREEN_SUPPORT
mDoGph_gInf_c::setWideZoomLightProjection(lightProjMtx);
#endif
+27 -1
View File
@@ -1441,7 +1441,11 @@ void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* pa
void dDlst_shadowControl_c::init() {
#if TARGET_PC
// Increase shadow map resolution
static u16 l_realImageSize[2] = {1024, 512};
u16 l_realImageSize[2] =
{
192 * dusk::getSettings().game.shadowResolutionMultiplier,
64 * dusk::getSettings().game.shadowResolutionMultiplier
};
#else
static u16 l_realImageSize[2] = {192, 64};
#endif
@@ -1480,7 +1484,19 @@ void dDlst_shadowControl_c::reset() {
#endif
}
#if TARGET_PC
int lastShadowValue = 0;
#endif
void dDlst_shadowControl_c::imageDraw(Mtx param_0) {
#if TARGET_PC
if (lastShadowValue != dusk::getSettings().game.shadowResolutionMultiplier) {
reset();
init();
lastShadowValue = dusk::getSettings().game.shadowResolutionMultiplier;
}
#endif
static u8 l_matDL[] ATTRIBUTE_ALIGN(32) = {
0x10, 0x00, 0x00, 0x10, 0x0E, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10,
0x00, 0x00, 0x04, 0x00, 0x61, 0x28, 0x38, 0x00, 0x00, 0x61, 0xC0, 0x08, 0xFF, 0xF2,
@@ -2001,3 +2017,13 @@ void dDlst_list_c::calcWipe() {
dComIfGd_set2DXlu(&mWipeDlst);
}
}
#if TARGET_PC
void dDlst_list_c::refresh3DlineMats(const cXyz& eye) {
for (int i = 0; i < 3; i++) {
for (mDoExt_3DlineMat_c* mat = m3DLineMatSortPacket[i].getFirstMat(); mat != NULL; mat = mat->field_0x4) {
mat->refreshGeometryForPresentationEye(eye);
}
}
}
#endif
-4
View File
@@ -11393,11 +11393,7 @@ void dKy_bg_MAxx_proc(void* bg_model_p) {
if (mat_name[6] == '2') {
C_MTXLightPerspective(sp1D8, dComIfGd_getView()->fovy,
camera_p->view.aspect, 1.0f, 1.0f,
#if TARGET_PC
dusk::getSettings().game.useWaterProjectionOffset ? -0.01f : 0.0f, 0.0f);
#else
-0.01f, 0.0f);
#endif
} else {
C_MTXLightPerspective(sp1D8, dComIfGd_getView()->fovy,
camera_p->view.aspect, 0.49f, -0.49f, 0.5f, 0.5f);
+6
View File
@@ -1133,6 +1133,12 @@ void dMenu_Fmap_c::zoom_region_to_spot_proc() {
void dMenu_Fmap_c::zoom_spot_to_region_init() {
mZoomLevel = 10;
field_0x1ec = 1.0f;
#if TARGET_PC
// Frame interp note: field_0x122d used to be set every draw, causing flickering. Do it here instead.
if (dusk::getSettings().game.enableFrameInterpolation) {
mpDraw2DBack->resetScrollArrowMask();
}
#endif
Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_ZOOMOUT, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
}
+6
View File
@@ -432,7 +432,13 @@ void dMenu_Fmap2DBack_c::draw() {
if (field_0x122d) {
mpMeterHaihai->drawHaihai(field_0x122d);
#if TARGET_PC
if (!dusk::getSettings().game.enableFrameInterpolation) {
field_0x122d = 0;
}
#else
field_0x122d = 0;
#endif
}
if (g_fmapHIO.mRangeCheck && !g_fmapHIO.mRangeCheckDrawPriority) {
+2
View File
@@ -39,7 +39,9 @@
#include "JSystem/JKernel/JKRAram.h"
#include "JSystem/JKernel/JKRAramArchive.h"
#if TARGET_PC
#include "dusk/memory.h"
#endif
#if DEBUG
#include "d/d_s_menu.h"
+11
View File
@@ -300,6 +300,10 @@ void interpolate(float step) {
interpolate_branch(g_previous_recording.root, g_current_recording.root, g_step);
}
float get_interpolation_step() {
return g_step;
}
void notify_sim_tick_complete() {
ensure_initialized();
g_pending_presentation_ui_ticks++;
@@ -394,5 +398,12 @@ bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out) {
return true;
}
// TODO: Is there already a built-in function for this?
void camera_eye_from_view_mtx(MtxP view_mtx, cXyz* o_eye) {
o_eye->x = -(view_mtx[0][0] * view_mtx[0][3] + view_mtx[1][0] * view_mtx[1][3] + view_mtx[2][0] * view_mtx[2][3]);
o_eye->y = -(view_mtx[0][1] * view_mtx[0][3] + view_mtx[1][1] * view_mtx[1][3] + view_mtx[2][1] * view_mtx[2][3]);
o_eye->z = -(view_mtx[0][2] * view_mtx[0][3] + view_mtx[1][2] * view_mtx[1][3] + view_mtx[2][2] * view_mtx[2][3]);
}
} // namespace frame_interp
} // namespace dusk
+10 -4
View File
@@ -206,10 +206,6 @@ namespace dusk {
void ImGuiConsole::PreDraw() {
ZoneScoped;
if (dusk::IsGameLaunched && !m_isLaunchInitialized) {
m_toasts.emplace_back("Press F1 to toggle menu"s, 5.f);
m_isLaunchInitialized = true;
}
UpdateSettings();
@@ -241,6 +237,16 @@ namespace dusk {
m_preLaunchWindow.draw();
}
if (!getSettings().backend.wasPresetChosen) {
m_firstRunPreset.draw();
return;
}
if (dusk::IsGameLaunched && !m_isLaunchInitialized) {
m_toasts.emplace_back("Press F1 to toggle menu"s, 5.f);
m_isLaunchInitialized = true;
}
m_menuGame.windowControllerConfig();
m_menuGame.windowInputViewer();
if (dusk::IsGameLaunched) {
+2
View File
@@ -6,6 +6,7 @@
#include <string>
#include <string_view>
#include "ImGuiFirstRunPreset.hpp"
#include "ImGuiMenuEnhancements.hpp"
#include "ImGuiMenuGame.hpp"
#include "ImGuiMenuTools.hpp"
@@ -35,6 +36,7 @@ private:
bool m_isLaunchInitialized = false;
std::deque<Toast> m_toasts;
ImGuiFirstRunPreset m_firstRunPreset;
ImGuiMenuGame m_menuGame;
ImGuiMenuEnhancements m_menuEnhancements;
ImGuiPreLaunchWindow m_preLaunchWindow;
+1 -1
View File
@@ -144,7 +144,7 @@ void ImGuiEngine_Initialize(float scale) {
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.60f);
}
Image GetImage(const std::string& path) {
+132
View File
@@ -0,0 +1,132 @@
#include "ImGuiFirstRunPreset.hpp"
#include "imgui.h"
#include "ImGuiConsole.hpp"
#include "ImGuiEngine.hpp"
#include "dusk/settings.h"
#include "dusk/config.hpp"
#include <dusk/dusk.h>
namespace dusk {
static void ApplyPresetClassic() {
auto& s = getSettings();
s.video.lockAspectRatio.setValue(true);
VILockAspectRatio(defaultAspectRatioW, defaultAspectRatioH);
}
static void ApplyPresetHD() {
auto& s = getSettings();
s.game.hideTvSettingsScreen.setValue(true);
s.game.noReturnRupees.setValue(true);
s.game.disableRupeeCutscenes.setValue(true);
s.game.noSwordRecoil.setValue(true);
s.game.fastClimbing.setValue(true);
s.game.noMissClimbing.setValue(true);
s.game.fastTears.setValue(true);
s.game.biggerWallets.setValue(true);
s.game.invertCameraXAxis.setValue(true);
}
static void ApplyPresetDusk() {
ApplyPresetHD();
auto& s = getSettings();
s.game.enableQuickTransform.setValue(true);
s.game.instantSaves.setValue(true);
s.game.midnasLamentNonStop.setValue(true);
s.game.enableFrameInterpolation.setValue(true);
}
// =========================================================================
void ImGuiFirstRunPreset::draw() {
const char* modalTitle = "Welcome to Dusk!";
if (m_done) return;
if (!m_opened) {
ImGui::OpenPopup(modalTitle);
m_opened = true;
}
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
ImGui::SetNextWindowSize(ImVec2(800.0f * ImGuiScale(), 0.0f), ImGuiCond_Always);
if (!ImGui::BeginPopupModal(modalTitle, nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) {
// force the user to actually pick one, and not just hit escape to skip the dialog
m_opened = false;
return;
}
ImGui::TextWrapped("Choose a preset to get started. You can change any setting later from the Enhancements menu.");
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
int chosen = -1;
if (ImGui::BeginTable("##presets", 5, ImGuiTableFlags_None)) {
ImGui::TableSetupColumn(nullptr, ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn(nullptr, ImGuiTableColumnFlags_WidthFixed, 16.0f * ImGuiScale());
ImGui::TableSetupColumn(nullptr, ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn(nullptr, ImGuiTableColumnFlags_WidthFixed, 16.0f * ImGuiScale());
ImGui::TableSetupColumn(nullptr, ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow();
ImGui::PushFont(ImGuiEngine::fontLarge);
ImGui::TableSetColumnIndex(0);
if (ImGui::Button("Classic##btn", ImVec2(ImGui::GetContentRegionAvail().x, 80.0f * ImGuiScale()))) {
chosen = 0;
}
ImGui::TableSetColumnIndex(2);
if (ImGui::Button("HD##btn", ImVec2(ImGui::GetContentRegionAvail().x, 80.0f * ImGuiScale()))) {
chosen = 1;
}
ImGui::TableSetColumnIndex(4);
if (ImGui::Button("Dusk##btn", ImVec2(ImGui::GetContentRegionAvail().x, 80.0f * ImGuiScale())))
{
chosen = 2;
}
ImGui::PopFont();
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Spacing();
ImGui::TextWrapped("All enhancements disabled to match the GameCube version. Good for speedrunning or simple nostalgia!");
ImGui::TableSetColumnIndex(2);
ImGui::Spacing();
ImGui::TextWrapped("Some enhancements enabled to match the HD version. A good starting point for most players!");
ImGui::TableSetColumnIndex(4);
ImGui::Spacing();
ImGui::TextWrapped("More enhancements enabled than the HD preset. Veteran players will appreciate the additional tweaks!");
ImGui::EndTable();
}
if (chosen >= 0) {
if (chosen == 0) ApplyPresetClassic();
if (chosen == 1) ApplyPresetHD();
if (chosen == 2) ApplyPresetDusk();
getSettings().backend.wasPresetChosen.setValue(true);
config::Save();
m_done = true;
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
} // namespace dusk
+14
View File
@@ -0,0 +1,14 @@
#pragma once
namespace dusk {
class ImGuiFirstRunPreset {
public:
void draw();
private:
bool m_opened = false;
bool m_done = false;
};
} // namespace dusk
+5
View File
@@ -85,6 +85,11 @@ namespace dusk {
ImGui::SetTooltip("Uses inter-frame interpolation to enable higher frame rates.\nVisual artifacts, animation glitches, or instability may occur.");
}
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::EndMenu();
}
+1 -5
View File
@@ -64,11 +64,7 @@ namespace dusk {
config::ImGuiCheckbox("Native Bloom", getSettings().game.enableBloom);
config::ImGuiCheckbox("Water Projection Offset", getSettings().game.useWaterProjectionOffset);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Adds GC-specific -0.01 transS offset\n"
"that causes ~6px ghost artifacts in water reflections.");
}
config::ImGuiCheckbox("Enable Water Refraction", getSettings().game.enableWaterRefraction);
ImGui::EndMenu();
}
+521 -1
View File
@@ -7,6 +7,8 @@
#include "d/d_com_inf_game.h"
#include "d/d_item_data.h"
#include "d/d_meter2_info.h"
#include "d/d_save.h"
#include <map>
@@ -280,6 +282,132 @@ namespace dusk {
{ dItemNo_NONE_e, {"None"} },
};
static constexpr int BUG_SPECIES_COUNT = 12;
static const u8 sBugItemIds[BUG_SPECIES_COUNT * 2] = {
dItemNo_M_ANT_e, dItemNo_F_ANT_e,
dItemNo_M_MAYFLY_e, dItemNo_F_MAYFLY_e,
dItemNo_M_BEETLE_e, dItemNo_F_BEETLE_e,
dItemNo_M_MANTIS_e, dItemNo_F_MANTIS_e,
dItemNo_M_STAG_BEETLE_e, dItemNo_F_STAG_BEETLE_e,
dItemNo_M_DANGOMUSHI_e, dItemNo_F_DANGOMUSHI_e,
dItemNo_M_BUTTERFLY_e, dItemNo_F_BUTTERFLY_e,
dItemNo_M_LADYBUG_e, dItemNo_F_LADYBUG_e,
dItemNo_M_SNAIL_e, dItemNo_F_SNAIL_e,
dItemNo_M_NANAFUSHI_e, dItemNo_F_NANAFUSHI_e,
dItemNo_M_GRASSHOPPER_e, dItemNo_F_GRASSHOPPER_e,
dItemNo_M_DRAGONFLY_e, dItemNo_F_DRAGONFLY_e,
};
static const u16 sBugTurnInFlags[BUG_SPECIES_COUNT * 2] = {
dSv_event_flag_c::F_0421, dSv_event_flag_c::F_0422,
dSv_event_flag_c::F_0423, dSv_event_flag_c::F_0424,
dSv_event_flag_c::F_0401, dSv_event_flag_c::F_0402,
dSv_event_flag_c::F_0413, dSv_event_flag_c::F_0414,
dSv_event_flag_c::F_0405, dSv_event_flag_c::F_0406,
dSv_event_flag_c::F_0411, dSv_event_flag_c::F_0412,
dSv_event_flag_c::F_0403, dSv_event_flag_c::F_0404,
dSv_event_flag_c::F_0415, dSv_event_flag_c::F_0416,
dSv_event_flag_c::F_0417, dSv_event_flag_c::F_0418,
dSv_event_flag_c::F_0409, dSv_event_flag_c::F_0410,
dSv_event_flag_c::F_0407, dSv_event_flag_c::F_0408,
dSv_event_flag_c::F_0419, dSv_event_flag_c::F_0420,
};
static const char* sBugSpeciesNames[BUG_SPECIES_COUNT] = {
"Ant", "Dayfly", "Beetle", "Mantis",
"Stag Beetle", "Pill Bug", "Butterfly", "Ladybug",
"Snail", "Phasmid", "Grasshopper", "Dragonfly",
};
static constexpr int HIDDEN_SKILL_COUNT = 7;
static const u16 sHiddenSkillFlags[HIDDEN_SKILL_COUNT] = {
dSv_event_flag_c::F_0339, dSv_event_flag_c::F_0338,
dSv_event_flag_c::F_0340, dSv_event_flag_c::F_0341,
dSv_event_flag_c::F_0342, dSv_event_flag_c::F_0343,
dSv_event_flag_c::F_0344,
};
static const char* sHiddenSkillNames[HIDDEN_SKILL_COUNT] = {
"Ending Blow", "Shield Attack", "Back Slice", "Helm Splitter",
"Mortal Draw", "Jump Strike", "Great Spin",
};
static constexpr int LETTER_COUNT = 16;
static const char* sLetterSenders[LETTER_COUNT] = {
"Renado", "Ooccoo 1", "Ooccoo 2", "The Postman",
"Kakariko Goods", "Barnes 1", "Barnes 2", "Barnes Bombs",
"Malo Mart", "Telma", "Purlo", "From Jr.",
"Princess Agitha", "Lanayru Tourism", "Shad", "Yeta",
};
static constexpr int FISH_COUNT = 6;
static const struct {
u8 index;
const char* name;
} sFishSpecies[FISH_COUNT] = {
{ 3, "Ordon Catfish" },
{ 5, "Greengill" },
{ 4, "Reekfish" },
{ 0, "Hyrule Bass" },
{ 2, "Hylian Pike" },
{ 1, "Hylian Loach" },
};
static const char* sSwordNames[4] = {
"Ordon Sword", "Master Sword", "Wooden Sword", "Light Sword",
};
static const char* sShieldNames[3] = {
"Wooden Shield", "Ordon Shield", "Hylian Shield",
};
static const char* sFusedShadowNames[3] = {
"Forest Temple",
"Goron Mines",
"Lakebed Temple",
};
static const struct {
u8 index;
const char* name;
} sMirrorShards[3] = {
{ 1, "Snowpeak Ruins" },
{ 2, "Temple of Time" },
{ 3, "City in the Sky" },
};
static const struct {
u8 slot;
u8 item;
} sDefaultInventory[] = {
{ SLOT_0, dItemNo_BOOMERANG_e },
{ SLOT_1, dItemNo_KANTERA_e },
{ SLOT_2, dItemNo_SPINNER_e },
{ SLOT_3, dItemNo_HVY_BOOTS_e },
{ SLOT_4, dItemNo_BOW_e },
{ SLOT_5, dItemNo_HAWK_EYE_e },
{ SLOT_6, dItemNo_IRONBALL_e },
{ SLOT_8, dItemNo_COPY_ROD_e },
{ SLOT_9, dItemNo_HOOKSHOT_e },
{ SLOT_10, dItemNo_W_HOOKSHOT_e },
{ SLOT_11, dItemNo_EMPTY_BOTTLE_e },
{ SLOT_12, dItemNo_EMPTY_BOTTLE_e },
{ SLOT_13, dItemNo_EMPTY_BOTTLE_e },
{ SLOT_14, dItemNo_EMPTY_BOTTLE_e },
{ SLOT_15, dItemNo_NORMAL_BOMB_e },
{ SLOT_16, dItemNo_WATER_BOMB_e },
{ SLOT_17, dItemNo_POKE_BOMB_e },
{ SLOT_18, dItemNo_DUNGEON_EXIT_e },
{ SLOT_20, dItemNo_FISHING_ROD_1_e},
{ SLOT_21, dItemNo_HORSE_FLUTE_e },
{ SLOT_22, dItemNo_ANCIENT_DOCUMENT_e },
{ SLOT_23, dItemNo_PACHINKO_e },
};
ImGuiSaveEditor::ImGuiSaveEditor() {}
void ImGuiSaveEditor::draw(bool& open) {
@@ -307,7 +435,7 @@ namespace dusk {
}
if (ImGui::BeginTabItem("Collection")) {
//DrawFlagsTab();
drawCollectionTab();
ImGui::EndTabItem();
}
@@ -675,9 +803,30 @@ namespace dusk {
}
}
static u8 getSlotDefault(int slot) {
for (size_t i = 0; i < sizeof(sDefaultInventory) / sizeof(sDefaultInventory[0]); i++) {
if (sDefaultInventory[i].slot == slot) {
return sDefaultInventory[i].item;
}
}
return dItemNo_NONE_e;
}
void ImGuiSaveEditor::drawInventoryTab() {
dSv_player_item_c& item = dComIfGs_getSaveData()->getPlayer().getItem();
if (ImGui::Button("Default All##inv_default_all")) {
for (int slot = 0; slot < 24; slot++) {
dComIfGs_setItem(slot, getSlotDefault(slot));
}
}
ImGui::SameLine();
if (ImGui::Button("Clear All##inv_clear_all")) {
for (int slot = 0; slot < 24; slot++) {
dComIfGs_setItem(slot, dItemNo_NONE_e);
}
}
ImGuiBeginGroupPanel("Items", { 200, 100 });
for (int slot = 0; slot < 24; slot++) {
ImGui::Text("Slot %02d: ", slot);
@@ -696,12 +845,369 @@ namespace dusk {
}
ImGui::EndCombo();
}
ImGui::SameLine();
if (ImGui::SmallButton(fmt::format("Default##slot_d_{}", slot).c_str())) {
dComIfGs_setItem(slot, getSlotDefault(slot));
}
ImGui::SameLine();
if (ImGui::SmallButton(fmt::format("Clear##slot_c_{}", slot).c_str())) {
dComIfGs_setItem(slot, dItemNo_NONE_e);
}
}
ImGuiEndGroupPanel();
}
static inline void setItemFirstBit(u8 itemNo, bool owned) {
if (owned) {
dComIfGs_onItemFirstBit(itemNo);
} else {
dComIfGs_offItemFirstBit(itemNo);
}
}
static inline void setEventBit(u16 flag, bool on) {
if (on) {
dComIfGs_onEventBit(flag);
} else {
dComIfGs_offEventBit(flag);
}
}
static void setLetterGetFlag(int idx, bool received) {
dSv_letter_info_c& info = dComIfGs_getSaveData()->getPlayer().getLetterInfo();
if (received) {
if (dComIfGs_isLetterGetFlag(idx)) return;
dComIfGs_onLetterGetFlag(idx);
u8 slot = dMeter2Info_getRecieveLetterNum() - 1;
if (slot < 64) {
dComIfGs_setGetNumber(slot, (u8)(idx + 1));
}
} else {
if (!dComIfGs_isLetterGetFlag(idx)) return;
info.mLetterGetFlags[idx >> 5] &= ~(1u << (idx & 0x1F));
for (int j = 0; j < 64; j++) {
if (dComIfGs_getGetNumber(j) == idx + 1) {
for (int k = j; k < 63; k++) {
dComIfGs_setGetNumber(k, dComIfGs_getGetNumber(k + 1));
}
dComIfGs_setGetNumber(63, 0);
break;
}
}
}
}
void ImGuiSaveEditor::drawCollectionTab() {
if (ImGui::TreeNode("Equipment")) {
if (ImGui::TreeNode("Swords")) {
for (int i = 0; i < 4; i++) {
bool got = dComIfGs_isCollectSword((u8)i) != 0;
if (ImGui::Checkbox(fmt::format("{0}##sword_{1}", sSwordNames[i], i).c_str(), &got)) {
if (got) dComIfGs_setCollectSword((u8)i);
else dComIfGs_offCollectSword((u8)i);
}
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Shields")) {
for (int i = 0; i < 3; i++) {
bool got = dComIfGs_isCollectShield((u8)i) != 0;
if (ImGui::Checkbox(fmt::format("{0}##shield_{1}", sShieldNames[i], i).c_str(), &got)) {
if (got) dComIfGs_setCollectShield((u8)i);
else dComIfGs_offCollectShield((u8)i);
}
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Tunics")) {
bool ordonClothes = dComIfGs_isItemFirstBit(dItemNo_WEAR_CASUAL_e) != 0;
if (ImGui::Checkbox("Ordon Clothes##tunic_ordon", &ordonClothes)) {
setItemFirstBit(dItemNo_WEAR_CASUAL_e, ordonClothes);
}
bool greenTunic = dComIfGs_isCollectClothes(KOKIRI_CLOTHES_FLAG) != 0;
if (ImGui::Checkbox("Hero's Clothes##tunic_green", &greenTunic)) {
if (greenTunic) dComIfGs_setCollectClothes(KOKIRI_CLOTHES_FLAG);
else dComIfGs_offCollectClothes(KOKIRI_CLOTHES_FLAG);
}
bool zoraArmor = dComIfGs_isItemFirstBit(dItemNo_WEAR_ZORA_e) != 0;
if (ImGui::Checkbox("Zora Armor##tunic_zora", &zoraArmor)) {
setItemFirstBit(dItemNo_WEAR_ZORA_e, zoraArmor);
}
bool magicArmor = dComIfGs_isItemFirstBit(dItemNo_ARMOR_e) != 0;
if (ImGui::Checkbox("Magic Armor##tunic_magic", &magicArmor)) {
setItemFirstBit(dItemNo_ARMOR_e, magicArmor);
}
ImGui::TreePop();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Key Items")) {
if (ImGui::TreeNode("Fused Shadows")) {
for (int i = 0; i < 3; i++) {
bool got = dComIfGs_isCollectCrystal((u8)i) != 0;
if (ImGui::Checkbox(
fmt::format("{0}##fs_{1}", sFusedShadowNames[i], i).c_str(), &got)) {
if (got) dComIfGs_onCollectCrystal((u8)i);
else dComIfGs_offCollectCrystal((u8)i);
}
}
ImGui::Spacing();
if (ImGui::Button("All##fs_all")) {
for (int i = 0; i < 3; i++) dComIfGs_onCollectCrystal((u8)i);
}
ImGui::SameLine();
if (ImGui::Button("None##fs_clear")) {
for (int i = 0; i < 3; i++) dComIfGs_offCollectCrystal((u8)i);
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Mirror Shards")) {
for (int i = 0; i < 3; i++) {
u8 idx = sMirrorShards[i].index;
bool got = dComIfGs_isCollectMirror(idx) != 0;
if (ImGui::Checkbox(
fmt::format("{0}##ms_{1}", sMirrorShards[i].name, i).c_str(), &got)) {
if (got) dComIfGs_onCollectMirror(idx);
else dComIfGs_offCollectMirror(idx);
}
}
ImGui::Spacing();
if (ImGui::Button("All##ms_all")) {
for (int i = 0; i < 3; i++) dComIfGs_onCollectMirror(sMirrorShards[i].index);
}
ImGui::SameLine();
if (ImGui::Button("None##ms_clear")) {
for (int i = 0; i < 3; i++) dComIfGs_offCollectMirror(sMirrorShards[i].index);
}
ImGui::TreePop();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Heart Pieces & Poe Souls")) {
if (ImGui::TreeNode("Poe Souls")) {
int poeCount = dComIfGs_getPohSpiritNum();
ImGui::Text("Collected:");
ImGui::SameLine();
ImGui::SetNextItemWidth(100.0f);
if (ImGui::InputInt("##poe_count", &poeCount)) {
if (poeCount < 0) poeCount = 0;
if (poeCount > 60) poeCount = 60;
dComIfGs_setPohSpiritNum((u8)poeCount);
}
ImGui::SameLine();
ImGui::TextDisabled("/ 60");
ImGui::Spacing();
if (ImGui::Button("All 60##poe_all")) {
dComIfGs_setPohSpiritNum(60);
}
ImGui::SameLine();
if (ImGui::Button("Clear##poe_clear")) {
dComIfGs_setPohSpiritNum(0);
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Heart Pieces")) {
int maxLife = dComIfGs_getMaxLife();
int hearts = maxLife / 5;
int pieces = maxLife % 5;
ImGui::Text("Max Life:");
ImGui::SameLine();
ImGui::SetNextItemWidth(160.0f);
if (ImGui::InputInt("##max_life", &maxLife, 1, 5)) {
if (maxLife < 15) maxLife = 15;
if (maxLife > 100) maxLife = 100;
dComIfGs_setMaxLife((u8)maxLife);
u16 maxHealth = (dComIfGs_getMaxLife() / 5) * 4;
if (dComIfGs_getLife() > maxHealth) {
dComIfGs_setLife(maxHealth);
}
}
ImGui::SameLine();
ImGui::TextDisabled("(%d hearts + %d pieces)", hearts, pieces);
ImGui::Spacing();
if (ImGui::Button("3 Hearts##hp_min")) {
dComIfGs_setMaxLife(15);
dComIfGs_setLife(12);
}
ImGui::SameLine();
if (ImGui::Button("20 Hearts##hp_max")) {
dComIfGs_setMaxLife(100);
dComIfGs_setLife(80);
}
ImGui::TreePop();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Golden Bugs")) {
if (ImGui::BeginTable("GoldenBugTable", 5,
ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
ImGui::TableSetupColumn("Species");
ImGui::TableSetupColumn("Male");
ImGui::TableSetupColumn("Female");
ImGui::TableSetupColumn("M \xe2\x86\x92 Agitha"); // M → Agitha
ImGui::TableSetupColumn("F \xe2\x86\x92 Agitha"); // F → Agitha
ImGui::TableHeadersRow();
for (int species = 0; species < BUG_SPECIES_COUNT; species++) {
int maleIdx = species * 2;
int femaleIdx = species * 2 + 1;
u8 maleItem = sBugItemIds[maleIdx];
u8 femaleItem = sBugItemIds[femaleIdx];
u16 maleFlag = sBugTurnInFlags[maleIdx];
u16 femaleFlag = sBugTurnInFlags[femaleIdx];
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::TextUnformatted(sBugSpeciesNames[species]);
ImGui::TableSetColumnIndex(1);
bool maleOwned = dComIfGs_isItemFirstBit(maleItem) != 0;
if (ImGui::Checkbox(fmt::format("##bugM_own_{}", species).c_str(), &maleOwned)) {
setItemFirstBit(maleItem, maleOwned);
}
ImGui::TableSetColumnIndex(2);
bool femaleOwned = dComIfGs_isItemFirstBit(femaleItem) != 0;
if (ImGui::Checkbox(fmt::format("##bugF_own_{}", species).c_str(), &femaleOwned)) {
setItemFirstBit(femaleItem, femaleOwned);
}
ImGui::TableSetColumnIndex(3);
bool maleGiven = dComIfGs_isEventBit(maleFlag) != 0;
if (ImGui::Checkbox(fmt::format("##bugM_giv_{}", species).c_str(), &maleGiven)) {
setEventBit(maleFlag, maleGiven);
}
ImGui::TableSetColumnIndex(4);
bool femaleGiven = dComIfGs_isEventBit(femaleFlag) != 0;
if (ImGui::Checkbox(fmt::format("##bugF_giv_{}", species).c_str(), &femaleGiven)) {
setEventBit(femaleFlag, femaleGiven);
}
}
ImGui::EndTable();
}
ImGui::Spacing();
if (ImGui::Button("Collect All##bugs_all")) {
for (int i = 0; i < BUG_SPECIES_COUNT * 2; i++) {
dComIfGs_onItemFirstBit(sBugItemIds[i]);
}
}
ImGui::SameLine();
if (ImGui::Button("Clear All##bugs_clear")) {
for (int i = 0; i < BUG_SPECIES_COUNT * 2; i++) {
dComIfGs_offItemFirstBit(sBugItemIds[i]);
dComIfGs_offEventBit(sBugTurnInFlags[i]);
}
}
ImGui::SameLine();
if (ImGui::Button("Give All to Agitha##bugs_giveall")) {
for (int i = 0; i < BUG_SPECIES_COUNT * 2; i++) {
dComIfGs_onEventBit(sBugTurnInFlags[i]);
}
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Hidden Skills")) {
for (int i = 0; i < HIDDEN_SKILL_COUNT; i++) {
bool learned = dComIfGs_isEventBit(sHiddenSkillFlags[i]) != 0;
if (ImGui::Checkbox(
fmt::format("{0}##skill_{1}", sHiddenSkillNames[i], i).c_str(), &learned)) {
setEventBit(sHiddenSkillFlags[i], learned);
}
}
ImGui::Spacing();
if (ImGui::Button("Learn All##skills_all")) {
for (int i = 0; i < HIDDEN_SKILL_COUNT; i++) {
dComIfGs_onEventBit(sHiddenSkillFlags[i]);
}
}
ImGui::SameLine();
if (ImGui::Button("Forget All##skills_clear")) {
for (int i = 0; i < HIDDEN_SKILL_COUNT; i++) {
dComIfGs_offEventBit(sHiddenSkillFlags[i]);
}
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Collection Logs")) {
if (ImGui::TreeNode("Postman Letters")) {
for (int i = 0; i < LETTER_COUNT; i++) {
bool had = dComIfGs_isLetterGetFlag(i) != 0;
if (ImGui::Checkbox(
fmt::format("{0}##letter_{1}", sLetterSenders[i], i).c_str(), &had)) {
setLetterGetFlag(i, had);
}
}
ImGui::Spacing();
if (ImGui::Button("Receive All##letters_all")) {
for (int i = 0; i < LETTER_COUNT; i++) setLetterGetFlag(i, true);
}
ImGui::SameLine();
if (ImGui::Button("Clear All##letters_clear")) {
for (int i = 0; i < LETTER_COUNT; i++) setLetterGetFlag(i, false);
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Fishing Log")) {
dSv_fishing_info_c& fish = dComIfGs_getSaveData()->getPlayer().getFishingInfo();
if (ImGui::BeginTable("FishTable", 3,
ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
ImGui::TableSetupColumn("Species");
ImGui::TableSetupColumn("Caught");
ImGui::TableSetupColumn("Biggest (cm)");
ImGui::TableHeadersRow();
for (int i = 0; i < FISH_COUNT; i++) {
u8 idx = sFishSpecies[i].index;
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::TextUnformatted(sFishSpecies[i].name);
ImGui::TableSetColumnIndex(1);
int count = dComIfGs_getFishNum(idx);
ImGui::SetNextItemWidth(100.0f);
if (ImGui::InputInt(fmt::format("##fish_c_{}", i).c_str(), &count, 1, 10)) {
if (count < 0) count = 0;
if (count > 999) count = 999;
fish.mFishCount[idx] = (u16)count;
}
ImGui::TableSetColumnIndex(2);
int size = dComIfGs_getFishSize(idx);
ImGui::SetNextItemWidth(100.0f);
if (ImGui::InputInt(fmt::format("##fish_s_{}", i).c_str(), &size, 1, 10)) {
if (size < 0) size = 0;
if (size > 255) size = 255;
dComIfGs_setFishSize(idx, (u8)size);
}
}
ImGui::EndTable();
}
ImGui::TreePop();
}
ImGui::TreePop();
}
}
void drawFlagList(const char* id, BE(u32)& flags) {
u32 tempFlagField = flags;
@@ -845,5 +1351,19 @@ namespace dusk {
if (ImGui::BeginCombo("Target Type", "Hold")) {
ImGui::EndCombo();
}
static const char* kSoundModeNames[] = { "Mono", "Stereo", "Surround" };
const char* current = (config.mSoundMode < 3) ? kSoundModeNames[config.mSoundMode]
: "Unknown";
if (ImGui::BeginCombo("Sound", current)) {
for (u8 i = 0; i < 3; i++) {
bool selected = (config.mSoundMode == i);
if (ImGui::Selectable(kSoundModeNames[i], selected)) {
config.mSoundMode = i;
}
if (selected) ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
}
}
+1
View File
@@ -15,6 +15,7 @@ namespace dusk {
void drawPlayerStatusTab();
void drawLocationTab();
void drawInventoryTab();
void drawCollectionTab();
void drawFlagsTab();
void drawConfigTab();
+8 -4
View File
@@ -40,8 +40,9 @@ UserSettings g_userSettings = {
// Graphics
.enableBloom {"game.enableBloom", true},
.useWaterProjectionOffset {"game.useWaterProjectionOffset", false},
.enableWaterRefraction {"game.enableWaterRefraction", true},
.enableFrameInterpolation = {"game.enableFrameInterpolation", false},
.shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1},
// Audio
.noLowHpSound {"game.noLowHpSound", false},
@@ -57,14 +58,15 @@ UserSettings g_userSettings = {
.restoreWiiGlitches {"game.restoreWiiGlitches", false},
// Controls
.enableTurboKeybind {"game.enableTurboKeybind", true},
.enableTurboKeybind {"game.enableTurboKeybind", false},
},
.backend = {
.isoPath {"backend.isoPath", ""},
.graphicsBackend {"backend.graphicsBackend", "auto"},
.skipPreLaunchUI {"backend.skipPreLaunchUI", false},
.showPipelineCompilation{"backend.showPipelineCompilation", false}
.showPipelineCompilation {"backend.showPipelineCompilation", false},
.wasPresetChosen {"backend.wasPresetChosen", false}
}
};
@@ -101,7 +103,8 @@ void registerSettings() {
Register(g_userSettings.game.enableMirrorMode);
Register(g_userSettings.game.invertCameraXAxis);
Register(g_userSettings.game.enableBloom);
Register(g_userSettings.game.useWaterProjectionOffset);
Register(g_userSettings.game.enableWaterRefraction);
Register(g_userSettings.game.shadowResolutionMultiplier);
Register(g_userSettings.game.enableFastIronBoots);
Register(g_userSettings.game.canTransformAnywhere);
Register(g_userSettings.game.freeMagicArmor);
@@ -117,6 +120,7 @@ void registerSettings() {
Register(g_userSettings.backend.graphicsBackend);
Register(g_userSettings.backend.skipPreLaunchUI);
Register(g_userSettings.backend.showPipelineCompilation);
Register(g_userSettings.backend.wasPresetChosen);
}
// Transient settings
+74 -5
View File
@@ -2398,7 +2398,12 @@ void mDoExt_3DlineMat0_c::draw() {
var_r28++;
}
field_0x16 ^= (u8)1;
#if TARGET_PC
if (!dusk::getSettings().game.enableFrameInterpolation)
#endif
{
field_0x16 ^= (u8)1;
}
}
void mDoExt_3DlineMat0_c::update(int param_0, f32 param_1, GXColor& param_2, u16 param_3,
@@ -2648,6 +2653,9 @@ int mDoExt_3DlineMat1_c::init(u16 param_0, u16 param_1, ResTIMG* param_2, int pa
field_0x4 = 0;
mIsDrawn = 0;
#if TARGET_PC
mInterpLineKind = 0;
#endif
GXInitTexObj(&mTextureObject, (void*)((intptr_t)param_2 + param_2->imageOffset), param_2->width,
param_2->height, (GXTexFmt)param_2->format, (GXTexWrapMode)param_2->wrapS,
@@ -2720,11 +2728,19 @@ void mDoExt_3DlineMat1_c::draw() {
lines++;
}
GXSetTexCoordScaleManually(GX_TEXCOORD0, 0, 0, 0);
mIsDrawn ^= (u8)1;
#if TARGET_PC
if (!dusk::getSettings().game.enableFrameInterpolation)
#endif
{
mIsDrawn ^= (u8)1;
}
}
void mDoExt_3DlineMat1_c::update(int param_0, f32 param_1, GXColor& param_2, u16 param_3,
dKy_tevstr_c* param_4) {
#if TARGET_PC
void mDoExt_3DlineMat1_c::update(int param_0, f32 param_1, GXColor& param_2, u16 param_3, dKy_tevstr_c* param_4, const cXyz* presentationEye) {
#else
void mDoExt_3DlineMat1_c::update(int param_0, f32 param_1, GXColor& param_2, u16 param_3, dKy_tevstr_c* param_4) {
#endif
mColor = param_2;
this->mpTevStr = param_4;
if (param_0 < 0) {
@@ -2734,6 +2750,13 @@ void mDoExt_3DlineMat1_c::update(int param_0, f32 param_1, GXColor& param_2, u16
} else {
field_0x34 = param_0;
}
#if TARGET_PC
mInterpLineKind = 1;
mInterpLineF = param_1;
mInterpLineU16 = param_3;
#endif
view_class* sp_3c = dComIfGd_getView();
mDoExt_3Dline_c* sp_38 = mpLines;
f32 local_f27 = param_3 != 0 ? param_1 / param_3 : 0.0f;
@@ -2787,7 +2810,12 @@ void mDoExt_3DlineMat1_c::update(int param_0, f32 param_1, GXColor& param_2, u16
local_f31 += local_f30 * 0.02f * (8.0f / param_1);
}
#if TARGET_PC
const cXyz& lineEye = (presentationEye != nullptr && dusk::getSettings().game.enableFrameInterpolation) ? *presentationEye : sp_3c->lookat.eye;
sp_13c = *local_r27 - lineEye;
#else
sp_13c = *local_r27 - sp_3c->lookat.eye;
#endif
sp_130 = sp_130.outprod(sp_13c);
sp_130.normalizeZP();
@@ -2822,7 +2850,11 @@ void mDoExt_3DlineMat1_c::update(int param_0, f32 param_1, GXColor& param_2, u16
local_f31 += local_f30 * 0.02f * (8.0f / param_1);
}
#if TARGET_PC
sp_13c = local_r27[0] - lineEye;
#else
sp_13c = local_r27[0] - sp_3c->lookat.eye;
#endif
sp_130 = sp_130.outprod(sp_13c);
sp_130.normalizeZP();
@@ -2894,7 +2926,11 @@ void mDoExt_3DlineMat2_c::setMaterial() {
GXLoadNrmMtxImm(cMtx_getIdentity(), 0);
}
void mDoExt_3DlineMat1_c::update(int param_0, GXColor& param_2, dKy_tevstr_c* param_4) {
#if TARGET_PC
void mDoExt_3DlineMat1_c::update(int param_0, GXColor& param_2, dKy_tevstr_c* param_4, const cXyz* presentationEye) {
#else
void mDoExt_3DlineMat1_c::update(int param_0, GXColor& param_2, dKy_tevstr_c* param_4
#endif
mColor = param_2;
this->mpTevStr = param_4;
if (param_0 < 0) {
@@ -2904,6 +2940,11 @@ void mDoExt_3DlineMat1_c::update(int param_0, GXColor& param_2, dKy_tevstr_c* pa
} else {
field_0x34 = param_0;
}
#if TARGET_PC
mInterpLineKind = 2;
#endif
view_class* stack_3c = dComIfGd_getView();
mDoExt_3Dline_c* sp_38 = mpLines;
f32 local_f30;
@@ -2929,6 +2970,12 @@ void mDoExt_3DlineMat1_c::update(int param_0, GXColor& param_2, dKy_tevstr_c* pa
for (s32 sp_14 = 0; sp_14 < mNumLines; sp_14++) {
local_r27 = sp_38[0].field_0x0;
size_p = sp_38->field_0x4;
#if TARGET_PC
if (presentationEye != nullptr && dusk::getSettings().game.enableFrameInterpolation && size_p == NULL) {
sp_38 += 1;
continue;
}
#endif
JUT_ASSERT(5875, size_p != NULL);
sp_24 = sp_38->field_0x8[mIsDrawn];
sp_28 = sp_24;
@@ -2942,7 +2989,12 @@ void mDoExt_3DlineMat1_c::update(int param_0, GXColor& param_2, dKy_tevstr_c* pa
sp_130 = local_r27[1] - local_r27[0];
local_f30 = sp_130.abs();
local_f31 += local_f30 * 0.1f;
#if TARGET_PC
const cXyz& lineEye = (presentationEye != nullptr && dusk::getSettings().game.enableFrameInterpolation) ? *presentationEye : stack_3c->lookat.eye;
sp_13c = local_r27[0] - lineEye;
#else
sp_13c = local_r27[0] - stack_3c->lookat.eye;
#endif
sp_130 = sp_130.outprod(sp_13c);
sp_130.normalizeZP();
local_r30->x = sp_130.x * 64.0f;
@@ -2964,7 +3016,11 @@ void mDoExt_3DlineMat1_c::update(int param_0, GXColor& param_2, dKy_tevstr_c* pa
sp_130 = local_r27[1] - local_r27[0];
local_f30 = sp_130.abs();
local_f31 += local_f30 * 0.1f;
#if TARGET_PC
sp_13c = local_r27[0] - lineEye;
#else
sp_13c = local_r27[0] - stack_3c->lookat.eye;
#endif
sp_130 = sp_130.outprod(sp_13c);
sp_130.normalizeZP();
local_r30 += 2;
@@ -3008,6 +3064,19 @@ void mDoExt_3DlineMat1_c::update(int param_0, GXColor& param_2, dKy_tevstr_c* pa
}
}
#if TARGET_PC
void mDoExt_3DlineMat1_c::refreshGeometryForPresentationEye(const cXyz& eye) {
if (!dusk::getSettings().game.enableFrameInterpolation) {
return;
}
if (mInterpLineKind == 1) {
update(field_0x34, mInterpLineF, mColor, mInterpLineU16, mpTevStr, &eye);
} else if (mInterpLineKind == 2) {
update(field_0x34, mColor, mpTevStr, &eye);
}
}
#endif
void mDoExt_3DlineMatSortPacket::setMat(mDoExt_3DlineMat_c* i_3DlineMat) {
if (mp3DlineMat == NULL) {
dComIfGd_getListPacket()->entryImm(this, 0);
+19 -1
View File
@@ -29,6 +29,7 @@
#include "d/d_meter2_info.h"
#include "d/d_s_play.h"
#include "dusk/endian.h"
#include "dusk/frame_interpolation.h"
#include "dusk/gx_helper.h"
#include "dusk/logging.h"
#include "f_ap/f_ap_game.h"
@@ -39,7 +40,6 @@
#include "m_Do/m_Do_graphic.h"
#include "m_Do/m_Do_machine.h"
#include "m_Do/m_Do_main.h"
#include "dusk/frame_interpolation.h"
#include "tracy/Tracy.hpp"
#if PLATFORM_WII || PLATFORM_SHIELD
@@ -51,6 +51,7 @@
#endif
#if TARGET_PC
#include "d/actor/d_a_horse.h"
#include "dusk/imgui/ImGuiConsole.hpp"
#include "dusk/dusk.h"
#endif
@@ -1897,6 +1898,11 @@ int mDoGph_Painter() {
j3dSys.setViewMtx(camera_p->view.viewMtx);
#endif
dKy_setLight();
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
dKy_setLight_again();
}
#endif
GX_DEBUG_GROUP(dComIfGd_drawOpaListSky);
GX_DEBUG_GROUP(dComIfGd_drawXluListSky);
@@ -1947,6 +1953,18 @@ int mDoGph_Painter() {
GX_DEBUG_GROUP(dComIfGd_drawOpaListDark);
}
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
cXyz pres_eye;
dusk::frame_interp::camera_eye_from_view_mtx(j3dSys.getViewMtx(), &pres_eye);
// FRAME INTERP NOTE: Currently only recalculating points for Epona's reins. Need a more global solution.
if (daHorse_c* horse = dComIfGp_getHorseActor()) {
horse->lerpControlPoints(dusk::frame_interp::get_interpolation_step());
}
g_dComIfG_gameInfo.drawlist.refresh3DlineMats(pres_eye);
}
#endif
GX_DEBUG_GROUP(dComIfGd_drawOpaListPacket);
#if DEBUG
-1
View File
@@ -53,7 +53,6 @@
#include "dusk/main.h"
#include "dusk/imgui/ImGuiConsole.hpp"
#include "version.h"
#include "dusk/time.h"
#include <aurora/aurora.h>
#include <aurora/event.h>