Merge remote-tracking branch 'origin/main' into mods

# Conflicts:
#	CMakeLists.txt
#	include/dusk/gx_helper.h
This commit is contained in:
Luke Street
2026-06-06 09:44:35 -06:00
64 changed files with 1626 additions and 559 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install ninja-build clang lld openssl libcurl4-openssl-dev \
sudo apt-get -y install ninja-build clang lld mold 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 \
+15 -1
View File
@@ -137,11 +137,18 @@ target_compile_definitions(aurora_mtx PRIVATE MTX_USE_PS=1)
add_subdirectory(libs/freeverb)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DUSK_GFX_DEBUG_GROUPS_DEFAULT ON)
else ()
set(DUSK_GFX_DEBUG_GROUPS_DEFAULT OFF)
endif ()
option(DUSK_BUILD_WARNINGS "Enable compiler warnings (off by default)")
option(DUSK_SELECTED_OPT "If on, selected parts of the project will be compiled with optimizations on Debug, intending to make the game run at 30 FPS. Note for MSVC: you will need to remove '/RTC1' from your debug flags in CMake.")
option(DUSK_MOVIE_SUPPORT "If on, compile against libjpeg-turbo to enable THP file decoding" ON)
option(DUSK_ENABLE_UPDATE_CHECKER "Enable update checking support" ON)
option(DUSK_ENABLE_SENTRY_NATIVE "Enable sentry-native crash reporting support" OFF)
option(DUSK_GFX_DEBUG_GROUPS "Report debug groups to the native graphics API" ${DUSK_GFX_DEBUG_GROUPS_DEFAULT})
set(DUSK_SENTRY_DSN "" CACHE STRING "Sentry DSN")
set(DUSK_SENTRY_ENVIRONMENT "development" CACHE STRING "Sentry environment")
@@ -189,6 +196,8 @@ if (DUSK_MOVIE_SUPPORT)
CMAKE_MSVC_RUNTIME_LIBRARY
CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
CMAKE_OSX_ARCHITECTURES
CMAKE_OSX_DEPLOYMENT_TARGET
CMAKE_OSX_SYSROOT
DEPLOYMENT_TARGET
ENABLE_ARC
ENABLE_BITCODE
@@ -380,7 +389,7 @@ set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::p
aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt funchook-static
Threads::Threads)
list(APPEND GAME_LIBS libzstd_static)
list(APPEND GAME_LIBS zstd::libzstd)
if (DUSK_ENABLE_SENTRY_NATIVE)
list(APPEND GAME_LIBS sentry)
@@ -462,6 +471,11 @@ if (DUSK_ENABLE_CODE_MODS)
endif ()
endif ()
if (DUSK_GFX_DEBUG_GROUPS)
list(APPEND GAME_COMPILE_DEFS DUSK_GFX_DEBUG_GROUPS=1)
target_compile_definitions(aurora_gx PRIVATE AURORA_GFX_DEBUG_GROUPS)
endif ()
# game_debug is for game code files that we know work when compiled with DEBUG=1
# Of course, if building a release build, this distinction is irrelevant
set(GAME_DEBUG_FILES
+41 -20
View File
@@ -19,7 +19,19 @@
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded"
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDLL"
}
},
{
"name": "release",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDLL",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": {
"type": "BOOL",
"value": true
}
}
},
{
@@ -46,6 +58,10 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
},
"vendor": {
@@ -201,6 +217,10 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
},
"vendor": {
@@ -284,24 +304,21 @@
"type": "BOOL",
"value": false
},
"ENABLE_ARC": {
"type": "BOOL",
"value": false
},
"Rust_CARGO_TARGET": "aarch64-apple-tvos",
"Rust_TOOLCHAIN": "nightly",
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_DISABLE_FIND_PACKAGE_BZip2": {
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_LibLZMA": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_zstd": {
"type": "BOOL",
"value": true
}
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew"
},
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": {
@@ -327,8 +344,14 @@
"type": "BOOL",
"value": false
},
"AURORA_SDL3_VERSION": "3.4.8",
"AURORA_SDL3_REF": "refs/tags/release-3.4.8"
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_zstd": {
"type": "BOOL",
"value": true
}
}
},
{
@@ -356,7 +379,8 @@
"hidden": true,
"inherits": [
"android-base",
"ci"
"ci",
"release"
],
"cacheVariables": {
"DUSK_ENABLE_SENTRY_NATIVE": {
@@ -384,7 +408,8 @@
"ci"
],
"cacheVariables": {
"AURORA_SDL3_PROVIDER": "vendor"
"AURORA_SDL3_PROVIDER": "vendor",
"CMAKE_LINKER_TYPE": "MOLD"
}
},
{
@@ -413,12 +438,8 @@
"type": "BOOL",
"value": true
},
"CMAKE_OSX_DEPLOYMENT_TARGET": "11.0",
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew",
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
}
"CMAKE_OSX_DEPLOYMENT_TARGET": "12.0",
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew"
}
},
{
+1 -1
+1
View File
@@ -1432,6 +1432,7 @@ set(DUSK_FILES
src/dusk/game_clock.cpp
src/dusk/globals.cpp
src/dusk/gyro.cpp
src/dusk/mouse.cpp
src/dusk/gamepad_color.cpp
src/dusk/autosave.cpp
src/dusk/http/http.hpp
+32
View File
@@ -0,0 +1,32 @@
From f69d29614644f9963f5cb3f828b58575d60a1c5a Mon Sep 17 00:00:00 2001
From: Joshua Trees <gh@jtrees.io>
Date: Thu, 4 Jun 2026 01:04:04 +0100
Subject: [PATCH] fix cmake paths
---
cmake/nodConfig.cmake.in | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/cmake/nodConfig.cmake.in b/cmake/nodConfig.cmake.in
index 0969382..2a24a88 100644
--- a/cmake/nodConfig.cmake.in
+++ b/cmake/nodConfig.cmake.in
@@ -1,12 +1,12 @@
@PACKAGE_INIT@
-set(_nod_libdir "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_LIBDIR@")
-set(_nod_incdir "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@")
+set(_nod_libdir "@CMAKE_INSTALL_FULL_LIBDIR@")
+set(_nod_incdir "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
if (NOT TARGET nod::nod_shared AND NOT TARGET nod::nod_static)
# Shared library
if (WIN32)
- set(_nod_dll "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_BINDIR@/${CMAKE_SHARED_LIBRARY_PREFIX}nod${CMAKE_SHARED_LIBRARY_SUFFIX}")
+ set(_nod_dll "@CMAKE_INSTALL_FULL_BINDIR@/${CMAKE_SHARED_LIBRARY_PREFIX}nod${CMAKE_SHARED_LIBRARY_SUFFIX}")
set(_nod_implib "${_nod_libdir}/${CMAKE_IMPORT_LIBRARY_PREFIX}nod${CMAKE_IMPORT_LIBRARY_SUFFIX}")
if (EXISTS "${_nod_dll}")
add_library(nod::nod_shared SHARED IMPORTED)
--
2.53.0
+127 -115
View File
@@ -57,12 +57,22 @@
inherit (pkgs.stdenv.hostPlatform) isDarwin;
hasNodPrebuilt = nodPrebuiltInfo ? ${system};
aurora = pkgs.fetchFromGitHub {
owner = "encounter";
repo = "aurora";
rev = "10006618ee493f248b8597e4dfa1d2871d76a1d9";
hash = "sha256-lY2xuVyB7aPJ9+2wwLRB3F5U/BuPSxdSpegdG+qNd9o=";
};
aurora = builtins.pathExists "${self}/extern/aurora/CMakeLists.txt";
needSubmodules = ''
dusklight: The aurora submodule is not vendored. Add submodules=1 to build.
As a flake input:
dusklight.url = "git+https://github.com/TwilitRealm/dusklight?ref=main&submodules=1";
nix command:
nix run 'git+https://github.com/TwilitRealm/dusklight?submodules=1'
Local checkout:
nix run '.?submodules=1#dusklight'
'';
dawn = pkgs.fetchzip {
url = "https://github.com/encounter/dawn-build/releases/download/${dawnVersion}/dawn-${dawnInfo.${system}.triple}.tar.gz";
@@ -86,6 +96,7 @@
rev = nodVersion;
hash = "sha256-+zrtVzjo0+X/6uMcNUn1+FaSR+jOhrcQSDNBFjw0NDs=";
};
patches = [ ./fix-cmake-paths.patch ];
cargoDeps = pkgs.rustPlatform.importCargoLock {
lockFile = "${finalAttrs.src}/Cargo.lock";
};
@@ -153,119 +164,120 @@
};
};
dusklight = pkgs.stdenv.mkDerivation {
pname = "dusklight";
version = versionSuffix;
src = ./.;
dusklight =
if !aurora then
throw needSubmodules
else
pkgs.stdenv.mkDerivation {
pname = "dusklight";
version = versionSuffix;
src = ./.;
postUnpack = ''
chmod -R u+w "$sourceRoot"
rm -rf "$sourceRoot/extern/aurora"
mkdir -p "$sourceRoot/extern"
cp -r ${aurora} "$sourceRoot/extern/aurora"
chmod -R u+w "$sourceRoot/extern/aurora"
substituteInPlace "$sourceRoot/extern/aurora/CMakeLists.txt" \
--replace-warn "add_subdirectory(tests)" ""
'';
nativeBuildInputs = [
pkgs.cmake
pkgs.ninja
pkgs.pkg-config
pkgs.python3
pkgs.python3Packages.markupsafe
]
++ lib.optionals (!isDarwin) [ pkgs.autoPatchelfHook ];
buildInputs = [
pkgs.sdl3
pkgs.freetype
pkgs.zstd
pkgs.cxxopts
pkgs.nlohmann_json
pkgs.xxHash
pkgs.abseil-cpp
pkgs.zlib
pkgs.libpng
pkgs.libjpeg_turbo
pkgs.curl
pkgs.openssl
]
++ lib.optionals isDarwin [
pkgs.apple-sdk_15
pkgs.libiconv
]
++ lib.optionals (!isDarwin) [
pkgs.libGL
pkgs.libGLU
pkgs.libglvnd
pkgs.vulkan-loader
pkgs.libX11
pkgs.libxcb
pkgs.libXcursor
pkgs.libxi
pkgs.libxrandr
pkgs.libxscrnsaver
pkgs.libxtst
pkgs.libxinerama
pkgs.libxkbcommon
pkgs.wayland
pkgs.libdecor
pkgs.alsa-lib
pkgs.libpulseaudio
pkgs.pipewire
pkgs.dbus
pkgs.udev
pkgs.libusb1
pkgs.libunwind
pkgs.gtk3
];
cmakeBuildType = "RelWithDebInfo";
ninjaFlags = [ "dusklight" ];
cmakeFlags = [
"-DDUSK_VERSION_OVERRIDE=${versionSuffix}"
"-DFETCHCONTENT_FULLY_DISCONNECTED=ON"
"-DAURORA_DAWN_PROVIDER=package"
"-DAURORA_DAWN_LINKAGE=static"
"-DAURORA_NOD_PROVIDER=package"
"-DAURORA_NOD_LINKAGE=static"
"-DAURORA_SDL3_PROVIDER=system"
]
++ lib.mapAttrsToList (key: src: "-DFETCHCONTENT_SOURCE_DIR_${key}=${src}") fetchContentDirs;
installPhase =
if isDarwin then
''
runHook preInstall
mkdir -p "$out/Applications"
cp -r Dusklight.app "$out/Applications/Dusklight.app"
runHook postInstall
''
else
''
runHook preInstall
install -Dm755 dusklight "$out/bin/dusklight"
cp -r "$src/res" "$out/bin/res"
install -Dm644 "$src/platforms/freedesktop/dev.twilitrealm.dusk.desktop" \
"$out/share/applications/dev.twilitrealm.dusk.desktop"
for size in 16 32 48 64 128 256 512 1024; do
install -Dm644 "$src/platforms/freedesktop/''${size}x''${size}/apps/dev.twilitrealm.dusk.png" \
"$out/share/icons/hicolor/''${size}x''${size}/apps/dev.twilitrealm.dusk.png"
done
runHook postInstall
postUnpack = ''
chmod -R u+w "$sourceRoot"
substituteInPlace "$sourceRoot/extern/aurora/CMakeLists.txt" \
--replace-warn "add_subdirectory(tests)" ""
'';
dontStrip = true;
nativeBuildInputs = [
pkgs.cmake
pkgs.ninja
pkgs.pkg-config
pkgs.python3
pkgs.python3Packages.markupsafe
]
++ lib.optionals (!isDarwin) [ pkgs.autoPatchelfHook ];
meta = {
description = "Dusklight native PC port of the Twilight Princess decompilation";
homepage = "https://github.com/zeldaret/tp";
platforms = supportedSystems;
mainProgram = "dusklight";
};
};
buildInputs = [
pkgs.sdl3
pkgs.freetype
pkgs.zstd
pkgs.cxxopts
pkgs.nlohmann_json
pkgs.xxHash
pkgs.abseil-cpp
pkgs.zlib
pkgs.libpng
pkgs.libjpeg_turbo
pkgs.curl
pkgs.openssl
]
++ lib.optionals isDarwin [
pkgs.apple-sdk_15
pkgs.libiconv
]
++ lib.optionals (!isDarwin) [
pkgs.libGL
pkgs.libGLU
pkgs.libglvnd
pkgs.vulkan-loader
pkgs.libX11
pkgs.libxcb
pkgs.libXcursor
pkgs.libxi
pkgs.libxrandr
pkgs.libxscrnsaver
pkgs.libxtst
pkgs.libxinerama
pkgs.libxkbcommon
pkgs.wayland
pkgs.libdecor
pkgs.alsa-lib
pkgs.libpulseaudio
pkgs.pipewire
pkgs.dbus
pkgs.udev
pkgs.libusb1
pkgs.libunwind
pkgs.gtk3
nod
];
cmakeBuildType = "RelWithDebInfo";
ninjaFlags = [ "dusklight" ];
cmakeFlags = [
"-DDUSK_VERSION_OVERRIDE=${versionSuffix}"
"-DFETCHCONTENT_FULLY_DISCONNECTED=ON"
"-DAURORA_DAWN_PROVIDER=package"
"-DAURORA_DAWN_LINKAGE=static"
"-DAURORA_NOD_PROVIDER=system"
"-DAURORA_SDL3_PROVIDER=system"
"-DBUILD_SHARED_LIBS=OFF"
]
++ lib.mapAttrsToList (key: src: "-DFETCHCONTENT_SOURCE_DIR_${key}=${src}") fetchContentDirs;
installPhase =
if isDarwin then
''
runHook preInstall
mkdir -p "$out/Applications"
cp -r Dusklight.app "$out/Applications/Dusklight.app"
runHook postInstall
''
else
''
runHook preInstall
install -Dm755 dusklight "$out/bin/dusklight"
cp -r "$src/res" "$out/bin/res"
install -Dm644 "$src/platforms/freedesktop/dev.twilitrealm.dusk.desktop" \
"$out/share/applications/dev.twilitrealm.dusk.desktop"
for size in 16 32 48 64 128 256 512 1024; do
install -Dm644 "$src/platforms/freedesktop/''${size}x''${size}/apps/dev.twilitrealm.dusk.png" \
"$out/share/icons/hicolor/''${size}x''${size}/apps/dev.twilitrealm.dusk.png"
done
runHook postInstall
'';
dontStrip = true;
meta = {
description = "Dusklight native PC port of the Twilight Princess decompilation";
homepage = "https://github.com/zeldaret/tp";
platforms = supportedSystems;
mainProgram = "dusklight";
};
};
# Tooling common to every supported host (Linux and macOS).
commonDevTools = [
+5 -1
View File
@@ -88,6 +88,10 @@ public:
/* 0x02C */ cXyz field_0x2c;
/* 0x038 */ cXyz field_0x38[60];
/* 0x308 */ cXyz field_0x308[60];
#if TARGET_PC
TGXTexObj mBlurTexObj;
ResTIMG* mpCachedBlurTex = nullptr;
#endif
}; // Size = 0x5D8
class dAlink_bottleWaterPcallBack_c : public JPAParticleCallBack {
@@ -4551,7 +4555,7 @@ public:
#if TARGET_PC
void handleWolfHowl();
void handleQuickTransform();
bool checkGyroAimContext();
bool checkAimContext();
void onIronBallChainInterpCallback();
+4
View File
@@ -50,6 +50,10 @@ public:
/* 0x14 */ Mtx mProjMtx;
/* 0x44 */ ResTIMG* mpImg;
/* 0x48 */ u8* mpData;
#if TARGET_PC
TGXTexObj mTexObj;
ResTIMG* mpCachedImg = nullptr;
#endif
};
class daPy_boomerangMove_c {
+1
View File
@@ -1037,6 +1037,7 @@ public:
bool test1Camera(s32);
bool test2Camera(s32);
#if TARGET_PC
static bool canUseFreeCam();
bool freeCamera();
bool executeDebugFlyCam();
void deactivateDebugFlyCam();
+2 -1
View File
@@ -198,6 +198,7 @@ struct HOUSI_EFF {
/* 0x4C */ u16 field_0x4c;
}; // Size: 0x50
// Housi is the rising square particles in Twilight
class dKankyo_housi_Packet : public J3DPacket {
public:
virtual void draw();
@@ -208,7 +209,7 @@ public:
/* 0x0020 */ HOUSI_EFF mHousiEff[300];
/* 0x5DE0 */ u8 field_0x5de0[8];
/* 0x5DE8 */ f32 field_0x5de8;
/* 0x5DEC */ s16 field_0x5dec;
/* 0x5DEC */ s16 mHousiCount;
}; // Size: 0x5DF0
struct CLOUD_EFF {
+21
View File
@@ -7,12 +7,16 @@
#include <dolphin/gx/GXExtra.h>
#include "tracy/Tracy.hpp"
#if DUSK_GFX_DEBUG_GROUPS
#define GX_DEBUG_GROUP(name, ...) \
do { \
GXPushDebugGroup(#name); \
name(__VA_ARGS__); \
GXPopDebugGroup(); \
} while (0)
#else
#define GX_DEBUG_GROUP(name, ...) name(__VA_ARGS__)
#endif
#ifdef TARGET_PC
class GXTexObjRAII : public GXTexObj {
@@ -38,8 +42,25 @@ public:
static_assert(sizeof(GXTexObjRAII) == sizeof(GXTexObj),
"GXTexObjRAII should have the same size as GXTexObj");
typedef GXTexObjRAII TGXTexObj;
class GXTlutObjRAII : public GXTlutObj {
public:
GXTlutObjRAII() : GXTlutObj() {}
~GXTlutObjRAII() { GXDestroyTlutObj(this); }
void reset() { GXDestroyTlutObj(this); }
GXTlutObjRAII(const GXTlutObjRAII&) = delete;
GXTlutObjRAII& operator=(const GXTlutObjRAII&) = delete;
GXTlutObjRAII(GXTlutObjRAII&&) = delete;
GXTlutObjRAII& operator=(GXTlutObjRAII&&) = delete;
};
static_assert(sizeof(GXTlutObjRAII) == sizeof(GXTlutObj),
"GXTlutObjRAII should have the same size as GXTlutObj");
typedef GXTlutObjRAII TGXTlutObj;
#else
typedef GXTexObj TGXTexObj;
typedef GXTlutObj TGXTlutObj;
#endif
struct GXScopedDebugGroup {
+1 -4
View File
@@ -1,5 +1,4 @@
#ifndef DUSK_GYRO_H
#define DUSK_GYRO_H
#pragma once
namespace dusk::gyro {
void read(float dt);
@@ -14,5 +13,3 @@ bool get_sensor_keep_alive();
void set_sensor_keep_alive(bool value);
bool rollgoal_gyro_enabled();
} // namespace dusk::gyro
#endif
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include <SDL3/SDL_events.h>
namespace dusk::mouse {
void read();
void getAimDeltas(float& out_yaw, float& out_pitch);
void getCameraDeltas(float& out_yaw, float& out_pitch);
void handle_event(const SDL_Event& event) noexcept;
void onFocusLost();
void onFocusGained();
} // namespace dusk::mouse
+7 -1
View File
@@ -153,6 +153,7 @@ struct UserSettings {
ConfigVar<bool> noMissClimbing;
ConfigVar<bool> fastTears;
ConfigVar<bool> no2ndFishForCat;
ConfigVar<bool> buttonFishing;
ConfigVar<bool> instantSaves;
ConfigVar<bool> instantText;
ConfigVar<bool> sunsSong;
@@ -162,6 +163,7 @@ struct UserSettings {
// Preferences
ConfigVar<bool> enableMirrorMode;
ConfigVar<bool> minimalHUD;
ConfigVar<float> hudScale;
ConfigVar<bool> pauseOnFocusLost;
ConfigVar<bool> enableLinkDollRotation;
ConfigVar<bool> enableAchievementToasts;
@@ -187,7 +189,6 @@ struct UserSettings {
ConfigVar<bool> midnasLamentNonStop;
// Input
ConfigVar<GyroMode> gyroMode;
ConfigVar<bool> enableGyroAim;
ConfigVar<bool> enableGyroRollgoal;
ConfigVar<float> gyroSensitivityX;
@@ -197,6 +198,11 @@ struct UserSettings {
ConfigVar<float> gyroDeadband;
ConfigVar<bool> gyroInvertPitch;
ConfigVar<bool> gyroInvertYaw;
ConfigVar<bool> enableMouseCamera;
ConfigVar<bool> enableMouseAim;
ConfigVar<float> mouseAimSensitivity;
ConfigVar<float> mouseCameraSensitivity;
ConfigVar<bool> invertMouseY;
ConfigVar<bool> freeCamera;
ConfigVar<bool> invertCameraXAxis;
ConfigVar<bool> invertCameraYAxis;
+1 -1
View File
@@ -44,7 +44,7 @@ struct mDoLib_clipper {
void mDoLib_project(Vec* src, Vec* dst);
u32 mDoLib_setResTimgObj(ResTIMG const* res, TGXTexObj* o_texObj, u32 tlut_name,
GXTlutObj* o_tlutObj);
TGXTlutObj* o_tlutObj);
void mDoLib_pos2camera(Vec* src, Vec* dst);
#if PLATFORM_WII
+41 -16
View File
@@ -952,45 +952,70 @@ if(DEFINED APPLE_TARGET_TRIPLE)
set(APPLE_TARGET_TRIPLE_FLAG "-target ${APPLE_TARGET_TRIPLE}")
endif()
function(ios_toolchain_set_cached_flags variable description)
set(clean_flags "${${variable}}")
foreach(toolchain_flag IN LISTS ARGN)
if(NOT "${toolchain_flag}" STREQUAL "")
string(REPLACE "${toolchain_flag}" "" clean_flags "${clean_flags}")
endif()
endforeach()
string(REGEX REPLACE "[ \t]+" " " clean_flags "${clean_flags}")
string(STRIP "${clean_flags}" clean_flags)
set(final_flags "")
foreach(toolchain_flag IN LISTS ARGN)
if(NOT "${toolchain_flag}" STREQUAL "")
string(APPEND final_flags " ${toolchain_flag}")
endif()
endforeach()
if(NOT "${clean_flags}" STREQUAL "")
string(APPEND final_flags " ${clean_flags}")
endif()
string(REGEX REPLACE "[ \t]+" " " final_flags "${final_flags}")
string(STRIP "${final_flags}" final_flags)
set(${variable} "${final_flags}" CACHE INTERNAL "${description}")
endfunction()
#Check if Xcode generator is used since that will handle these flags automagically
if(CMAKE_GENERATOR MATCHES "Xcode")
message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as the generator. Modifying the Xcode build-settings directly instead.")
else()
set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_C_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all C build types.")
ios_toolchain_set_cached_flags(CMAKE_C_FLAGS "Flags used by the compiler during all C build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${OBJC_LEGACY_VARS}" "${BITCODE}" "${VISIBILITY}")
set(CMAKE_C_FLAGS_DEBUG "-O0 -g ${CMAKE_C_FLAGS_DEBUG}")
set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_C_FLAGS_MINSIZEREL}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_C_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_CXX_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all CXX build types.")
ios_toolchain_set_cached_flags(CMAKE_CXX_FLAGS "Flags used by the compiler during all CXX build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${OBJC_LEGACY_VARS}" "${BITCODE}" "${VISIBILITY}")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g ${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_CXX_FLAGS_MINSIZEREL}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_CXX_FLAGS_RELEASE}")
if(NAMED_LANGUAGE_SUPPORT_INT)
set(CMAKE_OBJC_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJC_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all OBJC build types.")
ios_toolchain_set_cached_flags(CMAKE_OBJC_FLAGS "Flags used by the compiler during all OBJC build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${BITCODE}" "${VISIBILITY}" "${FOBJC_ARC}" "${OBJC_VARS}")
set(CMAKE_OBJC_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJC_FLAGS_DEBUG}")
set(CMAKE_OBJC_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJC_FLAGS_MINSIZEREL}")
set(CMAKE_OBJC_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJC_FLAGS_RELWITHDEBINFO}")
set(CMAKE_OBJC_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJC_FLAGS_RELEASE}")
set(CMAKE_OBJCXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJCXX_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all OBJCXX build types.")
ios_toolchain_set_cached_flags(CMAKE_OBJCXX_FLAGS "Flags used by the compiler during all OBJCXX build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${BITCODE}" "${VISIBILITY}" "${FOBJC_ARC}" "${OBJC_VARS}")
set(CMAKE_OBJCXX_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJCXX_FLAGS_DEBUG}")
set(CMAKE_OBJCXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJCXX_FLAGS_MINSIZEREL}")
set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_OBJCXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}")
endif()
set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all C link types.")
set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all CXX link types.")
ios_toolchain_set_cached_flags(CMAKE_C_LINK_FLAGS "Flags used by the compiler for all C link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
ios_toolchain_set_cached_flags(CMAKE_CXX_LINK_FLAGS "Flags used by the compiler for all CXX link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
if(NAMED_LANGUAGE_SUPPORT_INT)
set(CMAKE_OBJC_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJC_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all OBJC link types.")
set(CMAKE_OBJCXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJCXX_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all OBJCXX link types.")
ios_toolchain_set_cached_flags(CMAKE_OBJC_LINK_FLAGS "Flags used by the compiler for all OBJC link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
ios_toolchain_set_cached_flags(CMAKE_OBJCXX_LINK_FLAGS "Flags used by the compiler for all OBJCXX link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
endif()
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp" CACHE INTERNAL
"Flags used by the compiler for all ASM build types.")
@@ -1,6 +1,7 @@
#ifndef J3DSHAPEDRAW_H
#define J3DSHAPEDRAW_H
#include <gx.h>
#include <types.h>
/**
@@ -12,6 +13,9 @@ public:
u32 countVertex(u32);
void addTexMtxIndexInDL(u32, u32, u32);
J3DShapeDraw(u8 const*, u32);
#if TARGET_PC
J3DShapeDraw(u8 const*, u32, const GXVtxDescList*);
#endif
void draw() const;
virtual ~J3DShapeDraw();
@@ -3,6 +3,8 @@
#include "JSystem/J2DGraph/J2DGrafContext.h"
#include <gx.h>
#include <tracy/Tracy.hpp>
J2DGrafContext::J2DGrafContext(f32 x, f32 y, f32 width, f32 height)
: mBounds(x, y, x + width, y + height), mScissorBounds(x, y, x + width, y + height) {
if (x < 0.0f || y < 0.0f) {
@@ -137,6 +139,7 @@ void J2DGrafContext::setLineWidth(u8 lineWidth) {
}
void J2DGrafContext::fillBox(JGeometry::TBox2<f32> const& box) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mBoxPart.mType, (GXBlendFactor)mBoxPart.mSrcFactor,
(GXBlendFactor)mBoxPart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
@@ -155,6 +158,7 @@ void J2DGrafContext::fillBox(JGeometry::TBox2<f32> const& box) {
}
void J2DGrafContext::drawFrame(JGeometry::TBox2<f32> const& box) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mBoxPart.mType, (GXBlendFactor)mBoxPart.mSrcFactor,
(GXBlendFactor)mBoxPart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
@@ -175,6 +179,7 @@ void J2DGrafContext::drawFrame(JGeometry::TBox2<f32> const& box) {
}
void J2DGrafContext::line(JGeometry::TVec2<f32> start, JGeometry::TVec2<f32> end) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mLinePart.mType, (GXBlendFactor)mLinePart.mSrcFactor,
(GXBlendFactor)mLinePart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
+339 -4
View File
@@ -1,15 +1,310 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include <cstring>
#include <gx.h>
#include <stdint.h>
#include "JSystem/J3DGraphBase/J3DShapeDraw.h"
#include "JSystem/JKernel/JKRHeap.h"
#include <cstring>
#include <stdint.h>
#include <gx.h>
#if TARGET_PC
#include <algorithm>
#include <tracy/Tracy.hpp>
#include <vector>
#include "dusk/logging.h"
namespace {
u16 read_be16(const u8* data) {
return (u16(data[0]) << 8) | data[1];
}
void append_be16(std::vector<u8>& out, u16 value) {
out.push_back(value >> 8);
out.push_back(value & 0xFF);
}
void append_bytes(std::vector<u8>& out, const u8* data, u32 size) {
out.insert(out.end(), data, data + size);
}
bool is_matrix_idx_attr(GXAttr attr) {
return attr >= GX_VA_PNMTXIDX && attr <= GX_VA_TEX7MTXIDX;
}
bool is_draw_opcode(u8 opcode) {
return opcode == GX_QUADS || opcode == GX_TRIANGLES || opcode == GX_TRIANGLESTRIP ||
opcode == GX_TRIANGLEFAN || opcode == GX_LINES || opcode == GX_LINESTRIP ||
opcode == GX_POINTS;
}
bool is_mergeable_draw_opcode(u8 opcode) {
return opcode == GX_QUADS || opcode == GX_TRIANGLES || opcode == GX_TRIANGLESTRIP ||
opcode == GX_TRIANGLEFAN;
}
bool calc_vtx_stride(const GXVtxDescList* vtxDesc, u32& stride) {
stride = 0;
for (; vtxDesc->attr != GX_VA_NULL; vtxDesc++) {
switch (vtxDesc->type) {
case GX_NONE:
break;
case GX_DIRECT:
if (!is_matrix_idx_attr(vtxDesc->attr)) {
return false;
}
stride += 1;
break;
case GX_INDEX8:
stride += 1;
break;
case GX_INDEX16:
stride += 2;
break;
default:
return false;
}
}
return stride != 0;
}
bool get_command_size(const u8* dlStart, u32 dlSize, u32 offset, u32 stride, u32& cmdSize) {
if (offset >= dlSize) {
return false;
}
const u8 cmd = dlStart[offset];
const u8 opcode = cmd & GX_OPCODE_MASK;
switch (opcode) {
case GX_NOP:
case GX_CMD_INVL_VC:
cmdSize = 1;
return true;
case (GX_LOAD_BP_REG & GX_OPCODE_MASK):
cmdSize = 5;
return offset + cmdSize <= dlSize;
case GX_LOAD_CP_REG:
cmdSize = 6;
return offset + cmdSize <= dlSize;
case GX_LOAD_XF_REG: {
if (offset + 5 > dlSize) {
return false;
}
const u16 count = read_be16(dlStart + offset + 1) + 1;
cmdSize = 5 + count * 4;
return offset + cmdSize <= dlSize;
}
case GX_LOAD_INDX_A:
case GX_LOAD_INDX_B:
case GX_LOAD_INDX_C:
case GX_LOAD_INDX_D:
cmdSize = 5;
return offset + cmdSize <= dlSize;
case GX_CMD_CALL_DL:
cmdSize = 9;
return offset + cmdSize <= dlSize;
default:
if (is_draw_opcode(opcode)) {
if (offset + 3 > dlSize) {
return false;
}
const u16 vtxCount = read_be16(dlStart + offset + 1);
cmdSize = 3 + vtxCount * stride;
return offset + cmdSize <= dlSize;
}
return false;
}
}
struct MergeRun {
u8 cmd = 0;
u16 vtxCount = 0;
std::vector<u8> vertices;
};
void flush_merge_run(std::vector<u8>& out, MergeRun& run) {
if (run.vtxCount == 0) {
return;
}
out.push_back(run.cmd);
append_be16(out, run.vtxCount);
append_bytes(out, run.vertices.data(), run.vertices.size());
run.vertices.clear();
run.vtxCount = 0;
}
void append_vertex(std::vector<u8>& out, const u8* vertices, u32 stride, u16 idx) {
append_bytes(out, vertices + idx * stride, stride);
}
bool triangulate_draw(
std::vector<u8>& out, u8 opcode, const u8* vertices, u32 stride, u16 vtxCount) {
switch (opcode) {
case GX_TRIANGLES:
append_bytes(out, vertices, vtxCount * stride);
return true;
case GX_TRIANGLEFAN:
if (vtxCount < 3) {
return false;
}
for (u16 v = 2; v < vtxCount; v++) {
append_vertex(out, vertices, stride, 0);
append_vertex(out, vertices, stride, v - 1);
append_vertex(out, vertices, stride, v);
}
return true;
case GX_TRIANGLESTRIP:
if (vtxCount < 3) {
return false;
}
for (u16 v = 2; v < vtxCount; v++) {
if ((v & 1) == 0) {
append_vertex(out, vertices, stride, v - 2);
append_vertex(out, vertices, stride, v - 1);
} else {
append_vertex(out, vertices, stride, v - 1);
append_vertex(out, vertices, stride, v - 2);
}
append_vertex(out, vertices, stride, v);
}
return true;
case GX_QUADS:
if ((vtxCount & 3) != 0) {
return false;
}
for (u16 v = 0; v < vtxCount; v += 4) {
append_vertex(out, vertices, stride, v);
append_vertex(out, vertices, stride, v + 1);
append_vertex(out, vertices, stride, v + 2);
append_vertex(out, vertices, stride, v + 2);
append_vertex(out, vertices, stride, v + 3);
append_vertex(out, vertices, stride, v);
}
return true;
default:
return false;
}
}
void append_triangles_to_run(
std::vector<u8>& out, MergeRun& run, u8 cmd, const std::vector<u8>& vertices, u32 stride) {
u32 offset = 0;
u32 remaining = vertices.size() / stride;
while (remaining != 0) {
if (run.vtxCount != 0 && run.cmd != cmd) {
flush_merge_run(out, run);
}
if (run.vtxCount == 0) {
run.cmd = cmd;
}
u32 available = 0xFFFF - run.vtxCount;
if (available == 0) {
flush_merge_run(out, run);
continue;
}
u32 toCopy = std::min(remaining, available);
append_bytes(run.vertices, vertices.data() + offset * stride, toCopy * stride);
run.vtxCount += toCopy;
offset += toCopy;
remaining -= toCopy;
if (run.vtxCount == 0xFFFF) {
flush_merge_run(out, run);
}
}
}
bool optimize_display_list(const u8* dlStart, u32 dlSize, u32 stride, std::vector<u8>& out) {
MergeRun run;
out.reserve(dlSize);
for (u32 offset = 0; offset < dlSize;) {
u32 cmdSize = 0;
if (!get_command_size(dlStart, dlSize, offset, stride, cmdSize)) {
return false;
}
const u8 cmd = dlStart[offset];
const u8 opcode = cmd & GX_OPCODE_MASK;
if (opcode == GX_NOP) {
offset += cmdSize;
continue;
}
if (!is_draw_opcode(opcode)) {
flush_merge_run(out, run);
append_bytes(out, dlStart + offset, cmdSize);
offset += cmdSize;
continue;
}
if (!is_mergeable_draw_opcode(opcode)) {
flush_merge_run(out, run);
append_bytes(out, dlStart + offset, cmdSize);
offset += cmdSize;
continue;
}
const u16 vtxCount = read_be16(dlStart + offset + 1);
const u8* vertices = dlStart + offset + 3;
std::vector<u8> triangles;
if (!triangulate_draw(triangles, opcode, vertices, stride, vtxCount)) {
flush_merge_run(out, run);
append_bytes(out, dlStart + offset, cmdSize);
offset += cmdSize;
continue;
}
append_triangles_to_run(out, run, (GX_TRIANGLES | (cmd & GX_VAT_MASK)), triangles, stride);
offset += cmdSize;
}
flush_merge_run(out, run);
return true;
}
void set_display_list_copy(void*& displayList, u32& displayListSize, const u8* data, u32 size) {
const u32 alignedSize = ALIGN_NEXT(size, 0x20);
u8* newDL = JKR_NEW_ARRAY_ARGS(u8, alignedSize, 0x20);
if (size != 0) {
std::memcpy(newDL, data, size);
}
for (u32 i = size; i < alignedSize; i++) {
newDL[i] = 0;
}
displayList = newDL;
displayListSize = alignedSize;
DCStoreRange(newDL, displayListSize);
}
} // namespace
#endif
u32 J3DShapeDraw::countVertex(u32 stride) {
u32 count = 0;
u8* dlStart = (u8*)getDisplayList();
#if TARGET_PC
for (u32 offset = 0; offset < getDisplayListSize();) {
u8 cmd = dlStart[offset];
u8 opcode = cmd & GX_OPCODE_MASK;
u32 cmdSize = 0;
if (!get_command_size(dlStart, getDisplayListSize(), offset, stride, cmdSize)) {
break;
}
if (!is_draw_opcode(opcode)) {
offset += cmdSize;
continue;
}
int vtxNum = be16(*reinterpret_cast<u16*>(dlStart + offset + 1));
count += vtxNum;
offset += 3 + stride * vtxNum;
}
#else
for (u8* dl = dlStart; (dl - dlStart) < getDisplayListSize();) {
u8 cmd = *(u8*)dl;
dl++;
@@ -20,6 +315,7 @@ u32 J3DShapeDraw::countVertex(u32 stride) {
count += vtxNum;
dl = (u8*)dl + stride * vtxNum;
}
#endif
return count;
}
@@ -34,13 +330,32 @@ void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
u8* newDL = newDLStart;
for (; (oldDL - oldDLStart) < mDisplayListSize;) {
#if TARGET_PC
u32 oldOffset = oldDL - oldDLStart;
u32 cmdSize = 0;
if (!get_command_size(oldDLStart, mDisplayListSize, oldOffset, stride, cmdSize)) {
memcpy(newDL, oldDL, mDisplayListSize - oldOffset);
newDL += mDisplayListSize - oldOffset;
break;
}
#endif
// Copy command
u8 cmd = *(u8*)oldDL;
oldDL++;
*newDL++ = cmd;
#if TARGET_PC
u8 opcode = cmd & GX_OPCODE_MASK;
if (!is_draw_opcode(opcode)) {
memcpy(newDL, oldDL, cmdSize - 1);
oldDL += cmdSize - 1;
newDL += cmdSize - 1;
continue;
}
#else
if (cmd != GX_TRIANGLEFAN && cmd != GX_TRIANGLESTRIP)
break;
#endif
// Copy count
int vtxNum = *(u16*)oldDL;
@@ -71,11 +386,31 @@ void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
}
J3DShapeDraw::J3DShapeDraw(const u8* displayList, u32 displayListSize) {
#if TARGET_PC
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
#else
mDisplayList = (void*)displayList;
mDisplayListSize = displayListSize;
#endif
}
#if TARGET_PC
J3DShapeDraw::J3DShapeDraw(
const u8* displayList, u32 displayListSize, const GXVtxDescList* vtxDesc) {
u32 stride = 0;
std::vector<u8> optimized;
if (calc_vtx_stride(vtxDesc, stride) &&
optimize_display_list(displayList, displayListSize, stride, optimized))
{
set_display_list_copy(mDisplayList, mDisplayListSize, optimized.data(), optimized.size());
} else {
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
}
}
#endif
void J3DShapeDraw::draw() const {
ZoneScoped;
GXCallDisplayList(mDisplayList, mDisplayListSize);
}
@@ -132,7 +132,12 @@ J3DShapeDraw* J3DShapeFactory::newShapeDraw(int shapeNo, int mtxGroupNo) const {
const J3DShapeInitData& shapeInitData = mShapeInitData[mIndexTable[shapeNo]];
const J3DShapeDrawInitData& drawInitData =
(&mDrawInitData[shapeInitData.mDrawInitDataIndex])[mtxGroupNo];
#if TARGET_PC
shapeDraw = JKR_NEW J3DShapeDraw(&mDisplayListData[drawInitData.mDisplayListIndex], drawInitData.mDisplayListSize,
getVtxDescList(shapeNo));
#else
shapeDraw = JKR_NEW J3DShapeDraw(&mDisplayListData[drawInitData.mDisplayListIndex], drawInitData.mDisplayListSize);
#endif
J3D_ASSERT_ALLOCMEM(193, shapeDraw);
return shapeDraw;
}
@@ -154,7 +159,7 @@ s32 J3DShapeFactory::calcSize(int shapeNo, u32 flag) {
for (u32 i = 0; i < mtxGroupNo; i++) {
size += calcSizeShapeMtx(flag, shapeNo, i);
size += 0x0C;
size += sizeof(J3DShapeDraw);
}
return size;
+1 -2
View File
@@ -206,8 +206,7 @@ void JPABaseParticle::init_c(JPAEmitterWorkData* work, JPABaseParticle* parent)
#if TARGET_PC
void JPABaseParticle::interp(JPAEmitterWorkData* work, void const* drawFunc) {
static bool enable = false;
if (!enable)
if (!dusk::frame_interp::is_enabled())
return;
// don't interpolate the first frame
@@ -761,6 +761,15 @@ bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
}
}
#ifdef TARGET_PC
if (((pBsp && pBsp->getDirType() == 3) || (pCsp && pCsp->getDirType() == 3)) &&
dusk::frame_interp::is_enabled())
{
// ensure mGlobalEmtrDir is valid
calcWorkData_d(work);
}
#endif
JPANode<JPABaseParticle>* next = NULL;
for (JPANode<JPABaseParticle>* node = emtr->mAlivePtclBase.getFirst(); node != emtr->mAlivePtclBase.getEnd(); node = next) {
next = node->getNext();
+1
View File
@@ -249,6 +249,7 @@ f32 JUTResFont::drawChar_scale(f32 pos_x, f32 pos_y, f32 scale_x, f32 scale_y, i
f32 x2;
f32 y1;
ZoneScoped;
JUT_ASSERT(378, mValid);
JUTFont::TWidth width;
loadFont(str_int, GX_TEXMAP0, &width FONT_DRAW_CTX_ARG);
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>dev.twilitrealm.dusk</id>
<launchable type="desktop-id">dev.twilitrealm.dusk.desktop</launchable>
<name>Dusklight</name>
<summary>Native port of a classic adventure game</summary>
<developer id="dev.twilitrealm">
<name>Twilit Realm</name>
</developer>
<url type="homepage">https://twilitrealm.dev</url>
<url type="bugtracker">https://github.com/TwilitRealm/dusklight/issues</url>
<metadata_license>CC0-1.0</metadata_license>
<project_license>CC0-1.0</project_license>
<content_rating type="oars-1.0"/>
<supports>
<control>console</control>
<control>gamepad</control>
</supports>
<description>
<p>
Dusklight is a reverse-engineered reimplementation of a classic adventure game.
It aims to be as accurate as possible to the original while also providing new options, enhancements, and tools to customize your experience.
</p>
</description>
<provides>
<binary>dusklight</binary>
<id>dev.twilitrealm.dusk.desktop</id>
</provides>
<releases>
<release version="UNRELEASED" date="2026-12-31">
<description>
<p>Initial Flatpak release.</p>
</description>
</release>
</releases>
</component>
+1 -1
View File
@@ -144,7 +144,7 @@ void daAlink_c::handleQuickTransform() {
procCoMetamorphoseInit();
}
bool daAlink_c::checkGyroAimContext() {
bool daAlink_c::checkAimContext() {
switch (mProcID) {
case PROC_SUBJECTIVITY:
case PROC_SWIM_SUBJECTIVITY:
+16 -3
View File
@@ -2028,11 +2028,10 @@ void daAlink_blur_c::traceBlur(cXyz const* param_0, cXyz const* param_1, s16 par
}
void daAlink_blur_c::draw() {
ZoneScoped;
j3dSys.reinitGX();
#ifdef TARGET_PC
TGXTexObj texObj;
#else
#if !TARGET_PC
static TGXTexObj texObj;
#endif
static GXColor nColor0 = {0xFF, 0xFF, 0xFF, 0x14};
@@ -2040,11 +2039,25 @@ void daAlink_blur_c::draw() {
GXSetNumIndStages(0);
nColor0.a = field_0x20;
#if TARGET_PC
if (mpCachedBlurTex != m_blurTex) {
mBlurTexObj.reset();
GXInitTexObj(&mBlurTexObj,
reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(m_blurTex) + m_blurTex->imageOffset),
16, 4, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(
&mBlurTexObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
mpCachedBlurTex = m_blurTex;
}
GXLoadTexObj(&mBlurTexObj, GX_TEXMAP0);
#else
GXInitTexObj(&texObj, (void*)((uintptr_t)m_blurTex + m_blurTex->imageOffset), 16, 4, GX_TF_I4,
GX_CLAMP, GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(&texObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE,
GX_ANISO_1);
GXLoadTexObj(&texObj, GX_TEXMAP0);
#endif
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBA4, 8);
GXClearVtxDesc();
+31 -11
View File
@@ -11,8 +11,9 @@
#include "d/actor/d_a_tag_mhint.h"
#if TARGET_PC
#include "dusk/gyro.h"
#include "dusk/action_bindings.h"
#include "dusk/gyro.h"
#include "dusk/mouse.h"
#endif
bool daAlink_c::checkNoSubjectModeCamera() {
@@ -120,18 +121,28 @@ BOOL daAlink_c::setBodyAngleToCamera() {
var_f31 /= dComIfGp_getCameraZoomScale(field_0x317c);
}
shape_angle.y = shape_angle.y + (var_f31 * cM_ssin(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonXAxis ? -1.0f : 1.0f)));
sp8 = mBodyAngle.x + (var_f31 * cM_scos(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonYAxis ? -1.0f : 1.0f)));
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
#if TARGET_PC
if (dusk::getSettings().game.enableMouseAim && checkAimContext()) {
sp8 = mBodyAngle.x;
} else
#endif
{
shape_angle.y = shape_angle.y + (var_f31 * cM_ssin(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonXAxis ? -1.0f : 1.0f)));
sp8 = mBodyAngle.x + (var_f31 * cM_scos(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonYAxis ? -1.0f : 1.0f)));
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
}
} else {
sp8 = mBodyAngle.x;
}
#if TARGET_PC
if (dusk::getSettings().game.enableGyroAim && checkGyroAimContext()) {
if ((dusk::getSettings().game.enableGyroAim ||
dusk::getSettings().game.enableMouseAim) &&
checkAimContext())
{
f32 gyro_scale = 1.0f;
if (checkWolfEyeUp()) {
gyro_scale *= 0.6f;
@@ -141,12 +152,21 @@ BOOL daAlink_c::setBodyAngleToCamera() {
gyro_scale /= dComIfGp_getCameraZoomScale(field_0x317c);
}
f32 gy_yaw = 0.f;
f32 gy_pitch = 0.f;
dusk::gyro::getAimDeltas(gy_yaw, gy_pitch);
f32 final_yaw = 0.f;
f32 final_pitch = 0.f;
if (dusk::getSettings().game.enableMouseAim) {
dusk::mouse::getAimDeltas(final_yaw, final_pitch);
}
if (dusk::getSettings().game.enableGyroAim) {
f32 gyro_yaw = 0.f;
f32 gyro_pitch = 0.f;
dusk::gyro::getAimDeltas(gyro_yaw, gyro_pitch);
final_yaw += gyro_yaw;
final_pitch += gyro_pitch;
}
shape_angle.y = shape_angle.y + cM_rad2s(gy_yaw * gyro_scale);
sp8 = sp8 + cM_rad2s(gy_pitch * gyro_scale);
shape_angle.y = shape_angle.y + cM_rad2s(final_yaw * gyro_scale);
sp8 = sp8 + cM_rad2s(final_pitch * gyro_scale);
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
+27 -4
View File
@@ -305,6 +305,7 @@ static void mant_build_anchor_frame(const cXyz& anchor_a, const cXyz& anchor_b,
#endif
void daMant_packet_c::draw() {
ZoneScoped;
#if TARGET_PC
void* image = l_Egnd_mantTEX;
void* lut = l_Egnd_mantPAL;
@@ -418,15 +419,36 @@ void daMant_packet_c::draw() {
GXSetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K3_A);
GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
#if TARGET_PC
static bool textureObjsInitialized = false;
static TGXTlutObj tlutObj;
static TGXTexObj mainTexObj;
static TGXTexObj undersideTexObj;
if (!textureObjsInitialized) {
GXInitTlutObj(&tlutObj, lut, GX_TL_RGB5A3, 0x100);
GXInitTexObjCI(&mainTexObj, image, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&mainTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
GXInitTexObjCI(
&undersideTexObj, l_Egnd_mantTEX_U, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&undersideTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
textureObjsInitialized = true;
}
#else
GXTlutObj GStack_80;
GXInitTlutObj(&GStack_80, lut, GX_TL_RGB5A3, 0x100);
TGXTexObj GStack_74;
GXInitTexObjCI(&GStack_74, image, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&GStack_74, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
#endif
GXLoadTlut(&GStack_80, 0);
#if TARGET_PC
GXLoadTlut(&tlutObj, GX_TLUT0);
GXLoadTexObj(&mainTexObj, GX_TEXMAP0);
#else
GXLoadTlut(&GStack_80, GX_TLUT0);
GXLoadTexObj(&GStack_74, GX_TEXMAP0);
#endif
GXSetCullMode(GX_CULL_BACK);
@@ -442,12 +464,13 @@ void daMant_packet_c::draw() {
GXLoadNrmMtxImm(MStack_54, GX_PNMTX0);
GXCallDisplayList(l_Egnd_mantDL, 0x3e0);
#ifdef TARGET_PC
GStack_74.reset();
#endif
#if TARGET_PC
GXLoadTexObj(&undersideTexObj, GX_TEXMAP0);
#else
GXInitTexObjCI(&GStack_74, l_Egnd_mantTEX_U, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&GStack_74, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
GXLoadTexObj(&GStack_74, GX_TEXMAP0);
#endif
GXSetTevColor(GX_TEVREG0, COMPOUND_LITERAL(GXColor){0, 0, 0, 0});
GXSetTevKColor(GX_KCOLOR0, COMPOUND_LITERAL(GXColor){0, 0, 0, 0});
+17
View File
@@ -5755,6 +5755,12 @@ static void play_camera_u(dmg_rod_class* i_this) {
}
}
#if TARGET_PC
BOOL item_any_fishing_rod(int itemId) {
return itemId == dItemNo_FISHING_ROD_1_e || (itemId >= dItemNo_BEE_ROD_e && itemId <= dItemNo_JEWEL_WORM_ROD_e);
}
#endif
static int dmg_rod_Execute(dmg_rod_class* i_this) {
fopAc_ac_c* actor = &i_this->actor;
@@ -5821,6 +5827,17 @@ static int dmg_rod_Execute(dmg_rod_class* i_this) {
i_this->prev_rod_substick_y = i_this->rod_substick_y;
i_this->rod_substick_y = mDoCPd_c::getSubStickY(PAD_1);
#if TARGET_PC
if (dusk::getSettings().game.buttonFishing) {
if ((item_any_fishing_rod(dComIfGp_getSelectItem(0)) && mDoCPd_c::getHoldX(PAD_1)) ||
(item_any_fishing_rod(dComIfGp_getSelectItem(1)) && mDoCPd_c::getHoldY(PAD_1)))
{
i_this->rod_stick_y = -1.0f;
i_this->rod_substick_y = -1.0f;
}
}
#endif
i_this->reel_speed = 5.0f;
i_this->reel_btn_flags = mDoCPd_c::getHoldB(PAD_1) | mDoCPd_c::getHoldDown(PAD_1);
if (mDoCPd_c::getHoldDown(PAD_1)) {
+2
View File
@@ -105,6 +105,7 @@ int dMirror_packet_c::entryModel(J3DModel* i_model) {
void dMirror_packet_c::mirrorZdraw(f32* param_0, f32* param_1, f32 param_2, f32 param_3,
f32 param_4, f32 param_5, f32 param_6, f32 param_7) {
ZoneScoped;
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE);
GXSetNumTexGens(0);
@@ -265,6 +266,7 @@ void dMirror_packet_c::modelDraw(J3DModel* i_model, Mtx param_1) {
}
void dMirror_packet_c::mainDraw() {
ZoneScoped;
j3dSys.reinitGX();
cXyz sp19C[5];
+1 -1
View File
@@ -178,7 +178,7 @@ static void anm_init(npc_ks_class* i_this, int param_2, f32 i_morf, u8 i_attr, f
param_2 = 42;
} else {
// bug: developers meant to set equal to 44?
param_2 == 44;
IF_NOT_DUSK(param_2 == 44);
dComIfGs_shake_kandelaar();
}
}
+1
View File
@@ -261,6 +261,7 @@ void FlagCloth_c::execute() {
}
void FlagCloth_c::draw() {
ZoneScoped;
j3dSys.reinitGX();
GXSetNumIndStages(0);
dKy_setLight_again();
+1
View File
@@ -220,6 +220,7 @@ void FlagCloth2_c::initCcSphere(fopAc_ac_c*) {
}
inline void FlagCloth2_c::draw() {
ZoneScoped;
j3dSys.reinitGX();
GXSetNumIndStages(0);
dKy_setLight_again();
+17
View File
@@ -392,7 +392,10 @@ static const u8* l_sightDL_get() {
#endif
void daPy_sightPacket_c::draw() {
ZoneScoped;
#if !TARGET_PC
TGXTexObj texObj;
#endif
j3dSys.reinitGX();
GXSetNumIndStages(0);
@@ -407,10 +410,24 @@ void daPy_sightPacket_c::draw() {
GXSetTevColor(GX_TEVREG0, reg0);
GXSetTevColor(GX_TEVREG1, reg1);
#if TARGET_PC
if (mpCachedImg != mpImg) {
mTexObj.reset();
GXInitTexObj(&mTexObj, mpData, mpImg->width, mpImg->height,
static_cast<GXTexFmt>(mpImg->format), static_cast<GXTexWrapMode>(mpImg->wrapS),
static_cast<GXTexWrapMode>(mpImg->wrapT),
mpImg->mipmapCount > 1 ? GX_ENABLE : GX_DISABLE);
GXInitTexObjLOD(
&mTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, GX_FALSE, GX_FALSE, GX_ANISO_1);
mpCachedImg = mpImg;
}
GXLoadTexObj(&mTexObj, GX_TEXMAP0);
#else
GXInitTexObj(&texObj, mpData, mpImg->width, mpImg->height, (GXTexFmt)mpImg->format,
(GXTexWrapMode)mpImg->wrapS, (GXTexWrapMode)mpImg->wrapT, mpImg->mipmapCount > 1 ? GX_ENABLE : GX_DISABLE);
GXInitTexObjLOD(&texObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, GX_FALSE, GX_FALSE, GX_ANISO_1);
GXLoadTexObj(&texObj, GX_TEXMAP0);
#endif
GXLoadPosMtxImm(mProjMtx, GX_PNMTX0);
GXSetCurrentMtx(0);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
+1
View File
@@ -598,6 +598,7 @@ dFlower_packet_c::dFlower_packet_c() {
}
void dFlower_packet_c::draw() {
ZoneScoped;
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
j3dSys.reinitGX();
+1
View File
@@ -518,6 +518,7 @@ dGrass_packet_c::dGrass_packet_c() {
}
void dGrass_packet_c::draw() {
ZoneScoped;
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
cXyz spB4;
cXyz spA8;
+27 -2
View File
@@ -32,6 +32,8 @@
#include "dusk/frame_interpolation.h"
#include "dusk/logging.h"
#include "dusk/action_bindings.h"
#include "dusk/mouse.h"
#include "dusk/settings.h"
#include "imgui.h"
#endif
@@ -7638,12 +7640,16 @@ void dCamera_c::deactivateDebugFlyCam() {
mDebugFlyCam.initialized = false;
}
bool dCamera_c::canUseFreeCam() {
return dusk::getSettings().game.freeCamera || dusk::getSettings().game.enableMouseCamera;
}
bool dCamera_c::freeCamera() {
if (dusk::getSettings().game.freeCamera && mGear == 1) {
if (canUseFreeCam() && mGear == 1) {
mGear = 0;
}
if (!dusk::getSettings().game.freeCamera || mCamStyle == 70)
if (!canUseFreeCam() || mCamStyle == 70)
{
mCamParam.mManualMode = 0;
return false;
@@ -7669,6 +7675,17 @@ bool dCamera_c::freeCamera() {
mCamParam.freeYAngle += camMovement.y * magnitude * dusk::getSettings().game.freeCameraYSensitivity * 5.0f;
}
f32 yaw_rad = 0.0f;
f32 pitch_rad = 0.0f;
dusk::mouse::getCameraDeltas(yaw_rad, pitch_rad);
if (dusk::getSettings().game.enableMouseCamera && (yaw_rad != 0.0f || pitch_rad != 0.0f) &&
!dComIfGp_checkCameraAttentionStatus(dComIfGp_getPlayerCameraID(0), 0x8))
{
mCamParam.mManualMode = 1;
mCamParam.freeXAngle += MTXRadToDeg(yaw_rad);
mCamParam.freeYAngle += -MTXRadToDeg(pitch_rad);
}
fopAc_ac_c* player = dComIfGp_getPlayer(0);
if (!mCamParam.mManualMode || player == nullptr) {
return false;
@@ -9350,6 +9367,10 @@ bool dCamera_c::rideCamera(s32 param_0) {
mStyleSettle.mFinished = true;
}
#if TARGET_PC
freeCamera();
#endif
return true;
}
@@ -9479,6 +9500,10 @@ bool dCamera_c::rideCamera(s32 param_0) {
setFlag(0x400);
}
#if TARGET_PC
freeCamera();
#endif
return true;
}
+17 -6
View File
@@ -41,12 +41,12 @@ public:
/* 0x14 */ GXColor field_0x14;
/* 0x18 */ GXColor field_0x18;
/* 0x1C */ TGXTexObj field_0x1c;
/* 0x3C */ GXTlutObj field_0x3c;
/* 0x3C */ TGXTlutObj field_0x3c;
/* 0x48 */ s16 field_0x48;
/* 0x4A */ s16 field_0x4a;
/* 0x4C */ u8 field_0x4c;
/* 0x50 */ TGXTexObj field_0x50;
/* 0x70 */ GXTlutObj field_0x70;
/* 0x70 */ TGXTlutObj field_0x70;
/* 0x7C */ s16 field_0x7c;
/* 0x7E */ s16 field_0x7e;
/* 0x80 */ u8 field_0x80;
@@ -100,7 +100,7 @@ public:
u8 check() { return field_0x0; }
int getCI() { return mCI; }
TGXTexObj* getTexObj() { return &mTexObj; }
GXTlutObj* getTlutObj() { return &mTlutObj; }
TGXTlutObj* getTlutObj() { return &mTlutObj; }
GXColor* getColor() { return &mColor; }
f32 getS() { return mS; }
f32 getT() { return mT; }
@@ -110,7 +110,7 @@ public:
/* 0x00 */ u8 field_0x0;
/* 0x01 */ u8 mCI;
/* 0x04 */ TGXTexObj mTexObj;
/* 0x24 */ GXTlutObj mTlutObj;
/* 0x24 */ TGXTlutObj mTlutObj;
/* 0x30 */ GXColor mColor;
/* 0x34 */ f32 mS;
/* 0x38 */ f32 mT;
@@ -188,6 +188,7 @@ void dDlst_window_c::setScissor(f32 xOrig, f32 yOrig, f32 width, f32 height) {
}
void dDlst_2DTri_c::draw() {
ZoneScoped;
f32 f4;
f32 f5;
f32 f2 = cM_scos(field_0xc);
@@ -224,6 +225,7 @@ void dDlst_2DTri_c::draw() {
}
void dDlst_2DQuad_c::draw() {
ZoneScoped;
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
@@ -247,6 +249,7 @@ void dDlst_2DQuad_c::draw() {
}
void dDlst_2DPoint_c::draw() {
ZoneScoped;
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
@@ -268,6 +271,7 @@ void dDlst_2DPoint_c::draw() {
}
void dDlst_2DT_c::draw() {
ZoneScoped;
static GXColor l_color = {0xFF, 0xFF, 0xFF, 0xE0};
f32 var5 = field_0xe;
f32 var6 = field_0x10;
@@ -326,6 +330,7 @@ void dDlst_2DT_c::draw() {
}
void dDlst_2DT2_c::draw() {
ZoneScoped;
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBA6, 0);
GXClearVtxDesc();
@@ -665,6 +670,7 @@ void dDlst_2DT2_c::init(ResTIMG* i_timg, f32 param_1, f32 param_2, f32 param_3,
}
void dDlst_2DM_c::draw() {
ZoneScoped;
s16 r31 = field_0x22;
s16 r30 = field_0x24;
int r29 = field_0x22 + 256.0f;
@@ -728,6 +734,7 @@ void dDlst_2DM_c::draw() {
void dDlst_2Dm_c::draw() {
ZoneScoped;
s16 r31 = field_0x48;
s16 r30 = field_0x4a;
int r29 = field_0x48 + 256.0f;
@@ -794,6 +801,7 @@ void dDlst_2Dm_c::draw() {
void dDlst_2DMt_c::draw() {
ZoneScoped;
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
@@ -933,6 +941,7 @@ f32 cM_rnd_c::getValue(f32 param_0, f32 param_1) {
}
void dDlst_effectLine_c::draw() {
ZoneScoped;
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
@@ -1034,6 +1043,7 @@ void dDlst_shadowPoly_c::draw() {
return;
#endif
ZoneScoped;
dDlst_shadowTri_c* tri = getTri();
GXBegin(GX_TRIANGLES, GX_VTXFMT0, mCount * 3);
@@ -1610,6 +1620,7 @@ void dDlst_shadowControl_c::imageDraw(Mtx param_0) {
}
void dDlst_shadowControl_c::draw(Mtx param_0) {
ZoneScoped;
static GXTevColorChan l_tevColorChan[4] = {
GX_CH_RED,
GX_CH_GREEN,
@@ -1985,7 +1996,7 @@ int dDlst_list_c::set(dDlst_base_c**& p_start, dDlst_base_c**& p_end, dDlst_base
return 1;
}
#if TARGET_PC && (TRACY_ENABLE || PARTIAL_DEBUG)
#if DUSK_GFX_DEBUG_GROUPS
static absl::flat_hash_map<std::type_index, const char*> typeDrawNames;
static const char* getTypeDrawName(dDlst_base_c* dlst) {
@@ -2008,7 +2019,7 @@ void dDlst_list_c::draw(dDlst_base_c** p_start, dDlst_base_c** p_end) {
for (; p_start < p_end; p_start++) {
dDlst_base_c* dlst = *p_start;
#if TARGET_PC && (TRACY_ENABLE || PARTIAL_DEBUG)
#if DUSK_GFX_DEBUG_GROUPS
const auto name = getTypeDrawName(dlst);
GXScopedDebugGroup scope(name);
#endif
+246 -31
View File
@@ -94,6 +94,39 @@ static void dKyr_set_btitex(TGXTexObj* i_obj, ResTIMG* i_img) {
dKyr_set_btitex_common(i_obj, i_img, GX_TEXMAP0);
}
#if TARGET_PC
template <int N>
struct CachedTexObjs {
TGXTexObj texObj[N];
ResTIMG* timg[N] = {};
};
template <int N>
static GXTexObj* load_cached_tex(CachedTexObjs<N>& cache, ResTIMG* img, GXTexMapID mapID) {
for (int i = 0; i < N; i++) {
if (img != nullptr && cache.timg[i] == img) {
GXLoadTexObj(&cache.texObj[i], mapID);
return &cache.texObj[i];
}
}
int slot = 0;
for (int i = 0; i < N; i++) {
if (cache.timg[i] == nullptr) {
slot = i;
break;
}
}
if (cache.timg[slot] != nullptr) {
cache.texObj[slot].reset();
}
cache.timg[slot] = img;
dKyr_set_btitex_common(&cache.texObj[slot], img, mapID);
return &cache.texObj[slot];
}
#endif
void dKyr_lenzflare_move() {
dKankyo_sun_Packet* sun_packet = g_env_light.mpSunPacket;
dKankyo_sunlenz_Packet* lenz_packet = g_env_light.mpSunLenzPacket;
@@ -929,7 +962,7 @@ void dKyr_housi_move() {
if (g_env_light.mHousiCount != 0 ||
(g_env_light.mHousiCount == 0 && housi_packet->field_0x5de8 <= 0.0f))
{
housi_packet->field_0x5dec = g_env_light.mHousiCount;
housi_packet->mHousiCount = g_env_light.mHousiCount;
}
if (g_env_light.mHousiCount != 0) {
@@ -938,7 +971,7 @@ void dKyr_housi_move() {
cLib_addCalc(&housi_packet->field_0x5de8, 0.0f, 0.2f, 0.05f, 0.01f);
}
if (housi_packet->field_0x5dec == 0) {
if (housi_packet->mHousiCount == 0) {
return;
}
@@ -977,7 +1010,7 @@ void dKyr_housi_move() {
}
}
for (int i = housi_packet->field_0x5dec - 1; i >= 0; i--) {
for (int i = housi_packet->mHousiCount - 1; i >= 0; i--) {
f32 var_f26 = 0.4f * housi_packet->field_0x5de8;
effect = &housi_packet->mHousiEff[i];
@@ -2025,16 +2058,27 @@ void vrkumo_move() {
}
}
static void dKr_cullVtx_Set() {
static void dKr_cullVtx_Set(IF_DUSK(bool const vtxColor = false)) {
GXSetCullMode(GX_CULL_NONE);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBA4, 8);
#if TARGET_PC
if (vtxColor) {
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
}
#endif
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
#if TARGET_PC
if (vtxColor) {
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
}
#endif
}
static void dKyr_draw_rev_moon(Mtx drawMtx, u8** tex) {
ZoneScoped;
dKankyo_sun_Packet* sun_packet = g_env_light.mpSunPacket;
dKankyo_sunlenz_Packet* lenz_packet = g_env_light.mpSunLenzPacket;
camera_class* camera = (camera_class*)dComIfGp_getCamera(0);
@@ -2122,10 +2166,17 @@ static void dKyr_draw_rev_moon(Mtx drawMtx, u8** tex) {
return;
}
#if TARGET_PC
static CachedTexObjs<8> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
load_cached_tex(texobj, (ResTIMG*)tex[1], GX_TEXMAP1);
load_cached_tex(texobj, (ResTIMG*)tex[texidx + 2], GX_TEXMAP2);
#else
TGXTexObj texobj;
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[1], GX_TEXMAP1);
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[texidx + 2], GX_TEXMAP2);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
@@ -2205,7 +2256,11 @@ static void dKyr_draw_rev_moon(Mtx drawMtx, u8** tex) {
for (int i = 0; i < 2; i++) {
if (i == 1) {
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)lenz_packet->mpResBall, GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)lenz_packet->mpResBall);
#endif
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
@@ -2470,10 +2525,17 @@ void dKyr_drawSun(Mtx drawMtx, cXyz* ppos, GXColor& unused, u8** tex) {
return;
}
#if TARGET_PC
static CachedTexObjs<8> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
load_cached_tex(texobj, (ResTIMG*)tex[1], GX_TEXMAP1);
load_cached_tex(texobj, (ResTIMG*)tex[texidx + 2], GX_TEXMAP2);
#else
TGXTexObj texobj;
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[1], GX_TEXMAP1);
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[texidx + 2], GX_TEXMAP2);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
@@ -2567,7 +2629,11 @@ void dKyr_drawSun(Mtx drawMtx, cXyz* ppos, GXColor& unused, u8** tex) {
for (int i = 0; i < 2; i++) {
if (i == 1) {
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)lenz_packet->mpResBall, GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)lenz_packet->mpResBall);
#endif
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
@@ -2680,6 +2746,7 @@ void dKyr_drawSun(Mtx drawMtx, cXyz* ppos, GXColor& unused, u8** tex) {
}
void dKyr_drawLenzflare(Mtx drawMtx, cXyz* ppos, GXColor& param_2, u8** tex) {
ZoneScoped;
dKankyo_sunlenz_Packet* lenz_packet = g_env_light.mpSunLenzPacket;
dKankyo_sun_Packet* sun_packet = g_env_light.mpSunPacket;
camera_class* camera = (camera_class*)dComIfGp_getCamera(0);
@@ -2730,8 +2797,13 @@ void dKyr_drawLenzflare(Mtx drawMtx, cXyz* ppos, GXColor& param_2, u8** tex) {
j3dSys.reinitGX();
#if TARGET_PC
static CachedTexObjs<3> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
GXSetTevColor(GX_TEVREG1, color_reg1);
@@ -3036,11 +3108,23 @@ void dKyr_drawLenzflare(Mtx drawMtx, cXyz* ppos, GXColor& param_2, u8** tex) {
}
if (i == 1) {
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)tex[2], GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)tex[2]);
#endif
} else if (i == 2) {
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)tex[3], GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)tex[3]);
#endif
} else {
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
}
spE4.x = -var_f31;
@@ -3131,8 +3215,13 @@ void dKyr_drawRain(Mtx drawMtx, u8** tex) {
return;
}
#if TARGET_PC
static CachedTexObjs<1> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
GXSetNumTexGens(1);
@@ -3296,8 +3385,13 @@ void dKyr_drawSibuki(Mtx drawMtx, u8** tex) {
color.b = 0xC8;
color.a = rain_packet->mSibukiAlpha * alphaFade;
#if TARGET_PC
static CachedTexObjs<1> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[1], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[1]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color);
GXSetTevColor(GX_TEVREG1, color);
@@ -3378,21 +3472,26 @@ void dKyr_drawSibuki(Mtx drawMtx, u8** tex) {
}
void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
ZoneScoped;
dKankyo_housi_Packet* housi_packet = g_env_light.mpHousiPacket;
static f32 rot = 0.0f;
Mtx camMtx;
Mtx rotMtx;
cXyz pos[4];
#if TARGET_PC
static CachedTexObjs<1> texobj;
#else
TGXTexObj spDC;
#endif
cXyz spD0;
Vec spC4;
Vec spB8;
bool var_r28 = 0;
if (housi_packet->field_0x5dec != 0) {
bool isPalaceOfTwilight = 0;
if (housi_packet->mHousiCount != 0) {
if (strcmp(dComIfGp_getStartStageName(), "D_MN08") == 0) {
var_r28 = 1;
isPalaceOfTwilight = 1;
}
if (strcmp(dComIfGp_getStartStageName(), "D_MN08") != 0 ||
@@ -3419,7 +3518,7 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
color_reg1.b = 0xCA;
color_reg1.a = 0xFF;
if (dKy_darkworld_check() == 1 || var_r28 == 1) {
if (dKy_darkworld_check() == 1 || isPalaceOfTwilight == 1) {
color_reg0.r = 0;
color_reg0.g = 0;
color_reg0.b = 0;
@@ -3471,18 +3570,27 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
f32 temp_f24 = 6.5f;
for (int i = 0; i < 1; i++) {
dKyr_set_btitex(&spDC, (ResTIMG*)*tex);
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)*tex, GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)*tex);
#endif
#if TARGET_PC
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0, GX_DISABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE);
#else
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
#endif
GXSetTevColor(GX_TEVREG1, color_reg1);
GXSetNumTexGens(1);
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
GXSetNumTevStages(1);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C1, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, DUSK_IF_ELSE(GX_COLOR0A0, GX_COLOR_NULL));
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C1, DUSK_IF_ELSE(GX_CC_RASC, GX_CC_C0), GX_CC_TEXC, GX_CC_ZERO);
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE,
GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, DUSK_IF_ELSE(GX_CA_RASA, GX_CA_CA), GX_CA_TEXA, GX_CA_ZERO);
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE,
GX_TEVPREV);
@@ -3505,7 +3613,7 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
GXSetClipMode(GX_CLIP_DISABLE);
GXSetNumIndStages(0);
dKr_cullVtx_Set();
dKr_cullVtx_Set(IF_DUSK(true));
rot += 1.2f;
MTXRotRad(rotMtx, 'Z', DEG_TO_RAD(rot));
@@ -3514,7 +3622,13 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
GXLoadPosMtxImm(drawMtx, GX_PNMTX0);
GXSetCurrentMtx(GX_PNMTX0);
for (int j = 0; j < housi_packet->field_0x5dec; j++) {
#if TARGET_PC
// Dusklight optimization: we submit a single large draw call, rather than hundreds.
u32 vertCount = 4 * housi_packet->mHousiCount;
GXBegin(GX_QUADS, GX_VTXFMT0, vertCount);
#endif
for (int j = 0; j < housi_packet->mHousiCount; j++) {
fopAc_ac_c* player = dComIfGp_getPlayer(0);
spD0.x =
@@ -3525,6 +3639,10 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
housi_packet->mHousiEff[j].mBasePos.z + housi_packet->mHousiEff[j].mPosition.z;
if (i == 1 && j == 0) {
#if TARGET_PC
// Never gets hit I think?
abort();
#endif
color_reg0.r = 0;
color_reg0.g = 0;
color_reg0.b = 0;
@@ -3553,8 +3671,10 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
color_reg0.a = housi_packet->mHousiEff[j].mAlpha * var_f25;
block_14:
GXLoadTexObj(&spDC, GX_TEXMAP0);
#if !TARGET_PC // GXLoadTextObj does nothing, TEV colors replaced with vertex colors
GXLoadTexObj(&texobj, GX_TEXMAP0);
GXSetTevColor(GX_TEVREG0, color_reg0);
#endif
f32 var_f27 = housi_packet->mHousiEff[j].field_0x48 * 9.0f;
if (g_env_light.field_0xea9 == 1) {
@@ -3566,7 +3686,7 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
f32 temp_f30 =
(var_f27 * 0.2f) * cM_fcos(housi_packet->mHousiEff[j].mScale.y * 6.0f);
if (dKy_darkworld_check() == 1 || var_r28 == 1) {
if (dKy_darkworld_check() == 1 || isPalaceOfTwilight == 1) {
cXyz sp7C[] = {
cXyz(-1.0f, -0.5f, 0.0f),
cXyz(-1.0f, 1.5f, 0.0f),
@@ -3711,24 +3831,34 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
pos[3].z = spD0.z + spB8.z;
}
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
IF_NOT_DUSK(GXBegin(GX_QUADS, GX_VTXFMT0, 4));
s16 var_r17 = 0x1FF;
if (dKy_darkworld_check() == true || var_r28 == 1) {
if (dKy_darkworld_check() == true || isPalaceOfTwilight == 1) {
var_r17 = 0xFA;
}
GXPosition3f32(pos[0].x, pos[0].y, pos[0].z);
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0, 0);
GXPosition3f32(pos[1].x, pos[1].y, pos[1].z);
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(var_r17, 0);
GXPosition3f32(pos[2].x, pos[2].y, pos[2].z);
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(var_r17, var_r17);
GXPosition3f32(pos[3].x, pos[3].y, pos[3].z);
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0, var_r17);
GXEnd();
IF_NOT_DUSK(GXEnd());
}
}
#if TARGET_PC
GXEnd();
#endif
}
GXSetClipMode(GX_CLIP_ENABLE);
@@ -3738,6 +3868,7 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
}
void dKyr_drawSnow(Mtx drawMtx, u8** tex) {
ZoneScoped;
camera_class* camera = (camera_class*)dComIfGp_getCamera(0);
dKankyo_snow_Packet* snow_packet = g_env_light.mpSnowPacket;
@@ -3801,25 +3932,37 @@ void dKyr_drawSnow(Mtx drawMtx, u8** tex) {
}
if (tex[0] != NULL) {
TGXTexObj spA0;
dKyr_set_btitex(&spA0, (ResTIMG*)tex[0]);
#if TARGET_PC
static CachedTexObjs<1> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
#if TARGET_PC
// Dusklight optimization: enable draw call merging
// by using vertex color instead of GX_TEVREG0
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0, GX_DISABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE);
#else
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
#endif
GXSetTevColor(GX_TEVREG1, color_reg1);
GXSetNumTexGens(1);
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
GXSetNumTevStages(1);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C1, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, DUSK_IF_ELSE(GX_COLOR0A0, GX_COLOR_NULL));
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C1, DUSK_IF_ELSE(GX_CC_RASC, GX_CC_C0), GX_CC_TEXC, GX_CC_ZERO);
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, DUSK_IF_ELSE(GX_CA_RASA, GX_CA_CA), GX_CA_TEXA, GX_CA_ZERO);
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_COPY);
GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_DISABLE);
GXSetClipMode(GX_CLIP_DISABLE);
GXSetNumIndStages(0);
dKr_cullVtx_Set();
dKr_cullVtx_Set(IF_DUSK(true));
Mtx rotMtx;
MTXRotRad(rotMtx, 'Z', DEG_TO_RAD(rot));
@@ -3896,7 +4039,7 @@ void dKyr_drawSnow(Mtx drawMtx, u8** tex) {
}
}
GXSetTevColor(GX_TEVREG0, color_reg0);
IF_NOT_DUSK(GXSetTevColor(GX_TEVREG0, color_reg0));
f32 sp38 = 2.0f * (i / 500.0f) * snow_packet->field_0x6d80;
f32 sp68 = sp50 * (camera->view.lookat.eye.abs(sp7C) / 1000.0f);
if (sp68 > 1.0f) {
@@ -3944,19 +4087,23 @@ void dKyr_drawSnow(Mtx drawMtx, u8** tex) {
for (int k = 0; k < spC; k++) {
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
GXPosition3f32(pos[0].x + (temp_f31 * add_table[k].x), pos[0].y + (temp_f31 * add_table[k].y), pos[0].z + (temp_f31 * add_table[k].z));
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0, 0);
GXPosition3f32(pos[1].x + (temp_f31 * add_table[k].x), pos[1].y + (temp_f31 * add_table[k].y), pos[1].z + (temp_f31 * add_table[k].z));
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0xFF, 0);
GXPosition3f32(pos[2].x + (temp_f31 * add_table[k].x), pos[2].y + (temp_f31 * add_table[k].y), pos[2].z + (temp_f31 * add_table[k].z));
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0xFF, 0xFF);
GXPosition3f32(pos[3].x + (temp_f31 * add_table[k].x), pos[3].y + (temp_f31 * add_table[k].y), pos[3].z + (temp_f31 * add_table[k].z));
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0, 0xFF);
GXEnd();
}
if ((g_env_light.field_0xe90 != 0 && dComIfGp_roomControl_getStayNo() == 0 && sp7C.z < 3000.0f) || dComIfGp_roomControl_getStayNo() == 3 || dComIfGp_roomControl_getStayNo() == 6 || dComIfGp_roomControl_getStayNo() == 9 || dComIfGp_roomControl_getStayNo() == 13) {
color_reg0.a = 255.0f * ((0.4f * snow_packet->mSnowEff[i].field_0x30) + temp_f29);
GXSetTevColor(GX_TEVREG0, color_reg0);
IF_NOT_DUSK(GXSetTevColor(GX_TEVREG0, color_reg0));
f32 sp34;
f32 sp30;
@@ -4012,12 +4159,16 @@ void dKyr_drawSnow(Mtx drawMtx, u8** tex) {
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
int var_r27 = 0;
GXPosition3f32(pos[0].x + (temp_f31 * add_table[var_r27].x), pos[0].y + (temp_f31 * add_table[var_r27].y), pos[0].z + (temp_f31 * add_table[var_r27].z));
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0, 0);
GXPosition3f32(pos[1].x + (temp_f31 * add_table[var_r27].x), pos[1].y + (temp_f31 * add_table[var_r27].y), pos[1].z + (temp_f31 * add_table[var_r27].z));
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0xFF, 0);
GXPosition3f32(pos[2].x + (temp_f31 * add_table[var_r27].x), pos[2].y + (temp_f31 * add_table[var_r27].y), pos[2].z + (temp_f31 * add_table[var_r27].z));
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0xFF, 0xFF);
GXPosition3f32(pos[3].x + (temp_f31 * add_table[var_r27].x), pos[3].y + (temp_f31 * add_table[var_r27].y), pos[3].z + (temp_f31 * add_table[var_r27].z));
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0, 0xFF);
GXEnd();
}
@@ -4353,6 +4504,7 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) {
}
void drawCloudShadow(Mtx drawMtx, u8** tex) {
ZoneScoped;
dScnKy_env_light_c* envlight = dKy_getEnvlight();
dKankyo_cloud_Packet* cloud_packet = g_env_light.mpCloudPacket;
camera_class* camera = (camera_class*)dComIfGp_getCamera(0);
@@ -4388,7 +4540,12 @@ void drawCloudShadow(Mtx drawMtx, u8** tex) {
GXSetClipMode(GX_CLIP_DISABLE);
#if TARGET_PC
static CachedTexObjs<1> texobj;
TGXTexObj fb_texobj;
#else
TGXTexObj texobj, fb_texobj;
#endif
if (g_env_light.mMoyaMode < 50) {
dKy_ParticleColor_get_bg(&camera->view.lookat.eye, NULL, &sp48, &sp44, &sp40, &sp3C, 0.0f);
f32 temp_f30 = 0.4f;
@@ -4401,7 +4558,11 @@ void drawCloudShadow(Mtx drawMtx, u8** tex) {
color_reg1.g = (0.45f * sp38.g) + (0.55f * sp44.g);
color_reg1.b = (0.45f * sp38.b) + (0.55f * sp44.b);
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
GXSetTevColor(GX_TEVREG1, color_reg1);
@@ -4446,7 +4607,11 @@ void drawCloudShadow(Mtx drawMtx, u8** tex) {
color_reg1.b = 0;
color_reg1.a = 0xFF;
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP1);
#else
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[0], GX_TEXMAP1);
#endif
ResTIMG* fb_timg = mDoGph_gInf_c::getFrameBufferTimg();
dDlst_window_c* window = dComIfGp_getWindow(0);
@@ -4593,7 +4758,11 @@ void drawVrkumo(Mtx drawMtx, GXColor& color, u8** tex) {
Mtx camMtx;
Mtx rotMtx;
#if TARGET_PC
static CachedTexObjs<3> texobj;
#else
TGXTexObj texobj;
#endif
cXyz proj;
f32 rot;
@@ -4703,7 +4872,11 @@ void drawVrkumo(Mtx drawMtx, GXColor& color, u8** tex) {
color_reg1.r = 0;
color_reg1.g = 0;
color_reg1.b = 0;
#if TARGET_PC
auto* loaded_texobj = load_cached_tex(texobj, (ResTIMG*)tex[j], GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)tex[j]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color);
@@ -4808,7 +4981,11 @@ void drawVrkumo(Mtx drawMtx, GXColor& color, u8** tex) {
}
if (!(vrkumo_packet->mVrkumoEff[k].mAlpha <= 0.000001f)) {
#if TARGET_PC
GXLoadTexObj(loaded_texobj, GX_TEXMAP0);
#else
GXLoadTexObj(&texobj, GX_TEXMAP0);
#endif
GXSetTevColor(GX_TEVREG0, color);
sp60 = sp68 * (0.2f + (0.2f * (k / 100.0f)));
@@ -5341,6 +5518,7 @@ void dKyr_odour_move() {
}
void dKyr_odour_draw(Mtx drawMtx, u8** tex) {
ZoneScoped;
dScnKy_env_light_c* envlight = dKy_getEnvlight();
dKankyo_odour_Packet* odour_packet = envlight->mOdourData.mpOdourPacket;
camera_class* camera = (camera_class*)dComIfGp_getCamera(0);
@@ -5429,8 +5607,14 @@ void dKyr_odour_draw(Mtx drawMtx, u8** tex) {
break;
}
#if TARGET_PC
static CachedTexObjs<1> texobj;
TGXTexObj fb_texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP1);
#else
TGXTexObj texobj, fb_texobj;
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[0], GX_TEXMAP1);
#endif
ResTIMG* fb_timg = mDoGph_gInf_c::getFrameBufferTimg();
dDlst_window_c* window = dComIfGp_getWindow(0);
@@ -5445,18 +5629,23 @@ void dKyr_odour_draw(Mtx drawMtx, u8** tex) {
MTXRotRad(rotMtx, 'Z', DEG_TO_RAD(rot));
MTXConcat(camMtx, rotMtx, camMtx);
// Dusklight opt: enable draw call merging
// by using vertex color instead of GX_TEVREG0
GXLoadPosMtxImm(drawMtx, GX_PNMTX0);
GXSetCurrentMtx(GX_PNMTX0);
GXLoadTexMtxImm(spF0, GX_TEXMTX0, GX_MTX3x4);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBA4, 8);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX1, GX_CLR_RGBA, GX_RGBA4, 8);
IF_DUSK(GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0));
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX1, GX_DIRECT);
IF_DUSK(GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT));
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE);
GXSetChanCtrl(GX_COLOR0, GX_DISABLE, GX_SRC_REG, DUSK_IF_ELSE(GX_SRC_VTX, GX_SRC_REG), GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE);
GXSetTevColor(GX_TEVREG0, color_reg0);
GXSetTevColor(GX_TEVREG1, color_reg1);
GXSetNumTexGens(2);
@@ -5464,14 +5653,14 @@ void dKyr_odour_draw(Mtx drawMtx, u8** tex) {
GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY);
GXSetNumTevStages(2);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_C0, GX_CC_C1);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, DUSK_IF_ELSE(GX_CC_RASC, GX_CC_C0), GX_CC_C1);
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_TEXA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0);
GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_CPREV, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO);
GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_FALSE, GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, DUSK_IF_ELSE(GX_CA_RASA, GX_CA_A0), GX_CA_TEXA, GX_CA_ZERO);
GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_FALSE, GX_TEVPREV);
GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_COPY);
GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0);
@@ -5513,7 +5702,7 @@ void dKyr_odour_draw(Mtx drawMtx, u8** tex) {
if (effect->mStatus != 0) {
if (!(temp_f29 <= 0.000001f)) {
color_reg0.a = 255.0f * temp_f29;
GXSetTevColor(GX_TEVREG0, color_reg0);
IF_NOT_DUSK(GXSetTevColor(GX_TEVREG0, color_reg0));
sp70 = sp4C;
@@ -5551,15 +5740,19 @@ void dKyr_odour_draw(Mtx drawMtx, u8** tex) {
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
GXPosition3f32(pos[0].x, pos[0].y, pos[0].z);
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0, 0);
GXTexCoord2s16(0, 0);
GXPosition3f32(pos[1].x, pos[1].y, pos[1].z);
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0xFF, 0);
GXTexCoord2s16(0xFF, 0);
GXPosition3f32(pos[2].x, pos[2].y, pos[2].z);
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0xFF, 0xFF);
GXTexCoord2s16(0xFF, 0xFF);
GXPosition3f32(pos[3].x, pos[3].y, pos[3].z);
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
GXTexCoord2s16(0, 0xFF);
GXTexCoord2s16(0, 0xFF);
GXEnd();
@@ -5730,6 +5923,7 @@ void dKyr_mud_move() {
}
void dKyr_mud_draw(Mtx drawMtx, u8** tex) {
ZoneScoped;
dKankyo_mud_Packet* mud_packet = g_env_light.mpMudPacket;
dKankyo_sun_Packet* sun_packet = g_env_light.mpSunPacket;
@@ -5823,8 +6017,13 @@ void dKyr_mud_draw(Mtx drawMtx, u8** tex) {
if (g_env_light.camera_water_in_status == 0) {
for (int i = 0; i < 1; i++) {
#if TARGET_PC
static CachedTexObjs<1> texobj_cache;
auto* texobj = load_cached_tex(texobj_cache, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
@@ -5864,7 +6063,11 @@ void dKyr_mud_draw(Mtx drawMtx, u8** tex) {
color_reg0.a = mud_packet->mEffect[j].field_0x38 * var_f31;
#if TARGET_PC
GXLoadTexObj(texobj, GX_TEXMAP0);
#else
GXLoadTexObj(&texobj, GX_TEXMAP0);
#endif
GXSetTevColor(GX_TEVREG0, color_reg0);
f32 sp30 = 1.0f;
@@ -5949,6 +6152,7 @@ void dKyr_evil_move() {
}
static void dKyr_evil_draw2(Mtx drawMtx, u8** tex) {
ZoneScoped;
dScnKy_env_light_c* envlight = dKy_getEnvlight();
dKankyo_evil_Packet* evil_packet = envlight->mpEvilPacket;
camera_class* camera = (camera_class*)dComIfGp_getCamera(0);
@@ -5985,8 +6189,13 @@ static void dKyr_evil_draw2(Mtx drawMtx, u8** tex) {
color_reg0.b = 0x87;
color_reg0.a = 0xFF;
#if TARGET_PC
static CachedTexObjs<1> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[1], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[1]);
#endif
#if TARGET_PC
if (dusk::frame_interp::get_ui_tick_pending())
@@ -6187,6 +6396,7 @@ static f32 dKyr_near_bosslight_check(cXyz pos) {
}
void dKyr_evil_draw(Mtx drawMtx, u8** tex) {
ZoneScoped;
dScnKy_env_light_c* envlight = dKy_getEnvlight();
dKankyo_evil_Packet* evil_packet = envlight->mpEvilPacket;
camera_class* camera = (camera_class*)dComIfGp_getCamera(0);
@@ -6223,8 +6433,13 @@ void dKyr_evil_draw(Mtx drawMtx, u8** tex) {
color_reg1.b = 10;
color_reg1.a = 255;
#if TARGET_PC
static CachedTexObjs<1> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
#if TARGET_PC
if (dusk::frame_interp::get_ui_tick_pending())
+3 -3
View File
@@ -79,7 +79,7 @@ SNOW_EFF::~SNOW_EFF() {}
SNOW_EFF::SNOW_EFF() {}
void dKankyo_snow_Packet::draw() {
dKyr_drawSnow(j3dSys.getViewMtx(), &mpTex);
GX_DEBUG_GROUP(dKyr_drawSnow, j3dSys.getViewMtx(), &mpTex);
}
STAR_EFF::~STAR_EFF() {}
@@ -103,7 +103,7 @@ HOUSI_EFF::~HOUSI_EFF() {}
HOUSI_EFF::HOUSI_EFF() {}
void dKankyo_housi_Packet::draw() {
dKyr_drawHousi(j3dSys.getViewMtx(), &mpResTex);
GX_DEBUG_GROUP(dKyr_drawHousi, j3dSys.getViewMtx(), &mpResTex);
}
VRKUMO_EFF::~VRKUMO_EFF() {}
@@ -119,7 +119,7 @@ EF_ODOUR_EFF::~EF_ODOUR_EFF() {}
EF_ODOUR_EFF::EF_ODOUR_EFF() {}
void dKankyo_odour_Packet::draw() {
dKyr_odour_draw(j3dSys.getViewMtx(), &mpResTex);
GX_DEBUG_GROUP(dKyr_odour_draw, j3dSys.getViewMtx(), &mpResTex);
}
EF_MUD_EFF::~EF_MUD_EFF() {}
+161
View File
@@ -23,6 +23,39 @@
#include "dusk/frame_interpolation.h"
#include <cstring>
#if TARGET_PC
#include "dusk/settings.h"
#include <algorithm>
namespace {
// Reads the user HUD scale setting, clamped to a safe range.
f32 dGetUserHudScale() {
return std::clamp(dusk::getSettings().game.hudScale.getValue(), 0.5f, 2.0f);
}
// The screen corner each HUD group is anchored to. A pane scales around its own origin,
// so without correction it drifts away from the screen edge; this names the corner that
// must stay put.
enum class HudCorner { TopLeft, TopRight, BottomLeft, BottomRight };
// Adds the paneTrans offset that keeps i_corner pinned in place while the user HUD scale
// grows or shrinks the pane. The shift is half the change in size pushed toward the
// anchor corner, so it depends only on the pane's size (not its on-screen position) and
// works whether the HUD is scaled down or up. i_pull < 1 applies a partial horizontal
// push for a pane whose content sits inset from its box edge (the heart row).
void dAnchorHudScale(CPaneMgr* i_pane, HudCorner i_corner, f32* io_x, f32* io_y, f32 i_pull = 1.0f) {
const f32 half = (1.0f - dGetUserHudScale()) * 0.5f;
const f32 dirX =
(i_corner == HudCorner::TopRight || i_corner == HudCorner::BottomRight) ? 1.0f : -1.0f;
const f32 dirY =
(i_corner == HudCorner::BottomLeft || i_corner == HudCorner::BottomRight) ? 1.0f : -1.0f;
*io_x += dirX * i_pane->getInitSizeX() * half * i_pull;
*io_y += dirY * i_pane->getInitSizeY() * half;
}
} // namespace
#endif
dMeter2Draw_c::dMeter2Draw_c(JKRExpHeap* mp_heap) {
OS_REPORT("enter dMeter2Draw_c::dMeter2Draw_c(JKRExpHeap *mp_heap)\n");
@@ -536,6 +569,12 @@ void dMeter2Draw_c::init() {
}
void dMeter2Draw_c::exec(u32 i_status) {
#if TARGET_PC
// n_all keeps the vanilla scale. Scaling the root pane shrinks every child toward
// its centred origin; per-child scaling in each drawXxx() path keeps each HUD group
// anchored to its own pane origin and also pulls it toward the screen corner.
const f32 userHudScale = dGetUserHudScale();
#endif
if (mParentScale != g_drawHIO.mParentScale) {
mParentScale = g_drawHIO.mParentScale;
mpParent->scale(g_drawHIO.mParentScale, g_drawHIO.mParentScale);
@@ -546,6 +585,39 @@ void dMeter2Draw_c::exec(u32 i_status) {
mpParent->setAlphaRate(g_drawHIO.mParentAlpha);
}
#if TARGET_PC
if (i_status & 0x1000000) {
f32 ringPosX = g_drawHIO.mRingHUDButtonsPosX;
f32 ringPosY = g_drawHIO.mRingHUDButtonsPosY;
dAnchorHudScale(mpButtonParent, HudCorner::TopRight, &ringPosX, &ringPosY);
if (mButtonsPosX != ringPosX || mButtonsPosY != ringPosY) {
mButtonsPosX = ringPosX;
mButtonsPosY = ringPosY;
mpButtonParent->paneTrans(ringPosX, ringPosY);
}
const f32 ringButtonsScale = g_drawHIO.mRingHUDButtonsScale * userHudScale;
if (mButtonsScale != ringButtonsScale) {
mButtonsScale = ringButtonsScale;
mpButtonParent->scale(ringButtonsScale, ringButtonsScale);
}
} else {
f32 mainPosX = g_drawHIO.mMainHUDButtonsPosX;
f32 mainPosY = g_drawHIO.mMainHUDButtonsPosY;
dAnchorHudScale(mpButtonParent, HudCorner::TopRight, &mainPosX, &mainPosY);
if (mButtonsPosX != mainPosX || mButtonsPosY != mainPosY) {
mButtonsPosX = mainPosX;
mButtonsPosY = mainPosY;
mpButtonParent->paneTrans(mainPosX, mainPosY);
}
const f32 mainButtonsScale = g_drawHIO.mMainHUDButtonsScale * userHudScale;
if (mButtonsScale != mainButtonsScale) {
mButtonsScale = mainButtonsScale;
mpButtonParent->scale(mainButtonsScale, mainButtonsScale);
}
}
#else
if (i_status & 0x1000000) {
if (mButtonsPosX != g_drawHIO.mRingHUDButtonsPosX ||
mButtonsPosY != g_drawHIO.mRingHUDButtonsPosY)
@@ -574,6 +646,7 @@ void dMeter2Draw_c::exec(u32 i_status) {
mpButtonParent->scale(g_drawHIO.mMainHUDButtonsScale, g_drawHIO.mMainHUDButtonsScale);
}
}
#endif
}
void dMeter2Draw_c::draw() {
@@ -588,6 +661,9 @@ void dMeter2Draw_c::draw() {
if (mpItemXY[i] != NULL) {
for (int j = 0; j < 3; j++) {
f32 temp_f30 = mItemParams[i].num_scale * 16.0f;
#if TARGET_PC
temp_f30 *= dGetUserHudScale();
#endif
Vec vtx0 = mpItemXY[i]->getPanePtr()->getGlbVtx(0);
Vec vtx3 = mpItemXY[i]->getPanePtr()->getGlbVtx(3);
@@ -1478,7 +1554,12 @@ void dMeter2Draw_c::drawLife(s16 i_maxLife, s16 i_life, f32 i_posX, f32 i_posY)
}
}
#if TARGET_PC
const f32 lifeParentScale = g_drawHIO.mLifeParentScale * dGetUserHudScale();
mpLifeParent->scale(lifeParentScale, lifeParentScale);
#else
mpLifeParent->scale(g_drawHIO.mLifeParentScale, g_drawHIO.mLifeParentScale);
#endif
for (int i = 0; i < 20; i++) {
mpHeartMark[i]->scale(g_drawHIO.mHeartMarkScale, g_drawHIO.mHeartMarkScale);
@@ -1488,7 +1569,16 @@ void dMeter2Draw_c::drawLife(s16 i_maxLife, s16 i_life, f32 i_posX, f32 i_posY)
mpBigHeart->scale(g_drawHIO.mBigHeartScale, g_drawHIO.mBigHeartScale);
}
#if TARGET_PC
f32 lifePosX = i_posX;
f32 lifePosY = i_posY;
// The heart row sits inset from its box's left edge, so use a partial horizontal pull
// to keep it from jamming against the screen edge.
dAnchorHudScale(mpLifeParent, HudCorner::TopLeft, &lifePosX, &lifePosY, 0.6f);
mpLifeParent->paneTrans(lifePosX, lifePosY);
#else
mpLifeParent->paneTrans(i_posX, i_posY);
#endif
}
void dMeter2Draw_c::setAlphaLifeChange(bool param_0) {
@@ -1601,9 +1691,22 @@ void dMeter2Draw_c::drawKanteraScreen(u8 i_meterType) {
mpMagicMeter->resize(field_0x584[i_meterType], field_0x590[i_meterType]);
mpMagicFrameR->move(field_0x59c[i_meterType], field_0x5a8[i_meterType]);
mpMagicBase->resize(field_0x5b4[i_meterType], field_0x5c0[i_meterType]);
#if TARGET_PC
const f32 magicUserScale = dGetUserHudScale();
mpMagicParent->scale(field_0x5cc[i_meterType] * magicUserScale,
field_0x5d8[i_meterType] * magicUserScale);
f32 magicPosX = field_0x5e4[i_meterType];
f32 magicPosY = field_0x5f0[i_meterType];
// The oil/magic bar sits inset within its pane box, so use a reduced horizontal pull
// (like the heart row) to keep it from overshooting off the left edge when shrunk.
dAnchorHudScale(mpMagicParent, HudCorner::TopLeft, &magicPosX, &magicPosY, 0.3f);
mpMagicParent->paneTrans(magicPosX, magicPosY);
#else
mpMagicParent->scale(field_0x5cc[i_meterType], field_0x5d8[i_meterType]);
mpMagicParent->paneTrans(field_0x5e4[i_meterType], field_0x5f0[i_meterType]);
#endif
mpKanteraScreen->draw(0.0f, 0.0f, graf_ctx);
}
@@ -1867,10 +1970,21 @@ void dMeter2Draw_c::drawLightDrop(u8 i_num, u8 i_needNum, f32 i_posX, f32 i_posY
field_0x6fc = param_5;
mLightDropVesselScale = i_vesselScale;
#if TARGET_PC
const f32 lightDropUserScale = dGetUserHudScale();
const f32 lightDropScale = mLightDropVesselScale * field_0x6f8 * lightDropUserScale;
mpLightDropParent->scale(lightDropScale, lightDropScale);
f32 lightDropPosX = i_posX;
f32 lightDropPosY = i_posY;
dAnchorHudScale(mpLightDropParent, HudCorner::TopRight, &lightDropPosX, &lightDropPosY);
mpLightDropParent->paneTrans(lightDropPosX, lightDropPosY);
#else
mpLightDropParent->scale(mLightDropVesselScale * field_0x6f8,
mLightDropVesselScale * field_0x6f8);
mpLightDropParent->paneTrans(i_posX, i_posY);
#endif
}
void dMeter2Draw_c::setAlphaLightDropChange(bool unused) {}
@@ -1943,8 +2057,13 @@ void dMeter2Draw_c::setAlphaLightDropAnimeMax() {
field_0x6f8 = 1.0f;
}
#if TARGET_PC
const f32 dropAnimScale = mLightDropVesselScale * field_0x6f8 * dGetUserHudScale();
mpLightDropParent->scale(dropAnimScale, dropAnimScale);
#else
mpLightDropParent->scale(mLightDropVesselScale * field_0x6f8,
mLightDropVesselScale * field_0x6f8);
#endif
if (g_drawHIO.mLightDrop.mDropGetScaleAnimFrameNum == mpLightDropParent->getAlphaTimer()) {
dMeter2Info_setLightDropGetFlag(dComIfGp_getStartStageDarkArea(), 0xFF);
@@ -2015,10 +2134,22 @@ void dMeter2Draw_c::drawRupee(s16 i_rupeeNum) {
static_cast<J2DPicture*>(mpRupeeTexture[0][0]->getPanePtr())->changeTexture(timg, 0);
static_cast<J2DPicture*>(mpRupeeTexture[0][1]->getPanePtr())->changeTexture(timg, 0);
#if TARGET_PC
const f32 rupeeKeyUserScale = dGetUserHudScale();
const f32 rupeeKeyScale = g_drawHIO.mRupeeKeyScale * field_0x718 * rupeeKeyUserScale;
mpRupeeKeyParent->scale(rupeeKeyScale, rupeeKeyScale);
f32 rupeeKeyPosX = g_drawHIO.mRupeeKeyPosX;
f32 rupeeKeyPosY = g_drawHIO.mRupeeKeyPosY;
// Rupees/keys read better anchored to the bottom-right corner than the top-right.
dAnchorHudScale(mpRupeeKeyParent, HudCorner::BottomRight, &rupeeKeyPosX, &rupeeKeyPosY);
mpRupeeKeyParent->paneTrans(rupeeKeyPosX, rupeeKeyPosY);
#else
mpRupeeKeyParent->scale(g_drawHIO.mRupeeKeyScale * field_0x718,
g_drawHIO.mRupeeKeyScale * field_0x718);
mpRupeeKeyParent->paneTrans(g_drawHIO.mRupeeKeyPosX, g_drawHIO.mRupeeKeyPosY);
#endif
mpRupeeParent[0]->scale(g_drawHIO.mRupeeScale, g_drawHIO.mRupeeScale);
mpRupeeParent[0]->paneTrans(g_drawHIO.mRupeePosX, g_drawHIO.mRupeePosY);
@@ -2137,8 +2268,18 @@ void dMeter2Draw_c::drawKey(s16 i_keyNum) {
}
}
#if TARGET_PC
const f32 keyScale = g_drawHIO.mKeyScale * dGetUserHudScale();
mpKeyParent->scale(keyScale, keyScale);
f32 keyPosX = g_drawHIO.mKeyPosX;
f32 keyPosY = g_drawHIO.mKeyPosY;
dAnchorHudScale(mpKeyParent, HudCorner::BottomRight, &keyPosX, &keyPosY);
mpKeyParent->paneTrans(keyPosX, keyPosY);
#else
mpKeyParent->scale(g_drawHIO.mKeyScale, g_drawHIO.mKeyScale);
mpKeyParent->paneTrans(g_drawHIO.mKeyPosX, g_drawHIO.mKeyPosY);
#endif
}
void dMeter2Draw_c::setAlphaKeyChange(bool param_0) {
@@ -2596,11 +2737,24 @@ f32 dMeter2Draw_c::getButtonCrossParentInitTransY() {
}
void dMeter2Draw_c::drawButtonCross(f32 i_posX, f32 i_posY) {
#if TARGET_PC
const f32 buttonCrossUserScale = dGetUserHudScale();
const f32 buttonCrossScale = g_drawHIO.mButtonCrossScale * buttonCrossUserScale;
mpButtonCrossParent->scale(buttonCrossScale, buttonCrossScale);
#else
mpButtonCrossParent->scale(g_drawHIO.mButtonCrossScale, g_drawHIO.mButtonCrossScale);
#endif
mpTextI->scale(g_drawHIO.mButtonCrossTextScale, g_drawHIO.mButtonCrossTextScale);
mpTextM->scale(g_drawHIO.mButtonCrossTextScale, g_drawHIO.mButtonCrossTextScale);
#if TARGET_PC
f32 buttonCrossPosX = i_posX;
f32 buttonCrossPosY = i_posY;
dAnchorHudScale(mpButtonCrossParent, HudCorner::TopLeft, &buttonCrossPosX, &buttonCrossPosY);
mpButtonCrossParent->paneTrans(buttonCrossPosX, buttonCrossPosY);
#else
mpButtonCrossParent->paneTrans(i_posX, i_posY);
#endif
}
void dMeter2Draw_c::setAlphaButtonCrossAnimeMin() {
@@ -3505,9 +3659,16 @@ void dMeter2Draw_c::drawKanteraMeter(u8 i_button, f32 i_alphaRate) {
Vec vtx0 = pane->getPanePtr()->getGlbVtx(0);
Vec vtx3 = pane->getPanePtr()->getGlbVtx(3);
#if TARGET_PC
const f32 oilUserScale = dGetUserHudScale();
mpKanteraMeter[i_button]->setPos(((vtx0.x + vtx3.x) * 0.5f) + 9.0f * oilUserScale + sp10[i_button],
vtx3.y + sp8[i_button]);
mpKanteraMeter[i_button]->setScale(0.6f * oilUserScale, 0.6f * oilUserScale);
#else
mpKanteraMeter[i_button]->setPos(((vtx0.x + vtx3.x) * 0.5f) + 9.0f + sp10[i_button],
vtx3.y + sp8[i_button]);
mpKanteraMeter[i_button]->setScale(0.6f, 0.6f);
#endif
mpKanteraMeter[i_button]->setNowGauge(dComIfGs_getMaxOil(), dComIfGs_getOil());
mpKanteraMeter[i_button]->setAlphaRate(i_alphaRate);
}
+14 -2
View File
@@ -16,6 +16,10 @@
#include "f_op/f_op_overlap_mng.h"
#include "m_Do/m_Do_controller_pad.h"
#include "d/d_camera.h"
#if TARGET_PC
#include "dusk/settings.h"
#include <algorithm>
#endif
#include <cstring>
#if (PLATFORM_WII || PLATFORM_SHIELD)
@@ -621,8 +625,16 @@ void dMeterMap_c::draw() {
mMapJ2DPicture->setAlpha(alpha);
#if TARGET_PC
mMapJ2DPicture->draw(mDoGph_gInf_c::ScaleHUDXLeft(drawPosX), drawPosY, sizeX, sizeY, false,
false, false);
// Scale the minimap with the user HUD scale and shift down so its bottom-left
// corner stays anchored to the same screen position as at scale 1.0.
const f32 userHudScale =
std::clamp(dusk::getSettings().game.hudScale.getValue(), 0.5f, 2.0f);
const f32 scaledSizeX = sizeX * userHudScale;
const f32 scaledSizeY = sizeY * userHudScale;
const f32 mapBottomShift = sizeY - scaledSizeY;
mMapJ2DPicture->draw(mDoGph_gInf_c::ScaleHUDXLeft(drawPosX),
drawPosY + mapBottomShift, scaledSizeX, scaledSizeY,
false, false, false);
#else
mMapJ2DPicture->draw(drawPosX, drawPosY, sizeX, sizeY, false, false, false);
#endif
+4
View File
@@ -1359,6 +1359,7 @@ void dPa_control_c::calcMenu() {
}
void dPa_control_c::draw(JPADrawInfo* param_0, u8 param_1) {
ZoneScoped;
if (mEmitterMng != NULL) {
j3dSys.reinitGX();
dKy_setLight_again();
@@ -1957,6 +1958,7 @@ void dPa_gen_d_light8PcallBack::execute(JPABaseEmitter* i_emitter, JPABasePartic
}
void dPa_light8PcallBack::draw(JPABaseEmitter* param_1, JPABaseParticle* param_2) {
ZoneScoped;
Mtx local_60;
Mtx auStack_90;
Mtx auStack_c0;
@@ -2084,6 +2086,7 @@ void dPa_light8PcallBack::draw(JPABaseEmitter* param_1, JPABaseParticle* param_2
}
void dPa_gen_b_light8PcallBack::draw(JPABaseEmitter* param_1, JPABaseParticle* param_2) {
ZoneScoped;
Mtx local_80;
JGeometry::TVec3<f32> local_8c;
JGeometry::TVec3<f32> aTStack_98;
@@ -2172,6 +2175,7 @@ void dPa_gen_b_light8PcallBack::draw(JPABaseEmitter* param_1, JPABaseParticle* p
}
void dPa_gen_d_light8PcallBack::draw(JPABaseEmitter* param_1, JPABaseParticle* param_2) {
ZoneScoped;
Mtx local_60;
Mtx auStack_90;
Mtx auStack_c0;
+2 -1
View File
@@ -34,6 +34,7 @@
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#include <mach-o/loader.h>
#include <TargetConditionals.h>
#else
#include <elf.h>
#include <link.h>
@@ -929,7 +930,7 @@ void install() {
SymInitialize(GetCurrentProcess(), nullptr, TRUE);
#endif
g_prevFilter = SetUnhandledExceptionFilter(&windowsHandler);
#else
#elif !defined(__APPLE__) || !TARGET_OS_TV
Dl_info moduleInfo;
if (dladdr(reinterpret_cast<void*>(&install), &moduleInfo) != 0) {
g_ctx.moduleBase = reinterpret_cast<uintptr_t>(moduleInfo.dli_fbase);
+2 -102
View File
@@ -16,7 +16,6 @@
#include <vector>
#include <SDL3/SDL_filesystem.h>
#include <SDL3/SDL_iostream.h>
#include <SDL3/SDL_misc.h>
#include <SDL3/SDL_stdinc.h>
@@ -28,8 +27,6 @@ namespace {
aurora::Module Log{"dusk::data"};
constexpr auto kLocationDescriptorName = "data_location.json";
constexpr auto kPipelineCacheName = "pipeline_cache.db";
constexpr auto kInitialPipelineCacheName = "initial_pipeline_cache.db";
constexpr std::array<std::string_view, 4> kUserDataDirectories = {
"texture_replacements",
@@ -111,7 +108,7 @@ std::filesystem::path get_pref_path() {
Log.fatal("Unable to get PrefPath: {}", SDL_GetError());
}
std::filesystem::path result{reinterpret_cast<const char8_t*>(prefPath)};
std::filesystem::path result = path_from_utf8(prefPath);
SDL_free(prefPath);
return result;
}
@@ -128,7 +125,7 @@ std::filesystem::path base_path_relative(const std::filesystem::path& path) {
if (!basePath) {
return path;
}
return std::filesystem::path{basePath} / path;
return path_from_utf8(basePath) / path;
}
std::filesystem::path default_data_path(const std::filesystem::path& prefPath) {
@@ -888,102 +885,6 @@ void ensure_data_directory(const std::filesystem::path& dataPath) {
}
}
SDL_IOStream* open_initial_pipeline_cache_source(std::string& sourcePathString) {
const auto basePath = base_path_relative(kInitialPipelineCacheName);
sourcePathString = io::fs_path_to_string(basePath);
auto* source = SDL_IOFromFile(sourcePathString.c_str(), "rb");
if (source != nullptr) {
return source;
}
sourcePathString = std::string{kInitialPipelineCacheName};
return SDL_IOFromFile(sourcePathString.c_str(), "rb");
}
void ensure_initial_pipeline_cache(const std::filesystem::path& configDir) {
if (configDir.empty()) {
return;
}
std::error_code ec;
std::filesystem::create_directories(configDir, ec);
if (ec) {
Log.warn("Failed to create config directory '{}' for pipeline cache: {}",
io::fs_path_to_string(configDir), ec.message());
return;
}
const auto pipelineCachePath = configDir / kPipelineCacheName;
if (std::filesystem::exists(pipelineCachePath, ec)) {
return;
}
std::string sourcePathString;
SDL_IOStream* source = open_initial_pipeline_cache_source(sourcePathString);
if (source == nullptr) {
Log.info("No bundled initial pipeline cache found");
return;
}
const auto pipelineCacheString = io::fs_path_to_string(pipelineCachePath);
SDL_IOStream* destination = SDL_IOFromFile(pipelineCacheString.c_str(), "wb");
if (destination == nullptr) {
Log.warn("Failed to open '{}' for seeded pipeline cache: {}", pipelineCacheString,
SDL_GetError());
SDL_CloseIO(source);
return;
}
bool copied = true;
std::array<char, 64 * 1024> buffer{};
while (true) {
const size_t bytesRead = SDL_ReadIO(source, buffer.data(), buffer.size());
if (bytesRead > 0) {
size_t bytesWritten = 0;
while (bytesWritten < bytesRead) {
const size_t written = SDL_WriteIO(
destination, buffer.data() + bytesWritten, bytesRead - bytesWritten);
if (written == 0) {
Log.warn("Failed to write seeded pipeline cache '{}': {}", pipelineCacheString,
SDL_GetError());
copied = false;
break;
}
bytesWritten += written;
}
}
if (!copied) {
break;
}
if (bytesRead < buffer.size()) {
if (SDL_GetIOStatus(source) == SDL_IO_STATUS_EOF) {
break;
}
Log.warn(
"Failed to read bundled pipeline cache '{}': {}", sourcePathString, SDL_GetError());
copied = false;
break;
}
}
if (!SDL_CloseIO(destination)) {
Log.warn(
"Failed to close seeded pipeline cache '{}': {}", pipelineCacheString, SDL_GetError());
copied = false;
}
SDL_CloseIO(source);
if (!copied) {
std::filesystem::remove(pipelineCachePath, ec);
return;
}
Log.info("Seeded pipeline cache from '{}'", sourcePathString);
}
} // namespace
bool open_data_path() {
@@ -1096,7 +997,6 @@ Paths initialize_data() {
migrate_data(prefPath, dataPath, descriptor ? &descriptor->descriptor : nullptr);
ensure_data_directory(dataPath);
ensure_data_directory(prefPath);
ensure_initial_pipeline_cache(prefPath);
return Paths{
.userPath = dataPath,
+6
View File
@@ -4,8 +4,14 @@ GXTexObjRAII::~GXTexObjRAII() { GXDestroyTexObj(this); }
void GXTexObjRAII::reset() { GXDestroyTexObj(this); }
GXScopedDebugGroup::GXScopedDebugGroup(const char* text) {
#if DUSK_GFX_DEBUG_GROUPS
GXPushDebugGroup(text);
#else
(void)text;
#endif
}
GXScopedDebugGroup::~GXScopedDebugGroup() {
#if DUSK_GFX_DEBUG_GROUPS
GXPopDebugGroup();
#endif
}
+2 -53
View File
@@ -2,8 +2,6 @@
#include "dusk/ui/ui.hpp"
#include "d/actor/d_a_alink.h"
#include <aurora/lib/window.hpp>
#include <SDL3/SDL_mouse.h>
#include <cmath>
namespace dusk::gyro {
@@ -16,14 +14,11 @@ constexpr float kGravityEmaAlpha = 0.1f;
constexpr float kMinGravityProjection = 0.2f;
// Let roll contribute more strongly as the pad approaches an upright posture.
constexpr float kRollAimBoostMax = 2.0f;
constexpr float kMousePixelToRad = 0.0025f;
bool s_sensor_enabled = false;
bool s_accel_enabled = false;
bool s_was_aiming = false;
bool s_have_gravity_baseline = false;
bool s_mouse_enabled = false;
bool s_mouse_relative = false;
float s_smooth_gx = 0.0f;
float s_smooth_gy = 0.0f;
float s_smooth_gz = 0.0f;
@@ -43,7 +38,6 @@ void reset_filter_state() {
s_baseline_gravity_y = s_baseline_gravity_z = 0.0f;
s_was_aiming = false;
s_have_gravity_baseline = false;
s_mouse_enabled = false;
s_yaw_rad = s_pitch_rad = s_roll_rad = 0.0f;
s_rollgoal_ax = s_rollgoal_az = 0;
}
@@ -72,7 +66,7 @@ bool get_sensor_keep_alive() { return s_sensor_keep_alive; }
void set_sensor_keep_alive(bool value) { s_sensor_keep_alive = value; }
bool rollgoal_gyro_enabled() {
return getSettings().game.enableGyroRollgoal && getSettings().game.gyroMode.getValue() != GyroMode::Mouse;
return getSettings().game.enableGyroRollgoal;
}
bool queryGyroAimContext() {
@@ -85,7 +79,7 @@ bool queryGyroAimContext() {
return false;
}
return link->checkGyroAimContext() && dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10);
return link->checkAimContext() && dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10);
}
void read(float dt) {
@@ -94,26 +88,6 @@ void read(float dt) {
const bool aim_just_ended = !aim_active && s_was_aiming;
s_was_aiming = aim_active;
const bool mouse_mode = getSettings().game.gyroMode.getValue() == GyroMode::Mouse;
const bool mouse_gyro_active = !ui::any_document_visible() && mouse_mode && (aim_active || s_sensor_keep_alive);
SDL_Window* window = aurora::window::get_sdl_window();
if (window != nullptr && mouse_gyro_active != s_mouse_relative &&
SDL_SetWindowRelativeMouseMode(window, mouse_gyro_active))
{
s_mouse_relative = mouse_gyro_active;
}
if (mouse_gyro_active && !s_mouse_enabled && window != nullptr) {
const AuroraWindowSize sz = aurora::window::get_window_size();
const float cx = static_cast<float>(sz.width) * 0.5f;
const float cy = static_cast<float>(sz.height) * 0.5f;
SDL_WarpMouseInWindow(window, cx, cy);
float discard_x = 0.0f;
float discard_y = 0.0f;
SDL_GetRelativeMouseState(&discard_x, &discard_y);
}
s_mouse_enabled = mouse_gyro_active;
if (!s_sensor_keep_alive && !aim_active) {
disable_pad_sensors();
reset_filter_state();
@@ -126,31 +100,6 @@ void read(float dt) {
s_have_gravity_baseline = false;
}
if (mouse_mode && !mouse_gyro_active) {
s_pitch_rad = 0.0f;
s_yaw_rad = 0.0f;
s_roll_rad = 0.0f;
return;
}
if (mouse_mode) {
disable_pad_sensors();
float mx_rel = 0.0f;
float my_rel = 0.0f;
SDL_GetRelativeMouseState(&mx_rel, &my_rel);
// Convert pixels to radians
s_pitch_rad = my_rel * kMousePixelToRad * getSettings().game.gyroSensitivityY;
s_yaw_rad = -mx_rel * kMousePixelToRad * getSettings().game.gyroSensitivityX;
s_roll_rad = 0.0f;
s_pitch_rad = getSettings().game.gyroInvertPitch ? -s_pitch_rad : s_pitch_rad;
s_yaw_rad = getSettings().game.gyroInvertYaw ? -s_yaw_rad : s_yaw_rad;
s_yaw_rad = getSettings().game.enableMirrorMode ? -s_yaw_rad : s_yaw_rad;
return;
}
if (!s_sensor_enabled) {
if (!PADHasSensor(PAD_CHAN0, PAD_SENSOR_GYRO)) {
return;
+5 -3
View File
@@ -49,7 +49,9 @@ namespace dusk {
dCam->Reset(center, eye);
}
ImGui::InputFloat("Camera FOV", &dCam->mFovy);
if (ImGui::InputFloat("Camera FOV", &dCam->mFovy)) {
dCam->mFovy = std::clamp(dCam->mFovy, 0.1f, 179.9f);
}
ImGui::SeparatorText("Options");
@@ -75,12 +77,12 @@ namespace dusk {
if (!getSettings().game.debugFlyCam) {
ImGui::BeginDisabled();
}
config::ImGuiCheckbox("Lock Events", getSettings().game.debugFlyCamLockEvents);
config::ImGuiCheckbox("Freeze Time", getSettings().game.debugFlyCamLockEvents);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
if (!getSettings().game.debugFlyCam) {
ImGui::SetTooltip("Enable Fly Mode first.");
} else {
ImGui::SetTooltip("Freeze game events while flying.");
ImGui::SetTooltip("Freezes the game while flying.");
}
}
if (!getSettings().game.debugFlyCam) {
-65
View File
@@ -12,7 +12,6 @@
#include "ImGuiConsole.hpp"
#include "ImGuiEngine.hpp"
#include "JSystem/JUtility/JUTGamePad.h"
#include "SDL3/SDL_mouse.h"
#include "dusk/action_bindings.h"
#include "dusk/audio/DuskAudioSystem.h"
#include "dusk/config.hpp"
@@ -61,10 +60,6 @@ namespace dusk {
ImGui::TextUnformatted(text.data(), text.data() + text.size());
}
void DuskToast(std::string_view message, float duration) {
g_imguiConsole.AddToast(message, duration);
}
void ImGuiTextCenter(std::string_view text) {
ImGui::NewLine();
float fontSize = ImGui::CalcTextSize(
@@ -376,22 +371,6 @@ namespace dusk {
m_menuTools.ShowActorSpawner();
}
// Hide mouse cursor if the F1 menu is not open and the cursor is idle for 3 seconds.
if (dusk::getSettings().game.gyroMode.getValue() != GyroMode::Mouse)
{
ImGuiIO& io = ImGui::GetIO();
if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f) {
mouseHideTimer = 0.0f;
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange; // Imgui will re-show cursor.
} else if (mouseHideTimer <= 3.0f) {
mouseHideTimer += ImGui::GetIO().DeltaTime;
} else {
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
SDL_HideCursor();
}
}
ShowToasts();
}
void ImGuiConsole::PostDraw() {
@@ -545,50 +524,6 @@ namespace dusk {
return false;
}
void ImGuiConsole::AddToast(std::string_view message, float duration) {
m_toasts.emplace_back(std::string(message), duration);
}
void ImGuiConsole::ShowToasts() {
if (m_toasts.empty()) {
return;
}
auto& toast = m_toasts.front();
const float dt = ImGui::GetIO().DeltaTime;
toast.remain -= dt;
toast.current += dt;
const ImGuiViewport* viewport = ImGui::GetMainViewport();
const ImVec2 workPos = viewport->WorkPos;
const ImVec2 workSize = viewport->WorkSize;
constexpr float padding = 10.0f;
const ImVec2 windowPos{workPos.x + workSize.x / 2, workPos.y + workSize.y - padding};
ImGui::SetNextWindowPos(windowPos, ImGuiCond_Always, ImVec2{0.5f, 1.f});
const float alpha = std::min({toast.remain, toast.current, 1.f});
ImGui::SetNextWindowBgAlpha(alpha * 0.65f);
ImVec4 textColor = ImGui::GetStyleColorVec4(ImGuiCol_Text);
textColor.w *= alpha;
ImVec4 borderColor = ImGui::GetStyleColorVec4(ImGuiCol_Border);
borderColor.w *= alpha;
ImGui::PushStyleColor(ImGuiCol_Text, textColor);
ImGui::PushStyleColor(ImGuiCol_Border, borderColor);
if (ImGui::Begin("Toast", nullptr,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav |
ImGuiWindowFlags_NoMove))
{
ImGuiStringViewText(toast.message);
}
ImGui::End();
ImGui::PopStyleColor(2);
if (toast.remain <= 0.f) {
m_toasts.pop_front();
}
}
void ImGuiConsole::ShowPipelineProgress() {
const auto* stats = aurora_get_stats();
const u32 queuedPipelines = stats->queuedPipelines;
-13
View File
@@ -24,29 +24,17 @@ public:
void PostDraw();
static bool CheckMenuViewToggle(ImGuiKey key, bool& active);
void AddToast(std::string_view message, float duration = 3.f);
private:
struct Toast {
std::string message;
float remain;
float current = 0.f;
Toast(std::string message, float duration) noexcept : message(std::move(message)),
remain(duration) {}
};
float mouseHideTimer = 0.0f;
bool m_isHidden = true;
bool m_isLaunchInitialized = false;
ImGuiWindow* m_dragScrollWindow = nullptr;
ImVec2 m_dragScrollLastMousePos = {};
std::deque<Toast> m_toasts;
// Keep always last
ImGuiMenuTools m_menuTools;
void ShowToasts();
void ShowPipelineProgress();
void UpdateDragScroll();
};
@@ -60,7 +48,6 @@ std::string BytesToString(size_t bytes);
void SetOverlayWindowLocation(int corner);
bool ShowCornerContextMenu(int& corner, int avoidCorner);
void ImGuiStringViewText(std::string_view text);
void DuskToast(std::string_view message, float duration = 3.f);
void ImGuiBeginGroupPanel(const char* name, const ImVec2& size);
void ImGuiEndGroupPanel();
void ImGuiTextCenter(std::string_view text);
+211
View File
@@ -0,0 +1,211 @@
#include "dusk/mouse.h"
#include "dusk/settings.h"
#include "dusk/ui/ui.hpp"
#include "d/actor/d_a_alink.h"
#include "d/d_com_inf_game.h"
#include <aurora/lib/window.hpp>
#include <imgui.h>
#include <SDL3/SDL_mouse.h>
#include <SDL3/SDL_video.h>
namespace dusk::mouse {
namespace {
constexpr float kMousePixelToRad = 0.0025f;
constexpr int kIdleHideFrames = 99; // Approx. 3 seconds with 33ms ticks
float s_aim_yaw_rad = 0.0f;
float s_aim_pitch_rad = 0.0f;
float s_camera_yaw_rad = 0.0f;
float s_camera_pitch_rad = 0.0f;
int s_idle_frames = 0;
void reset_deltas() {
s_aim_yaw_rad = s_aim_pitch_rad = 0.0f;
s_camera_yaw_rad = s_camera_pitch_rad = 0.0f;
}
bool queryMouseAimContext() {
if (!getSettings().game.enableMouseAim) {
return false;
}
daAlink_c* link = daAlink_getAlinkActorClass();
if (link == nullptr) {
return false;
}
return link->checkAimContext() && dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10);
}
bool wantMouseCapture() {
return getSettings().game.enableMouseCamera.getValue() || queryMouseAimContext();
}
bool isWindowFocused(SDL_Window* window) {
if (window == nullptr) {
return false;
}
return (SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) != 0;
}
bool shouldCaptureMouse(SDL_Window* window) {
if (window == nullptr || ui::any_document_visible()) {
return false;
}
return wantMouseCapture() && isWindowFocused(window);
}
bool syncCaptureState(SDL_Window* window, bool should_capture) {
if (window == nullptr) {
reset_deltas();
return false;
}
const bool was_captured = SDL_GetWindowRelativeMouseMode(window);
if (was_captured != should_capture) {
SDL_SetWindowMouseGrab(window, should_capture);
SDL_SetWindowRelativeMouseMode(window, should_capture);
}
const bool is_captured = SDL_GetWindowRelativeMouseMode(window);
if (is_captured && !was_captured) {
const AuroraWindowSize sz = aurora::window::get_window_size();
const float cx = static_cast<float>(sz.width) * 0.5f;
const float cy = static_cast<float>(sz.height) * 0.5f;
SDL_WarpMouseInWindow(window, cx, cy);
float discard_x = 0.0f;
float discard_y = 0.0f;
SDL_GetRelativeMouseState(&discard_x, &discard_y);
}
if (!is_captured) {
reset_deltas();
}
return is_captured;
}
void accumulateDeltas(float mx_rel, float my_rel, bool camera_active, bool aim_active) {
const auto& game = getSettings().game;
const bool mirror_mode = game.enableMirrorMode.getValue();
const bool invert_y = game.invertMouseY.getValue();
if (aim_active) {
const float aimSens = game.mouseAimSensitivity.getValue();
s_aim_yaw_rad = -mx_rel * kMousePixelToRad * aimSens;
s_aim_pitch_rad = my_rel * kMousePixelToRad * aimSens;
s_aim_yaw_rad = mirror_mode ? -s_aim_yaw_rad : s_aim_yaw_rad;
s_aim_pitch_rad = invert_y ? -s_aim_pitch_rad : s_aim_pitch_rad;
} else {
s_aim_yaw_rad = s_aim_pitch_rad = 0.0f;
}
if (camera_active) {
const float camSens = game.mouseCameraSensitivity.getValue();
s_camera_yaw_rad = -mx_rel * kMousePixelToRad * camSens;
s_camera_pitch_rad = -my_rel * kMousePixelToRad * camSens;
s_camera_yaw_rad = mirror_mode ? -s_camera_yaw_rad : s_camera_yaw_rad;
s_camera_pitch_rad = invert_y ? -s_camera_pitch_rad : s_camera_pitch_rad;
} else {
s_camera_yaw_rad = s_camera_pitch_rad = 0.0f;
}
}
void set_cursor_visible(bool visible) {
if (visible) {
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange;
SDL_ShowCursor();
} else {
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
SDL_HideCursor();
}
}
void update_cursor_visibility(SDL_Window* window, bool captured) {
if (window == nullptr || !isWindowFocused(window)) {
return;
}
if (captured) {
s_idle_frames = 0;
set_cursor_visible(false);
return;
}
const ImGuiIO& io = ImGui::GetIO();
if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f) {
s_idle_frames = 0;
set_cursor_visible(true);
return;
}
if (s_idle_frames < kIdleHideFrames) {
++s_idle_frames;
set_cursor_visible(true);
} else {
set_cursor_visible(false);
}
}
} // namespace
void read() {
SDL_Window* window = aurora::window::get_sdl_window();
const bool capture_active = syncCaptureState(window, shouldCaptureMouse(window));
update_cursor_visibility(window, capture_active);
if (!capture_active) {
return;
}
const bool aim_active = capture_active && queryMouseAimContext();
const bool camera_active = capture_active && getSettings().game.enableMouseCamera;
float mx_rel = 0.0f;
float my_rel = 0.0f;
SDL_GetRelativeMouseState(&mx_rel, &my_rel);
accumulateDeltas(mx_rel, my_rel, camera_active, aim_active);
}
void getAimDeltas(float& out_yaw, float& out_pitch) {
out_yaw = s_aim_yaw_rad;
out_pitch = s_aim_pitch_rad;
}
void getCameraDeltas(float& out_yaw, float& out_pitch) {
out_yaw = 0.0f;
out_pitch = 0.0f;
if (!getSettings().game.enableMouseCamera) {
return;
}
out_yaw = s_camera_yaw_rad;
out_pitch = s_camera_pitch_rad;
}
void handle_event(const SDL_Event& event) noexcept {
switch (event.type) {
case SDL_EVENT_WINDOW_FOCUS_LOST:
onFocusLost();
break;
case SDL_EVENT_WINDOW_FOCUS_GAINED:
onFocusGained();
break;
}
}
void onFocusLost() {
SDL_Window* window = aurora::window::get_sdl_window();
if (window != nullptr) {
syncCaptureState(window, false);
}
s_idle_frames = 0;
set_cursor_visible(true);
}
void onFocusGained() {
SDL_Window* window = aurora::window::get_sdl_window();
syncCaptureState(window, shouldCaptureMouse(window));
}
} // namespace dusk::mouse
+14 -2
View File
@@ -41,6 +41,7 @@ UserSettings g_userSettings = {
.noMissClimbing {"game.noMissClimbing", false},
.fastTears {"game.fastTears", false},
.no2ndFishForCat {"game.no2ndFishForCat", false},
.buttonFishing {"game.buttonFishing", false},
.instantSaves {"game.instantSaves", false},
.instantText {"game.instantText", false},
.sunsSong {"game.sunsSong", false},
@@ -50,6 +51,7 @@ UserSettings g_userSettings = {
// Preferences
.enableMirrorMode {"game.enableMirrorMode", false},
.minimalHUD {"game.minimalHUD", false},
.hudScale {"game.hudScale", 1.0f},
.pauseOnFocusLost {"game.pauseOnFocusLost", false},
.enableLinkDollRotation {"game.enableLinkDollRotation", false},
.enableAchievementToasts {"game.enableAchievementToasts", true},
@@ -75,7 +77,6 @@ UserSettings g_userSettings = {
.midnasLamentNonStop {"game.midnasLamentNonStop", false},
// Input
.gyroMode {"game.gyroMode", GyroMode::Sensor},
.enableGyroAim {"game.enableGyroAim", false},
.enableGyroRollgoal {"game.enableGyroRollgoal", false},
.gyroSensitivityX {"game.gyroSensitivityX", 1.0f},
@@ -85,6 +86,11 @@ UserSettings g_userSettings = {
.gyroDeadband {"game.gyroDeadband", 0.04f},
.gyroInvertPitch {"game.gyroInvertPitch", false},
.gyroInvertYaw {"game.gyroInvertYaw", false},
.enableMouseCamera {"game.enableMouseCamera", false},
.enableMouseAim {"game.enableMouseAim", false},
.mouseAimSensitivity {"game.mouseAimSensitivity", 1.0f},
.mouseCameraSensitivity {"game.mouseCameraSensitivity", 1.0f},
.invertMouseY {"game.invertMouseY", false},
.freeCamera {"game.freeCamera", false},
.invertCameraXAxis {"game.invertCameraXAxis", false},
.invertCameraYAxis {"game.invertCameraYAxis", false},
@@ -219,6 +225,7 @@ void registerSettings() {
Register(g_userSettings.game.fastClimbing);
Register(g_userSettings.game.fastTears);
Register(g_userSettings.game.no2ndFishForCat);
Register(g_userSettings.game.buttonFishing);
Register(g_userSettings.game.instantSaves);
Register(g_userSettings.game.instantText);
Register(g_userSettings.game.sunsSong);
@@ -234,6 +241,7 @@ void registerSettings() {
Register(g_userSettings.game.freeCameraXSensitivity);
Register(g_userSettings.game.freeCameraYSensitivity);
Register(g_userSettings.game.minimalHUD);
Register(g_userSettings.game.hudScale);
Register(g_userSettings.game.pauseOnFocusLost);
Register(g_userSettings.game.enableDiscordPresence);
Register(g_userSettings.game.bloomMode);
@@ -281,7 +289,6 @@ void registerSettings() {
Register(g_userSettings.game.alwaysGreatspin);
Register(g_userSettings.game.invincibleEnemies);
Register(g_userSettings.game.enableFrameInterpolation);
Register(g_userSettings.game.gyroMode);
Register(g_userSettings.game.enableGyroAim);
Register(g_userSettings.game.enableGyroRollgoal);
Register(g_userSettings.game.gyroSensitivityX);
@@ -291,6 +298,11 @@ void registerSettings() {
Register(g_userSettings.game.gyroSmoothing);
Register(g_userSettings.game.gyroInvertPitch);
Register(g_userSettings.game.gyroInvertYaw);
Register(g_userSettings.game.enableMouseCamera);
Register(g_userSettings.game.enableMouseAim);
Register(g_userSettings.game.mouseAimSensitivity);
Register(g_userSettings.game.mouseCameraSensitivity);
Register(g_userSettings.game.invertMouseY);
Register(g_userSettings.game.freeCamera);
Register(g_userSettings.game.debugFlyCam);
Register(g_userSettings.game.debugFlyCamLockEvents);
+1 -1
View File
@@ -217,7 +217,7 @@ void AchievementsWindow::updateTotal() {
return;
}
const auto all = AchievementSystem::get().getAchievements();
int total = static_cast<int>(all.size());
const int total = std::count_if(all.begin(), all.end(), [](const Achievement& achievement){ return achievement.category != AchievementCategory::Glitched;});
int unlocked = 0;
for (const auto& a : all) {
if (a.unlocked) {
-15
View File
@@ -5,7 +5,6 @@
#include "Z2AudioLib/Z2SeMgr.h"
#include "m_Do/m_Do_audio.h"
#include <imgui.h>
namespace dusk::ui {
namespace {
@@ -107,7 +106,6 @@ bool Document::visible() const {
bool Document::handle_nav_command(Rml::Event& event, NavCommand cmd) {
if (cmd == NavCommand::Menu) {
toggle_cursor_if_gyro(!visible());
mDoAud_seStartMenu(visible() ? kSoundMenuClose : kSoundMenuOpen);
toggle();
return true;
@@ -115,17 +113,4 @@ bool Document::handle_nav_command(Rml::Event& event, NavCommand cmd) {
return false;
}
void Document::toggle_cursor_if_gyro(bool cursor_enabled) {
if (dusk::getSettings().game.gyroMode.getValue() == GyroMode::Mouse)
{
if (cursor_enabled) {
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange;
SDL_ShowCursor();
} else {
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
SDL_HideCursor();
}
}
}
} // namespace dusk::ui
-2
View File
@@ -43,8 +43,6 @@ public:
bool pending_close() const { return mPendingClose; }
bool closed() const { return mClosed; }
void toggle_cursor_if_gyro(bool);
protected:
virtual bool handle_nav_command(Rml::Event& event, NavCommand cmd);
-2
View File
@@ -46,7 +46,6 @@ MenuBar::MenuBar() : Document(kDocumentSource), mRoot(mDocument->GetElementById(
mTabBar = std::make_unique<TabBar>(mRoot, TabBar::Props{
.onClose =
[this] {
toggle_cursor_if_gyro(false);
mDoAud_seStartMenu(kSoundMenuClose);
hide(false);
},
@@ -219,7 +218,6 @@ bool MenuBar::handle_nav_command(Rml::Event& event, NavCommand cmd) {
return true;
}
if (cmd == NavCommand::Cancel && visible()) {
toggle_cursor_if_gyro(false);
mDoAud_seStartMenu(kSoundMenuClose);
hide(false);
return true;
-2
View File
@@ -700,8 +700,6 @@ Prelaunch::Prelaunch() : Document(kDocumentSource), mRoot(mDocument->GetElementB
return;
}
toggle_cursor_if_gyro(false);
mDoAud_seStartMenu(kSoundPlay);
show_menu_notification();
+1
View File
@@ -37,6 +37,7 @@ void applyPresetDusk() {
s.game.invertCameraXAxis.setValue(true);
s.game.invertFirstPersonYAxis.setValue(true);
s.game.no2ndFishForCat.setValue(true);
s.game.buttonFishing.setValue(true);
s.game.enableAchievementToasts.setValue(true);
s.game.enableControllerToasts.setValue(true);
s.game.enableQuickTransform.setValue(true);
+46 -64
View File
@@ -383,9 +383,7 @@ int float_setting_percent(ConfigVar<float>& var) {
}
bool gyro_enabled() {
return getSettings().game.enableGyroAim ||
(getSettings().game.enableGyroRollgoal &&
getSettings().game.gyroMode.getValue() != GyroMode::Mouse);
return getSettings().game.enableGyroAim || getSettings().game.enableGyroRollgoal;
}
struct ConfigBoolProps {
@@ -453,7 +451,7 @@ SelectButton& config_percent_select(Pane& leftPane, Pane& rightPane, ConfigVar<f
});
leftPane.register_control(button, rightPane, [helpText = std::move(helpText)](Pane& pane) {
pane.clear();
pane.add_text(helpText);
pane.add_rml(helpText);
});
return button;
}
@@ -949,73 +947,32 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
leftPane.add_section("Camera");
addOption("Free Camera", getSettings().game.freeCamera,
"Enables twin-stick camera control, letting the C-Stick move the camera vertically as "
"well as horizontally.");
addOption("Invert Camera X Axis", getSettings().game.invertCameraXAxis,
"Invert horizontal camera movement.");
addOption("Invert Camera Y Axis", getSettings().game.invertCameraYAxis,
"Invert vertical camera movement when Free Camera is enabled.",
[] { return !getSettings().game.freeCamera; });
"Enables free camera control, letting you control the camera fully with the C-Stick.");
config_percent_select(leftPane, rightPane, getSettings().game.freeCameraXSensitivity,
"Free Camera X Sensitivity", "Adjusts twin-stick camera X axis sensitivity.", 50, 200, 5,
[] { return !getSettings().game.freeCamera; });
"Free Camera X Sensitivity",
"Adjusts horizontal free camera sensitivity.<br/><br/>Applies to the control stick only.",
50, 200, 5, [] { return !getSettings().game.freeCamera; });
config_percent_select(leftPane, rightPane, getSettings().game.freeCameraYSensitivity,
"Free Camera Y Sensitivity", "Adjusts twin-stick camera Y axis sensitivity.", 50, 200, 5,
"Free Camera Y Sensitivity",
"Adjusts vertical free camera sensitivity.<br/><br/>Applies to the control stick only.",
50, 200, 5, [] { return !getSettings().game.freeCamera; });
addOption("Invert Camera X Axis", getSettings().game.invertCameraXAxis,
"Invert horizontal camera movement.<br/><br/>Applies to the control stick only.");
addOption("Invert Camera Y Axis", getSettings().game.invertCameraYAxis,
"Invert vertical camera movement.<br/><br/>Applies to the control stick only.",
[] { return !getSettings().game.freeCamera; });
addOption("Invert First Person X Axis", getSettings().game.invertFirstPersonXAxis,
"Invert horizontal movement while aiming with items or first person camera. Applies only to the control stick (the gyroscope can be inverted in Input settings).");
"Invert horizontal movement while aiming with items or first person camera.<br/><br/>Applies to the control stick only.");
addOption("Invert First Person Y Axis", getSettings().game.invertFirstPersonYAxis,
"Invert vertical movement while aiming with items or first person camera. Applies only to the control stick (the gyroscope can be inverted in Input settings).");
addOption("Invert Air/Swim X Axis", getSettings().game.invertAirSwimX,
"Invert horizontal movement while flying or swimming.");
addOption("Invert Air/Swim Y Axis", getSettings().game.invertAirSwimY,
"Invert vertical movement while flying or swimming.");
"Invert vertical movement while aiming with items or first person camera.<br/><br/>Applies to the control stick only.");
leftPane.add_section("Gyro");
leftPane.register_control(
leftPane.add_select_button({
.key = "Gyro Input Method",
.getValue =
[] {
const auto mode = getSettings().game.gyroMode.getValue();
const auto idx = static_cast<size_t>(mode);
return Rml::String{kGyroInputModeLabels[idx]};
},
.isModified =
[] {
return getSettings().game.gyroMode.getValue() !=
getSettings().game.gyroMode.getDefaultValue();
},
}),
rightPane, [](Pane& pane) {
for (size_t i = 0; i < kGyroInputModeLabels.size(); i++) {
pane
.add_button({
.text = Rml::String{kGyroInputModeLabels[i]},
.isSelected =
[i] {
return getSettings().game.gyroMode.getValue() == static_cast<GyroMode>(i);
},
})
.on_pressed([i] {
mDoAud_seStartMenu(kSoundItemChange);
const GyroMode mode = static_cast<GyroMode>(i);
getSettings().game.gyroMode.setValue(mode);
config::Save();
});
}
pane.add_rml(
"<br/><b>Sensor</b> reads motion directly from a supported controller's gyro via SDL.<br/>"
"<br/><b>Mouse</b> treats mouse input as gyro, intended for use with the Steam Deck.<br/>"
"<br/>Mouse input cannot currently be used with Gyro Rollgoal.");
});
addOption("Gyro Aim", getSettings().game.enableGyroAim,
"Enables gyro controls while in look mode, aiming a hawk, and aiming "
"supported items.<br/><br/>Supported items include the Slingshot, Gale Boomerang, "
"Hero's Bow, Clawshot(s), Ball and Chain, and Dominion Rod.");
addOption("Gyro Rollgoal", getSettings().game.enableGyroRollgoal,
"Enables gyro controls for Rollgoal in Hena's Cabin.",
[] { return getSettings().game.gyroMode.getValue() == GyroMode::Mouse; });
"Enables gyro controls for Rollgoal in Hena's Cabin.");
config_percent_select(leftPane, rightPane, getSettings().game.gyroSensitivityY,
"Gyro Pitch Sensitivity", "Controls vertical gyro aiming sensitivity.", 25, 400, 5,
[] { return !gyro_enabled(); });
@@ -1025,10 +982,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
config_percent_select(leftPane, rightPane, getSettings().game.gyroSensitivityRollgoal,
"Rollgoal Sensitivity", "Controls how strongly gyro input tilts the Rollgoal table.",
25, 400, 5,
[] {
return !getSettings().game.enableGyroRollgoal ||
getSettings().game.gyroMode.getValue() == GyroMode::Mouse;
});
[] { return !getSettings().game.enableGyroRollgoal; });
config_percent_select(leftPane, rightPane, getSettings().game.gyroDeadband, "Gyro Deadband",
"Ignores small gyro movement to reduce drift and jitter.", 0, 50, 1,
[] { return !gyro_enabled(); });
@@ -1039,8 +993,29 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
"Invert vertical gyro aiming.", [] { return !gyro_enabled(); });
addOption("Invert Gyro Yaw", getSettings().game.gyroInvertYaw,
"Invert horizontal gyro aiming.", [] { return !gyro_enabled(); });
leftPane.add_section("Mouse");
addOption("Mouse Aim", getSettings().game.enableMouseAim,
"Enables mouse input while in look mode, aiming a hawk, and aiming "
"supported items.<br/><br/>Supported items include the Slingshot, Gale Boomerang, "
"Hero's Bow, Clawshot(s), Ball and Chain, and Dominion Rod.");
addOption("Mouse Camera", getSettings().game.enableMouseCamera,
"Enables mouse input for controlling the third-person camera.");
config_percent_select(leftPane, rightPane, getSettings().game.mouseAimSensitivity,
"Mouse Aim Sensitivity", "Controls mouse aim sensitivity.", 25, 400, 5,
[] { return !getSettings().game.enableMouseAim; });
config_percent_select(leftPane, rightPane, getSettings().game.mouseCameraSensitivity,
"Mouse Camera Sensitivity", "Controls mouse camera sensitivity.", 25, 400, 5,
[] { return !getSettings().game.enableMouseCamera; });
addOption("Invert Mouse Y", getSettings().game.invertMouseY,
"Invert vertical mouse control for both aiming and camera.",
[] { return !getSettings().game.enableMouseAim || !getSettings().game.enableMouseCamera; });
leftPane.add_section("Gameplay");
addOption("Invert Air/Swim X Axis", getSettings().game.invertAirSwimX,
"Invert horizontal movement while flying or swimming.");
addOption("Invert Air/Swim Y Axis", getSettings().game.invertAirSwimY,
"Invert vertical movement while flying or swimming.");
addOption("Swap Direct Select Input", getSettings().game.swapDirectSelect,
"Swap the controls for using Direct Select on the item wheel, making Direct Select the default and holding L to scroll the wheel.");
@@ -1138,6 +1113,11 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
addOption("Minimal HUD", getSettings().game.minimalHUD,
"Disables the elements of the main HUD of the game.<br/>Useful for a more immersive "
"experience.");
config_percent_select(leftPane, rightPane, getSettings().game.hudScale,
"HUD Scale",
"Scales the size of the gameplay HUD (hearts, buttons, mini-map, etc.). Does not affect dialog boxes or menus.",
50, 200, 5,
[] { return getSettings().game.minimalHUD.getValue(); });
addOption("Restore Wii 1.0 Glitches", getSettings().game.restoreWiiGlitches,
"Restores patched glitches from Wii USA 1.0, the first released version.");
addOption("Enable Rotating Link Doll", getSettings().game.enableLinkDollRotation,
@@ -1198,6 +1178,8 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
"Link will not recoil when his sword hits walls.");
addOption("No 2nd Fish for Cat", getSettings().game.no2ndFishForCat,
"Skip needing to catch a second fish for Sera's cat.");
addOption("Button Fishing", getSettings().game.buttonFishing,
"Allow fishing with the Fishing Rod using the button the item is assigned to.");
addOption("Show Poe Count on Map", getSettings().game.enhancedMapMenus,
"Displays collected/total number of Poe Souls for a region on the map.");
addSpeedrunDisabledOption("Sun's Song (R+X)", getSettings().game.sunsSong,
+11
View File
@@ -36,9 +36,20 @@ static int fopCam_Execute(camera_class* i_this) {
fapGm_HIO_c::startCpuTimer();
#endif
#if TARGET_PC
if (dusk::getSettings().game.debugFlyCam && dusk::getSettings().game.debugFlyCamLockEvents) {
dScnPly_c::setPauseTimer(1);
ret = fpcMtd_Execute((process_method_class*)i_this->submethod, i_this);
} else {
if (!dComIfGp_isPauseFlag() && !dScnPly_c::isPause()) {
ret = fpcMtd_Execute((process_method_class*)i_this->submethod, i_this);
}
}
#else
if (!dComIfGp_isPauseFlag() && !dScnPly_c::isPause()) {
ret = fpcMtd_Execute((process_method_class*)i_this->submethod, i_this);
}
#endif
#if DEBUG
fapGm_HIO_c::stopCpuTimer("カメラ(計算処理)"); // Camera (computational processing)
+10
View File
@@ -2369,6 +2369,7 @@ static u8 l_matDL[132] ATTRIBUTE_ALIGN(32) = {
};
void mDoExt_3DlineMat0_c::setMaterial() {
ZoneScoped;
j3dSys.reinitGX();
GXSetNumIndStages(0);
dKy_setLight_again();
@@ -2384,6 +2385,7 @@ void mDoExt_3DlineMat0_c::setMaterial() {
}
void mDoExt_3DlineMat0_c::draw() {
ZoneScoped;
GXSetTevColor(GX_TEVREG2, field_0x8);
if (field_0xc != NULL) {
@@ -2692,6 +2694,7 @@ static u8 l_mat1DL[141] ATTRIBUTE_ALIGN(32) = {
};
void mDoExt_3DlineMat1_c::setMaterial() {
ZoneScoped;
j3dSys.reinitGX();
GXSetNumIndStages(0);
dKy_setLight_again();
@@ -2709,6 +2712,7 @@ void mDoExt_3DlineMat1_c::setMaterial() {
}
void mDoExt_3DlineMat1_c::draw() {
ZoneScoped;
GXLoadTexObj(&mTextureObject, GX_TEXMAP0);
GXSetTexCoordScaleManually(GX_TEXCOORD0, 1, GXGetTexObjWidth(&mTextureObject), GXGetTexObjHeight(&mTextureObject));
GXSetTevColor(GX_TEVREG2, mColor);
@@ -2922,6 +2926,7 @@ void mDoExt_3DlineMat1_c::update(int param_0, f32 param_1, GXColor& param_2, u16
#endif
void mDoExt_3DlineMat2_c::setMaterial() {
ZoneScoped;
j3dSys.reinitGX();
GXSetNumIndStages(0);
GXClearVtxDesc();
@@ -3119,6 +3124,7 @@ mDoExt_cube8pPacket::mDoExt_cube8pPacket(cXyz* i_points, const GXColor& i_color)
}
void drawCube(MtxP mtx, cXyz* pos, const GXColor& color) {
ZoneScoped;
GXSETARRAY(GX_VA_POS, pos, sizeof(cXyz) * 8, sizeof(cXyz), true);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXClearVtxDesc();
@@ -3198,6 +3204,7 @@ mDoExt_quadPacket::mDoExt_quadPacket(cXyz* i_points, const GXColor& i_color, u8
}
void mDoExt_quadPacket::draw() {
ZoneScoped;
GXSETARRAY(GX_VA_POS, mPoints, sizeof(mPoints), sizeof(cXyz), true);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXClearVtxDesc();
@@ -3248,6 +3255,7 @@ mDoExt_trianglePacket::mDoExt_trianglePacket(cXyz* i_points, const GXColor& i_co
}
void mDoExt_trianglePacket::draw() {
ZoneScoped;
j3dSys.reinitGX();
GXSETARRAY(GX_VA_POS, mPoints, sizeof(mPoints), sizeof(cXyz), true);
@@ -3301,6 +3309,7 @@ mDoExt_linePacket::mDoExt_linePacket(cXyz& i_start, cXyz& i_end, const GXColor&
}
void mDoExt_linePacket::draw() {
ZoneScoped;
j3dSys.reinitGX();
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
@@ -3418,6 +3427,7 @@ mDoExt_pointPacket::mDoExt_pointPacket(cXyz& i_position, const GXColor& i_color,
}
void mDoExt_pointPacket::draw() {
ZoneScoped;
j3dSys.reinitGX();
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
+4 -1
View File
@@ -11,12 +11,15 @@
#include <types.h>
u32 mDoLib_setResTimgObj(ResTIMG const* i_img, TGXTexObj* o_texObj, u32 tlut_name,
GXTlutObj* o_tlutObj) {
TGXTlutObj* o_tlutObj) {
#ifdef TARGET_PC
o_texObj->reset();
#endif
if (i_img->indexTexture) {
JUT_ASSERT(44, o_tlutObj != NULL);
#ifdef TARGET_PC
o_tlutObj->reset();
#endif
GXInitTlutObj(o_tlutObj, (void*)((u8*)i_img + i_img->paletteOffset),
(GXTlutFmt)i_img->colorFormat, (u16)i_img->numColors);
GXInitTexObjCI(o_texObj, (void*)((u8*)i_img + i_img->imageOffset), i_img->width, i_img->height,
+7
View File
@@ -55,6 +55,7 @@
#include "dusk/frame_interpolation.h"
#include "dusk/game_clock.h"
#include "dusk/gyro.h"
#include "dusk/mouse.h"
#include "dusk/imgui/ImGuiConsole.hpp"
#include "dusk/imgui/ImGuiEngine.hpp"
#include "dusk/iso_validate.hpp"
@@ -169,6 +170,7 @@ bool launchUILoop() {
while (event != nullptr && event->type != AURORA_NONE) {
switch (event->type) {
case AURORA_SDL_EVENT:
dusk::mouse::handle_event(event->sdl);
dusk::ui::handle_event(event->sdl);
dusk::g_imguiConsole.HandleSDLEvent(event->sdl);
break;
@@ -247,12 +249,15 @@ void main01(void) {
goto eventsDone;
case AURORA_PAUSED:
dusk::audio::SetPaused(true);
dusk::mouse::onFocusLost();
break;
case AURORA_UNPAUSED:
dusk::audio::SetPaused(false);
dusk::game_clock::reset_frame_timer();
dusk::mouse::onFocusGained();
break;
case AURORA_SDL_EVENT:
dusk::mouse::handle_event(event->sdl);
dusk::ui::handle_event(event->sdl);
dusk::g_imguiConsole.HandleSDLEvent(event->sdl);
break;
@@ -289,6 +294,7 @@ void main01(void) {
for (int sim_tick = 0; sim_tick < pacing.sim_ticks_to_run; ++sim_tick) {
dusk::frame_interp::begin_sim_tick();
mDoCPd_c::read();
dusk::mouse::read();
dusk::gyro::read(pacing.sim_pace);
fapGm_Execute();
mDoAud_Execute();
@@ -311,6 +317,7 @@ void main01(void) {
// Game Inputs
mDoCPd_c::read();
dusk::mouse::read();
dusk::gyro::read(pacing.presentation_dt_seconds);
// EXECUTE GAME LOGIC & RENDER