Compare commits

..

1 Commits

Author SHA1 Message Date
Luke Street b247eaa5d3 (Temp) Disable map scale 2026-06-08 22:49:58 -06:00
114 changed files with 921 additions and 9835 deletions
+2 -2
View File
@@ -291,13 +291,13 @@ message(STATUS "dusklight: Fetching cxxopts")
FetchContent_Declare(cxxopts FetchContent_Declare(cxxopts
URL https://github.com/jarro2783/cxxopts/archive/refs/tags/v3.3.1.tar.gz URL https://github.com/jarro2783/cxxopts/archive/refs/tags/v3.3.1.tar.gz
URL_HASH SHA256=3bfc70542c521d4b55a46429d808178916a579b28d048bd8c727ee76c39e2072 URL_HASH SHA256=3bfc70542c521d4b55a46429d808178916a579b28d048bd8c727ee76c39e2072
DOWNLOAD_EXTRACT_TIMESTAMP FALSE DOWNLOAD_EXTRACT_TIMESTAMP TRUE
) )
message(STATUS "dusklight: Fetching nlohmann/json") message(STATUS "dusklight: Fetching nlohmann/json")
FetchContent_Declare(json FetchContent_Declare(json
URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz
URL_HASH SHA256=42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa URL_HASH SHA256=42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa
DOWNLOAD_EXTRACT_TIMESTAMP FALSE DOWNLOAD_EXTRACT_TIMESTAMP TRUE
) )
FetchContent_MakeAvailable(cxxopts json) FetchContent_MakeAvailable(cxxopts json)
+1 -5
View File
@@ -158,11 +158,7 @@
"cacheVariables": { "cacheVariables": {
"CMAKE_C_COMPILER": "cl", "CMAKE_C_COMPILER": "cl",
"CMAKE_CXX_COMPILER": "cl", "CMAKE_CXX_COMPILER": "cl",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install", "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
}
}, },
"vendor": { "vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": { "microsoft.com/VisualStudioSettings/CMake/1.0": {
+18 -4
View File
@@ -20,17 +20,31 @@ It aims to be as accurate as possible to the original while also providing new o
> Dusklight does *not* provide any copyrighted assets. You must provide your own copy of the original game. > Dusklight does *not* provide any copyrighted assets. You must provide your own copy of the original game.
> [!IMPORTANT] > [!IMPORTANT]
> At a minimum, Dusklight requires a GPU with support for D3D12, Vulkan 1.1+, or Metal. For older devices, best-effort support is provided for D3D11 and OpenGL ES (Android), but will not achieve full accuracy or performance. Your experience with specific hardware, operating systems, and drivers may vary. > At a minimum, Dusklight requires a GPU with support for either D3D12, Vulkan, or Metal. Your experience with specific hardware, operating systems, and drivers may vary. In particular, older Intel iGPUs have a high likelihood of incompatibility. We are also aware of a number of issues on devices with Adreno GPUs and are working to resolve them.
### 1. Dump your game ### 1. Dump your game
You must dump your own copy of the game. Please see [this article](https://wiki.dolphin-emu.org/index.php?title=Ripping_Games) for instructions. After dumping, you can use a program like [Dolphin](https://dolphin-emu.org/) or [nodtool](https://github.com/encounter/nod/releases) to convert the `.iso` to `.rvz` to save space. You must dump your own copy of the game, please see [this article](https://wiki.dolphin-emu.org/index.php?title=Ripping_Games) for instructions. After dumping, you can use a program like [Dolphin](https://dolphin-emu.org/) or [nodtool](https://github.com/encounter/nod/releases) to convert the `.iso` to a `.rvz` to save space.
Currently, only the GameCube USA and EUR releases are supported. Support for other versions of the game is planned in the future. Currently, only the GameCube USA and EUR releases are supported. Support for other versions of the game is planned in the future.
### 2. Install Dusklight ### 2. Download [Dusklight](https://github.com/TwilitRealm/dusklight/releases)
Visit the [official installation guide](https://twilitrealm.dev/install/) for full instructions. ### 3. Setup the game
**Windows / macOS / Linux**
- Extract the .zip file
- Launch Dusklight
- Press **Select Disc Image** and provide the path to your supported game dump
- Press **Play**!
**iOS**
- Follow the [iOS setup guide](docs/ios-install-altstore.md)
**Android**
- Install the Dusklight APK
- Launch Dusklight
- Press **Select Disc Image** and provide the path to your supported game dump
- Press **Play**!
# Building # Building
+1 -1
-16
View File
@@ -1418,11 +1418,7 @@ set(DUSK_FILES
include/dusk/scope_guard.hpp include/dusk/scope_guard.hpp
src/dusk/dvd_asset.cpp src/dusk/dvd_asset.cpp
src/d/actor/d_a_alink_dusk.cpp src/d/actor/d_a_alink_dusk.cpp
src/dusk/android_frame_rate.hpp
src/dusk/android_frame_rate.cpp
src/dusk/asserts.cpp src/dusk/asserts.cpp
src/dusk/batch.cpp
src/dusk/batch.hpp
src/dusk/config.cpp src/dusk/config.cpp
src/dusk/crash_handler.cpp src/dusk/crash_handler.cpp
src/dusk/crash_reporting.cpp src/dusk/crash_reporting.cpp
@@ -1436,8 +1432,6 @@ set(DUSK_FILES
src/dusk/game_clock.cpp src/dusk/game_clock.cpp
src/dusk/globals.cpp src/dusk/globals.cpp
src/dusk/gyro.cpp src/dusk/gyro.cpp
include/dusk/menu_pointer.h
src/dusk/menu_pointer.cpp
src/dusk/mouse.cpp src/dusk/mouse.cpp
src/dusk/gamepad_color.cpp src/dusk/gamepad_color.cpp
src/dusk/autosave.cpp src/dusk/autosave.cpp
@@ -1451,7 +1445,6 @@ set(DUSK_FILES
src/dusk/stubs.cpp src/dusk/stubs.cpp
include/dusk/texture_replacements.hpp include/dusk/texture_replacements.hpp
src/dusk/texture_replacements.cpp src/dusk/texture_replacements.cpp
src/dusk/touch_camera.cpp
src/dusk/update_check.cpp src/dusk/update_check.cpp
src/dusk/update_check.hpp src/dusk/update_check.hpp
#src/dusk/m_Do_ext_dusk.cpp #src/dusk/m_Do_ext_dusk.cpp
@@ -1481,7 +1474,6 @@ set(DUSK_FILES
src/dusk/ui/button.hpp src/dusk/ui/button.hpp
src/dusk/ui/component.cpp src/dusk/ui/component.cpp
src/dusk/ui/component.hpp src/dusk/ui/component.hpp
src/dusk/ui/controls.hpp
src/dusk/ui/controller_config.cpp src/dusk/ui/controller_config.cpp
src/dusk/ui/controller_config.hpp src/dusk/ui/controller_config.hpp
src/dusk/ui/document.cpp src/dusk/ui/document.cpp
@@ -1494,8 +1486,6 @@ set(DUSK_FILES
src/dusk/ui/graphics_tuner.hpp src/dusk/ui/graphics_tuner.hpp
src/dusk/ui/input.cpp src/dusk/ui/input.cpp
src/dusk/ui/input.hpp src/dusk/ui/input.hpp
src/dusk/ui/icon_provider.cpp
src/dusk/ui/icon_provider.hpp
src/dusk/ui/modal.cpp src/dusk/ui/modal.cpp
src/dusk/ui/modal.hpp src/dusk/ui/modal.hpp
src/dusk/ui/nav_types.hpp src/dusk/ui/nav_types.hpp
@@ -1521,12 +1511,6 @@ set(DUSK_FILES
src/dusk/ui/string_button.hpp src/dusk/ui/string_button.hpp
src/dusk/ui/tab_bar.cpp src/dusk/ui/tab_bar.cpp
src/dusk/ui/tab_bar.hpp src/dusk/ui/tab_bar.hpp
src/dusk/ui/touch_controls_common.cpp
src/dusk/ui/touch_controls_common.hpp
src/dusk/ui/touch_controls.cpp
src/dusk/ui/touch_controls.hpp
src/dusk/ui/touch_controls_editor.cpp
src/dusk/ui/touch_controls_editor.hpp
src/dusk/ui/ui.cpp src/dusk/ui/ui.cpp
src/dusk/ui/ui.hpp src/dusk/ui/ui.hpp
src/dusk/ui/warp.cpp src/dusk/ui/warp.cpp
+16 -22
View File
@@ -16,37 +16,37 @@
]; ];
forAllSystems = lib.genAttrs supportedSystems; forAllSystems = lib.genAttrs supportedSystems;
dawnVersion = "v20260618.032059"; dawnVersion = "v20260423.175430";
nodVersion = "v2.0.0-alpha.10"; nodVersion = "v2.0.0-alpha.8";
versionSuffix = "nix-" + (self.shortRev or self.dirtyShortRev or "dirty"); versionSuffix = "nix-" + (self.shortRev or self.dirtyShortRev or "dirty");
dawnInfo = { dawnInfo = {
"x86_64-linux" = { "x86_64-linux" = {
triple = "linux-x86_64"; triple = "linux-x86_64";
hash = "sha256-GFSd573b+VQx/VmFdNQgWDd0V9ayQlcw0Zuopke12ak="; hash = "sha256-HXfKTLHtMPwupnFnaflCARtXVPuS/0PoCePXidjE5xs=";
}; };
"aarch64-linux" = { "aarch64-linux" = {
triple = "linux-aarch64"; triple = "linux-aarch64";
hash = "sha256-ZaoP7BAjBMnfAv2/AMRi3FNH2ZtyqASCSFyU/oB2Mzg="; hash = "sha256-34yyFpfqBZUwoFXQ41F0AwAU78FaNihOSY0oriwn6B0=";
}; };
"aarch64-darwin" = { "aarch64-darwin" = {
triple = "darwin-arm64"; triple = "darwin-arm64";
hash = "sha256-HT+qtlLaSHyoXPrUcXgcTGa877X5YfzbxRD4bJb7i1Y="; hash = "sha256-eQnzrBp6gjiBek1VYQ9A5W13ClYWrDDKjIqv/7eNTR4=";
}; };
"x86_64-darwin" = { "x86_64-darwin" = {
triple = "darwin-x86_64"; triple = "darwin-x86_64";
hash = "sha256-cUNaCbA7rlKSukDVKGaVEVw0Zt1+mSbaHbmUCMvMVWc="; hash = "sha256-QGWiGdxiI9kci3NPXH6QFFirxn16851zB/w3jqhIBJ4=";
}; };
}; };
nodPrebuiltInfo = { nodPrebuiltInfo = {
"x86_64-linux" = { "x86_64-linux" = {
triple = "linux-x86_64"; triple = "linux-x86_64";
hash = "sha256-FVQWECVA2gWdc+n5OQ/Tvwn8z0qdgjSd1WlFt5HKOec="; hash = "sha256-mUqvLsbsqaZ+HAjMmHYPYO+MgtanGRTw7Gzn5uXR5rE=";
}; };
"aarch64-darwin" = { "aarch64-darwin" = {
triple = "macos-arm64"; triple = "macos-arm64";
hash = "sha256-8ZEejxksVgShNKUVRCBYaLOp9x/qOC9pAeVrElQUGUk="; hash = "sha256-UPy1ywCcv0K6VJOU3uUelJuUdBh3UNaPRlyP5LOBeDw=";
}; };
}; };
@@ -75,7 +75,7 @@
''; '';
dawn = pkgs.fetchzip { dawn = pkgs.fetchzip {
url = "https://github.com/encounter/dawn/releases/download/${dawnVersion}/dawn-${dawnInfo.${system}.triple}.tar.gz"; url = "https://github.com/encounter/dawn-build/releases/download/${dawnVersion}/dawn-${dawnInfo.${system}.triple}.tar.gz";
hash = dawnInfo.${system}.hash; hash = dawnInfo.${system}.hash;
stripRoot = false; stripRoot = false;
}; };
@@ -94,7 +94,7 @@
owner = "encounter"; owner = "encounter";
repo = "nod"; repo = "nod";
rev = nodVersion; rev = nodVersion;
hash = "sha256-r8qDlOVxv5iKiFjJQrcBuL9HVoOM3yEjRVnQIMqaICs="; hash = "sha256-+zrtVzjo0+X/6uMcNUn1+FaSR+jOhrcQSDNBFjw0NDs=";
}; };
patches = [ ./fix-cmake-paths.patch ]; patches = [ ./fix-cmake-paths.patch ];
cargoDeps = pkgs.rustPlatform.importCargoLock { cargoDeps = pkgs.rustPlatform.importCargoLock {
@@ -138,15 +138,15 @@
NOD_PREBUILT = nod; NOD_PREBUILT = nod;
CXXOPTS = pkgs.cxxopts.src; CXXOPTS = pkgs.cxxopts.src;
JSON = pkgs.nlohmann_json.src; JSON = pkgs.nlohmann_json.src;
XXHASH = pkgs.xxhash.src; XXHASH = pkgs.xxHash.src;
ZSTD = pkgs.zstd.src; ZSTD = pkgs.zstd.src;
FMT = pkgs.fetchzip { FMT = pkgs.fetchzip {
url = "https://github.com/fmtlib/fmt/archive/refs/tags/12.1.0.tar.gz"; url = "https://github.com/fmtlib/fmt/archive/refs/tags/11.1.4.tar.gz";
hash = "sha256-ZmI1Dv0ZabPlxa02OpERI47jp7zFfjpeWCy1WyuPYZ0="; hash = "sha256-sUbxlYi/Aupaox3JjWFqXIjcaQa0LFjclQAOleT+FRA=";
}; };
TRACY = pkgs.fetchzip { TRACY = pkgs.fetchzip {
url = "https://github.com/wolfpld/tracy/archive/6789e7d6f9a65ec98926b602097a33a9676d2606.tar.gz"; url = "https://github.com/wolfpld/tracy/archive/a64b9a20294d59421a2f57aeca3c6383d8c48169.tar.gz";
hash = "sha256-Xxyd7G/mnXEPpN+ehmwl0AkAhS3CwObpJNDgcqbdUJg="; hash = "sha256-hbNGOsGeyGSvCJ2No8RkwOib1lX2on3vNZSzyVkZdXw=";
}; };
IMGUI = pkgs.fetchFromGitHub { IMGUI = pkgs.fetchFromGitHub {
owner = "ocornut"; owner = "ocornut";
@@ -194,7 +194,7 @@
pkgs.zstd pkgs.zstd
pkgs.cxxopts pkgs.cxxopts
pkgs.nlohmann_json pkgs.nlohmann_json
pkgs.xxhash pkgs.xxHash
pkgs.abseil-cpp pkgs.abseil-cpp
pkgs.zlib pkgs.zlib
pkgs.libpng pkgs.libpng
@@ -269,12 +269,6 @@
runHook postInstall runHook postInstall
''; '';
postFixup = lib.optionalString (!isDarwin) ''
patchelf \
--add-needed "${pkgs.vulkan-loader}/lib/libvulkan.so" \
$out/bin/dusklight
'';
dontStrip = true; dontStrip = true;
meta = { meta = {
-1
View File
@@ -4556,7 +4556,6 @@ public:
void handleWolfHowl(); void handleWolfHowl();
void handleQuickTransform(); void handleQuickTransform();
bool checkAimContext(); bool checkAimContext();
bool checkAimInputContext();
void onIronBallChainInterpCallback(); void onIronBallChainInterpCallback();
+2 -7
View File
@@ -88,14 +88,9 @@ public:
/* 0x396A */ u8 field_0x396A[0x399E - 0x396A]; /* 0x396A */ u8 field_0x396A[0x399E - 0x396A];
/* 0x399E */ s16 field_0x399e; /* 0x399E */ s16 field_0x399e;
/* 0x39A0 */ u8 field_0x39A0[0x39A4 - 0x39A0]; /* 0x39A0 */ u8 field_0x39A0[0x39A4 - 0x39A0];
#if TARGET_PC
/* 0x39A4 */ cM_rnd_c mMantRng;
#endif
}; };
#if TARGET_PC
STATIC_ASSERT(sizeof(mant_class) == 0x39ac);
#else
STATIC_ASSERT(sizeof(mant_class) == 0x39a4); STATIC_ASSERT(sizeof(mant_class) == 0x39a4);
#endif
#endif /* D_A_MANT_H */ #endif /* D_A_MANT_H */
-10
View File
@@ -4,10 +4,6 @@
#include "JSystem/J3DGraphBase/J3DPacket.h" #include "JSystem/J3DGraphBase/J3DPacket.h"
#include "SSystem/SComponent/c_xyz.h" #include "SSystem/SComponent/c_xyz.h"
#if TARGET_PC
#include "dusk/batch.hpp"
#endif
class cCcD_Obj; class cCcD_Obj;
class dCcMassS_HitInf; class dCcMassS_HitInf;
class fopAc_ac_c; class fopAc_ac_c;
@@ -111,12 +107,6 @@ public:
#if TARGET_PC #if TARGET_PC
TGXTexObj mTexObj_l_J_Ohana00_64TEX; TGXTexObj mTexObj_l_J_Ohana00_64TEX;
TGXTexObj mTexObj_l_J_Ohana01_64128_0419TEX; TGXTexObj mTexObj_l_J_Ohana01_64128_0419TEX;
dusk::batch::LeafTemplate mTplHana00; // l_J_hana00DL
dusk::batch::LeafTemplate mTplHana00Cut; // l_J_hana00_cDL
dusk::batch::LeafTemplate mTplHana01; // l_J_hana01DL
dusk::batch::LeafTemplate mTplHana01Cut00; // l_J_hana01_c_00DL
dusk::batch::LeafTemplate mTplHana01Cut; // l_J_hana01_c_01DL
#endif #endif
}; // Size: 0x12A54 }; // Size: 0x12A54
-8
View File
@@ -4,10 +4,6 @@
#include "JSystem/J3DGraphBase/J3DPacket.h" #include "JSystem/J3DGraphBase/J3DPacket.h"
#include "SSystem/SComponent/c_xyz.h" #include "SSystem/SComponent/c_xyz.h"
#if TARGET_PC
#include "../../../src/dusk/batch.hpp"
#endif
class cCcD_Obj; class cCcD_Obj;
class csXyz; class csXyz;
class dCcMassS_HitInf; class dCcMassS_HitInf;
@@ -114,10 +110,6 @@ public:
#if TARGET_PC #if TARGET_PC
TGXTexObj mTexObj_l_M_Hijiki00TEX; TGXTexObj mTexObj_l_M_Hijiki00TEX;
TGXTexObj mTexObj_l_M_kusa05_RGBATEX; TGXTexObj mTexObj_l_M_kusa05_RGBATEX;
dusk::batch::LeafTemplate mTplKusa9q; // l_M_Kusa_9qDL
dusk::batch::LeafTemplate mTplKusa9qCut; // l_M_Kusa_9q_cDL
dusk::batch::LeafTemplate mTplTengusa; // l_M_TenGusaDL
#endif #endif
}; // Size: 0x1D718 }; // Size: 0x1D718
+1 -1
View File
@@ -1037,7 +1037,7 @@ public:
bool test1Camera(s32); bool test1Camera(s32);
bool test2Camera(s32); bool test2Camera(s32);
#if TARGET_PC #if TARGET_PC
static bool isAimActive(); static bool canUseFreeCam();
bool freeCamera(); bool freeCamera();
bool executeDebugFlyCam(); bool executeDebugFlyCam();
void deactivateDebugFlyCam(); void deactivateDebugFlyCam();
-13
View File
@@ -287,11 +287,6 @@ public:
MEMCARDCHECKPROC_ERR_YESNO_CURSOR_MOVE_ANM, MEMCARDCHECKPROC_ERR_YESNO_CURSOR_MOVE_ANM,
MEMCARDCHECKPROC_SAVEDATA_CLEAR, MEMCARDCHECKPROC_SAVEDATA_CLEAR,
#if TARGET_PC
MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE,
MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE_ERR_WAIT,
#endif
#if PLATFORM_WII || PLATFORM_SHIELD #if PLATFORM_WII || PLATFORM_SHIELD
MEMCARDCHECKPROC_NAND_STAT_CHECK, MEMCARDCHECKPROC_NAND_STAT_CHECK,
MEMCARDCHECKPROC_GAMEFILE_INIT_SEL, MEMCARDCHECKPROC_GAMEFILE_INIT_SEL,
@@ -416,10 +411,6 @@ public:
bool yesnoWakuAlpahAnm(u8); bool yesnoWakuAlpahAnm(u8);
#if TARGET_PC #if TARGET_PC
void fileSelectWide(); void fileSelectWide();
bool pointerDataSelect();
bool pointerMenuSelect();
bool pointerCopyDataToSelect();
bool pointerYesNoSelect(bool errorSelect);
#endif #endif
void _draw(); void _draw();
void errorMoveAnmInitSet(int, int); void errorMoveAnmInitSet(int, int);
@@ -454,10 +445,6 @@ public:
void MemCardMakeGameFile(); void MemCardMakeGameFile();
void MemCardMakeGameFileWait(); void MemCardMakeGameFileWait();
void MemCardMakeGameFileCheck(); void MemCardMakeGameFileCheck();
#if TARGET_PC
void MemCardAutoMakeGameFile();
void MemCardAutoMakeGameFileErrWait();
#endif
void MemCardMsgWindowInitOpen(); void MemCardMsgWindowInitOpen();
void MemCardMsgWindowOpen(); void MemCardMsgWindowOpen();
void MemCardMsgWindowClose(); void MemCardMsgWindowClose();
-3
View File
@@ -157,9 +157,6 @@ public:
int getDispType() const; int getDispType() const;
void _move(f32, f32, int, f32); void _move(f32, f32, int, f32);
void _draw(); void _draw();
#if TARGET_PC
bool refreshTextureSize();
#endif
virtual ~dMap_c() { virtual ~dMap_c() {
#if DEBUG #if DEBUG
-2
View File
@@ -74,8 +74,6 @@ public:
#if TARGET_PC #if TARGET_PC
void menuCollectWide(); void menuCollectWide();
bool pointerWait();
void pointerActivateCurrent();
#endif #endif
void _create(); void _create();
-4
View File
@@ -51,10 +51,6 @@ public:
void setBButtonString(u16); void setBButtonString(u16);
void setHIO(bool); void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); } virtual void draw() { _draw(); }
virtual ~dMenu_Insect_c(); virtual ~dMenu_Insect_c();
-4
View File
@@ -55,10 +55,6 @@ public:
u8 getLetterNum(); u8 getLetterNum();
void setHIO(bool); void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); } virtual void draw() { _draw(); }
virtual ~dMenu_Letter_c(); virtual ~dMenu_Letter_c();
-3
View File
@@ -80,9 +80,6 @@ public:
void setBButtonString(u16); void setBButtonString(u16);
bool isRumbleSupported(); bool isRumbleSupported();
bool dpdMenuMove(); bool dpdMenuMove();
#if TARGET_PC
bool pointerConfirmSelect();
#endif
void paneResize(u64); void paneResize(u64);
void initialize(); void initialize();
void yesnoMenuMoveAnmInitSet(int, int); void yesnoMenuMoveAnmInitSet(int, int);
-4
View File
@@ -74,9 +74,6 @@ public:
void clacEllipsePlotAverage(int, f32, f32); void clacEllipsePlotAverage(int, f32, f32);
bool dpdMove(); bool dpdMove();
u8 openExplain(u8); u8 openExplain(u8);
#if TARGET_PC
bool pointerMove();
#endif
virtual void draw() { _draw(); } virtual void draw() { _draw(); }
virtual ~dMenu_Ring_c(); virtual ~dMenu_Ring_c();
@@ -218,7 +215,6 @@ private:
bool mCursorInterpPrevAngular; bool mCursorInterpPrevAngular;
bool mCursorInterpCurrAngular; bool mCursorInterpCurrAngular;
bool mCursorInterpInit; bool mCursorInterpInit;
bool mPointerTouchPressHoveredCurrent;
#endif #endif
}; };
-2
View File
@@ -266,8 +266,6 @@ public:
#if TARGET_PC #if TARGET_PC
void menuSaveWide(); void menuSaveWide();
bool pointerSaveSelect();
bool pointerYesNoSelect(bool errorSelect, u8 errParam = 0, u8 soundParam = 0);
#endif #endif
void _draw2(); void _draw2();
-4
View File
@@ -49,10 +49,6 @@ public:
u8 getSkillNum(); u8 getSkillNum();
void setHIO(bool); void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); } virtual void draw() { _draw(); }
virtual ~dMenu_Skill_c(); virtual ~dMenu_Skill_c();
-10
View File
@@ -360,12 +360,7 @@ inline void dMsgObject_demoMessageGroup() {
} }
inline bool dMsgObject_isTalkNowCheck() { inline bool dMsgObject_isTalkNowCheck() {
#if TARGET_PC
dMsgObject_c* msgObject = dMsgObject_getMsgObjectClass();
return msgObject != NULL && msgObject->getStatus() != 1;
#else
return dMsgObject_getMsgObjectClass()->getStatus() == 1 ? false : true; return dMsgObject_getMsgObjectClass()->getStatus() == 1 ? false : true;
#endif
} }
inline bool dMsgObject_isKillMessageFlag() { inline bool dMsgObject_isKillMessageFlag() {
@@ -502,12 +497,7 @@ inline void dMsgObject_onMsgSend() {
} }
inline bool dMsgObject_isFukidashiCheck() { inline bool dMsgObject_isFukidashiCheck() {
#if TARGET_PC
dMsgObject_c* msgObject = dMsgObject_getMsgObjectClass();
return msgObject != NULL && msgObject->getScrnDrawPtr() != NULL;
#else
return dMsgObject_getMsgObjectClass()->getScrnDrawPtr() == NULL ? false : true; return dMsgObject_getMsgObjectClass()->getScrnDrawPtr() == NULL ? false : true;
#endif
} }
inline void* dMsgObject_getTalkHeap() { inline void* dMsgObject_getTalkHeap() {
-4
View File
@@ -49,10 +49,6 @@ public:
void selectScale(); void selectScale();
void selectTrans(); void selectTrans();
void selectAnimeTransform(int); void selectAnimeTransform(int);
#if TARGET_PC
bool pointerMove();
bool consumePointerClick();
#endif
void setOffsetX(f32 i_offsetX) { mOffsetX = i_offsetX; } void setOffsetX(f32 i_offsetX) { mOffsetX = i_offsetX; }
bool isAnimeUpdate(int param_0) { return (field_0x114 & (u8)(1 << param_0)) ? TRUE : FALSE; } bool isAnimeUpdate(int param_0) { return (field_0x114 & (u8)(1 << param_0)) ? TRUE : FALSE; }
-8
View File
@@ -9,8 +9,6 @@ namespace dusk {
enum class ActionBinds { enum class ActionBinds {
FIRST_PERSON_CAMERA, FIRST_PERSON_CAMERA,
CALL_MIDNA, CALL_MIDNA,
OPEN_MAP_SCREEN,
TOGGLE_MINIMAP,
OPEN_DUSKLIGHT_MENU, OPEN_DUSKLIGHT_MENU,
TURBO_SPEED_BUTTON, TURBO_SPEED_BUTTON,
COUNT, COUNT,
@@ -34,12 +32,6 @@ bool isActionBound(ActionBinds action, u32 port);
void updateActionBindings(); void updateActionBindings();
void setVirtualActionBind(ActionBinds action, u32 port, bool pressed, bool available = true);
void clearVirtualActionBind(ActionBinds action, u32 port);
void clearAllVirtualActionBinds();
bool getActionBindTrig(ActionBinds action, u32 port); bool getActionBindTrig(ActionBinds action, u32 port);
bool getActionBindHold(ActionBinds action, u32 port); bool getActionBindHold(ActionBinds action, u32 port);
+2 -9
View File
@@ -4,7 +4,6 @@
#include "dolphin/types.h" #include "dolphin/types.h"
#include <type_traits> #include <type_traits>
#include <cstdlib> #include <cstdlib>
#include <limits>
#include <string> #include <string>
/** /**
@@ -140,16 +139,11 @@ concept ConfigValueInteger =
|| std::is_same_v<T, s64> || std::is_same_v<T, s64>
|| std::is_same_v<T, u64>; || std::is_same_v<T, u64>;
template <typename T>
struct ConfigValueTraits {
static constexpr bool enabled = false;
};
/** /**
* \brief Concept that defines the legal set of types that can be used for CVar values. * \brief Concept that defines the legal set of types that can be used for CVar values.
* *
* Valid types cannot be cv-qualified and must be basic primitive types (int, float, bool), * Valid types cannot be cv-qualified and must be basic primitive types (int, float, bool),
* strings, enums of the basic primitives, or explicitly-enabled structured settings. * strings, or enums of the basic primitives.
*/ */
template <typename T> template <typename T>
concept ConfigValue = concept ConfigValue =
@@ -160,8 +154,7 @@ concept ConfigValue =
|| std::is_same_v<T, f32> || std::is_same_v<T, f32>
|| std::is_same_v<T, f64> || std::is_same_v<T, f64>
|| std::is_same_v<T, std::string> || std::is_same_v<T, std::string>
|| (std::is_enum_v<T> && ConfigValueInteger<std::underlying_type_t<T>>) || (std::is_enum_v<T> && ConfigValueInteger<std::underlying_type_t<T>>));
|| ConfigValueTraits<T>::enabled);
template <ConfigValue T> template <ConfigValue T>
const ConfigImplBase* GetConfigImpl(); const ConfigImplBase* GetConfigImpl();
-65
View File
@@ -1,65 +0,0 @@
#pragma once
#include "dolphin/types.h"
class CPaneMgr;
namespace dusk::menu_pointer {
using TargetId = u16;
constexpr TargetId InvalidTarget = 0xffff;
enum class Context {
None,
FileSelect,
Save,
ItemWheel,
Collection,
Options,
Dialog,
};
enum class Phase {
Move,
Press,
Release,
Cancel,
};
struct State {
f32 x = 0.0f;
f32 y = 0.0f;
bool valid = false;
bool down = false;
bool pressed = false;
bool released = false;
bool clicked = false;
bool touch = false;
};
void begin_game_frame() noexcept;
void end_game_frame() noexcept;
void begin_context(Context context) noexcept;
bool handle_fallthrough_pointer(f32 x, f32 y, Phase phase, bool touch, s32 mouseButton = -1) noexcept;
bool active() noexcept;
bool enabled() noexcept;
bool mouse_capture_active() noexcept;
const State& state() noexcept;
void set_hover_target(TargetId target) noexcept;
bool consume_click() noexcept;
bool peek_click() noexcept;
void set_dialog_choice(u8 choice, bool clicked) noexcept;
bool get_dialog_choice(u8& choice) noexcept;
bool consume_dialog_click(u8& choice) noexcept;
void defer_activation(Context context, TargetId target) noexcept;
bool consume_deferred_activation(Context context, TargetId target) noexcept;
void clear_deferred_activation(Context context) noexcept;
u32 suppressed_pad_buttons(u32 port) noexcept;
void finish_pad_suppression_read(u32 port) noexcept;
bool hit_rect(f32 left, f32 top, f32 right, f32 bottom, f32 padding = 0.0f) noexcept;
bool hit_pane(CPaneMgr* pane, f32 padding = 0.0f) noexcept;
bool hit_pane(J2DPane* pane, f32 padding = 0.0f) noexcept;
} // namespace dusk::menu_pointer
+4 -4
View File
@@ -4,9 +4,9 @@
namespace dusk::mouse { namespace dusk::mouse {
void read(); void read();
void get_aim_deltas(float& out_yaw, float& out_pitch); void getAimDeltas(float& out_yaw, float& out_pitch);
void get_camera_deltas(float& out_yaw, float& out_pitch); void getCameraDeltas(float& out_yaw, float& out_pitch);
void handle_event(const SDL_Event& event) noexcept; void handle_event(const SDL_Event& event) noexcept;
void on_focus_lost(); void onFocusLost();
void on_focus_gained(); void onFocusGained();
} // namespace dusk::mouse } // namespace dusk::mouse
+17 -31
View File
@@ -1,9 +1,9 @@
#pragma once #ifndef DUSK_CONFIG_H
#define DUSK_CONFIG_H
#include <array> #include <array>
#include "dusk/config_var.hpp" #include "dusk/config_var.hpp"
#include "dusk/ui/controls.hpp"
namespace dusk { namespace dusk {
@@ -40,18 +40,17 @@ enum class DiscVerificationState : u8 {
HashMismatch, HashMismatch,
}; };
enum class GyroMode : u8 {
Sensor = 0,
Mouse = 1,
};
enum class FrameInterpMode : u8 { enum class FrameInterpMode : u8 {
Off = 0, Off = 0,
Capped = 1, Capped = 1,
Unlimited = 2, Unlimited = 2,
}; };
enum class TouchTargeting : u8 {
Hybrid = 0,
Hold = 1,
Switch = 2,
};
enum class MenuScaling : u8 { enum class MenuScaling : u8 {
GameCube = 0, GameCube = 0,
Wii = 1, Wii = 1,
@@ -98,15 +97,15 @@ struct ConfigEnumRange<DiscVerificationState> {
}; };
template <> template <>
struct ConfigEnumRange<FrameInterpMode> { struct ConfigEnumRange<GyroMode> {
static constexpr auto min = FrameInterpMode::Off; static constexpr auto min = GyroMode::Sensor;
static constexpr auto max = FrameInterpMode::Unlimited; static constexpr auto max = GyroMode::Mouse;
}; };
template <> template <>
struct ConfigEnumRange<TouchTargeting> { struct ConfigEnumRange<FrameInterpMode> {
static constexpr auto min = TouchTargeting::Hybrid; static constexpr auto min = FrameInterpMode::Off;
static constexpr auto max = TouchTargeting::Switch; static constexpr auto max = FrameInterpMode::Unlimited;
}; };
template <> template <>
@@ -120,11 +119,6 @@ struct ConfigEnumRange<MagicArmorMode> {
static constexpr auto min = MagicArmorMode::NORMAL; static constexpr auto min = MagicArmorMode::NORMAL;
static constexpr auto max = MagicArmorMode::COSMETIC; static constexpr auto max = MagicArmorMode::COSMETIC;
}; };
template <>
struct ConfigValueTraits<ui::ControlLayout> {
static constexpr bool enabled = true;
};
} // namespace config } // namespace config
// Persistent user settings // Persistent user settings
@@ -140,9 +134,6 @@ struct UserSettings {
ConfigVar<bool> enableFpsOverlay; ConfigVar<bool> enableFpsOverlay;
ConfigVar<int> fpsOverlayCorner; ConfigVar<int> fpsOverlayCorner;
ConfigVar<int> maxFrameRate; ConfigVar<int> maxFrameRate;
ConfigVar<bool> rememberWindowSize;
ConfigVar<int> lastWindowWidth;
ConfigVar<int> lastWindowHeight;
} video; } video;
struct { struct {
@@ -227,10 +218,6 @@ struct UserSettings {
ConfigVar<float> mouseCameraSensitivity; ConfigVar<float> mouseCameraSensitivity;
ConfigVar<bool> invertMouseY; ConfigVar<bool> invertMouseY;
ConfigVar<bool> freeCamera; ConfigVar<bool> freeCamera;
ConfigVar<bool> enableTouchControls;
ConfigVar<TouchTargeting> touchTargeting;
ConfigVar<bool> enableMenuPointer;
ConfigVar<ui::ControlLayout> touchControlsLayout;
ConfigVar<bool> invertCameraXAxis; ConfigVar<bool> invertCameraXAxis;
ConfigVar<bool> invertCameraYAxis; ConfigVar<bool> invertCameraYAxis;
ConfigVar<bool> invertFirstPersonXAxis; ConfigVar<bool> invertFirstPersonXAxis;
@@ -239,8 +226,6 @@ struct UserSettings {
ConfigVar<bool> invertAirSwimY; ConfigVar<bool> invertAirSwimY;
ConfigVar<float> freeCameraXSensitivity; ConfigVar<float> freeCameraXSensitivity;
ConfigVar<float> freeCameraYSensitivity; ConfigVar<float> freeCameraYSensitivity;
ConfigVar<float> touchCameraXSensitivity;
ConfigVar<float> touchCameraYSensitivity;
ConfigVar<bool> debugFlyCam; ConfigVar<bool> debugFlyCam;
ConfigVar<bool> debugFlyCamLockEvents; ConfigVar<bool> debugFlyCamLockEvents;
ConfigVar<bool> allowBackgroundInput; ConfigVar<bool> allowBackgroundInput;
@@ -288,6 +273,7 @@ struct UserSettings {
ConfigVar<DiscVerificationState> isoVerification; ConfigVar<DiscVerificationState> isoVerification;
ConfigVar<std::string> graphicsBackend; ConfigVar<std::string> graphicsBackend;
ConfigVar<bool> skipPreLaunchUI; ConfigVar<bool> skipPreLaunchUI;
ConfigVar<bool> showPipelineCompilation;
ConfigVar<bool> wasPresetChosen; ConfigVar<bool> wasPresetChosen;
ConfigVar<bool> checkForUpdates; ConfigVar<bool> checkForUpdates;
ConfigVar<int> cardFileType; ConfigVar<int> cardFileType;
@@ -298,8 +284,6 @@ struct UserSettings {
struct { struct {
std::array<ActionBindConfigVar, 4> firstPersonCamera; std::array<ActionBindConfigVar, 4> firstPersonCamera;
std::array<ActionBindConfigVar, 4> callMidna; std::array<ActionBindConfigVar, 4> callMidna;
std::array<ActionBindConfigVar, 4> openMapScreen;
std::array<ActionBindConfigVar, 4> toggleMinimap;
std::array<ActionBindConfigVar, 4> openDusklightMenu; std::array<ActionBindConfigVar, 4> openDusklightMenu;
std::array<ActionBindConfigVar, 4> turboSpeedButton; std::array<ActionBindConfigVar, 4> turboSpeedButton;
} actionBindings; } actionBindings;
@@ -331,4 +315,6 @@ struct TransientSettings {
TransientSettings& getTransientSettings(); TransientSettings& getTransientSettings();
} // namespace dusk }
#endif // DUSK_CONFIG_H
-12
View File
@@ -1,12 +0,0 @@
#pragma once
namespace dusk::touch_camera {
constexpr float YAW_DEGREES_PER_DP = 0.34f;
constexpr float PITCH_DEGREES_PER_DP = 0.22f;
void add_delta(float yaw_dp, float pitch_dp) noexcept;
bool consume_delta(float& yaw_dp, float& pitch_dp) noexcept;
void clear() noexcept;
} // namespace dusk::touch_camera
@@ -212,9 +212,6 @@ public:
void setCornerColor(JUtility::TColor c0) { void setCornerColor(JUtility::TColor c0) {
setCornerColor(c0, c0, c0, c0); setCornerColor(c0, c0, c0, c0);
} }
#if TARGET_PC
JUtility::TColor corner(size_t index) const { return mCornerColor[index]; }
#endif
protected: protected:
/* 0x100 */ JUTTexture* mTexture[2]; /* 0x100 */ JUTTexture* mTexture[2];
@@ -3,20 +3,6 @@
#include <gx.h> #include <gx.h>
#if TARGET_PC
#include <mtx.h>
struct ParticleDrawCtx {
bool batch; // off = immediate mode
bool useTexMtx; // UVs transformed by texMtx
bool useClr0; // prm color in GX_VA_CLR0
bool useClr1; // env color in GX_VA_CLR1
Mtx texMtx;
GXColor clr0;
GXColor clr1;
};
#endif
struct JPAEmitterWorkData; struct JPAEmitterWorkData;
class JPABaseParticle; class JPABaseParticle;
class JKRHeap; class JKRHeap;
@@ -89,9 +75,6 @@ public:
const GXTevColorArg* getTevColorArg() const { return st_ca[(pBsd->mFlags >> 0x0F) & 0x07]; } const GXTevColorArg* getTevColorArg() const { return st_ca[(pBsd->mFlags >> 0x0F) & 0x07]; }
const GXTevAlphaArg* getTevAlphaArg() const { return st_aa[(pBsd->mFlags >> 0x12) & 0x01]; } const GXTevAlphaArg* getTevAlphaArg() const { return st_aa[(pBsd->mFlags >> 0x12) & 0x01]; }
#if TARGET_PC
u32 getTevColorArgSel() const { return (pBsd->mFlags >> 0x0F) & 0x07; }
#endif
u32 getType() const { return (pBsd->mFlags >> 0) & 0x0F; } u32 getType() const { return (pBsd->mFlags >> 0) & 0x0F; }
u32 getDirType() const { return (pBsd->mFlags >> 4) & 0x07; } u32 getDirType() const { return (pBsd->mFlags >> 4) & 0x07; }
@@ -203,34 +186,26 @@ void JPARegistPrm(JPAEmitterWorkData*);
void JPARegistEnv(JPAEmitterWorkData*); void JPARegistEnv(JPAEmitterWorkData*);
void JPARegistPrmEnv(JPAEmitterWorkData*); void JPARegistPrmEnv(JPAEmitterWorkData*);
#if TARGET_PC void JPADrawPoint(JPAEmitterWorkData*, JPABaseParticle*);
#define JPA_DRAW_PARTICLE_ARGS JPAEmitterWorkData*, JPABaseParticle*, ParticleDrawCtx* void JPADrawLine(JPAEmitterWorkData*, JPABaseParticle*);
#else void JPADrawRotBillboard(JPAEmitterWorkData*, JPABaseParticle*);
#define JPA_DRAW_PARTICLE_ARGS JPAEmitterWorkData*, JPABaseParticle* void JPADrawBillboard(JPAEmitterWorkData*, JPABaseParticle*);
#endif void JPADrawRotDirection(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawDirection(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawPoint(JPA_DRAW_PARTICLE_ARGS); void JPADrawRotation(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawLine(JPA_DRAW_PARTICLE_ARGS); void JPADrawDBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotBillboard(JPA_DRAW_PARTICLE_ARGS); void JPADrawRotYBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawBillboard(JPA_DRAW_PARTICLE_ARGS); void JPADrawYBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotDirection(JPA_DRAW_PARTICLE_ARGS); void JPADrawParticleCallBack(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawDirection(JPA_DRAW_PARTICLE_ARGS); void JPALoadTexAnm(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotation(JPA_DRAW_PARTICLE_ARGS); void JPASetPointSize(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawDBillboard(JPA_DRAW_PARTICLE_ARGS); void JPASetLineWidth(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotYBillboard(JPA_DRAW_PARTICLE_ARGS); void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawYBillboard(JPA_DRAW_PARTICLE_ARGS); void JPARegistAlpha(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawParticleCallBack(JPA_DRAW_PARTICLE_ARGS); void JPARegistEnv(JPAEmitterWorkData*, JPABaseParticle*);
void JPALoadTexAnm(JPA_DRAW_PARTICLE_ARGS); void JPARegistAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
void JPASetPointSize(JPA_DRAW_PARTICLE_ARGS); void JPARegistPrmAlpha(JPAEmitterWorkData*, JPABaseParticle*);
void JPASetLineWidth(JPA_DRAW_PARTICLE_ARGS); void JPARegistPrmAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
void JPALoadCalcTexCrdMtxAnm(JPA_DRAW_PARTICLE_ARGS);
void JPARegistAlpha(JPA_DRAW_PARTICLE_ARGS);
void JPARegistEnv(JPA_DRAW_PARTICLE_ARGS);
void JPARegistAlphaEnv(JPA_DRAW_PARTICLE_ARGS);
void JPARegistPrmAlpha(JPA_DRAW_PARTICLE_ARGS);
void JPARegistPrmAlphaEnv(JPA_DRAW_PARTICLE_ARGS);
#undef JPA_DRAW_PARTICLE_ARGS
#if TARGET_PC #if TARGET_PC
void JPAInterpBillboard(JPAEmitterWorkData*, JPABaseParticle*); void JPAInterpBillboard(JPAEmitterWorkData*, JPABaseParticle*);
@@ -17,10 +17,6 @@ class JPADynamicsBlock;
class JPAFieldBlock; class JPAFieldBlock;
class JPAKeyBlock; class JPAKeyBlock;
#if TARGET_PC
struct ParticleDrawCtx;
#endif
/** /**
* @ingroup jsystem-jparticle * @ingroup jsystem-jparticle
* *
@@ -54,19 +50,13 @@ public:
public: public:
typedef void (*EmitterFunc)(JPAEmitterWorkData*); typedef void (*EmitterFunc)(JPAEmitterWorkData*);
typedef void (*ParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*); typedef void (*ParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*);
#if TARGET_PC
typedef void (*DrawParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*,
ParticleDrawCtx*);
#else
typedef ParticleFunc DrawParticleFunc;
#endif
/* 0x00 */ EmitterFunc* mpCalcEmitterFuncList; /* 0x00 */ EmitterFunc* mpCalcEmitterFuncList;
/* 0x04 */ EmitterFunc* mpDrawEmitterFuncList; /* 0x04 */ EmitterFunc* mpDrawEmitterFuncList;
/* 0x08 */ EmitterFunc* mpDrawEmitterChildFuncList; /* 0x08 */ EmitterFunc* mpDrawEmitterChildFuncList;
/* 0x0C */ ParticleFunc* mpCalcParticleFuncList; /* 0x0C */ ParticleFunc* mpCalcParticleFuncList;
/* 0x10 */ DrawParticleFunc* mpDrawParticleFuncList; /* 0x10 */ ParticleFunc* mpDrawParticleFuncList;
/* 0x14 */ ParticleFunc* mpCalcParticleChildFuncList; /* 0x14 */ ParticleFunc* mpCalcParticleChildFuncList;
/* 0x18 */ DrawParticleFunc* mpDrawParticleChildFuncList; /* 0x18 */ ParticleFunc* mpDrawParticleChildFuncList;
/* 0x1C */ JPABaseShape* pBsp; /* 0x1C */ JPABaseShape* pBsp;
/* 0x20 */ JPAExtraShape* pEsp; /* 0x20 */ JPAExtraShape* pEsp;
@@ -87,20 +77,6 @@ public:
/* 0x45 */ u8 mpDrawParticleFuncListNum; /* 0x45 */ u8 mpDrawParticleFuncListNum;
/* 0x46 */ u8 mpCalcParticleChildFuncListNum; /* 0x46 */ u8 mpCalcParticleChildFuncListNum;
/* 0x47 */ u8 mpDrawParticleChildFuncListNum; /* 0x47 */ u8 mpDrawParticleChildFuncListNum;
#if TARGET_PC
struct BatchInfo {
f32 vtxPos[8][3];
f32 vtxUv[8][2];
u8 vtxCount; // 4 (quad) or 8 (cross)
bool supported; // draw func list contains only batchable funcs
bool hasPtclColor; // per-particle JPARegist* func is present
bool hasPtclTexMtx; // JPALoadCalcTexCrdMtxAnm is present
};
BatchInfo mBatchInfo;
void initBatchInfo();
#endif
}; };
#endif /* JPARESOURCE_H */ #endif /* JPARESOURCE_H */
+2 -2
View File
@@ -136,8 +136,8 @@ void J3DLoadCPCmd(u8 addr, u32 val) {
#if TARGET_PC #if TARGET_PC
static void J3DLoadArrayBasePtr(GXAttr attr, void* data, u32 size, bool le) { static void J3DLoadArrayBasePtr(GXAttr attr, void* data, u32 size, bool le) {
u32 idx = (attr == GX_VA_NBT) ? 1 : (attr - GX_VA_POS); u32 idx = (attr == GX_VA_NBT) ? 1 : (attr - GX_VA_POS);
GXCmd1u8(GX_AURORA); GXCmd1u8(GX_LOAD_AURORA);
GXCmd1u16(GX_AURORA_LOAD_ARRAYBASE | idx); GXCmd1u16(GX_LOAD_AURORA_ARRAYBASE | idx);
GXCmd1u64((u64)data); GXCmd1u64((u64)data);
GXCmd1u32(size); GXCmd1u32(size);
GXCmd1u8(le ? 1 : 0); GXCmd1u8(le ? 1 : 0);
+293 -55
View File
@@ -7,11 +7,265 @@
#include "JSystem/JKernel/JKRHeap.h" #include "JSystem/JKernel/JKRHeap.h"
#if TARGET_PC #if TARGET_PC
#include <aurora/dl.hpp> #include <algorithm>
#include <tracy/Tracy.hpp> #include <tracy/Tracy.hpp>
#include <vector>
#include "dusk/logging.h"
namespace { 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) { void set_display_list_copy(void*& displayList, u32& displayListSize, const u8* data, u32 size) {
const u32 alignedSize = ALIGN_NEXT(size, 0x20); const u32 alignedSize = ALIGN_NEXT(size, 0x20);
u8* newDL = JKR_NEW_ARRAY_ARGS(u8, alignedSize, 0x20); u8* newDL = JKR_NEW_ARRAY_ARGS(u8, alignedSize, 0x20);
@@ -35,11 +289,20 @@ u32 J3DShapeDraw::countVertex(u32 stride) {
u8* dlStart = (u8*)getDisplayList(); u8* dlStart = (u8*)getDisplayList();
#if TARGET_PC #if TARGET_PC
aurora::gx::dl::Reader reader{dlStart, getDisplayListSize(), static_cast<u8>(stride)}; for (u32 offset = 0; offset < getDisplayListSize();) {
while (const auto cmd = reader.next()) { u8 cmd = dlStart[offset];
if (cmd->kind != aurora::gx::dl::Command::Kind::Passthrough) { u8 opcode = cmd & GX_OPCODE_MASK;
count += cmd->draw.vtxCount; 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 #else
for (u8* dl = dlStart; (dl - dlStart) < getDisplayListSize();) { for (u8* dl = dlStart; (dl - dlStart) < getDisplayListSize();) {
@@ -57,53 +320,6 @@ u32 J3DShapeDraw::countVertex(u32 stride) {
return count; return count;
} }
#if TARGET_PC
void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
u32 byteNum = countVertex(stride);
u32 oldSize = mDisplayListSize;
u32 newSize = ALIGN_NEXT(oldSize + byteNum, 0x20);
u8* newDLStart = JKR_NEW_ARRAY_ARGS(u8, newSize, 0x20);
u8* oldDLStart = (u8*)mDisplayList;
u8* newDL = newDLStart;
aurora::gx::dl::Reader reader{oldDLStart, mDisplayListSize, static_cast<u8>(stride)};
while (const auto cmd = reader.next()) {
if (cmd->kind == aurora::gx::dl::Command::Kind::Passthrough) {
std::memcpy(newDL, cmd->data, cmd->size);
newDL += cmd->size;
continue;
}
const auto& draw = cmd->draw;
const u32 headerSize = draw.vertices - cmd->data;
std::memcpy(newDL, cmd->data, headerSize);
newDL += headerSize;
for (u32 i = 0; i < draw.vtxCount; i++) {
const u8* oldVtx = draw.vertices + stride * i;
u8 pnmtxidx = oldVtx[0];
std::memcpy(newDL, oldVtx, attrOffs);
newDL += attrOffs;
*newDL++ = valueBase + pnmtxidx;
std::memcpy(newDL, oldVtx + attrOffs, stride - attrOffs);
newDL += stride - attrOffs;
}
}
if (reader.failed()) {
// preserve the remainder untouched
std::memcpy(newDL, oldDLStart + reader.pos(), mDisplayListSize - reader.pos());
newDL += mDisplayListSize - reader.pos();
}
u32 realSize = ALIGN_NEXT((uintptr_t)newDL - (uintptr_t)newDLStart, 0x20);
for (; (newDL - newDLStart) < newSize; newDL++)
*newDL = 0;
mDisplayListSize = realSize;
mDisplayList = newDLStart;
DCStoreRange(newDLStart, mDisplayListSize);
}
#else
void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) { void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
u32 byteNum = countVertex(stride); u32 byteNum = countVertex(stride);
u32 oldSize = mDisplayListSize; u32 oldSize = mDisplayListSize;
@@ -114,13 +330,32 @@ void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
u8* newDL = newDLStart; u8* newDL = newDLStart;
for (; (oldDL - oldDLStart) < mDisplayListSize;) { 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 // Copy command
u8 cmd = *(u8*)oldDL; u8 cmd = *(u8*)oldDL;
oldDL++; oldDL++;
*newDL++ = cmd; *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) if (cmd != GX_TRIANGLEFAN && cmd != GX_TRIANGLESTRIP)
break; break;
#endif
// Copy count // Copy count
int vtxNum = *(u16*)oldDL; int vtxNum = *(u16*)oldDL;
@@ -149,7 +384,6 @@ void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
mDisplayList = newDLStart; mDisplayList = newDLStart;
DCStoreRange(newDLStart, mDisplayListSize); DCStoreRange(newDLStart, mDisplayListSize);
} }
#endif
J3DShapeDraw::J3DShapeDraw(const u8* displayList, u32 displayListSize) { J3DShapeDraw::J3DShapeDraw(const u8* displayList, u32 displayListSize) {
#if TARGET_PC #if TARGET_PC
@@ -163,8 +397,12 @@ J3DShapeDraw::J3DShapeDraw(const u8* displayList, u32 displayListSize) {
#if TARGET_PC #if TARGET_PC
J3DShapeDraw::J3DShapeDraw( J3DShapeDraw::J3DShapeDraw(
const u8* displayList, u32 displayListSize, const GXVtxDescList* vtxDesc) { const u8* displayList, u32 displayListSize, const GXVtxDescList* vtxDesc) {
if (const auto optimized = aurora::gx::dl::optimize(displayList, displayListSize, vtxDesc)) { u32 stride = 0;
set_display_list_copy(mDisplayList, mDisplayListSize, optimized->data(), optimized->size()); 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 { } else {
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize); set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
} }
+30 -269
View File
@@ -14,33 +14,6 @@
#endif #endif
#include "tracy/Tracy.hpp" #include "tracy/Tracy.hpp"
#if TARGET_PC
#define JPA_DRAW_CTX_PARAM , ParticleDrawCtx* ctx
namespace {
GXColor emitter_prm_color(JPAEmitterWorkData* work) {
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g);
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
return prm;
}
GXColor emitter_env_color(JPAEmitterWorkData* work) {
JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = emtr->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
return env;
}
} // namespace
#else
#define JPA_DRAW_CTX_PARAM
#endif
void JPASetPointSize(JPAEmitterWorkData* work) { void JPASetPointSize(JPAEmitterWorkData* work) {
GXSetPointSize((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE); GXSetPointSize((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
} }
@@ -49,16 +22,15 @@ void JPASetLineWidth(JPAEmitterWorkData* work) {
GXSetLineWidth((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE); GXSetLineWidth((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
} }
void JPASetPointSize(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPASetPointSize(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
GXSetPointSize((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE); GXSetPointSize((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
} }
void JPASetLineWidth(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPASetLineWidth(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
GXSetLineWidth((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE); GXSetLineWidth((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
} }
void JPARegistPrm(JPAEmitterWorkData* work) { void JPARegistPrm(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr; JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr; GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r); prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
@@ -69,7 +41,6 @@ void JPARegistPrm(JPAEmitterWorkData* work) {
} }
void JPARegistEnv(JPAEmitterWorkData* work) { void JPARegistEnv(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr; JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = emtr->mEnvClr; GXColor env = emtr->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r); env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
@@ -79,7 +50,6 @@ void JPARegistEnv(JPAEmitterWorkData* work) {
} }
void JPARegistPrmEnv(JPAEmitterWorkData* work) { void JPARegistPrmEnv(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr; JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr; GXColor prm = emtr->mPrmClr;
GXColor env = emtr->mEnvClr; GXColor env = emtr->mEnvClr;
@@ -94,8 +64,7 @@ void JPARegistPrmEnv(JPAEmitterWorkData* work) {
GXSetTevColor(GX_TEVREG1, env); GXSetTevColor(GX_TEVREG1, env);
} }
void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr; JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr; GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r); prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
@@ -103,19 +72,10 @@ void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b); prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a); prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm); prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
if (ctx->useClr1) {
ctx->clr1 = emitter_env_color(work);
}
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm); GXSetTevColor(GX_TEVREG0, prm);
} }
void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
ZoneScoped; ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr; JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = ptcl->mPrmClr; GXColor prm = ptcl->mPrmClr;
@@ -124,19 +84,10 @@ void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b); prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a); prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm); prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
if (ctx->useClr1) {
ctx->clr1 = emitter_env_color(work);
}
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm); GXSetTevColor(GX_TEVREG0, prm);
} }
void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
ZoneScoped; ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr; JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = ptcl->mPrmClr; GXColor prm = ptcl->mPrmClr;
@@ -149,19 +100,11 @@ void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DR
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r); env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g); env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b); env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm); GXSetTevColor(GX_TEVREG0, prm);
GXSetTevColor(GX_TEVREG1, env); GXSetTevColor(GX_TEVREG1, env);
} }
void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr; JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr; GXColor prm = emtr->mPrmClr;
GXColor env = ptcl->mEnvClr; GXColor env = ptcl->mEnvClr;
@@ -173,31 +116,16 @@ void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r); env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g); env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b); env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm); GXSetTevColor(GX_TEVREG0, prm);
GXSetTevColor(GX_TEVREG1, env); GXSetTevColor(GX_TEVREG1, env);
} }
void JPARegistEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPARegistEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr; JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = ptcl->mEnvClr; GXColor env = ptcl->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r); env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g); env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b); env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = emitter_prm_color(work);
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG1, env); GXSetTevColor(GX_TEVREG1, env);
} }
@@ -330,7 +258,7 @@ void JPAGenCalcTexCrdMtxAnm(JPAEmitterWorkData* work) {
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0); GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
} }
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) { void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
ZoneScoped; ZoneScoped;
JPABaseShape* shape = work->mpRes->getBsp(); JPABaseShape* shape = work->mpRes->getBsp();
f32 dVar16 = param_1->mAge; f32 dVar16 = param_1->mAge;
@@ -358,12 +286,6 @@ void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1
local_108[2][1] = 0.0f; local_108[2][1] = 0.0f;
local_108[2][2] = 1.0f; local_108[2][2] = 1.0f;
local_108[2][3] = 0.0f; local_108[2][3] = 0.0f;
#if TARGET_PC
if (ctx->batch) {
MTXCopy(local_108, ctx->texMtx);
return;
}
#endif
GXLoadTexMtxImm(local_108, 0x1e, GX_MTX2x4); GXLoadTexMtxImm(local_108, 0x1e, GX_MTX2x4);
} }
@@ -377,7 +299,7 @@ void JPALoadTexAnm(JPAEmitterWorkData* work) {
work->mpResMgr->load(work->mpRes->getTexIdx(work->mpEmtr->mTexAnmIdx), GX_TEXMAP0); work->mpResMgr->load(work->mpRes->getTexIdx(work->mpEmtr->mTexAnmIdx), GX_TEXMAP0);
} }
void JPALoadTexAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPALoadTexAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
ZoneScoped; ZoneScoped;
work->mpResMgr->load(work->mpRes->getTexIdx(ptcl->mTexAnmIdx), GX_TEXMAP0); work->mpResMgr->load(work->mpRes->getTexIdx(ptcl->mTexAnmIdx), GX_TEXMAP0);
} }
@@ -507,47 +429,6 @@ static projectionFunc p_prj[3] = {
}; };
#if TARGET_PC #if TARGET_PC
static void emit_batch_quad(JPAEmitterWorkData* work, const ParticleDrawCtx* ctx,
const Mtx posMtx) {
const JPAResource::BatchInfo& info = work->mpRes->mBatchInfo;
for (int i = 0; i < info.vtxCount; i++) {
Vec localPos = {info.vtxPos[i][0], info.vtxPos[i][1], info.vtxPos[i][2]};
Vec drawPos;
MTXMultVec(posMtx, &localPos, &drawPos);
f32 texS = info.vtxUv[i][0];
f32 texT = info.vtxUv[i][1];
if (ctx->useTexMtx) {
f32 srcS = texS;
f32 srcT = texT;
texS = ctx->texMtx[0][0] * srcS + ctx->texMtx[0][1] * srcT + ctx->texMtx[0][3];
texT = ctx->texMtx[1][0] * srcS + ctx->texMtx[1][1] * srcT + ctx->texMtx[1][3];
}
GXPosition3f32(drawPos.x, drawPos.y, drawPos.z);
if (ctx->useClr0) {
GXColor4u8(ctx->clr0.r, ctx->clr0.g, ctx->clr0.b, ctx->clr0.a);
}
if (ctx->useClr1) {
GXColor4u8(ctx->clr1.r, ctx->clr1.g, ctx->clr1.b, ctx->clr1.a);
}
GXTexCoord2f32(texS, texT);
}
}
static void submit_particle_quad(
JPAEmitterWorkData* work, ParticleDrawCtx* ctx, const Mtx posMtx, const u8* dl, u32 dlSize) {
if (ctx->batch) {
emit_batch_quad(work, ctx, posMtx);
return;
}
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(dl, dlSize);
}
void JPAInterpBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { void JPAInterpBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
Mtx ptclPosMtx; Mtx ptclPosMtx;
MTXTrans(ptclPosMtx, ptcl->mPosition.x, ptcl->mPosition.y, ptcl->mPosition.z); MTXTrans(ptclPosMtx, ptcl->mPosition.x, ptcl->mPosition.y, ptcl->mPosition.z);
@@ -567,7 +448,7 @@ void JPAInterpRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
} }
#endif #endif
void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) { if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return; return;
} }
@@ -592,16 +473,12 @@ void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_C
posMtx[2][2] = 1.0f; posMtx[2][2] = 1.0f;
posMtx[2][3] = pos.z; posMtx[2][3] = pos.z;
posMtx[0][1] = posMtx[0][2] = posMtx[1][0] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f; posMtx[0][1] = posMtx[0][2] = posMtx[1][0] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0); GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx); p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl)); GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
} }
void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) { if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return; return;
} }
@@ -640,16 +517,12 @@ void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRA
posMtx[2][2] = 1.0f; posMtx[2][2] = 1.0f;
posMtx[2][3] = pos.z; posMtx[2][3] = pos.z;
posMtx[0][2] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f; posMtx[0][2] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0); GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx); p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl)); GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
} }
void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) { void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) { if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return; return;
} }
@@ -669,16 +542,12 @@ void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DR
local_38[2][2] = work->mYBBCamMtx[2][2]; local_38[2][2] = work->mYBBCamMtx[2][2];
local_38[2][3] = local_48.z; local_38[2][3] = local_48.z;
local_38[0][1] = local_38[0][2] = local_38[1][0] = local_38[2][0] = 0.0f; local_38[0][1] = local_38[0][2] = local_38[1][0] = local_38[2][0] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, local_38, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(local_38, GX_PNMTX0); GXLoadPosMtxImm(local_38, GX_PNMTX0);
p_prj[work->mPrjType](work, local_38); p_prj[work->mPrjType](work, local_38);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl)); GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
} }
void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) { void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) { if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return; return;
} }
@@ -707,13 +576,9 @@ void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA
local_38[2][1] = local_94 * fVar1; local_38[2][1] = local_94 * fVar1;
local_38[2][2] = local_90; local_38[2][2] = local_90;
local_38[2][3] = local_48.z; local_38[2][3] = local_48.z;
#if TARGET_PC
submit_particle_quad(work, ctx, local_38, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(local_38, GX_PNMTX0); GXLoadPosMtxImm(local_38, GX_PNMTX0);
p_prj[work->mPrjType](work, local_38); p_prj[work->mPrjType](work, local_38);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl)); GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
} }
void dirTypeVel(JPAEmitterWorkData const* work, JPABaseParticle const* param_1, void dirTypeVel(JPAEmitterWorkData const* work, JPABaseParticle const* param_1,
@@ -876,88 +741,6 @@ static u8* p_dl[2] = {
}; };
#if TARGET_PC #if TARGET_PC
static bool make_direction_mtx(JPAEmitterWorkData* work, JPABaseParticle* ptcl, Mtx posMtx) {
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
JGeometry::TVec3<f32> baseAxis(ptcl->mBaseAxis);
p_direction[work->mDirType](work, ptcl, &axisY);
if (axisY.isZero()) {
return false;
}
axisY.normalize();
axisZ.cross(baseAxis, axisY);
if (axisZ.isZero()) {
return false;
}
axisZ.normalize();
baseAxis.cross(axisY, axisZ);
baseAxis.normalize();
ptcl->mBaseAxis.set(baseAxis);
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
posMtx[0][0] = baseAxis.x;
posMtx[0][1] = axisY.x;
posMtx[0][2] = axisZ.x;
posMtx[0][3] = ptcl->mPosition.x;
posMtx[1][0] = baseAxis.y;
posMtx[1][1] = axisY.y;
posMtx[1][2] = axisZ.y;
posMtx[1][3] = ptcl->mPosition.y;
posMtx[2][0] = baseAxis.z;
posMtx[2][1] = axisY.z;
posMtx[2][2] = axisZ.z;
posMtx[2][3] = ptcl->mPosition.z;
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
return true;
}
static bool make_rot_direction_mtx(JPAEmitterWorkData* work, JPABaseParticle* ptcl, Mtx posMtx) {
f32 sinRot = JMASSin(ptcl->mRotateAngle);
f32 cosRot = JMASCos(ptcl->mRotateAngle);
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
JGeometry::TVec3<f32> baseAxis(ptcl->mBaseAxis);
p_direction[work->mDirType](work, ptcl, &axisY);
if (axisY.isZero()) {
return false;
}
axisY.normalize();
axisZ.cross(baseAxis, axisY);
if (axisZ.isZero()) {
return false;
}
axisZ.normalize();
baseAxis.cross(axisY, axisZ);
baseAxis.normalize();
ptcl->mBaseAxis.set(baseAxis);
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
Mtx rotMtx;
Mtx dirMtx;
p_rot[work->mRotType](sinRot, cosRot, rotMtx);
p_plane[work->mPlaneType](rotMtx, scaleX, scaleY);
dirMtx[0][0] = baseAxis.x;
dirMtx[0][1] = axisY.x;
dirMtx[0][2] = axisZ.x;
dirMtx[0][3] = ptcl->mPosition.x;
dirMtx[1][0] = baseAxis.y;
dirMtx[1][1] = axisY.y;
dirMtx[1][2] = axisZ.y;
dirMtx[1][3] = ptcl->mPosition.y;
dirMtx[2][0] = baseAxis.z;
dirMtx[2][1] = axisY.z;
dirMtx[2][2] = axisZ.z;
dirMtx[2][3] = ptcl->mPosition.z;
MTXConcat(dirMtx, rotMtx, posMtx);
return true;
}
void JPAInterpDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { void JPAInterpDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
JGeometry::TVec3<f32> axisY; JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ; JGeometry::TVec3<f32> axisZ;
@@ -1040,7 +823,7 @@ void JPAInterpRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
} }
#endif #endif
void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) { if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return; return;
} }
@@ -1049,12 +832,8 @@ void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_C
Mtx posMtx; Mtx posMtx;
#if TARGET_PC #if TARGET_PC
if (!dusk::frame_interp::lookup_replacement(ptcl, posMtx) && if (!dusk::frame_interp::lookup_replacement(ptcl, posMtx))
!make_direction_mtx(work, ptcl, posMtx)) #endif
{
return;
}
#else
{ {
JGeometry::TVec3<f32> axisY; JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ; JGeometry::TVec3<f32> axisZ;
@@ -1090,19 +869,14 @@ void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_C
posMtx[2][3] = ptcl->mPosition.z; posMtx[2][3] = ptcl->mPosition.z;
p_plane[work->mPlaneType](posMtx, scaleX, scaleY); p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
} }
#endif
MTXConcat(work->mPosCamMtx, posMtx, posMtx); MTXConcat(work->mPosCamMtx, posMtx, posMtx);
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, p_dl[work->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0); GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx); p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl)); GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
#endif
} }
void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) { if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return; return;
} }
@@ -1112,12 +886,8 @@ void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRA
Mtx mtx1; Mtx mtx1;
Mtx mtx2; Mtx mtx2;
#if TARGET_PC #if TARGET_PC
if (!dusk::frame_interp::lookup_replacement(ptcl, mtx1) && if (!dusk::frame_interp::lookup_replacement(ptcl, mtx1))
!make_rot_direction_mtx(work, ptcl, mtx1)) #endif
{
return;
}
#else
{ {
f32 sinRot = JMASSin(ptcl->mRotateAngle); f32 sinRot = JMASSin(ptcl->mRotateAngle);
f32 cosRot = JMASCos(ptcl->mRotateAngle); f32 cosRot = JMASCos(ptcl->mRotateAngle);
@@ -1157,18 +927,13 @@ void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRA
mtx2[2][3] = ptcl->mPosition.z; mtx2[2][3] = ptcl->mPosition.z;
MTXConcat(mtx2, mtx1, mtx1); MTXConcat(mtx2, mtx1, mtx1);
} }
#endif
MTXConcat(work->mPosCamMtx, mtx1, mtx2); MTXConcat(work->mPosCamMtx, mtx1, mtx2);
#if TARGET_PC
submit_particle_quad(work, ctx, mtx2, p_dl[work->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(mtx2, GX_PNMTX0); GXLoadPosMtxImm(mtx2, GX_PNMTX0);
p_prj[work->mPrjType](work, mtx2); p_prj[work->mPrjType](work, mtx2);
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl)); GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
#endif
} }
void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) { void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) { if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return; return;
} }
@@ -1205,7 +970,7 @@ void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA
GXCallDisplayList(jpa_dl, sizeof(jpa_dl)); GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
} }
void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) { void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) { if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return; return;
} }
@@ -1223,16 +988,12 @@ void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_D
auStack_88[1][3] = param_1->mPosition.y; auStack_88[1][3] = param_1->mPosition.y;
auStack_88[2][3] = param_1->mPosition.z; auStack_88[2][3] = param_1->mPosition.z;
MTXConcat(param_0->mPosCamMtx, auStack_88, auStack_88); MTXConcat(param_0->mPosCamMtx, auStack_88, auStack_88);
#if TARGET_PC
submit_particle_quad(param_0, ctx, auStack_88, p_dl[param_0->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(auStack_88, 0); GXLoadPosMtxImm(auStack_88, 0);
p_prj[param_0->mPrjType](param_0, auStack_88); p_prj[param_0->mPrjType](param_0, auStack_88);
GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl)); GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl));
#endif
} }
void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) { if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return; return;
} }
@@ -1249,7 +1010,7 @@ void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_P
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8); GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
} }
void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) { void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) { if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return; return;
} }
@@ -1325,7 +1086,7 @@ void JPADrawStripe(JPAEmitterWorkData* param_0) {
GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1); GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd(); for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) { node = node_func(node), coord += step) {
param_0->mpCurNode = node; param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject(); JPABaseParticle* particle = node->getObject();
@@ -1350,7 +1111,7 @@ void JPADrawStripe(JPAEmitterWorkData* param_0) {
} }
particle->mBaseAxis.cross(local_f8, local_104); particle->mBaseAxis.cross(local_f8, local_104);
particle->mBaseAxis.normalize(); particle->mBaseAxis.normalize();
local_c8[0][0] = local_104.x; local_c8[0][0] = local_104.x;
local_c8[0][1] = local_f8.x; local_c8[0][1] = local_f8.x;
local_c8[0][2] = particle->mBaseAxis.x; local_c8[0][2] = particle->mBaseAxis.x;
@@ -1416,7 +1177,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1); GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd(); for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) { node = node_func(node), coord += step) {
param_0->mpCurNode = node; param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject(); JPABaseParticle* particle = node->getObject();
@@ -1441,7 +1202,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
} }
particle->mBaseAxis.cross(local_c0, local_cc); particle->mBaseAxis.cross(local_c0, local_cc);
particle->mBaseAxis.normalize(); particle->mBaseAxis.normalize();
local_90[0][0] = local_cc.x; local_90[0][0] = local_cc.x;
local_90[0][1] = local_c0.x; local_90[0][1] = local_c0.x;
local_90[0][2] = particle->mBaseAxis.x; local_90[0][2] = particle->mBaseAxis.x;
@@ -1466,7 +1227,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
coord = start_coord; coord = start_coord;
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1); GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd(); for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) { node = node_func(node), coord += step) {
param_0->mpCurNode = node; param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject(); JPABaseParticle* particle = node->getObject();
@@ -1491,7 +1252,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
} }
particle->mBaseAxis.cross(local_c0, local_cc); particle->mBaseAxis.cross(local_c0, local_cc);
particle->mBaseAxis.normalize(); particle->mBaseAxis.normalize();
local_90[0][0] = local_cc.x; local_90[0][0] = local_cc.x;
local_90[0][1] = local_c0.x; local_90[0][1] = local_c0.x;
local_90[0][2] = particle->mBaseAxis.x; local_90[0][2] = particle->mBaseAxis.x;
@@ -1528,7 +1289,7 @@ void JPADrawEmitterCallBackB(JPAEmitterWorkData* work) {
emtr->mpEmtrCallBack->draw(emtr); emtr->mpEmtrCallBack->draw(emtr);
} }
void JPADrawParticleCallBack(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) { void JPADrawParticleCallBack(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
JPABaseEmitter* emtr = work->mpEmtr; JPABaseEmitter* emtr = work->mpEmtr;
if (emtr->mpPtclCallBack == NULL) { if (emtr->mpPtclCallBack == NULL) {
return; return;
+6 -275
View File
@@ -18,21 +18,9 @@
#include "global.h" #include "global.h"
#include "tracy/Tracy.hpp" #include "tracy/Tracy.hpp"
#if TARGET_PC
#define JPA_DRAW_CTX_ARG , &ctx
#else
#define JPA_DRAW_CTX_ARG
#endif
JPAResource::JPAResource() { JPAResource::JPAResource() {
mpCalcEmitterFuncList = mpDrawEmitterFuncList = mpDrawEmitterChildFuncList = NULL; mpCalcEmitterFuncList = mpDrawEmitterFuncList = mpDrawEmitterChildFuncList = NULL;
#if TARGET_PC
mpCalcParticleFuncList = mpCalcParticleChildFuncList = NULL;
mpDrawParticleFuncList = mpDrawParticleChildFuncList = NULL;
mBatchInfo = {};
#else
mpCalcParticleFuncList = mpDrawParticleFuncList = mpCalcParticleChildFuncList = mpDrawParticleChildFuncList = NULL; mpCalcParticleFuncList = mpDrawParticleFuncList = mpCalcParticleChildFuncList = mpDrawParticleChildFuncList = NULL;
#endif
pBsp = NULL; pBsp = NULL;
pEsp = NULL; pEsp = NULL;
pCsp = NULL; pCsp = NULL;
@@ -73,60 +61,6 @@ static u8 jpa_crd[32] ATTRIBUTE_ALIGN(32) = {
0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02,
}; };
#if TARGET_PC
void JPAResource::initBatchInfo() {
mBatchInfo = {};
bool hasDrawFunc = false;
for (int i = 0; i < mpDrawParticleFuncListNum; i++) {
DrawParticleFunc func = mpDrawParticleFuncList[i];
if (func == JPADrawBillboard || func == JPADrawRotBillboard ||
func == JPADrawYBillboard || func == JPADrawRotYBillboard ||
func == JPADrawDirection || func == JPADrawRotDirection || func == JPADrawRotation)
{
hasDrawFunc = true;
} else if (func == JPADrawParticleCallBack) {
// Batchable only for emitters without a particle callback; checked per draw
} else if (func == JPALoadCalcTexCrdMtxAnm) {
mBatchInfo.hasPtclTexMtx = true;
} else if (func == JPARegistAlpha || func == JPARegistPrmAlpha ||
func == JPARegistPrmAlphaEnv || func == JPARegistAlphaEnv ||
func == static_cast<DrawParticleFunc>(JPARegistEnv)) // overloaded
{
mBatchInfo.hasPtclColor = true;
} else {
// JPADrawPoint, JPADrawLine, JPADrawDBillboard, JPALoadTexAnm,
// JPASetPointSize, JPASetLineWidth
return;
}
}
if (!hasDrawFunc) {
return;
}
// Template array offsets, same math as setPTev
int base_plane_type = (pBsp->getType() == 3 || pBsp->getType() == 7) ?
pBsp->getBasePlaneType() : 0;
int center_offset = pEsp != nullptr ? (pEsp->getScaleCenterX() + 3 * pEsp->getScaleCenterY()) * 0xC : 0x30;
const s8* pos = reinterpret_cast<const s8*>(jpa_pos) + center_offset + base_plane_type * 0x6C;
const s8* crd = reinterpret_cast<const s8*>(jpa_crd) + (pBsp->getTilingS() + 2 * pBsp->getTilingT()) * 8;
bool cross = pBsp->getType() == 4 || pBsp->getType() == 8;
mBatchInfo.vtxCount = cross ? 8 : 4;
for (int i = 0; i < mBatchInfo.vtxCount; i++) {
int posIdx = i < 4 ? i : 72 + (i - 4);
int crdIdx = i & 3;
mBatchInfo.vtxPos[i][0] = pos[posIdx * 3 + 0];
mBatchInfo.vtxPos[i][1] = pos[posIdx * 3 + 1];
mBatchInfo.vtxPos[i][2] = pos[posIdx * 3 + 2];
mBatchInfo.vtxUv[i][0] = crd[crdIdx * 2 + 0];
mBatchInfo.vtxUv[i][1] = crd[crdIdx * 2 + 1];
}
mBatchInfo.supported = true;
}
#endif
void JPAResource::init(JKRHeap* heap) { void JPAResource::init(JKRHeap* heap) {
BOOL is_glbl_clr_anm = pBsp->isGlblClrAnm(); BOOL is_glbl_clr_anm = pBsp->isGlblClrAnm();
BOOL is_glbl_tex_anm = pBsp->isGlblTexAnm(); BOOL is_glbl_tex_anm = pBsp->isGlblTexAnm();
@@ -591,10 +525,7 @@ void JPAResource::init(JKRHeap* heap) {
if (mpDrawParticleFuncListNum != 0) { if (mpDrawParticleFuncListNum != 0) {
mpDrawParticleFuncList = mpDrawParticleFuncList =
(DrawParticleFunc*)JKRAllocFromHeap( (ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleFuncListNum * sizeof(ParticleFunc), alignof(ParticleFunc));
heap,
mpDrawParticleFuncListNum * sizeof(DrawParticleFunc),
alignof(DrawParticleFunc));
} }
func_no = 0; func_no = 0;
@@ -704,10 +635,7 @@ void JPAResource::init(JKRHeap* heap) {
if (mpDrawParticleChildFuncListNum != 0) { if (mpDrawParticleChildFuncListNum != 0) {
mpDrawParticleChildFuncList = mpDrawParticleChildFuncList =
(DrawParticleFunc*)JKRAllocFromHeap( (ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleChildFuncListNum * sizeof(ParticleFunc), sizeof(EmitterFunc));
heap,
mpDrawParticleChildFuncListNum * sizeof(DrawParticleFunc),
alignof(DrawParticleFunc));
} }
func_no = 0; func_no = 0;
@@ -771,10 +699,6 @@ void JPAResource::init(JKRHeap* heap) {
mpDrawParticleChildFuncList[func_no] = &JPARegistPrmAlphaEnv; mpDrawParticleChildFuncList[func_no] = &JPARegistPrmAlphaEnv;
func_no++; func_no++;
} }
#if TARGET_PC
initBatchInfo();
#endif
} }
bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) { bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
@@ -884,183 +808,6 @@ void JPAResource::draw(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
} }
} }
#if TARGET_PC
static GXTevAlphaArg to_vtx_alpha_arg(GXTevAlphaArg arg) {
return arg == GX_CA_A0 ? GX_CA_RASA : arg;
}
static void batch_set_tev_op(GXTevStageID stage) {
GXSetTevColorOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
}
static void batch_setup_tev(JPAEmitterWorkData* work, bool useClr1) {
JPABaseShape* shape = work->mpRes->getBsp();
JPAExTexShape* ets = work->mpRes->getEts();
bool useIndirect = ets != nullptr && ets->isUseIndirect();
// JPAEmitterManager::draw configures both channels to pass vertex color through
GXSetNumChans(useClr1 ? 2 : 1);
const GXTevAlphaArg* alphaArg = shape->getTevAlphaArg();
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GXSetTevAlphaIn(GX_TEVSTAGE0, to_vtx_alpha_arg(alphaArg[0]), to_vtx_alpha_arg(alphaArg[1]),
to_vtx_alpha_arg(alphaArg[2]), to_vtx_alpha_arg(alphaArg[3]));
batch_set_tev_op(GX_TEVSTAGE0);
if (!useIndirect) {
GXSetTevDirect(GX_TEVSTAGE0);
}
GXTevStageID nextStage = GX_TEVSTAGE1;
switch (shape->getTevColorArgSel()) {
case 0: // TEXC
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_ONE, GX_CC_ZERO);
break;
case 1: // C0 * TEXC
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
break;
case 2: // lerp(C0, 1, TEXC)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO);
break;
case 3: // lerp(C1, C0, TEXC) = C0 * TEXC (stage 0) + C1 * (1 - TEXC) (stage 1)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
GXSetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR1A1);
GXSetTevColorIn(nextStage, GX_CC_RASC, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
break;
case 4: // TEXC * C0 + C1: C0 * TEXC (stage 0), + C1 (stage 1)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
GXSetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR1A1);
GXSetTevColorIn(nextStage, GX_CC_CPREV, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
break;
case 5: // C0
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
break;
}
if (ets != nullptr && ets->isUseSecTex()) {
// Mirrors setPTev's secondary texture stage, at the next free stage
GXTexCoordID texCoord = useIndirect ? GX_TEXCOORD2 : GX_TEXCOORD1;
GXSetTevOrder(nextStage, texCoord, GX_TEXMAP3, GX_COLOR_NULL);
GXSetTevColorIn(nextStage, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_ZERO);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
}
GXSetNumTevStages(nextStage);
}
static void batch_setup_vtx_desc(bool useClr0, bool useClr1) {
static Mtx identityMtx = {
{1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, 0.0f},
};
GXLoadPosMtxImm(identityMtx, GX_PNMTX0);
GXSetCurrentMtx(GX_PNMTX0);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
if (useClr0) {
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
}
if (useClr1) {
GXSetVtxDesc(GX_VA_CLR1, GX_DIRECT);
}
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
if (useClr0) {
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
}
if (useClr1) {
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0);
}
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
}
static void batch_restore_gx(JPAEmitterWorkData* work, bool changedTev, bool changedTexMtx) {
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSetCurrentMtx(GX_PNMTX0);
if (changedTexMtx) {
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
}
if (changedTev) {
GXSetNumChans(0);
work->mpRes->getBsp()->setGX(work);
work->mpRes->setPTev();
}
}
static bool draw_particle_batch(JPAEmitterWorkData* work) {
ZoneScoped;
JPAResource* res = work->mpRes;
const JPAResource::BatchInfo& info = res->mBatchInfo;
if (!info.supported || work->mPrjType != 0 || work->mpEmtr->mpPtclCallBack != nullptr) {
return false;
}
bool useClr0 = false;
bool useClr1 = false;
if (info.hasPtclColor) {
u32 colorSel = res->getBsp()->getTevColorArgSel();
if (colorSel >= 6) {
return false;
}
useClr0 = true;
useClr1 = colorSel == 3 || colorSel == 4;
batch_setup_tev(work, useClr1);
}
if (info.hasPtclTexMtx) {
// UVs are CPU-transformed; drop the texgen
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
}
batch_setup_vtx_desc(useClr0, useClr1);
ParticleDrawCtx ctx{};
ctx.batch = true;
ctx.useTexMtx = info.hasPtclTexMtx;
ctx.useClr0 = useClr0;
ctx.useClr1 = useClr1;
bool fwdAhead = res->getBsp()->isDrawFwdAhead();
JPANode<JPABaseParticle>* node = fwdAhead ? work->mpEmtr->mAlivePtclBase.getLast() :
work->mpEmtr->mAlivePtclBase.getFirst();
GXBegin(GX_QUADS, GX_VTXFMT1, GX_AUTO);
while (node != work->mpEmtr->mAlivePtclBase.getEnd()) {
work->mpCurNode = node;
for (int i = res->mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*res->mpDrawParticleFuncList[i])(work, node->getObject(), &ctx);
}
node = fwdAhead ? node->getPrev() : node->getNext();
}
GXEnd();
batch_restore_gx(work, useClr0, info.hasPtclTexMtx);
return true;
}
#endif
void JPAResource::drawP(JPAEmitterWorkData* work) { void JPAResource::drawP(JPAEmitterWorkData* work) {
ZoneScoped; ZoneScoped;
work->mpEmtr->clearStatus(0x80); work->mpEmtr->clearStatus(0x80);
@@ -1095,25 +842,13 @@ void JPAResource::drawP(JPAEmitterWorkData* work) {
(*mpDrawEmitterFuncList[i])(work); (*mpDrawEmitterFuncList[i])(work);
} }
#if TARGET_PC
if (draw_particle_batch(work)) {
GXSetMisc(GX_MT_XF_FLUSH, 0);
if (work->mpEmtr->mpEmtrCallBack != nullptr) {
work->mpEmtr->mpEmtrCallBack->drawAfter(work->mpEmtr);
}
return;
}
ParticleDrawCtx ctx{}; // immediate mode
#endif
if (pBsp->isDrawFwdAhead()) { if (pBsp->isDrawFwdAhead()) {
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclBase.getLast(); JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclBase.getLast();
for (; node != work->mpEmtr->mAlivePtclBase.getEnd(); node = node->getPrev()) { for (; node != work->mpEmtr->mAlivePtclBase.getEnd(); node = node->getPrev()) {
work->mpCurNode = node; work->mpCurNode = node;
if (mpDrawParticleFuncList != NULL) { if (mpDrawParticleFuncList != NULL) {
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) { for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG); (*mpDrawParticleFuncList[i])(work, node->getObject());
} }
} }
} }
@@ -1123,7 +858,7 @@ void JPAResource::drawP(JPAEmitterWorkData* work) {
work->mpCurNode = node; work->mpCurNode = node;
if (mpDrawParticleFuncList != NULL) { if (mpDrawParticleFuncList != NULL) {
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) { for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG); (*mpDrawParticleFuncList[i])(work, node->getObject());
} }
} }
} }
@@ -1170,17 +905,13 @@ void JPAResource::drawC(JPAEmitterWorkData* work) {
(*mpDrawEmitterChildFuncList[i])(work); (*mpDrawEmitterChildFuncList[i])(work);
} }
#if TARGET_PC
ParticleDrawCtx ctx{}; // immediate mode
#endif
if (pBsp->isDrawFwdAhead()) { if (pBsp->isDrawFwdAhead()) {
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclChld.getLast(); JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclChld.getLast();
for (; node != work->mpEmtr->mAlivePtclChld.getEnd(); node = node->getPrev()) { for (; node != work->mpEmtr->mAlivePtclChld.getEnd(); node = node->getPrev()) {
work->mpCurNode = node; work->mpCurNode = node;
if (mpDrawParticleChildFuncList != NULL) { if (mpDrawParticleChildFuncList != NULL) {
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) { for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleChildFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG); (*mpDrawParticleChildFuncList[i])(work, node->getObject());
} }
} }
} }
@@ -1190,7 +921,7 @@ void JPAResource::drawC(JPAEmitterWorkData* work) {
work->mpCurNode = node; work->mpCurNode = node;
if (mpDrawParticleChildFuncList != NULL) { if (mpDrawParticleChildFuncList != NULL) {
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) { for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleChildFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG); (*mpDrawParticleChildFuncList[i])(work, node->getObject());
} }
} }
} }
@@ -4,7 +4,6 @@ import android.app.ActionBar;
import android.app.Activity; import android.app.Activity;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.ClipData; import android.content.ClipData;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
@@ -15,16 +14,12 @@ import android.provider.DocumentsContract;
import android.provider.OpenableColumns; import android.provider.OpenableColumns;
import android.provider.Settings; import android.provider.Settings;
import android.util.Log; import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View; import android.view.View;
import android.view.Window; import android.view.Window;
import android.view.WindowInsets; import android.view.WindowInsets;
import android.view.WindowInsetsController; import android.view.WindowInsetsController;
import org.libsdl.app.SDLActivity; import org.libsdl.app.SDLActivity;
import org.libsdl.app.SDLSurface;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@@ -32,7 +27,6 @@ import java.util.List;
public class DuskActivity extends SDLActivity { public class DuskActivity extends SDLActivity {
private static final String TAG = "DuskActivity"; private static final String TAG = "DuskActivity";
private static final float DEFAULT_SURFACE_FRAME_RATE = 60.0f;
private static final int FOLDER_DIALOG_REQUEST_CODE = 0x4455; private static final int FOLDER_DIALOG_REQUEST_CODE = 0x4455;
private static final int MANAGE_STORAGE_REQUEST_CODE = 0x4456; private static final int MANAGE_STORAGE_REQUEST_CODE = 0x4456;
private static final String EXTERNAL_STORAGE_AUTHORITY = private static final String EXTERNAL_STORAGE_AUTHORITY =
@@ -94,11 +88,6 @@ public class DuskActivity extends SDLActivity {
hideSystemBars(); hideSystemBars();
} }
@Override
protected SDLSurface createSDLSurface(Context context) {
return new DuskSurface(context);
}
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
@@ -150,77 +139,6 @@ public class DuskActivity extends SDLActivity {
}; };
} }
public void setPreferredSurfaceFrameRate(float frameRate) {
runOnUiThread(() -> {
if (mSurface instanceof DuskSurface) {
((DuskSurface)mSurface).setPreferredFrameRate(frameRate);
}
});
}
private static final class DuskSurface extends SDLSurface {
private float preferredFrameRate = DEFAULT_SURFACE_FRAME_RATE;
DuskSurface(Context context) {
super(context);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.surfaceChanged(holder, format, width, height);
setTargetFrameRate(holder);
}
void setPreferredFrameRate(float frameRate) {
preferredFrameRate = frameRate;
setTargetFrameRate(getHolder());
}
private void setTargetFrameRate(SurfaceHolder holder) {
if (!mIsSurfaceReady || Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
return;
}
Surface surface = holder != null ? holder.getSurface() : getHolder().getSurface();
if (surface == null || !surface.isValid()) {
return;
}
float targetFrameRate = getMaxSupportedFrameRate();
if (preferredFrameRate > 0.0f) {
targetFrameRate = preferredFrameRate;
}
if (targetFrameRate <= 0.0f) {
return;
}
try {
surface.setFrameRate(
targetFrameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
Log.v(TAG, "Requested surface frame rate " + targetFrameRate + " fps");
} catch (RuntimeException e) {
Log.w(TAG, "Failed to request surface frame rate", e);
}
}
private float getMaxSupportedFrameRate() {
if (mDisplay == null) {
return 0.0f;
}
float maxFrameRate = mDisplay.getRefreshRate();
Display.Mode[] modes = mDisplay.getSupportedModes();
if (modes == null) {
return maxFrameRate;
}
for (Display.Mode mode : modes) {
maxFrameRate = Math.max(maxFrameRate, mode.getRefreshRate());
}
return maxFrameRate;
}
}
@Override @Override
protected String[] getArguments() { protected String[] getArguments() {
Intent intent = getIntent(); Intent intent = getIntent();
@@ -19,13 +19,9 @@ import android.os.*;
import java.lang.Runnable; import java.lang.Runnable;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDevice { class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDevice {
private static final String TAG = "hidapi"; private static final String TAG = "hidapi";
@@ -37,19 +33,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
private boolean mIsConnected = false; private boolean mIsConnected = false;
private boolean mIsChromebook = false; private boolean mIsChromebook = false;
private boolean mIsReconnecting = false; private boolean mIsReconnecting = false;
private boolean mHasEnabledNotifications = false;
private boolean mHasSeenInputUpdate = false;
private boolean mFrozen = false; private boolean mFrozen = false;
private LinkedList<GattOperation> mOperations; private LinkedList<GattOperation> mOperations;
GattOperation mCurrentOperation = null; GattOperation mCurrentOperation = null;
private Handler mHandler; private Handler mHandler;
private int mProductId = -1;
private int mReportId = 0;
private UUID mInputCharacteristic;
private static final int D0G_BLE2_PID = 0x1106;
private static final int TRITON_BLE_PID = 0x1303;
private static final int TRANSPORT_AUTO = 0; private static final int TRANSPORT_AUTO = 0;
private static final int TRANSPORT_BREDR = 1; private static final int TRANSPORT_BREDR = 1;
@@ -58,14 +45,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000; private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000;
static final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3"); static final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicD0G = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3"); static final UUID inputCharacteristic = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicTriton_0x45 = UUID.fromString("100F6C7A-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicTriton_0x47 = UUID.fromString("100F6C7C-1735-4313-B402-38567131E5F3");
static final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3"); static final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3");
static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 }; static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 };
private HashMap<Integer, BluetoothGattCharacteristic> mOutputReportChars = new HashMap<Integer, BluetoothGattCharacteristic>();
static class GattOperation { static class GattOperation {
private enum Operation { private enum Operation {
CHR_READ, CHR_READ,
@@ -78,7 +61,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
byte[] mValue; byte[] mValue;
BluetoothGatt mGatt; BluetoothGatt mGatt;
boolean mResult = true; boolean mResult = true;
int mDelayMs = 0;
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid) { private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid) {
mGatt = gatt; mGatt = gatt;
@@ -86,13 +68,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mUuid = uuid; mUuid = uuid;
} }
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, int delayMs) {
mGatt = gatt;
mOp = operation;
mUuid = uuid;
mDelayMs = delayMs;
}
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value) { private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value) {
mGatt = gatt; mGatt = gatt;
mOp = operation; mOp = operation;
@@ -100,14 +75,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mValue = value; mValue = value;
} }
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value, int delayMs) {
mGatt = gatt;
mOp = operation;
mUuid = uuid;
mValue = value;
mDelayMs = delayMs;
}
public void run() { public void run() {
// This is executed in main thread // This is executed in main thread
BluetoothGattCharacteristic chr; BluetoothGattCharacteristic chr;
@@ -169,8 +136,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
return mResult; return mResult;
} }
public int getDelayMs() { return mDelayMs; }
private BluetoothGattCharacteristic getCharacteristic(UUID uuid) { private BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
BluetoothGattService valveService = mGatt.getService(steamControllerService); BluetoothGattService valveService = mGatt.getService(steamControllerService);
if (valveService == null) if (valveService == null)
@@ -189,10 +154,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid) { static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid) {
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid); return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid);
} }
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid, int delayMs) {
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid, delayMs);
}
} }
HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) { HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) {
@@ -205,8 +166,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mHandler = new Handler(Looper.getMainLooper()); mHandler = new Handler(Looper.getMainLooper());
mGatt = connectGatt(); mGatt = connectGatt();
mHasEnabledNotifications = false;
mHasSeenInputUpdate = false;
// final HIDDeviceBLESteamController finalThis = this; // final HIDDeviceBLESteamController finalThis = this;
// mHandler.postDelayed(new Runnable() { // mHandler.postDelayed(new Runnable() {
// @Override // @Override
@@ -355,45 +314,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
Log.v(TAG, "Found Valve steam controller service " + service.getUuid()); Log.v(TAG, "Found Valve steam controller service " + service.getUuid());
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) { for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
if (chr.getUuid().equals(inputCharacteristicTriton_0x45)) { if (chr.getUuid().equals(inputCharacteristic)) {
Log.v(TAG, "Found Triton input characteristic 0x45"); Log.v(TAG, "Found input characteristic");
mProductId = TRITON_BLE_PID;
mReportId = 0x45;
mInputCharacteristic = chr.getUuid();
} else if (chr.getUuid().equals(inputCharacteristicTriton_0x47)) {
Log.v(TAG, "Found Triton input characteristic 0x47");
mProductId = TRITON_BLE_PID;
mReportId = 0x47;
mInputCharacteristic = chr.getUuid();
} else if (chr.getUuid().equals(inputCharacteristicD0G)) {
Log.v(TAG, "Found D0G input characteristic");
mProductId = D0G_BLE2_PID;
mReportId = 0x03;
mInputCharacteristic = chr.getUuid();
} else {
Pattern reportPattern = Pattern.compile("100F6C([0-9A-Z]{2})", Pattern.CASE_INSENSITIVE);
Matcher matcher = reportPattern.matcher(chr.getUuid().toString());
if (matcher.find()) {
try {
int reportId = Integer.parseInt(matcher.group(1), 16);
reportId -= 0x35;
if (reportId >= 0x80) {
// This is a Triton output report characteristic that we need to care about.
Log.v(TAG, "Found Triton output report 0x" + Integer.toString(reportId, 16));
mOutputReportChars.put(reportId, chr);
}
}
catch (NumberFormatException nfe) {
Log.w(TAG, "Could not parse report characteristic " + chr.getUuid().toString() + ": " + nfe.toString());
}
}
}
}
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
if (chr.getUuid().equals(mInputCharacteristic)) {
// Start notifications // Start notifications
BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")); BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
if (cccd != null) { if (cccd != null) {
@@ -450,30 +372,21 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mCurrentOperation = mOperations.removeFirst(); mCurrentOperation = mOperations.removeFirst();
} }
Runnable gattOperationRunnable = new Runnable() { // Run in main thread
@Override mHandler.post(new Runnable() {
public void run() { @Override
synchronized (mOperations) { public void run() {
if (mCurrentOperation == null) { synchronized (mOperations) {
Log.e(TAG, "Current operation null in executor?"); if (mCurrentOperation == null) {
return; Log.e(TAG, "Current operation null in executor?");
} return;
mCurrentOperation.run();
// now wait for the GATT callback and when it comes, finish this operation
} }
mCurrentOperation.run();
// now wait for the GATT callback and when it comes, finish this operation
} }
}; }
});
if (mCurrentOperation.getDelayMs() == 0) {
// Run in main thread
mHandler.post(gattOperationRunnable);
}
else {
// If we have a delay on this operation, wait before we post it.
mHandler.postDelayed(gattOperationRunnable, mCurrentOperation.getDelayMs());
}
} }
private void queueGattOperation(GattOperation op) { private void queueGattOperation(GattOperation op) {
@@ -484,39 +397,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
} }
private void enableNotification(UUID chrUuid) { private void enableNotification(UUID chrUuid) {
// Add a 500ms delay to notification write for Amazon Fire TV devices, as otherwise if we do this too quickly after connecting GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid);
// it will return success and then silently drop the operation on the floor.
GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid, 500);
queueGattOperation(op); queueGattOperation(op);
// Amazon Fire devices can also silently timeout on writeDescriptor, so
// set up a little delayed check that will attempt to write a second time.
//
// While this only seems to be needed on Amazon Fire TV devices at present, it
// doesn't hurt to have a retry on other devices as well.
//
final HIDDeviceBLESteamController finalThis = this;
final UUID finalUuid = chrUuid;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (!finalThis.mHasEnabledNotifications) {
if (finalThis.mHasSeenInputUpdate) {
// Amazon Five devices may have enabled notifications on the input characteristic and not given us a callback. If we've seen
// input reports, though, somewhat by definition notifications are enabled.
Log.w(TAG, "WriteDescriptor has never returned, but we've seen input reports. Moving on with controller initialization.");
finalThis.mHasEnabledNotifications = true;
finalThis.enableValveMode();
return;
}
// Give one more try.
GattOperation retry = HIDDeviceBLESteamController.GattOperation.enableNotification(finalThis.mGatt, finalUuid, 500);
finalThis.queueGattOperation(retry);
}
}
}, 1000);
} }
void writeCharacteristic(UUID uuid, byte[] value) { void writeCharacteristic(UUID uuid, byte[] value) {
@@ -566,16 +448,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mIsConnected = false; mIsConnected = false;
gatt.disconnect(); gatt.disconnect();
mGatt = connectGatt(false); mGatt = connectGatt(false);
} else { }
if (getProductId() == TRITON_BLE_PID) { else {
// Android will not properly play well with Data Length Extensions without manually requesting a large MTU,
// and Triton controllers require DLE support.
//
// 517 is basically a "magic number" as far as Android's bluetooth code is concerned, so do not change
// this value. It is functionally "please enable data length extensions" on some Android builds.
mGatt.requestMtu(517);
}
probeService(this); probeService(this);
} }
} }
@@ -600,7 +474,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
// Only register controller with the native side once it has been fully configured // Only register controller with the native side once it has been fully configured
if (!isRegistered()) { if (!isRegistered()) {
Log.v(TAG, "Registering Steam Controller with ID: " + getId()); Log.v(TAG, "Registering Steam Controller with ID: " + getId());
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId); mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true);
setRegistered(); setRegistered();
} }
} }
@@ -613,8 +487,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
// Enable this for verbose logging of controller input reports // Enable this for verbose logging of controller input reports
//Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue())); //Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue()));
if (characteristic.getUuid().equals(mInputCharacteristic) && !mFrozen) { if (characteristic.getUuid().equals(inputCharacteristic) && !mFrozen) {
mHasSeenInputUpdate = true;
mManager.HIDDeviceInputReport(getId(), characteristic.getValue()); mManager.HIDDeviceInputReport(getId(), characteristic.getValue());
} }
} }
@@ -624,36 +497,19 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
//Log.v(TAG, "onDescriptorRead status=" + status); //Log.v(TAG, "onDescriptorRead status=" + status);
} }
private void enableValveMode()
{
BluetoothGattService valveService = mGatt.getService(steamControllerService);
if (valveService == null)
return;
BluetoothGattCharacteristic reportChr = valveService.getCharacteristic(reportCharacteristic);
if (reportChr != null) {
if (getProductId() == TRITON_BLE_PID) {
// For Triton we just mark things registered.
Log.v(TAG, "Registering Triton Steam Controller with ID: " + getId());
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId);
setRegistered();
} else {
// For the original controller, we need to manually enter Valve mode.
Log.v(TAG, "Writing report characteristic to enter valve mode");
reportChr.setValue(enterValveMode);
mGatt.writeCharacteristic(reportChr);
}
}
}
@Override @Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
BluetoothGattCharacteristic chr = descriptor.getCharacteristic(); BluetoothGattCharacteristic chr = descriptor.getCharacteristic();
//Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid()); //Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid());
if (chr.getUuid().equals(mInputCharacteristic)) { if (chr.getUuid().equals(inputCharacteristic)) {
mHasEnabledNotifications = true; boolean hasWrittenInputDescriptor = true;
enableValveMode(); BluetoothGattCharacteristic reportChr = chr.getService().getCharacteristic(reportCharacteristic);
if (reportChr != null) {
Log.v(TAG, "Writing report characteristic to enter valve mode");
reportChr.setValue(enterValveMode);
gatt.writeCharacteristic(reportChr);
}
} }
finishCurrentGattOperation(); finishCurrentGattOperation();
@@ -692,20 +548,9 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
@Override @Override
public int getProductId() { public int getProductId() {
if (mProductId > 0) { // We don't have an easy way to query from the Bluetooth device, but we know what it is
// We've already set a product ID. final int D0G_BLE2_PID = 0x1106;
return mProductId; return D0G_BLE2_PID;
}
if (mDevice.getName().startsWith("Steam Ctrl")) {
// We're a newer Triton device
mProductId = TRITON_BLE_PID;
} else {
// We're an OG Steam Controller
mProductId = D0G_BLE2_PID;
}
return mProductId;
} }
@Override @Override
@@ -756,29 +601,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
writeCharacteristic(reportCharacteristic, actual_report); writeCharacteristic(reportCharacteristic, actual_report);
return report.length; return report.length;
} else { } else {
// If we're an original-recipe Steam Controller we just write to the characteristic directly. //Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report));
if (getProductId() == D0G_BLE2_PID) { writeCharacteristic(reportCharacteristic, report);
//Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report)); return report.length;
writeCharacteristic(reportCharacteristic, report);
return report.length;
}
// If we're a Triton, we need to find the correct report characteristic.
if (report.length > 0) {
int reportId = report[0] & 0xFF;
BluetoothGattCharacteristic targetedReportCharacteristic = mOutputReportChars.get(reportId);
if (targetedReportCharacteristic != null) {
byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1);
//Log.v(TAG, "writeOutputReport 0x" + Integer.toString(reportId, 16) + " " + HexDump.dumpHexString(report));
writeCharacteristic(targetedReportCharacteristic.getUuid(), actual_report);
return report.length;
} else {
Log.w(TAG, "Got report write request for unknown report type 0x" + Integer.toString(reportId, 16));
}
}
} }
return -1;
} }
@Override @Override
@@ -256,7 +256,6 @@ public class HIDDeviceManager {
0x24c6, // PowerA 0x24c6, // PowerA
0x2c22, // Qanba 0x2c22, // Qanba
0x2dc8, // 8BitDo 0x2dc8, // 8BitDo
0x3537, // GameSir
0x37d7, // Flydigi 0x37d7, // Flydigi
0x9886, // ASTRO Gaming 0x9886, // ASTRO Gaming
}; };
@@ -361,7 +360,7 @@ public class HIDDeviceManager {
HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index); HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index);
int id = device.getId(); int id = device.getId();
mDevicesById.put(id, device); mDevicesById.put(id, device);
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false, 0); HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false);
} }
} }
} }
@@ -530,13 +529,7 @@ public class HIDDeviceManager {
return false; return false;
} }
// Steam Controllers will always support Bluetooth Low Energy return bluetoothDevice.getName().equals("SteamController") && ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) != 0);
if ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) == 0) {
return false;
}
// Match on the name either the original Steam Controller or the new second-generation one advertise with.
return bluetoothDevice.getName().equals("SteamController") || bluetoothDevice.getName().startsWith("Steam Ctrl");
} }
private void close() { private void close() {
@@ -688,7 +681,7 @@ public class HIDDeviceManager {
private native void HIDDeviceRegisterCallback(); private native void HIDDeviceRegisterCallback();
private native void HIDDeviceReleaseCallback(); private native void HIDDeviceReleaseCallback();
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth, int reportID); native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth);
native void HIDDeviceOpenPending(int deviceID); native void HIDDeviceOpenPending(int deviceID);
native void HIDDeviceOpenResult(int deviceID, boolean opened); native void HIDDeviceOpenResult(int deviceID, boolean opened);
native void HIDDeviceDisconnected(int deviceID); native void HIDDeviceDisconnected(int deviceID);
@@ -21,7 +21,6 @@ class HIDDeviceUSB implements HIDDevice {
protected InputThread mInputThread; protected InputThread mInputThread;
protected boolean mRunning; protected boolean mRunning;
protected boolean mFrozen; protected boolean mFrozen;
protected boolean mClaimed;
public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) { public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) {
mManager = manager; mManager = manager;
@@ -30,7 +29,6 @@ class HIDDeviceUSB implements HIDDevice {
mInterface = mDevice.getInterface(mInterfaceIndex).getId(); mInterface = mDevice.getInterface(mInterfaceIndex).getId();
mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier()); mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier());
mRunning = false; mRunning = false;
mClaimed = false;
} }
String getIdentifier() { String getIdentifier() {
@@ -116,7 +114,6 @@ class HIDDeviceUSB implements HIDDevice {
close(); close();
return false; return false;
} }
mClaimed = true;
// Find the endpoints // Find the endpoints
for (int j = 0; j < iface.getEndpointCount(); j++) { for (int j = 0; j < iface.getEndpointCount(); j++) {
@@ -135,12 +132,9 @@ class HIDDeviceUSB implements HIDDevice {
} }
} }
// Make sure the required endpoints were present. The original Steam Controller and the wireless dongle for it do NOT // Make sure the required endpoints were present
// actually have -- or require -- output endpoints, so we need to accept only an input one for them or else we'll fall if (mInputEndpoint == null || mOutputEndpoint == null) {
// back to the Android system gamepad functionality (and lose our paddles et al).
if (mInputEndpoint == null) {
Log.w(TAG, "Missing required endpoint on USB device " + getDeviceName()); Log.w(TAG, "Missing required endpoint on USB device " + getDeviceName());
mConnection.releaseInterface(iface);
close(); close();
return false; return false;
} }
@@ -160,11 +154,6 @@ class HIDDeviceUSB implements HIDDevice {
return -1; return -1;
} }
if (!mClaimed) {
Log.w(TAG, "writeReport() called but some other process currently owns the USB device");
return -1;
}
if (feature) { if (feature) {
int res = -1; int res = -1;
int offset = 0; int offset = 0;
@@ -196,11 +185,6 @@ class HIDDeviceUSB implements HIDDevice {
} }
return length; return length;
} else { } else {
if (mOutputEndpoint == null)
{
Log.e(TAG, "Tried to write an output report to an interface with no output endpoint!");
return -1;
}
int res = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000); int res = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
if (res != report.length) { if (res != report.length) {
Log.w(TAG, "writeOutputReport() returned " + res + " on device " + getDeviceName()); Log.w(TAG, "writeOutputReport() returned " + res + " on device " + getDeviceName());
@@ -221,12 +205,6 @@ class HIDDeviceUSB implements HIDDevice {
Log.w(TAG, "readReport() called with no device connection"); Log.w(TAG, "readReport() called with no device connection");
return false; return false;
} }
if (!mClaimed) {
if (feature) {
return false;
}
return true;
}
if (report_number == 0x0) { if (report_number == 0x0) {
/* Offset the return buffer by 1, so that the report ID /* Offset the return buffer by 1, so that the report ID
@@ -280,13 +258,10 @@ class HIDDeviceUSB implements HIDDevice {
mInputThread = null; mInputThread = null;
} }
if (mConnection != null) { if (mConnection != null) {
if (mClaimed) { UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
UsbInterface iface = mDevice.getInterface(mInterfaceIndex); mConnection.releaseInterface(iface);
mConnection.releaseInterface(iface);
}
mConnection.close(); mConnection.close();
mConnection = null; mConnection = null;
mClaimed = false;
} }
} }
@@ -299,22 +274,6 @@ class HIDDeviceUSB implements HIDDevice {
@Override @Override
public void setFrozen(boolean frozen) { public void setFrozen(boolean frozen) {
mFrozen = frozen; mFrozen = frozen;
/* If we have a valid device connection and the claim state doesn't match what we want, try to correct that. */
if (mConnection != null && mClaimed == mFrozen) {
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
if (frozen) {
mClaimed = !mConnection.releaseInterface(iface);
if (mClaimed) {
Log.e(TAG, "Tried to release claim on USB device, but failed!");
}
} else {
mClaimed = mConnection.claimInterface(iface, true);
if (!mClaimed) {
Log.e(TAG, "Tried to regain claim on USB device, but failed!");
}
}
}
} }
protected class InputThread extends Thread { protected class InputThread extends Thread {
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
private static final String TAG = "SDL"; private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 3; private static final int SDL_MAJOR_VERSION = 3;
private static final int SDL_MINOR_VERSION = 4; private static final int SDL_MINOR_VERSION = 4;
private static final int SDL_MICRO_VERSION = 10; private static final int SDL_MICRO_VERSION = 8;
/* /*
// Display InputType.SOURCE/CLASS of events and devices // Display InputType.SOURCE/CLASS of events and devices
// //
@@ -530,8 +530,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (mHIDDeviceManager != null) { if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(true); mHIDDeviceManager.setFrozen(true);
} }
if (!mHasMultiWindow) { if (!mHasMultiWindow) {
pauseNativeThread(); pauseNativeThread();
} }
@@ -544,8 +543,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (mHIDDeviceManager != null) { if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(false); mHIDDeviceManager.setFrozen(false);
} }
if (!mHasMultiWindow) { if (!mHasMultiWindow) {
resumeNativeThread(); resumeNativeThread();
} }
@@ -618,14 +616,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
super.onWindowFocusChanged(hasFocus); super.onWindowFocusChanged(hasFocus);
Log.v(TAG, "onWindowFocusChanged(): " + hasFocus); Log.v(TAG, "onWindowFocusChanged(): " + hasFocus);
// If we are gaining focus, we can always try to restore our USB devices. If we are losing focus,
// only try to relinquish them if we don't have background events allowed (for multi-window Android setups).
if (hasFocus || !SDLActivity.nativeGetHintBoolean("SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", false)) {
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(!hasFocus);
}
}
if (SDLActivity.mBrokenLibraries) { if (SDLActivity.mBrokenLibraries) {
return; return;
} }
@@ -1491,11 +1481,11 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) { if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
// Note that we process events with specific key codes here // Note that we process events with specific key codes here
if (event.getAction() == KeyEvent.ACTION_DOWN) { if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLControllerManager.onNativePadDown(deviceId, keyCode, event.getScanCode())) { if (SDLControllerManager.onNativePadDown(deviceId, keyCode)) {
return true; return true;
} }
} else if (event.getAction() == KeyEvent.ACTION_UP) { } else if (event.getAction() == KeyEvent.ACTION_UP) {
if (SDLControllerManager.onNativePadUp(deviceId, keyCode, event.getScanCode())) { if (SDLControllerManager.onNativePadUp(deviceId, keyCode)) {
return true; return true;
} }
} }
@@ -1973,7 +1963,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
Intent i = new Intent(Intent.ACTION_VIEW); Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url)); i.setData(Uri.parse(url));
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY int flags = Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
| Intent.FLAG_ACTIVITY_NEW_DOCUMENT; | Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
i.addFlags(flags); i.addFlags(flags);
@@ -2237,4 +2227,3 @@ class SDLClipboardHandler implements
SDLActivity.onNativeClipboardChanged(); SDLActivity.onNativeClipboardChanged();
} }
} }
@@ -10,10 +10,6 @@ import android.hardware.lights.Light;
import android.hardware.lights.LightsRequest; import android.hardware.lights.LightsRequest;
import android.hardware.lights.LightsManager; import android.hardware.lights.LightsManager;
import android.hardware.lights.LightState; import android.hardware.lights.LightState;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.graphics.Color; import android.graphics.Color;
import android.os.Build; import android.os.Build;
import android.os.VibrationEffect; import android.os.VibrationEffect;
@@ -34,18 +30,16 @@ public class SDLControllerManager
static native void nativeAddJoystick(int device_id, String name, String desc, static native void nativeAddJoystick(int device_id, String name, String desc,
int vendor_id, int product_id, int vendor_id, int product_id,
int button_mask, int button_mask,
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led, int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led);
boolean has_accelerometer, boolean has_gyroscope);
static native void nativeRemoveJoystick(int device_id); static native void nativeRemoveJoystick(int device_id);
static native void nativeAddHaptic(int device_id, String name); static native void nativeAddHaptic(int device_id, String name);
static native void nativeRemoveHaptic(int device_id); static native void nativeRemoveHaptic(int device_id);
static public native boolean onNativePadDown(int device_id, int keycode, int scancode); static public native boolean onNativePadDown(int device_id, int keycode);
static public native boolean onNativePadUp(int device_id, int keycode, int scancode); static public native boolean onNativePadUp(int device_id, int keycode);
static native void onNativeJoy(int device_id, int axis, static native void onNativeJoy(int device_id, int axis,
float value); float value);
static native void onNativeHat(int device_id, int hat_id, static native void onNativeHat(int device_id, int hat_id,
int x, int y); int x, int y);
static native void onNativeJoySensor(int device_id, int sensor_type, long sensor_timestamp, float x, float y, float z);
protected static SDLJoystickHandler mJoystickHandler; protected static SDLJoystickHandler mJoystickHandler;
protected static SDLHapticHandler mHapticHandler; protected static SDLHapticHandler mHapticHandler;
@@ -87,13 +81,6 @@ public class SDLControllerManager
mJoystickHandler.setLED(device_id, red, green, blue); mJoystickHandler.setLED(device_id, red, green, blue);
} }
/**
* This method is called by SDL using JNI.
*/
static void joystickSetSensorsEnabled(int device_id, boolean enabled) {
mJoystickHandler.setSensorsEnabled(device_id, enabled);
}
/** /**
* This method is called by SDL using JNI. * This method is called by SDL using JNI.
*/ */
@@ -166,10 +153,6 @@ class SDLJoystickHandler {
ArrayList<InputDevice.MotionRange> hats; ArrayList<InputDevice.MotionRange> hats;
ArrayList<Light> lights; ArrayList<Light> lights;
LightsManager.LightsSession lightsSession; LightsManager.LightsSession lightsSession;
SensorManager sensorManager;
SDLJoySensorListener sensorListener;
Sensor accelerometerSensor;
Sensor gyroscopeSensor;
} }
static class RangeComparator implements Comparator<InputDevice.MotionRange> { static class RangeComparator implements Comparator<InputDevice.MotionRange> {
@Override @Override
@@ -242,13 +225,12 @@ class SDLJoystickHandler {
joystick.desc = getJoystickDescriptor(joystickDevice); joystick.desc = getJoystickDescriptor(joystickDevice);
joystick.axes = new ArrayList<InputDevice.MotionRange>(); joystick.axes = new ArrayList<InputDevice.MotionRange>();
joystick.hats = new ArrayList<InputDevice.MotionRange>(); joystick.hats = new ArrayList<InputDevice.MotionRange>();
java.util.Set<Integer> axisStrsSet = new java.util.HashSet<Integer>();
joystick.lights = new ArrayList<Light>(); joystick.lights = new ArrayList<Light>();
List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges(); List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
Collections.sort(ranges, new RangeComparator()); Collections.sort(ranges, new RangeComparator());
for (InputDevice.MotionRange range : ranges) { for (InputDevice.MotionRange range : ranges) {
if (((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) && axisStrsSet.add(range.getAxis())) { if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) { if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
joystick.hats.add(range); joystick.hats.add(range);
} else { } else {
@@ -259,8 +241,6 @@ class SDLJoystickHandler {
boolean can_rumble = false; boolean can_rumble = false;
boolean has_rgb_led = false; boolean has_rgb_led = false;
boolean has_accelerometer = false;
boolean has_gyroscope = false;
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) { if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
VibratorManager vibratorManager = joystickDevice.getVibratorManager(); VibratorManager vibratorManager = joystickDevice.getVibratorManager();
int[] vibrators = vibratorManager.getVibratorIds(); int[] vibrators = vibratorManager.getVibratorIds();
@@ -278,26 +258,12 @@ class SDLJoystickHandler {
joystick.lightsSession = lightsManager.openSession(); joystick.lightsSession = lightsManager.openSession();
has_rgb_led = true; has_rgb_led = true;
} }
SensorManager sensorManager = joystickDevice.getSensorManager();
if (sensorManager != null) {
joystick.sensorManager = sensorManager;
joystick.sensorListener = new SDLJoySensorListener(joystick.device_id);
joystick.accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (joystick.accelerometerSensor != null) {
has_accelerometer = true;
}
joystick.gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
if (joystick.gyroscopeSensor != null) {
has_gyroscope = true;
}
}
} }
mJoysticks.add(joystick); mJoysticks.add(joystick);
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc, SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
getVendorId(joystickDevice), getProductId(joystickDevice), getVendorId(joystickDevice), getProductId(joystickDevice),
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led, getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led);
has_accelerometer, has_gyroscope);
} }
} }
} }
@@ -542,31 +508,6 @@ class SDLJoystickHandler {
} }
joystick.lightsSession.requestLights(lightsRequest.build()); joystick.lightsSession.requestLights(lightsRequest.build());
} }
void setSensorsEnabled(int device_id, boolean enabled) {
if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
return;
}
SDLJoystick joystick = getJoystick(device_id);
if (joystick == null || joystick.sensorManager == null) {
return;
}
if (enabled) {
if (joystick.accelerometerSensor != null) {
SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
}
if (joystick.gyroscopeSensor != null) {
SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor, SensorManager.SENSOR_DELAY_GAME);
}
} else {
if (joystick.accelerometerSensor != null) {
SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor);
}
if (joystick.gyroscopeSensor != null) {
SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor);
}
}
}
} }
class SDLHapticHandler_API31 extends SDLHapticHandler { class SDLHapticHandler_API31 extends SDLHapticHandler {
@@ -992,19 +933,3 @@ class SDLGenericMotionListener_API29 extends SDLGenericMotionListener_API26 {
return penDevice.isExternal() ? SDL_PEN_DEVICE_TYPE_INDIRECT : SDL_PEN_DEVICE_TYPE_DIRECT; return penDevice.isExternal() ? SDL_PEN_DEVICE_TYPE_INDIRECT : SDL_PEN_DEVICE_TYPE_DIRECT;
} }
} }
class SDLJoySensorListener implements SensorEventListener {
int device_id;
public SDLJoySensorListener(int device_id) {
this.device_id = device_id;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
@Override
public void onSensorChanged(SensorEvent event) {
SDLControllerManager.onNativeJoySensor(device_id, event.sensor.getType(), event.timestamp, event.values[0], event.values[1], event.values[2]);
}
}
@@ -1,32 +0,0 @@
package org.libsdl.app;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
// This class coordinates synchronized access to sensor manager registration
//
// This prevents a java.util.ConcurrentModificationException exception on
// Android 16, specifically on the Samsung Tab S9 Ultra.
class SDLSensorManager
{
static private SDLSensorManager mManager = new SDLSensorManager();
public static void registerListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
mManager.RegisterListener(manager, listener, sensor, samplingPeriodUs);
}
public static void unregisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor) {
mManager.UnregisterListener(manager, listener, sensor);
}
private synchronized void RegisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
manager.registerListener(listener, sensor, samplingPeriodUs, null);
}
private synchronized void UnregisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor) {
manager.unregisterListener(listener, sensor);
}
}
@@ -47,9 +47,6 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// Is SurfaceView ready for rendering // Is SurfaceView ready for rendering
protected boolean mIsSurfaceReady; protected boolean mIsSurfaceReady;
// Is on-screen keyboard visible
protected boolean mKeyboardVisible;
// Pinch events // Pinch events
private final ScaleGestureDetector scaleGestureDetector; private final ScaleGestureDetector scaleGestureDetector;
@@ -216,18 +213,6 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
WindowInsets.Type.displayCutout()); WindowInsets.Type.displayCutout());
SDLActivity.onNativeInsetsChanged(combined.left, combined.right, combined.top, combined.bottom); SDLActivity.onNativeInsetsChanged(combined.left, combined.right, combined.top, combined.bottom);
if (insets.isVisible(WindowInsets.Type.ime())) {
if (!mKeyboardVisible) {
mKeyboardVisible = true;
SDLActivity.onNativeScreenKeyboardShown();
}
} else {
if (mKeyboardVisible) {
mKeyboardVisible = false;
SDLActivity.onNativeScreenKeyboardHidden();
}
}
} }
// Pass these to any child views in case they need them // Pass these to any child views in case they need them
@@ -333,11 +318,11 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
protected void enableSensor(int sensortype, boolean enabled) { protected void enableSensor(int sensortype, boolean enabled) {
// TODO: This uses getDefaultSensor - what if we have >1 accels? // TODO: This uses getDefaultSensor - what if we have >1 accels?
if (enabled) { if (enabled) {
SDLSensorManager.registerListener(mSensorManager, this, mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(sensortype), mSensorManager.getDefaultSensor(sensortype),
SensorManager.SENSOR_DELAY_GAME); SensorManager.SENSOR_DELAY_GAME, null);
} else { } else {
SDLSensorManager.unregisterListener(mSensorManager, this, mSensorManager.unregisterListener(this,
mSensorManager.getDefaultSensor(sensortype)); mSensorManager.getDefaultSensor(sensortype));
} }
} }
+3 -53
View File
@@ -16,12 +16,11 @@ body {
flex-direction: column; flex-direction: column;
justify-content: flex-end; justify-content: flex-end;
align-items: stretch; align-items: stretch;
z-index: 2; z-index: 1;
pointer-events: none; pointer-events: none;
} }
fps, fps,
pipeline-progress,
toast { toast {
position: absolute; position: absolute;
border: 1dp #92875B; border: 1dp #92875B;
@@ -99,7 +98,7 @@ toast message row.muted {
opacity: 0.5; opacity: 0.5;
} }
progress { toast progress {
height: 4dp; height: 4dp;
position: absolute; position: absolute;
left: 0; left: 0;
@@ -107,50 +106,10 @@ progress {
width: 100%; width: 100%;
} }
progress fill { toast progress fill {
background-color: rgba(194, 164, 45, 80%); background-color: rgba(194, 164, 45, 80%);
} }
pipeline-progress {
left: 12dp;
bottom: 12dp;
display: flex;
flex-flow: column;
z-index: 100;
min-width: 260dp;
max-width: 90%;
padding: 10dp 16dp 12dp;
border-radius: 7dp;
overflow: hidden;
filter: opacity(0);
transition: filter 0.2s linear-in-out;
pointer-events: none;
}
pipeline-progress[open] {
filter: opacity(1);
}
pipeline-status {
display: flex;
align-items: center;
gap: 8dp;
font-size: 18dp;
font-weight: normal;
white-space: nowrap;
}
icon.pipeline-spinner {
width: 1.2em;
height: 1.2em;
line-height: 1.2em;
font-size: 1.2em;
color: #C2A42D;
text-align: center;
transform-origin: center;
animation: 1s linear infinite pipeline-spinner-spin;
}
toast.achievement { toast.achievement {
border: 1dp #C2A42D; border: 1dp #C2A42D;
} }
@@ -351,15 +310,6 @@ logo img.outer {
} }
} }
@keyframes pipeline-spinner-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (max-height: 640dp) { @media (max-height: 640dp) {
toast { toast {
top: 20dp; top: 20dp;
-339
View File
@@ -1,339 +0,0 @@
*, *:before, *:after {
box-sizing: border-box;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
font-family: "Fira Sans Condensed";
font-weight: bold;
color: rgba(248, 244, 232, 90%);
z-index: 1;
filter: opacity(0);
transition: filter 0.2s linear-in-out;
}
body[open] {
filter: opacity(1);
}
body:not([open]) {
pointer-events: none;
}
button {
display: flex;
align-items: center;
justify-content: center;
decorator: none;
padding: 0;
border: 1dp rgba(255, 255, 255, 22%);
background-color: rgba(22, 24, 28, 48%);
color: rgba(248, 244, 232, 90%);
text-align: center;
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 6dp 18dp rgba(0, 0, 0, 28%); */
transform-origin: center;
transition: background-color border-color filter transform 0.08s linear-in-out,
opacity 0.2s linear-in-out;
}
button.pressed,
button.active {
background-color: rgba(63, 78, 90, 68%);
border-color: rgba(255, 255, 255, 48%);
filter: brightness(1.18);
}
button:hidden {
opacity: 0;
pointer-events: none;
}
button span {
display: block;
line-height: 1;
}
button icon {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
button icon glyph {
display: block;
font-family: "Material Symbols Rounded";
font-weight: normal;
font-size: 24dp;
line-height: 1;
}
.midna-icon,
.item-icon,
.item-count,
.oil-meter {
display: none;
}
.midna-icon.visible,
.item-icon.visible,
.item-count.visible,
.oil-meter.visible {
display: block;
}
.control {
position: absolute;
}
.trigger-l.active {
background-color: rgba(57, 116, 133, 74%);
border-color: rgba(128, 222, 234, 72%);
}
.trigger,
.skip {
border-radius: 23dp;
}
.trigger {
font-size: 22dp;
}
.button-z {
background-color: rgba(118, 79, 158, 58%);
border-color: rgba(203, 170, 255, 36%);
}
.midna-icon {
position: absolute;
left: 9dp;
top: -1dp;
height: 48dp;
}
.button-z.has-icon span,
.face.has-item span {
position: absolute;
font-size: 13dp;
line-height: 1;
}
.button-z.has-icon span {
right: 9dp;
bottom: 7dp;
}
.button-z.pressed {
background-color: rgba(139, 91, 187, 82%);
border-color: rgba(220, 194, 255, 70%);
}
action-bar {
position: absolute;
display: flex;
align-items: center;
border: 1dp rgba(255, 255, 255, 22%);
border-radius: 23dp;
background-color: rgba(22, 24, 28, 48%);
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 -6dp 18dp rgba(0, 0, 0, 28%); */
overflow: hidden;
opacity: 1;
transform-origin: center;
transition: opacity 0.2s linear-in-out;
}
action-bar:hidden,
action-bar:hidden button,
action-bar:hidden separator {
opacity: 0;
pointer-events: none;
}
.utility {
position: relative;
flex: 1 1 auto;
width: 56dp;
height: 44dp;
margin: 0;
border-width: 0dp;
border-radius: 0;
background-color: transparent;
box-shadow: none;
}
.utility,
.skip {
opacity: 0.55;
}
.utility.pressed {
background-color: rgba(63, 78, 90, 68%);
}
.utility.pressed,
.skip.pressed {
opacity: 1;
}
.skip {
z-index: 1;
border-color: rgba(255, 255, 255, 36%);
}
separator {
display: block;
flex: 0 0 1dp;
width: 1dp;
height: 24dp;
background-color: rgba(255, 255, 255, 18%);
opacity: 1;
transition: opacity 0.2s linear-in-out;
}
.face {
position: absolute;
border-radius: 29dp;
font-size: 24dp;
overflow: visible;
}
.item-icon {
width: auto;
height: auto;
max-width: 76%;
max-height: 76%;
}
.item-count {
position: absolute;
left: 6dp;
bottom: 5dp;
min-width: 17dp;
height: 15dp;
padding: 1dp 3dp;
border-radius: 7dp;
background-color: rgba(0, 0, 0, 52%);
color: rgba(255, 255, 255, 92%);
font-size: 12dp;
line-height: 13dp;
text-align: center;
}
.oil-meter {
position: absolute;
left: 12dp;
bottom: -5dp;
width: 34dp;
height: 8dp;
padding: 2dp;
border: 1dp rgba(42, 32, 18, 82%);
border-radius: 4dp;
background-color: rgba(18, 14, 10, 70%);
/* box-shadow: 0 2dp 6dp rgba(0, 0, 0, 35%); */
}
oil-fill {
display: block;
width: 0%;
height: 100%;
border-radius: 2dp;
background-color: rgb(255, 232, 74);
}
.face.has-item span {
right: 6dp;
bottom: 6dp;
color: rgba(255, 255, 255, 88%);
}
.face.a {
border-radius: 37dp;
font-size: 31dp;
background-color: rgba(34, 112, 123, 62%);
}
.face.b {
background-color: rgba(161, 61, 66, 58%);
}
.face.x {
background-color: rgba(83, 115, 151, 56%);
}
.face.y {
background-color: rgba(113, 91, 150, 54%);
}
button.control.docked-top,
action-bar.docked-top {
border-top-width: 0dp;
border-top-left-radius: 0dp;
border-top-right-radius: 0dp;
}
button.control.docked-bottom,
action-bar.docked-bottom {
border-bottom-width: 0dp;
border-bottom-left-radius: 0dp;
border-bottom-right-radius: 0dp;
}
button.control.docked-left,
action-bar.docked-left {
border-left-width: 0dp;
border-top-left-radius: 0dp;
border-bottom-left-radius: 0dp;
}
button.control.docked-right,
action-bar.docked-right {
border-right-width: 0dp;
border-top-right-radius: 0dp;
border-bottom-right-radius: 0dp;
}
touch-stick {
display: block;
position: absolute;
width: 124dp;
height: 124dp;
border-radius: 62dp;
background-color: rgba(18, 20, 24, 35%);
border: 1dp rgba(255, 255, 255, 20%);
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 8dp 24dp rgba(0, 0, 0, 24%); */
opacity: 0;
pointer-events: none;
transition: opacity 0.18s linear-in-out;
}
touch-stick.active {
opacity: 1;
}
stick-ring {
position: absolute;
left: 18dp;
top: 18dp;
width: 88dp;
height: 88dp;
border-radius: 44dp;
border: 1dp rgba(255, 255, 255, 18%);
}
stick-knob {
position: absolute;
width: 48dp;
height: 48dp;
border-radius: 24dp;
background-color: rgba(238, 236, 226, 55%);
border: 1dp rgba(255, 255, 255, 45%);
}
-138
View File
@@ -1,138 +0,0 @@
body.touch-editor {
background-color: rgba(4, 6, 8, 34%);
z-index: 8;
}
body.touch-editor .control,
body.touch-editor action-bar {
opacity: 0.88;
cursor: move;
pointer-events: auto;
}
body.touch-editor .control:hover,
body.touch-editor action-bar:hover,
body.touch-editor .control.editor-selected,
body.touch-editor action-bar.editor-selected {
border-color: rgba(255, 232, 128, 80%);
filter: brightness(1.15);
}
body.touch-editor action-bar button,
body.touch-editor action-bar separator {
pointer-events: none;
}
selection-frame {
display: none;
position: absolute;
z-index: 20;
border: 2dp rgba(255, 232, 128, 88%);
background-color: rgba(255, 232, 128, 7%);
pointer-events: none;
}
selection-frame.visible {
display: block;
}
resize-handle {
display: block;
position: absolute;
width: 22dp;
height: 22dp;
border: 2dp rgba(255, 244, 190, 96%);
border-radius: 11dp;
background-color: rgba(34, 37, 42, 86%);
pointer-events: auto;
}
resize-handle.left {
left: -12dp;
}
resize-handle.right {
right: -12dp;
}
resize-handle.top {
top: -12dp;
}
resize-handle.bottom {
bottom: -12dp;
}
resize-handle.horizontal {
top: 50%;
margin-top: -11dp;
}
resize-handle.vertical {
left: 50%;
margin-left: -11dp;
}
resize-handle.corner.left {
left: -12dp;
}
resize-handle.corner.right {
right: -12dp;
}
resize-handle.corner.top {
top: -12dp;
}
resize-handle.corner.bottom {
bottom: -12dp;
}
editor-toolbar {
display: flex;
position: absolute;
left: 24dp;
right: 24dp;
top: 50%;
z-index: 30;
height: 48dp;
margin-top: -24dp;
gap: 8dp;
justify-content: center;
pointer-events: auto;
}
editor-toolbar button.editor-command {
flex: 0 1 150dp;
min-width: 96dp;
height: 48dp;
padding: 0 14dp;
border-radius: 8dp;
border: 1dp rgba(255, 255, 255, 26%);
background-color: rgba(17, 19, 24, 88%);
color: rgba(255, 250, 232, 94%);
font-family: "Fira Sans";
font-size: 18dp;
line-height: 48dp;
opacity: 1;
cursor: pointer;
}
editor-toolbar button.editor-command span {
display: block;
width: 100%;
line-height: 48dp;
text-align: center;
}
editor-toolbar button.editor-command.primary {
border-color: rgba(255, 232, 128, 70%);
background-color: rgba(96, 82, 38, 90%);
}
editor-toolbar button.editor-command:hover,
editor-toolbar button.editor-command:focus-visible {
border-color: rgba(255, 244, 190, 92%);
background-color: rgba(78, 85, 96, 92%);
}
-10
View File
@@ -175,13 +175,3 @@ bool daAlink_c::checkAimContext() {
return false; return false;
} }
} }
bool daAlink_c::checkAimInputContext() {
switch (mProcID) {
case PROC_HOOKSHOT_ROOF_WAIT:
case PROC_HOOKSHOT_WALL_WAIT:
return false;
default:
return checkAimContext();
}
}
+13 -33
View File
@@ -14,7 +14,6 @@
#include "dusk/action_bindings.h" #include "dusk/action_bindings.h"
#include "dusk/gyro.h" #include "dusk/gyro.h"
#include "dusk/mouse.h" #include "dusk/mouse.h"
#include "dusk/touch_camera.h"
#endif #endif
bool daAlink_c::checkNoSubjectModeCamera() { bool daAlink_c::checkNoSubjectModeCamera() {
@@ -122,11 +121,18 @@ BOOL daAlink_c::setBodyAngleToCamera() {
var_f31 /= dComIfGp_getCameraZoomScale(field_0x317c); 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))); #if TARGET_PC
sp8 = mBodyAngle.x + (var_f31 * cM_scos(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonYAxis ? -1.0f : 1.0f))); if (dusk::getSettings().game.enableMouseAim && checkAimContext()) {
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x; 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 { } else {
sp8 = mBodyAngle.x; sp8 = mBodyAngle.x;
@@ -135,7 +141,7 @@ BOOL daAlink_c::setBodyAngleToCamera() {
#if TARGET_PC #if TARGET_PC
if ((dusk::getSettings().game.enableGyroAim || if ((dusk::getSettings().game.enableGyroAim ||
dusk::getSettings().game.enableMouseAim) && dusk::getSettings().game.enableMouseAim) &&
checkAimInputContext()) checkAimContext())
{ {
f32 gyro_scale = 1.0f; f32 gyro_scale = 1.0f;
if (checkWolfEyeUp()) { if (checkWolfEyeUp()) {
@@ -149,7 +155,7 @@ BOOL daAlink_c::setBodyAngleToCamera() {
f32 final_yaw = 0.f; f32 final_yaw = 0.f;
f32 final_pitch = 0.f; f32 final_pitch = 0.f;
if (dusk::getSettings().game.enableMouseAim) { if (dusk::getSettings().game.enableMouseAim) {
dusk::mouse::get_aim_deltas(final_yaw, final_pitch); dusk::mouse::getAimDeltas(final_yaw, final_pitch);
} }
if (dusk::getSettings().game.enableGyroAim) { if (dusk::getSettings().game.enableGyroAim) {
f32 gyro_yaw = 0.f; f32 gyro_yaw = 0.f;
@@ -166,32 +172,6 @@ BOOL daAlink_c::setBodyAngleToCamera() {
sp8 = mBodyAngle.x; sp8 = mBodyAngle.x;
} }
} }
if (dusk::getSettings().game.enableTouchControls && checkAimInputContext()) {
f32 touchYawDp = 0.0f;
f32 touchPitchDp = 0.0f;
if (dusk::touch_camera::consume_delta(touchYawDp, touchPitchDp)) {
f32 scale = 1.0f;
if (checkWolfEyeUp()) {
scale *= 0.6f;
}
if (dComIfGp_checkPlayerStatus0(0, 0x200000)) {
scale /= dComIfGp_getCameraZoomScale(field_0x317c);
}
const f32 yawDeg = -touchYawDp * dusk::touch_camera::YAW_DEGREES_PER_DP * scale *
dusk::getSettings().game.touchCameraXSensitivity;
const f32 pitchDeg = touchPitchDp * dusk::touch_camera::PITCH_DEGREES_PER_DP *
scale * dusk::getSettings().game.touchCameraYSensitivity;
shape_angle.y = shape_angle.y + cM_deg2s(yawDeg);
sp8 = sp8 + cM_deg2s(pitchDeg);
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
}
}
#endif #endif
if (checkNotItemSinkLimit() && sp8 > 0) { if (checkNotItemSinkLimit() && sp8 > 0) {
+3 -22
View File
@@ -11,7 +11,6 @@
#include "d/d_com_inf_game.h" #include "d/d_com_inf_game.h"
#if TARGET_PC #if TARGET_PC
#include <aurora/texture.hpp>
#include "dusk/dvd_asset.hpp" #include "dusk/dvd_asset.hpp"
#include "dusk/frame_interpolation.h" #include "dusk/frame_interpolation.h"
@@ -41,8 +40,6 @@ static f32* l_texCoord_get() { alignas(32) static f32 buf[338]; static bool _
//#define l_pos (l_pos_get()) //#define l_pos (l_pos_get())
#define l_normal (l_normal_get()) #define l_normal (l_normal_get())
#define l_texCoord (l_texCoord_get()) #define l_texCoord (l_texCoord_get())
static bool l_Egnd_mantTEX_hasReplacement = false;
#else #else
#include "assets/l_Egnd_mantTEX.h" #include "assets/l_Egnd_mantTEX.h"
@@ -226,7 +223,6 @@ void daMant_packet_c::draw() {
GXInitTexObjCI( GXInitTexObjCI(
&undersideTexObj, l_Egnd_mantTEX_U, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0); &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); GXInitTexObjLOD(&undersideTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
l_Egnd_mantTEX_hasReplacement = aurora::texture::has_replacement(&mainTexObj, &tlutObj);
textureObjsInitialized = true; textureObjsInitialized = true;
} }
#else #else
@@ -640,11 +636,7 @@ static int daMant_Execute(mant_class* i_this) {
iVar8 = 0; iVar8 = 0;
if (i_this->field_0x3967 != 0) { if (i_this->field_0x3967 != 0) {
#if TARGET_PC
mant_cut_type = l_Egnd_mantTEX_hasReplacement ? 1 : i_this->field_0x3967;
#else
mant_cut_type = i_this->field_0x3967; mant_cut_type = i_this->field_0x3967;
#endif
if (i_this->field_0x3968 < 15) { if (i_this->field_0x3968 < 15) {
i_this->field_0x3968++; i_this->field_0x3968++;
@@ -656,18 +648,9 @@ static int daMant_Execute(mant_class* i_this) {
iVar8 = 20; iVar8 = 20;
} }
#if TARGET_PC unaff_r29 = cM_rndF(65536.0f);
if (l_Egnd_mantTEX_hasReplacement) { var_f31 = cM_rndFX(32.0f);
unaff_r29 = i_this->mMantRng.getF(65536.0f); var_f30 = cM_rndFX(32.0f);
var_f31 = i_this->mMantRng.getFX(32.0f);
var_f30 = i_this->mMantRng.getFX(32.0f);
} else
#endif
{
unaff_r29 = cM_rndF(65536.0f);
var_f31 = cM_rndFX(32.0f);
var_f30 = cM_rndFX(32.0f);
}
} }
i_this->field_0x3967 = 0; i_this->field_0x3967 = 0;
@@ -777,8 +760,6 @@ static int daMant_Create(fopAc_ac_c* i_this) {
if(textureObjsInitialized) { if(textureObjsInitialized) {
GXInitTlutObjData(&tlutObj, l_Egnd_mantPAL); // make sure the cached textures are updated GXInitTlutObjData(&tlutObj, l_Egnd_mantPAL); // make sure the cached textures are updated
} }
m_this->mMantRng.init(66, 16983, 855);
#endif #endif
lbl_277_bss_0 = 0; lbl_277_bss_0 = 0;
-10
View File
@@ -6882,16 +6882,6 @@ static int daNpc_Ks_Delete(npc_ks_class* i_this) {
i_this->model->stopZelAnime(); i_this->model->stopZelAnime();
} }
#if TARGET_PC
if (leader == i_this) {
leader = NULL;
}
if (saru_p[i_this->set_id] == i_this) {
saru_p[i_this->set_id] = NULL;
}
#endif
return 1; return 1;
} }
-378
View File
@@ -15,12 +15,6 @@ const u16 l_J_Ohana00_64TEX__height = 63;
using GameVersion = dusk::version::GameVersion; using GameVersion = dusk::version::GameVersion;
static u8* l_J_Ohana00_64TEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x9060}, {GameVersion::GcnPal, 0x9060}}, 0x800), true); return buf; } static u8* l_J_Ohana00_64TEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x9060}, {GameVersion::GcnPal, 0x9060}}, 0x800), true); return buf; }
#define l_J_Ohana00_64TEX (l_J_Ohana00_64TEX_get()) #define l_J_Ohana00_64TEX (l_J_Ohana00_64TEX_get())
// from d_grass.inc
static MtxP get_model_mtx(Mtx modelMtx, Mtx storage);
static void transform_positions(
const dusk::batch::LeafTemplate& tpl, const Vec* posArray, const Mtx mtx, Vec* xfPos);
static void split_batch(u32& emitted, u32 vtxCount);
#else #else
#include "assets/l_J_Ohana00_64TEX.h" #include "assets/l_J_Ohana00_64TEX.h"
#endif #endif
@@ -594,12 +588,6 @@ dFlower_packet_c::dFlower_packet_c() {
GXInitTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, l_J_Ohana01_64128_0419TEX, GXInitTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, l_J_Ohana01_64128_0419TEX,
l_J_Ohana01_64128_0419TEX__width + 1, l_J_Ohana01_64128_0419TEX__height + 1, GX_TF_CMPR, GX_MIRROR, GX_MIRROR, GX_FALSE l_J_Ohana01_64128_0419TEX__width + 1, l_J_Ohana01_64128_0419TEX__height + 1, GX_TF_CMPR, GX_MIRROR, GX_MIRROR, GX_FALSE
); );
dusk::batch::decode_leaf_template(l_J_hana00DL, 0x140, mTplHana00);
dusk::batch::decode_leaf_template(l_J_hana00_cDL, 0xC0, mTplHana00Cut);
dusk::batch::decode_leaf_template(l_J_hana01DL, 0x120, mTplHana01);
dusk::batch::decode_leaf_template(l_J_hana01_c_00DL, 0xC0, mTplHana01Cut00);
dusk::batch::decode_leaf_template(l_J_hana01_c_01DL, 0x120, mTplHana01Cut);
#endif #endif
m_deleteRoom = &dFlower_packet_c::deleteRoom; m_deleteRoom = &dFlower_packet_c::deleteRoom;
@@ -609,371 +597,6 @@ dFlower_packet_c::dFlower_packet_c() {
#endif #endif
} }
#if TARGET_PC
static void batch_setup_tev(u32 lightMask) {
GXSetCullMode(GX_CULL_NONE);
GXSetNumChans(2);
GXSetChanCtrl(GX_COLOR0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE);
GXSetChanCtrl(GX_COLOR1, GX_TRUE, GX_SRC_VTX, GX_SRC_REG, lightMask, GX_DF_CLAMP, GX_AF_SPOT);
GXSetNumTevStages(3);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR1A1);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
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_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_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_CPREV, GX_CC_RASC, GX_CC_ZERO);
GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);
GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
GXSetTevColorIn(GX_TEVSTAGE2, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_C0);
GXSetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE2, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA);
GXSetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
}
static GXColor hana00_amb_color(const dFlower_data_c* flower, const dKy_tevstr_c* tevstr) {
GXColor amb = {0, 0, 0, 0xFF};
if (DEBUG && g_kankyoHIO.navy.grass_adjust_ON != 0) {
amb.r = g_kankyoHIO.navy.grass_ambcol.r * 2;
amb.g = g_kankyoHIO.navy.grass_ambcol.g * 2;
amb.b = g_kankyoHIO.navy.grass_ambcol.b * 2;
} else {
amb.r = (flower->field_0x04 & 0x1F) * 2;
amb.g = ((flower->field_0x04 >> 5) & 0x1F) * 2;
amb.b = ((flower->field_0x04 >> 0xA) & 0x1F) * 2;
}
if (daPy_py_c::checkNowWolfPowerUp()) {
f32 ambRate = g_env_light.bg_amb_col[0].r / 255.0f;
f32 col = (((flower->field_0x04 & 0x1F) * 2 + 0x10));
amb.r = col * (ambRate * 4.0f);
ambRate = g_env_light.bg_amb_col[0].g / 255.0f;
f32 col2 = (((flower->field_0x04 >> 5) & 0x1F) * 2 + 0x10);
amb.g = col2 * (4.0f * ambRate);
ambRate = g_env_light.bg_amb_col[0].b / 255.0f;
f32 col3 = (((flower->field_0x04 >> 10) & 0x1F) * 2 + 0x10);
amb.b = col3 * (4.0f * ambRate);
}
if (amb.r == 0x3E) {
amb.r = tevstr->AmbCol.r;
}
if (amb.g == 0x3E) {
amb.g = tevstr->AmbCol.g;
}
if (amb.b == 0x3E) {
amb.b = tevstr->AmbCol.b;
}
return amb;
}
static GXColor hana01_amb_color(int idx, const dKy_tevstr_c* tevstr) {
f32 rRate = tevstr->AmbCol.r * 0.03125f;
if (rRate > 1.0f) {
rRate = 1.0f;
}
f32 gRate = tevstr->AmbCol.g * 0.03125f;
if (gRate > 1.0f) {
gRate = 1.0f;
}
f32 bRate = tevstr->AmbCol.b * 0.03125f;
if (bRate > 1.0f) {
bRate = 1.0f;
}
GXColor amb = {1, 1, 1, 1};
GXColor sub;
sub.r = -0.4f * tevstr->AmbCol.r * rRate;
sub.g = -0.4f * tevstr->AmbCol.g * gRate;
sub.b = -0.4f * tevstr->AmbCol.b * bRate;
switch (idx & 7) {
case 0:
amb.r = tevstr->AmbCol.r + sub.r;
amb.g = tevstr->AmbCol.g;
amb.b = tevstr->AmbCol.b;
break;
case 1:
amb.r = tevstr->AmbCol.r;
amb.g = tevstr->AmbCol.g + sub.g;
amb.b = tevstr->AmbCol.b;
break;
case 2:
amb.r = tevstr->AmbCol.r;
amb.g = tevstr->AmbCol.g;
amb.b = tevstr->AmbCol.b + sub.b;
break;
case 3:
amb.r = tevstr->AmbCol.r + sub.r;
amb.g = tevstr->AmbCol.g + sub.g;
amb.b = tevstr->AmbCol.b;
break;
case 4:
amb.r = tevstr->AmbCol.r;
amb.g = tevstr->AmbCol.g + sub.g;
amb.b = tevstr->AmbCol.b + sub.b;
break;
case 5:
amb.r = tevstr->AmbCol.r + sub.r;
amb.g = tevstr->AmbCol.g;
amb.b = tevstr->AmbCol.b + sub.b;
break;
case 6:
amb.r = tevstr->AmbCol.r + sub.r;
amb.g = tevstr->AmbCol.g + sub.g;
amb.b = tevstr->AmbCol.b + sub.b;
break;
case 7:
break;
}
if (daPy_py_c::checkNowWolfPowerUp()) {
f32 ambRate = g_env_light.bg_amb_col[0].r / 255.0f;
amb.r = (amb.r + 8) * (6.0f * ambRate);
ambRate = g_env_light.bg_amb_col[0].g / 255.0f;
amb.g = (amb.g + 8) * (6.0f * ambRate);
ambRate = g_env_light.bg_amb_col[0].b / 255.0f;
amb.b = (amb.b + 8) * (6.0f * ambRate);
}
amb.a = 0xFF;
return amb;
}
static void flower_emit(const dusk::batch::LeafTemplate& tpl, const Vec* xformedPos, GXColor amb) {
for (u32 i = 0; i < tpl.vtxCount; i++) {
const dusk::batch::LeafTemplate::Vtx& v = tpl.vtx[i];
const Vec& p = xformedPos[v.pos];
GXPosition3f32(p.x, p.y, p.z);
GXNormal1x8(v.nrm);
GXColor1x8(v.clr);
GXColor4u8(amb.r, amb.g, amb.b, amb.a);
GXTexCoord1x8(v.tex);
}
}
void dFlower_packet_c::draw() {
ZoneScoped;
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
j3dSys.reinitGX();
GXSetNumIndStages(0);
dKy_setLight_again();
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);
GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSETARRAY(GX_VA_POS, &l_flowerPos, sizeof(l_flowerPos), sizeof(Vec), true);
GXSETARRAY(GX_VA_NRM, &l_flowerNormal, sizeof(l_flowerNormal), sizeof(Vec), true);
GXSETARRAY(GX_VA_CLR0, &l_flowerColor, sizeof(l_flowerColor), sizeof(GXColor), true);
GXSETARRAY(GX_VA_TEX0, &l_flowerTexCoord, sizeof(l_flowerTexCoord), 8, true);
static GXVtxDescList vtxDescList[] = {
{GX_VA_POS, GX_DIRECT},
{GX_VA_NRM, GX_INDEX8},
{GX_VA_CLR0, GX_INDEX8},
{GX_VA_CLR1, GX_DIRECT},
{GX_VA_TEX0, GX_INDEX8},
{GX_VA_NULL, GX_NONE},
};
static Vec xfPos[256];
Mtx identity;
MTXIdentity(identity);
// --- hana00 ---
for (int i = 0; i < 64; i++) {
dFlower_data_c* first = m_room[i].getData();
if (first == nullptr || !dComIfGp_roomControl_checkStatusFlag(i, 0x10)) {
continue;
}
dKy_tevstr_c* tevstr = dComIfGp_roomControl_getTevStr(i);
int lightCount = 6;
if (dComIfGp_roomControl_getStatusRoomDt(i) != nullptr) {
lightCount = dComIfGp_roomControl_getStatusRoomDt(i)->getLightVecInfoNum();
}
if (dKy_SunMoon_Light_Check() && lightCount < 2) {
lightCount = 2;
}
for (int j = 0; j < 6; j++) {
if (kankyo->field_0x0c18[j].field_0x26 == 1) {
lightCount++;
}
}
if (lightCount <= 2) {
GXCallDisplayList(l_matLight4DL, 0x80);
} else {
GXCallDisplayList(l_matDL, 0x80);
}
GXSetTevColorS10(GX_TEVREG0, {0, 0, 0, 0});
dKy_Global_amb_set(tevstr);
dKy_GxFog_tevstr_set(tevstr);
dKy_setLight_nowroom_grass(tevstr->room_no, 1.0f);
GXLoadTexObj(&mTexObj_l_J_Ohana00_64TEX, GX_TEXMAP0);
batch_setup_tev(lightCount <= 2 ? (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4) :
(GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4 |
GX_LIGHT5 | GX_LIGHT6 | GX_LIGHT7));
GXSetVtxDescv(vtxDescList);
GXLoadPosMtxImm(identity, GX_PNMTX0);
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
for (int bucket = 0; bucket < 2; bucket++) {
const bool cut = bucket != 0;
const dusk::batch::LeafTemplate& tpl = cut ? mTplHana00Cut : mTplHana00;
bool open = false;
u32 emitted = 0;
for (dFlower_data_c* flower = first; flower != nullptr; flower = flower->mp_next) {
if (cLib_checkBit<u8>(flower->m_state, 4) ||
cLib_checkBit<u8>(flower->m_state, 0x40))
{
continue;
}
if ((cLib_checkBit<u8>(flower->m_state, 8) != 0) != cut) {
continue;
}
if (!open) {
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
open = true;
}
split_batch(emitted, tpl.vtxCount);
Mtx interpMtx;
MtxP mtx = get_model_mtx(flower->m_modelMtx, interpMtx);
transform_positions(tpl, reinterpret_cast<Vec*>(l_flowerPos), mtx, xfPos);
flower_emit(tpl, xfPos, hana00_amb_color(flower, tevstr));
}
if (open) {
GXEnd();
}
}
}
// --- hana01 ---
GXSETARRAY(GX_VA_POS, mp_pos, sizeof(l_flowerPos2), sizeof(Vec), true);
GXSETARRAY(GX_VA_NRM, &l_flowerNormal2, sizeof(l_flowerNormal2), sizeof(Vec), true);
GXSETARRAY(GX_VA_CLR0, mp_colors, sizeof(l_flowerColor2), sizeof(GXColor), true);
GXSETARRAY(GX_VA_TEX0, mp_texCoords, sizeof(l_flowerTexCoord2), 8, true);
for (int i = 0; i < 64; i++) {
dFlower_data_c* first = m_room[i].getData();
if (first == NULL) {
continue;
}
dKy_tevstr_c* tevstr = dComIfGp_roomControl_getTevStr(i);
int lightCount = 6;
if (dComIfGp_roomControl_getStatusRoomDt(i) != NULL) {
lightCount = dComIfGp_roomControl_getStatusRoomDt(i)->getLightVecInfoNum();
}
#if DEBUG
if (g_kankyoHIO.light.m_HOSTIO_setting != 0) {
lightCount = g_kankyoHIO.dungeonLight.usedLights;
}
#endif
if (dKy_SunMoon_Light_Check() == TRUE && lightCount < 2) {
lightCount = 2;
}
if (lightCount <= 2) {
GXCallDisplayList(mp_mat2Light4DL, m_mat2Light4DL_size);
} else {
GXCallDisplayList(mp_mat2DL, m_mat2DL_size);
}
GXSetTevColorS10(GX_TEVREG0, {0, 0, 0, 0});
dKy_Global_amb_set(tevstr);
dKy_GxFog_tevstr_set(tevstr);
dKy_setLight_nowroom_grass(tevstr->room_no, 1.0f);
GXLoadTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, GX_TEXMAP0);
batch_setup_tev(lightCount <= 2 ? (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4) :
(GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4 |
GX_LIGHT5 | GX_LIGHT6 | GX_LIGHT7));
GXSetVtxDescv(vtxDescList);
GXLoadPosMtxImm(identity, GX_PNMTX0);
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
const dusk::batch::LeafTemplate* const buckets[3] = {
&mTplHana01, &mTplHana01Cut00, &mTplHana01Cut};
for (int bucket = 0; bucket < 3; bucket++) {
const dusk::batch::LeafTemplate& tpl = *buckets[bucket];
bool open = false;
u32 emitted = 0;
int idx = 0;
for (dFlower_data_c* flower = first; flower != NULL; flower = flower->mp_next, idx++) {
if (cLib_checkBit<u8>(flower->m_state, 4) ||
!cLib_checkBit<u8>(flower->m_state, 0x40))
{
continue;
}
const int flowerBucket = cLib_checkBit<u8>(flower->m_state, 8) ? 2 :
cLib_checkBit<u8>(flower->m_state, 0x10) ? 1 :
0;
if (flowerBucket != bucket) {
continue;
}
if (!open) {
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
open = true;
}
split_batch(emitted, tpl.vtxCount);
Mtx interpMtx;
MtxP mtx = get_model_mtx(flower->m_modelMtx, interpMtx);
transform_positions(tpl, mp_pos, mtx, xfPos);
flower_emit(tpl, xfPos, hana01_amb_color(idx, tevstr));
}
if (open) {
GXEnd();
}
}
}
GXSetNumTevStages(1);
GXSetNumChans(1);
J3DShape::resetVcdVatCache();
}
#else
void dFlower_packet_c::draw() { void dFlower_packet_c::draw() {
ZoneScoped; ZoneScoped;
dScnKy_env_light_c* kankyo = dKy_getEnvlight(); dScnKy_env_light_c* kankyo = dKy_getEnvlight();
@@ -1263,7 +886,6 @@ void dFlower_packet_c::draw() {
J3DShape::resetVcdVatCache(); J3DShape::resetVcdVatCache();
} }
#endif
void dFlower_packet_c::calc() { void dFlower_packet_c::calc() {
dFlower_anm_c* anm_p = getAnm(); dFlower_anm_c* anm_p = getAnm();
-356
View File
@@ -512,366 +512,11 @@ dGrass_packet_c::dGrass_packet_c() {
m_Mkusa_9q_cDL_size = 0xC0; m_Mkusa_9q_cDL_size = 0xC0;
field_0x1d714 = 0; field_0x1d714 = 0;
#if TARGET_PC
dusk::batch::decode_leaf_template(mp_Mkusa_9q_DL, m_Mkusa_9q_DL_size, mTplKusa9q);
dusk::batch::decode_leaf_template(mp_Mkusa_9q_cDL, m_Mkusa_9q_cDL_size, mTplKusa9qCut);
dusk::batch::decode_leaf_template(l_M_TenGusaDL, 0xC0, mTplTengusa);
#endif
OS_REPORT("草群メモリ=%f\n", 117.7734375f); OS_REPORT("草群メモリ=%f\n", 117.7734375f);
m_deleteRoom = &dGrass_packet_c::deleteRoom; m_deleteRoom = &dGrass_packet_c::deleteRoom;
} }
#if TARGET_PC
static MtxP get_model_mtx(Mtx modelMtx, Mtx storage) {
if (dusk::frame_interp::lookup_replacement(modelMtx, storage)) {
cMtx_concat(j3dSys.getViewMtx(), storage, storage);
return storage;
}
return modelMtx;
}
static void transform_positions(
const dusk::batch::LeafTemplate& tpl, const Vec* posArray, const Mtx mtx, Vec* xfPos) {
for (u32 i = 0; i < tpl.posRefCount; i++) {
const u8 idx = tpl.posRefs[i];
MTXMultVec(mtx, &posArray[idx], &xfPos[idx]);
}
}
static void split_batch(u32& emitted, u32 vtxCount) {
if (emitted + vtxCount > 0xFFFF) {
GXEnd();
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
emitted = 0;
}
emitted += vtxCount;
}
static GXColor blade_amb_color(const dGrass_data_c* blade, const dKy_tevstr_c* tevstr) {
GXColor amb;
amb.a = 0;
#if DEBUG
if (g_kankyoHIO.navy.grass_adjust_ON) {
amb.r = g_kankyoHIO.navy.grass_ambcol.r * 2;
amb.g = g_kankyoHIO.navy.grass_ambcol.g * 2;
amb.b = g_kankyoHIO.navy.grass_ambcol.b * 2;
return amb;
}
#endif
amb.r = (blade->m_addCol & 0x1F) * 2;
amb.g = ((blade->m_addCol >> 5) & 0x1F) * 2;
amb.b = ((blade->m_addCol >> 0xA) & 0x1F) * 2;
if (daPy_py_c::checkNowWolfPowerUp()) {
f32 ambRate = g_env_light.bg_amb_col[0].r / 255.0f;
f32 col = (((blade->m_addCol & 0x1F) * 2 + 0x10));
amb.r = col * (ambRate * 4.0f);
ambRate = g_env_light.bg_amb_col[0].g / 255.0f;
f32 col2 = (((blade->m_addCol >> 5) & 0x1F) * 2 + 0x10);
amb.g = col2 * (4.0f * ambRate);
ambRate = g_env_light.bg_amb_col[0].b / 255.0f;
f32 col3 = (((blade->m_addCol >> 10) & 0x1F) * 2 + 0x10);
amb.b = col3 * (4.0f * ambRate);
}
f32 roomAmbScale = 1.0f - (static_cast<int>(blade->m_pos.x) & 0xFF) * 0.001953125f;
f32 colScale = 1.1f - (static_cast<u8>(static_cast<int>(blade->m_pos.x)) & 0xFF) / 2000.0f;
colScale -= (static_cast<int>(blade->m_pos.z) & 0xFF) / 2000.0f;
if (colScale > 1.0f) {
colScale = 1.0f;
}
if (amb.r == 0x3E) {
amb.r = tevstr->AmbCol.r * roomAmbScale;
} else {
amb.r = amb.r * colScale;
}
if (amb.g == 0x3E) {
amb.g = tevstr->AmbCol.g * roomAmbScale;
} else {
amb.g = amb.g * colScale;
}
if (amb.b == 0x3E) {
amb.b = tevstr->AmbCol.b * roomAmbScale;
} else {
amb.b = amb.b * colScale;
}
return amb;
}
static void blade_emit(const dusk::batch::LeafTemplate& tpl, const Vec* xformedPos,
const GXColor* colors, GXColor amb) {
for (u32 i = 0; i < tpl.vtxCount; i++) {
const dusk::batch::LeafTemplate::Vtx& v = tpl.vtx[i];
const Vec& p = xformedPos[v.pos];
GXPosition3f32(p.x, p.y, p.z);
GXNormal1x8(v.nrm);
GXColor4u8(amb.r, amb.g, amb.b, colors[v.clr].a);
GXTexCoord1x8(v.tex);
}
}
void dGrass_packet_c::draw() {
ZoneScoped;
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
j3dSys.reinitGX();
GXSetNumIndStages(0);
dKy_setLight_again();
GXClearVtxDesc();
static GXVtxDescList l_vtxDescList[] = {
{GX_VA_POS, GX_INDEX8},
{GX_VA_NRM, GX_INDEX8},
{GX_VA_CLR0, GX_INDEX8},
{GX_VA_TEX0, GX_INDEX8},
{GX_VA_NULL, GX_NONE},
};
static GXVtxDescList l_batchVtxDescList[] = {
{GX_VA_POS, GX_DIRECT},
{GX_VA_NRM, GX_INDEX8},
{GX_VA_CLR0, GX_DIRECT},
{GX_VA_TEX0, GX_INDEX8},
{GX_VA_NULL, GX_NONE},
};
GXSetVtxDescv(l_vtxDescList);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSETARRAY(GX_VA_POS, mp_pos, sizeof(l_pos), sizeof(Vec), true);
GXSETARRAY(GX_VA_NRM, mp_normal, sizeof(l_normal), sizeof(Vec), true);
GXSETARRAY(GX_VA_CLR0, mp_colors, sizeof(l_color), sizeof(GXColor), true);
GXSETARRAY(GX_VA_TEX0, mp_texCoords, sizeof(l_texCoord), 8, true);
GXColorS10 reg1 = {0, 0, 0, 0};
// daytime "shine" alpha curve (TEVREG1 alpha)
f32 daytime = g_env_light.getDaytime();
f32 ratio;
f32 shine;
if (daytime >= 90.0f && daytime < 135.0f) {
ratio = 1.0f - (0.022222223f * (135.0f - daytime));
shine = 100.0f - (18.0f * ratio);
} else if (daytime >= 135.0f && daytime < 225.0f) {
ratio = 1.0f - (0.011111111f * (225.0f - daytime));
shine = 82.0f - (25.0f * ratio);
} else if (daytime >= 225.0f && daytime < 270.0f) {
ratio = 1.0f - (0.022222223f * (270.0f - daytime));
shine = 57.0f - (-25.0f * ratio);
} else if (daytime >= 270.0f && daytime < 315.0f) {
ratio = (1.0f - (0.022222223f * (315.0f - daytime)));
shine = 82.0f - (-18.0f * ratio);
} else {
shine = 100.0f;
}
#if DEBUG
if (g_kankyoHIO.navy.grass_shine_value != 0.0f) {
shine = g_kankyoHIO.navy.grass_shine_value;
}
#endif
static Vec xfPos[256];
Mtx identity;
PSMTXIdentity(identity);
for (int i = 0; i < 64; i++) {
dGrass_data_c* first = m_room[i].getData();
if (first == NULL || !dComIfGp_roomControl_checkStatusFlag(i, 0x10)) {
continue;
}
int lightCount = 6;
dKy_tevstr_c* tevstr = dComIfGp_roomControl_getTevStr(i);
f32 lightInf = g_env_light.grass_light_inf_rate * g_env_light.bg_light_influence;
lightInf += 0.5f * (1.0f - lightInf);
J3DLightInfo* lightInfo = tevstr->mLights[0].getLightInfo();
reg1.r = lightInfo->mColor.r * lightInf;
reg1.g = lightInfo->mColor.g * lightInf;
reg1.b = lightInfo->mColor.b * lightInf;
reg1.a = shine;
if (memcmp(dComIfGp_getStartStageName(), "D_MN01", 6) == 0) {
reg1.r = 0;
reg1.g = 0x1E;
reg1.b = 5;
reg1.a = 0x50;
}
GFSetTevColorS10(GX_TEVREG1, reg1);
if (dComIfGp_roomControl_getStatusRoomDt(i) != nullptr) {
lightCount = dComIfGp_roomControl_getStatusRoomDt(i)->getLightVecInfoNum();
}
#if DEBUG
if (g_kankyoHIO.light.m_HOSTIO_setting != 0) {
lightCount = g_kankyoHIO.dungeonLight.usedLights;
}
#endif
if (dKy_SunMoon_Light_Check() == TRUE && lightCount < 2) {
lightCount = 2;
}
for (int j = 0; j < 6; j++) {
if (kankyo->field_0x0c18[j].field_0x26 == 1) {
lightCount++;
}
}
// room-level setup
if (first->field_0x05 <= 3 || first->field_0x05 >= 10) {
GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0);
if (lightCount <= 3) {
GXCallDisplayList(mp_kusa9q_14_DL, m_kusa9q_DL_14_size);
} else {
GXCallDisplayList(mp_kusa9q_DL, m_kusa9q_DL_size);
}
} else {
GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0);
GXCallDisplayList(l_Tengusa_matDL, 0xA0);
}
GFSetTevColorS10(GX_TEVREG2, {0, 0, 0, 0});
dKy_Global_amb_set(tevstr);
dKy_GfFog_tevstr_set(tevstr);
dKy_setLight_nowroom_grass(tevstr->room_no, 0.0f);
GXSetVtxDescv(l_batchVtxDescList);
GXLoadPosMtxImm(identity, GX_PNMTX0);
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
// buckets: (kusa05 vs tengusa) x (standing vs cut)
bool hasRegrowing = false;
for (int bucket = 0; bucket < 4; bucket++) {
const bool kusaTex = bucket < 2;
const bool cut = (bucket & 1) != 0;
const dusk::batch::LeafTemplate& tpl =
cut ? mTplKusa9qCut : (kusaTex ? mTplKusa9q : mTplTengusa);
bool open = false;
u32 emitted = 0;
for (dGrass_data_c* blade = first; blade != NULL; blade = blade->mp_next) {
if (cLib_checkBit<u8>(blade->field_0x01, 2)) {
continue; // clipped
}
if (blade->field_0x02 < -1) {
hasRegrowing = true;
continue;
}
const bool bladeKusaTex = blade->field_0x05 <= 3 || blade->field_0x05 >= 10;
if (bladeKusaTex != kusaTex || (blade->field_0x02 < 0) != cut) {
continue;
}
if (!open) {
if (kusaTex) {
GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0);
if (lightCount <= 2) {
GXCallDisplayList(mp_kusa9q_14_DL, m_kusa9q_DL_14_size);
} else {
GXCallDisplayList(mp_kusa9q_DL, m_kusa9q_DL_size);
}
} else {
GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0);
GXCallDisplayList(l_Tengusa_matDL, 0xA0);
}
// change amb_src to GX_SRC_VTX
const u32 lightMask =
(kusaTex && lightCount <= 2)
? (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4)
: (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4 | GX_LIGHT5 |
GX_LIGHT6 | GX_LIGHT7);
GXSetChanCtrl(GX_COLOR0, GX_TRUE, GX_SRC_VTX, GX_SRC_REG, lightMask,
GX_DF_CLAMP, GX_AF_SPOT);
reg1.a = cut ? 0 : shine;
GFSetTevColorS10(GX_TEVREG1, reg1);
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
open = true;
}
split_batch(emitted, tpl.vtxCount);
Mtx interpMtx;
MtxP mtx = get_model_mtx(blade->m_modelMtx, interpMtx);
transform_positions(tpl, mp_pos, mtx, xfPos);
blade_emit(tpl, xfPos, mp_colors, blade_amb_color(blade, tevstr));
}
if (open) {
GXEnd();
}
}
// regrowing blades have per-blade TEVREG2 alpha
// draw them with the original immediate path
if (hasRegrowing) {
GXSetVtxDescv(l_vtxDescList);
for (dGrass_data_c* blade = first; blade != NULL; blade = blade->mp_next) {
if (blade->field_0x02 >= -1 || cLib_checkBit<u8>(blade->field_0x01, 2)) {
continue;
}
const bool kusaTex = blade->field_0x05 <= 3 || blade->field_0x05 >= 10;
if (kusaTex) {
GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0);
if (lightCount <= 2) {
GXCallDisplayList(mp_kusa9q_14_DL, m_kusa9q_DL_14_size);
} else {
GXCallDisplayList(mp_kusa9q_DL, m_kusa9q_DL_size);
}
} else {
GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0);
GXCallDisplayList(l_Tengusa_matDL, 0xA0);
}
reg1.a = 0;
GFSetTevColorS10(GX_TEVREG1, reg1);
GXSetChanAmbColor(GX_COLOR0A0, blade_amb_color(blade, tevstr));
Mtx modelMtx;
GXLoadPosMtxImm(get_model_mtx(blade->m_modelMtx, modelMtx), GX_PNMTX0);
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
GFSetTevColorS10(GX_TEVREG2,
{0, 0, 0, static_cast<s16>(-0x100 - (blade->field_0x02 << 8) / 40)});
if (blade->field_0x02 != -2) {
if (kusaTex) {
GXCallDisplayList(mp_Mkusa_9q_DL, m_Mkusa_9q_DL_size);
} else {
GXCallDisplayList(l_M_TenGusaDL, 0xC0);
}
} else {
GXCallDisplayList(mp_Mkusa_9q_cDL, m_Mkusa_9q_cDL_size);
}
GFSetTevColorS10(GX_TEVREG2, {0, 0, 0, 0});
}
}
}
J3DShape::resetVcdVatCache();
}
#else
void dGrass_packet_c::draw() { void dGrass_packet_c::draw() {
ZoneScoped; ZoneScoped;
dScnKy_env_light_c* kankyo = dKy_getEnvlight(); dScnKy_env_light_c* kankyo = dKy_getEnvlight();
@@ -1166,7 +811,6 @@ void dGrass_packet_c::draw() {
J3DShape::resetVcdVatCache(); J3DShape::resetVcdVatCache();
} }
#endif
void dGrass_packet_c::calc() { void dGrass_packet_c::calc() {
cXyz* temp_r29 = dKyw_get_wind_vec(); cXyz* temp_r29 = dKyw_get_wind_vec();
+8 -47
View File
@@ -34,7 +34,6 @@
#include "dusk/action_bindings.h" #include "dusk/action_bindings.h"
#include "dusk/mouse.h" #include "dusk/mouse.h"
#include "dusk/settings.h" #include "dusk/settings.h"
#include "dusk/touch_camera.h"
#include "imgui.h" #include "imgui.h"
#endif #endif
@@ -7500,15 +7499,6 @@ static constexpr s16 FLYCAM_ROLL_SPEED = 256;
static ImVec2 sFlyCamLastMousePos = {-1.f, -1.f}; static ImVec2 sFlyCamLastMousePos = {-1.f, -1.f};
#if TARGET_PC #if TARGET_PC
static constexpr f32 TOUCH_CAMERA_CSTICK_EXIT_THRESHOLD = 0.05f;
static bool sTouchFreeCameraActive = false;
bool dCamera_c::isAimActive() {
auto* link = daAlink_getAlinkActorClass();
return link != nullptr && link->checkAimInputContext() &&
dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10);
}
bool dCamera_c::executeDebugFlyCam() { bool dCamera_c::executeDebugFlyCam() {
if (!dusk::getSettings().game.debugFlyCam) { if (!dusk::getSettings().game.debugFlyCam) {
if (mDebugFlyCam.initialized) { if (mDebugFlyCam.initialized) {
@@ -7602,10 +7592,6 @@ bool dCamera_c::executeDebugFlyCam() {
sFlyCamLastMousePos = mouseValid ? io.MousePos : ImVec2{-1.0f, -1.0f}; sFlyCamLastMousePos = mouseValid ? io.MousePos : ImVec2{-1.0f, -1.0f};
} }
if (dusk::getSettings().game.enableMirrorMode) {
stickX *= -1.0f;
}
f32 verticalDisp = 0.0f; f32 verticalDisp = 0.0f;
if (trigR >= FLYCAM_TRIGGER_DEADZONE) { if (trigR >= FLYCAM_TRIGGER_DEADZONE) {
verticalDisp += trigR; verticalDisp += trigR;
@@ -7654,30 +7640,16 @@ void dCamera_c::deactivateDebugFlyCam() {
mDebugFlyCam.initialized = false; mDebugFlyCam.initialized = false;
} }
bool dCamera_c::freeCamera() { bool dCamera_c::canUseFreeCam() {
f32 touchYawDp = 0.0f; return dusk::getSettings().game.freeCamera || dusk::getSettings().game.enableMouseCamera;
f32 touchPitchDp = 0.0f; }
bool touchCameraMoved = false;
const bool touchControlsEnabled = dusk::getSettings().game.enableTouchControls;
if (touchControlsEnabled && !isAimActive()) {
touchCameraMoved = dusk::touch_camera::consume_delta(touchYawDp, touchPitchDp);
}
if (!touchControlsEnabled ||
mPadInfo.mCStick.mLastValue > TOUCH_CAMERA_CSTICK_EXIT_THRESHOLD)
{
sTouchFreeCameraActive = false;
}
if (touchCameraMoved) {
sTouchFreeCameraActive = true;
}
const bool useFreeCamera = dusk::getSettings().game.freeCamera || bool dCamera_c::freeCamera() {
dusk::getSettings().game.enableMouseCamera || sTouchFreeCameraActive; if (canUseFreeCam() && mGear == 1) {
if (useFreeCamera && mGear == 1) {
mGear = 0; mGear = 0;
} }
if (!useFreeCamera || mCamStyle == 70) if (!canUseFreeCam() || mCamStyle == 70)
{ {
mCamParam.mManualMode = 0; mCamParam.mManualMode = 0;
return false; return false;
@@ -7688,17 +7660,6 @@ bool dCamera_c::freeCamera() {
mCamParam.freeYAngle = mViewCache.mDirection.mInclination.Degree(); mCamParam.freeYAngle = mViewCache.mDirection.mInclination.Degree();
} }
if (touchCameraMoved) {
mCamParam.mManualMode = 1;
const f32 yawInput = dusk::getSettings().game.invertCameraXAxis ? -touchYawDp : touchYawDp;
const f32 pitchInput =
touchPitchDp * (dusk::getSettings().game.invertCameraYAxis ? -1.0f : 1.0f);
mCamParam.freeXAngle += yawInput * dusk::getSettings().game.touchCameraXSensitivity *
dusk::touch_camera::YAW_DEGREES_PER_DP;
mCamParam.freeYAngle += pitchInput * dusk::getSettings().game.touchCameraYSensitivity *
dusk::touch_camera::PITCH_DEGREES_PER_DP;
}
cXyz camMovement = {mPadInfo.mCStick.mLastPosX, mPadInfo.mCStick.mLastPosY, 0.0f}; cXyz camMovement = {mPadInfo.mCStick.mLastPosX, mPadInfo.mCStick.mLastPosY, 0.0f};
f32 magnitude = sqrt(mPadInfo.mCStick.mLastPosX * mPadInfo.mCStick.mLastPosX + mPadInfo.mCStick.mLastPosY * mPadInfo.mCStick.mLastPosY); f32 magnitude = sqrt(mPadInfo.mCStick.mLastPosX * mPadInfo.mCStick.mLastPosX + mPadInfo.mCStick.mLastPosY * mPadInfo.mCStick.mLastPosY);
@@ -7716,7 +7677,7 @@ bool dCamera_c::freeCamera() {
f32 yaw_rad = 0.0f; f32 yaw_rad = 0.0f;
f32 pitch_rad = 0.0f; f32 pitch_rad = 0.0f;
dusk::mouse::get_camera_deltas(yaw_rad, pitch_rad); dusk::mouse::getCameraDeltas(yaw_rad, pitch_rad);
if (dusk::getSettings().game.enableMouseCamera && (yaw_rad != 0.0f || pitch_rad != 0.0f) && if (dusk::getSettings().game.enableMouseCamera && (yaw_rad != 0.0f || pitch_rad != 0.0f) &&
!dComIfGp_checkCameraAttentionStatus(dComIfGp_getPlayerCameraID(0), 0x8)) !dComIfGp_checkCameraAttentionStatus(dComIfGp_getPlayerCameraID(0), 0x8))
{ {
@@ -11398,7 +11359,7 @@ static int camera_execute(camera_process_class* i_this) {
const auto target = get_target_trim_height(i_this); const auto target = get_target_trim_height(i_this);
const auto step = dusk::frame_interp::get_interpolation_step(); const auto step = dusk::frame_interp::get_interpolation_step();
const auto cur = camera->TrimHeight(); const auto cur = camera->TrimHeight();
const auto prev = (4.0f * cur - target) / 3.0f; const auto prev = (4.0f * cur - target) / 3.0f;
const auto trim_height = prev + (cur - prev) * step; const auto trim_height = prev + (cur - prev) * step;
widezoom_correction(i_this, trim_height); widezoom_correction(i_this, trim_height);
-325
View File
@@ -23,22 +23,8 @@
#include "m_Do/m_Do_graphic.h" #include "m_Do/m_Do_graphic.h"
#include <cstring> #include <cstring>
#if TARGET_PC
#include "dusk/menu_pointer.h"
#include "dusk/string.hpp" #include "dusk/string.hpp"
namespace {
constexpr u8 pointer_target(u8 group, u8 index) noexcept {
return static_cast<u8>((group << 4) | (index & 0x0F));
}
constexpr u8 s_pointerDataSelectTarget = 0;
constexpr u8 s_pointerMenuSelectTarget = 1;
constexpr u8 s_pointerCopySelectTarget = 2;
constexpr u8 s_pointerYesNoSelectTarget = 3;
} // namespace
#endif
static s32 SelStartFrameTbl[3] = { static s32 SelStartFrameTbl[3] = {
59, 59,
99, 99,
@@ -770,147 +756,8 @@ void dFile_select_c::dataSelectInit() {
} }
} }
#if TARGET_PC
bool dFile_select_c::pointerDataSelect() {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
for (u8 i = 0; i < 3; ++i) {
if (!dusk::menu_pointer::hit_pane(mSelFilePanes[i], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerDataSelectTarget, i));
const bool clicked = dusk::menu_pointer::consume_click();
if (mSelectNum != i) {
mDoAud_seStart(Z2SE_FILE_SELECT_CURSOR, NULL, 0, 0);
mLastSelectNum = mSelectNum;
mSelectNum = i;
if (clicked) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerDataSelectTarget, i));
}
dataSelectAnmSet();
mDataSelProc = DATASELPROC_DATA_SELECT_MOVE_ANIME;
return true;
}
if (clicked) {
dataSelectStart();
return true;
}
}
return false;
}
bool dFile_select_c::pointerMenuSelect() {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
for (u8 i = 0; i < 3; ++i) {
if (!dusk::menu_pointer::hit_pane(m3mSelPane[i], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerMenuSelectTarget, i));
const bool clicked = dusk::menu_pointer::consume_click();
if (!mIsDataNew[mSelectNum] && mSelectMenuNum != i) {
mDoAud_seStart(Z2SE_SY_MENU_CURSOR_COMMON, NULL, 0, 0);
mLastSelectMenuNum = mSelectMenuNum;
mSelectMenuNum = i;
if (clicked) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerMenuSelectTarget, i));
}
menuSelectAnmSet();
mDataSelProc = DATASELPROC_MENU_SELECT_MOVE_ANM;
return true;
}
if (clicked) {
menuSelectStart();
return true;
}
}
return false;
}
bool dFile_select_c::pointerCopyDataToSelect() {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
for (u8 i = 0; i < 2; ++i) {
if (!dusk::menu_pointer::hit_pane(mCpSelPane[i], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerCopySelectTarget, i));
const bool clicked = dusk::menu_pointer::consume_click();
if (field_0x026b != i) {
mDoAud_seStart(Z2SE_FILE_SELECT_CURSOR, NULL, 0, 0);
field_0x026c = field_0x026b;
field_0x026b = i;
if (clicked) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerCopySelectTarget, i));
}
copyDataToSelectMoveAnmSet();
mDataSelProc = DATASELPROC_COPY_DATA_TO_SELECT_MOVE_ANM;
return true;
}
if (clicked) {
copyDataToSelectStart();
return true;
}
}
return false;
}
bool dFile_select_c::pointerYesNoSelect(bool errorSelect) {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
for (u8 i = 0; i < 2; ++i) {
if (!dusk::menu_pointer::hit_pane(mYnSelPane[i], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerYesNoSelectTarget, i));
const bool clicked =
(!errorSelect || field_0x0268 == i) && dusk::menu_pointer::consume_click();
if (field_0x0268 != i) {
field_0x0269 = field_0x0268;
field_0x0268 = i;
if (errorSelect) {
errCurMove(0);
return false;
} else {
mDoAud_seStart(Z2SE_SY_MENU_CURSOR_COMMON, NULL, 0, 0);
if (clicked) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerYesNoSelectTarget, i));
}
yesnoSelectAnmSet();
mDataSelProc = DATASELPROC_YES_NO_CURSOR_MOVE_ANM;
return true;
}
}
if (clicked) {
if (errorSelect) {
if (field_0x0268 != 0) {
mDoAud_seStart(Z2SE_SY_CURSOR_OK, 0, 0, 0);
} else {
mDoAud_seStart(Z2SE_SY_CURSOR_CANCEL, 0, 0, 0);
}
mSelIcon->setAlphaRate(0.0f);
} else {
yesNoSelectStart();
}
return true;
}
}
return false;
}
#endif
// handles switching between quest logs // handles switching between quest logs
void dFile_select_c::dataSelect() { void dFile_select_c::dataSelect() {
#if TARGET_PC
if (pointerDataSelect()) {
return;
}
#endif
stick->checkTrigger(); stick->checkTrigger();
// If A or Start was pressed // If A or Start was pressed
@@ -954,9 +801,6 @@ static u16 msgTbl[3] = {
}; };
void dFile_select_c::dataSelectStart() { void dFile_select_c::dataSelectStart() {
#if TARGET_PC
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::FileSelect);
#endif
mSelIcon->setAlphaRate(0.0f); mSelIcon->setAlphaRate(0.0f);
if (mIsNoData[mSelectNum]) { if (mIsNoData[mSelectNum]) {
@@ -1105,17 +949,6 @@ void dFile_select_c::dataSelectAnmSet() {
} }
void dFile_select_c::dataSelectMoveAnime() { void dFile_select_c::dataSelectMoveAnime() {
#if TARGET_PC
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
if (mSelectNum != 0xFF && dusk::menu_pointer::hit_pane(mSelFilePanes[mSelectNum], 8.0f)) {
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerDataSelectTarget, mSelectNum));
if (dusk::menu_pointer::consume_click()) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerDataSelectTarget, mSelectNum));
}
}
#endif
bool iVar7 = true; bool iVar7 = true;
bool iVar6 = true; bool iVar6 = true;
bool bVar1 = true; bool bVar1 = true;
@@ -1164,14 +997,6 @@ void dFile_select_c::dataSelectMoveAnime() {
mSelFilePanes[mLastSelectNum]->getPanePtr()->setAnimation((J2DAnmTransform*)NULL); mSelFilePanes[mLastSelectNum]->getPanePtr()->setAnimation((J2DAnmTransform*)NULL);
} }
#if TARGET_PC
if (dusk::menu_pointer::consume_deferred_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerDataSelectTarget, mSelectNum))) {
dataSelectStart();
return;
}
#endif
mDataSelProc = DATASELPROC_DATA_SELECT; mDataSelProc = DATASELPROC_DATA_SELECT;
} }
} }
@@ -1336,12 +1161,6 @@ void dFile_select_c::selectDataOpenEraseMove() {
// Handles selecting between copy / start / delete menus in quest log // Handles selecting between copy / start / delete menus in quest log
void dFile_select_c::menuSelect() { void dFile_select_c::menuSelect() {
#if TARGET_PC
if (pointerMenuSelect()) {
return;
}
#endif
stick->checkTrigger(); stick->checkTrigger();
// if a was pressed, do the menu selection process // if a was pressed, do the menu selection process
@@ -1372,9 +1191,6 @@ void dFile_select_c::menuSelect() {
// Handles copy / start / delete actions depending on which menu is selected from menuSelect // Handles copy / start / delete actions depending on which menu is selected from menuSelect
void dFile_select_c::menuSelectStart() { void dFile_select_c::menuSelectStart() {
#if TARGET_PC
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::FileSelect);
#endif
#if TARGET_PC #if TARGET_PC
if (!dusk::getSettings().game.hideTvSettingsScreen || mSelectMenuNum != 1) { if (!dusk::getSettings().game.hideTvSettingsScreen || mSelectMenuNum != 1) {
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0); mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
@@ -1496,19 +1312,6 @@ void dFile_select_c::menuSelectAnmSet() {
} }
void dFile_select_c::menuSelectMoveAnm() { void dFile_select_c::menuSelectMoveAnm() {
#if TARGET_PC
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
if (mSelectMenuNum != 0xFF &&
dusk::menu_pointer::hit_pane(m3mSelPane[mSelectMenuNum], 8.0f))
{
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerMenuSelectTarget, mSelectMenuNum));
if (dusk::menu_pointer::consume_click()) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerMenuSelectTarget, mSelectMenuNum));
}
}
#endif
bool tmp1 = true; bool tmp1 = true;
if (mSelectMenuNum != 0xFF && if (mSelectMenuNum != 0xFF &&
@@ -1566,14 +1369,6 @@ void dFile_select_c::menuSelectMoveAnm() {
m3mSelPane[mLastSelectMenuNum]->getPanePtr()->setAnimation((J2DAnmTransform*)NULL); m3mSelPane[mLastSelectMenuNum]->getPanePtr()->setAnimation((J2DAnmTransform*)NULL);
} }
#if TARGET_PC
if (dusk::menu_pointer::consume_deferred_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerMenuSelectTarget, mSelectMenuNum))) {
menuSelectStart();
return;
}
#endif
mDataSelProc = DATASELPROC_MENU_SELECT; mDataSelProc = DATASELPROC_MENU_SELECT;
} }
} }
@@ -1903,12 +1698,6 @@ void dFile_select_c::setSaveDataForCopySel() {
} }
void dFile_select_c::copyDataToSelect() { void dFile_select_c::copyDataToSelect() {
#if TARGET_PC
if (pointerCopyDataToSelect()) {
return;
}
#endif
stick->checkTrigger(); stick->checkTrigger();
if (mDoCPd_c::getTrigA(PAD_1)) { if (mDoCPd_c::getTrigA(PAD_1)) {
@@ -1933,9 +1722,6 @@ void dFile_select_c::copyDataToSelect() {
} }
void dFile_select_c::copyDataToSelectStart() { void dFile_select_c::copyDataToSelectStart() {
#if TARGET_PC
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::FileSelect);
#endif
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0); mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
mCpDataToNum = getCptoNum(field_0x026b); mCpDataToNum = getCptoNum(field_0x026b);
@@ -2001,19 +1787,6 @@ void dFile_select_c::copyDataToSelectMoveAnmSet() {
} }
void dFile_select_c::copyDataToSelectMoveAnm() { void dFile_select_c::copyDataToSelectMoveAnm() {
#if TARGET_PC
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
if (field_0x026b != 0xFF &&
dusk::menu_pointer::hit_pane(mCpSelPane[field_0x026b], 8.0f))
{
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerCopySelectTarget, field_0x026b));
if (dusk::menu_pointer::consume_click()) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerCopySelectTarget, field_0x026b));
}
}
#endif
bool iVar7 = true; bool iVar7 = true;
bool iVar6 = true; bool iVar6 = true;
bool bVar1 = true; bool bVar1 = true;
@@ -2063,14 +1836,6 @@ void dFile_select_c::copyDataToSelectMoveAnm() {
mSelIcon2->setAlphaRate(1.0f); mSelIcon2->setAlphaRate(1.0f);
} }
#if TARGET_PC
if (dusk::menu_pointer::consume_deferred_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerCopySelectTarget, field_0x026b))) {
copyDataToSelectStart();
return;
}
#endif
mDataSelProc = DATASELPROC_COPY_DATA_TO_SELECT; mDataSelProc = DATASELPROC_COPY_DATA_TO_SELECT;
} }
} }
@@ -2340,12 +2105,6 @@ void dFile_select_c::yesnoCursorShow() {
} }
void dFile_select_c::YesNoSelect() { void dFile_select_c::YesNoSelect() {
#if TARGET_PC
if (pointerYesNoSelect(false)) {
return;
}
#endif
stick->checkTrigger(); stick->checkTrigger();
if (mDoCPd_c::getTrigA(PAD_1)) { if (mDoCPd_c::getTrigA(PAD_1)) {
@@ -2370,9 +2129,6 @@ void dFile_select_c::YesNoSelect() {
} }
void dFile_select_c::yesNoSelectStart() { void dFile_select_c::yesNoSelectStart() {
#if TARGET_PC
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::FileSelect);
#endif
if (field_0x0268 != 0) { if (field_0x0268 != 0) {
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0); mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
field_0x03b1 = 1; field_0x03b1 = 1;
@@ -2528,31 +2284,10 @@ void dFile_select_c::YesNoCancelMove() {
} }
void dFile_select_c::yesNoCursorMoveAnm() { void dFile_select_c::yesNoCursorMoveAnm() {
#if TARGET_PC
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
if (field_0x0268 != 0xFF &&
dusk::menu_pointer::hit_pane(mYnSelPane[field_0x0268], 8.0f))
{
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerYesNoSelectTarget, field_0x0268));
if (dusk::menu_pointer::consume_click()) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerYesNoSelectTarget, field_0x0268));
}
}
#endif
bool isYnSelMove = yesnoSelectMoveAnm(); bool isYnSelMove = yesnoSelectMoveAnm();
bool isYnWakuAlpha = yesnoWakuAlpahAnm(field_0x0269); bool isYnWakuAlpha = yesnoWakuAlpahAnm(field_0x0269);
if (isYnSelMove == true && isYnWakuAlpha == true) { if (isYnSelMove == true && isYnWakuAlpha == true) {
yesnoCursorShow(); yesnoCursorShow();
#if TARGET_PC
if (dusk::menu_pointer::consume_deferred_activation(
dusk::menu_pointer::Context::FileSelect,
pointer_target(s_pointerYesNoSelectTarget, field_0x0268))) {
yesNoSelectStart();
return;
}
#endif
mDataSelProc = DATASELPROC_YES_NO_SELECT; mDataSelProc = DATASELPROC_YES_NO_SELECT;
} }
} }
@@ -4503,11 +4238,6 @@ static MemCardCheckFuncT MemCardCheckProc[] = {
&dFile_select_c::MemCardErrYesNoCursorMoveAnm, &dFile_select_c::MemCardErrYesNoCursorMoveAnm,
&dFile_select_c::MemCardSaveDataClear, &dFile_select_c::MemCardSaveDataClear,
#if TARGET_PC
&dFile_select_c::MemCardAutoMakeGameFile,
&dFile_select_c::MemCardAutoMakeGameFileErrWait,
#endif
#if PLATFORM_WII || PLATFORM_SHIELD #if PLATFORM_WII || PLATFORM_SHIELD
&dFile_select_c::nandStatCheck, &dFile_select_c::nandStatCheck,
&dFile_select_c::gameFileInitSel, &dFile_select_c::gameFileInitSel,
@@ -4591,33 +4321,11 @@ void dFile_select_c::MemCardStatCheck() {
mDoMemCd_Load(); mDoMemCd_Load();
mCardCheckProc = MEMCARDCHECKPROC_LOAD_WAIT; mCardCheckProc = MEMCARDCHECKPROC_LOAD_WAIT;
break; break;
#if TARGET_PC
case 1: { // no save file
if (dusk::getSettings().game.instantSaves) {
field_0x03b1 = 1;
setInitSaveData();
dataSave();
mCardCheckProc = MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE;
} else {
errDispInitSet(22, 0);
field_0x0280 = true;
mNextCardCheckProc = MEMCARDCHECKPROC_MAKE_GAMEFILE_SEL;
}
break;
}
case 4: // card is writing
if (dusk::getSettings().game.instantSaves) {
field_0x03b1 = 1;
mCardCheckProc = MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE;
}
break;
#else
case 1: case 1:
errDispInitSet(22, 0); errDispInitSet(22, 0);
field_0x0280 = true; field_0x0280 = true;
mNextCardCheckProc = MEMCARDCHECKPROC_MAKE_GAMEFILE_SEL; mNextCardCheckProc = MEMCARDCHECKPROC_MAKE_GAMEFILE_SEL;
break; break;
#endif
} }
#else #else
switch (status) { switch (status) {
@@ -5323,33 +5031,6 @@ void dFile_select_c::MemCardMakeGameFileCheck() {
} }
} }
#if TARGET_PC
void dFile_select_c::MemCardAutoMakeGameFile() {
field_0x03b4 = mDoMemCd_SaveSync();
if (field_0x03b4 == 0) {
return;
}
field_0x03b1 = 0;
if (field_0x03b4 == 1) {
mDoMemCd_Load();
mCardCheckProc = MEMCARDCHECKPROC_LOAD_WAIT;
} else {
errDispInitSet(0x1A, 0);
field_0x0280 = false;
mWindowCloseMsgDispCb = NULL;
mKeyWaitMsgDispCb = NULL;
mNextCardCheckProc = MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE_ERR_WAIT;
}
}
void dFile_select_c::MemCardAutoMakeGameFileErrWait() {
mNextCardCheckProc = MEMCARDCHECKPROC_STAT_CHECK;
mKeyWaitCardCheckProc = MEMCARDCHECKPROC_MSG_WINDOW_CLOSE;
mCardCheckProc = MEMCARDCHECKPROC_ERRMSG_WAIT_KEY;
}
#endif
#if PLATFORM_WII || PLATFORM_SHIELD #if PLATFORM_WII || PLATFORM_SHIELD
void dFile_select_c::gameFileInitSel() { void dFile_select_c::gameFileInitSel() {
if (errYesNoSelect() != 0) { if (errYesNoSelect() != 0) {
@@ -5503,12 +5184,6 @@ void dFile_select_c::MemCardMsgWindowClose() {
bool dFile_select_c::errYesNoSelect() { bool dFile_select_c::errYesNoSelect() {
bool rv = false; bool rv = false;
#if TARGET_PC
if (pointerYesNoSelect(true)) {
return true;
}
#endif
stick->checkTrigger(); stick->checkTrigger();
if (mDoCPd_c::getTrigA(PAD_1)) { if (mDoCPd_c::getTrigA(PAD_1)) {
+1 -28
View File
@@ -1213,10 +1213,6 @@ void dMap_c::changeTextureSize(int param_1, int param_2, int param_3) {
JUT_ASSERT(2672, mImage_p != NULL); JUT_ASSERT(2672, mImage_p != NULL);
JUT_ASSERT(2673, mResTIMG != NULL); JUT_ASSERT(2673, mResTIMG != NULL);
#if TARGET_PC
GXDestroyCopyTex(mImage_p);
#endif
mTexSizeX = param_1 >> param_3; mTexSizeX = param_1 >> param_3;
mTexSizeY = param_2 >> param_3; mTexSizeY = param_2 >> param_3;
@@ -1230,24 +1226,6 @@ void dMap_c::changeTextureSize(int param_1, int param_2, int param_3) {
} }
#endif #endif
#if TARGET_PC
bool dMap_c::refreshTextureSize() {
JUT_ASSERT(2688, mImage_p != NULL);
JUT_ASSERT(2689, mResTIMG != NULL);
const u16 oldWidth = mResTIMG->width;
const u16 oldHeight = mResTIMG->height;
makeResTIMG(mResTIMG, mTexSizeX, mTexSizeY, mImage_p, (u8*)m_res, 0x33);
if (mResTIMG->width == oldWidth && mResTIMG->height == oldHeight) {
return false;
}
GXDestroyCopyTex(mImage_p);
return true;
}
#endif
void dMap_c::_remove() { void dMap_c::_remove() {
if (mImage_p != NULL) { if (mImage_p != NULL) {
#if TARGET_PC #if TARGET_PC
@@ -1640,7 +1618,7 @@ void dMap_c::_move(f32 i_centerX, f32 i_centerZ, int i_roomNo, f32 param_3) {
mCenterX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -mPackX :) mPackX; mCenterX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -mPackX :) mPackX;
mCenterZ -= mPackZ; mCenterZ -= mPackZ;
mCenterX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -field_0x64 : ) field_0x64; mCenterX += field_0x64;
mCenterZ += mPackPlusZ; mCenterZ += mPackPlusZ;
} }
@@ -1649,8 +1627,6 @@ void dMap_c::_move(f32 i_centerX, f32 i_centerZ, int i_roomNo, f32 param_3) {
{ {
#if DEBUG #if DEBUG
field_0x64 = 33830.0f; field_0x64 = 33830.0f;
#elif TARGET_PC
field_0x64 = dusk::getSettings().game.enableMirrorMode ? 33830.0f : 0.0f;
#else #else
field_0x64 = 0.0f; field_0x64 = 0.0f;
#endif #endif
@@ -1659,9 +1635,6 @@ void dMap_c::_move(f32 i_centerX, f32 i_centerZ, int i_roomNo, f32 param_3) {
f32 temp = (field_0x58 * (f32)(field_0x74 + 4)) * 0.5f; f32 temp = (field_0x58 * (f32)(field_0x74 + 4)) * 0.5f;
#if DEBUG #if DEBUG
mRightEdgePlus = -(((dMpath_c::getMinZ() - (-127103.67f)) - temp) / field_0x58); mRightEdgePlus = -(((dMpath_c::getMinZ() - (-127103.67f)) - temp) / field_0x58);
#elif TARGET_PC
mRightEdgePlus = dusk::getSettings().game.enableMirrorMode ? -(((dMpath_c::getMinX() - (-127103.67f)) - temp) / field_0x58) : 0.0f;
#else #else
mRightEdgePlus = 0.0f; mRightEdgePlus = 0.0f;
#endif #endif
+32 -45
View File
@@ -15,49 +15,32 @@
#include <cstring> #include <cstring>
#ifdef TARGET_PC #ifdef TARGET_PC
#include "dusk/settings.h"
#include "m_Do/m_Do_graphic.h"
#include <dolphin/gx/GXAurora.h>
#include <aurora/math.hpp>
#include <algorithm>
#include <array>
#include <cmath>
#include <functional>
#include <limits>
#include <numbers>
#include <span> #include <span>
#include <numbers>
#include <array>
constexpr u16 kMapIconResolutionMultiplier = 4; constexpr u16 kPreferredMapResolutionMultiplier = 1;
constexpr u16 kMapImageSide = 16 * kMapIconResolutionMultiplier; constexpr u32 kMaxMapRenderPixels = 2048 * 2048;
constexpr u16 kMapImageSide = 16 * kPreferredMapResolutionMultiplier;
constexpr u32 kMapImageTotalPixels = kMapImageSide * kMapImageSide; constexpr u32 kMapImageTotalPixels = kMapImageSide * kMapImageSide;
typedef std::function<u8(size_t, size_t)> PaintI8Fn; typedef std::function<u8(size_t, size_t)> PaintI8Fn;
u16 scaled_map_axis(u16 value, f32 scale) { u16 map_resolution_multiplier(u16 width, u16 height) {
const auto scaledValue = const u32 basePixels = static_cast<u32>(width) * height;
static_cast<u32>(std::max(1.0f, std::round(static_cast<f32>(value) * scale))); if (basePixels == 0) {
return static_cast<u16>(std::min<u32>(scaledValue, std::numeric_limits<u16>::max())); return 1;
}
aurora::Vec2<u16> map_render_size_for(u16 width, u16 height) {
if (width == 0 || height == 0) {
return {width, height};
} }
u32 renderWidth = 0; u16 scale = kPreferredMapResolutionMultiplier;
u32 renderHeight = 0; while (scale > 1) {
AuroraGetRenderSize(&renderWidth, &renderHeight); const u32 scalePixels = static_cast<u32>(scale) * scale;
if (basePixels <= kMaxMapRenderPixels / scalePixels) {
const f32 logicalWidth = std::max(mDoGph_gInf_c::getWidthF(), 1.0f); break;
const f32 logicalHeight = std::max(mDoGph_gInf_c::getHeightF(), 1.0f); }
const f32 irScaleX = renderWidth > 0 ? static_cast<f32>(renderWidth) / logicalWidth : 1.0f; scale--;
const f32 irScaleY = renderHeight > 0 ? static_cast<f32>(renderHeight) / logicalHeight : 1.0f; }
const f32 hudScale = std::clamp(dusk::getSettings().game.hudScale.getValue(), 0.5f, 2.0f); return scale;
return {
scaled_map_axis(width, irScaleX * hudScale),
scaled_map_axis(height, irScaleY * hudScale),
};
} }
void paint_i8(std::span<u8> dst, size_t width, PaintI8Fn paint) { void paint_i8(std::span<u8> dst, size_t width, PaintI8Fn paint) {
@@ -513,9 +496,9 @@ void dRenderingMap_c::makeResTIMG(ResTIMG* p_image, u16 width, u16 height, u8* p
p_image->format = GX_TF_C8; p_image->format = GX_TF_C8;
p_image->alphaEnabled = 2; p_image->alphaEnabled = 2;
#ifdef TARGET_PC #ifdef TARGET_PC
const auto [rw, rh] = map_render_size_for(width, height); const u16 scale = map_resolution_multiplier(width, height);
p_image->width = rw; p_image->width = width * scale;
p_image->height = rh; p_image->height = height * scale;
#else #else
p_image->width = width; p_image->width = width;
p_image->height = height; p_image->height = height;
@@ -598,14 +581,16 @@ void dRenderingFDAmap_c::drawBack() const {
void dRenderingFDAmap_c::preRenderingMap() { void dRenderingFDAmap_c::preRenderingMap() {
#ifdef TARGET_PC #ifdef TARGET_PC
const auto [rw, rh] = map_render_size_for(mTexWidth, mTexHeight); const u16 scale = map_resolution_multiplier(mTexWidth, mTexHeight);
GXCreateFrameBuffer(rw, rh); const u16 w = mTexWidth * scale;
const u16 h = mTexHeight * scale;
GXCreateFrameBuffer(w, h);
// Set logical viewport dimensions // Set logical viewport dimensions
GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f); GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f);
GXSetScissor(0, 0, mTexWidth, mTexHeight); GXSetScissor(0, 0, mTexWidth, mTexHeight);
// Set render viewport dimensions // Set render viewport dimensions
GXSetViewportRender(0.0f, 0.0f, rw, rh, 0.0f, 1.0f); GXSetViewportRender(0.0f, 0.0f, w, h, 0.0f, 1.0f);
GXSetScissorRender(0, 0, rw, rh); GXSetScissorRender(0, 0, w, h);
#else #else
GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f); GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f);
GXSetScissor(0, 0, mTexWidth, mTexHeight); GXSetScissor(0, 0, mTexWidth, mTexHeight);
@@ -643,9 +628,11 @@ void dRenderingFDAmap_c::preRenderingMap() {
void dRenderingFDAmap_c::postRenderingMap() { void dRenderingFDAmap_c::postRenderingMap() {
GXSetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL); GXSetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL);
#ifdef TARGET_PC #ifdef TARGET_PC
const auto [rw, rh] = map_render_size_for(mTexWidth, mTexHeight); const u16 scale = map_resolution_multiplier(mTexWidth, mTexHeight);
GXSetTexCopySrc(0, 0, rw, rh); const u16 w = mTexWidth * scale;
GXSetTexCopyDst(rw, rh, GX_CTF_R8, GX_FALSE); const u16 h = mTexHeight * scale;
GXSetTexCopySrc(0, 0, w, h);
GXSetTexCopyDst(w, h, GX_CTF_R8, GX_FALSE);
GXCopyTex(field_0x4, GX_TRUE); GXCopyTex(field_0x4, GX_TRUE);
GXRestoreFrameBuffer(); GXRestoreFrameBuffer();
#else #else
-92
View File
@@ -36,10 +36,6 @@
#include "d/d_menu_window.h" #include "d/d_menu_window.h"
#include "JSystem/J3DGraphBase/J3DMaterial.h" #include "JSystem/J3DGraphBase/J3DMaterial.h"
#if TARGET_PC
#include "dusk/menu_pointer.h"
#endif
typedef void (dMenu_Collect2D_c::*initFunc)(); typedef void (dMenu_Collect2D_c::*initFunc)();
static DUSK_CONSTEXPR initFunc init[] = { static DUSK_CONSTEXPR initFunc init[] = {
&dMenu_Collect2D_c::wait_init, &dMenu_Collect2D_c::save_open_init, &dMenu_Collect2D_c::wait_init, &dMenu_Collect2D_c::save_open_init,
@@ -1790,12 +1786,6 @@ void dMenu_Collect2D_c::wait_init() {
} }
void dMenu_Collect2D_c::wait_proc() { void dMenu_Collect2D_c::wait_proc() {
#if TARGET_PC
if (pointerWait()) {
return;
}
#endif
if (dMw_A_TRIGGER()) { if (dMw_A_TRIGGER()) {
if (mCursorX == 0 && mCursorY == 5) { if (mCursorX == 0 && mCursorY == 5) {
if (mDoGph_gInf_c::getFader()->mStatus == 1) { if (mDoGph_gInf_c::getFader()->mStatus == 1) {
@@ -1897,88 +1887,6 @@ void dMenu_Collect2D_c::wait_proc() {
} }
} }
#if TARGET_PC
void dMenu_Collect2D_c::pointerActivateCurrent() {
if (mCursorX == 0 && mCursorY == 5) {
if (mDoGph_gInf_c::getFader()->mStatus == 1) {
mSubWindowOpenCheck = 1;
Z2GetAudioMgr()->seStart(Z2SE_SY_MENU_CHANGE_WINDOW, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
dMeter2Info_set2DVibrationM();
}
} else if (mCursorX == 1 && mCursorY == 5) {
if (mDoGph_gInf_c::getFader()->mStatus == 1) {
mSubWindowOpenCheck = 2;
Z2GetAudioMgr()->seStart(Z2SE_SY_MENU_CHANGE_WINDOW, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
dMeter2Info_set2DVibrationM();
}
} else if (mCursorX == 3 && mCursorY == 4) {
if (field_0x22d[3][4] != 0 && mDoGph_gInf_c::getFader()->mStatus == 1) {
mSubWindowOpenCheck = 3;
dMeter2Info_set2DVibration();
}
} else if (mCursorX == 2 && mCursorY == 4) {
if (isFishIconVisible() && mDoGph_gInf_c::getFader()->mStatus == 1) {
mSubWindowOpenCheck = 4;
dMeter2Info_set2DVibration();
}
} else if (mCursorX == 3 && mCursorY == 3) {
if (isSkillIconVisible() && mDoGph_gInf_c::getFader()->mStatus == 1) {
mSubWindowOpenCheck = 5;
dMeter2Info_set2DVibration();
}
} else if (mCursorX == 2 && mCursorY == 3) {
if (isInsectIconVisible() && mDoGph_gInf_c::getFader()->mStatus == 1) {
mSubWindowOpenCheck = 6;
dMeter2Info_set2DVibration();
}
} else if (field_0x22d[mCursorX][mCursorY] != 0 && !mIsWolf) {
if ((mCursorX >= 3 && mCursorX <= 4) || (mCursorX == 5 && mCursorY == 2)) {
u8 cursorY = mCursorY;
if (cursorY == 0) {
if (daPy_getPlayerActorClass()->getSwordChangeWaitTimer() == 0) {
changeSword();
}
} else if (cursorY == 1) {
if (daPy_getPlayerActorClass()->getShieldChangeWaitTimer() == 0) {
changeShield();
}
} else if (cursorY == 2 &&
daPy_getPlayerActorClass()->getClothesChangeWaitTimer() == 0)
{
changeClothe();
}
}
}
}
bool dMenu_Collect2D_c::pointerWait() {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Collection);
for (u8 y = 0; y < 6; ++y) {
for (u8 x = 0; x < 7; ++x) {
if (getItemTag(x, y, true) == 0 || !dusk::menu_pointer::hit_pane(mpSelPm[x][y], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(static_cast<dusk::menu_pointer::TargetId>(x + y * 7));
if (mCursorX != x || mCursorY != y) {
mDoAud_seStart(Z2SE_SY_MENU_CURSOR_COMMON, NULL, 0, 0);
mCursorX = x;
mCursorY = y;
cursorPosSet();
setItemNameString(mCursorX, mCursorY);
}
if (dusk::menu_pointer::consume_click()) {
pointerActivateCurrent();
return true;
}
return false;
}
}
return false;
}
#endif
void dMenu_Collect2D_c::save_open_init() { void dMenu_Collect2D_c::save_open_init() {
JKRHeap* heap = mDoExt_setCurrentHeap(mpSubHeap); JKRHeap* heap = mDoExt_setCurrentHeap(mpSubHeap);
+1 -24
View File
@@ -914,20 +914,6 @@ void dMenu_DmapBg_c::dMapBgWide() {
void dMenu_DmapBg_c::draw() { void dMenu_DmapBg_c::draw() {
#if TARGET_PC #if TARGET_PC
dMapBgWide(); dMapBgWide();
static bool prevMirror = false; // default state of panes is not mirrored
if(prevMirror != dusk::getSettings().game.enableMirrorMode) {
if(dusk::getSettings().game.enableMirrorMode) {
static_cast<J2DPicture*>(mFloorScreen->search(MULTI_CHAR('rink')))->setMirror(J2DMirror_X);
static_cast<J2DPicture*>(mBaseScreen->search(MULTI_CHAR('map000')))->setMirror(J2DMirror_X);
}
else {
static_cast<J2DPicture*>(mFloorScreen->search(MULTI_CHAR('rink')))->setMirror(MIRROR0);
static_cast<J2DPicture*>(mBaseScreen->search(MULTI_CHAR('map000')))->setMirror(MIRROR0);
}
prevMirror = dusk::getSettings().game.enableMirrorMode;
}
#endif #endif
u32 scissor_left; u32 scissor_left;
@@ -974,15 +960,6 @@ void dMenu_DmapBg_c::draw() {
mpBackTexture->setAlpha(dVar17 * (field_0xdbc * field_0xd9c)); mpBackTexture->setAlpha(dVar17 * (field_0xdbc * field_0xd9c));
f32 local_28c = mpBackTexture->getBounds().i.x; f32 local_28c = mpBackTexture->getBounds().i.x;
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
CPaneMgr mgr;
Vec local_94 = mgr.getGlobalVtxCenter(mMapPane, true, 0);
local_28c = (local_94.x * 2.0f) - (local_28c + 0.5f * mpBackTexture->getWidth()) - 0.5f * mpBackTexture->getWidth();
}
#endif
mpBackTexture->setBlackWhite(color_black, color_white); mpBackTexture->setBlackWhite(color_black, color_white);
mpBackTexture->draw(local_28c, field_0xd94 + mpBackTexture->getBounds().i.y, mpBackTexture->getWidth(), mpBackTexture->draw(local_28c, field_0xd94 + mpBackTexture->getBounds().i.y, mpBackTexture->getWidth(),
mpBackTexture->getHeight(), mpBackTexture->getHeight(),
@@ -2004,7 +1981,7 @@ void dMenu_Dmap_c::mapControl() {
f32 temp_f28 = (var_f29 / 100.0f) * var_f31; f32 temp_f28 = (var_f29 / 100.0f) * var_f31;
f32 sp18 = temp_f28 * cM_ssin(stick_angle); f32 sp18 = temp_f28 * cM_ssin(stick_angle);
f32 sp14 = temp_f28 * cM_scos(stick_angle); f32 sp14 = temp_f28 * cM_scos(stick_angle);
mMapCtrl->setPlusZoomCenterX(IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -sp18 :) sp18); mMapCtrl->setPlusZoomCenterX(sp18);
mMapCtrl->setPlusZoomCenterZ(sp14); mMapCtrl->setPlusZoomCenterZ(sp14);
} }
+20 -1
View File
@@ -359,7 +359,14 @@ f32 dMenu_StageMapCtrl_c::getPixelStageSizeZ() const {
f32 dMenu_StageMapCtrl_c::getPixelCenterX() const { f32 dMenu_StageMapCtrl_c::getPixelCenterX() const {
f32 var_f31 = dMpath_c::getCenterX(); f32 var_f31 = dMpath_c::getCenterX();
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
return (1.0f / field_0xbc) * (field_0x9c + var_f31);
}
else return (1.0f / field_0xbc) * (field_0x9c - var_f31);
#else
return (1.0f / field_0xbc) * (field_0x9c - var_f31); return (1.0f / field_0xbc) * (field_0x9c - var_f31);
#endif
} }
f32 dMenu_StageMapCtrl_c::getPixelCenterZ() const { f32 dMenu_StageMapCtrl_c::getPixelCenterZ() const {
@@ -418,7 +425,18 @@ inline static f32 rightModeCnvPos(f32 param_0) {
void dMenu_StageMapCtrl_c::cnvPosTo2Dpos(f32 param_0, f32 param_1, f32* param_2, void dMenu_StageMapCtrl_c::cnvPosTo2Dpos(f32 param_0, f32 param_1, f32* param_2,
f32* param_3) const { f32* param_3) const {
if (param_2 != NULL) { if (param_2 != NULL) {
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
*param_2 =
(0.5f * field_0x94) + rightModeCnvPos((1.0f / field_0xbc) * (field_0x9c + param_0));
} else {
*param_2 =
(0.5f * field_0x94) + rightModeCnvPos((1.0f / field_0xbc) * (param_0 - field_0x9c));
}
#else
*param_2 = (0.5f * field_0x94) + rightModeCnvPos((1.0f / field_0xbc) * (param_0 - field_0x9c)); *param_2 = (0.5f * field_0x94) + rightModeCnvPos((1.0f / field_0xbc) * (param_0 - field_0x9c));
#endif
} }
if (param_3 != NULL) { if (param_3 != NULL) {
@@ -915,7 +933,8 @@ void dMenu_StageMapCtrl_c::move() {
void dMenu_DmapMapCtrl_c::draw() { void dMenu_DmapMapCtrl_c::draw() {
if (field_0xef != 0) { if (field_0xef != 0) {
setPos(field_0xeb, field_0xec, field_0x9c, setPos(field_0xeb, field_0xec,
IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -field_0x9c :) field_0x9c,
field_0xa0, field_0xbc, true, field_0xd8); field_0xa0, field_0xbc, true, field_0xd8);
} }
} }
+15 -10
View File
@@ -931,8 +931,17 @@ void dMenu_Fmap_c::region_map_proc() {
mpDraw2DBack->regionMapMove(mpStick); mpDraw2DBack->regionMapMove(mpStick);
int stage_no, room_no; int stage_no, room_no;
#if TARGET_PC
f32 arrow_pos_x = mpDraw2DBack->getArrowPos2DX();
if (dusk::getSettings().game.enableMirrorMode) {
arrow_pos_x = mpDraw2DBack->getMirrorPosX(arrow_pos_x, 0.0f);
}
f32 pos_x = arrow_pos_x - mDoGph_gInf_c::getMinXF() - mDoGph_gInf_c::getWidthF() * 0.5f;
#else
f32 pos_x = mpDraw2DBack->getArrowPos2DX() - mDoGph_gInf_c::getMinXF() f32 pos_x = mpDraw2DBack->getArrowPos2DX() - mDoGph_gInf_c::getMinXF()
- mDoGph_gInf_c::getWidthF() * 0.5f; - mDoGph_gInf_c::getWidthF() * 0.5f;
#endif
f32 pos_y = mpDraw2DBack->getArrowPos2DY() - mDoGph_gInf_c::getHeightF() * 0.5f; f32 pos_y = mpDraw2DBack->getArrowPos2DY() - mDoGph_gInf_c::getHeightF() * 0.5f;
mpMenuFmapMap->getPointStagePathInnerNo(getNowFmapRegionData(), pos_x, pos_y, mpMenuFmapMap->getPointStagePathInnerNo(getNowFmapRegionData(), pos_x, pos_y,
@@ -2477,6 +2486,12 @@ void dMenu_Fmap_c::portalWarpMapMove(STControl* i_stick) {
f32 arrow_y = mpDraw2DBack->getArrowPos2DY(); f32 arrow_y = mpDraw2DBack->getArrowPos2DY();
u8 uVar6 = 0xff; u8 uVar6 = 0xff;
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
arrow_x = mpDraw2DBack->getMirrorPosX(arrow_x, 0.0f);
}
#endif
for (int i = 0; i < portal_dat->mCount; i++) { for (int i = 0; i < portal_dat->mCount; i++) {
if (portals[i].mRegionNo == mpDraw2DBack->getRegionCursor() + 1 if (portals[i].mRegionNo == mpDraw2DBack->getRegionCursor() + 1
@@ -2546,11 +2561,6 @@ void dMenu_Fmap_c::drawIcon(f32 param_0, bool param_1) {
if (mProcess == PROC_PORTAL_DEMO1) { if (mProcess == PROC_PORTAL_DEMO1) {
is_portal_demo1 = 1; is_portal_demo1 = 1;
} }
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
angle = 0x10000 - angle;
}
#endif
mpDraw2DBack->setIcon2DPos(0x11, stage_name, pos.x, pos.z, cM_sht2d(angle), mpDraw2DBack->setIcon2DPos(0x11, stage_name, pos.x, pos.z, cM_sht2d(angle),
is_portal_demo1, param_1); is_portal_demo1, param_1);
@@ -2639,11 +2649,6 @@ void dMenu_Fmap_c::drawPlayEnterIcon() {
angle = dComIfGs_getPlayerFieldLastStayAngleY(); angle = dComIfGs_getPlayerFieldLastStayAngleY();
SAFE_STRCPY(stage_name, dComIfGs_getPlayerFieldLastStayName()); SAFE_STRCPY(stage_name, dComIfGs_getPlayerFieldLastStayName());
} }
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
angle = 0x10000 - angle;
}
#endif
mpDraw2DBack->setIcon2DPos(0x15, stage_name, pos.x, pos.z, cM_sht2d(angle), 0, false); mpDraw2DBack->setIcon2DPos(0x15, stage_name, pos.x, pos.z, cM_sht2d(angle), 0, false);
} }
} }
+19 -86
View File
@@ -17,10 +17,7 @@
#include "d/d_msg_scrn_explain.h" #include "d/d_msg_scrn_explain.h"
#include "m_Do/m_Do_graphic.h" #include "m_Do/m_Do_graphic.h"
#include "d/actor/d_a_midna.h" #include "d/actor/d_a_midna.h"
#if TARGET_PC
#include "dusk/frame_interpolation.h" #include "dusk/frame_interpolation.h"
#include "dusk/ui/touch_controls.hpp"
#endif
#include <cstring> #include <cstring>
#if TARGET_PC #if TARGET_PC
@@ -426,15 +423,7 @@ void dMenu_Fmap2DBack_c::draw() {
} }
mpPointParent->setAlphaRate(mArrowAlpha * mSpotTextureFadeAlpha); mpPointParent->setAlphaRate(mArrowAlpha * mSpotTextureFadeAlpha);
mpPointParent->translate(mArrowPos2DX + mTransX, mArrowPos2DY + mTransZ);
f32 drawX = mArrowPos2DX + mTransX;
#ifdef TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
drawX = getMirrorPosX(drawX, 0.0f);
}
#endif
mpPointParent->translate(drawX, mArrowPos2DY + mTransZ);
mpPointScreen->draw(0.0f, 0.0f, grafPort); mpPointScreen->draw(0.0f, 0.0f, grafPort);
} }
@@ -753,7 +742,7 @@ void dMenu_Fmap2DBack_c::zoomMapCalc(f32 i_zoom) {
f32 tmp2 = (dVar12 + (i_zoom * (centerX - dVar12))); f32 tmp2 = (dVar12 + (i_zoom * (centerX - dVar12)));
f32 tmp2_ = (dVar11 + (i_zoom * (centerY - dVar11))); f32 tmp2_ = (dVar11 + (i_zoom * (centerY - dVar11)));
field_0xf0c[mRegionCursor] = field_0xf0c[mRegionCursor] =
((tmp2 + (tmp3 * mZoom)) - mRegionMapSizeX[mRegionCursor] * mZoom * 0.5f) - ((tmp2 + (tmp3 * mZoom)) - mRegionMapSizeX[mRegionCursor] * mZoom * 0.5f) -
mRegionMinMapX[mRegionCursor]; mRegionMinMapX[mRegionCursor];
@@ -1026,11 +1015,6 @@ void dMenu_Fmap2DBack_c::allmap_move2(STControl* param_0) {
f32 delta_y = speed * cM_ssin(angle); f32 delta_y = speed * cM_ssin(angle);
f32 delta_x = speed * cM_scos(angle); f32 delta_x = speed * cM_scos(angle);
#ifdef TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
delta_y = -delta_y;
}
#endif
control_xpos = control_xpos + delta_y; control_xpos = control_xpos + delta_y;
control_ypos = control_ypos + delta_x; control_ypos = control_ypos + delta_x;
} }
@@ -1059,6 +1043,11 @@ void dMenu_Fmap2DBack_c::allmap_move2(STControl* param_0) {
calcAllMapPos2D((mArrowPos3DX + control_xpos) - mStageTransX, calcAllMapPos2D((mArrowPos3DX + control_xpos) - mStageTransX,
(mArrowPos3DZ + control_ypos) - mStageTransZ, &sp14, &sp10); (mArrowPos3DZ + control_ypos) - mStageTransZ, &sp14, &sp10);
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
sp14 = getMirrorPosX(sp14, 0.0f);
}
#endif
mSelectRegion = 0xff; mSelectRegion = 0xff;
for (int i = 7; i >= 0; i--) { for (int i = 7; i >= 0; i--) {
@@ -1473,12 +1462,6 @@ void dMenu_Fmap2DBack_c::worldGridDraw() {
f32 dVar8 = -mStageTransZ; f32 dVar8 = -mStageTransZ;
calcAllMapPos2D(dVar9, dVar8, &local_74, &local_78); calcAllMapPos2D(dVar9, dVar8, &local_74, &local_78);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_74 = getMirrorPosX(local_74, 0.0f);
}
#endif
J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74, J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74,
mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(), mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(),
JUtility::TColor(255, 255, 255, 255), 6); JUtility::TColor(255, 255, 255, 255), 6);
@@ -1487,11 +1470,6 @@ void dMenu_Fmap2DBack_c::worldGridDraw() {
while (true) { while (true) {
calcAllMapPos2D(xPos, dVar8, &local_74, &local_78); calcAllMapPos2D(xPos, dVar8, &local_74, &local_78);
if (local_74 >= getMapScissorAreaLX()) { if (local_74 >= getMapScissorAreaLX()) {
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_74 = getMirrorPosX(local_74, 0.0f);
}
#endif
J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74, J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74,
mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(), mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(),
JUtility::TColor(255, 255, 255, 255), 6); JUtility::TColor(255, 255, 255, 255), 6);
@@ -1553,12 +1531,6 @@ void dMenu_Fmap2DBack_c::regionGridDraw() {
f32 dVar8 = mRegionOriginZ[mRegionCursor] - mStageTransZ; f32 dVar8 = mRegionOriginZ[mRegionCursor] - mStageTransZ;
calcAllMapPos2D(dVar9, dVar8, &local_74, &local_78); calcAllMapPos2D(dVar9, dVar8, &local_74, &local_78);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_74 = getMirrorPosX(local_74, 0.0f);
}
#endif
J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74, J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74,
mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(), mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(),
JUtility::TColor(180, 0, 0, 255), 6); JUtility::TColor(180, 0, 0, 255), 6);
@@ -1567,12 +1539,6 @@ void dMenu_Fmap2DBack_c::regionGridDraw() {
while (true) { while (true) {
calcAllMapPos2D(xPos, dVar8, &local_74, &local_78); calcAllMapPos2D(xPos, dVar8, &local_74, &local_78);
if (local_74 >= getMapScissorAreaLX()) { if (local_74 >= getMapScissorAreaLX()) {
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_74 = getMirrorPosX(local_74, 0.0f);
}
#endif
J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74, J2DDrawLine(local_74, mDoGph_gInf_c::getMinYF(), local_74,
mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(), mDoGph_gInf_c::getMinYF() + mDoGph_gInf_c::getHeightF(),
JUtility::TColor(180, 0, 0, 255), 6); JUtility::TColor(180, 0, 0, 255), 6);
@@ -1635,12 +1601,6 @@ void dMenu_Fmap2DBack_c::worldOriginDraw() {
f32 local_44, local_48; f32 local_44, local_48;
calcAllMapPos2D(-mStageTransX, -mStageTransZ, &local_44, &local_48); calcAllMapPos2D(-mStageTransX, -mStageTransZ, &local_44, &local_48);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_44 = getMirrorPosX(local_44, 0.0f);
}
#endif
J2DDrawLine(mDoGph_gInf_c::getMinXF(), local_48 - local_44 + mDoGph_gInf_c::getMinXF(), J2DDrawLine(mDoGph_gInf_c::getMinXF(), local_48 - local_44 + mDoGph_gInf_c::getMinXF(),
mDoGph_gInf_c::getMinXF() + mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getMinXF() + mDoGph_gInf_c::getWidthF(),
local_48 - local_44 + (mDoGph_gInf_c::getMinXF() + mDoGph_gInf_c::getWidthF()), local_48 - local_44 + (mDoGph_gInf_c::getMinXF() + mDoGph_gInf_c::getWidthF()),
@@ -1675,13 +1635,6 @@ void dMenu_Fmap2DBack_c::scrollAreaDraw() {
calcAllMapPos2D(x_min - mStageTransX, z_min - mStageTransZ, &local_4c, &local_50); calcAllMapPos2D(x_min - mStageTransX, z_min - mStageTransZ, &local_4c, &local_50);
calcAllMapPos2D(x_max - mStageTransX, z_max - mStageTransZ, &local_54, &local_58); calcAllMapPos2D(x_max - mStageTransX, z_max - mStageTransZ, &local_54, &local_58);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
local_4c = getMirrorPosX(local_4c, 0.0f);
local_54 = getMirrorPosX(local_54, 0.0f);
}
#endif
J2DDrawLine(local_4c, local_50, local_4c, local_58, J2DDrawLine(local_4c, local_50, local_4c, local_58,
JUtility::TColor(255, 255, 255, 255), 6); JUtility::TColor(255, 255, 255, 255), 6);
J2DDrawLine(local_54, local_50, local_54, local_58, J2DDrawLine(local_54, local_50, local_54, local_58,
@@ -1702,11 +1655,6 @@ void dMenu_Fmap2DBack_c::regionOriginDraw() {
f32 center_x, center_y; f32 center_x, center_y;
calcAllMapPos2D(mRegionOriginX[i] - mStageTransX, mRegionOriginZ[i] - mStageTransZ, calcAllMapPos2D(mRegionOriginX[i] - mStageTransX, mRegionOriginZ[i] - mStageTransZ,
&center_x, &center_y); &center_x, &center_y);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
center_x = getMirrorPosX(center_x - 3.0f, 3.0f);
}
#endif
J2DFillBox(center_x - 3.0f, center_y - 3.0f, 6.0f, 6.0f, JUtility::TColor(255, 0, 0, 255)); J2DFillBox(center_x - 3.0f, center_y - 3.0f, 6.0f, 6.0f, JUtility::TColor(255, 0, 0, 255));
} }
} }
@@ -1724,11 +1672,6 @@ void dMenu_Fmap2DBack_c::stageOriginDraw() {
f32 v1 = mRegionOriginX[mRegionCursor] + stage_data[i].mOffsetX - mStageTransX; f32 v1 = mRegionOriginX[mRegionCursor] + stage_data[i].mOffsetX - mStageTransX;
f32 v2 = mRegionOriginZ[mRegionCursor] + stage_data[i].mOffsetZ - mStageTransZ; f32 v2 = mRegionOriginZ[mRegionCursor] + stage_data[i].mOffsetZ - mStageTransZ;
calcAllMapPos2D(v1, v2, &center_x, &center_y); calcAllMapPos2D(v1, v2, &center_x, &center_y);
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
center_x = getMirrorPosX(center_x - 3.0f, 3.0f);
}
#endif
J2DFillBox(center_x - 3.0f, center_y - 3.0f, 6.0f, 6.0f, J2DFillBox(center_x - 3.0f, center_y - 3.0f, 6.0f, 6.0f,
JUtility::TColor(0, 0, 255, 255)); JUtility::TColor(0, 0, 255, 255));
} }
@@ -1975,7 +1918,7 @@ void dMenu_Fmap2DBack_c::regionMapMove(STControl* i_stick) {
f32 speed = base_speed / 100.0f * local_78; f32 speed = base_speed / 100.0f * local_78;
f32 speed_y = speed * cM_ssin(angle); f32 speed_y = speed * cM_ssin(angle);
f32 speed_x = speed * cM_scos(angle); f32 speed_x = speed * cM_scos(angle);
control_xpos += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -speed_y :) speed_y; control_xpos += speed_y;
control_ypos += speed_x; control_ypos += speed_x;
} }
} }
@@ -2000,6 +1943,11 @@ void dMenu_Fmap2DBack_c::regionMapMove(STControl* i_stick) {
calcAllMapPos2D(mArrowPos3DX + control_xpos - mStageTransX, calcAllMapPos2D(mArrowPos3DX + control_xpos - mStageTransX,
mArrowPos3DZ + control_ypos - mStageTransZ, &pos_x, &pos_y); mArrowPos3DZ + control_ypos - mStageTransZ, &pos_x, &pos_y);
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
pos_x = getMirrorPosX(pos_x, 0.0f);
}
#endif
mSelectRegion = 0xff; mSelectRegion = 0xff;
int region = mRegionCursor; int region = mRegionCursor;
@@ -2031,6 +1979,11 @@ void dMenu_Fmap2DBack_c::stageMapMove(STControl* i_stick, u8 param_1, bool param
if (stick_value >= slow_bound && param_2 && field_0x1238 != 2) { if (stick_value >= slow_bound && param_2 && field_0x1238 != 2) {
bVar6 = true; bVar6 = true;
s16 angle = i_stick->getAngleStick(); s16 angle = i_stick->getAngleStick();
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
angle = -angle;
}
#endif
f32 local_68 = mTexMaxX - mTexMinX; f32 local_68 = mTexMaxX - mTexMinX;
f32 spot_zoom = getSpotMapZoomRate(); f32 spot_zoom = getSpotMapZoomRate();
f32 region_zoom = getRegionMapZoomRate(mRegionCursor); f32 region_zoom = getRegionMapZoomRate(mRegionCursor);
@@ -2045,7 +1998,7 @@ void dMenu_Fmap2DBack_c::stageMapMove(STControl* i_stick, u8 param_1, bool param
f32 speed = base_speed / 100.0f * local_78; f32 speed = base_speed / 100.0f * local_78;
f32 speed_x = speed * cM_ssin(angle); f32 speed_x = speed * cM_ssin(angle);
f32 speed_z = speed * cM_scos(angle); f32 speed_z = speed * cM_scos(angle);
mStageTransX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -speed_x :) speed_x; mStageTransX += speed_x;
mStageTransZ += speed_z; mStageTransZ += speed_z;
} else if (!param_2) { } else if (!param_2) {
return; return;
@@ -2139,11 +2092,6 @@ void dMenu_Fmap2DBack_c::drawDebugStageArea() {
if (stage_no >= 0) { if (stage_no >= 0) {
f32 v = i + mDoGph_gInf_c::getMinXF(); f32 v = i + mDoGph_gInf_c::getMinXF();
f32 v2 = j; f32 v2 = j;
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
v = getMirrorPosX(v - 3.0f, 3.0f);
}
#endif
J2DFillBox(v - 3.0f, v2 - 3.0f, 6.0f, 6.0f, colors[stage_no % 6]); J2DFillBox(v - 3.0f, v2 - 3.0f, 6.0f, 6.0f, colors[stage_no % 6]);
} }
} }
@@ -2179,11 +2127,6 @@ void dMenu_Fmap2DBack_c::drawDebugRegionArea() {
mRegionMapSizeX[region] * mZoom, mRegionMapSizeY[region] * mZoom, mRegionMapSizeX[region] * mZoom, mRegionMapSizeY[region] * mZoom,
mpAreaTex[region]->getTexture(0)->getTexInfo()); mpAreaTex[region]->getTexture(0)->getTexInfo());
if (u) { if (u) {
#if TARGET_PC
if(dusk::getSettings().game.enableMirrorMode) {
pos_x = getMirrorPosX(pos_x - 3.0f, 3.0f);
}
#endif
J2DFillBox(pos_x - 3.0f, pos_y - 3.0f, 6.0f, 6.0f, colors[region]); J2DFillBox(pos_x - 3.0f, pos_y - 3.0f, 6.0f, 6.0f, colors[region]);
break; break;
} }
@@ -2566,10 +2509,6 @@ dMenu_Fmap2DTop_c::dMenu_Fmap2DTop_c(JKRExpHeap* i_heap, STControl* i_stick) {
} }
dMenu_Fmap2DTop_c::~dMenu_Fmap2DTop_c() { dMenu_Fmap2DTop_c::~dMenu_Fmap2DTop_c() {
#if TARGET_PC
dusk::ui::set_control_override(dusk::ui::Control::Z, dusk::ui::ControlOverride::Default);
#endif
deleteExplain(); deleteExplain();
JKR_DELETE(mpTitleScreen); JKR_DELETE(mpTitleScreen);
mpTitleScreen = NULL; mpTitleScreen = NULL;
@@ -2843,12 +2782,6 @@ void dMenu_Fmap2DTop_c::setZButtonString(u32 param_0, u8 i_alpha) {
param_0 = 0x533; param_0 = 0x533;
} }
#if TARGET_PC
dusk::ui::set_control_override(dusk::ui::Control::Z,
param_0 != 0 && isWarpAccept() ? dusk::ui::ControlOverride::Action :
dusk::ui::ControlOverride::Default);
#endif
#if VERSION == VERSION_GCN_JPN #if VERSION == VERSION_GCN_JPN
static const u64 cont_zt[5] = {MULTI_CHAR('cont_zt'), MULTI_CHAR('cont_zt1'), MULTI_CHAR('cont_zt2'), MULTI_CHAR('cont_zt3'), MULTI_CHAR('cont_zt4')}; static const u64 cont_zt[5] = {MULTI_CHAR('cont_zt'), MULTI_CHAR('cont_zt1'), MULTI_CHAR('cont_zt2'), MULTI_CHAR('cont_zt3'), MULTI_CHAR('cont_zt4')};
#define setZButtonString_font_zt cont_zt #define setZButtonString_font_zt cont_zt
-44
View File
@@ -22,10 +22,6 @@
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#if TARGET_PC
#include "dusk/menu_pointer.h"
#endif
typedef void (dMenu_Insect_c::*initFunc)(); typedef void (dMenu_Insect_c::*initFunc)();
static initFunc map_init_process[] = { static initFunc map_init_process[] = {
&dMenu_Insect_c::wait_init, &dMenu_Insect_c::explain_open_init, &dMenu_Insect_c::wait_init, &dMenu_Insect_c::explain_open_init,
@@ -284,12 +280,6 @@ void dMenu_Insect_c::wait_init() {
void dMenu_Insect_c::wait_move() { void dMenu_Insect_c::wait_move() {
if (mDoGph_gInf_c::getFader()->getStatus() == 1) { if (mDoGph_gInf_c::getFader()->getStatus() == 1) {
#if TARGET_PC
if (pointerWait()) {
return;
}
#endif
if (mDoCPd_c::getTrigB(PAD_1) || field_0xf7 == 0) { if (mDoCPd_c::getTrigB(PAD_1) || field_0xf7 == 0) {
if (mDoCPd_c::getTrigB(PAD_1) && field_0xf6 == 1) { if (mDoCPd_c::getTrigB(PAD_1) && field_0xf6 == 1) {
dMeter2Info_setInsectSelectType(0); dMeter2Info_setInsectSelectType(0);
@@ -311,40 +301,6 @@ void dMenu_Insect_c::wait_move() {
} }
} }
#if TARGET_PC
bool dMenu_Insect_c::pointerWait() {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Collection);
for (u8 y = 0; y < 4; ++y) {
for (u8 x = 0; x < 6; ++x) {
const int index = x + y * 6;
if (!isGetInsect(x, y) || !dusk::menu_pointer::hit_pane(mpINSParent[index], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(index);
if (field_0xf4 != x || field_0xf5 != y) {
field_0xf4 = x;
field_0xf5 = y;
setCursorPos();
setAButtonString(0x368);
Z2GetAudioMgr()->seStart(Z2SE_SY_CURSOR_ITEM, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
}
if (dusk::menu_pointer::consume_click()) {
field_0xf3 = 1;
Z2GetAudioMgr()->seStart(Z2SE_SY_EXP_WIN_OPEN, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
dMeter2Info_set2DVibration();
return true;
}
return false;
}
}
return false;
}
#endif
void dMenu_Insect_c::explain_open_init() { void dMenu_Insect_c::explain_open_init() {
char local_78[32]; char local_78[32];
char local_98[32]; char local_98[32];
-68
View File
@@ -19,15 +19,6 @@
#ifdef TARGET_PC #ifdef TARGET_PC
#include "dusk/achievements.h" #include "dusk/achievements.h"
#include "dusk/menu_pointer.h"
#include "dusk/ui/touch_controls.hpp"
static void enable_turn_page_controls(bool enabled) {
const auto controlOverride =
enabled ? dusk::ui::ControlOverride::Action : dusk::ui::ControlOverride::Default;
dusk::ui::set_control_override(dusk::ui::Control::L, controlOverride);
dusk::ui::set_control_override(dusk::ui::Control::R, controlOverride);
}
#endif #endif
#if VERSION == VERSION_GCN_JPN #if VERSION == VERSION_GCN_JPN
@@ -91,10 +82,6 @@ dMenu_Letter_c::dMenu_Letter_c(JKRExpHeap* i_heap, STControl* i_stick, CSTContro
dMenu_Letter_c::~dMenu_Letter_c() { dMenu_Letter_c::~dMenu_Letter_c() {
#if TARGET_PC
enable_turn_page_controls(false);
#endif
JKR_DELETE(mpDrawCursor); JKR_DELETE(mpDrawCursor);
mpDrawCursor = NULL; mpDrawCursor = NULL;
@@ -370,10 +357,6 @@ int dMenu_Letter_c::_open() {
} }
int dMenu_Letter_c::_close() { int dMenu_Letter_c::_close() {
#if TARGET_PC
enable_turn_page_controls(false);
#endif
s16 closeWindowFrame = s16 closeWindowFrame =
g_drawHIO.mLetterSelectScreen.mCloseFrame[dMeter_drawLetterHIO_c::WINDOW_FRAME]; g_drawHIO.mLetterSelectScreen.mCloseFrame[dMeter_drawLetterHIO_c::WINDOW_FRAME];
field_0x368 = 0; field_0x368 = 0;
@@ -403,10 +386,6 @@ int dMenu_Letter_c::_close() {
} }
void dMenu_Letter_c::wait_init() { void dMenu_Letter_c::wait_init() {
#if TARGET_PC
enable_turn_page_controls(field_0x374 > 1);
#endif
setAButtonString(0x40c); setAButtonString(0x40c);
setBButtonString(0x3f9); setBButtonString(0x3f9);
} }
@@ -414,12 +393,6 @@ void dMenu_Letter_c::wait_init() {
void dMenu_Letter_c::wait_move() { void dMenu_Letter_c::wait_move() {
u8 oldIndex = mIndex; u8 oldIndex = mIndex;
if (mDoGph_gInf_c::getFader()->getStatus() == 1) { if (mDoGph_gInf_c::getFader()->getStatus() == 1) {
#if TARGET_PC
if (pointerWait()) {
return;
}
#endif
if (mDoCPd_c::getTrigB(PAD_1) != 0) { if (mDoCPd_c::getTrigB(PAD_1) != 0) {
mpDrawCursor->offPlayAnime(0); mpDrawCursor->offPlayAnime(0);
mStatus = 3; mStatus = 3;
@@ -475,41 +448,8 @@ void dMenu_Letter_c::wait_move() {
} }
} }
#if TARGET_PC
bool dMenu_Letter_c::pointerWait() {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Collection);
for (u8 i = 0; i < field_0x373; ++i) {
if (!dusk::menu_pointer::hit_pane(mpLetterParent[i], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(i);
if (mIndex != i) {
mIndex = i;
changeActiveColor();
Z2GetAudioMgr()->seStart(Z2SE_SY_CURSOR_ITEM, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
}
if (dusk::menu_pointer::consume_click()) {
mProcess = 3;
Z2GetAudioMgr()->seStart(Z2SE_SY_LETTER_OPEN, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
dMeter2Info_set2DVibration();
return true;
}
return false;
}
return false;
}
#endif
void dMenu_Letter_c::slide_right_init() { void dMenu_Letter_c::slide_right_init() {
#if TARGET_PC
enable_turn_page_controls(false);
#endif
field_0x358 = -field_0x1ec->getWidth() * mDoGph_gInf_c::getInvScale(); field_0x358 = -field_0x1ec->getWidth() * mDoGph_gInf_c::getInvScale();
field_0x35c = field_0x1ec->getWidth() IF_NOT_DUSK(* mDoGph_gInf_c::getInvScale()); field_0x35c = field_0x1ec->getWidth() IF_NOT_DUSK(* mDoGph_gInf_c::getInvScale());
changePageLight(); changePageLight();
@@ -527,10 +467,6 @@ void dMenu_Letter_c::slide_right_move() {
} }
void dMenu_Letter_c::slide_left_init() { void dMenu_Letter_c::slide_left_init() {
#if TARGET_PC
enable_turn_page_controls(false);
#endif
field_0x358 = field_0x1ec->getWidth() * mDoGph_gInf_c::getInvScale(); field_0x358 = field_0x1ec->getWidth() * mDoGph_gInf_c::getInvScale();
field_0x35c = -field_0x1ec->getWidth() IF_NOT_DUSK(* mDoGph_gInf_c::getInvScale()); field_0x35c = -field_0x1ec->getWidth() IF_NOT_DUSK(* mDoGph_gInf_c::getInvScale());
changePageLight(); changePageLight();
@@ -548,10 +484,6 @@ void dMenu_Letter_c::slide_left_move() {
} }
void dMenu_Letter_c::read_open_init() { void dMenu_Letter_c::read_open_init() {
#if TARGET_PC
enable_turn_page_controls(false);
#endif
field_0x36a = 0; field_0x36a = 0;
u8 idx = field_0x3ac[field_0x36f * 6 + mIndex] - 1; u8 idx = field_0x3ac[field_0x36f * 6 + mIndex] - 1;
field_0x3e3 = 1; field_0x3e3 = 1;
+15 -7
View File
@@ -394,8 +394,21 @@ void dMenuMapCommon_c::drawIcon(f32 i_posX, f32 i_posY, f32 param_3, f32 param_4
icon_size_y *= _c7c; icon_size_y *= _c7c;
} }
#if TARGET_PC
f32 rotation = mIconInfo[info_idx].rotation;
if (dusk::getSettings().game.enableMirrorMode &&
(mIconInfo[info_idx].icon_no == ICON_LINK_e ||
mIconInfo[info_idx].icon_no == ICON_LINK_ENTER_e))
{
rotation = -rotation;
}
mPictures[mIconInfo[info_idx].icon_no]->rotate(icon_size_x / 2, icon_size_y / 2, ROTATE_Z,
rotation);
#else
mPictures[mIconInfo[info_idx].icon_no]->rotate(icon_size_x / 2, icon_size_y / 2, ROTATE_Z, mPictures[mIconInfo[info_idx].icon_no]->rotate(icon_size_x / 2, icon_size_y / 2, ROTATE_Z,
mIconInfo[info_idx].rotation); mIconInfo[info_idx].rotation);
#endif
if (mIconInfo[info_idx].icon_no == ICON_LIGHT_DROP_e) { if (mIconInfo[info_idx].icon_no == ICON_LIGHT_DROP_e) {
mPictures[mIconInfo[info_idx].icon_no]->setAlpha((180.0f * _c80) / 255.0f); mPictures[mIconInfo[info_idx].icon_no]->setAlpha((180.0f * _c80) / 255.0f);
@@ -410,15 +423,10 @@ void dMenuMapCommon_c::drawIcon(f32 i_posX, f32 i_posY, f32 param_3, f32 param_4
} }
f32 pos_x = i_posX + (icon_pos_x - (icon_size_x / 2)); f32 pos_x = i_posX + (icon_pos_x - (icon_size_x / 2));
bool r4 = false;
#if TARGET_PC #if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) { if (dusk::getSettings().game.enableMirrorMode) {
pos_x = getMirrorCenterPosX(i_posX + (icon_pos_x - (icon_size_x / 2)), icon_size_x / 2); pos_x = getMirrorCenterPosX(i_posX + (icon_pos_x - (icon_size_x / 2)), icon_size_x / 2);
} }
if(mIconInfo[info_idx].icon_no == ICON_GOLD_WOLF_e) {
r4 = true;
}
#endif #endif
mPictures[mIconInfo[info_idx].icon_no]->draw(pos_x, (i_posY + (icon_pos_y - icon_size_y / 2)), mPictures[mIconInfo[info_idx].icon_no]->draw(pos_x, (i_posY + (icon_pos_y - icon_size_y / 2)),
@@ -427,7 +435,7 @@ void dMenuMapCommon_c::drawIcon(f32 i_posX, f32 i_posY, f32 param_3, f32 param_4
if (mIconInfo[info_idx].icon_no == ICON_LIGHT_DROP_e) { if (mIconInfo[info_idx].icon_no == ICON_LIGHT_DROP_e) {
mLightDropPic->draw((pos_x + (icon_size_x / 2)) - (var_f29 / 2), mLightDropPic->draw((pos_x + (icon_size_x / 2)) - (var_f29 / 2),
((icon_size_y / 2) + (i_posY + (icon_pos_y - icon_size_y / 2))) - (var_f28 / 2), ((icon_size_y / 2) + (i_posY + (icon_pos_y - icon_size_y / 2))) - (var_f28 / 2),
var_f29, var_f28, r4, false, false); var_f29, var_f28, false, false, false);
} }
} }
} }
@@ -861,4 +869,4 @@ void dMenuMapCommon_c::getFmapPoeCount(const int regionNo, int& nowCount, int& t
} }
} }
} }
#endif #endif
-172
View File
@@ -26,11 +26,6 @@
#include "JSystem/JAudio2/JASDriverIF.h" #include "JSystem/JAudio2/JASDriverIF.h"
#if TARGET_PC
#include "dusk/menu_pointer.h"
#include "dusk/ui/touch_controls.hpp"
#endif
typedef void (dMenu_Option_c::*initFunc)(); typedef void (dMenu_Option_c::*initFunc)();
static initFunc init[] = { static initFunc init[] = {
&dMenu_Option_c::atten_init, &dMenu_Option_c::atten_init,
@@ -83,12 +78,6 @@ enum SelectType {
SelectType8, SelectType8,
}; };
#if TARGET_PC
static dusk::menu_pointer::TargetId option_yes_no_target(u8 index) noexcept {
return static_cast<dusk::menu_pointer::TargetId>(0x100 + index);
}
#endif
dMenu_Option_c::dMenu_Option_c(JKRArchive* i_archive, STControl* i_stick) { dMenu_Option_c::dMenu_Option_c(JKRArchive* i_archive, STControl* i_stick) {
mUseFlag = 0; mUseFlag = 0;
mBarScale[0] = g_drawHIO.mOptionScreen.mBarScale[0]; mBarScale[0] = g_drawHIO.mOptionScreen.mBarScale[0];
@@ -304,10 +293,6 @@ void dMenu_Option_c::_create() {
} }
void dMenu_Option_c::_delete() { void dMenu_Option_c::_delete() {
#if TARGET_PC
dusk::ui::set_control_override(dusk::ui::Control::Z, dusk::ui::ControlOverride::Default);
#endif
JKR_DELETE(mpString); JKR_DELETE(mpString);
mpString = NULL; mpString = NULL;
@@ -533,15 +518,6 @@ void dMenu_Option_c::_move() {
(this->*init[field_0x3ef])(); (this->*init[field_0x3ef])();
} }
} }
#if TARGET_PC
if (field_0x3f4 == 5 && field_0x3ef != SelectType3 && field_0x3f3 == 5 &&
field_0x3ef != SelectType4 && field_0x3ef != SelectType5 && field_0x3ef != SelectType6 &&
field_0x3ef != SelectType7 && pointerConfirmSelect())
{
goto skip;
}
#endif
} }
skip: skip:
u8 oldValue = field_0x3ef; u8 oldValue = field_0x3ef;
@@ -1098,44 +1074,6 @@ void dMenu_Option_c::confirm_move_move() {
bool leftTrigger = checkLeftTrigger(); bool leftTrigger = checkLeftTrigger();
bool rightTrigger = checkRightTrigger(); bool rightTrigger = checkRightTrigger();
#if TARGET_PC
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Options);
for (u8 i = 0; i < 2; ++i) {
if (!dusk::menu_pointer::hit_pane(mpYesNoSelBase_c[i], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(option_yes_no_target(i));
const bool clicked = dusk::menu_pointer::consume_click();
if (field_0x3f9 != i) {
Z2GetAudioMgr()->seStart(Z2SE_SY_MENU_CURSOR_COMMON, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
field_0x3fa = field_0x3f9;
field_0x3f9 = i;
if (clicked) {
yesNoSelectStart();
field_0x3ef = SelectType7;
dMeter2Info_set2DVibrationM();
mpWarning->_move();
setAnimation();
return;
}
yesnoSelectAnmSet();
field_0x3ef = SelectType6;
mpWarning->_move();
setAnimation();
return;
}
if (clicked) {
yesNoSelectStart();
field_0x3ef = SelectType7;
dMeter2Info_set2DVibrationM();
mpWarning->_move();
setAnimation();
return;
}
}
#endif
if (mDoCPd_c::getTrigA(PAD_1) != 0) { if (mDoCPd_c::getTrigA(PAD_1) != 0) {
yesNoSelectStart(); yesNoSelectStart();
field_0x3ef = SelectType7; field_0x3ef = SelectType7;
@@ -1172,36 +1110,11 @@ void dMenu_Option_c::confirm_select_init() {
} }
void dMenu_Option_c::confirm_select_move() { void dMenu_Option_c::confirm_select_move() {
#if TARGET_PC
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Options);
if (field_0x3f9 != 0xff &&
dusk::menu_pointer::hit_pane(mpYesNoSelBase_c[field_0x3f9], 8.0f))
{
const dusk::menu_pointer::TargetId target = option_yes_no_target(field_0x3f9);
dusk::menu_pointer::set_hover_target(target);
if (dusk::menu_pointer::consume_click()) {
dusk::menu_pointer::defer_activation(dusk::menu_pointer::Context::Options, target);
}
}
#endif
u8 selectMoveAnm = yesnoSelectMoveAnm(); u8 selectMoveAnm = yesnoSelectMoveAnm();
u8 wakuAlphaAnm = yesnoWakuAlpahAnm(field_0x3fa); u8 wakuAlphaAnm = yesnoWakuAlpahAnm(field_0x3fa);
if (selectMoveAnm == 1 && wakuAlphaAnm == 1) { if (selectMoveAnm == 1 && wakuAlphaAnm == 1) {
yesnoCursorShow(); yesnoCursorShow();
#if TARGET_PC
if (field_0x3f9 != 0xff &&
dusk::menu_pointer::consume_deferred_activation(
dusk::menu_pointer::Context::Options, option_yes_no_target(field_0x3f9)))
{
yesNoSelectStart();
field_0x3ef = SelectType7;
dMeter2Info_set2DVibrationM();
mpWarning->_move();
setAnimation();
return;
}
#endif
field_0x3ef = SelectType5; field_0x3ef = SelectType5;
} }
mpWarning->_move(); mpWarning->_move();
@@ -2150,11 +2063,6 @@ void dMenu_Option_c::cursorAnime(f32 i_cursorValue) {
} }
void dMenu_Option_c::setZButtonString(u16 i_stringID) { void dMenu_Option_c::setZButtonString(u16 i_stringID) {
#if TARGET_PC
dusk::ui::set_control_override(dusk::ui::Control::Z,
i_stringID != 0 ? dusk::ui::ControlOverride::Action : dusk::ui::ControlOverride::Default);
#endif
if (i_stringID == 0) { if (i_stringID == 0) {
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
if (mpZButtonText[i] != NULL) { if (mpZButtonText[i] != NULL) {
@@ -2234,87 +2142,7 @@ bool dMenu_Option_c::isRumbleSupported() {
return JUTGamePad::sRumbleSupported >> 0x1f; return JUTGamePad::sRumbleSupported >> 0x1f;
} }
#if TARGET_PC
bool dMenu_Option_c::pointerConfirmSelect() {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Options);
for (u8 i = 0; i < SelectType3; ++i) {
if (dusk::menu_pointer::hit_pane(mpMenuPane[i], 8.0f)) {
dusk::menu_pointer::set_hover_target(i);
return false;
}
}
dusk::menu_pointer::set_hover_target(0x200);
if (!dusk::menu_pointer::consume_click()) {
return false;
}
field_0x3f7 = 1;
field_0x3f5 = field_0x3ef;
field_0x3ef = SelectType4;
dMeter2Info_set2DVibration();
(this->*init[field_0x3ef])();
return true;
}
#endif
bool dMenu_Option_c::dpdMenuMove() { bool dMenu_Option_c::dpdMenuMove() {
#if TARGET_PC
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Options);
for (u8 i = 0; i < SelectType3; ++i) {
if (!dusk::menu_pointer::hit_pane(mpMenuPane[i], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(i);
if (getSelectType() != i) {
field_0x3ef = i;
setCursorPos(i);
Z2GetAudioMgr()->seStart(Z2SE_SY_CURSOR_OPTION, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
}
if (!dusk::menu_pointer::consume_click()) {
return true;
}
switch (i) {
case SelectType0:
field_0x3e4 ^= 1;
field_0x3da = 5;
field_0x3ef = SelectType3;
field_0x3f5 = SelectType0;
Z2GetAudioMgr()->seStart(Z2SE_SY_OPTION_SWITCH, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
return true;
case SelectType1:
if (isRumbleSupported()) {
field_0x3ea ^= 1;
if (field_0x3ea != 0) {
mDoCPd_c::startMotorWave(0, &field_0x3e0, JUTGamePad::CRumble::VAL_0, 0x3c);
}
field_0x3da = 5;
field_0x3ef = SelectType3;
field_0x3f5 = SelectType1;
Z2GetAudioMgr()->seStart(Z2SE_SY_OPTION_SWITCH, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
}
return true;
case SelectType2:
if (field_0x3e9 == 0) {
field_0x3e9 = 2;
} else {
field_0x3e9--;
}
field_0x3da = 5;
mDoAud_setOutputMode(dMo_soundMode[field_0x3e9]);
setSoundMode(dMo_soundMode[field_0x3e9]);
field_0x3ef = SelectType3;
field_0x3f5 = SelectType2;
Z2GetAudioMgr()->seStart(Z2SE_SY_OPTION_SWITCH, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
return true;
}
}
#endif
return false; return false;
} }
-103
View File
@@ -31,9 +31,7 @@
#if TARGET_PC #if TARGET_PC
#include "dusk/game_clock.h" #include "dusk/game_clock.h"
#include "dusk/menu_pointer.h"
#include "dusk/settings.h" #include "dusk/settings.h"
#include "dusk/ui/touch_controls.hpp"
#endif #endif
typedef void (dMenu_Ring_c::*initFunc)(); typedef void (dMenu_Ring_c::*initFunc)();
@@ -198,7 +196,6 @@ dMenu_Ring_c::dMenu_Ring_c(JKRExpHeap* i_heap, STControl* i_stick, CSTControl* i
mCursorInterpPrevAngular = false; mCursorInterpPrevAngular = false;
mCursorInterpCurrAngular = false; mCursorInterpCurrAngular = false;
mCursorInterpInit = false; mCursorInterpInit = false;
mPointerTouchPressHoveredCurrent = false;
#endif #endif
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
field_0x674[i] = 0; field_0x674[i] = 0;
@@ -617,9 +614,6 @@ void dMenu_Ring_c::_delete() {
* initializes a new process if mStatus changes * initializes a new process if mStatus changes
*/ */
void dMenu_Ring_c::_move() { void dMenu_Ring_c::_move() {
#if TARGET_PC
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::ItemWheel);
#endif
mRingRadiusH = g_ringHIO.mRingRadiusH; mRingRadiusH = g_ringHIO.mRingRadiusH;
mRingRadiusV = g_ringHIO.mRingRadiusV; mRingRadiusV = g_ringHIO.mRingRadiusV;
mOldStatus = mStatus; // Save current status for check mOldStatus = mStatus; // Save current status for check
@@ -1523,11 +1517,6 @@ void dMenu_Ring_c::stick_wait_proc() {
setDoStatus(0); setDoStatus(0);
return; return;
} }
#if TARGET_PC
if (pointerMove()) {
return;
}
#endif
if (dMw_A_TRIGGER() && !dMeter2Info_isTouchKeyCheck(0xe)) { if (dMw_A_TRIGGER() && !dMeter2Info_isTouchKeyCheck(0xe)) {
Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0); Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
} }
@@ -1539,70 +1528,6 @@ void dMenu_Ring_c::stick_wait_proc() {
} }
} }
#if TARGET_PC
bool dMenu_Ring_c::pointerMove() {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::ItemWheel);
const auto& pointer = dusk::menu_pointer::state();
if (!pointer.valid || mItemsTotal == 0) {
return false;
}
int hoveredSlot = -1;
f32 bestDistance = 42.0f;
for (u8 i = 0; i < mItemsTotal; ++i) {
const f32 x = mItemSlotPosX[i] + mCenterPosX;
const f32 y = mItemSlotPosY[i] + mCenterPosY;
const f32 distance = calcDistance(pointer.x, pointer.y, x, y);
if (distance < bestDistance) {
bestDistance = distance;
hoveredSlot = i;
}
}
if (hoveredSlot < 0) {
return false;
}
if (pointer.pressed) {
mPointerTouchPressHoveredCurrent = pointer.touch && hoveredSlot == mCurrentSlot;
}
dusk::menu_pointer::set_hover_target(static_cast<dusk::menu_pointer::TargetId>(hoveredSlot));
if (mCurrentSlot != hoveredSlot) {
mDirectSelectCursorPos.x = mItemSlotPosX[mCurrentSlot];
mDirectSelectCursorPos.z = mItemSlotPosY[mCurrentSlot];
mCurrentSlot = hoveredSlot;
mDirectSelectActive = true;
field_0x670 = field_0x63e[mCurrentSlot];
setStatus(STATUS_MOVE);
field_0x6b2 = 0;
return true;
}
const bool clickOpensExplain = !pointer.touch || mPointerTouchPressHoveredCurrent;
if (clickOpensExplain && dusk::menu_pointer::consume_click()) {
const u8 item = dComIfGs_getItem(mItemSlots[mCurrentSlot], false);
if (!dMeter2Info_isTouchKeyCheck(0xe) && openExplain(item)) {
dMeter2Info_setItemExplainWindowStatus(1);
field_0x6c4 = mCurrentSlot;
setStatus(STATUS_EXPLAIN);
dMeter2Info_set2DVibration();
setDoStatus(0);
} else {
Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
}
mPointerTouchPressHoveredCurrent = false;
return true;
}
if (pointer.released) {
mPointerTouchPressHoveredCurrent = false;
}
return false;
}
#endif
void dMenu_Ring_c::stick_move_init() { void dMenu_Ring_c::stick_move_init() {
if (mCursorSpeed == 0) { if (mCursorSpeed == 0) {
mCursorSpeed = g_ringHIO.mCursorInitSpeed; mCursorSpeed = g_ringHIO.mCursorInitSpeed;
@@ -1747,40 +1672,12 @@ void dMenu_Ring_c::drawSelectItem() {
#else #else
if (field_0x674[i] < 10) { if (field_0x674[i] < 10) {
#endif #endif
#if TARGET_PC
f32 initSizeX;
f32 initSizeY;
f32 initScaleX;
f32 initScaleY;
Vec pos;
dusk::ui::EquipTarget touchTarget;
if (dusk::ui::get_equip_target(i, touchTarget)) {
initSizeX = touchTarget.width;
initSizeY = touchTarget.height;
initScaleX = 1.0f;
initScaleY = 1.0f;
pos.x = touchTarget.left;
pos.y = touchTarget.top;
pos.z = 0.0f;
} else {
CPaneMgr* meterItemPane = dMeter2Info_getMeterItemPanePtr(i);
if (meterItemPane == NULL) {
continue;
}
initSizeX = meterItemPane->getInitSizeX() * 1.7f;
initSizeY = meterItemPane->getInitSizeY() * 1.7f;
initScaleX = meterItemPane->getInitScaleX();
initScaleY = meterItemPane->getInitScaleY();
pos = meterItemPane->getGlobalVtxCenter(meterItemPane->mPane, true, 0);
}
#else
f32 initSizeX = dMeter2Info_getMeterItemPanePtr(i)->getInitSizeX() * 1.7f; f32 initSizeX = dMeter2Info_getMeterItemPanePtr(i)->getInitSizeX() * 1.7f;
f32 initSizeY = dMeter2Info_getMeterItemPanePtr(i)->getInitSizeY() * 1.7f; f32 initSizeY = dMeter2Info_getMeterItemPanePtr(i)->getInitSizeY() * 1.7f;
f32 initScaleX = dMeter2Info_getMeterItemPanePtr(i)->getInitScaleX(); f32 initScaleX = dMeter2Info_getMeterItemPanePtr(i)->getInitScaleX();
f32 initScaleY = dMeter2Info_getMeterItemPanePtr(i)->getInitScaleY(); f32 initScaleY = dMeter2Info_getMeterItemPanePtr(i)->getInitScaleY();
Vec pos = dMeter2Info_getMeterItemPanePtr(i)->getGlobalVtxCenter( Vec pos = dMeter2Info_getMeterItemPanePtr(i)->getGlobalVtxCenter(
dMeter2Info_getMeterItemPanePtr(i)->mPane, true, 0); dMeter2Info_getMeterItemPanePtr(i)->mPane, true, 0);
#endif
#if TARGET_PC #if TARGET_PC
f32 fVar14 = 0.1f + 0.8f * u; f32 fVar14 = 0.1f + 0.8f * u;
+2 -159
View File
@@ -18,15 +18,11 @@
#include "m_Do/m_Do_controller_pad.h" #include "m_Do/m_Do_controller_pad.h"
#include "m_Do/m_Do_graphic.h" #include "m_Do/m_Do_graphic.h"
#include "d/d_msg_scrn_explain.h" #include "d/d_msg_scrn_explain.h"
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
#include "JSystem/J2DGraph/J2DAnmLoader.h" #include "JSystem/J2DGraph/J2DAnmLoader.h"
#include "f_op/f_op_msg_mng.h" #include "f_op/f_op_msg_mng.h"
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#include "dusk/menu_pointer.h"
#include "dusk/settings.h"
#endif
static int SelStartFrameTbl[3] = { static int SelStartFrameTbl[3] = {
59, 59,
99, 99,
@@ -58,17 +54,6 @@ static int YnSelStartFrameTbl[2][2] = {
static int YnSelEndFrameTbl[2][2] = {{2138, 3171}, {2150, 3181}}; static int YnSelEndFrameTbl[2][2] = {{2138, 3171}, {2150, 3181}};
#if TARGET_PC
namespace {
constexpr u8 pointer_target(u8 group, u8 index) noexcept {
return static_cast<u8>((group << 4) | (index & 0x0F));
}
constexpr u8 s_pointerSaveSelectTarget = 0;
constexpr u8 s_pointerYesNoSelectTarget = 1;
} // namespace
#endif
static dMs_HIO_c g_msHIO; static dMs_HIO_c g_msHIO;
dMs_HIO_c::dMs_HIO_c() { dMs_HIO_c::dMs_HIO_c() {
@@ -1781,12 +1766,6 @@ void dMenu_save_c::openSaveSelect3() {
void dMenu_save_c::saveSelect() { void dMenu_save_c::saveSelect() {
if (!mDoRst::isReset()) { if (!mDoRst::isReset()) {
#if TARGET_PC
if (pointerSaveSelect()) {
return;
}
#endif
stick->checkTrigger(); stick->checkTrigger();
if (mDoCPd_c::getTrigA(PAD_1)) { if (mDoCPd_c::getTrigA(PAD_1)) {
@@ -1813,86 +1792,7 @@ void dMenu_save_c::saveSelect() {
} }
} }
#if TARGET_PC
bool dMenu_save_c::pointerSaveSelect() {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Save);
for (u8 i = 0; i < 3; ++i) {
if (!dusk::menu_pointer::hit_pane(mpSelData[i], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerSaveSelectTarget, i));
const bool clicked = dusk::menu_pointer::consume_click();
if (mSelectedFile != i) {
mDoAud_seStart(Z2SE_FILE_SELECT_CURSOR, NULL, 0, 0);
mLastSelFile = mSelectedFile;
mSelectedFile = i;
if (clicked) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::Save,
pointer_target(s_pointerSaveSelectTarget, i));
}
dataSelectAnmSet();
mMenuProc = PROC_SAVE_SELECT_MOVE_ANM;
return true;
}
if (clicked) {
saveSelectStart();
return true;
}
}
return false;
}
bool dMenu_save_c::pointerYesNoSelect(bool errorSelect, u8 errParam, u8 soundParam) {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Save);
for (u8 i = 0; i < 2; ++i) {
if (!dusk::menu_pointer::hit_pane(mpNoYes[i], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerYesNoSelectTarget, i));
const bool clicked =
(!errorSelect || mYesNoCursor == i) && dusk::menu_pointer::consume_click();
if (mYesNoCursor != i) {
if (errorSelect) {
errCurMove(errParam, soundParam);
return false;
}
mDoAud_seStart(Z2SE_SY_MENU_CURSOR_COMMON, NULL, 0, 0);
mYesNoPrevCursor = mYesNoCursor;
mYesNoCursor = i;
if (clicked) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::Save,
pointer_target(s_pointerYesNoSelectTarget, i));
}
yesnoSelectAnmSet(0);
mMenuProc = PROC_YES_NO_CURSOR_MOVE_ANM;
return true;
}
if (clicked) {
if (errorSelect) {
if (mYesNoCursor != CURSOR_NO) {
if (soundParam == 0) {
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
}
} else if (soundParam == 0) {
mDoAud_seStart(Z2SE_SY_CURSOR_CANCEL, NULL, 0, 0);
}
mSelIcon->setAlphaRate(0.0f);
} else {
yesnoSelectStart();
}
return true;
}
}
return false;
}
#endif
void dMenu_save_c::saveSelectStart() { void dMenu_save_c::saveSelectStart() {
#if TARGET_PC
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::Save);
#endif
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0); mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
selectDataMoveAnmInitSet(SelOpenStartFrameTbl[mSelectedFile], selectDataMoveAnmInitSet(SelOpenStartFrameTbl[mSelectedFile],
SelOpenEndFrameTbl[mSelectedFile]); SelOpenEndFrameTbl[mSelectedFile]);
@@ -1951,19 +1851,6 @@ void dMenu_save_c::dataSelectAnmSet() {
} }
void dMenu_save_c::saveSelectMoveAnime() { void dMenu_save_c::saveSelectMoveAnime() {
#if TARGET_PC
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Save);
if (mSelectedFile != 0xFF &&
dusk::menu_pointer::hit_pane(mpSelData[mSelectedFile], 8.0f))
{
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerSaveSelectTarget, mSelectedFile));
if (dusk::menu_pointer::consume_click()) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::Save,
pointer_target(s_pointerSaveSelectTarget, mSelectedFile));
}
}
#endif
bool bookWakuAnmComplete = true; bool bookWakuAnmComplete = true;
bool selWakuAnmComplete = true; bool selWakuAnmComplete = true;
bool var_r29 = true; bool var_r29 = true;
@@ -2013,26 +1900,12 @@ void dMenu_save_c::saveSelectMoveAnime() {
if (mLastSelFile != 0xFF) { if (mLastSelFile != 0xFF) {
mpSelData[mLastSelFile]->getPanePtr()->setAnimation((J2DAnmTransformKey*)NULL); mpSelData[mLastSelFile]->getPanePtr()->setAnimation((J2DAnmTransformKey*)NULL);
} }
#if TARGET_PC
if (dusk::menu_pointer::consume_deferred_activation(
dusk::menu_pointer::Context::Save,
pointer_target(s_pointerSaveSelectTarget, mSelectedFile))) {
saveSelectStart();
return;
}
#endif
mMenuProc = PROC_SAVE_SELECT; mMenuProc = PROC_SAVE_SELECT;
} }
} }
void dMenu_save_c::saveYesNoSelect() { void dMenu_save_c::saveYesNoSelect() {
if (!mDoRst::isReset()) { if (!mDoRst::isReset()) {
#if TARGET_PC
if (pointerYesNoSelect(false)) {
return;
}
#endif
stick->checkTrigger(); stick->checkTrigger();
if (mDoCPd_c::getTrigA(PAD_1)) { if (mDoCPd_c::getTrigA(PAD_1)) {
@@ -2060,9 +1933,6 @@ void dMenu_save_c::saveYesNoSelect() {
} }
void dMenu_save_c::yesnoSelectStart() { void dMenu_save_c::yesnoSelectStart() {
#if TARGET_PC
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::Save);
#endif
if (mYesNoCursor != CURSOR_NO) { if (mYesNoCursor != CURSOR_NO) {
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0); mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
mSelIcon->setAlphaRate(0.0f); mSelIcon->setAlphaRate(0.0f);
@@ -2131,32 +2001,11 @@ void dMenu_save_c::yesnoSelectAnmSet(u8 param_0) {
} }
void dMenu_save_c::yesNoCursorMoveAnm() { void dMenu_save_c::yesNoCursorMoveAnm() {
#if TARGET_PC
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Save);
if (mYesNoCursor != 0xFF &&
dusk::menu_pointer::hit_pane(mpNoYes[mYesNoCursor], 8.0f))
{
dusk::menu_pointer::set_hover_target(pointer_target(s_pointerYesNoSelectTarget, mYesNoCursor));
if (dusk::menu_pointer::consume_click()) {
dusk::menu_pointer::defer_activation(
dusk::menu_pointer::Context::Save,
pointer_target(s_pointerYesNoSelectTarget, mYesNoCursor));
}
}
#endif
bool selAnmComplete = yesnoSelectMoveAnm(0); bool selAnmComplete = yesnoSelectMoveAnm(0);
bool wakuAnmComplete = yesnoWakuAlpahAnm(mYesNoPrevCursor); bool wakuAnmComplete = yesnoWakuAlpahAnm(mYesNoPrevCursor);
if (selAnmComplete == true && wakuAnmComplete == true) { if (selAnmComplete == true && wakuAnmComplete == true) {
yesnoCursorShow(); yesnoCursorShow();
#if TARGET_PC
if (dusk::menu_pointer::consume_deferred_activation(
dusk::menu_pointer::Context::Save,
pointer_target(s_pointerYesNoSelectTarget, mYesNoCursor))) {
yesnoSelectStart();
return;
}
#endif
mMenuProc = PROC_SAVE_YES_NO_SELECT; mMenuProc = PROC_SAVE_YES_NO_SELECT;
} }
} }
@@ -2332,12 +2181,6 @@ bool dMenu_save_c::errYesNoSelect(u8 param_0, u8 param_1) {
return false; return false;
} }
#if TARGET_PC
if (pointerYesNoSelect(true, param_0, param_1)) {
return true;
}
#endif
stick->checkTrigger(); stick->checkTrigger();
if (mDoCPd_c::getTrigA(PAD_1)) { if (mDoCPd_c::getTrigA(PAD_1)) {
-39
View File
@@ -18,10 +18,6 @@
#include "m_Do/m_Do_graphic.h" #include "m_Do/m_Do_graphic.h"
#include <cstring> #include <cstring>
#if TARGET_PC
#include "dusk/menu_pointer.h"
#endif
typedef void (dMenu_Skill_c::*initFunc)(); typedef void (dMenu_Skill_c::*initFunc)();
static initFunc map_init_process[] = { static initFunc map_init_process[] = {
&dMenu_Skill_c::wait_init, &dMenu_Skill_c::wait_init,
@@ -279,12 +275,6 @@ void dMenu_Skill_c::wait_init() {
void dMenu_Skill_c::wait_move() { void dMenu_Skill_c::wait_move() {
u8 oldIndex = mIndex; u8 oldIndex = mIndex;
if (mDoGph_gInf_c::getFader()->getStatus() == 1) { if (mDoGph_gInf_c::getFader()->getStatus() == 1) {
#if TARGET_PC
if (pointerWait()) {
return;
}
#endif
if (mDoCPd_c::getTrigB(PAD_1) != 0) { if (mDoCPd_c::getTrigB(PAD_1) != 0) {
mpDrawCursor->offPlayAnime(0); mpDrawCursor->offPlayAnime(0);
mStatus = 3; mStatus = 3;
@@ -309,35 +299,6 @@ void dMenu_Skill_c::wait_move() {
} }
} }
#if TARGET_PC
bool dMenu_Skill_c::pointerWait() {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Collection);
for (u8 i = 0; i < mSkillNum; ++i) {
if (!dusk::menu_pointer::hit_pane(mpLetterParent[i], 8.0f)) {
continue;
}
dusk::menu_pointer::set_hover_target(i);
if (mIndex != i) {
mIndex = i;
changeActiveColor();
Z2GetAudioMgr()->seStart(Z2SE_SY_CURSOR_ITEM, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
}
if (dusk::menu_pointer::consume_click()) {
mProcess = PROC_WAIT_MOVE;
Z2GetAudioMgr()->seStart(Z2SE_SY_EXP_WIN_OPEN, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
dMeter2Info_set2DVibration();
return true;
}
return false;
}
return false;
}
#endif
void dMenu_Skill_c::read_open_init() { void dMenu_Skill_c::read_open_init() {
static const u32 i_id[7] = { static const u32 i_id[7] = {
1716, 1715, 1717, 1718, 1719, 1720, 1721, 1716, 1715, 1717, 1718, 1719, 1720, 1721,
+2 -28
View File
@@ -437,12 +437,7 @@ void dMeter2_c::checkStatus() {
field_0x128 = daPy_py_c::checkNowWolf(); field_0x128 = daPy_py_c::checkNowWolf();
#if TARGET_PC
dMsgObject_c* msgObject = dMsgObject_getMsgObjectClass();
if (!dComIfGp_2dShowCheck() || (msgObject != NULL && msgObject->isPlaceMessage())) {
#else
if (!dComIfGp_2dShowCheck() || dMsgObject_getMsgObjectClass()->isPlaceMessage()) { if (!dComIfGp_2dShowCheck() || dMsgObject_getMsgObjectClass()->isPlaceMessage()) {
#endif
mStatus |= 0x4000; mStatus |= 0x4000;
} else if (dComIfGp_checkPlayerStatus1(0, 1) && dComIfGp_getAStatus() == 0x12) { } else if (dComIfGp_checkPlayerStatus1(0, 1) && dComIfGp_getAStatus() == 0x12) {
mStatus |= 0x200000; mStatus |= 0x200000;
@@ -668,15 +663,8 @@ void dMeter2_c::moveLife() {
draw_life = true; draw_life = true;
} }
#if TARGET_PC if (mLifeGaugeScale != g_drawHIO.mLifeParentScale) {
const f32 lifeGaugeScale = mLifeGaugeScale = g_drawHIO.mLifeParentScale;
g_drawHIO.mLifeParentScale *
std::clamp(dusk::getSettings().game.hudScale.getValue(), 0.5f, 2.0f);
#else
const f32 lifeGaugeScale = g_drawHIO.mLifeParentScale;
#endif
if (mLifeGaugeScale != lifeGaugeScale) {
mLifeGaugeScale = lifeGaugeScale;
draw_life = true; draw_life = true;
} }
@@ -2875,14 +2863,8 @@ void dMeter2_c::alphaAnimeButton() {
u8 var_31; u8 var_31;
var_31 = 0; var_31 = 0;
#if TARGET_PC
dMsgObject_c* msgObject = dMsgObject_getMsgObjectClass();
if ((mStatus & 0x4000) ||
((mStatus & 0x100) && (msgObject != NULL && msgObject->isAutoMessageFlag())) ||
#else
if ((mStatus & 0x4000) || if ((mStatus & 0x4000) ||
((mStatus & 0x100) && dMsgObject_getMsgObjectClass()->isAutoMessageFlag()) || ((mStatus & 0x100) && dMsgObject_getMsgObjectClass()->isAutoMessageFlag()) ||
#endif
((mStatus & 0x40000000) && !(mStatus & 0x100)) || (mStatus & 0x80000000) || (mStatus & 8) || ((mStatus & 0x40000000) && !(mStatus & 0x100)) || (mStatus & 0x80000000) || (mStatus & 8) ||
(mStatus & 0x10) || (mStatus & 0x20) || (mStatus & 0x04000000) || (mStatus & 0x10000000)) (mStatus & 0x10) || (mStatus & 0x20) || (mStatus & 0x04000000) || (mStatus & 0x10000000))
{ {
@@ -2984,15 +2966,7 @@ void dMeter2_c::alphaAnimeButtonCross() {
field_0x190++; field_0x190++;
} }
} else { } else {
#if TARGET_PC
if (dusk::getSettings().game.enableTouchControls) {
mpMeterDraw->setAlphaButtonCrossAnimeMin();
} else {
mpMeterDraw->setAlphaButtonCrossAnimeMax();
}
#else
mpMeterDraw->setAlphaButtonCrossAnimeMax(); mpMeterDraw->setAlphaButtonCrossAnimeMax();
#endif
if (field_0x190 < 5) { if (field_0x190 < 5) {
field_0x190++; field_0x190++;
-35
View File
@@ -25,7 +25,6 @@
#if TARGET_PC #if TARGET_PC
#include "dusk/settings.h" #include "dusk/settings.h"
#include "dusk/ui/icon_provider.hpp"
#include <algorithm> #include <algorithm>
namespace { namespace {
@@ -654,22 +653,10 @@ void dMeter2Draw_c::draw() {
J2DGrafContext* graf_ctx = dComIfGp_getCurrentGrafPort(); J2DGrafContext* graf_ctx = dComIfGp_getCurrentGrafPort();
graf_ctx->setup2D(); graf_ctx->setup2D();
#if TARGET_PC
const bool touchControlsEnabled = dusk::getSettings().game.enableTouchControls;
if (touchControlsEnabled) {
mpButtonParent->hide();
} else {
mpButtonParent->show();
}
#endif
mpScreen->draw(0.0f, 0.0f, graf_ctx); mpScreen->draw(0.0f, 0.0f, graf_ctx);
drawKanteraScreen(1); drawKanteraScreen(1);
drawKanteraScreen(2); drawKanteraScreen(2);
#if TARGET_PC
if (!touchControlsEnabled) {
#endif
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
if (mpItemXY[i] != NULL) { if (mpItemXY[i] != NULL) {
for (int j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
@@ -718,9 +705,6 @@ void dMeter2Draw_c::draw() {
} }
} }
} }
#if TARGET_PC
}
#endif
if (mpLightDropParent->getAlphaRate() != 0.0f) { if (mpLightDropParent->getAlphaRate() != 0.0f) {
f32 var_f28 = g_drawHIO.mLightDrop.mPikariScaleNormal; f32 var_f28 = g_drawHIO.mLightDrop.mPikariScaleNormal;
@@ -803,11 +787,7 @@ void dMeter2Draw_c::draw() {
} }
} }
#if TARGET_PC
if (!touchControlsEnabled && field_0x738 > 0.0f) {
#else
if (field_0x738 > 0.0f) { if (field_0x738 > 0.0f) {
#endif
drawPikari(mpButtonMidona, &field_0x738, g_drawHIO.mMidnaIconPikariScale, drawPikari(mpButtonMidona, &field_0x738, g_drawHIO.mMidnaIconPikariScale,
g_drawHIO.mMidnaIconPikariFrontOuter, g_drawHIO.mMidnaIconPikariFrontInner, g_drawHIO.mMidnaIconPikariFrontOuter, g_drawHIO.mMidnaIconPikariFrontInner,
g_drawHIO.mMidnaIconPikariBackOuter, g_drawHIO.mMidnaIconPikariBackInner, g_drawHIO.mMidnaIconPikariBackOuter, g_drawHIO.mMidnaIconPikariBackInner,
@@ -2472,11 +2452,6 @@ void dMeter2Draw_c::drawButtonB(u8 i_action, bool param_1, f32 i_posX, f32 i_pos
SAFE_STRCPY(static_cast<J2DTextBox*>(mpBText[i]->getPanePtr())->getStringPtr(), mp_string); SAFE_STRCPY(static_cast<J2DTextBox*>(mpBText[i]->getPanePtr())->getStringPtr(), mp_string);
} }
#if TARGET_PC
if (dusk::getSettings().game.enableTouchControls) {
mpScreen->search(MULTI_CHAR('item_b_n'))->hide();
} else
#endif
if (i_action == 0x26 || i_action == 0x2E) { if (i_action == 0x26 || i_action == 0x2E) {
mpScreen->search(MULTI_CHAR('item_b_n'))->show(); mpScreen->search(MULTI_CHAR('item_b_n'))->show();
var_r31 = 1; var_r31 = 1;
@@ -2754,12 +2729,6 @@ void dMeter2Draw_c::drawButtonXY(int i_no, u8 i_itemNo, u8 i_action, bool param_
mpTextXY[i_no]->scale(g_drawHIO.mButtonXYTextScale, g_drawHIO.mButtonXYTextScale); mpTextXY[i_no]->scale(g_drawHIO.mButtonXYTextScale, g_drawHIO.mButtonXYTextScale);
mpTextXY[i_no]->paneTrans(g_drawHIO.mButtonXYTextPosX, g_drawHIO.mButtonXYTextPosY); mpTextXY[i_no]->paneTrans(g_drawHIO.mButtonXYTextPosX, g_drawHIO.mButtonXYTextPosY);
} }
#if TARGET_PC
if (dusk::getSettings().game.enableTouchControls) {
mpScreen->search(tag[i_no])->hide();
}
#endif
} }
} }
@@ -3325,10 +3294,6 @@ void dMeter2Draw_c::setButtonIconMidonaAlpha(u32 param_0) {
} }
mpButtonXY[2]->setAlpha(255.0f * field_0x724 * temp_f30_2); mpButtonXY[2]->setAlpha(255.0f * field_0x724 * temp_f30_2);
#if TARGET_PC
dusk::ui::update_midna_icon_texture(mpButtonMidona != NULL ? mpButtonMidona->getPanePtr() : NULL);
#endif
} }
void dMeter2Draw_c::setButtonIconAlpha(int i_no, u8 unused0, u32 unused1, bool unused2) { void dMeter2Draw_c::setButtonIconAlpha(int i_no, u8 unused0, u32 unused1, bool unused2) {
+2 -57
View File
@@ -22,10 +22,6 @@
#endif #endif
#include <cstring> #include <cstring>
#if TARGET_PC
#include "dusk/action_bindings.h"
#endif
#if (PLATFORM_WII || PLATFORM_SHIELD) #if (PLATFORM_WII || PLATFORM_SHIELD)
dMeter_map_HIO_c g_meter_mapHIO; dMeter_map_HIO_c g_meter_mapHIO;
#endif #endif
@@ -543,12 +539,6 @@ void dMeterMap_c::_move(u32 param_0) {
} }
#endif #endif
#if TARGET_PC
if (mMap->refreshTextureSize()) {
mMapJ2DPicture->changeTexture(mMap->getResTIMGPointer(), 0);
}
#endif
int stayNo = dComIfGp_roomControl_getStayNo(); int stayNo = dComIfGp_roomControl_getStayNo();
field_0x14 = param_0; field_0x14 = param_0;
@@ -742,38 +732,7 @@ void dMeterMap_c::ctrlShowMap() {
} }
} }
} } else if (!mDoCPd_c::getTrigUp(PAD_1) && !mDoCPd_c::getTrigDown(PAD_1)) {
#if TARGET_PC
else if (!isEventRunCheck() &&
(dMeter2Info_getMapStatus() == 0 || dMeter2Info_getMapStatus() == 1) &&
!dMeter2Info_isSub2DStatus(1) && (isFmapScreen() || isDmapScreen()) &&
dusk::getActionBindTrig(dusk::ActionBinds::OPEN_MAP_SCREEN, PAD_1))
{
dMeter2Info_setMapStatus(2);
dMeter2Info_setMapKeyDirection(0x400);
Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_OPEN_S, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
dMeter2Info_set2DVibration();
} else if (!isEventRunCheck() &&
(dMeter2Info_getMapStatus() == 0 || dMeter2Info_getMapStatus() == 1) &&
isEnableDispMapAndMapDispSizeTypeNo() &&
dusk::getActionBindTrig(dusk::ActionBinds::TOGGLE_MINIMAP, PAD_1))
{
if (isDispPosInsideFlg()) {
setDispPosOutsideFlg_SE_On();
Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_CLOSE_S, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
dMeter2Info_setMapStatus(0);
} else {
setDispPosInsideFlg_SE_On();
Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_OPEN_S, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
dMeter2Info_set2DVibration();
dMeter2Info_setMapStatus(1);
}
}
#endif
else if (!mDoCPd_c::getTrigUp(PAD_1) && !mDoCPd_c::getTrigDown(PAD_1)) {
keyCheck(); keyCheck();
} }
@@ -868,21 +827,7 @@ void dMeterMap_c::meter_map_move(u32 param_0) {
dMeter2Info_set2DVibration(); dMeter2Info_set2DVibration();
} }
dMeter2Info_resetPauseStatus(); dMeter2Info_resetPauseStatus();
} } else if (
#if TARGET_PC
else if (!dComIfGp_event_runCheck() && !dMsgObject_isTalkNowCheck() &&
(dMeter2Info_getMapStatus() == 0 || dMeter2Info_getMapStatus() == 1) &&
!dMeter2Info_isSub2DStatus(1) && (isFmapScreen() || isDmapScreen()) &&
dusk::getActionBindTrig(dusk::ActionBinds::OPEN_MAP_SCREEN, PAD_1))
{
dMeter2Info_setMapStatus(2);
dMeter2Info_setMapKeyDirection(0x400);
Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_OPEN_S, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
dMeter2Info_set2DVibration();
}
#endif
else if (
#if DEBUG #if DEBUG
dMw_RIGHT_TRIGGER() && dMw_RIGHT_TRIGGER() &&
#else #else
-15
View File
@@ -13,7 +13,6 @@
#include "JSystem/JUtility/JUTFont.h" #include "JSystem/JUtility/JUTFont.h"
#if TARGET_PC #if TARGET_PC
#include "dusk/menu_pointer.h"
#include "dusk/scope_guard.hpp" #include "dusk/scope_guard.hpp"
#endif #endif
@@ -576,20 +575,6 @@ void jmessage_tReference::pageSend() {
void jmessage_tReference::selectMessage() { void jmessage_tReference::selectMessage() {
if (mSelectNum != 0) { if (mSelectNum != 0) {
#if TARGET_PC
u8 pointerChoice = 0xFF;
if (dusk::menu_pointer::get_dialog_choice(pointerChoice) && pointerChoice < mSelectNum &&
pointerChoice != mSelectPos)
{
mSelectPos = pointerChoice;
if (mSelectType != 0) {
getObjectPtr()->getSequenceProcessor()->calcStringLength();
}
Z2GetAudioMgr()->seStart(Z2SE_SY_TALK_CURSOR, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
-1.0f, 0);
}
#endif
mpStick->checkTrigger(); mpStick->checkTrigger();
if (mSelectType == 0) { if (mSelectType == 0) {
+13 -18
View File
@@ -26,13 +26,12 @@
#include <cstring> #include <cstring>
#include "JSystem/JKernel/JKRExpHeap.h" #include "JSystem/JKernel/JKRExpHeap.h"
#include "dusk/version.hpp"
#include "m_Do/m_Do_controller_pad.h" #include "m_Do/m_Do_controller_pad.h"
#include "m_Do/m_Do_lib.h" #include "m_Do/m_Do_lib.h"
#if TARGET_PC #if TARGET_PC
#include "dusk/menu_pointer.h"
#include "dusk/settings.h" #include "dusk/settings.h"
#include "dusk/version.hpp"
#include <vector> #include <vector>
#include <array> #include <array>
#include <algorithm> #include <algorithm>
@@ -428,6 +427,17 @@ static void dummyStrings() {
dMsgObject_HIO_c g_MsgObject_HIO_c; dMsgObject_HIO_c g_MsgObject_HIO_c;
int dMsgObject_c::_execute() { int dMsgObject_c::_execute() {
// TODO: enabling wii message overrides fixes direction text, but gives wrong item control text
/*#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
// enable wii message index override
g_MsgObject_HIO_c.mMessageDisplay = 1;
} else if (!dusk::getSettings().game.enableMirrorMode && g_MsgObject_HIO_c.mMessageDisplay == 1) {
g_MsgObject_HIO_c.mMessageDisplay = 0;
}
#endif*/
field_0x4c7 = 0; field_0x4c7 = 0;
if (mpTalkHeap != NULL) { if (mpTalkHeap != NULL) {
field_0x148 = mDoExt_setCurrentHeap(mpTalkHeap); field_0x148 = mDoExt_setCurrentHeap(mpTalkHeap);
@@ -1113,20 +1123,7 @@ void dMsgObject_c::selectProc() {
dComIfGp_setAStatusForce(0x2a, 0); dComIfGp_setAStatusForce(0x2a, 0);
} }
} }
#if TARGET_PC if (mDoCPd_c::getTrigA(0)) {
jmessage_tReference* pRef = (jmessage_tReference*)mpRenProc->getReference();
u8 pointerChoice = 0xFF;
bool pointerConfirm = dusk::menu_pointer::consume_dialog_click(pointerChoice) &&
pointerChoice < pRef->getSelectNum();
if (pointerConfirm) {
pRef->setSelectPos(pointerChoice);
}
#endif
if (mDoCPd_c::getTrigA(0)
#if TARGET_PC
|| pointerConfirm
#endif
) {
if (getSelectCursorPosLocal() != 0xff) { if (getSelectCursorPosLocal() != 0xff) {
field_0x1a3 = 1; field_0x1a3 = 1;
} }
@@ -1148,9 +1145,7 @@ void dMsgObject_c::selectProc() {
} }
field_0x1a3 = 2; field_0x1a3 = 2;
} }
#ifndef TARGET_PC
jmessage_tReference* pRef = (jmessage_tReference*)mpRenProc->getReference(); jmessage_tReference* pRef = (jmessage_tReference*)mpRenProc->getReference();
#endif
if (getStatusLocal() == 8) { if (getStatusLocal() == 8) {
if (isMidonaMessage() && field_0x1a3 != 0) { if (isMidonaMessage() && field_0x1a3 != 0) {
if (field_0x1a3 == 2 && getSelectCancelPos() == 3) { if (field_0x1a3 == 2 && getSelectCancelPos() == 3) {
-56
View File
@@ -16,17 +16,6 @@
#include "d/d_msg_object.h" #include "d/d_msg_object.h"
#include "d/d_pane_class.h" #include "d/d_pane_class.h"
#if TARGET_PC
#include "dusk/menu_pointer.h"
namespace {
bool hit_choice_pane(CPaneMgr* pane, f32 padding) {
return pane != NULL && pane->getPanePtr() != NULL && pane->getPanePtr()->isVisible() &&
dusk::menu_pointer::hit_pane(pane, padding);
}
} // namespace
#endif
typedef void (dMsgScrn3Select_c::*processFn)(); typedef void (dMsgScrn3Select_c::*processFn)();
processFn process[] = { processFn process[] = {
&dMsgScrn3Select_c::open1Proc, &dMsgScrn3Select_c::open2Proc, &dMsgScrn3Select_c::waitProc, &dMsgScrn3Select_c::open1Proc, &dMsgScrn3Select_c::open2Proc, &dMsgScrn3Select_c::waitProc,
@@ -481,9 +470,6 @@ bool dMsgScrn3Select_c::selAnimeMove(u8 i_selNum, u8 param_1, bool param_2) {
mSelNum = i_selNum; mSelNum = i_selNum;
field_0x114 = 0; field_0x114 = 0;
field_0x108 = param_2; field_0x108 = param_2;
#if TARGET_PC
pointerMove();
#endif
(this->*process[mProcess])(); (this->*process[mProcess])();
@@ -532,48 +518,6 @@ bool dMsgScrn3Select_c::selAnimeMove(u8 i_selNum, u8 param_1, bool param_2) {
return mProcess == PROC_SELECT_e ? TRUE : FALSE; return mProcess == PROC_SELECT_e ? TRUE : FALSE;
} }
#if TARGET_PC
bool dMsgScrn3Select_c::pointerMove() {
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Dialog);
mDPDPoint = 0xFF;
const u8 firstPane = mSelNum == 2 ? 1 : 0;
for (u8 choice = 0; choice < mSelNum; ++choice) {
const u8 paneIndex = firstPane + choice;
if (paneIndex >= 3) {
continue;
}
// TODO: this sucks and should be replaced with Wii mpTouchArea
bool hit = hit_choice_pane(mpSel_c[paneIndex], 8.0f) ||
hit_choice_pane(mpTmSel_c[paneIndex], 24.0f) ||
hit_choice_pane(mpTmrSel_c[paneIndex], 24.0f) ||
hit_choice_pane(mpKahen_c[paneIndex], 8.0f) ||
hit_choice_pane(mpCursor_c[paneIndex], 8.0f);
for (int i = 0; i < 5 && !hit; ++i) {
hit = hit_choice_pane(mpSelCldw_c[i][paneIndex], 8.0f);
}
if (!hit) {
continue;
}
mDPDPoint = choice;
field_0x110 = paneIndex;
dusk::menu_pointer::set_hover_target(choice);
dusk::menu_pointer::set_dialog_choice(choice, dusk::menu_pointer::peek_click());
return true;
}
return false;
}
bool dMsgScrn3Select_c::consumePointerClick() {
u8 choice = 0xFF;
return dusk::menu_pointer::consume_dialog_click(choice);
}
#endif
bool dMsgScrn3Select_c::selAnimeEnd() { bool dMsgScrn3Select_c::selAnimeEnd() {
if (mProcess == PROC_MAX_e) { if (mProcess == PROC_MAX_e) {
return true; return true;
-4
View File
@@ -643,10 +643,6 @@ f32 dMsgScrnExplain_c::getAlphaRatio() {
bool dMsgScrnExplain_c::checkTriggerA() { bool dMsgScrnExplain_c::checkTriggerA() {
if (mDoCPd_c::getTrigA(PAD_1)) { if (mDoCPd_c::getTrigA(PAD_1)) {
return true; return true;
#if TARGET_PC
} else if (mpSelect_c != NULL && mpSelect_c->consumePointerClick()) {
return true;
#endif
} else { } else {
return false; return false;
} }
+13 -15
View File
@@ -181,24 +181,22 @@ void OSWaitCond(OSCond* cond, OSMutex* mutex) {
mutex->count = 0; mutex->count = 0;
mutex->thread = nullptr; mutex->thread = nullptr;
// Keep one recursion level held so cv.wait() is what releases the mutex; // Unlock the recursive mutex the same number of times it was locked
// fully unlocking before the wait opens a window where a signal is lost. for (s32 i = 0; i < savedCount; i++) {
if (savedCount >= 1) { mutexData.nativeMutex.unlock();
for (s32 i = 1; i < savedCount; i++) { }
mutexData.nativeMutex.unlock();
} // Wait on the condition variable
std::unique_lock lock(mutexData.nativeMutex, std::adopt_lock); {
condData.cv.wait(lock); std::unique_lock<std::recursive_mutex> lock(mutexData.nativeMutex);
lock.release();
for (s32 i = 1; i < savedCount; i++) {
mutexData.nativeMutex.lock();
}
} else {
// Mutex wasn't held on entry (contract violation); wait anyway.
std::unique_lock lock(mutexData.nativeMutex);
condData.cv.wait(lock); condData.cv.wait(lock);
} }
// Re-lock the recursive mutex the same number of times
for (s32 i = 0; i < savedCount; i++) {
mutexData.nativeMutex.lock();
}
// Restore GC mutex state // Restore GC mutex state
mutex->thread = currentThread; mutex->thread = currentThread;
mutex->count = savedCount; mutex->count = savedCount;
+20 -61
View File
@@ -8,19 +8,10 @@ namespace dusk {
static std::array<std::array<ActionBindPressData, static_cast<int>(ActionBinds::COUNT)>, PAD_CHANMAX> actionPressData{}; static std::array<std::array<ActionBindPressData, static_cast<int>(ActionBinds::COUNT)>, PAD_CHANMAX> actionPressData{};
struct VirtualActionBindData {
bool pressed = false;
bool available = false;
};
static std::array<std::array<VirtualActionBindData, static_cast<int>(ActionBinds::COUNT)>, PAD_CHANMAX> virtualActionData{};
ActionBindsMap& getActionBinds() { ActionBindsMap& getActionBinds() {
static ActionBindsMap actionBinds = { static ActionBindsMap actionBinds = {
{ActionBinds::FIRST_PERSON_CAMERA, {&getSettings().actionBindings.firstPersonCamera, "First Person Camera"}}, {ActionBinds::FIRST_PERSON_CAMERA, {&getSettings().actionBindings.firstPersonCamera, "First Person Camera"}},
{ActionBinds::CALL_MIDNA, {&getSettings().actionBindings.callMidna, "Call Midna"}}, {ActionBinds::CALL_MIDNA, {&getSettings().actionBindings.callMidna, "Call Midna"}},
{ActionBinds::OPEN_MAP_SCREEN, {&getSettings().actionBindings.openMapScreen, "Open Map Screen"}},
{ActionBinds::TOGGLE_MINIMAP, {&getSettings().actionBindings.toggleMinimap, "Toggle Minimap"}},
{ActionBinds::OPEN_DUSKLIGHT_MENU, {&getSettings().actionBindings.openDusklightMenu, "Open Dusklight Menu"}}, {ActionBinds::OPEN_DUSKLIGHT_MENU, {&getSettings().actionBindings.openDusklightMenu, "Open Dusklight Menu"}},
{ActionBinds::TURBO_SPEED_BUTTON, {&getSettings().actionBindings.turboSpeedButton, "Turbo Speed Button"}}, {ActionBinds::TURBO_SPEED_BUTTON, {&getSettings().actionBindings.turboSpeedButton, "Turbo Speed Button"}},
}; };
@@ -34,10 +25,6 @@ bool isActionBound(ActionBinds action, u32 port) {
return false; return false;
} }
if (port < PAD_CHANMAX && virtualActionData[port][static_cast<int>(action)].available) {
return true;
}
return getActionBindButton(action, port) != PAD_NATIVE_BUTTON_INVALID; return getActionBindButton(action, port) != PAD_NATIVE_BUTTON_INVALID;
} }
@@ -54,71 +41,43 @@ void updateActionBindings() {
// If the action isn't bound, or if documents are visible and the action isn't // If the action isn't bound, or if documents are visible and the action isn't
// opening the dusklight menu, don't update. Otherwise, we may accidentally // opening the dusklight menu, don't update. Otherwise, we may accidentally
// perform actions while the dusklight menu is open. // perform actions while the dusklight menu is open.
const int button = boundAction.configVars->at(port); if (!isActionBound(action, port) ||
const bool virtualAvailable = virtualActionData[port][static_cast<int>(action)].available;
if ((button == PAD_NATIVE_BUTTON_INVALID && !virtualAvailable) ||
(ui::any_document_visible() && action != ActionBinds::OPEN_DUSKLIGHT_MENU)) { (ui::any_document_visible() && action != ActionBinds::OPEN_DUSKLIGHT_MENU)) {
continue; continue;
} }
if (button != PAD_NATIVE_BUTTON_INVALID) { int button = boundAction.configVars->at(port);
// If keyboard is active for this port
u32 count = 0; // If keyboard is active for this port
if (PADGetKeyButtonBindings(port, &count) != nullptr) { u32 count = 0;
int numKeys = 0; if (PADGetKeyButtonBindings(port, &count) != nullptr) {
const bool* kbState = SDL_GetKeyboardState(&numKeys); int numKeys = 0;
if (kbState[button]) { const bool* kbState = SDL_GetKeyboardState(&numKeys);
if (kbState[button]) {
actionPressData[port][static_cast<int>(action)].pressedCurFrame = true;
}
} else {
// If controller is active
auto controller = aurora::input::get_controller_for_player(port);
if (controller) {
if (SDL_GetGamepadButton(controller->m_controller, static_cast<SDL_GamepadButton>(button))) {
actionPressData[port][static_cast<int>(action)].pressedCurFrame = true; actionPressData[port][static_cast<int>(action)].pressedCurFrame = true;
} }
} else {
// If controller is active
auto controller = aurora::input::get_controller_for_player(port);
if (controller) {
if (SDL_GetGamepadButton(controller->m_controller, static_cast<SDL_GamepadButton>(button))) {
actionPressData[port][static_cast<int>(action)].pressedCurFrame = true;
}
}
} }
} }
} }
for (auto& [action, _] : getActionBinds()) {
const auto& virtualAction = virtualActionData[port][static_cast<int>(action)];
if (virtualAction.available && virtualAction.pressed && !ui::any_document_visible()) {
actionPressData[port][static_cast<int>(action)].pressedCurFrame = true;
}
}
} }
} }
void setVirtualActionBind(ActionBinds action, u32 port, bool pressed, bool available) {
if (port >= PAD_CHANMAX) {
return;
}
virtualActionData[port][static_cast<int>(action)] = {
.pressed = pressed,
.available = available,
};
}
void clearVirtualActionBind(ActionBinds action, u32 port) {
if (port >= PAD_CHANMAX) {
return;
}
virtualActionData[port][static_cast<int>(action)] = {};
}
void clearAllVirtualActionBinds() {
virtualActionData = {};
}
bool getActionBindTrig(ActionBinds action, u32 port) { bool getActionBindTrig(ActionBinds action, u32 port) {
return actionPressData[port][static_cast<int>(action)].pressedCurFrame && return isActionBound(action, port) &&
actionPressData[port][static_cast<int>(action)].pressedCurFrame &&
!actionPressData[port][static_cast<int>(action)].pressedPrevFrame; !actionPressData[port][static_cast<int>(action)].pressedPrevFrame;
} }
bool getActionBindHold(ActionBinds action, u32 port) { bool getActionBindHold(ActionBinds action, u32 port) {
return actionPressData[port][static_cast<int>(action)].pressedCurFrame && return isActionBound(action, port) &&
actionPressData[port][static_cast<int>(action)].pressedCurFrame &&
actionPressData[port][static_cast<int>(action)].pressedPrevFrame; actionPressData[port][static_cast<int>(action)].pressedPrevFrame;
} }
-74
View File
@@ -1,74 +0,0 @@
#include "dusk/android_frame_rate.hpp"
#if defined(TARGET_ANDROID) || defined(__ANDROID__) || defined(ANDROID)
#include "dusk/settings.h"
#include <SDL3/SDL_system.h>
#include <jni.h>
namespace dusk::android {
namespace {
float preferred_surface_frame_rate() {
switch (getSettings().game.enableFrameInterpolation.getValue()) {
case FrameInterpMode::Off:
return 30.0f;
case FrameInterpMode::Unlimited:
default:
return 0.0f;
case FrameInterpMode::Capped:
return static_cast<float>(getSettings().video.maxFrameRate.getValue());
}
}
bool clear_pending_exception(JNIEnv* env) {
if (env == nullptr || !env->ExceptionCheck()) {
return false;
}
env->ExceptionClear();
return true;
}
} // namespace
void update_surface_frame_rate() {
auto* env = static_cast<JNIEnv*>(SDL_GetAndroidJNIEnv());
if (env == nullptr) {
return;
}
jobject activity = static_cast<jobject>(SDL_GetAndroidActivity());
if (activity == nullptr || clear_pending_exception(env)) {
if (activity != nullptr) {
env->DeleteLocalRef(activity);
}
return;
}
jclass activityClass = env->GetObjectClass(activity);
if (activityClass == nullptr || clear_pending_exception(env)) {
env->DeleteLocalRef(activity);
return;
}
jmethodID setPreferredFrameRate =
env->GetMethodID(activityClass, "setPreferredSurfaceFrameRate", "(F)V");
env->DeleteLocalRef(activityClass);
if (setPreferredFrameRate == nullptr || clear_pending_exception(env)) {
env->DeleteLocalRef(activity);
return;
}
jvalue args[1]{};
args[0].f = preferred_surface_frame_rate();
env->CallVoidMethodA(activity, setPreferredFrameRate, args);
env->DeleteLocalRef(activity);
clear_pending_exception(env);
}
} // namespace dusk::android
#else
namespace dusk::android {
void update_surface_frame_rate() {}
} // namespace dusk::android
#endif
-7
View File
@@ -1,7 +0,0 @@
#pragma once
namespace dusk::android {
void update_surface_frame_rate();
} // namespace dusk::android
-72
View File
@@ -1,72 +0,0 @@
#include "dusk/batch.hpp"
#include "dusk/logging.h"
#include <aurora/dl.hpp>
#include <dolphin/gx/GXEnum.h>
namespace dusk::batch {
void decode_leaf_template(const u8* dl, u32 size, LeafTemplate& out) {
out.vtxCount = 0;
out.posRefCount = 0;
bool posSeen[256] = {};
static constexpr GXVtxDescList kLeafDesc[] = {
{GX_VA_POS, GX_INDEX8},
{GX_VA_NRM, GX_INDEX8},
{GX_VA_CLR0, GX_INDEX8},
{GX_VA_TEX0, GX_INDEX8},
{GX_VA_NULL, GX_NONE},
};
aurora::gx::dl::Reader reader{dl, size, kLeafDesc};
while (const auto cmd = reader.next()) {
if (cmd->kind == aurora::gx::dl::Command::Kind::Passthrough) {
if (cmd->data[0] != GX_NOP) {
DuskLog.fatal("decode_leaf_template: unexpected opcode {:#x}", cmd->data[0]);
}
continue;
}
if (cmd->kind != aurora::gx::dl::Command::Kind::Draw) {
DuskLog.fatal("decode_leaf_template: unexpected pre-optimized draw");
}
const auto& draw = cmd->draw;
bool overflow = false;
const bool expanded =
aurora::gx::dl::expand_triangles(draw.prim, draw.vtxCount, [&](u16 i0, u16 i1, u16 i2) {
if (overflow || out.vtxCount + 3 > LeafTemplate::kMaxVtx) {
overflow = true;
return;
}
for (const u16 elem : {i0, i1, i2}) {
LeafTemplate::Vtx& v = out.vtx[out.vtxCount++];
v.pos = draw.attr_idx(elem, GX_VA_POS);
v.nrm = draw.attr_idx(elem, GX_VA_NRM);
v.clr = draw.attr_idx(elem, GX_VA_CLR0);
v.tex = draw.attr_idx(elem, GX_VA_TEX0);
if (!posSeen[v.pos]) {
posSeen[v.pos] = true;
if (out.posRefCount >= LeafTemplate::kMaxPosRefs) {
overflow = true;
return;
}
out.posRefs[out.posRefCount++] = v.pos;
}
}
});
if (!expanded) {
DuskLog.fatal("decode_leaf_template: untriangulable draw (prim {:#x}, {} verts)",
static_cast<u32>(draw.prim), draw.vtxCount);
}
if (overflow) {
DuskLog.fatal("decode_leaf_template: template overflow ({} verts, {} positions)",
out.vtxCount, out.posRefCount);
}
}
if (reader.failed()) {
DuskLog.fatal("decode_leaf_template: failed to walk display list");
}
}
} // namespace dusk::batch
-25
View File
@@ -1,25 +0,0 @@
#pragma once
#include <dolphin/types.h>
namespace dusk::batch {
struct LeafTemplate {
static constexpr u32 kMaxVtx = 192;
static constexpr u32 kMaxPosRefs = 64;
struct Vtx {
u8 pos;
u8 nrm;
u8 clr;
u8 tex;
};
Vtx vtx[kMaxVtx];
u16 vtxCount = 0;
u8 posRefs[kMaxPosRefs];
u8 posRefCount = 0;
};
void decode_leaf_template(const u8* dl, u32 size, LeafTemplate& out);
} // namespace dusk
+51 -224
View File
@@ -1,23 +1,19 @@
#include "dusk/config.hpp" #include "dusk/config.hpp"
#include "absl/container/flat_hash_map.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "nlohmann/json.hpp" #include "nlohmann/json.hpp"
#include "absl/container/flat_hash_map.h"
#include "aurora/lib/logging.hpp" #include "aurora/lib/logging.hpp"
#include "dusk/io.hpp" #include "dusk/io.hpp"
#include "dusk/settings.h" #include "dusk/settings.h"
#include <cmath>
#include <filesystem>
#include <limits> #include <limits>
#include <optional> #include <filesystem>
#include <string>
#include <string_view>
#include <system_error> #include <system_error>
#include <utility> #include <string>
#include "dusk/action_bindings.h"
#include "dusk/main.h" #include "dusk/main.h"
#include "dusk/action_bindings.h"
using namespace dusk::config; using namespace dusk::config;
@@ -30,104 +26,6 @@ aurora::Module DuskConfigLog("dusk::config");
static absl::flat_hash_map<std::string_view, ConfigVarBase*> RegisteredConfigVars; static absl::flat_hash_map<std::string_view, ConfigVarBase*> RegisteredConfigVars;
static bool RegistrationDone = false; static bool RegistrationDone = false;
static std::optional<dusk::ui::ControlAnchor> parse_control_anchor(std::string_view value) {
if (value == "none") {
return dusk::ui::ControlAnchor::None;
}
if (value == "top") {
return dusk::ui::ControlAnchor::Top;
}
if (value == "left") {
return dusk::ui::ControlAnchor::Left;
}
if (value == "bottom") {
return dusk::ui::ControlAnchor::Bottom;
}
if (value == "right") {
return dusk::ui::ControlAnchor::Right;
}
if (value == "topLeft") {
return dusk::ui::ControlAnchor::TopLeft;
}
if (value == "topRight") {
return dusk::ui::ControlAnchor::TopRight;
}
if (value == "bottomLeft") {
return dusk::ui::ControlAnchor::BottomLeft;
}
if (value == "bottomRight") {
return dusk::ui::ControlAnchor::BottomRight;
}
return std::nullopt;
}
static const char* control_anchor_value(dusk::ui::ControlAnchor anchor) {
switch (anchor) {
case dusk::ui::ControlAnchor::None:
return "none";
case dusk::ui::ControlAnchor::Top:
return "top";
case dusk::ui::ControlAnchor::Left:
return "left";
case dusk::ui::ControlAnchor::Bottom:
return "bottom";
case dusk::ui::ControlAnchor::Right:
return "right";
case dusk::ui::ControlAnchor::TopLeft:
return "topLeft";
case dusk::ui::ControlAnchor::TopRight:
return "topRight";
case dusk::ui::ControlAnchor::BottomLeft:
return "bottomLeft";
case dusk::ui::ControlAnchor::BottomRight:
return "bottomRight";
}
return "none";
}
static std::optional<float> json_finite_float(const json& object, const char* key) {
const auto iter = object.find(key);
if (iter == object.end() || !iter->is_number()) {
return std::nullopt;
}
const float value = iter->get<float>();
if (!std::isfinite(value)) {
return std::nullopt;
}
return value;
}
static std::optional<dusk::ui::ControlProps> parse_control_props(const json& value) {
if (!value.is_object()) {
return std::nullopt;
}
const auto x = json_finite_float(value, "x");
const auto y = json_finite_float(value, "y");
const auto w = json_finite_float(value, "w");
const auto h = json_finite_float(value, "h");
const auto scale = json_finite_float(value, "scale");
const auto anchorIter = value.find("anchor");
if (!x || !y || !w || !h || !scale || anchorIter == value.end() || !anchorIter->is_string()) {
return std::nullopt;
}
const auto anchor = parse_control_anchor(anchorIter->get<std::string>());
if (!anchor || *w <= 0.0f || *h <= 0.0f || *scale <= 0.0f) {
return std::nullopt;
}
return dusk::ui::ControlProps{
.x = *x,
.y = *y,
.w = *w,
.h = *h,
.scale = *scale,
.anchor = *anchor,
};
}
static std::filesystem::path GetConfigJsonPath() { static std::filesystem::path GetConfigJsonPath() {
return dusk::ConfigPath / ConfigFileName; return dusk::ConfigPath / ConfigFileName;
} }
@@ -148,8 +46,8 @@ static void ReplaceFile(const std::filesystem::path& source, const std::filesyst
} }
} }
ConfigVarBase::ConfigVarBase(const char* name, const ConfigImplBase* impl) ConfigVarBase::ConfigVarBase(const char* name, const ConfigImplBase* impl) : name(name), registered(false), layer(ConfigVarLayer::Default), impl(impl) {
: name(name), registered(false), layer(ConfigVarLayer::Default), impl(impl) {} }
const char* ConfigVarBase::getName() const noexcept { const char* ConfigVarBase::getName() const noexcept {
return name; return name;
@@ -174,13 +72,11 @@ static T sanitizeEnumValue(const ConfigVar<T>& cVar, T value) {
return value; return value;
} }
template <ConfigValue T> template<ConfigValue T>
void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) { void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) {
if constexpr (std::is_enum_v<T>) { if constexpr (std::is_enum_v<T>) {
if (jsonValue.is_boolean()) { if (jsonValue.is_boolean()) {
DuskConfigLog.error("Doing default migration of CVar {} from bool, enum values may not " DuskConfigLog.error("Doing default migration of CVar {} from bool, enum values may not be what is expected!", cVar.getName());
"be what is expected!",
cVar.getName());
using Underlying = std::underlying_type_t<T>; using Underlying = std::underlying_type_t<T>;
const bool b = jsonValue.get<bool>(); const bool b = jsonValue.get<bool>();
@@ -195,14 +91,13 @@ void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) {
cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<T>()), false); cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<T>()), false);
} }
template <ConfigValue T> template<ConfigValue T>
nlohmann::json ConfigImpl<T>::dumpToJson(const ConfigVar<T>& cVar) { nlohmann::json ConfigImpl<T>::dumpToJson(const ConfigVar<T>& cVar) {
return cVar.getValueForSave(); return cVar.getValueForSave();
} }
template <ConfigValue T> template<ConfigValue T> requires std::is_integral_v<T> && std::is_signed_v<T>
requires std::is_integral_v<T>&& std::is_signed_v<T> static void loadFromArgImpl( static void loadFromArgImpl(ConfigVar<T>& cVar, const std::string_view stringValue) {
ConfigVar<T>& cVar, const std::string_view stringValue) {
const std::string str(stringValue); const std::string str(stringValue);
const auto result = std::stoll(str); const auto result = std::stoll(str);
if (result >= std::numeric_limits<T>::min() && result <= std::numeric_limits<T>::max()) { if (result >= std::numeric_limits<T>::min() && result <= std::numeric_limits<T>::max()) {
@@ -212,9 +107,8 @@ requires std::is_integral_v<T>&& std::is_signed_v<T> static void loadFromArgImpl
} }
} }
template <ConfigValue T> template<ConfigValue T> requires std::is_integral_v<T> && std::is_unsigned_v<T>
requires std::is_integral_v<T>&& std::is_unsigned_v<T> static void loadFromArgImpl( static void loadFromArgImpl(ConfigVar<T>& cVar, const std::string_view stringValue) {
ConfigVar<T>& cVar, const std::string_view stringValue) {
const std::string str(stringValue); const std::string str(stringValue);
const auto result = std::stoull(str); const auto result = std::stoull(str);
if (result <= std::numeric_limits<T>::max()) { if (result <= std::numeric_limits<T>::max()) {
@@ -240,17 +134,14 @@ static void loadFromArgImpl(ConfigVar<std::string>& cVar, const std::string_view
cVar.setOverrideValue(std::string(stringValue)); cVar.setOverrideValue(std::string(stringValue));
} }
template <ConfigValue T> template<ConfigValue T> requires std::is_enum_v<T>
requires std::is_enum_v<T> static void loadFromArgImpl( static void loadFromArgImpl(ConfigVar<T>& cVar, const std::string_view stringValue) {
ConfigVar<T>& cVar, const std::string_view stringValue) {
using Underlying = std::underlying_type_t<T>; using Underlying = std::underlying_type_t<T>;
const std::string str(stringValue); const std::string str(stringValue);
if constexpr (std::is_signed_v<Underlying>) { if constexpr (std::is_signed_v<Underlying>) {
const auto result = std::stoll(str); const auto result = std::stoll(str);
if (result >= std::numeric_limits<Underlying>::min() && if (result >= std::numeric_limits<Underlying>::min() && result <= std::numeric_limits<Underlying>::max()) {
result <= std::numeric_limits<Underlying>::max())
{
cVar.setOverrideValue(sanitizeEnumValue(cVar, static_cast<T>(result))); cVar.setOverrideValue(sanitizeEnumValue(cVar, static_cast<T>(result)));
} else { } else {
throw std::out_of_range("Value is too large"); throw std::out_of_range("Value is too large");
@@ -265,20 +156,16 @@ requires std::is_enum_v<T> static void loadFromArgImpl(
} }
} }
template <ConfigValue T> template<ConfigValue T>
void ConfigImpl<T>::loadFromArg(ConfigVar<T>& cVar, const std::string_view stringValue) { void ConfigImpl<T>::loadFromArg(ConfigVar<T>& cVar, const std::string_view stringValue) {
loadFromArgImpl(cVar, stringValue); loadFromArgImpl(cVar, stringValue);
} }
template <> template<>
void ConfigImpl<bool>::loadFromArg(ConfigVar<bool>& cVar, const std::string_view stringValue) { void ConfigImpl<bool>::loadFromArg(ConfigVar<bool>& cVar, const std::string_view stringValue) {
if (stringValue == "1" || stringValue == "TRUE" || stringValue == "true" || if (stringValue == "1" || stringValue == "TRUE" || stringValue == "true" || stringValue == "True") {
stringValue == "True")
{
cVar.setOverrideValue(true); cVar.setOverrideValue(true);
} else if (stringValue == "0" || stringValue == "FALSE" || stringValue == "false" || } else if (stringValue == "0" || stringValue == "FALSE" || stringValue == "false" || stringValue == "False") {
stringValue == "False")
{
cVar.setOverrideValue(false); cVar.setOverrideValue(false);
} else { } else {
throw InvalidConfigError("Value cannot be parsed as boolean"); throw InvalidConfigError("Value cannot be parsed as boolean");
@@ -287,104 +174,42 @@ void ConfigImpl<bool>::loadFromArg(ConfigVar<bool>& cVar, const std::string_view
// My IDE is convinced this namespace is necessary. It shouldn't be AFAICT? // My IDE is convinced this namespace is necessary. It shouldn't be AFAICT?
namespace dusk::config { namespace dusk::config {
template class ConfigImpl<bool>; template class ConfigImpl<bool>;
template class ConfigImpl<s8>; template class ConfigImpl<s8>;
template class ConfigImpl<u8>; template class ConfigImpl<u8>;
template class ConfigImpl<s16>; template class ConfigImpl<s16>;
template class ConfigImpl<u16>; template class ConfigImpl<u16>;
template class ConfigImpl<s32>; template class ConfigImpl<s32>;
template class ConfigImpl<u32>; template class ConfigImpl<u32>;
template class ConfigImpl<s64>; template class ConfigImpl<s64>;
template class ConfigImpl<u64>; template class ConfigImpl<u64>;
template class ConfigImpl<f32>; template class ConfigImpl<f32>;
template class ConfigImpl<f64>; template class ConfigImpl<f64>;
template class ConfigImpl<std::string>; template class ConfigImpl<std::string>;
template class ConfigImpl<dusk::BloomMode>; template class ConfigImpl<dusk::BloomMode>;
template class ConfigImpl<dusk::DepthOfFieldMode>; template class ConfigImpl<dusk::DepthOfFieldMode>;
template class ConfigImpl<dusk::DiscVerificationState>; template class ConfigImpl<dusk::DiscVerificationState>;
template class ConfigImpl<dusk::GameLanguage>; template class ConfigImpl<dusk::GameLanguage>;
template class ConfigImpl<dusk::GyroMode>;
template <> template<> void ConfigImpl<FrameInterpMode>::loadFromJson(ConfigVar<FrameInterpMode>& cVar, const json& jsonValue) {
void ConfigImpl<FrameInterpMode>::loadFromJson( if (jsonValue.is_boolean()) {
ConfigVar<FrameInterpMode>& cVar, const json& jsonValue) { const bool b = jsonValue.get<bool>();
if (jsonValue.is_boolean()) {
const bool b = jsonValue.get<bool>();
const FrameInterpMode mode = b ? FrameInterpMode::Unlimited : FrameInterpMode::Off; const FrameInterpMode mode = b ? FrameInterpMode::Unlimited : FrameInterpMode::Off;
cVar.setValue(sanitizeEnumValue(cVar, mode), false); cVar.setValue(sanitizeEnumValue(cVar, mode), false);
return; return;
}
cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<FrameInterpMode>()), false);
}
template <>
void ConfigImpl<ui::ControlLayout>::loadFromJson(
ConfigVar<ui::ControlLayout>& cVar, const json& jsonValue) {
if (!jsonValue.is_object()) {
return;
}
const int version = jsonValue.value("version", 0);
if (version != ui::ControlLayout::Version) {
return;
}
const auto controlsIter = jsonValue.find("controls");
if (controlsIter == jsonValue.end() || !controlsIter->is_object()) {
return;
}
ui::ControlLayout layout{.version = version};
for (const auto& control : controlsIter->items()) {
if (!ui::is_control_layout_id(control.key())) {
continue;
} }
if (const auto props = parse_control_props(control.value())) { cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<FrameInterpMode>()), false);
layout.controls[control.key()] = *props;
}
} }
template class ConfigImpl<dusk::FrameInterpMode>;
cVar.setValue(std::move(layout), false); template class ConfigImpl<dusk::MenuScaling>;
template class ConfigImpl<dusk::Resampler>;
template class ConfigImpl<dusk::MagicArmorMode>;
} }
template <>
void ConfigImpl<ui::ControlLayout>::loadFromArg(
ConfigVar<ui::ControlLayout>&, const std::string_view) {
throw InvalidConfigError("Touch control layout cannot be parsed from launch arguments");
}
template <>
nlohmann::json ConfigImpl<ui::ControlLayout>::dumpToJson(const ConfigVar<ui::ControlLayout>& cVar) {
const auto& layout = cVar.getValueForSave();
json controls = json::object();
for (const auto& [id, props] : layout.controls) {
controls[id] = {
{"x", props.x},
{"y", props.y},
{"w", props.w},
{"h", props.h},
{"scale", props.scale},
{"anchor", control_anchor_value(props.anchor)},
};
}
return {
{"version", ui::ControlLayout::Version},
{"controls", std::move(controls)},
};
}
template class ConfigImpl<dusk::FrameInterpMode>;
template class ConfigImpl<dusk::TouchTargeting>;
template class ConfigImpl<dusk::MenuScaling>;
template class ConfigImpl<dusk::Resampler>;
template class ConfigImpl<dusk::MagicArmorMode>;
template class ConfigImpl<dusk::ui::ControlLayout>;
} // namespace dusk::config
void dusk::config::Register(ConfigVarBase& configVar) { void dusk::config::Register(ConfigVarBase& configVar) {
const auto& name = configVar.getName(); const auto& name = configVar.getName();
if (RegistrationDone) { if (RegistrationDone) {
@@ -473,7 +298,9 @@ void dusk::config::Save() {
} }
const auto configPathString = io::fs_path_to_string(configJsonPath); const auto configPathString = io::fs_path_to_string(configJsonPath);
DuskConfigLog.info("Saving config to '{}'", configPathString); DuskConfigLog.info(
"Saving config to '{}'",
configPathString);
json j; json j;
+10 -1
View File
@@ -70,7 +70,16 @@ bool rollgoal_gyro_enabled() {
} }
bool queryGyroAimContext() { bool queryGyroAimContext() {
return getSettings().game.enableGyroAim.getValue() && dCamera_c::isAimActive(); if (!static_cast<bool>(getSettings().game.enableGyroAim)) {
return false;
}
daAlink_c* link = daAlink_getAlinkActorClass();
if (link == nullptr) {
return false;
}
return link->checkAimContext() && dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10);
} }
void read(float dt) { void read(float dt) {
+28
View File
@@ -375,6 +375,7 @@ namespace dusk {
void ImGuiConsole::PostDraw() { void ImGuiConsole::PostDraw() {
m_menuTools.afterDraw(); m_menuTools.afterDraw();
ShowPipelineProgress();
} }
void ImGuiConsole::UpdateDragScroll() { void ImGuiConsole::UpdateDragScroll() {
@@ -523,4 +524,31 @@ namespace dusk {
return false; return false;
} }
void ImGuiConsole::ShowPipelineProgress() {
const auto* stats = aurora_get_stats();
const u32 queuedPipelines = stats->queuedPipelines;
if (queuedPipelines == 0 || !getSettings().backend.showPipelineCompilation) {
return;
}
const u32 createdPipelines = stats->createdPipelines;
const u32 totalPipelines = queuedPipelines + createdPipelines;
const auto* viewport = ImGui::GetMainViewport();
const auto padding = viewport->WorkPos.y + 10.f;
const auto halfWidth = viewport->GetWorkCenter().x;
ImGui::SetNextWindowPos(ImVec2{halfWidth, padding}, ImGuiCond_Always, ImVec2{0.5f, 0.f});
ImGui::SetNextWindowSize(ImVec2{halfWidth, 0.f}, ImGuiCond_Always);
ImGui::SetNextWindowBgAlpha(0.65f);
ImGui::Begin("Pipelines", nullptr,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing);
const auto percent = static_cast<float>(createdPipelines) / static_cast<float>(totalPipelines);
const auto progressStr = fmt::format("Processing pipelines: {} / {}", createdPipelines, totalPipelines);
const auto textSize = ImGui::CalcTextSize(progressStr.data(), progressStr.data() + progressStr.size());
ImGui::NewLine();
ImGui::SameLine(ImGui::GetWindowWidth() / 2.f - textSize.x + textSize.x / 2.f);
ImGuiStringViewText(progressStr);
ImGui::ProgressBar(percent);
ImGui::End();
}
} }
+1
View File
@@ -35,6 +35,7 @@ private:
// Keep always last // Keep always last
ImGuiMenuTools m_menuTools; ImGuiMenuTools m_menuTools;
void ShowPipelineProgress();
void UpdateDragScroll(); void UpdateDragScroll();
}; };
-123
View File
@@ -1,16 +1,12 @@
#include "dusk/logging.h" #include "dusk/logging.h"
#include <algorithm>
#include <array> #include <array>
#include <atomic> #include <atomic>
#include <chrono> #include <chrono>
#include <cctype>
#include <cstdint>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <filesystem> #include <filesystem>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <vector>
#include "dusk/io.hpp" #include "dusk/io.hpp"
#include "tracy/Tracy.hpp" #include "tracy/Tracy.hpp"
@@ -48,9 +44,6 @@ namespace {
// We use this to check if the LogState is destroyed before attempting to acquire it. // We use this to check if the LogState is destroyed before attempting to acquire it.
std::atomic g_logStateAlive(true); std::atomic g_logStateAlive(true);
std::atomic<int> g_logFd(-1); std::atomic<int> g_logFd(-1);
constexpr size_t MaxRetainedLogCount = 10;
constexpr size_t MaxRetainedOldLogCount = MaxRetainedLogCount - 1;
constexpr uintmax_t MaxRetainedOldLogBytes = 100ull * 1024ull * 1024ull;
struct LogState { struct LogState {
std::mutex mutex; std::mutex mutex;
@@ -98,121 +91,6 @@ FILE* LogStreamForLevel(AuroraLogLevel level) {
return level >= LOG_ERROR ? stderr : stdout; return level >= LOG_ERROR ? stderr : stdout;
} }
struct LogFileCandidate {
std::filesystem::path path;
std::string filename;
uintmax_t size;
};
void warn_log_cleanup_failure(
const char* action, const std::filesystem::path& path, const std::error_code& ec) {
std::fprintf(stderr, "[WARNING | dusk] Failed to %s '%s': %s\n", action,
dusk::io::fs_path_to_string(path).c_str(), ec.message().c_str());
}
bool is_digit_at(const std::string_view value, size_t index) {
return std::isdigit(static_cast<unsigned char>(value[index])) != 0;
}
bool is_generated_log_file_name(const std::filesystem::path& path) {
const std::string filename = path.filename().string();
constexpr std::string_view currentPrefix = "dusklight-"sv;
constexpr std::string_view legacyPrefix = "dusk-"sv;
constexpr std::string_view suffix = ".log"sv;
size_t timestampOffset = 0;
if (filename.starts_with(currentPrefix)) {
timestampOffset = currentPrefix.size();
} else if (filename.starts_with(legacyPrefix)) {
timestampOffset = legacyPrefix.size();
} else {
return false;
}
if (filename.size() != timestampOffset + 19 || !filename.ends_with(suffix) ||
filename[timestampOffset + 8] != '-') {
return false;
}
for (size_t i = timestampOffset; i < timestampOffset + 8; ++i) {
if (!is_digit_at(filename, i)) {
return false;
}
}
for (size_t i = timestampOffset + 9; i < timestampOffset + 15; ++i) {
if (!is_digit_at(filename, i)) {
return false;
}
}
return true;
}
void delete_log_file(const std::filesystem::path& path) {
std::error_code ec;
std::filesystem::remove(path, ec);
if (ec) {
warn_log_cleanup_failure("remove old log file", path, ec);
}
}
void prune_old_log_files(const std::filesystem::path& logsDir) {
std::error_code ec;
std::filesystem::directory_iterator entries{logsDir, ec};
if (ec) {
warn_log_cleanup_failure("inspect log directory", logsDir, ec);
return;
}
std::vector<LogFileCandidate> candidates;
for (const auto& entry : entries) {
const std::filesystem::path path = entry.path();
if (!is_generated_log_file_name(path)) {
continue;
}
ec.clear();
const auto status = entry.symlink_status(ec);
if (ec) {
warn_log_cleanup_failure("inspect log file", path, ec);
continue;
}
if (!std::filesystem::is_regular_file(status)) {
continue;
}
ec.clear();
const uintmax_t size = entry.file_size(ec);
if (ec) {
warn_log_cleanup_failure("inspect size of log file", path, ec);
continue;
}
candidates.push_back({path, path.filename().string(), size});
}
std::sort(candidates.begin(), candidates.end(),
[](const LogFileCandidate& a, const LogFileCandidate& b) {
return a.filename > b.filename;
});
const size_t retainedCount = std::min(candidates.size(), MaxRetainedOldLogCount);
uintmax_t retainedBytes = 0;
for (size_t i = 0; i < retainedCount; ++i) {
retainedBytes += candidates[i].size;
}
size_t retainedAfterSizeLimit = retainedCount;
while (retainedAfterSizeLimit > 0 && retainedBytes > MaxRetainedOldLogBytes) {
--retainedAfterSizeLimit;
retainedBytes -= candidates[retainedAfterSizeLimit].size;
}
for (size_t i = retainedAfterSizeLimit; i < candidates.size(); ++i) {
delete_log_file(candidates[i].path);
}
}
std::string MakeTimestampedLogName() { std::string MakeTimestampedLogName() {
const auto now = std::chrono::system_clock::now(); const auto now = std::chrono::system_clock::now();
const std::time_t nowTime = std::chrono::system_clock::to_time_t(now); const std::time_t nowTime = std::chrono::system_clock::to_time_t(now);
@@ -352,7 +230,6 @@ void dusk::InitializeFileLogging(const std::filesystem::path& configDir, AuroraL
io::fs_path_to_string(logsDir).c_str(), ec.message().c_str()); io::fs_path_to_string(logsDir).c_str(), ec.message().c_str());
return; return;
} }
prune_old_log_files(logsDir);
const std::filesystem::path logPath = logsDir / MakeTimestampedLogName(); const std::filesystem::path logPath = logsDir / MakeTimestampedLogName();
g_logState.file = io::FileStream::Create(logPath).ToInner(); g_logState.file = io::FileStream::Create(logPath).ToInner();
-514
View File
@@ -1,514 +0,0 @@
#include "dusk/menu_pointer.h"
#include "d/d_pane_class.h"
#include "dusk/settings.h"
#include "m_Do/m_Do_graphic.h"
#include <aurora/rmlui.hpp>
#include <dolphin/pad.h>
#include <algorithm>
#include <chrono>
namespace dusk::menu_pointer {
namespace {
using Clock = std::chrono::steady_clock;
constexpr auto kTapMaxDuration = std::chrono::milliseconds(300);
constexpr f32 kTapMoveThresholdDp = 12.0f;
struct Gesture {
bool active = false;
bool movedTooFar = false;
bool crossedTarget = false;
bool pressTargetValid = false;
Context pressContext = Context::None;
TargetId pressTarget = InvalidTarget;
f32 startX = 0.0f;
f32 startY = 0.0f;
Clock::time_point startedAt{};
};
State s_state;
bool s_clickConsumed = false;
Context s_lastContext = Context::None;
Context s_currentContext = Context::None;
u8 s_lastDialogChoice = 0xFF;
u8 s_currentDialogChoice = 0xFF;
bool s_lastDialogChoiceValid = false;
bool s_currentDialogChoiceValid = false;
bool s_lastDialogClicked = false;
bool s_currentDialogClicked = false;
bool s_mouseActive = false;
bool s_mouseButtonCaptured = false;
s32 s_mouseButton = -1;
u32 s_suppressedPadHoldMask = 0;
u32 s_suppressedPadNextReadMask = 0;
Context s_deferredActivationContext = Context::None;
TargetId s_deferredActivationTarget = InvalidTarget;
Gesture s_gesture;
bool s_hoverTargetValid = false;
TargetId s_hoverTarget = InvalidTarget;
bool s_clickPending = false;
Context s_clickContext = Context::None;
TargetId s_clickTarget = InvalidTarget;
bool s_clickTargetValid = false;
s32 scancode_from_rml_button(s32 button) noexcept {
switch (button) {
case 0:
return PAD_KEY_MOUSE_LEFT;
case 1:
return PAD_KEY_MOUSE_RIGHT;
case 2:
return PAD_KEY_MOUSE_MIDDLE;
default:
return PAD_KEY_INVALID;
}
}
bool is_mouse_scancode(s32 scancode) noexcept {
return scancode >= PAD_KEY_MOUSE_X2 && scancode <= PAD_KEY_MOUSE_LEFT;
}
PADButton pad_button_for_scancode(u32 port, s32 scancode) noexcept {
u32 count = 0;
PADKeyButtonBinding* bindings = PADGetKeyButtonBindings(port, &count);
if (bindings == nullptr) {
return 0;
}
for (u32 i = 0; i < count; ++i) {
if (bindings[i].scancode == scancode) {
return bindings[i].padButton;
}
}
return 0;
}
s32 menu_confirm_mouse_scancode() noexcept {
constexpr u32 port = PAD_CHAN0;
u32 count = 0;
PADKeyButtonBinding* bindings = PADGetKeyButtonBindings(port, &count);
if (bindings == nullptr) {
return PAD_KEY_MOUSE_LEFT;
}
for (u32 i = 0; i < count; ++i) {
if (bindings[i].padButton == PAD_BUTTON_A && is_mouse_scancode(bindings[i].scancode)) {
return bindings[i].scancode;
}
}
return pad_button_for_scancode(port, PAD_KEY_MOUSE_LEFT) != 0 ? PAD_KEY_INVALID :
PAD_KEY_MOUSE_LEFT;
}
bool mouse_button_is_menu_confirm(s32 button) noexcept {
const s32 scancode = scancode_from_rml_button(button);
return scancode != PAD_KEY_INVALID && scancode == menu_confirm_mouse_scancode();
}
void suppress_pad_for_mouse_button(s32 button, bool held) noexcept {
const s32 scancode = scancode_from_rml_button(button);
if (scancode == PAD_KEY_INVALID) {
return;
}
const PADButton padButton = pad_button_for_scancode(PAD_CHAN0, scancode);
if (padButton == 0) {
return;
}
s_suppressedPadNextReadMask |= padButton;
if (held) {
s_suppressedPadHoldMask |= padButton;
} else {
s_suppressedPadHoldMask &= ~padButton;
}
}
f32 tap_move_threshold() noexcept {
auto* context = aurora::rmlui::get_context();
if (context == nullptr) {
return kTapMoveThresholdDp;
}
return kTapMoveThresholdDp * std::max(context->GetDensityIndependentPixelRatio(), 1.0f);
}
void update_gesture_movement(f32 x, f32 y) noexcept {
if (!s_gesture.active || s_gesture.movedTooFar) {
return;
}
const f32 dx = x - s_gesture.startX;
const f32 dy = y - s_gesture.startY;
const f32 threshold = tap_move_threshold();
if (dx * dx + dy * dy > threshold * threshold) {
s_gesture.movedTooFar = true;
}
}
void clear_click_state() noexcept {
s_clickConsumed = false;
s_clickPending = false;
s_clickContext = Context::None;
s_clickTarget = InvalidTarget;
s_clickTargetValid = false;
s_state.clicked = false;
}
void set_position_from_rml(f32 x, f32 y) noexcept {
auto* context = aurora::rmlui::get_context();
if (context == nullptr) {
return;
}
const auto dimensions = context->GetDimensions();
const f32 width = std::max(static_cast<f32>(dimensions.x), 1.0f);
const f32 height = std::max(static_cast<f32>(dimensions.y), 1.0f);
s_state.x = mDoGph_gInf_c::getMinXF() + x / width * mDoGph_gInf_c::getWidthF();
s_state.y = mDoGph_gInf_c::getMinYF() + y / height * mDoGph_gInf_c::getHeightF();
s_state.valid = true;
}
void clear_input_state() noexcept {
s_state = {};
clear_click_state();
s_lastDialogChoice = 0xFF;
s_currentDialogChoice = 0xFF;
s_lastDialogChoiceValid = false;
s_currentDialogChoiceValid = false;
s_lastDialogClicked = false;
s_currentDialogClicked = false;
s_mouseActive = false;
s_mouseButtonCaptured = false;
s_mouseButton = -1;
s_suppressedPadHoldMask = 0;
s_suppressedPadNextReadMask = 0;
s_deferredActivationContext = Context::None;
s_deferredActivationTarget = InvalidTarget;
s_gesture = {};
s_hoverTargetValid = false;
s_hoverTarget = InvalidTarget;
}
} // namespace
bool handle_fallthrough_pointer(f32 x, f32 y, Phase phase, bool touch, s32 mouseButton) noexcept {
if (!enabled()) {
return false;
}
if (!touch) {
if (phase == Phase::Press) {
if (!mouse_button_is_menu_confirm(mouseButton)) {
return false;
}
s_mouseButtonCaptured = true;
s_mouseButton = mouseButton;
suppress_pad_for_mouse_button(mouseButton, true);
} else if (phase == Phase::Release) {
if (!s_mouseButtonCaptured || s_mouseButton != mouseButton) {
return false;
}
suppress_pad_for_mouse_button(mouseButton, false);
s_mouseButtonCaptured = false;
s_mouseButton = -1;
} else if (phase == Phase::Cancel) {
if (s_mouseButtonCaptured) {
suppress_pad_for_mouse_button(s_mouseButton, false);
s_mouseButtonCaptured = false;
s_mouseButton = -1;
} else if (!s_mouseActive) {
return false;
}
}
s_mouseActive = true;
}
if (phase != Phase::Cancel) {
update_gesture_movement(x, y);
set_position_from_rml(x, y);
}
s_state.touch = touch;
switch (phase) {
case Phase::Press:
clear_click_state();
s_gesture = {
.active = true,
.startX = x,
.startY = y,
.startedAt = Clock::now(),
};
s_state.down = true;
s_state.pressed = true;
break;
case Phase::Release: {
const bool shortEnough =
s_gesture.active && Clock::now() - s_gesture.startedAt <= kTapMaxDuration;
const bool stillEnough = s_gesture.active && !s_gesture.movedTooFar;
const bool targetClean = s_gesture.active && !s_gesture.crossedTarget;
s_clickContext = s_gesture.pressContext;
s_clickTarget = s_gesture.pressTarget;
s_clickTargetValid = s_gesture.pressTargetValid;
s_clickPending = shortEnough && stillEnough && targetClean;
s_state.down = false;
s_state.released = true;
s_state.clicked = s_clickPending;
s_gesture = {};
break;
}
case Phase::Cancel:
clear_click_state();
s_gesture = {};
s_state.down = false;
break;
case Phase::Move:
default:
break;
}
return true;
}
void begin_game_frame() noexcept {
s_currentContext = Context::None;
s_currentDialogChoice = 0xFF;
s_currentDialogChoiceValid = false;
s_currentDialogClicked = false;
s_clickConsumed = false;
if (!enabled()) {
clear_input_state();
}
}
void end_game_frame() noexcept {
if (s_gesture.active && s_gesture.pressTargetValid &&
s_currentContext == s_gesture.pressContext && !s_hoverTargetValid)
{
s_gesture.crossedTarget = true;
}
s_lastContext = s_currentContext;
s_lastDialogChoice = s_currentDialogChoice;
s_lastDialogChoiceValid = s_currentDialogChoiceValid;
s_lastDialogClicked = s_currentDialogClicked;
s_state.pressed = false;
s_state.released = false;
s_state.clicked = false;
if (!s_state.down) {
s_state.valid = false;
}
s_clickConsumed = false;
s_clickPending = false;
s_clickContext = Context::None;
s_clickTarget = InvalidTarget;
s_clickTargetValid = false;
s_hoverTargetValid = false;
s_hoverTarget = InvalidTarget;
}
void begin_context(Context context) noexcept {
if (context == Context::None || !enabled()) {
return;
}
if (s_lastContext == Context::None && s_currentContext == Context::None) {
s_state = {};
s_mouseActive = false;
s_mouseButtonCaptured = false;
s_mouseButton = -1;
s_suppressedPadHoldMask = 0;
s_suppressedPadNextReadMask = 0;
s_deferredActivationContext = Context::None;
s_deferredActivationTarget = InvalidTarget;
s_gesture = {};
s_hoverTargetValid = false;
s_hoverTarget = InvalidTarget;
clear_click_state();
}
s_currentContext = context;
}
bool active() noexcept {
return s_currentContext != Context::None || s_lastContext != Context::None;
}
bool enabled() noexcept {
return getSettings().game.enableMenuPointer.getValue();
}
bool mouse_capture_active() noexcept {
return enabled() && s_mouseButtonCaptured;
}
const State& state() noexcept {
return s_state;
}
void set_hover_target(TargetId target) noexcept {
s_hoverTargetValid = true;
s_hoverTarget = target;
if (s_gesture.active && !s_gesture.pressTargetValid && s_state.down) {
s_gesture.pressContext = s_currentContext;
s_gesture.pressTarget = target;
s_gesture.pressTargetValid = true;
}
if (s_gesture.active && s_gesture.pressTargetValid &&
(s_currentContext != s_gesture.pressContext || target != s_gesture.pressTarget))
{
s_gesture.crossedTarget = true;
}
}
bool click_matches_hover_target() noexcept {
if (!s_clickPending || !s_hoverTargetValid) {
return false;
}
if (!s_clickTargetValid) {
return true;
}
return s_currentContext == s_clickContext && s_hoverTarget == s_clickTarget;
}
bool consume_click() noexcept {
if (s_clickConsumed || !click_matches_hover_target()) {
return false;
}
s_clickConsumed = true;
s_clickPending = false;
s_state.clicked = false;
return true;
}
bool peek_click() noexcept {
return !s_clickConsumed && click_matches_hover_target();
}
void set_dialog_choice(u8 choice, bool clicked) noexcept {
s_currentDialogChoice = choice;
s_currentDialogChoiceValid = true;
s_currentDialogClicked = clicked;
}
bool get_dialog_choice(u8& choice) noexcept {
if (s_currentDialogChoiceValid) {
choice = s_currentDialogChoice;
return true;
}
if (s_lastDialogChoiceValid) {
choice = s_lastDialogChoice;
return true;
}
return false;
}
bool consume_dialog_click(u8& choice) noexcept {
if (s_currentDialogChoiceValid && s_currentDialogClicked) {
choice = s_currentDialogChoice;
s_currentDialogClicked = false;
return true;
}
if (s_lastDialogChoiceValid && s_lastDialogClicked) {
choice = s_lastDialogChoice;
s_lastDialogClicked = false;
return true;
}
return false;
}
void defer_activation(Context context, TargetId target) noexcept {
s_deferredActivationContext = context;
s_deferredActivationTarget = target;
}
bool consume_deferred_activation(Context context, TargetId target) noexcept {
if (s_deferredActivationContext != context || s_deferredActivationTarget != target) {
return false;
}
s_deferredActivationContext = Context::None;
s_deferredActivationTarget = InvalidTarget;
return true;
}
void clear_deferred_activation(Context context) noexcept {
if (s_deferredActivationContext != context) {
return;
}
s_deferredActivationContext = Context::None;
s_deferredActivationTarget = InvalidTarget;
}
u32 suppressed_pad_buttons(u32 port) noexcept {
if (port != PAD_CHAN0) {
return 0;
}
return s_suppressedPadHoldMask | s_suppressedPadNextReadMask;
}
void finish_pad_suppression_read(u32 port) noexcept {
if (port != PAD_CHAN0) {
return;
}
s_suppressedPadNextReadMask = 0;
}
bool hit_rect(f32 left, f32 top, f32 right, f32 bottom, f32 padding) noexcept {
const auto& state = menu_pointer::state();
if (!state.valid) {
return false;
}
if (left > right) {
std::swap(left, right);
}
if (top > bottom) {
std::swap(top, bottom);
}
return state.x >= left - padding && state.x <= right + padding && state.y >= top - padding &&
state.y <= bottom + padding;
}
bool hit_pane(CPaneMgr* pane, f32 padding) noexcept {
if (pane == nullptr || pane->getPanePtr() == nullptr) {
return false;
}
Mtx mtx;
Vec v0 = pane->getGlobalVtx(&mtx, 0, false, 0);
Vec v1 = pane->getGlobalVtx(&mtx, 1, false, 0);
Vec v2 = pane->getGlobalVtx(&mtx, 2, false, 0);
Vec v3 = pane->getGlobalVtx(&mtx, 3, false, 0);
const f32 left = std::min({v0.x, v1.x, v2.x, v3.x});
const f32 right = std::max({v0.x, v1.x, v2.x, v3.x});
const f32 top = std::min({v0.y, v1.y, v2.y, v3.y});
const f32 bottom = std::max({v0.y, v1.y, v2.y, v3.y});
return hit_rect(left, top, right, bottom, padding);
}
bool hit_pane(J2DPane* pane, f32 padding) noexcept {
if (pane == nullptr || !pane->isVisible()) {
return false;
}
const JGeometry::TBox2<f32>& bounds = pane->getBounds();
return hit_rect(bounds.i.x, bounds.i.y, bounds.f.x, bounds.f.y, padding);
}
} // namespace dusk::menu_pointer
+60 -74
View File
@@ -1,69 +1,62 @@
#include "dusk/mouse.h" #include "dusk/mouse.h"
#include "d/actor/d_a_alink.h"
#include "d/d_com_inf_game.h"
#include "dusk/menu_pointer.h"
#include "dusk/settings.h" #include "dusk/settings.h"
#include "dusk/ui/ui.hpp" #include "dusk/ui/ui.hpp"
#include "d/actor/d_a_alink.h"
#include "d/d_com_inf_game.h"
#include <SDL3/SDL_mouse.h>
#include <SDL3/SDL_video.h>
#include <aurora/lib/window.hpp> #include <aurora/lib/window.hpp>
#include <imgui.h> #include <imgui.h>
#include <SDL3/SDL_mouse.h>
#include <chrono> #include <SDL3/SDL_video.h>
namespace dusk::mouse { namespace dusk::mouse {
namespace { namespace {
using Clock = std::chrono::steady_clock;
constexpr float kMousePixelToRad = 0.0025f; constexpr float kMousePixelToRad = 0.0025f;
constexpr auto kCursorIdleDuration = std::chrono::seconds(1); constexpr int kIdleHideFrames = 99; // Approx. 3 seconds with 33ms ticks
float s_aim_yaw_rad = 0.0f; float s_aim_yaw_rad = 0.0f;
float s_aim_pitch_rad = 0.0f; float s_aim_pitch_rad = 0.0f;
float s_camera_yaw_rad = 0.0f; float s_camera_yaw_rad = 0.0f;
float s_camera_pitch_rad = 0.0f; float s_camera_pitch_rad = 0.0f;
Clock::time_point s_last_cursor_motion = Clock::now(); int s_idle_frames = 0;
void reset_deltas() { void reset_deltas() {
s_aim_yaw_rad = s_aim_pitch_rad = 0.0f; s_aim_yaw_rad = s_aim_pitch_rad = 0.0f;
s_camera_yaw_rad = s_camera_pitch_rad = 0.0f; s_camera_yaw_rad = s_camera_pitch_rad = 0.0f;
} }
bool query_mouse_aim_context() { bool queryMouseAimContext() {
return getSettings().game.enableMouseAim.getValue() && dCamera_c::isAimActive(); 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 want_mouse_capture() { bool wantMouseCapture() {
return getSettings().game.enableMouseCamera.getValue() || query_mouse_aim_context(); return getSettings().game.enableMouseCamera.getValue() || queryMouseAimContext();
} }
bool mouse_input_enabled() { bool isWindowFocused(SDL_Window* window) {
const auto& game = getSettings().game;
return game.enableMouseAim.getValue() || game.enableMouseCamera.getValue();
}
bool is_window_focused(SDL_Window* window) {
if (window == nullptr) { if (window == nullptr) {
return false; return false;
} }
return (SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) != 0; return (SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) != 0;
} }
bool imgui_windows_visible() { bool shouldCaptureMouse(SDL_Window* window) {
return ImGui::GetIO().MetricsRenderWindows > 0; if (window == nullptr || ui::any_document_visible()) {
}
bool should_capture_mouse(SDL_Window* window) {
if (window == nullptr || ui::any_document_visible() || imgui_windows_visible() ||
menu_pointer::active())
{
return false; return false;
} }
return want_mouse_capture() && is_window_focused(window); return wantMouseCapture() && isWindowFocused(window);
} }
bool sync_capture_state(SDL_Window* window, bool should_capture) { bool syncCaptureState(SDL_Window* window, bool should_capture) {
if (window == nullptr) { if (window == nullptr) {
reset_deltas(); reset_deltas();
return false; return false;
@@ -93,7 +86,7 @@ bool sync_capture_state(SDL_Window* window, bool should_capture) {
return is_captured; return is_captured;
} }
void accumulate_deltas(float mx_rel, float my_rel, bool camera_active, bool aim_active) { void accumulateDeltas(float mx_rel, float my_rel, bool camera_active, bool aim_active) {
const auto& game = getSettings().game; const auto& game = getSettings().game;
const bool mirror_mode = game.enableMirrorMode.getValue(); const bool mirror_mode = game.enableMirrorMode.getValue();
const bool invert_y = game.invertMouseY.getValue(); const bool invert_y = game.invertMouseY.getValue();
@@ -129,62 +122,57 @@ void set_cursor_visible(bool visible) {
} }
} }
bool cursor_idle() {
return Clock::now() - s_last_cursor_motion >= kCursorIdleDuration;
}
bool should_show_cursor(bool captured) {
if (captured) {
return false;
}
if (ui::any_document_visible()) {
return true;
}
if (imgui_windows_visible()) {
return true;
}
if (menu_pointer::enabled() && menu_pointer::active()) {
return true;
}
if (mouse_input_enabled()) {
return false;
}
return !cursor_idle();
}
void update_cursor_visibility(SDL_Window* window, bool captured) { void update_cursor_visibility(SDL_Window* window, bool captured) {
if (window == nullptr || !is_window_focused(window)) { if (window == nullptr || !isWindowFocused(window)) {
return; return;
} }
set_cursor_visible(should_show_cursor(captured)); 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 } // namespace
void read() { void read() {
SDL_Window* window = aurora::window::get_sdl_window(); SDL_Window* window = aurora::window::get_sdl_window();
const bool capture_active = sync_capture_state(window, should_capture_mouse(window)); const bool capture_active = syncCaptureState(window, shouldCaptureMouse(window));
update_cursor_visibility(window, capture_active); update_cursor_visibility(window, capture_active);
if (!capture_active) { if (!capture_active) {
return; return;
} }
const bool aim_active = capture_active && query_mouse_aim_context(); const bool aim_active = capture_active && queryMouseAimContext();
const bool camera_active = capture_active && getSettings().game.enableMouseCamera; const bool camera_active = capture_active && getSettings().game.enableMouseCamera;
float mx_rel = 0.0f; float mx_rel = 0.0f;
float my_rel = 0.0f; float my_rel = 0.0f;
SDL_GetRelativeMouseState(&mx_rel, &my_rel); SDL_GetRelativeMouseState(&mx_rel, &my_rel);
accumulate_deltas(mx_rel, my_rel, camera_active, aim_active); accumulateDeltas(mx_rel, my_rel, camera_active, aim_active);
} }
void get_aim_deltas(float& out_yaw, float& out_pitch) { void getAimDeltas(float& out_yaw, float& out_pitch) {
out_yaw = s_aim_yaw_rad; out_yaw = s_aim_yaw_rad;
out_pitch = s_aim_pitch_rad; out_pitch = s_aim_pitch_rad;
} }
void get_camera_deltas(float& out_yaw, float& out_pitch) { void getCameraDeltas(float& out_yaw, float& out_pitch) {
out_yaw = 0.0f; out_yaw = 0.0f;
out_pitch = 0.0f; out_pitch = 0.0f;
@@ -198,28 +186,26 @@ void get_camera_deltas(float& out_yaw, float& out_pitch) {
void handle_event(const SDL_Event& event) noexcept { void handle_event(const SDL_Event& event) noexcept {
switch (event.type) { switch (event.type) {
case SDL_EVENT_MOUSE_MOTION:
s_last_cursor_motion = Clock::now();
break;
case SDL_EVENT_WINDOW_FOCUS_LOST: case SDL_EVENT_WINDOW_FOCUS_LOST:
on_focus_lost(); onFocusLost();
break; break;
case SDL_EVENT_WINDOW_FOCUS_GAINED: case SDL_EVENT_WINDOW_FOCUS_GAINED:
on_focus_gained(); onFocusGained();
break; break;
} }
} }
void on_focus_lost() { void onFocusLost() {
SDL_Window* window = aurora::window::get_sdl_window(); SDL_Window* window = aurora::window::get_sdl_window();
if (window != nullptr) { if (window != nullptr) {
sync_capture_state(window, false); syncCaptureState(window, false);
} }
s_idle_frames = 0;
set_cursor_visible(true); set_cursor_visible(true);
} }
void on_focus_gained() { void onFocusGained() {
SDL_Window* window = aurora::window::get_sdl_window(); SDL_Window* window = aurora::window::get_sdl_window();
sync_capture_state(window, should_capture_mouse(window)); syncCaptureState(window, shouldCaptureMouse(window));
} }
} // namespace dusk::mouse } // namespace dusk::mouse
+2 -38
View File
@@ -11,9 +11,6 @@ UserSettings g_userSettings = {
.enableFpsOverlay {"game.enableFpsOverlay", false}, .enableFpsOverlay {"game.enableFpsOverlay", false},
.fpsOverlayCorner {"game.fpsOverlayCorner", 0}, .fpsOverlayCorner {"game.fpsOverlayCorner", 0},
.maxFrameRate {"video.maxFrameRate", 240}, .maxFrameRate {"video.maxFrameRate", 240},
.rememberWindowSize {"video.rememberWindowSize", false},
.lastWindowWidth {"video.lastWindowWidth", 0},
.lastWindowHeight {"video.lastWindowHeight", 0},
}, },
.audio = { .audio = {
@@ -95,10 +92,6 @@ UserSettings g_userSettings = {
.mouseCameraSensitivity {"game.mouseCameraSensitivity", 1.0f}, .mouseCameraSensitivity {"game.mouseCameraSensitivity", 1.0f},
.invertMouseY {"game.invertMouseY", false}, .invertMouseY {"game.invertMouseY", false},
.freeCamera {"game.freeCamera", false}, .freeCamera {"game.freeCamera", false},
.enableTouchControls {"game.enableTouchControls", false},
.touchTargeting {"game.touchTargeting", TouchTargeting::Hybrid},
.enableMenuPointer {"game.enableMenuPointer", true},
.touchControlsLayout {"game.touchControlsLayout", ui::ControlLayout{}},
.invertCameraXAxis {"game.invertCameraXAxis", false}, .invertCameraXAxis {"game.invertCameraXAxis", false},
.invertCameraYAxis {"game.invertCameraYAxis", false}, .invertCameraYAxis {"game.invertCameraYAxis", false},
.invertFirstPersonXAxis {"game.invertFirstPersonXAxis", false}, .invertFirstPersonXAxis {"game.invertFirstPersonXAxis", false},
@@ -107,8 +100,6 @@ UserSettings g_userSettings = {
.invertAirSwimY {"game.invertAirSwimY", false}, .invertAirSwimY {"game.invertAirSwimY", false},
.freeCameraXSensitivity {"game.freeCameraXSensitivity", 1.0f}, .freeCameraXSensitivity {"game.freeCameraXSensitivity", 1.0f},
.freeCameraYSensitivity {"game.freeCameraYSensitivity", 1.0f}, .freeCameraYSensitivity {"game.freeCameraYSensitivity", 1.0f},
.touchCameraXSensitivity {"game.touchCameraXSensitivity", 1.0f},
.touchCameraYSensitivity {"game.touchCameraYSensitivity", 1.0f},
.debugFlyCam {"game.debugFlyCam", false}, .debugFlyCam {"game.debugFlyCam", false},
.debugFlyCamLockEvents {"game.debugFlyCamLockEvents", true}, .debugFlyCamLockEvents {"game.debugFlyCamLockEvents", true},
.allowBackgroundInput {"game.allowBackgroundInput", true}, .allowBackgroundInput {"game.allowBackgroundInput", true},
@@ -161,6 +152,7 @@ UserSettings g_userSettings = {
.isoVerification {"backend.isoVerification", DiscVerificationState::Unknown}, .isoVerification {"backend.isoVerification", DiscVerificationState::Unknown},
.graphicsBackend {"backend.graphicsBackend", "auto"}, .graphicsBackend {"backend.graphicsBackend", "auto"},
.skipPreLaunchUI {"backend.skipPreLaunchUI", false}, .skipPreLaunchUI {"backend.skipPreLaunchUI", false},
.showPipelineCompilation {"backend.showPipelineCompilation", false},
.wasPresetChosen {"backend.wasPresetChosen", false}, .wasPresetChosen {"backend.wasPresetChosen", false},
.checkForUpdates {"backend.checkForUpdates", true}, .checkForUpdates {"backend.checkForUpdates", true},
.cardFileType {"backend.cardFileType", static_cast<int>(CARD_GCIFOLDER)}, .cardFileType {"backend.cardFileType", static_cast<int>(CARD_GCIFOLDER)},
@@ -181,18 +173,6 @@ UserSettings g_userSettings = {
ActionBindConfigVar{"actionBindings.callMidna_port2", PAD_NATIVE_BUTTON_INVALID}, ActionBindConfigVar{"actionBindings.callMidna_port2", PAD_NATIVE_BUTTON_INVALID},
ActionBindConfigVar{"actionBindings.callMidna_port3", PAD_NATIVE_BUTTON_INVALID}, ActionBindConfigVar{"actionBindings.callMidna_port3", PAD_NATIVE_BUTTON_INVALID},
}, },
.openMapScreen {
ActionBindConfigVar{"actionBindings.openMapScreen_port0", PAD_NATIVE_BUTTON_INVALID},
ActionBindConfigVar{"actionBindings.openMapScreen_port1", PAD_NATIVE_BUTTON_INVALID},
ActionBindConfigVar{"actionBindings.openMapScreen_port2", PAD_NATIVE_BUTTON_INVALID},
ActionBindConfigVar{"actionBindings.openMapScreen_port3", PAD_NATIVE_BUTTON_INVALID},
},
.toggleMinimap {
ActionBindConfigVar{"actionBindings.toggleMinimap_port0", PAD_NATIVE_BUTTON_INVALID},
ActionBindConfigVar{"actionBindings.toggleMinimap_port1", PAD_NATIVE_BUTTON_INVALID},
ActionBindConfigVar{"actionBindings.toggleMinimap_port2", PAD_NATIVE_BUTTON_INVALID},
ActionBindConfigVar{"actionBindings.toggleMinimap_port3", PAD_NATIVE_BUTTON_INVALID},
},
.openDusklightMenu { .openDusklightMenu {
ActionBindConfigVar{"actionBindings.openDusklightMenu_port0", PAD_NATIVE_BUTTON_INVALID}, ActionBindConfigVar{"actionBindings.openDusklightMenu_port0", PAD_NATIVE_BUTTON_INVALID},
ActionBindConfigVar{"actionBindings.openDusklightMenu_port1", PAD_NATIVE_BUTTON_INVALID}, ActionBindConfigVar{"actionBindings.openDusklightMenu_port1", PAD_NATIVE_BUTTON_INVALID},
@@ -220,9 +200,6 @@ void registerSettings() {
Register(g_userSettings.video.enableFpsOverlay); Register(g_userSettings.video.enableFpsOverlay);
Register(g_userSettings.video.fpsOverlayCorner); Register(g_userSettings.video.fpsOverlayCorner);
Register(g_userSettings.video.maxFrameRate); Register(g_userSettings.video.maxFrameRate);
Register(g_userSettings.video.rememberWindowSize);
Register(g_userSettings.video.lastWindowWidth);
Register(g_userSettings.video.lastWindowHeight);
// Audio // Audio
Register(g_userSettings.audio.masterVolume); Register(g_userSettings.audio.masterVolume);
@@ -263,8 +240,6 @@ void registerSettings() {
Register(g_userSettings.game.invertAirSwimY); Register(g_userSettings.game.invertAirSwimY);
Register(g_userSettings.game.freeCameraXSensitivity); Register(g_userSettings.game.freeCameraXSensitivity);
Register(g_userSettings.game.freeCameraYSensitivity); Register(g_userSettings.game.freeCameraYSensitivity);
Register(g_userSettings.game.touchCameraXSensitivity);
Register(g_userSettings.game.touchCameraYSensitivity);
Register(g_userSettings.game.minimalHUD); Register(g_userSettings.game.minimalHUD);
Register(g_userSettings.game.hudScale); Register(g_userSettings.game.hudScale);
Register(g_userSettings.game.pauseOnFocusLost); Register(g_userSettings.game.pauseOnFocusLost);
@@ -329,10 +304,6 @@ void registerSettings() {
Register(g_userSettings.game.mouseCameraSensitivity); Register(g_userSettings.game.mouseCameraSensitivity);
Register(g_userSettings.game.invertMouseY); Register(g_userSettings.game.invertMouseY);
Register(g_userSettings.game.freeCamera); Register(g_userSettings.game.freeCamera);
Register(g_userSettings.game.enableTouchControls);
Register(g_userSettings.game.touchTargeting);
Register(g_userSettings.game.enableMenuPointer);
Register(g_userSettings.game.touchControlsLayout);
Register(g_userSettings.game.debugFlyCam); Register(g_userSettings.game.debugFlyCam);
Register(g_userSettings.game.debugFlyCamLockEvents); Register(g_userSettings.game.debugFlyCamLockEvents);
Register(g_userSettings.game.allowBackgroundInput); Register(g_userSettings.game.allowBackgroundInput);
@@ -346,6 +317,7 @@ void registerSettings() {
Register(g_userSettings.backend.isoVerification); Register(g_userSettings.backend.isoVerification);
Register(g_userSettings.backend.graphicsBackend); Register(g_userSettings.backend.graphicsBackend);
Register(g_userSettings.backend.skipPreLaunchUI); Register(g_userSettings.backend.skipPreLaunchUI);
Register(g_userSettings.backend.showPipelineCompilation);
Register(g_userSettings.backend.wasPresetChosen); Register(g_userSettings.backend.wasPresetChosen);
Register(g_userSettings.backend.checkForUpdates); Register(g_userSettings.backend.checkForUpdates);
Register(g_userSettings.backend.cardFileType); Register(g_userSettings.backend.cardFileType);
@@ -359,14 +331,6 @@ void registerSettings() {
Register(g_userSettings.actionBindings.callMidna[1]); Register(g_userSettings.actionBindings.callMidna[1]);
Register(g_userSettings.actionBindings.callMidna[2]); Register(g_userSettings.actionBindings.callMidna[2]);
Register(g_userSettings.actionBindings.callMidna[3]); Register(g_userSettings.actionBindings.callMidna[3]);
Register(g_userSettings.actionBindings.openMapScreen[0]);
Register(g_userSettings.actionBindings.openMapScreen[1]);
Register(g_userSettings.actionBindings.openMapScreen[2]);
Register(g_userSettings.actionBindings.openMapScreen[3]);
Register(g_userSettings.actionBindings.toggleMinimap[0]);
Register(g_userSettings.actionBindings.toggleMinimap[1]);
Register(g_userSettings.actionBindings.toggleMinimap[2]);
Register(g_userSettings.actionBindings.toggleMinimap[3]);
Register(g_userSettings.actionBindings.openDusklightMenu[0]); Register(g_userSettings.actionBindings.openDusklightMenu[0]);
Register(g_userSettings.actionBindings.openDusklightMenu[1]); Register(g_userSettings.actionBindings.openDusklightMenu[1]);
Register(g_userSettings.actionBindings.openDusklightMenu[2]); Register(g_userSettings.actionBindings.openDusklightMenu[2]);
-29
View File
@@ -1,29 +0,0 @@
#include "dusk/touch_camera.h"
namespace dusk::touch_camera {
namespace {
float s_yaw_dp = 0.0f;
float s_pitch_dp = 0.0f;
} // namespace
void add_delta(float yaw_dp, float pitch_dp) noexcept {
if (getSettings().game.enableMirrorMode) {
yaw_dp *= -1.0;
}
s_yaw_dp += yaw_dp;
s_pitch_dp += pitch_dp;
}
bool consume_delta(float& yaw_dp, float& pitch_dp) noexcept {
yaw_dp = s_yaw_dp;
pitch_dp = s_pitch_dp;
clear();
return yaw_dp != 0.0f || pitch_dp != 0.0f;
}
void clear() noexcept {
s_yaw_dp = 0.0f;
s_pitch_dp = 0.0f;
}
} // namespace dusk::touch_camera
+2
View File
@@ -19,6 +19,8 @@ public:
void set_text(const Rml::String& text); void set_text(const Rml::String& text);
Button& on_pressed(ButtonCallback callback); Button& on_pressed(ButtonCallback callback);
const Rml::String& get_text() const { return mProps.text; }
private: private:
void update_props(Props props); void update_props(Props props);
-14
View File
@@ -861,20 +861,6 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
break; break;
} }
case Page::Rumble: { case Page::Rumble: {
if (PADCanForceDeviceRumble(static_cast<u32>(port))) {
pane.add_child<BoolButton>(BoolButton::Props{
.key = "Use Device Haptics",
.getValue = [port] { return PADGetForceDeviceRumble(static_cast<u32>(port)); },
.setValue =
[port](bool value) {
PADSetForceDeviceRumble(static_cast<u32>(port), value ? TRUE : FALSE);
PADSerializeMappings();
},
.isDisabled = [this] { return mRumbleTestActive; },
});
pane.add_text("Use native device haptics instead of controller rumble. "
"Useful for devices with built-in gamepads.");
}
auto& rumbleTest = pane.add_select_button({ auto& rumbleTest = pane.add_select_button({
.key = "Test Rumble", .key = "Test Rumble",
.getValue = .getValue =
-192
View File
@@ -1,192 +0,0 @@
#pragma once
#include <map>
namespace dusk::ui {
struct EquipTarget {
float left = 0.0f;
float top = 0.0f;
float width = 0.0f;
float height = 0.0f;
bool valid = false;
};
enum class Control {
A,
B,
X,
Y,
Z,
L,
R,
FIRST_PERSON,
ITEMS,
COLLECTIONS,
MAP,
SKIP,
DPAD_UP,
DPAD_DOWN,
DPAD_LEFT,
DPAD_RIGHT,
COUNT,
};
enum class ControlAnchor : u8 {
None,
Top,
Left,
Bottom,
Right,
TopLeft,
TopRight,
BottomLeft,
BottomRight,
};
struct ControlProps {
float x = 0.0f;
float y = 0.0f;
float w = 0.0f;
float h = 0.0f;
float scale = 1.0f;
ControlAnchor anchor = ControlAnchor::None;
};
struct ControlRect {
float l = 0.0f;
float t = 0.0f;
float w = 0.0f;
float h = 0.0f;
};
struct ResolvedControlLayout {
ControlRect visual;
ControlRect box;
float scale = 1.0f;
};
struct ControlLayoutSize {
float w = 0.0f;
float h = 0.0f;
};
struct ControlLayout {
static constexpr int Version = 1;
int version = Version;
std::map<std::string, ControlProps, std::less<> > controls;
};
constexpr std::array<std::string_view, 9> kControlLayoutIds = {
"actionBar",
"buttonA",
"buttonB",
"buttonX",
"buttonY",
"buttonZ",
"skip",
"triggerL",
"triggerR",
};
constexpr bool is_control_layout_id(std::string_view id) noexcept {
for (const auto knownId : kControlLayoutIds) {
if (id == knownId) {
return true;
}
}
return false;
}
constexpr ControlRect resolve_anchored_rect(
ControlAnchor anchor, float x, float y, float w, float h, ControlLayoutSize docSize) noexcept {
switch (anchor) {
case ControlAnchor::None:
return {x * docSize.w - w * 0.5f, y * docSize.h - h * 0.5f, w, h};
case ControlAnchor::Top:
return {x * docSize.w - w * 0.5f, y, w, h};
case ControlAnchor::Bottom:
return {x * docSize.w - w * 0.5f, docSize.h - y - h, w, h};
case ControlAnchor::Left:
return {x, y * docSize.h - h * 0.5f, w, h};
case ControlAnchor::Right:
return {docSize.w - x - w, y * docSize.h - h * 0.5f, w, h};
case ControlAnchor::TopLeft:
return {x, y, w, h};
case ControlAnchor::TopRight:
return {docSize.w - x - w, y, w, h};
case ControlAnchor::BottomLeft:
return {x, docSize.h - y - h, w, h};
case ControlAnchor::BottomRight:
return {docSize.w - x - w, docSize.h - y - h, w, h};
}
return {};
}
constexpr ResolvedControlLayout resolve_control_layout(
ControlProps props, ControlLayoutSize docSize) noexcept {
const float visualW = props.w * props.scale;
const float visualH = props.h * props.scale;
const ControlRect visual =
resolve_anchored_rect(props.anchor, props.x, props.y, visualW, visualH, docSize);
const ControlRect box = {
visual.l + (visual.w - props.w) * 0.5f,
visual.t + (visual.h - props.h) * 0.5f,
props.w,
props.h,
};
return {
.visual = visual,
.box = box,
.scale = props.scale,
};
}
constexpr ControlProps encode_control_props(ControlRect visual, ControlLayoutSize docSize,
ControlProps props, ControlAnchor anchor) noexcept {
props.anchor = anchor;
switch (anchor) {
case ControlAnchor::None:
props.x = (visual.l + visual.w * 0.5f) / docSize.w;
props.y = (visual.t + visual.h * 0.5f) / docSize.h;
break;
case ControlAnchor::Top:
props.x = (visual.l + visual.w * 0.5f) / docSize.w;
props.y = visual.t;
break;
case ControlAnchor::Bottom:
props.x = (visual.l + visual.w * 0.5f) / docSize.w;
props.y = docSize.h - visual.t - visual.h;
break;
case ControlAnchor::Left:
props.x = visual.l;
props.y = (visual.t + visual.h * 0.5f) / docSize.h;
break;
case ControlAnchor::Right:
props.x = docSize.w - visual.l - visual.w;
props.y = (visual.t + visual.h * 0.5f) / docSize.h;
break;
case ControlAnchor::TopLeft:
props.x = visual.l;
props.y = visual.t;
break;
case ControlAnchor::TopRight:
props.x = docSize.w - visual.l - visual.w;
props.y = visual.t;
break;
case ControlAnchor::BottomLeft:
props.x = visual.l;
props.y = docSize.h - visual.t - visual.h;
break;
case ControlAnchor::BottomRight:
props.x = docSize.w - visual.l - visual.w;
props.y = docSize.h - visual.t - visual.h;
break;
}
return props;
}
} // namespace dusk::ui
+11 -44
View File
@@ -3,6 +3,7 @@
#include "aurora/rmlui.hpp" #include "aurora/rmlui.hpp"
#include "ui.hpp" #include "ui.hpp"
#include "Z2AudioLib/Z2SeMgr.h"
#include "m_Do/m_Do_audio.h" #include "m_Do/m_Do_audio.h"
namespace dusk::ui { namespace dusk::ui {
@@ -18,39 +19,32 @@ Rml::ElementDocument* load_document(const Rml::String& source) {
} // namespace } // namespace
Document::Document(const Rml::String& source, bool passive) Document::Document(const Rml::String& source) : mDocument(load_document(source)) {
: mDocument(load_document(source)), mPassive(passive) {
// Block events while hidden (except for Menu command); play nav sounds when visible // Block events while hidden (except for Menu command); play nav sounds when visible
listen( listen(
Rml::EventId::Keydown, Rml::EventId::Keydown,
[this](Rml::Event& event) { [this](Rml::Event& event) {
if (mPassive) {
return;
}
const auto cmd = map_nav_event(event); const auto cmd = map_nav_event(event);
if (cmd != NavCommand::Menu && (!visible() || !active())) { if (cmd != NavCommand::Menu && !visible()) {
event.StopImmediatePropagation(); event.StopImmediatePropagation();
} }
}, },
true); true);
const auto blockUnlessActive = [this](Rml::Event& event) { const auto blockUnlessVisible = [this](Rml::Event& event) {
if (!visible() || !active()) { if (!visible()) {
event.StopImmediatePropagation(); event.StopImmediatePropagation();
} }
}; };
listen(Rml::EventId::Mouseover, blockUnlessActive, true); listen(Rml::EventId::Mouseover, blockUnlessVisible, true);
listen(Rml::EventId::Click, blockUnlessActive, true); listen(Rml::EventId::Click, blockUnlessVisible, true);
listen(Rml::EventId::Scroll, blockUnlessActive, true); listen(Rml::EventId::Scroll, blockUnlessVisible, true);
listen(Rml::EventId::Keydown, [this](Rml::Event& event) { listen(Rml::EventId::Keydown, [this](Rml::Event& event) {
if (mPassive) { const auto cmd = map_nav_event(event);
auto* doc = top_document(); if (cmd == NavCommand::None) {
if (doc != nullptr && doc->handle_nav_event(event)) {
event.StopPropagation();
}
return; return;
} }
if (handle_nav_event(event)) { if (handle_nav_command(event, cmd)) {
event.StopPropagation(); event.StopPropagation();
} }
}); });
@@ -103,18 +97,6 @@ void Document::listen(Rml::Element* element, Rml::EventId event,
std::make_unique<ScopedEventListener>(element, event, std::move(callback), capture)); std::make_unique<ScopedEventListener>(element, event, std::move(callback), capture));
} }
void Document::listen(Rml::Element* element, const Rml::String& event,
ScopedEventListener::Callback callback, bool capture) {
if (element == nullptr) {
element = mDocument;
}
if (element == nullptr || event.empty() || !callback) {
return;
}
mListeners.emplace_back(
std::make_unique<ScopedEventListener>(element, event, std::move(callback), capture));
}
bool Document::visible() const { bool Document::visible() const {
if (mDocument == nullptr) { if (mDocument == nullptr) {
return false; return false;
@@ -122,21 +104,6 @@ bool Document::visible() const {
return *mDocument->GetProperty(Rml::PropertyId::Visibility) == Rml::Style::Visibility::Visible; return *mDocument->GetProperty(Rml::PropertyId::Visibility) == Rml::Style::Visibility::Visible;
} }
bool Document::active() const {
return !mClosed && !mPendingClose;
}
bool Document::handle_nav_event(Rml::Event& event) {
if (!active()) {
return false;
}
const auto cmd = map_nav_event(event);
if (cmd == NavCommand::None || (cmd != NavCommand::Menu && !visible())) {
return false;
}
return handle_nav_command(event, cmd);
}
bool Document::handle_nav_command(Rml::Event& event, NavCommand cmd) { bool Document::handle_nav_command(Rml::Event& event, NavCommand cmd) {
if (cmd == NavCommand::Menu) { if (cmd == NavCommand::Menu) {
mDoAud_seStartMenu(visible() ? kSoundMenuClose : kSoundMenuOpen); mDoAud_seStartMenu(visible() ? kSoundMenuClose : kSoundMenuOpen);
+4 -13
View File
@@ -7,7 +7,7 @@ namespace dusk::ui {
class Document { class Document {
public: public:
explicit Document(const Rml::String& source, bool passive = false); Document(const Rml::String& source);
virtual ~Document(); virtual ~Document();
Document(const Document&) = delete; Document(const Document&) = delete;
@@ -18,19 +18,12 @@ public:
virtual void update(); virtual void update();
virtual bool focus(); virtual bool focus();
virtual bool visible() const; virtual bool visible() const;
virtual bool active() const;
void listen(Rml::Element* element, Rml::EventId event, ScopedEventListener::Callback callback, void listen(Rml::Element* element, Rml::EventId event, ScopedEventListener::Callback callback,
bool capture = false); bool capture = false);
void listen(Rml::Element* element, const Rml::String& event,
ScopedEventListener::Callback callback, bool capture = false);
void listen(Rml::EventId event, ScopedEventListener::Callback callback, bool capture = false) { void listen(Rml::EventId event, ScopedEventListener::Callback callback, bool capture = false) {
listen(mDocument, event, std::move(callback), capture); listen(mDocument, event, std::move(callback), capture);
} }
void listen(
const Rml::String& event, ScopedEventListener::Callback callback, bool capture = false) {
listen(mDocument, event, std::move(callback), capture);
}
void toggle() { void toggle() {
if (visible()) { if (visible()) {
hide(false); hide(false);
@@ -42,15 +35,14 @@ public:
push_document(std::move(document)); push_document(std::move(document));
hide(false); hide(false);
} }
void pop(bool show = true) { void pop() {
hide(true); hide(true);
focus_top_document(show); show_top_document();
} }
bool pending_close() const { return mPendingClose; }
bool closed() const { return mClosed; } bool closed() const { return mClosed; }
bool handle_nav_event(Rml::Event& event);
protected: protected:
virtual bool handle_nav_command(Rml::Event& event, NavCommand cmd); virtual bool handle_nav_command(Rml::Event& event, NavCommand cmd);
@@ -58,7 +50,6 @@ protected:
std::vector<std::unique_ptr<ScopedEventListener> > mListeners; std::vector<std::unique_ptr<ScopedEventListener> > mListeners;
bool mPendingClose = false; bool mPendingClose = false;
bool mClosed = false; bool mClosed = false;
bool mPassive = false;
}; };
} // namespace dusk::ui } // namespace dusk::ui
-899
View File
@@ -1,899 +0,0 @@
#include "icon_provider.hpp"
#include "d/dolzel.h" // IWYU pragma: keep
#ifdef AURORA_ENABLE_RMLUI
#include <SDL3/SDL_surface.h>
#include <aurora/lib/gfx/texture_convert.hpp>
#include <aurora/rmlui.hpp>
#include <fmt/format.h>
#include <algorithm>
#include <array>
#include <charconv>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <limits>
#include <memory>
#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>
#include "JSystem/J2DGraph/J2DPicture.h"
#include "JSystem/JUtility/JUTTexture.h"
#include "d/actor/d_a_alink.h"
#include "d/d_com_inf_game.h"
#include "d/d_item_data.h"
#include "d/d_meter2_info.h"
#include "d/d_pane_class.h"
namespace dusk::ui {
namespace {
constexpr std::string_view kScheme = "item";
constexpr std::string_view kSourcePrefix = "item://";
constexpr std::string_view kMeterScheme = "meter";
constexpr std::string_view kMeterSourcePrefix = "meter://";
constexpr size_t kItemTextureBufferSize = 0xC00;
constexpr size_t kMaxCachedIcons = 128;
constexpr uint64_t kMeterTextureSourceSlots = 8;
constexpr uint32_t kMinRenderedPaneIconSize = 128;
constexpr uint32_t kMaxRenderedPaneIconSize = 1024;
struct alignas(32) ItemTextureBuffer {
std::array<std::byte, kItemTextureBufferSize> bytes{};
std::byte* data() noexcept { return bytes.data(); }
const std::byte* data() const noexcept { return bytes.data(); }
};
struct CachedIcon {
std::vector<uint8_t> pixels;
uint32_t width = 0;
uint32_t height = 0;
};
struct RuntimeIconState {
CachedIcon icon;
uint64_t revision = 0;
bool valid = false;
};
struct LayerColors {
JUtility::TColor black;
JUtility::TColor white;
std::array<JUtility::TColor, 4> corner;
};
struct RectF {
float left = std::numeric_limits<float>::max();
float top = std::numeric_limits<float>::max();
float right = std::numeric_limits<float>::lowest();
float bottom = std::numeric_limits<float>::lowest();
bool valid() const noexcept { return left < right && top < bottom; }
float width() const noexcept { return right - left; }
float height() const noexcept { return bottom - top; }
void include(float x, float y) noexcept {
if (!std::isfinite(x) || !std::isfinite(y)) {
return;
}
left = std::min(left, x);
top = std::min(top, y);
right = std::max(right, x);
bottom = std::max(bottom, y);
}
void include(const RectF& rect) noexcept {
if (!rect.valid()) {
return;
}
include(rect.left, rect.top);
include(rect.right, rect.bottom);
}
};
struct PictureLayer {
J2DPicture* picture = nullptr;
RectF rect;
uint8_t alpha = 0;
};
struct SurfaceDeleter {
void operator()(SDL_Surface* surface) const noexcept { SDL_DestroySurface(surface); }
};
using SurfacePtr = std::unique_ptr<SDL_Surface, SurfaceDeleter>;
std::unordered_map<std::string, CachedIcon>& icon_cache() {
static auto* cache = new std::unordered_map<std::string, CachedIcon>();
return *cache;
}
RuntimeIconState& midna_icon_state() {
static auto* state = new RuntimeIconState();
return *state;
}
std::string_view strip_query(std::string_view path) noexcept {
const auto queryPos = path.find_first_of("?#");
if (queryPos != std::string_view::npos) {
path = path.substr(0, queryPos);
}
return path;
}
std::optional<u8> parse_item_no(std::string_view text) noexcept {
if (text.starts_with("0x") || text.starts_with("0X")) {
text.remove_prefix(2);
}
unsigned value = 0;
const auto* first = text.data();
const auto* last = text.data() + text.size();
const auto [ptr, ec] = std::from_chars(first, last, value, 16);
if (ec != std::errc() || ptr != last || value > 0xFF) {
return std::nullopt;
}
return static_cast<u8>(value);
}
bool is_valid_icon_item(u8 itemNo) noexcept {
return itemNo != 0 && itemNo != dItemNo_NONE_e;
}
u8 item_icon_texture_item(u8 itemNo) noexcept {
if (itemNo == dItemNo_LIGHT_ARROW_e) {
return dItemNo_BOW_e;
}
return itemNo;
}
std::optional<u8> selected_slot_item(int slot) noexcept {
const u8 itemNo = dComIfGp_getSelectItem(slot);
if (!is_valid_icon_item(itemNo)) {
return std::nullopt;
}
return item_icon_texture_item(itemNo);
}
bool is_sword_item(u8 itemNo) noexcept {
switch (itemNo) {
case dItemNo_WOOD_STICK_e:
case dItemNo_SWORD_e:
case dItemNo_MASTER_SWORD_e:
case dItemNo_LIGHT_SWORD_e:
return true;
default:
return false;
}
}
std::optional<u8> b_button_item() noexcept {
const u8 action = dComIfGp_getAStatus();
if (action == 0x26 || action == 0x2E) {
const u8 sword = dComIfGs_getSelectEquipSword();
if (is_sword_item(sword)) {
return sword;
}
return std::nullopt;
}
if (action == 0x4F) {
return dItemNo_LURE_ROD_e;
}
return std::nullopt;
}
std::optional<u8> item_for_source(std::string_view source) noexcept {
if (!source.starts_with(kSourcePrefix)) {
return std::nullopt;
}
std::string_view path = strip_query(source.substr(kSourcePrefix.size()));
if (path.starts_with("item/")) {
path.remove_prefix(5);
const auto itemNo = parse_item_no(path);
if (itemNo && is_valid_icon_item(*itemNo)) {
return item_icon_texture_item(*itemNo);
}
return std::nullopt;
}
if (path == "slot/x") {
return selected_slot_item(0);
}
if (path == "slot/y") {
return selected_slot_item(1);
}
if (path == "button/b") {
return b_button_item();
}
return std::nullopt;
}
uint32_t item_revision(u8 itemNo) noexcept {
uint32_t revision = itemNo;
revision = revision * 131u + g_meter2_info.getItemType(itemNo);
if (itemNo == dItemNo_KANTERA_e || itemNo == dItemNo_KANTERA2_e) {
revision = revision * 131u + (dComIfGs_getOil() == 0 ? 0u : 1u);
}
if (itemNo == dItemNo_COPY_ROD_e) {
auto* player = daPy_getPlayerActorClass();
revision = revision * 131u + (player != nullptr && player->checkCopyRodTopUse() ? 1u : 0u);
}
return revision;
}
std::string item_source_for_item(u8 itemNo) {
itemNo = item_icon_texture_item(itemNo);
return fmt::format("{}://item/{:02x}?rev={:08x}", kScheme, itemNo, item_revision(itemNo));
}
std::optional<int> selected_slot_count(int slot) noexcept {
const u8 itemNo = dComIfGp_getSelectItem(slot);
if (!is_valid_icon_item(itemNo)) {
return std::nullopt;
}
if (item_icon_texture_item(itemNo) == dItemNo_KANTERA_e ||
item_icon_texture_item(itemNo) == dItemNo_KANTERA2_e)
{
return std::nullopt;
}
int count = 0;
int max = 0;
switch (itemNo) {
case dItemNo_BOW_e:
case dItemNo_LIGHT_ARROW_e:
case dItemNo_ARROW_LV1_e:
case dItemNo_ARROW_LV2_e:
case dItemNo_ARROW_LV3_e:
case dItemNo_HAWK_ARROW_e:
count = dComIfGs_getArrowNum();
max = dComIfGs_getArrowMax();
break;
case dItemNo_BOMB_ARROW_e:
count = std::min<int>(dComIfGp_getSelectItemNum(slot), dComIfGs_getArrowNum());
max = std::max<int>(dComIfGp_getSelectItemMaxNum(slot), dComIfGs_getArrowMax());
break;
default:
count = dComIfGp_getSelectItemNum(slot);
max = dComIfGp_getSelectItemMaxNum(slot);
break;
}
if (max <= 0) {
return std::nullopt;
}
return std::clamp(count, 0, max);
}
aurora::gfx::ConvertedTexture decode_timg(const ResTIMG* image) {
if (image == nullptr || image->width.host() == 0 || image->height.host() == 0) {
return {};
}
const auto* base = reinterpret_cast<const uint8_t*>(image);
const auto width = image->width.host();
const auto height = image->height.host();
const uint32_t textureSize = GXGetTexBufferSize(width, height, image->format, GX_FALSE, 0);
const auto* textureData = base + static_cast<int32_t>(image->imageOffset);
if (image->indexTexture != 0) {
const auto* paletteData = base + static_cast<int32_t>(image->paletteOffset);
return aurora::gfx::convert_texture_palette(image->format, width, height, 1,
aurora::ArrayRef{textureData, textureSize}, static_cast<GXTlutFmt>(image->colorFormat),
image->numColors,
aurora::ArrayRef{paletteData, static_cast<size_t>(image->numColors) * 2});
}
return aurora::gfx::convert_texture(
image->format, width, height, 1, aurora::ArrayRef{textureData, textureSize});
}
uint8_t lerp_u8(uint8_t a, uint8_t b, uint32_t t) noexcept {
return static_cast<uint8_t>(
(static_cast<uint32_t>(a) * (255u - t) + static_cast<uint32_t>(b) * t) / 255u);
}
JUtility::TColor lerp_color(
const JUtility::TColor& a, const JUtility::TColor& b, uint32_t t) noexcept {
return {
lerp_u8(a.r, b.r, t),
lerp_u8(a.g, b.g, t),
lerp_u8(a.b, b.b, t),
lerp_u8(a.a, b.a, t),
};
}
JUtility::TColor bilerp_corner(
const LayerColors& colors, uint32_t x, uint32_t y, uint32_t width, uint32_t height) noexcept {
const uint32_t u = width > 1 ? (x * 255u) / (width - 1u) : 0u;
const uint32_t v = height > 1 ? (y * 255u) / (height - 1u) : 0u;
const JUtility::TColor top = lerp_color(colors.corner[0], colors.corner[1], u);
const JUtility::TColor bottom = lerp_color(colors.corner[2], colors.corner[3], u);
return lerp_color(top, bottom, v);
}
std::array<uint8_t, 4> apply_layer_colors(std::span<const uint8_t, 4> src,
const LayerColors& colors, uint32_t x, uint32_t y, uint32_t width, uint32_t height) noexcept {
std::array out{
lerp_u8(colors.black.r, colors.white.r, src[0]),
lerp_u8(colors.black.g, colors.white.g, src[1]),
lerp_u8(colors.black.b, colors.white.b, src[2]),
src[3],
};
const auto corner = bilerp_corner(colors, x, y, width, height);
out[0] = static_cast<uint8_t>((static_cast<uint32_t>(out[0]) * corner.r) / 255u);
out[1] = static_cast<uint8_t>((static_cast<uint32_t>(out[1]) * corner.g) / 255u);
out[2] = static_cast<uint8_t>((static_cast<uint32_t>(out[2]) * corner.b) / 255u);
out[3] = static_cast<uint8_t>((static_cast<uint32_t>(out[3]) * corner.a) / 255u);
return out;
}
void blend_premultiplied(uint8_t* dst, const std::array<uint8_t, 4>& src) noexcept {
const uint32_t srcAlpha = src[3];
const uint32_t invAlpha = 255u - srcAlpha;
const uint32_t srcR = (static_cast<uint32_t>(src[0]) * srcAlpha) / 255u;
const uint32_t srcG = (static_cast<uint32_t>(src[1]) * srcAlpha) / 255u;
const uint32_t srcB = (static_cast<uint32_t>(src[2]) * srcAlpha) / 255u;
dst[0] = static_cast<uint8_t>(
std::min(255u, srcR + (static_cast<uint32_t>(dst[0]) * invAlpha) / 255u));
dst[1] = static_cast<uint8_t>(
std::min(255u, srcG + (static_cast<uint32_t>(dst[1]) * invAlpha) / 255u));
dst[2] = static_cast<uint8_t>(
std::min(255u, srcB + (static_cast<uint32_t>(dst[2]) * invAlpha) / 255u));
dst[3] = static_cast<uint8_t>(
std::min(255u, srcAlpha + (static_cast<uint32_t>(dst[3]) * invAlpha) / 255u));
}
LayerColors layer_colors(const J2DPicture& picture) noexcept {
return {
.black = picture.getBlack(),
.white = picture.getWhite(),
.corner = {picture.corner(0), picture.corner(1), picture.corner(2), picture.corner(3)},
};
}
LayerColors layer_colors(J2DPicture& picture, uint8_t alpha) noexcept {
std::array<JUtility::TColor, 4> corners{};
picture.getNewColor(corners.data());
for (auto& corner : corners) {
corner.a = static_cast<uint8_t>((static_cast<uint32_t>(corner.a) * alpha) / 255u);
}
return {
.black = picture.getBlack(),
.white = picture.getWhite(),
.corner = corners,
};
}
std::optional<CachedIcon> render_item_icon(u8 itemNo) {
std::array<ItemTextureBuffer, 4> buffers{};
std::array<J2DPicture, 4> pictures{};
const int textureCount =
dMeter2Info_readItemTexture(itemNo, buffers[0].data(), &pictures[0], buffers[1].data(),
&pictures[1], buffers[2].data(), &pictures[2], buffers[3].data(), &pictures[3], -1);
if (textureCount <= 0) {
return std::nullopt;
}
std::array<aurora::gfx::ConvertedTexture, 4> decodedLayers{};
std::array<LayerColors, 4> colors{};
int decodedCount = 0;
for (int i = 0; i < textureCount && i < static_cast<int>(decodedLayers.size()); ++i) {
auto decoded = decode_timg(reinterpret_cast<const ResTIMG*>(buffers[i].data()));
if (decoded.data.empty()) {
continue;
}
colors[decodedCount] = layer_colors(pictures[i]);
decodedLayers[decodedCount] = std::move(decoded);
++decodedCount;
}
if (decodedCount == 0) {
return std::nullopt;
}
CachedIcon icon{
.width = decodedLayers[0].width,
.height = decodedLayers[0].height,
};
icon.pixels.assign(static_cast<size_t>(icon.width) * static_cast<size_t>(icon.height) * 4, 0);
for (int layer = 0; layer < decodedCount; ++layer) {
const auto& decoded = decodedLayers[layer];
for (uint32_t y = 0; y < icon.height; ++y) {
const uint32_t sourceY = decoded.height > 0 ? (y * decoded.height) / icon.height : 0;
for (uint32_t x = 0; x < icon.width; ++x) {
const uint32_t sourceX = decoded.width > 0 ? (x * decoded.width) / icon.width : 0;
const size_t sourceOffset =
(static_cast<size_t>(sourceY) * decoded.width + static_cast<size_t>(sourceX)) *
4;
if (sourceOffset + 3 >= decoded.data.size()) {
continue;
}
const std::span<const uint8_t, 4> sourcePixel(
decoded.data.data() + sourceOffset, 4);
const auto pixel =
apply_layer_colors(sourcePixel, colors[layer], x, y, icon.width, icon.height);
uint8_t* destination =
icon.pixels.data() +
(static_cast<size_t>(y) * icon.width + static_cast<size_t>(x)) * 4;
blend_premultiplied(destination, pixel);
}
}
}
return icon;
}
SurfacePtr create_rgba_surface(uint32_t width, uint32_t height) {
if (width == 0 || height == 0 ||
width > static_cast<uint32_t>(std::numeric_limits<int>::max()) ||
height > static_cast<uint32_t>(std::numeric_limits<int>::max()))
{
return {};
}
return SurfacePtr{SDL_CreateSurface(
static_cast<int>(width), static_cast<int>(height), SDL_PIXELFORMAT_RGBA32)};
}
bool lock_surface(SDL_Surface* surface) noexcept {
return surface != nullptr && (!SDL_MUSTLOCK(surface) || SDL_LockSurface(surface));
}
void unlock_surface(SDL_Surface* surface) noexcept {
if (surface != nullptr && SDL_MUSTLOCK(surface)) {
SDL_UnlockSurface(surface);
}
}
SurfacePtr create_layer_surface(
const aurora::gfx::ConvertedTexture& decoded, const LayerColors& colors) {
if (decoded.width == 0 || decoded.height == 0 || decoded.data.empty()) {
return {};
}
auto surface = create_rgba_surface(decoded.width, decoded.height);
if (!surface || !lock_surface(surface.get())) {
return {};
}
for (uint32_t y = 0; y < decoded.height; ++y) {
auto* destination = static_cast<uint8_t*>(surface->pixels) +
static_cast<size_t>(y) * static_cast<size_t>(surface->pitch);
for (uint32_t x = 0; x < decoded.width; ++x) {
const size_t sourceOffset =
(static_cast<size_t>(y) * decoded.width + static_cast<size_t>(x)) * 4;
if (sourceOffset + 3 >= decoded.data.size()) {
continue;
}
const std::span<const uint8_t, 4> sourcePixel(decoded.data.data() + sourceOffset, 4);
const auto pixel =
apply_layer_colors(sourcePixel, colors, x, y, decoded.width, decoded.height);
std::memcpy(destination + static_cast<size_t>(x) * 4, pixel.data(), pixel.size());
}
}
unlock_surface(surface.get());
SDL_SetSurfaceBlendMode(surface.get(), SDL_BLENDMODE_BLEND);
return surface;
}
std::optional<CachedIcon> icon_from_surface(SDL_Surface* surface) {
if (surface == nullptr || surface->w <= 0 || surface->h <= 0) {
return std::nullopt;
}
CachedIcon icon{
.width = static_cast<uint32_t>(surface->w),
.height = static_cast<uint32_t>(surface->h),
};
const size_t rowSize = static_cast<size_t>(icon.width) * 4u;
icon.pixels.resize(rowSize * static_cast<size_t>(icon.height));
if (!lock_surface(surface)) {
return std::nullopt;
}
for (uint32_t y = 0; y < icon.height; ++y) {
const auto* source = static_cast<const uint8_t*>(surface->pixels) +
static_cast<size_t>(y) * static_cast<size_t>(surface->pitch);
auto* destination = icon.pixels.data() + static_cast<size_t>(y) * rowSize;
std::memcpy(destination, source, rowSize);
}
unlock_surface(surface);
return icon;
}
RectF pane_global_rect(J2DPane* pane) noexcept {
RectF rect;
CPaneMgr paneMgr;
Mtx m;
for (u8 i = 0; i < 4; ++i) {
const Vec vertex = paneMgr.getGlobalVtx(pane, &m, i, false, 0);
rect.include(vertex.x, vertex.y);
}
return rect;
}
uint8_t effective_pane_alpha(J2DPane& pane, uint8_t parentAlpha) noexcept {
uint32_t alpha = pane.getAlpha();
if (pane.isInfluencedAlpha()) {
alpha = alpha * parentAlpha / 255u;
}
return static_cast<uint8_t>(alpha);
}
void collect_picture_layers(
J2DPane* pane, std::vector<PictureLayer>& layers, uint8_t parentAlpha = 255) noexcept {
if (pane == nullptr || !pane->isVisible()) {
return;
}
const uint8_t paneAlpha = effective_pane_alpha(*pane, parentAlpha);
if (paneAlpha == 0) {
return;
}
if (pane->getKind() == MULTI_CHAR('PIC1') || pane->getKind() == MULTI_CHAR('PIC2')) {
auto* picture = static_cast<J2DPicture*>(pane);
if (picture->getTexture(0) != nullptr) {
RectF rect = pane_global_rect(pane);
if (rect.valid()) {
layers.push_back({
.picture = picture,
.rect = rect,
.alpha = paneAlpha,
});
}
}
}
for (J2DPane* child = pane->getFirstChildPane(); child != nullptr;
child = child->getNextChildPane())
{
collect_picture_layers(child, layers, paneAlpha);
}
}
std::optional<uint32_t> icon_dimension(float value) noexcept {
if (!std::isfinite(value) || value <= 0.0f) {
return std::nullopt;
}
const auto dimension = static_cast<uint32_t>(std::ceil(value));
if (dimension == 0 || dimension > kMaxRenderedPaneIconSize) {
return std::nullopt;
}
return dimension;
}
float pane_icon_render_scale(const std::vector<PictureLayer>& layers, const RectF& canvas) {
float scale = 1.0f;
for (const auto& layer : layers) {
if (layer.picture == nullptr || !layer.rect.valid() || layer.rect.width() <= 0.0f ||
layer.rect.height() <= 0.0f)
{
continue;
}
auto* texture = layer.picture->getTexture(0);
const ResTIMG* image = texture != nullptr ? texture->getTexInfo() : nullptr;
if (image == nullptr || image->width.host() == 0 || image->height.host() == 0) {
continue;
}
scale = std::max(scale, static_cast<float>(image->width) / layer.rect.width());
scale = std::max(scale, static_cast<float>(image->height) / layer.rect.height());
}
const float canvasMax = std::max(canvas.width(), canvas.height());
if (canvasMax <= 0.0f) {
return scale;
}
const float minScale = static_cast<float>(kMinRenderedPaneIconSize) / canvasMax;
const float maxScale = static_cast<float>(kMaxRenderedPaneIconSize) / canvasMax;
return std::clamp(std::max(scale, minScale), 1.0f, maxScale);
}
void composite_picture_layer(
SDL_Surface& icon, const RectF& canvas, const PictureLayer& layer, float renderScale) {
if (layer.picture == nullptr || !layer.rect.valid()) {
return;
}
auto* texture = layer.picture->getTexture(0);
if (texture == nullptr) {
return;
}
auto decoded = decode_timg(texture->getTexInfo());
if (decoded.data.empty() || decoded.width == 0 || decoded.height == 0) {
return;
}
const auto colors = layer_colors(*layer.picture, layer.alpha);
auto layerSurface = create_layer_surface(decoded, colors);
if (!layerSurface) {
return;
}
const float dstLeft = (layer.rect.left - canvas.left) * renderScale;
const float dstTop = (layer.rect.top - canvas.top) * renderScale;
const float dstRight = (layer.rect.right - canvas.left) * renderScale;
const float dstBottom = (layer.rect.bottom - canvas.top) * renderScale;
const float dstWidth = dstRight - dstLeft;
const float dstHeight = dstBottom - dstTop;
if (dstWidth <= 0.0f || dstHeight <= 0.0f) {
return;
}
const int x0 = std::clamp(static_cast<int>(std::floor(dstLeft)), 0, icon.w);
const int y0 = std::clamp(static_cast<int>(std::floor(dstTop)), 0, icon.h);
const int x1 = std::clamp(static_cast<int>(std::ceil(dstRight)), 0, icon.w);
const int y1 = std::clamp(static_cast<int>(std::ceil(dstBottom)), 0, icon.h);
if (x0 >= x1 || y0 >= y1) {
return;
}
SDL_Rect destinationRect{
.x = x0,
.y = y0,
.w = x1 - x0,
.h = y1 - y0,
};
SDL_BlitSurfaceScaled(
layerSurface.get(), nullptr, &icon, &destinationRect, SDL_SCALEMODE_LINEAR);
}
std::optional<CachedIcon> render_j2d_pane_icon(J2DPane* pane) {
std::vector<PictureLayer> layers;
collect_picture_layers(pane, layers);
if (layers.empty()) {
return std::nullopt;
}
RectF canvas;
for (const auto& layer : layers) {
canvas.include(layer.rect);
}
if (!canvas.valid()) {
return std::nullopt;
}
const float renderScale = pane_icon_render_scale(layers, canvas);
auto width = icon_dimension(canvas.width() * renderScale);
auto height = icon_dimension(canvas.height() * renderScale);
if (!width || !height) {
return std::nullopt;
}
auto surface = create_rgba_surface(*width, *height);
if (!surface) {
return std::nullopt;
}
for (const auto& layer : layers) {
composite_picture_layer(*surface, canvas, layer, renderScale);
}
return icon_from_surface(surface.get());
}
std::optional<aurora::rmlui::RuntimeTexture> icon_provider(std::string_view source) {
const auto itemNo = item_for_source(source);
if (!itemNo) {
return std::nullopt;
}
auto& cache = icon_cache();
const std::string key(source);
auto it = cache.find(key);
if (it == cache.end()) {
auto icon = render_item_icon(*itemNo);
if (!icon) {
return std::nullopt;
}
if (cache.size() >= kMaxCachedIcons) {
cache.erase(cache.begin());
}
it = cache.emplace(key, std::move(*icon)).first;
}
const auto& icon = it->second;
return aurora::rmlui::RuntimeTexture{
.width = icon.width,
.height = icon.height,
.rgba8 =
std::span(reinterpret_cast<const std::byte*>(icon.pixels.data()), icon.pixels.size()),
.premultipliedAlpha = true,
};
}
std::optional<aurora::rmlui::RuntimeTexture> meter_texture_provider(std::string_view source) {
if (!source.starts_with(kMeterSourcePrefix)) {
return std::nullopt;
}
const std::string name(strip_query(source.substr(kMeterSourcePrefix.size())));
if (name != "midna") {
return std::nullopt;
}
const auto& state = midna_icon_state();
if (!state.valid) {
return std::nullopt;
}
return aurora::rmlui::RuntimeTexture{
.width = state.icon.width,
.height = state.icon.height,
.rgba8 = std::span(
reinterpret_cast<const std::byte*>(state.icon.pixels.data()), state.icon.pixels.size()),
.premultipliedAlpha = true,
};
}
} // namespace
void register_icon_texture_provider() noexcept {
aurora::rmlui::register_texture_provider(std::string(kScheme), icon_provider);
aurora::rmlui::register_texture_provider(std::string(kMeterScheme), meter_texture_provider);
}
void unregister_icon_texture_provider() noexcept {
aurora::rmlui::unregister_texture_provider(kScheme);
aurora::rmlui::unregister_texture_provider(kMeterScheme);
icon_cache().clear();
midna_icon_state() = {};
}
void update_midna_icon_texture(J2DPane* pane) noexcept {
auto& state = midna_icon_state();
if (pane == nullptr || !pane->isVisible()) {
if (state.valid) {
state.valid = false;
state.icon = {};
state.revision++;
}
return;
}
auto icon = render_j2d_pane_icon(pane);
if (!icon) {
if (state.valid) {
state.valid = false;
state.icon = {};
state.revision++;
}
return;
}
if (!state.valid || state.icon.width != icon->width || state.icon.height != icon->height ||
state.icon.pixels != icon->pixels)
{
state.icon = std::move(*icon);
state.valid = true;
state.revision++;
}
}
std::string midna_icon_source() {
const auto& state = midna_icon_state();
if (!state.valid) {
return "";
}
return fmt::format(
"{}://midna?slot={}", kMeterScheme, state.revision % kMeterTextureSourceSlots);
}
uint64_t midna_icon_revision() noexcept {
const auto& state = midna_icon_state();
return state.valid ? state.revision : 0;
}
std::string item_icon_source_for_button(Control control) {
std::optional<u8> itemNo;
switch (control) {
case Control::X:
itemNo = selected_slot_item(0);
break;
case Control::Y:
itemNo = selected_slot_item(1);
break;
case Control::B:
itemNo = b_button_item();
break;
default:
break;
}
if (!itemNo) {
return {};
}
return item_source_for_item(*itemNo);
}
std::string item_count_label_for_button(Control control) {
std::optional<int> count;
switch (control) {
case Control::X:
count = selected_slot_count(0);
break;
case Control::Y:
count = selected_slot_count(1);
break;
default:
break;
}
if (!count) {
return {};
}
return fmt::format("{}", *count);
}
std::optional<float> item_oil_fill_for_button(Control control) noexcept {
std::optional<u8> itemNo;
switch (control) {
case Control::X:
itemNo = selected_slot_item(0);
break;
case Control::Y:
itemNo = selected_slot_item(1);
break;
default:
break;
}
if (!itemNo || (*itemNo != dItemNo_KANTERA_e && *itemNo != dItemNo_KANTERA2_e)) {
return std::nullopt;
}
const int maxOil = dComIfGs_getMaxOil();
if (maxOil <= 0) {
return std::nullopt;
}
return std::clamp(
static_cast<float>(dComIfGs_getOil()) / static_cast<float>(maxOil), 0.0f, 1.0f);
}
} // namespace dusk::ui
#else
namespace dusk::ui {
void register_icon_texture_provider() noexcept {}
void unregister_icon_texture_provider() noexcept {}
void update_midna_icon_texture(J2DPane*) noexcept {}
std::string midna_icon_source() {
return {};
}
uint64_t midna_icon_revision() noexcept {
return 0;
}
std::string item_icon_source_for_button(Control) {
return {};
}
std::string item_count_label_for_button(Control) {
return {};
}
std::optional<float> item_oil_fill_for_button(Control) noexcept {
return std::nullopt;
}
} // namespace dusk::ui
#endif
-23
View File
@@ -1,23 +0,0 @@
#pragma once
#include "controls.hpp"
#include <cstdint>
#include <optional>
#include <string>
class J2DPane;
namespace dusk::ui {
void register_icon_texture_provider() noexcept;
void unregister_icon_texture_provider() noexcept;
void update_midna_icon_texture(J2DPane* pane) noexcept;
std::string midna_icon_source();
uint64_t midna_icon_revision() noexcept;
std::string item_icon_source_for_button(Control control);
std::string item_count_label_for_button(Control control);
std::optional<float> item_oil_fill_for_button(Control control) noexcept;
} // namespace dusk::ui
+51 -71
View File
@@ -1,11 +1,10 @@
#include "overlay.hpp" #include "overlay.hpp"
#include "aurora/lib/logging.hpp" #include "aurora/lib/logging.hpp"
#include "controller_config.hpp"
#include "dusk/achievements.h" #include "dusk/achievements.h"
#include "dusk/action_bindings.h" #include "dusk/action_bindings.h"
#include "controller_config.hpp"
#include "dusk/livesplit.h" #include "dusk/livesplit.h"
#include "dusk/settings.h"
#include "dusk/speedrun.h" #include "dusk/speedrun.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "magic_enum.hpp" #include "magic_enum.hpp"
@@ -14,7 +13,6 @@
#include <SDL3/SDL_gamepad.h> #include <SDL3/SDL_gamepad.h>
#include <SDL3/SDL_timer.h> #include <SDL3/SDL_timer.h>
#include <algorithm> #include <algorithm>
#include <aurora/gfx.h>
#include <dolphin/pad.h> #include <dolphin/pad.h>
#include <m_Do/m_Do_main.h> #include <m_Do/m_Do_main.h>
@@ -33,13 +31,6 @@ const Rml::String kDocumentSource = R"RML(
</head> </head>
<body> <body>
<fps id="fps" /> <fps id="fps" />
<pipeline-progress id="pipeline-progress">
<pipeline-status>
<icon class="pipeline-spinner">&#xe9d0;</icon>
<span id="pipeline-progress-label" />
</pipeline-status>
<progress id="pipeline-progress-bar" />
</pipeline-progress>
<speedrun-timer id="speedrun-timer"> <speedrun-timer id="speedrun-timer">
<speedrun-rta id="speedrun-rta" /> <speedrun-rta id="speedrun-rta" />
<speedrun-igt id="speedrun-igt" /> <speedrun-igt id="speedrun-igt" />
@@ -55,7 +46,6 @@ constexpr std::array<std::pair<const char*, const char*>, 3> kAutoSaveLayers{{
}}; }};
constexpr auto kMenuNotificationDuration = std::chrono::milliseconds(2500); constexpr auto kMenuNotificationDuration = std::chrono::milliseconds(2500);
constexpr auto kPipelineProgressOpenDelay = std::chrono::milliseconds(250);
constexpr std::array<const char*, 4> kFpsCorners = {"tl", "tr", "bl", "br"}; constexpr std::array<const char*, 4> kFpsCorners = {"tl", "tr", "bl", "br"};
@@ -168,8 +158,8 @@ Rml::Element* create_menu_notification(Rml::Element* parent) {
Rml::String padButton{}; Rml::String padButton{};
SDL_Gamepad* gamepad = gamepad_for_port(PAD_CHAN0); SDL_Gamepad* gamepad = gamepad_for_port(PAD_CHAN0);
if (isActionBound(ActionBinds::OPEN_DUSKLIGHT_MENU, PAD_CHAN0) && gamepad != nullptr) { if (isActionBound(ActionBinds::OPEN_DUSKLIGHT_MENU, PAD_CHAN0) && gamepad != nullptr) {
padButton = native_button_name( padButton = native_button_name(gamepad,
gamepad, getActionBindButton(ActionBinds::OPEN_DUSKLIGHT_MENU, PAD_CHAN0)); getActionBindButton(ActionBinds::OPEN_DUSKLIGHT_MENU, PAD_CHAN0));
} else { } else {
padButton = back_button_name(); padButton = back_button_name();
} }
@@ -197,17 +187,51 @@ void remove_element(Rml::Element*& elem) noexcept {
} // namespace } // namespace
// https://vplesko.com/posts/how_to_implement_an_fps_counter.html
void Overlay::advance_fps_counter(float& outFps, Uint64 perfFreq) {
if (perfFreq == 0) {
outFps = 0.f;
return;
}
const Uint64 curr = SDL_GetPerformanceCounter();
if (!mFpsHavePrevCounter) {
mFpsPrevCounter = curr;
mFpsHavePrevCounter = true;
outFps = 0.f;
return;
}
const Uint64 processingTicks = curr - mFpsPrevCounter;
mFpsPrevCounter = curr;
mFpsFrameEvents.push_back({curr, processingTicks});
mFpsSumTicks += processingTicks;
while (!mFpsFrameEvents.empty() && mFpsFrameEvents.front().endCounter + perfFreq < curr) {
mFpsSumTicks -= mFpsFrameEvents.front().processingTicks;
mFpsFrameEvents.pop_front();
}
const auto n = mFpsFrameEvents.size();
if (n == 0 || mFpsSumTicks == 0) {
outFps = 0.f;
return;
}
const double avgSeconds =
static_cast<double>(mFpsSumTicks) / static_cast<double>(n) / static_cast<double>(perfFreq);
outFps = static_cast<float>(1.0 / avgSeconds);
}
static std::string FormatTime(OSTime ticks) { static std::string FormatTime(OSTime ticks) {
OSCalendarTime t; OSCalendarTime t;
OSTicksToCalendarTime(ticks, &t); OSTicksToCalendarTime(ticks, &t);
return fmt::format("{0:02}:{1:02}:{2:02}.{3:03}", t.hour, t.min, t.sec, t.msec); return fmt::format("{0:02}:{1:02}:{2:02}.{3:03}", t.hour, t.min, t.sec, t.msec);
} }
Overlay::Overlay() : Document(kDocumentSource, true) { Overlay::Overlay() : Document(kDocumentSource) {
mFpsCounter = mDocument->GetElementById("fps"); mFpsCounter = mDocument->GetElementById("fps");
mPipelineProgress = mDocument->GetElementById("pipeline-progress");
mPipelineProgressLabel = mDocument->GetElementById("pipeline-progress-label");
mPipelineProgressBar = mDocument->GetElementById("pipeline-progress-bar");
mSpeedrunTimer = mDocument->GetElementById("speedrun-timer"); mSpeedrunTimer = mDocument->GetElementById("speedrun-timer");
mSpeedrunRta = mDocument->GetElementById("speedrun-rta"); mSpeedrunRta = mDocument->GetElementById("speedrun-rta");
mSpeedrunIgt = mDocument->GetElementById("speedrun-igt"); mSpeedrunIgt = mDocument->GetElementById("speedrun-igt");
@@ -252,7 +276,8 @@ void Overlay::update() {
mFpsCounter->SetAttribute("corner", kFpsCorners[idx]); mFpsCounter->SetAttribute("corner", kFpsCorners[idx]);
const Uint64 perfFreq = SDL_GetPerformanceFrequency(); const Uint64 perfFreq = SDL_GetPerformanceFrequency();
float fps = aurora_get_fps(); float fps = 0.f;
advance_fps_counter(fps, perfFreq);
const Uint64 now = SDL_GetPerformanceCounter(); const Uint64 now = SDL_GetPerformanceCounter();
// Limit updates to twice per second // Limit updates to twice per second
@@ -265,12 +290,13 @@ void Overlay::update() {
} }
} else { } else {
mFpsCounter->RemoveAttribute("open"); mFpsCounter->RemoveAttribute("open");
mFpsFrameEvents.clear();
mFpsSumTicks = 0;
mFpsHavePrevCounter = false;
mFpsLastUpdate = 0; mFpsLastUpdate = 0;
} }
} }
update_pipeline_progress();
#if !(defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS && !TARGET_OS_MACCATALYST)) #if !(defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS && !TARGET_OS_MACCATALYST))
if (getSettings().game.speedrunMode && getSettings().game.liveSplitEnabled) { if (getSettings().game.speedrunMode && getSettings().game.liveSplitEnabled) {
dusk::speedrun::updateLiveSplit(); dusk::speedrun::updateLiveSplit();
@@ -322,8 +348,7 @@ void Overlay::update() {
mSpeedrunRta->RemoveAttribute("open"); mSpeedrunRta->RemoveAttribute("open");
} }
mSpeedrunIgt->SetInnerRML( mSpeedrunIgt->SetInnerRML(escape(fmt::format("IGT {}", FormatTime(m_speedrunInfo.m_igtTimer))));
escape(fmt::format("IGT {}", FormatTime(m_speedrunInfo.m_igtTimer))));
} else { } else {
mSpeedrunTimer->RemoveAttribute("open"); mSpeedrunTimer->RemoveAttribute("open");
} }
@@ -332,7 +357,6 @@ void Overlay::update() {
u32 count = 0; u32 count = 0;
const bool showControllerWarning = PADGetIndexForPort(PAD_CHAN0) < 0 && const bool showControllerWarning = PADGetIndexForPort(PAD_CHAN0) < 0 &&
PADGetKeyButtonBindings(PAD_CHAN0, &count) == nullptr && PADGetKeyButtonBindings(PAD_CHAN0, &count) == nullptr &&
!getSettings().game.enableTouchControls &&
dynamic_cast<Window*>(top_document()) == nullptr && dynamic_cast<Window*>(top_document()) == nullptr &&
dynamic_cast<WindowSmall*>(top_document()) == nullptr; dynamic_cast<WindowSmall*>(top_document()) == nullptr;
if (showControllerWarning && mControllerWarning == nullptr) { if (showControllerWarning && mControllerWarning == nullptr) {
@@ -387,8 +411,10 @@ void Overlay::update() {
std::chrono::duration<float>(clock::now() - mCurrentToastStartTime).count(); std::chrono::duration<float>(clock::now() - mCurrentToastStartTime).count();
const float ratio = duration > 0.0f ? std::clamp(elapsed / duration, 0.0f, 1.0f) : 1.0f; const float ratio = duration > 0.0f ? std::clamp(elapsed / duration, 0.0f, 1.0f) : 1.0f;
const auto remaining = 1.f - ratio; const auto remaining = 1.f - ratio;
if (auto* progress = mCurrentToast->QuerySelector("progress")) { Rml::ElementList list;
progress->SetAttribute("value", remaining); mDocument->GetElementsByTagName(list, "progress");
for (auto* elem : list) {
elem->SetAttribute("value", remaining);
} }
if (remaining == 0.f) { if (remaining == 0.f) {
if (mCurrentToast->IsPseudoClassSet("done") || if (mCurrentToast->IsPseudoClassSet("done") ||
@@ -407,52 +433,6 @@ void Overlay::update() {
} }
} }
void Overlay::update_pipeline_progress() {
if (mPipelineProgress == nullptr || mPipelineProgressLabel == nullptr ||
mPipelineProgressBar == nullptr)
{
return;
}
const auto* stats = aurora_get_stats();
const uint32_t queuedPipelines = stats != nullptr ? stats->queuedPipelines : 0;
if (queuedPipelines == 0) {
mPipelineProgress->RemoveAttribute("open");
mPipelineProgressActive = false;
mPipelineBatchCreatedBase = 0;
mLastQueuedPipelines = 0;
return;
}
const uint32_t createdPipelines = stats->createdPipelines;
if (!mPipelineProgressActive || createdPipelines < mPipelineBatchCreatedBase) {
mPipelineProgressActive = true;
mPipelineBatchCreatedBase = createdPipelines;
mPipelineProgressStartTime = clock::now();
mLastQueuedPipelines = 0;
}
const uint32_t builtPipelines = createdPipelines - mPipelineBatchCreatedBase;
const uint32_t totalPipelines = queuedPipelines + builtPipelines;
const float progress = totalPipelines > 0 ? static_cast<float>(builtPipelines) /
static_cast<float>(totalPipelines) :
0.0f;
if (queuedPipelines != mLastQueuedPipelines) {
mLastQueuedPipelines = queuedPipelines;
const auto noun = queuedPipelines == 1 ? "pipeline" : "pipelines";
mPipelineProgressLabel->SetInnerRML(
escape(fmt::format("Building {} {}", queuedPipelines, noun)));
}
mPipelineProgressBar->SetAttribute("value", progress);
if (clock::now() >= mPipelineProgressStartTime + kPipelineProgressOpenDelay) {
mPipelineProgress->SetAttribute("open", "");
} else {
mPipelineProgress->RemoveAttribute("open");
}
}
bool Overlay::handle_nav_command(Rml::Event& event, NavCommand cmd) { bool Overlay::handle_nav_command(Rml::Event& event, NavCommand cmd) {
Log.warn("Overlay received nav command: {}", magic_enum::enum_name(cmd)); Log.warn("Overlay received nav command: {}", magic_enum::enum_name(cmd));
return false; return false;
+13 -10
View File
@@ -3,6 +3,7 @@
#include "document.hpp" #include "document.hpp"
#include <chrono> #include <chrono>
#include <deque>
namespace dusk::ui { namespace dusk::ui {
@@ -16,13 +17,7 @@ public:
protected: protected:
bool handle_nav_command(Rml::Event& event, NavCommand cmd) override; bool handle_nav_command(Rml::Event& event, NavCommand cmd) override;
private:
void update_pipeline_progress();
Rml::Element* mFpsCounter = nullptr; Rml::Element* mFpsCounter = nullptr;
Rml::Element* mPipelineProgress = nullptr;
Rml::Element* mPipelineProgressLabel = nullptr;
Rml::Element* mPipelineProgressBar = nullptr;
Rml::Element* mCurrentToast = nullptr; Rml::Element* mCurrentToast = nullptr;
Rml::Element* mControllerWarning = nullptr; Rml::Element* mControllerWarning = nullptr;
Rml::Element* mMenuNotification = nullptr; Rml::Element* mMenuNotification = nullptr;
@@ -31,11 +26,19 @@ private:
Rml::Element* mSpeedrunIgt = nullptr; Rml::Element* mSpeedrunIgt = nullptr;
clock::time_point mCurrentToastStartTime; clock::time_point mCurrentToastStartTime;
clock::time_point mMenuNotificationStartTime; clock::time_point mMenuNotificationStartTime;
clock::time_point mPipelineProgressStartTime;
struct FpsFrameEvent {
Uint64 endCounter;
Uint64 processingTicks;
};
std::deque<FpsFrameEvent> mFpsFrameEvents;
Uint64 mFpsSumTicks = 0;
bool mFpsHavePrevCounter = false;
Uint64 mFpsPrevCounter = 0;
Uint64 mFpsLastUpdate = 0; Uint64 mFpsLastUpdate = 0;
uint32_t mPipelineBatchCreatedBase = 0;
uint32_t mLastQueuedPipelines = 0; void advance_fps_counter(float& outFps, Uint64 perfFreq);
bool mPipelineProgressActive = false;
}; };
} // namespace dusk::ui } // namespace dusk::ui
+1 -1
View File
@@ -715,7 +715,7 @@ Prelaunch::Prelaunch() : Document(kDocumentSource), mRoot(mDocument->GetElementB
} }
IsGameLaunched = true; IsGameLaunched = true;
pop(false); hide(true);
}); });
apply_intro_animation(mMenuButtons.back()->root(), "delay-1"); apply_intro_animation(mMenuButtons.back()->root(), "delay-1");

Some files were not shown because too many files have changed in this diff Show More