mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-04 11:19:58 -04:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b0b1978c76 | |||
| 965e958222 | |||
| 8de4863426 | |||
| 9235833413 | |||
| a0e9ee73a8 | |||
| 99fd2f9bc5 | |||
| 7eb61b71f1 | |||
| d8df116047 | |||
| 5f69895326 | |||
| 194cb94d43 | |||
| 22535ba84d | |||
| ab65f42816 | |||
| 0508acaa79 | |||
| d876c62822 | |||
| c26b05b1dd | |||
| 97c459a614 | |||
| cd9bb31b02 | |||
| e37c912053 | |||
| 4e42af6cd8 | |||
| 87a95fb1b8 | |||
| 83b210e26c | |||
| 158f31d056 |
+35
-32
@@ -8,8 +8,9 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
# SCCACHE_GHA_ENABLED: "true"
|
||||
RUSTC_WRAPPER: "sccache"
|
||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
@@ -21,13 +22,13 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- name: GCC x86_64
|
||||
runner: ubuntu-latest
|
||||
runner: [self-hosted, Linux]
|
||||
preset: gcc
|
||||
artifact_arch: x86_64
|
||||
- name: GCC aarch64
|
||||
runner: ubuntu-24.04-arm
|
||||
preset: gcc
|
||||
artifact_arch: aarch64
|
||||
# - name: GCC aarch64
|
||||
# runner: ubuntu-24.04-arm
|
||||
# preset: gcc
|
||||
# artifact_arch: aarch64
|
||||
# - name: Clang x86_64
|
||||
# runner: ubuntu-latest
|
||||
# preset: clang
|
||||
@@ -40,17 +41,22 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
if: 'false' # disabled for self-hosted
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install ninja-build clang lld openssl libcurl4-openssl-dev \
|
||||
zlib1g-dev libglu1-mesa-dev libdbus-1-dev libvulkan-dev libxi-dev libxrandr-dev libasound2-dev \
|
||||
libpulse-dev libudev-dev libpng-dev libncurses5-dev libx11-xcb-dev libfreetype-dev \
|
||||
libxinerama-dev libxcursor-dev python3-markupsafe libgtk-3-dev libssl-dev \
|
||||
libxss-dev libfuse2
|
||||
libxss-dev libfuse2 libusb-1.0-0-dev libdecor-0-dev libpipewire-0.3-dev libunwind-dev
|
||||
|
||||
- name: Setup sccache
|
||||
if: 'false' # disabled for self-hosted
|
||||
uses: mozilla-actions/sccache-action@v0.0.9
|
||||
|
||||
- name: Print sccache stats
|
||||
run: sccache --show-stats
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake --preset x-linux-ci-${{matrix.preset}}
|
||||
|
||||
@@ -68,9 +74,9 @@ jobs:
|
||||
build/install/Dusk-*.AppImage
|
||||
build/install/debug.tar.*
|
||||
|
||||
|
||||
build-apple:
|
||||
name: Build Apple (${{matrix.name}})
|
||||
if: 'false' # TODO enable when CI is free
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -80,14 +86,14 @@ jobs:
|
||||
platform: macos
|
||||
preset: x-macos-ci
|
||||
artifact_name: macos-appleclang-universal
|
||||
# - name: AppleClang iOS arm64 # TODO enable when CI is free
|
||||
# platform: ios
|
||||
# preset: x-ios-ci
|
||||
# artifact_name: ios-appleclang-arm64
|
||||
# - name: AppleClang tvOS arm64 # TODO enable when CI is free
|
||||
# platform: tvos
|
||||
# preset: x-tvos-ci
|
||||
# artifact_name: tvos-appleclang-arm64
|
||||
- name: AppleClang iOS arm64
|
||||
platform: ios
|
||||
preset: x-ios-ci
|
||||
artifact_name: ios-appleclang-arm64
|
||||
- name: AppleClang tvOS arm64
|
||||
platform: tvos
|
||||
preset: x-tvos-ci
|
||||
artifact_name: tvos-appleclang-arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -139,26 +145,22 @@ jobs:
|
||||
name: Build Windows (${{matrix.name}})
|
||||
runs-on: ${{matrix.runner}}
|
||||
|
||||
env:
|
||||
BUILD_DIR: C:\build
|
||||
SCCACHE_DIR: C:\sccache
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: MSVC x86_64
|
||||
runner: windows-latest
|
||||
runner: [self-hosted, Windows]
|
||||
preset: msvc
|
||||
msvc_arch: amd64
|
||||
vcpkg_arch: x64
|
||||
artifact_arch: x86_64
|
||||
- name: MSVC arm64
|
||||
runner: windows-11-arm
|
||||
preset: arm64-msvc
|
||||
msvc_arch: arm64
|
||||
vcpkg_arch: arm64
|
||||
artifact_arch: arm64
|
||||
# - name: MSVC arm64
|
||||
# runner: windows-11-arm
|
||||
# preset: arm64-msvc
|
||||
# msvc_arch: arm64
|
||||
# vcpkg_arch: arm64
|
||||
# artifact_arch: arm64
|
||||
# - name: Clang x86_64
|
||||
# runner: windows-latest
|
||||
# preset: clang
|
||||
@@ -185,11 +187,10 @@ jobs:
|
||||
uses: mozilla-actions/sccache-action@v0.0.9
|
||||
|
||||
- name: Install dependencies
|
||||
if: 'false' # disabled for self-hosted
|
||||
run: |
|
||||
choco install ninja
|
||||
vcpkg install zlib:${{matrix.vcpkg_arch}}-windows-static bzip2:${{matrix.vcpkg_arch}}-windows-static `
|
||||
zstd:${{matrix.vcpkg_arch}}-windows-static liblzma:${{matrix.vcpkg_arch}}-windows-static `
|
||||
freetype:${{matrix.vcpkg_arch}}-windows-static
|
||||
vcpkg install freetype:${{matrix.vcpkg_arch}}-windows-static zstd:${{matrix.vcpkg_arch}}-windows-static
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake --preset x-windows-ci-${{matrix.preset}}
|
||||
@@ -202,5 +203,7 @@ jobs:
|
||||
with:
|
||||
name: dusk-${{env.DUSK_VERSION}}-win32-msvc-${{matrix.artifact_arch}}
|
||||
path: |
|
||||
${{env.BUILD_DIR}}/install/*.exe
|
||||
${{env.BUILD_DIR}}/install/debug.7z
|
||||
build/install/*.exe
|
||||
build/install/*.dll
|
||||
build/install/res/
|
||||
build/install/debug.7z
|
||||
|
||||
+7
-3
@@ -113,7 +113,7 @@ set(DUSK_SENTRY_DSN "" CACHE STRING "Sentry DSN")
|
||||
set(DUSK_SENTRY_ENVIRONMENT "development" CACHE STRING "Sentry environment")
|
||||
|
||||
if (DUSK_MOVIE_SUPPORT)
|
||||
find_package(libjpeg-turbo QUIET)
|
||||
find_package(libjpeg-turbo 3.0 CONFIG QUIET)
|
||||
if (libjpeg-turbo_FOUND)
|
||||
message(STATUS "dusk: Using system libjpeg-turbo")
|
||||
else ()
|
||||
@@ -297,8 +297,12 @@ endif ()
|
||||
|
||||
# Edit & Continue
|
||||
if (MSVC)
|
||||
add_compile_options("/ZI")
|
||||
add_link_options("/INCREMENTAL")
|
||||
if (CMAKE_MSVC_DEBUG_INFORMATION_FORMAT STREQUAL "" AND CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "EditAndContinue")
|
||||
endif ()
|
||||
if (CMAKE_MSVC_DEBUG_INFORMATION_FORMAT STREQUAL "EditAndContinue")
|
||||
add_link_options("/INCREMENTAL")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if(ANDROID)
|
||||
|
||||
+28
-18
@@ -22,6 +22,20 @@
|
||||
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci",
|
||||
"hidden": true,
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER_LAUNCHER": "sccache",
|
||||
"CMAKE_CXX_COMPILER_LAUNCHER": "sccache",
|
||||
"DUSK_ENABLE_SENTRY_NATIVE": {
|
||||
"type": "BOOL",
|
||||
"value": true
|
||||
},
|
||||
"DUSK_SENTRY_DSN": "$env{SENTRY_DSN}",
|
||||
"DUSK_SENTRY_ENVIRONMENT": "production"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-default",
|
||||
"displayName": "Linux (default)",
|
||||
@@ -343,12 +357,9 @@
|
||||
"name": "x-linux-ci",
|
||||
"hidden": true,
|
||||
"inherits": [
|
||||
"relwithdebinfo"
|
||||
],
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER_LAUNCHER": "sccache",
|
||||
"CMAKE_CXX_COMPILER_LAUNCHER": "sccache"
|
||||
}
|
||||
"relwithdebinfo",
|
||||
"ci"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x-linux-ci-gcc",
|
||||
@@ -367,12 +378,9 @@
|
||||
{
|
||||
"name": "x-macos-ci",
|
||||
"inherits": [
|
||||
"macos-default-relwithdebinfo"
|
||||
],
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER_LAUNCHER": "sccache",
|
||||
"CMAKE_CXX_COMPILER_LAUNCHER": "sccache"
|
||||
}
|
||||
"macos-default-relwithdebinfo",
|
||||
"ci"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x-ios-ci",
|
||||
@@ -398,14 +406,16 @@
|
||||
"name": "x-windows-ci",
|
||||
"hidden": true,
|
||||
"inherits": [
|
||||
"relwithdebinfo"
|
||||
"relwithdebinfo",
|
||||
"ci"
|
||||
],
|
||||
"binaryDir": "$env{BUILD_DIR}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_INSTALL_PREFIX": "$env{BUILD_DIR}/install",
|
||||
"CMAKE_C_COMPILER_LAUNCHER": "sccache",
|
||||
"CMAKE_CXX_COMPILER_LAUNCHER": "sccache",
|
||||
"CMAKE_MSVC_DEBUG_INFORMATION_FORMAT": "Embedded"
|
||||
"CMAKE_MSVC_DEBUG_INFORMATION_FORMAT": "Embedded",
|
||||
"CMAKE_TOOLCHAIN_FILE": {
|
||||
"type": "FILEPATH",
|
||||
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
|
||||
},
|
||||
"VCPKG_TARGET_TRIPLET": "x64-windows"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -9,10 +9,10 @@ chmod +x linuxdeploy-$(uname -m).AppImage
|
||||
# Build AppImage
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
mkdir -p build/appdir/usr/{bin,share/{applications,icons/hicolor}}
|
||||
cp build/install/!(*.*) build/appdir/usr/bin
|
||||
cp -r build/install/!(*.*) build/appdir/usr/bin
|
||||
cp -r platforms/freedesktop/{16x16,32x32,48x48,64x64,128x128,256x256,512x512,1024x1024} build/appdir/usr/share/icons/hicolor
|
||||
cp platforms/freedesktop/dusk.desktop build/appdir/usr/share/applications
|
||||
|
||||
cd build/install
|
||||
VERSION="$DUSK_VERSION" NO_STRIP=1 "$RUNNER_WORKSPACE"/linuxdeploy-$(uname -m).AppImage \
|
||||
--appdir "$GITHUB_WORKSPACE"/build/appdir --output appimage
|
||||
-l /usr/lib/x86_64-linux-gnu/libusb-1.0.so --appdir "$GITHUB_WORKSPACE"/build/appdir --output appimage
|
||||
|
||||
Vendored
+1
-1
Submodule extern/aurora updated: 4dd23c74d8...4d7ff2ac11
@@ -1376,6 +1376,7 @@ set(DUSK_FILES
|
||||
src/dusk/imgui/ImGuiSaveEditor.cpp
|
||||
src/dusk/imgui/ImGuiStateShare.hpp
|
||||
src/dusk/imgui/ImGuiStateShare.cpp
|
||||
src/dusk/iso_validate.cpp
|
||||
src/dusk/offset_ptr.cpp
|
||||
src/dusk/OSContext.cpp
|
||||
src/dusk/OSThread.cpp
|
||||
|
||||
@@ -44,6 +44,9 @@ public:
|
||||
int draw();
|
||||
int execute();
|
||||
void drawMeter();
|
||||
#if TARGET_PC
|
||||
void updateOnWide();
|
||||
#endif
|
||||
void setComboCount(u8, u8);
|
||||
void setScoreCount(u32);
|
||||
void addScoreCount(cXyz*, u32, u8);
|
||||
|
||||
@@ -110,6 +110,10 @@ struct dMsgScrnHowl_c : public dMsgScrnBase_c {
|
||||
/* 0x27A0 */ f32 field_0x27a0;
|
||||
/* 0x27A4 */ f32 field_0x27a4;
|
||||
/* 0x27A8 */ f32 field_0x27a8;
|
||||
|
||||
#if TARGET_PC
|
||||
u8 showCursor;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* MSG_SCRN_D_MSG_SCRN_HOWL_H */
|
||||
|
||||
+18
-6
@@ -487,19 +487,31 @@ public:
|
||||
}
|
||||
}
|
||||
char* getPlayerName() const { return const_cast<char*>(mPlayerName); }
|
||||
void setPlayerName(const char* i_name) { strcpy(mPlayerName, i_name); }
|
||||
void setPlayerName(const char* i_name) {
|
||||
#if AVOID_UB
|
||||
strncpy(mPlayerName, i_name, sizeof(mPlayerName) - 1);
|
||||
mPlayerName[sizeof(mPlayerName) - 1] = '\0';
|
||||
#else
|
||||
strcpy(mPlayerName, i_name);
|
||||
#endif
|
||||
}
|
||||
char* getHorseName() const { return const_cast<char*>(mHorseName); }
|
||||
void setHorseName(const char* i_name) { strcpy(mHorseName, i_name); }
|
||||
void setHorseName(const char* i_name) {
|
||||
#if AVOID_UB
|
||||
strncpy(mHorseName, i_name, sizeof(mHorseName) - 1);
|
||||
mHorseName[sizeof(mHorseName) - 1] = '\0';
|
||||
#else
|
||||
strcpy(mHorseName, i_name);
|
||||
#endif
|
||||
}
|
||||
u8 getClearCount() const { return mClearCount; }
|
||||
|
||||
/* 0x00 */ BE(u64) unk0;
|
||||
/* 0x08 */ BE(s64) mTotalTime;
|
||||
/* 0x10 */ BE(u16) unk16;
|
||||
/* 0x12 */ BE(u16) mDeathCount;
|
||||
/* 0x14 */ char mPlayerName[16];
|
||||
/* 0x24 */ u8 unk36;
|
||||
/* 0x25 */ char mHorseName[16];
|
||||
/* 0x35 */ u8 unk53;
|
||||
/* 0x14 */ char mPlayerName[17];
|
||||
/* 0x25 */ char mHorseName[17];
|
||||
/* 0x36 */ u8 mClearCount;
|
||||
/* 0x37 */ u8 unk55[5];
|
||||
}; // Size: 0x40
|
||||
|
||||
@@ -34,6 +34,7 @@ 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 lookup_replacement(const void* source, Mtx out);
|
||||
bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out);
|
||||
@@ -41,6 +42,7 @@ bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out);
|
||||
void camera_eye_from_view_mtx(MtxP view_mtx, cXyz* o_eye);
|
||||
bool build_star_view(Mtx o_view, Mtx o_cam_billboard_base, cXyz* o_anchor_eye, float* o_fovy);
|
||||
|
||||
uint64_t alloc_simple_shadow_pair_base();
|
||||
} // namespace frame_interp
|
||||
} // namespace dusk
|
||||
#endif
|
||||
|
||||
@@ -66,6 +66,7 @@ struct UserSettings {
|
||||
// Preferences
|
||||
ConfigVar<bool> enableMirrorMode;
|
||||
ConfigVar<bool> invertCameraXAxis;
|
||||
ConfigVar<bool> disableMainHUD;
|
||||
|
||||
// Graphics
|
||||
ConfigVar<BloomMode> bloomMode;
|
||||
|
||||
@@ -393,7 +393,7 @@ static void waitPrecise(Limiter& limiter, Uint64 targetNs) {
|
||||
|
||||
static void waitForTick(u32 p1, u16 p2) {
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
if (dusk::getSettings().game.enableFrameInterpolation && !dusk::getTransientSettings().skipFrameRateLimit) {
|
||||
return;
|
||||
}
|
||||
if (dusk::getTransientSettings().skipFrameRateLimit) {
|
||||
|
||||
@@ -268,6 +268,11 @@ int daBalloon2D_c::draw() {
|
||||
int daBalloon2D_c::execute() {
|
||||
setAllAlpha();
|
||||
setComboAlpha();
|
||||
|
||||
#if TARGET_PC
|
||||
updateOnWide();
|
||||
#endif
|
||||
|
||||
setHIO(false);
|
||||
return 1;
|
||||
}
|
||||
@@ -278,6 +283,15 @@ void daBalloon2D_c::drawMeter() {
|
||||
drawAddScore();
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
void daBalloon2D_c::updateOnWide() {
|
||||
// Combo HUD
|
||||
l_HOSTIO = {};
|
||||
|
||||
l_HOSTIO.m.m2DNumberCombo2PosX = mDoGph_gInf_c::ScaleHUDXRight(l_HOSTIO.m.m2DNumberCombo2PosX);
|
||||
l_HOSTIO.m.mAdjustmentToggle = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void daBalloon2D_c::setComboCount(u8 size, u8 comboNum) {
|
||||
if (mComboNum != comboNum) {
|
||||
|
||||
@@ -363,6 +363,18 @@ int daMyna_c::destroy() {
|
||||
mpMorf->stopZelAnime();
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
// !@bug d_a_myna.rel unload used to zero these file-statics; with static linking they dangle across scenes.
|
||||
daMyna_LightActor = NULL;
|
||||
daMyna_evtTagActor0 = NULL;
|
||||
daMyna_evtTagActor1 = NULL;
|
||||
daMyna_actor_count = 0;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
daMyna_targetActor[i] = NULL;
|
||||
daMyna_subActor[i] = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
l_HOSTIO.removeHIO();
|
||||
#endif
|
||||
|
||||
@@ -239,6 +239,17 @@ cPhs_Step daNpcTheB_c::create() {
|
||||
fopAcM_ct(this, daNpcTheB_c);
|
||||
|
||||
cPhs_Step phase = dComIfG_resLoad(&mPhase, l_arcName);
|
||||
#if TARGET_PC
|
||||
// !@bug On PC (and presumably the WiiU version) during the wagon escort,
|
||||
// Telma's main() can queue the PERSONAL_COMBAT_INTRO (Telma's initial dialog when the escort starts)
|
||||
// before Link's create() sets getPlayer(0), so demoCheck drops the event and the dialog never shows up
|
||||
if (phase == cPhs_COMPLEATE_e && dComIfGp_getPlayer(0) == NULL &&
|
||||
strcmp(dComIfGp_getStartStageName(), "F_SP121") == 0 &&
|
||||
dComIfG_play_c::getLayerNo(0) == 3)
|
||||
{
|
||||
return cPhs_INIT_e;
|
||||
}
|
||||
#endif
|
||||
if (phase == cPhs_COMPLEATE_e) {
|
||||
if (!fopAcM_entrySolidHeap(this, createHeapCallBack, 0x2CB0)) {
|
||||
return cPhs_ERROR_e;
|
||||
|
||||
+19
-12
@@ -1,28 +1,29 @@
|
||||
#include "d/dolzel.h" // IWYU pragma: keep
|
||||
|
||||
#include <cstdio>
|
||||
#include "JSystem/J2DGraph/J2DAnimation.h"
|
||||
#include "JSystem/J2DGraph/J2DGrafContext.h"
|
||||
#include "JSystem/J2DGraph/J2DScreen.h"
|
||||
#include "JSystem/J3DGraphBase/J3DDrawBuffer.h"
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
#include "SSystem/SComponent/c_bg_s_shdw_draw.h"
|
||||
#include "SSystem/SComponent/c_math.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "d/d_drawlist.h"
|
||||
|
||||
#include <typeindex>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "client/TracyScoped.hpp"
|
||||
#include "d/d_s_play.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/gx_helper.h"
|
||||
#include "dusk/logging.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
#include "m_Do/m_Do_lib.h"
|
||||
#include "m_Do/m_Do_mtx.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include <cstdio>
|
||||
#include <typeindex>
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "client/TracyScoped.hpp"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/gx_helper.h"
|
||||
#include "dusk/logging.h"
|
||||
#endif
|
||||
|
||||
class dDlst_2Dm_c {
|
||||
public:
|
||||
virtual void draw();
|
||||
@@ -1432,8 +1433,14 @@ void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* pa
|
||||
mDoMtx_stack_c::scaleM(param_2, 1.0f, param_2 * param_5);
|
||||
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mMtx);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(&mVolumeMtx, mVolumeMtx);
|
||||
dusk::frame_interp::record_final_mtx_raw(&mMtx, mMtx);
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
mpTexObj = param_6;
|
||||
}
|
||||
|
||||
@@ -423,6 +423,13 @@ void dMeter2_c::setLifeZero() {
|
||||
|
||||
void dMeter2_c::checkStatus() {
|
||||
mStatus = 0;
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.disableMainHUD) {
|
||||
mStatus |= 0xF0000000;
|
||||
}
|
||||
#endif
|
||||
|
||||
field_0x12c = field_0x128;
|
||||
|
||||
field_0x128 = daPy_py_c::checkNowWolf();
|
||||
|
||||
@@ -2289,7 +2289,8 @@ dMeter_drawHIO_c::dMeter_drawHIO_c() {
|
||||
#if WIDESCREEN_SUPPORT
|
||||
void dMeter_drawHIO_c::updateOnWide() {
|
||||
#if TARGET_PC
|
||||
g_drawHIO = {}; // this might be a bad idea
|
||||
// Main HUD
|
||||
g_drawHIO = {};
|
||||
|
||||
g_drawHIO.mMainHUDButtonsPosX = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mMainHUDButtonsPosX);
|
||||
g_drawHIO.mRingHUDButtonsPosX = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mRingHUDButtonsPosX);
|
||||
@@ -2301,6 +2302,10 @@ void dMeter_drawHIO_c::updateOnWide() {
|
||||
g_drawHIO.mButtonCrossONPosX = mDoGph_gInf_c::ScaleHUDXLeft(g_drawHIO.mButtonCrossONPosX);
|
||||
g_drawHIO.mLifeGaugePosX = mDoGph_gInf_c::ScaleHUDXLeft(g_drawHIO.mLifeGaugePosX);
|
||||
g_drawHIO.mLanternMeterPosX = mDoGph_gInf_c::ScaleHUDXLeft(g_drawHIO.mLanternMeterPosX);
|
||||
|
||||
// River Canoe Minigame
|
||||
g_drawHIO.mMiniGame.mCounterPosX[1] = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mMiniGame.mCounterPosX[1]);
|
||||
g_drawHIO.mMiniGame.mIconPosX[1] = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mMiniGame.mIconPosX[1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
#include "JSystem/J2DGraph/J2DScreen.h"
|
||||
#include "Z2AudioLib/Z2WolfHowlMgr.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/settings.h"
|
||||
#endif
|
||||
|
||||
// POSIX already defines a macro with this name, but we know that this specific name is
|
||||
// used in TP based on assertion messages. This redefinition is scoped to this TU which
|
||||
// is unlikely to ever actually need the POSIX define, so we can just redefine it.
|
||||
@@ -307,6 +311,17 @@ void dMsgScrnHowl_c::exec() {
|
||||
mpButtonIcon[1]->setAlphaRate(field_0x1994 * alphaRate);
|
||||
mpButtonText[0]->setAlphaRate(field_0x1998 * alphaRate);
|
||||
mpButtonText[1]->setAlphaRate(field_0x1998 * alphaRate);
|
||||
|
||||
#if TARGET_PC
|
||||
showCursor = true;
|
||||
if (field_0x2798 == 0) {
|
||||
if (mPlotTime != field_0x212c) {
|
||||
field_0x212c = mPlotTime;
|
||||
} else {
|
||||
showCursor = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void dMsgScrnHowl_c::drawSelf() {
|
||||
@@ -490,6 +505,7 @@ void dMsgScrnHowl_c::drawWave() {
|
||||
grafContext->setScissor();
|
||||
#endif
|
||||
|
||||
#if !TARGET_PC
|
||||
bool bVar5 = true;
|
||||
if (field_0x2798 == 0) {
|
||||
if (mPlotTime != field_0x212c) {
|
||||
@@ -498,7 +514,14 @@ void dMsgScrnHowl_c::drawWave() {
|
||||
bVar5 = false;
|
||||
}
|
||||
}
|
||||
if (bVar5) {
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
if (showCursor)
|
||||
#else
|
||||
if (bVar5)
|
||||
#endif
|
||||
{
|
||||
for (int iVar10 = 0; iVar10 < field_0x2128 - 1; iVar10++) {
|
||||
f32 local_54 = local_e0;
|
||||
f32 local_c8 = field_0x180[sVar14];
|
||||
|
||||
+28
-10
@@ -23,6 +23,10 @@
|
||||
#include "m_Do/m_Do_lib.h"
|
||||
#include <cstring>
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
static int dTimer_createStart2D(s32 param_0, u16 param_1);
|
||||
|
||||
int dTimer_c::_create() {
|
||||
@@ -1336,29 +1340,44 @@ void dDlst_TimerScrnDraw_c::draw() {
|
||||
f32 temp = (f32)g_drawHIO.mMiniGame.mGetInTextAlphaFrames +
|
||||
((f32)g_drawHIO.mMiniGame.mGetInTextWaitFrames + 60.0f);
|
||||
|
||||
#if TARGET_PC
|
||||
const u32 pending_ui_ticks = dusk::frame_interp::get_presentation_ui_advance_ticks();
|
||||
#else
|
||||
const u32 pending_ui_ticks = 1u;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < 51; i++) {
|
||||
if (m_getin_info[i].bck_frame > 0.0f && m_getin_info[i].bck_frame < temp) {
|
||||
f32 var_f29 = 1.0f;
|
||||
for (u32 tick = 0; tick < pending_ui_ticks; tick++) {
|
||||
if (!(m_getin_info[i].bck_frame > 0.0f && m_getin_info[i].bck_frame < temp)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_getin_info[i].bck_frame < 60.0f) {
|
||||
m_getin_info[i].bck_frame += g_drawHIO.mMiniGame.mGetInTextAnimSpeed;
|
||||
if (m_getin_info[i].bck_frame > 60.0f) {
|
||||
m_getin_info[i].bck_frame = 60.0f;
|
||||
}
|
||||
|
||||
playBckAnimation(m_getin_info[i].bck_frame);
|
||||
} else if (m_getin_info[i].bck_frame < g_drawHIO.mMiniGame.mGetInTextWaitFrames + 60.0f)
|
||||
{
|
||||
} else if (m_getin_info[i].bck_frame < g_drawHIO.mMiniGame.mGetInTextWaitFrames + 60.0f) {
|
||||
m_getin_info[i].bck_frame++;
|
||||
playBckAnimation(60.0f);
|
||||
} else if (m_getin_info[i].bck_frame < temp) {
|
||||
m_getin_info[i].bck_frame++;
|
||||
playBckAnimation(60.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_getin_info[i].bck_frame > 0.0f && m_getin_info[i].bck_frame < temp) {
|
||||
f32 var_f29 = 1.0f;
|
||||
if (m_getin_info[i].bck_frame >= g_drawHIO.mMiniGame.mGetInTextWaitFrames + 60.0f &&
|
||||
m_getin_info[i].bck_frame < temp) {
|
||||
var_f29 = acc(g_drawHIO.mMiniGame.mGetInTextAlphaFrames,
|
||||
temp - m_getin_info[i].bck_frame, 0);
|
||||
}
|
||||
|
||||
if (m_getin_info[i].bck_frame < 60.0f) {
|
||||
playBckAnimation(m_getin_info[i].bck_frame);
|
||||
} else {
|
||||
playBckAnimation(60.0f);
|
||||
}
|
||||
|
||||
mpGetInParent->setAlphaRate(var_f29);
|
||||
|
||||
if (g_drawHIO.mMiniGame.mGetInTextLocation == 1) {
|
||||
@@ -1388,8 +1407,7 @@ void dDlst_TimerScrnDraw_c::draw() {
|
||||
m_getin_info[i].pikari_frame =
|
||||
18.0f - g_drawHIO.mMiniGame.mGetInPikariAnimSpeed;
|
||||
}
|
||||
} else if (m_getin_info[i].bck_frame > g_drawHIO.mMiniGame.mStartPikariAppearFrames)
|
||||
{
|
||||
} else if (m_getin_info[i].bck_frame > g_drawHIO.mMiniGame.mStartPikariAppearFrames) {
|
||||
m_getin_info[i].pikari_frame =
|
||||
18.0f - g_drawHIO.mMiniGame.mStartPikariAnimSpeed;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ struct Data {
|
||||
size_t child_index = 0;
|
||||
Mtx matrix{};
|
||||
const Mtx* dest = nullptr;
|
||||
uint64_t stable_tag = 0;
|
||||
};
|
||||
|
||||
struct Path;
|
||||
@@ -46,6 +47,8 @@ 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 {
|
||||
@@ -57,6 +60,7 @@ struct MatrixValue {
|
||||
};
|
||||
|
||||
using FinalMtxLookup = std::unordered_map<const Mtx*, const Data*>;
|
||||
using FinalMtxLookupTagged = std::unordered_map<uint64_t, const Data*>;
|
||||
|
||||
bool s_initialized = false;
|
||||
|
||||
@@ -142,8 +146,9 @@ const OpBucket* find_op_bucket(const Path& path, Op op) {
|
||||
return &*it;
|
||||
}
|
||||
|
||||
void build_final_mtx_lookup(const Path& path, FinalMtxLookup& lookup) {
|
||||
lookup.clear();
|
||||
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) {
|
||||
@@ -151,10 +156,12 @@ void build_final_mtx_lookup(const Path& path, FinalMtxLookup& lookup) {
|
||||
}
|
||||
|
||||
for (const Data& data : bucket->values) {
|
||||
if (data.dest == nullptr) {
|
||||
continue;
|
||||
if (data.dest != nullptr) {
|
||||
dest_lookup[data.dest] = &data;
|
||||
}
|
||||
if (data.stable_tag != 0) {
|
||||
tag_lookup[data.stable_tag] = &data;
|
||||
}
|
||||
lookup[data.dest] = &data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +208,8 @@ void store_replacement(const Data& old_data, const Data& new_data, float step) {
|
||||
|
||||
void interpolate_branch(const Path& old_path, const Path& new_path, float step) {
|
||||
FinalMtxLookup old_final_mtx_lookup;
|
||||
build_final_mtx_lookup(old_path, 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;
|
||||
@@ -230,7 +238,17 @@ void interpolate_branch(const Path& old_path, const Path& new_path, float step)
|
||||
}
|
||||
|
||||
const Data* indexed_old_data = find_matching_data(old_path, op, index);
|
||||
const Data* old_data = op == Op::FinalMtx ? find_matching_final_mtx(old_final_mtx_lookup, *new_data) : indexed_old_data;
|
||||
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);
|
||||
}
|
||||
@@ -370,7 +388,9 @@ void open_child(const void* key, int32_t id) {
|
||||
data.child_label = label;
|
||||
data.child_index = siblings.size();
|
||||
siblings.emplace_back(std::make_unique<Path>());
|
||||
g_current_path.push_back(siblings.back().get());
|
||||
Path* const child = siblings.back().get();
|
||||
child->draw_scope = label;
|
||||
g_current_path.push_back(child);
|
||||
}
|
||||
|
||||
void close_child() {
|
||||
@@ -388,6 +408,18 @@ void record_final_mtx_raw(const Mtx* dest, const Mtx src) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -501,4 +533,20 @@ bool build_star_view(Mtx o_view, Mtx o_cam_billboard_base, cXyz* o_anchor_eye, f
|
||||
*o_fovy = s_star_prev.fovy + (s_star_curr.fovy - s_star_prev.fovy) * step;
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -40,9 +40,15 @@ namespace dusk {
|
||||
|
||||
void ImGuiTextCenter(std::string_view text) {
|
||||
ImGui::NewLine();
|
||||
float fontSize = ImGui::CalcTextSize(text.data(), text.data() + text.size()).x;
|
||||
float fontSize = ImGui::CalcTextSize(
|
||||
text.data(),
|
||||
text.data() + text.size(),
|
||||
false,
|
||||
ImGui::GetWindowSize().x).x;
|
||||
ImGui::SameLine(ImGui::GetWindowSize().x / 2 - fontSize + fontSize / 2);
|
||||
ImGui::PushTextWrapPos(ImGui::GetWindowSize().x);
|
||||
ImGuiStringViewText(text);
|
||||
ImGui::PopTextWrapPos();
|
||||
}
|
||||
|
||||
bool ImGuiButtonCenter(std::string_view text) {
|
||||
|
||||
@@ -9,101 +9,117 @@ namespace dusk {
|
||||
|
||||
void ImGuiMenuEnhancements::draw() {
|
||||
if (ImGui::BeginMenu("Enhancements")) {
|
||||
if (ImGui::BeginMenu("Quality of Life")) {
|
||||
config::ImGuiCheckbox("Quick Transform (R+Y)", getSettings().game.enableQuickTransform);
|
||||
if (ImGui::BeginMenu("Gameplay")) {
|
||||
ImGui::SeparatorText("Preferences");
|
||||
|
||||
config::ImGuiCheckbox("Mirror Mode", getSettings().game.enableMirrorMode);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Allows you to quickly transform between forms\n"
|
||||
"without having to talk to Midna.");
|
||||
ImGui::SetTooltip("Mirrors the world horizontally, matching the Wii version of the game.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Sun's Song (R+X)", getSettings().game.sunsSong);
|
||||
config::ImGuiCheckbox("Disable Main HUD", getSettings().game.disableMainHUD);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Allows Wolf Link to howl and change the time of day.");
|
||||
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("No Rupee Returns", getSettings().game.noReturnRupees);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Always collect Rupees even if your Wallet is too full.");
|
||||
}
|
||||
|
||||
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("No Sword Recoil", getSettings().game.noSwordRecoil);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Link won't recoil when his sword hits walls.");
|
||||
}
|
||||
|
||||
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("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("Faster Tears of Light", getSettings().game.fastTears);
|
||||
config::ImGuiCheckbox("No Rupee Returns", getSettings().game.noReturnRupees);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Tears of Light dropped by Shadow Insects pop out faster like the HD version.");
|
||||
ImGui::SetTooltip("Always collect Rupees even if your Wallet is too full.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Hide TV Settings Screen", getSettings().game.hideTvSettingsScreen);
|
||||
config::ImGuiCheckbox("No Sword Recoil", getSettings().game.noSwordRecoil);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Hides the TV calibration screen shown when loading a save.");
|
||||
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("Skips the warning screen shown when loading the game.");
|
||||
ImGui::SetTooltip("Skip the warning screen shown when starting the game.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Instant Saves", getSettings().game.instantSaves);
|
||||
config::ImGuiCheckbox("Sun's Song (R+X)", getSettings().game.sunsSong);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Skip the delay when writing to the Memory Card.");
|
||||
ImGui::SetTooltip("Allows Wolf Link to howl and change the time of day.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Preferences")) {
|
||||
config::ImGuiCheckbox("Mirror Mode", getSettings().game.enableMirrorMode);
|
||||
config::ImGuiCheckbox("Quick Transform (R+Y)", getSettings().game.enableQuickTransform);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Mirrors the world, matching the Wii version of the game.");
|
||||
ImGui::SetTooltip("Transform instantly by pressing R and Y simultaneously.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -122,6 +138,10 @@ namespace dusk {
|
||||
}
|
||||
|
||||
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 while aiming the\n"
|
||||
@@ -133,9 +153,18 @@ namespace dusk {
|
||||
config::ImGuiCheckbox("Invert Gyro Pitch", getSettings().game.gyroAimInvertPitch);
|
||||
config::ImGuiCheckbox("Invert Gyro Yaw", getSettings().game.gyroAimInvertYaw);
|
||||
|
||||
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("Fast Iron Boots", getSettings().game.enableFastIronBoots);
|
||||
|
||||
@@ -157,23 +186,6 @@ namespace dusk {
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Difficulty")) {
|
||||
config::ImGuiSliderInt("Damage Multiplier", getSettings().game.damageMultiplier, 1, 8, "x%d");
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Instant Death", getSettings().game.instantDeath);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Any hit will instantly kill you.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Technical")) {
|
||||
config::ImGuiCheckbox("Restore Wii 1.0 Glitches", getSettings().game.restoreWiiGlitches);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
@@ -184,16 +196,6 @@ namespace dusk {
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Tools")) {
|
||||
config::ImGuiCheckbox("Enable Turbo Key", getSettings().game.enableTurboKeybind);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Holding TAB will speed up the game.\n"
|
||||
"This will not work with the \"Unlock Framerate\" enhancement.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "ImGuiConsole.hpp"
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "../iso_validate.hpp"
|
||||
|
||||
#include <SDL3/SDL_dialog.h>
|
||||
#include <SDL3/SDL_error.h>
|
||||
@@ -26,15 +27,42 @@ static constexpr std::array<SDL_DialogFileFilter, 2> skGameDiscFileFilters{{
|
||||
{"All Files", "*"},
|
||||
}};
|
||||
|
||||
static std::string ShowIsoInvalidError(const iso::ValidationError code) {
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
switch (code) {
|
||||
case iso::ValidationError::IOError:
|
||||
return "Unknown IO error occurred"s;
|
||||
case iso::ValidationError::InvalidImage:
|
||||
return "Unable to interpret selected file as a disc image"s;
|
||||
case iso::ValidationError::WrongGame:
|
||||
return "Selected disc image is for a different game"s;
|
||||
case iso::ValidationError::WrongVersion:
|
||||
return "Selected disc image is for an unsupported version of the game. Only North American GameCube (NTSC/GZ2E01) is supported at this time."s;
|
||||
case iso::ValidationError::ExecutableMismatch:
|
||||
return "Selected disc image contains modified executable files."s;
|
||||
default:
|
||||
return "Unknown error"s;
|
||||
}
|
||||
}
|
||||
|
||||
void fileDialogCallback(void* userdata, const char* const* filelist, [[maybe_unused]] int filter) {
|
||||
auto* self = static_cast<ImGuiPreLaunchWindow*>(userdata);
|
||||
self->m_errorString.clear();
|
||||
if (filelist != nullptr) {
|
||||
if (filelist[0] == nullptr) {
|
||||
// Cancelled
|
||||
self->m_selectedIsoPath.clear();
|
||||
} else {
|
||||
self->m_selectedIsoPath = filelist[0];
|
||||
getSettings().backend.isoPath.setValue(self->m_selectedIsoPath);
|
||||
const auto path = filelist[0];
|
||||
const auto ret = iso::validate(path);
|
||||
if (ret != iso::ValidationError::Success) {
|
||||
self->m_selectedIsoPath.clear();
|
||||
self->m_errorString = std::move(ShowIsoInvalidError(ret));
|
||||
return;
|
||||
}
|
||||
self->m_selectedIsoPath = path;
|
||||
getSettings().backend.isoPath.setValue(path);
|
||||
config::Save();
|
||||
}
|
||||
} else {
|
||||
@@ -111,6 +139,10 @@ void ImGuiPreLaunchWindow::drawMainMenu() {
|
||||
ImGui::PushFont(ImGuiEngine::fontLarge);
|
||||
|
||||
if (!isSelectedPathValid()) {
|
||||
if (!m_errorString.empty()) {
|
||||
ImGuiTextCenter(m_errorString);
|
||||
}
|
||||
|
||||
if (ImGuiButtonCenter("Select disc image...")) {
|
||||
SDL_ShowOpenFileDialog(&fileDialogCallback, this, aurora::window::get_sdl_window(),
|
||||
skGameDiscFileFilters.data(), int(skGameDiscFileFilters.size()),
|
||||
@@ -148,6 +180,10 @@ void ImGuiPreLaunchWindow::drawOptions() {
|
||||
if (ImGui::BeginChild("OptionsChild", ImVec2(childWidth, endCursorY - cursorY),
|
||||
ImGuiChildFlags_None, ImGuiWindowFlags_NoBackground))
|
||||
{
|
||||
if (!m_errorString.empty()) {
|
||||
ImGuiTextCenter(m_errorString);
|
||||
}
|
||||
|
||||
ImGui::InputText("Game ISO Path", &m_selectedIsoPath, ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Set")) {
|
||||
|
||||
@@ -445,7 +445,7 @@ namespace dusk {
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Minigame")) {
|
||||
//DrawFlagsTab();
|
||||
drawMinigameTab();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
@@ -829,8 +829,8 @@ namespace dusk {
|
||||
|
||||
ImGuiBeginGroupPanel("Items", { 200, 100 });
|
||||
for (int slot = 0; slot < 24; slot++) {
|
||||
ImGui::Text("Slot %02d: ", slot);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Slot %02d (%s): ", slot, itemMap.find(getSlotDefault(slot))->second.m_name.c_str());
|
||||
ImGui::SameLine(240.0f);
|
||||
if (ImGui::BeginCombo(fmt::format("##ItemComboBox{}", slot).c_str(), itemMap.find(item.mItems[slot])->second.m_name.c_str())) {
|
||||
if (ImGui::Selectable("None")) {
|
||||
dComIfGs_setItem(slot, dItemNo_NONE_e);
|
||||
@@ -856,7 +856,27 @@ namespace dusk {
|
||||
}
|
||||
ImGuiEndGroupPanel();
|
||||
|
||||
dSv_player_item_record_c& itemRecord = dComIfGs_getSaveData()->getPlayer().getItemRecord();
|
||||
dSv_player_item_max_c& itemMax = dComIfGs_getSaveData()->getPlayer().getItemMax();
|
||||
|
||||
ImGuiBeginGroupPanel("Item Max Capacities", { 200, 100 });
|
||||
ImGui::InputScalar("Arrows Max", ImGuiDataType_U8, &itemMax.mItemMax[0]);
|
||||
ImGui::InputScalar("Normal Bombs Max", ImGuiDataType_U8, &itemMax.mItemMax[1]);
|
||||
ImGui::InputScalar("Water Bombs Max", ImGuiDataType_U8, &itemMax.mItemMax[2]);
|
||||
ImGui::InputScalar("Bomblings Max", ImGuiDataType_U8, &itemMax.mItemMax[3]);
|
||||
ImGuiEndGroupPanel();
|
||||
|
||||
ImGuiBeginGroupPanel("Item Amounts", { 200, 100 });
|
||||
ImGui::InputScalar("Arrows Amount", ImGuiDataType_U8, &itemRecord.mArrowNum);
|
||||
ImGui::InputScalar("Slingshot Amount", ImGuiDataType_U8, &itemRecord.mPachinkoNum);
|
||||
ImGui::InputScalar("Bomb Bag 1 Amount", ImGuiDataType_U8, &itemRecord.mBombNum[0]);
|
||||
ImGui::InputScalar("Bomb Bag 2 Amount", ImGuiDataType_U8, &itemRecord.mBombNum[1]);
|
||||
ImGui::InputScalar("Bomb Bag 3 Amount", ImGuiDataType_U8, &itemRecord.mBombNum[2]);
|
||||
ImGui::InputScalar("Bottle 1 Amount", ImGuiDataType_U8, &itemRecord.mBottleNum[0]);
|
||||
ImGui::InputScalar("Bottle 2 Amount", ImGuiDataType_U8, &itemRecord.mBottleNum[1]);
|
||||
ImGui::InputScalar("Bottle 3 Amount", ImGuiDataType_U8, &itemRecord.mBottleNum[2]);
|
||||
ImGui::InputScalar("Bottle 4 Amount", ImGuiDataType_U8, &itemRecord.mBottleNum[3]);
|
||||
ImGuiEndGroupPanel();
|
||||
}
|
||||
|
||||
static inline void setItemFirstBit(u8 itemNo, bool owned) {
|
||||
@@ -902,27 +922,42 @@ namespace dusk {
|
||||
void ImGuiSaveEditor::drawCollectionTab() {
|
||||
if (ImGui::TreeNode("Equipment")) {
|
||||
if (ImGui::TreeNode("Swords")) {
|
||||
static u8 sword_list[] = {
|
||||
dItemNo_SWORD_e,
|
||||
dItemNo_MASTER_SWORD_e,
|
||||
dItemNo_WOOD_STICK_e,
|
||||
dItemNo_LIGHT_SWORD_e,
|
||||
};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
bool got = dComIfGs_isCollectSword((u8)i) != 0;
|
||||
bool got = dComIfGs_isItemFirstBit(sword_list[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);
|
||||
if (got) dComIfGs_onItemFirstBit(sword_list[i]);
|
||||
else dComIfGs_offItemFirstBit(sword_list[i]);
|
||||
}
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNode("Shields")) {
|
||||
static u8 shield_list[] = {
|
||||
dItemNo_SHIELD_e,
|
||||
dItemNo_WOOD_SHIELD_e,
|
||||
dItemNo_HYLIA_SHIELD_e,
|
||||
};
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
bool got = dComIfGs_isCollectShield((u8)i) != 0;
|
||||
bool got = dComIfGs_isItemFirstBit(shield_list[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);
|
||||
if (got) dComIfGs_onItemFirstBit(shield_list[i]);
|
||||
else dComIfGs_offItemFirstBit(shield_list[i]);
|
||||
}
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
// TODO: the game checks if you're in ranch clothes, and if so won't display any other tunics in the menu
|
||||
// find a way to deal with this later
|
||||
if (ImGui::TreeNode("Tunics")) {
|
||||
bool ordonClothes = dComIfGs_isItemFirstBit(dItemNo_WEAR_CASUAL_e) != 0;
|
||||
if (ImGui::Checkbox("Ordon Clothes##tunic_ordon", &ordonClothes)) {
|
||||
@@ -1235,7 +1270,7 @@ namespace dusk {
|
||||
}
|
||||
ImGuiEndGroupPanel();
|
||||
|
||||
ImVec2 cursor = ImGui::GetCursorPos();
|
||||
ImVec2 start_cursor = ImGui::GetCursorPos();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -1245,13 +1280,17 @@ namespace dusk {
|
||||
}
|
||||
ImGuiEndGroupPanel();
|
||||
|
||||
ImGui::SetCursorPos(cursor);
|
||||
ImVec2 cursor = ImGui::GetCursorPos();
|
||||
|
||||
ImGui::SetCursorPos(start_cursor);
|
||||
|
||||
ImGuiBeginGroupPanel("Item", { 100, 100 });
|
||||
for (int j = 0; j < 1; j++) {
|
||||
drawFlagList(fmt::format("##_item{}", j).c_str(), membit.mItem[j]);
|
||||
}
|
||||
ImGuiEndGroupPanel();
|
||||
|
||||
ImGui::SetCursorPos({ start_cursor.x, cursor.y });
|
||||
}
|
||||
|
||||
void ImGuiSaveEditor::drawFlagsTab() {
|
||||
@@ -1328,7 +1367,7 @@ namespace dusk {
|
||||
dSv_event_c& event = dComIfGs_getSaveData()->mEvent;
|
||||
for (int e = 0; e < 255; e++) {
|
||||
ImGui::Text("%03d ", e);
|
||||
ImGui::SameLine();
|
||||
ImGui::SameLine(80.0f);
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
bool flag = event.mEvent[e] & (1 << i);
|
||||
if (ImGui::Checkbox(fmt::format("##event{0}{1}", e, i).c_str(), &flag)) {
|
||||
@@ -1345,10 +1384,25 @@ namespace dusk {
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiSaveEditor::drawMinigameTab() {
|
||||
dSv_MiniGame_c& minigame = dComIfGs_getSaveData()->getMiniGame();
|
||||
InputScalarBE("STAR Game Time (Milliseconds)", ImGuiDataType_U32, &minigame.mHookGameTime);
|
||||
InputScalarBE("Snowboard Race Time (Milliseconds)", ImGuiDataType_U32, &minigame.mRaceGameTime);
|
||||
InputScalarBE("Fruit-Pop-Flight Score", ImGuiDataType_U32, &minigame.mBalloonScore);
|
||||
}
|
||||
|
||||
void ImGuiSaveEditor::drawConfigTab() {
|
||||
dSv_player_config_c& config = dComIfGs_getSaveData()->getPlayer().getConfig();
|
||||
ImGui::Checkbox("Enable Vibration", (bool*)&config.mVibration);
|
||||
if (ImGui::BeginCombo("Target Type", "Hold")) {
|
||||
|
||||
static const char* kTargetTypeNames[] = {"Hold", "Switch"};
|
||||
if (ImGui::BeginCombo("Target Type", kTargetTypeNames[config.mAttentionType])) {
|
||||
if (ImGui::Selectable("Hold")) {
|
||||
config.mAttentionType = 0;
|
||||
}
|
||||
if (ImGui::Selectable("Switch")) {
|
||||
config.mAttentionType = 1;
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace dusk {
|
||||
void drawInventoryTab();
|
||||
void drawCollectionTab();
|
||||
void drawFlagsTab();
|
||||
void drawMinigameTab();
|
||||
void drawConfigTab();
|
||||
|
||||
private:
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
#include "iso_validate.hpp"
|
||||
|
||||
#include <nod.h>
|
||||
#include <span>
|
||||
|
||||
#include "SDL3/SDL_iostream.h"
|
||||
|
||||
namespace dusk::iso {
|
||||
|
||||
constexpr const char* TP_GAME_IDS[] = {
|
||||
"GZ2E01", // GCN USA
|
||||
"GZ2P01", // GCN PAL
|
||||
"GZ2J01", // GCN JPN
|
||||
"RZDE01", // Wii USA
|
||||
"RZDP01", // Wii PAL
|
||||
"RZDJ01", // Wii JPN
|
||||
"RZDK01", // Wii KOR
|
||||
};
|
||||
|
||||
constexpr const char* SUPPORTED_TP_GAME_IDS[] = {
|
||||
"GZ2E01", // GCN USA
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
constexpr bool matches(const char (&id)[6], const char* const (&valid)[N]) {
|
||||
for (auto elem : valid) {
|
||||
if (strncmp(id, elem, 6) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct NodHandleWrapper {
|
||||
NodHandle* handle;
|
||||
|
||||
NodHandleWrapper() : handle(nullptr) {
|
||||
}
|
||||
|
||||
~NodHandleWrapper() {
|
||||
if (handle != nullptr) {
|
||||
nod_free(handle);
|
||||
handle = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static ValidationError convertNodError(NodResult result) {
|
||||
switch (result) {
|
||||
case NOD_RESULT_ERR_IO:
|
||||
return ValidationError::IOError;
|
||||
case NOD_RESULT_ERR_FORMAT:
|
||||
return ValidationError::InvalidImage;
|
||||
default:
|
||||
return ValidationError::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
s64 StreamReadAt(void* user_data, u64 offset, void* out, size_t len) {
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto io = static_cast<SDL_IOStream*>(user_data);
|
||||
|
||||
auto ret = SDL_SeekIO(io, static_cast<s64>(offset), SDL_IO_SEEK_SET);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto read = SDL_ReadIO(io, out, len);
|
||||
if (read == 0) {
|
||||
if (SDL_GetIOStatus(io) == SDL_IO_STATUS_EOF) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return static_cast<s64>(read);
|
||||
}
|
||||
|
||||
s64 StreamLength(void* user_data) {
|
||||
auto io = static_cast<SDL_IOStream*>(user_data);
|
||||
return SDL_GetIOSize(io);
|
||||
}
|
||||
|
||||
void StreamClose(void* user_data) {
|
||||
auto io = static_cast<SDL_IOStream*>(user_data);
|
||||
SDL_CloseIO(io);
|
||||
}
|
||||
|
||||
ValidationError validate(const char* path) {
|
||||
NodHandleWrapper disc;
|
||||
|
||||
const auto sdlStream = SDL_IOFromFile(path, "rb");
|
||||
const NodDiscStream nod_stream {
|
||||
.user_data = sdlStream,
|
||||
.read_at = StreamReadAt,
|
||||
.stream_len = StreamLength,
|
||||
.close = StreamClose,
|
||||
};
|
||||
|
||||
auto result = nod_disc_open_stream(&nod_stream, nullptr, &disc.handle);
|
||||
if (disc.handle == nullptr || result != NOD_RESULT_OK) {
|
||||
return convertNodError(result);
|
||||
}
|
||||
|
||||
NodDiscHeader header{};
|
||||
result = nod_disc_header(disc.handle, &header);
|
||||
if (result != NOD_RESULT_OK) {
|
||||
return convertNodError(result);
|
||||
}
|
||||
|
||||
if (!matches(header.game_id, TP_GAME_IDS)) {
|
||||
return ValidationError::WrongGame;
|
||||
}
|
||||
|
||||
if (!matches(header.game_id, SUPPORTED_TP_GAME_IDS)) {
|
||||
return ValidationError::WrongVersion;
|
||||
}
|
||||
|
||||
return ValidationError::Success;
|
||||
}
|
||||
} // namespace dusk::iso
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef DUSK_ISO_VALIDATE_HPP
|
||||
#define DUSK_ISO_VALIDATE_HPP
|
||||
|
||||
namespace dusk::iso {
|
||||
enum class ValidationError : u8 {
|
||||
Success = 0,
|
||||
IOError,
|
||||
InvalidImage,
|
||||
WrongGame,
|
||||
WrongVersion,
|
||||
ExecutableMismatch,
|
||||
Unknown
|
||||
};
|
||||
|
||||
ValidationError validate(const char* path);
|
||||
}
|
||||
|
||||
#endif // DUSK_ISO_VALIDATE_HPP
|
||||
@@ -40,6 +40,7 @@ UserSettings g_userSettings = {
|
||||
// Preferences
|
||||
.enableMirrorMode {"game.enableMirrorMode", false},
|
||||
.invertCameraXAxis {"game.invertCameraXAxis", false},
|
||||
.disableMainHUD {"game.disableMainHUD", false},
|
||||
|
||||
// Graphics
|
||||
.bloomMode {"game.bloomMode", BloomMode::Classic},
|
||||
@@ -117,6 +118,7 @@ void registerSettings() {
|
||||
Register(g_userSettings.game.sunsSong);
|
||||
Register(g_userSettings.game.enableMirrorMode);
|
||||
Register(g_userSettings.game.invertCameraXAxis);
|
||||
Register(g_userSettings.game.disableMainHUD);
|
||||
Register(g_userSettings.game.bloomMode);
|
||||
Register(g_userSettings.game.bloomMultiplier);
|
||||
Register(g_userSettings.game.enableWaterRefraction);
|
||||
|
||||
@@ -64,13 +64,12 @@ void fpcM_Management(fpcM_ManagementFunc i_preExecuteFn, fpcM_ManagementFunc i_p
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
// Frame interpolation: call moved to m_Do_main
|
||||
if (!dusk::getSettings().game.enableFrameInterpolation) {
|
||||
// FRAME INTERP NOTE: Called in m_Do_main when interp is enabled
|
||||
if (!dusk::getSettings().game.enableFrameInterpolation || dusk::getTransientSettings().skipFrameRateLimit)
|
||||
#endif
|
||||
{
|
||||
cAPIGph_Painter();
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!dPa_control_c::isStatus(1)) {
|
||||
fpcDt_Handler();
|
||||
|
||||
@@ -2383,8 +2383,8 @@ void mDoExt_3DlineMat0_c::draw() {
|
||||
int var_r26 = (field_0x14 << 1) & 0xFFFF;
|
||||
|
||||
for (int i = 0; i < field_0x10; i++) {
|
||||
GXSETARRAY(GX_VA_POS, field_0x18->field_0x8[field_0x16], sizeof(cXyz) * var_r26, sizeof(cXyz), true);
|
||||
GXSETARRAY(GX_VA_NRM, field_0x18->field_0x10[field_0x16], 3 * var_r26, 3, true);
|
||||
GXSETARRAY(GX_VA_POS, var_r28->field_0x8[field_0x16], sizeof(cXyz) * var_r26, sizeof(cXyz), true);
|
||||
GXSETARRAY(GX_VA_NRM, var_r28->field_0x10[field_0x16], 3 * var_r26, 3, true);
|
||||
|
||||
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, var_r26);
|
||||
for (u16 j = 0; j < (u16)var_r26; j++) {
|
||||
|
||||
@@ -2034,12 +2034,11 @@ int mDoGph_Painter() {
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_PC
|
||||
for (u32 i = 0; i < pending_ui_ticks; ++i) {
|
||||
for (u32 i = 0; i < pending_ui_ticks; ++i)
|
||||
#endif
|
||||
{
|
||||
dComIfGp_particle_calcMenu();
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
|
||||
JFWDisplay::getManager()->setFader(mDoGph_gInf_c::getFader());
|
||||
mDoGph_gInf_c::setClearColor(mDoGph_gInf_c::getBackColor());
|
||||
@@ -2599,13 +2598,12 @@ int mDoGph_Painter() {
|
||||
#endif
|
||||
|
||||
GXSetClipMode(GX_CLIP_ENABLE);
|
||||
#ifdef TARGET_PC
|
||||
for (u32 i = 0; i < pending_ui_ticks; ++i) {
|
||||
#if TARGET_PC
|
||||
for (u32 i = 0; i < pending_ui_ticks; ++i)
|
||||
#endif
|
||||
{
|
||||
dDlst_list_c::calcWipe();
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
j3dSys.reinitGX();
|
||||
|
||||
ortho.setOrtho(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(),
|
||||
|
||||
@@ -202,9 +202,8 @@ void main01(void) {
|
||||
if (preLaunchUIWindowSize.width != 0)
|
||||
mDoGph_gInf_c::setWindowSize(preLaunchUIWindowSize);
|
||||
|
||||
using clock = std::chrono::steady_clock;
|
||||
constexpr double kSimStepSeconds = 1.0 / 30.0;
|
||||
auto previous_time = clock::now();
|
||||
auto previous_time = std::chrono::steady_clock::now();
|
||||
double accumulator = kSimStepSeconds;
|
||||
|
||||
do {
|
||||
@@ -229,7 +228,7 @@ void main01(void) {
|
||||
|
||||
eventsDone:;
|
||||
|
||||
auto current_time = clock::now();
|
||||
auto current_time = std::chrono::steady_clock::now();
|
||||
double frame_seconds = std::chrono::duration<double>(current_time - previous_time).count();
|
||||
previous_time = current_time;
|
||||
accumulator += frame_seconds;
|
||||
@@ -242,9 +241,8 @@ void main01(void) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
if (dusk::getSettings().game.enableFrameInterpolation && !dusk::getTransientSettings().skipFrameRateLimit) {
|
||||
dusk::frame_interp::notify_presentation_frame();
|
||||
|
||||
while (accumulator >= kSimStepSeconds) {
|
||||
mDoCPd_c::read();
|
||||
if (dusk::getSettings().game.enableGyroAim) {
|
||||
@@ -254,13 +252,11 @@ void main01(void) {
|
||||
mDoAud_Execute();
|
||||
accumulator -= kSimStepSeconds;
|
||||
}
|
||||
|
||||
float interp_alpha = static_cast<float>(accumulator / kSimStepSeconds);
|
||||
dusk::frame_interp::interpolate(interp_alpha);
|
||||
dusk::frame_interp::interpolate(static_cast<float>(accumulator / kSimStepSeconds));
|
||||
cAPIGph_Painter();
|
||||
} else {
|
||||
accumulator = 0.0;
|
||||
|
||||
|
||||
// Game Inputs
|
||||
mDoCPd_c::read();
|
||||
if (dusk::getSettings().game.enableGyroAim) {
|
||||
|
||||
Reference in New Issue
Block a user