Compare commits

..

4 Commits

Author SHA1 Message Date
MelonSpeedruns 27274e7341 Merge remote-tracking branch 'origin/main' into feature/hyper-enemies
# Conflicts:
#	src/dusk/imgui/ImGuiMenuGame.cpp
#	src/dusk/settings.cpp
2026-05-03 17:23:54 -04:00
MelonSpeedruns ce0d89058a don't run hyper enemies while an event is running 2026-04-30 10:55:28 -04:00
MelonSpeedruns 36092f1fdb added setting 2026-04-27 18:29:14 -04:00
MelonSpeedruns 5eb3184174 Hyper Enemies (2x) 2026-04-27 16:55:43 -04:00
215 changed files with 6449 additions and 15314 deletions
+53 -57
View File
@@ -48,15 +48,13 @@ else ()
message(STATUS "Unable to find git, commit information will not be available")
endif ()
if (DUSK_WC_DESCRIBE MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)([-+].*)?$")
if (DUSK_WC_DESCRIBE MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)(-([0-9]+).*)?$")
set(DUSK_SHORT_VERSION_STRING "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
set(DUSK_VERSION_TWEAK "0")
if (DUSK_WC_DESCRIBE MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+-([0-9]+)(-dirty)?$")
set(DUSK_VERSION_TWEAK "${CMAKE_MATCH_1}")
elseif (DUSK_WC_DESCRIBE MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+-[0-9A-Za-z.-]+-([0-9]+)(-dirty)?$")
set(DUSK_VERSION_TWEAK "${CMAKE_MATCH_1}")
if (CMAKE_MATCH_5)
set(DUSK_VERSION_STRING "${DUSK_SHORT_VERSION_STRING}.${CMAKE_MATCH_5}")
else ()
set(DUSK_VERSION_STRING "${DUSK_SHORT_VERSION_STRING}.0")
endif ()
set(DUSK_VERSION_STRING "${DUSK_SHORT_VERSION_STRING}.${DUSK_VERSION_TWEAK}")
else ()
set(DUSK_WC_DESCRIBE "UNKNOWN-VERSION")
set(DUSK_VERSION_STRING "0.0.0.0")
@@ -71,7 +69,7 @@ message(STATUS "Dusk version set to ${DUSK_WC_DESCRIBE}")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
project(dusk LANGUAGES C CXX VERSION ${DUSK_VERSION_STRING})
if (APPLE)
enable_language(OBJC OBJCXX)
enable_language(OBJC)
endif ()
if (APPLE AND NOT TVOS AND CMAKE_SYSTEM_NAME STREQUAL tvOS)
# ios.toolchain.cmake hack for SDL
@@ -104,17 +102,19 @@ set(AURORA_ENABLE_DVD ON CACHE BOOL "Enable DVD API support" FORCE)
set(AURORA_ENABLE_CARD ON CACHE BOOL "Enable CARD API support" FORCE)
set(AURORA_ENABLE_RMLUI ON CACHE BOOL "Enable RmlUi UI support" FORCE)
add_subdirectory(extern/aurora EXCLUDE_FROM_ALL)
target_compile_definitions(aurora_mtx PRIVATE MTX_USE_PS=1)
add_subdirectory(libs/freeverb)
option(DUSK_BUILD_WARNINGS "Enable compiler warnings (off by default)")
option(DUSK_SELECTED_OPT "If on, selected parts of the project will be compiled with optimizations on Debug, intending to make the game run at 30 FPS. Note for MSVC: you will need to remove '/RTC1' from your debug flags in CMake.")
option(DUSK_MOVIE_SUPPORT "If on, compile against libjpeg-turbo to enable THP file decoding" ON)
option(DUSK_ENABLE_UPDATE_CHECKER "Enable update checking support" ON)
if(ANDROID)
set(DUSK_MOVIE_SUPPORT OFF)
set(NOD_COMPRESS_BZIP2 OFF CACHE BOOL "" FORCE)
set(NOD_COMPRESS_LZMA OFF CACHE BOOL "" FORCE)
set(NOD_COMPRESS_ZLIB OFF CACHE BOOL "" FORCE)
set(NOD_COMPRESS_ZSTD OFF CACHE BOOL "" FORCE)
endif ()
option(DUSK_ENABLE_SENTRY_NATIVE "Enable sentry-native crash reporting support" OFF)
@@ -283,9 +283,9 @@ set(DUSK_PRODUCT_NAME "Dusk")
set(DUSK_COPYRIGHT "Copyright (C) Twilit Realm contributors")
source_group("dolzel" FILES ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${REL_FILES})
source_group("dusk" FILES ${DUSK_FILES} ${DUSK_HTTP_BACKEND_FILES})
source_group("dusk" FILES ${DUSK_FILES})
set(GAME_COMPILE_DEFS TARGET_PC WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0 MTX_USE_PS=1)
set(GAME_COMPILE_DEFS TARGET_PC WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0)
set(GAME_INCLUDE_DIRS
include
@@ -297,10 +297,8 @@ set(GAME_INCLUDE_DIRS
extern
${CMAKE_BINARY_DIR})
find_package(Threads REQUIRED)
set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd
aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt
Threads::Threads)
aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt)
list(APPEND GAME_LIBS libzstd_static)
@@ -313,41 +311,6 @@ if (WIN32)
list(APPEND GAME_LIBS Ws2_32)
endif ()
set(DUSK_HTTP_BACKEND_SOURCE src/dusk/http/no_backend.cpp)
if (DUSK_ENABLE_UPDATE_CHECKER)
list(APPEND GAME_COMPILE_DEFS DUSK_ENABLE_UPDATE_CHECKER=1)
if (WIN32)
set(DUSK_HTTP_BACKEND_SOURCE src/dusk/http/winhttp.cpp)
list(APPEND GAME_LIBS winhttp)
list(APPEND GAME_COMPILE_DEFS DUSK_HTTP_BACKEND_WINHTTP=1)
message(STATUS "dusk: Enabled update checker (WinHTTP)")
elseif (ANDROID)
set(DUSK_HTTP_BACKEND_SOURCE src/dusk/http/android.cpp)
list(APPEND GAME_COMPILE_DEFS DUSK_HTTP_BACKEND_ANDROID=1)
message(STATUS "dusk: Enabled update checker (Android)")
elseif (APPLE)
find_library(FOUNDATION_FRAMEWORK Foundation REQUIRED)
set(DUSK_HTTP_BACKEND_SOURCE src/dusk/http/url_session.mm)
set_source_files_properties(src/dusk/http/url_session.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
list(APPEND GAME_LIBS ${FOUNDATION_FRAMEWORK})
list(APPEND GAME_COMPILE_DEFS DUSK_HTTP_BACKEND_URLSESSION=1)
message(STATUS "dusk: Enabled update checker (NSURLSession)")
elseif (CMAKE_SYSTEM_NAME STREQUAL Linux)
find_package(CURL QUIET OPTIONAL_COMPONENTS HTTPS SSL)
if (CURL_FOUND AND CURL_HTTPS_FOUND AND CURL_SSL_FOUND)
set(DUSK_HTTP_BACKEND_SOURCE src/dusk/http/curl.cpp)
list(APPEND GAME_LIBS CURL::libcurl)
list(APPEND GAME_COMPILE_DEFS DUSK_HTTP_BACKEND_LIBCURL=1)
message(STATUS "dusk: Enabled update checker (libcurl)")
else ()
message(STATUS "dusk: Disabled update checker (libcurl + HTTPS/SSL not found)")
endif ()
else ()
message(STATUS "dusk: Disabled update checker (unsupported platform)")
endif ()
endif ()
list(APPEND DUSK_FILES ${DUSK_HTTP_BACKEND_SOURCE})
if (DUSK_MOVIE_SUPPORT)
if (TARGET libjpeg-turbo::turbojpeg-static)
list(APPEND GAME_LIBS libjpeg-turbo::turbojpeg-static)
@@ -357,13 +320,46 @@ if (DUSK_MOVIE_SUPPORT)
list(APPEND GAME_COMPILE_DEFS MOVIE_SUPPORT=1)
endif ()
set(DUSK_ENABLE_DISCORD_DEFAULT ON)
if (DEFINED DUSK_ENABLE_DISCORD_RPC AND NOT DEFINED DUSK_ENABLE_DISCORD)
set(DUSK_ENABLE_DISCORD_DEFAULT ${DUSK_ENABLE_DISCORD_RPC})
endif ()
option(DUSK_ENABLE_DISCORD "Enable Discord Rich Presence support" ${DUSK_ENABLE_DISCORD_DEFAULT})
if (DUSK_ENABLE_DISCORD AND NOT ANDROID AND NOT IOS AND NOT TVOS)
list(APPEND GAME_COMPILE_DEFS DUSK_DISCORD=1)
option(DUSK_ENABLE_DISCORD_RPC "Enable Discord Rich Presence support" ON)
if (DUSK_ENABLE_DISCORD_RPC AND NOT ANDROID AND NOT IOS AND NOT TVOS)
FetchContent_Populate(discord_rpc
URL https://github.com/discord/discord-rpc/archive/refs/tags/v3.4.0.tar.gz
URL_HASH SHA256=e13427019027acd187352dacba6c65953af66fdf3c35fcf38fc40b454a9d7855
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)
# RapidJSON is a git submodule absent from the discord-rpc tarball; fetch separately.
FetchContent_Populate(rapidjson
URL https://github.com/Tencent/rapidjson/archive/refs/tags/v1.1.0.tar.gz
URL_HASH SHA256=bf7ced29704a1e696fbccf2a2b4ea068e7774fa37f6d7dd4039d0787f8bed98e
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)
if (NOT TARGET discord-rpc)
set(_drpc ${discord_rpc_SOURCE_DIR}/src)
set(_drpc_src
${_drpc}/discord_rpc.cpp
${_drpc}/rpc_connection.cpp
${_drpc}/serialization.cpp
)
if (WIN32)
list(APPEND _drpc_src ${_drpc}/connection_win.cpp ${_drpc}/discord_register_win.cpp)
elseif (APPLE)
list(APPEND _drpc_src ${_drpc}/connection_unix.cpp ${_drpc}/discord_register_osx.m)
else ()
list(APPEND _drpc_src ${_drpc}/connection_unix.cpp ${_drpc}/discord_register_linux.cpp)
endif ()
add_library(discord-rpc STATIC ${_drpc_src})
target_include_directories(discord-rpc PUBLIC
${discord_rpc_SOURCE_DIR}/include
${rapidjson_SOURCE_DIR}/include
)
if (UNIX)
target_link_libraries(discord-rpc PUBLIC pthread)
endif ()
endif ()
list(APPEND GAME_LIBS discord-rpc)
list(APPEND GAME_COMPILE_DEFS DUSK_DISCORD_RPC=1)
endif ()
# Edit & Continue
+1 -1
View File
@@ -30,7 +30,7 @@
"CMAKE_CXX_COMPILER_LAUNCHER": "sccache",
"DUSK_ENABLE_SENTRY_NATIVE": {
"type": "BOOL",
"value": false
"value": true
},
"DUSK_SENTRY_DSN": "$env{SENTRY_DSN}",
"DUSK_SENTRY_ENVIRONMENT": "production"
+15 -44
View File
@@ -1,66 +1,37 @@
<div align="center">
<img src="res/logo-mascot.png" alt="Logo" width="640">
![DuskLogo](res/logo-mascot.png)
<p align="center">
<a href="https://twilitrealm.dev">Official Website</a>
<a href="https://discord.gg/dusktp">Discord</a>
</p>
</div>
- ### **[Official Website](https://twilitrealm.dev)**
- ### **[Discord](https://discord.gg/QACynxeyna)**
# Overview
Dusk is a reverse-engineered reimplementation of Twilight Princess.
It aims to be as accurate as possible to the original while also providing new options, enhancements, and tools to customize your experience.
# Setup
**⚠️ Dusk does NOT provide any copyrighted assets. You must provide your own copy of the game.**
> [!IMPORTANT]
> Dusk does *not* provide any copyrighted assets. You must provide your own copy of the original game.
### 1. Verify your ROM dump
First make sure your dump of the game is clean and supported by Dusk. You can do this by checking the sha1 hash of your dump against this list of supported versions.
### 1. Verify your dump
First, make sure your dump of the game is clean and supported by Dusk. You can do this by checking the SHA-1 hash of your dump against this list of supported versions:
| Version | SHA-1 hash |
|--------------| ------------------------------------------ |
| GameCube USA | `75edd3ddff41f125d1b4ce1a40378f1b565519e7` |
| GameCube EUR | `2601822a488eeb86fb89db16ca8f29c2c953e1ca` |
*Support for other versions of the game is planned in the future.
| Version | sha1 hash |
|--------------| ---------------------------------------- |
| GameCube USA | 75edd3ddff41f125d1b4ce1a40378f1b565519e7 |
| GameCube PAL | 2601822a488eeb86fb89db16ca8f29c2c953e1ca |
### 2. Download [Dusk](https://github.com/TwilitRealm/dusk/releases)
### 3. Setup the game
**Windows / macOS / Linux**
- Extract the .zip file
- Extract the zip folder
- Launch Dusk
- Press **Select Disc Image** and provide the path to your supported game dump
- Press **Play**!
- Select Options, then set the ISO Path to your supported game dump
- Press Start Game to play!
**iOS**
- Follow the [iOS setup guide](docs/ios-install-altstore.md)
**Android**
- Install the Dusk apk
- Launch Dusk
- Press **Select Disc Image** and provide the path to your supported game dump
- Press **Play**!
![Dusk options](assets/dusk_options.png)
# Building
If you'd like to build Dusk from source, please read the [build instructions](docs/building.md).
Pull requests are welcomed! Note that we do not accept contributions that are primarily AI-generated and will close your PR if we suspect as much.
Pull Requests are welcomed! Note that we do not accept contributions that are primarily AI generated and will close your PR if we suspect as much.
# Credits
Special thanks to the [TP decompilation](https://github.com/zeldaret/tp) team, the GC/Wii decompilation community, the [Aurora](https://github.com/encounter/aurora) developers, the [TP speedrunning community](https://zsrtp.link), and all [contributors](https://github.com/TwilitRealm/dusk/graphs/contributors).
<br/>
<div align="center">
<a href="https://github.com/encounter/aurora">
<img src="assets/aurora-powered.png" alt="Powered by Aurora" width="800">
</a>
</div>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

-66
View File
@@ -1,66 +0,0 @@
<svg width="600" height="600" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
<circle cx="150" cy="150" r="105" fill="none" stroke="white" stroke-width="4"/>
<circle cx="150" cy="150" r="95" fill="none" stroke="white" stroke-width="4"/>
<circle cx="150" cy="150" r="60" fill="none" stroke="white" stroke-width="4"/>
<circle cx="150" cy="150" r="75" fill="none" stroke="white" stroke-width="4"/>
<defs>
<line id="ray" x1="150" y1="55" x2="150" y2="45"/>
<clipPath id="zigzag-clip">
<circle cx="150" cy="150" r="75"/>
</clipPath>
</defs>
<g stroke="white" stroke-width="3">
<use href="#ray"/>
<use href="#ray" transform="rotate(18 150 150)"/>
<use href="#ray" transform="rotate(36 150 150)"/>
<use href="#ray" transform="rotate(54 150 150)"/>
<use href="#ray" transform="rotate(72 150 150)"/>
<use href="#ray" transform="rotate(90 150 150)"/>
<use href="#ray" transform="rotate(108 150 150)"/>
<use href="#ray" transform="rotate(126 150 150)"/>
<use href="#ray" transform="rotate(144 150 150)"/>
<use href="#ray" transform="rotate(162 150 150)"/>
<use href="#ray" transform="rotate(180 150 150)"/>
<use href="#ray" transform="rotate(198 150 150)"/>
<use href="#ray" transform="rotate(216 150 150)"/>
<use href="#ray" transform="rotate(234 150 150)"/>
<use href="#ray" transform="rotate(252 150 150)"/>
<use href="#ray" transform="rotate(270 150 150)"/>
<use href="#ray" transform="rotate(288 150 150)"/>
<use href="#ray" transform="rotate(306 150 150)"/>
<use href="#ray" transform="rotate(324 150 150)"/>
<use href="#ray" transform="rotate(342 150 150)"/>
</g>
<polygon fill="none" stroke="white" stroke-width="4" opacity="1" clip-path="url(#zigzag-clip)"
points="
126.82,78.67
150,90
173.18,78.67
185.27,101.46
210.68,105.92
207.06,131.46
225,150
207.06,168.54
210.68,194.08
185.27,198.54
173.18,221.33
150,210
126.82,221.33
114.73,198.54
89.32,194.08
92.94,168.54
75,150
92.94,131.46
89.32,105.92
114.73,101.46
"/>
<g fill="none" stroke="white" stroke-width="4">
<polygon points="150,105 130,140 170,140"/>
<polygon points="130,140 110,175 150,175"/>
<polygon points="170,140 150,175 190,175"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

-46
View File
@@ -1,46 +0,0 @@
# Installing Dusk on iOS via AltStore
## Prerequisites
- Mac with Homebrew installed
- iPhone connected via USB
- Dusk IPA file (download the latest `Dusk-vX.X.X-ios-arm64.ipa` from the [releases page](https://github.com/TwilitRealm/dusk/releases))
- Game disc - `GZ2E01` (Gamecube USA) or `GZ2PE01` (Gamecube PAL)
## 1. Install AltServer
```sh
brew install altserver
open -a AltServer
```
AltServer will appear in your menu bar.
## 2. Enable Developer Mode (iOS 16+)
- On your iPhone, go to **Settings > Privacy & Security > Developer Mode**
- Toggle it on and restart when prompted
## 3. Install AltStore on Your iPhone
- Click AltServer in the menu bar
- Click **Install AltStore > [Your iPhone]**
- Enter your Apple ID credentials when prompted
- On your iPhone, go to **Settings > General > VPN & Device Management**
- Tap your Apple ID under "Developer App" and tap **Trust**
## 4. Copy Files to Your iPhone
Transfer the IPA and game disc to your iPhone so they're accessible in the Files app. A few ways to do this:
- **AirDrop** - Right-click the files on your Mac and choose Share > AirDrop
- **iCloud Drive** - Place files in iCloud Drive on your Mac and they'll sync to Files on your iPhone
- **USB transfer** - Connect your iPhone and drag files via Finder's sidebar
- **Cloud storage** - Upload to Google Drive, Dropbox, etc. and download on your iPhone
## 5. Install via AltStore
- Open **AltStore** on your iPhone
- Go to the **My Apps** tab
- Tap the **+** button (top left)
- Open the **Files** app and select the `.ipa` file
+1 -1
+11 -24
View File
@@ -1430,14 +1430,11 @@ set(DUSK_FILES
src/dusk/gyro.cpp
src/dusk/gamepad_color.cpp
src/dusk/autosave.cpp
src/dusk/http/http.hpp
src/dusk/io.cpp
src/dusk/layout.cpp
src/dusk/logging.cpp
src/dusk/settings.cpp
src/dusk/stubs.cpp
src/dusk/update_check.cpp
src/dusk/update_check.hpp
#src/dusk/m_Do_ext_dusk.cpp
src/dusk/imgui/ImGuiConfig.hpp
src/dusk/imgui/ImGuiConsole.hpp
@@ -1450,37 +1447,36 @@ set(DUSK_FILES
src/dusk/imgui/ImGuiBloomWindow.hpp
src/dusk/imgui/ImGuiMenuTools.cpp
src/dusk/imgui/ImGuiMenuTools.hpp
src/dusk/imgui/ImGuiPreLaunchWindow.cpp
src/dusk/imgui/ImGuiPreLaunchWindow.hpp
src/dusk/imgui/ImGuiFirstRunPreset.hpp
src/dusk/imgui/ImGuiFirstRunPreset.cpp
src/dusk/imgui/ImGuiProcessOverlay.cpp
src/dusk/imgui/ImGuiCameraOverlay.cpp
src/dusk/imgui/ImGuiHeapOverlay.cpp
src/dusk/imgui/ImGuiDebugPad.cpp
src/dusk/imgui/ImGuiControllerOverlay.cpp
src/dusk/imgui/ImGuiStubLog.cpp
src/dusk/imgui/ImGuiMapLoader.cpp
src/dusk/imgui/ImGuiSaveEditor.cpp
src/dusk/imgui/ImGuiStateShare.hpp
src/dusk/imgui/ImGuiStateShare.cpp
src/dusk/ui/achievements.cpp
src/dusk/ui/achievements.hpp
src/dusk/imgui/ImGuiAchievements.hpp
src/dusk/imgui/ImGuiAchievements.cpp
src/dusk/ui/bool_button.cpp
src/dusk/ui/bool_button.hpp
src/dusk/ui/button.cpp
src/dusk/ui/button.hpp
src/dusk/ui/component.cpp
src/dusk/ui/component.hpp
src/dusk/ui/controller_config.cpp
src/dusk/ui/controller_config.hpp
src/dusk/ui/document.cpp
src/dusk/ui/document.hpp
src/dusk/ui/editor.cpp
src/dusk/ui/editor.hpp
src/dusk/ui/event.cpp
src/dusk/ui/event.hpp
src/dusk/ui/graphics_tuner.cpp
src/dusk/ui/graphics_tuner.hpp
src/dusk/ui/input.cpp
src/dusk/ui/input.hpp
src/dusk/ui/modal.cpp
src/dusk/ui/modal.hpp
src/dusk/ui/nav_types.hpp
src/dusk/ui/number_button.cpp
src/dusk/ui/number_button.hpp
@@ -1488,12 +1484,12 @@ set(DUSK_FILES
src/dusk/ui/overlay.hpp
src/dusk/ui/pane.cpp
src/dusk/ui/pane.hpp
src/dusk/ui/menu_bar.cpp
src/dusk/ui/menu_bar.hpp
src/dusk/ui/popup.cpp
src/dusk/ui/popup.hpp
src/dusk/ui/prelaunch.cpp
src/dusk/ui/prelaunch.hpp
src/dusk/ui/preset.cpp
src/dusk/ui/preset.hpp
src/dusk/ui/prelaunch_options.cpp
src/dusk/ui/prelaunch_options.hpp
src/dusk/ui/select_button.cpp
src/dusk/ui/select_button.hpp
src/dusk/ui/settings.cpp
@@ -1514,15 +1510,6 @@ set(DUSK_FILES
src/dusk/OSReport.cpp
src/dusk/OSThread.cpp
src/dusk/OSMutex.cpp
src/dusk/discord.cpp
src/dusk/discord.hpp
src/dusk/discord_presence.cpp
src/dusk/version.cpp
)
set(DUSK_HTTP_BACKEND_FILES
src/dusk/http/no_backend.cpp
src/dusk/http/curl.cpp
src/dusk/http/winhttp.cpp
src/dusk/http/url_session.mm
)
-12
View File
@@ -4552,18 +4552,6 @@ public:
void handleWolfHowl();
void handleQuickTransform();
bool checkGyroAimContext();
void onIronBallChainInterpCallback();
static const int IRON_BALL_CHAIN_COUNT = 102;
cXyz mIBChainInterpPrevPos[IRON_BALL_CHAIN_COUNT];
cXyz mIBChainInterpCurrPos[IRON_BALL_CHAIN_COUNT];
csXyz mIBChainInterpPrevAngle[IRON_BALL_CHAIN_COUNT];
csXyz mIBChainInterpCurrAngle[IRON_BALL_CHAIN_COUNT];
cXyz mIBChainInterpPrevHandRoot;
cXyz mIBChainInterpCurrHandRoot;
bool mIBChainInterpPrevValid;
bool mIBChainInterpCurrValid;
#endif
}; // Size: 0x385C
-6
View File
@@ -80,12 +80,6 @@ public:
/* 0x125C */ u32 field_0x125c;
/* 0x1260 */ u8 field_0x1260[0x126C - 0x1260];
/* 0x126C */ u8 HIOInit;
#if TARGET_PC
cXyz mStalkLineInterpPrev[12];
cXyz mStalkLineInterpCurr[12];
bool mStalkLineInterpPrevValid;
bool mStalkLineInterpCurrValid;
#endif
};
STATIC_ASSERT(sizeof(e_db_class) == 0x1270);
-6
View File
@@ -73,12 +73,6 @@ public:
/* 0x124C */ f32 field_0x124c;
/* 0x1250 */ u8 field_0x1250[0x1264 - 0x1250];
/* 0x1264 */ u8 HIOInit;
#if TARGET_PC
cXyz mStalkLineInterpPrev[12];
cXyz mStalkLineInterpCurr[12];
bool mStalkLineInterpPrevValid;
bool mStalkLineInterpCurrValid;
#endif
};
STATIC_ASSERT(sizeof(e_hb_class) == 0x1268);
-9
View File
@@ -81,15 +81,6 @@ public:
/* 0x306D */ u8 field_0x306D[0x307C - 0x306D];
/* 0x307C */ u32 mBodyEffEmtrID;
/* 0x3080 */ u8 mInitHIO;
#if TARGET_PC
static const int HAIR_STRAND_COUNT = 22;
static const int HAIR_SEGMENT_COUNT = 16;
cXyz mHairInterpPrev[HAIR_STRAND_COUNT * HAIR_SEGMENT_COUNT];
cXyz mHairInterpCurr[HAIR_STRAND_COUNT * HAIR_SEGMENT_COUNT];
bool mHairInterpPrevValid;
bool mHairInterpCurrValid;
#endif
};
STATIC_ASSERT(sizeof(e_s1_class) == 0x3084);
-6
View File
@@ -74,12 +74,6 @@ public:
/* 0x1250 */ f32 field_0x1250;
/* 0x1254 */ u8 field_0x1254[0x1268 - 0x1254];
/* 0x1268 */ u8 field_0x1268;
#if TARGET_PC
cXyz mLineMatInterpPrev[12];
cXyz mLineMatInterpCurr[12];
bool mLineMatInterpPrevValid;
bool mLineMatInterpCurrValid;
#endif
};
STATIC_ASSERT(sizeof(e_yd_class) == 0x126c);
-9
View File
@@ -63,15 +63,6 @@ public:
/* 0x0BB4 */ yg_ke_s mYgKes[13];
/* 0x1880 */ mDoExt_3DlineMat0_c mLineMat;
/* 0x189C */ u8 mIsFirstSpawn;
#if TARGET_PC
static const int TENTACLE_STRAND_COUNT = 13;
static const int TENTACLE_SEGMENT_COUNT = 10;
cXyz mTentacleInterpPrev[TENTACLE_STRAND_COUNT * TENTACLE_SEGMENT_COUNT];
cXyz mTentacleInterpCurr[TENTACLE_STRAND_COUNT * TENTACLE_SEGMENT_COUNT];
bool mTentacleInterpPrevValid;
bool mTentacleInterpCurrValid;
#endif
};
STATIC_ASSERT(sizeof(e_yg_class) == 0x18a0);
-6
View File
@@ -77,12 +77,6 @@ public:
/* 0x1260 */ u32 field_0x1260;
/* 0x1260 */ u8 field_0x1264[0x1270 - 0x1264];
/* 0x1270 */ bool mIsHIOOwner;
#if TARGET_PC
cXyz mLineInterpPrev[12];
cXyz mLineInterpCurr[12];
bool mLineInterpPrevValid;
bool mLineInterpCurrValid;
#endif
};
STATIC_ASSERT(sizeof(e_yh_class) == 0x1274);
-12
View File
@@ -31,10 +31,6 @@ public:
csXyz* getAngle() { return field_0x8a4; }
J3DModelData* getModelData() { return mModelData; }
#if TARGET_PC
void onInterpCallback();
#endif
private:
/* 0x568 */ request_of_phase_process_class mPhase;
/* 0x570 */ J3DModelData* mModelData;
@@ -46,14 +42,6 @@ private:
/* 0x694 */ cXyz field_0x694[22];
/* 0x79C */ cXyz field_0x79c[22];
/* 0x8A4 */ csXyz field_0x8a4[22];
#if TARGET_PC
static const int CHAIN_COUNT = 22;
cXyz mChainInterpPrev[CHAIN_COUNT];
cXyz mChainInterpCurr[CHAIN_COUNT];
bool mChainInterpPrevValid;
bool mChainInterpCurrValid;
#endif
};
STATIC_ASSERT(sizeof(daObjFchain_c) == 0x928);
-11
View File
@@ -25,10 +25,6 @@ public:
int Draw();
int Delete();
#if TARGET_PC
void onInterpCallback();
#endif
enum Param_e {
LOCK_e = (1 << 6), NO_BASE_DISP = (1 << 7)
};
@@ -54,13 +50,6 @@ private:
/* 0x1020 */ dCcD_Cyl mCylinderCollider;
/* 0x115C */ s32 mStopSwingingFrames;
#if TARGET_PC
cXyz mChainInterpPrev[64];
cXyz mChainInterpCurr[64];
bool mChainInterpPrevValid;
bool mChainInterpCurrValid;
#endif
// Number of chain models
u32 getArg0() {
return fopAcM_GetParamBit(this, 0, 6);
-18
View File
@@ -118,18 +118,6 @@ class camera_class;
class dCamera_c;
typedef bool (dCamera_c::*engine_fn)(s32);
#if TARGET_PC
struct DebugFlyCam {
bool initialized;
f32 pitch;
f32 yaw;
cXyz savedCenter;
cXyz savedEye;
f32 savedFovy;
cSAngle savedBank;
};
#endif
class dCamera_c {
public:
class dCamInfo_c {
@@ -1040,8 +1028,6 @@ public:
bool test2Camera(s32);
#if TARGET_PC
bool freeCamera();
bool executeDebugFlyCam();
void deactivateDebugFlyCam();
#endif
bool towerCamera(s32);
bool hookshotCamera(s32);
@@ -1390,10 +1376,6 @@ public:
/* 0x970 */ dCamSetup_c mCamSetup;
/* 0xAEC */ dCamParam_c mCamParam;
/* 0xB0C */ u8 field_0xb0c;
#if TARGET_PC
DebugFlyCam mDebugFlyCam;
#endif
}; // Size: 0xB10
dCamera_c* dCam_getBody();
-6
View File
@@ -1845,12 +1845,6 @@ inline void dComIfGs_addDeathCount() {
g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().addDeathCount();
}
#if TARGET_PC
inline u16 dComIfGs_getDeathCount() {
return g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().getDeathCount();
}
#endif
inline char* dComIfGs_getPlayerName() {
return g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().getPlayerName();
}
-6
View File
@@ -169,12 +169,6 @@ public:
void mapBlink() {}
#if PLATFORM_WII || TARGET_PC
f32 getMirrorPosX(f32 param_0, f32 param_1) {
return (field_0x11dc * 2.0f - (param_0 + param_1)) - param_1;
}
#endif
// Unknown name
struct RegionTexData {
/* 0x00 */ float mMinX;
-10
View File
@@ -66,16 +66,6 @@ public:
_c90 = param_2;
}
#if PLATFORM_WII || TARGET_PC
f32 getMirrorCenterPosX(f32 param_0, f32 param_1) {
if (_c90) {
return (mCenterPosX * 2.0f - (param_0 + param_1)) - param_1;
}
return param_0;
}
#endif
struct Stage_c {
// Incomplete class
-3
View File
@@ -486,9 +486,6 @@ public:
mDeathCount++;
}
}
#if TARGET_PC
u16 getDeathCount() const { return mDeathCount; }
#endif
char* getPlayerName() const { return const_cast<char*>(mPlayerName); }
void setPlayerName(const char* i_name) {
#if AVOID_UB
+5 -1
View File
@@ -12,8 +12,9 @@
namespace dusk {
enum class AchievementCategory : uint8_t {
Challenge,
Story,
Collection,
Challenge,
Minigame,
Misc,
Glitched
@@ -49,6 +50,8 @@ public:
bool hasSignal(const char* key) const;
std::vector<Achievement> getAchievements() const;
bool hasPendingUnlock() const { return !m_pendingUnlocks.empty(); }
std::string consumePendingUnlock();
private:
struct Entry {
@@ -65,6 +68,7 @@ private:
std::unordered_set<std::string_view> m_signals;
bool m_loaded = false;
bool m_dirty = false;
std::queue<std::string> m_pendingUnlocks;
};
} // namespace dusk
+12 -8
View File
@@ -1,14 +1,18 @@
#pragma once
#ifdef DUSK_DISCORD
#ifdef DUSK_DISCORD_RPC
namespace dusk::discord {
namespace dusk {
namespace discord {
void initialize();
void run_callbacks();
void update_presence();
void shutdown();
void Initialize();
} // namespace dusk::discord
void RunCallbacks();
#endif // DUSK_DISCORD
void UpdatePresence();
void Shutdown();
}
}
#endif // DUSK_DISCORD_RPC
-1
View File
@@ -12,7 +12,6 @@ void rollgoalTableOffset(s16& out_ax, s16& out_az);
extern bool s_sensor_keep_alive;
bool get_sensor_keep_alive();
void set_sensor_keep_alive(bool value);
bool rollgoal_gyro_enabled();
} // namespace dusk::gyro
#endif
+1 -14
View File
@@ -1,27 +1,14 @@
#ifndef DUSK_MAIN_H
#define DUSK_MAIN_H
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#include <filesystem>
namespace dusk {
extern bool IsRunning;
extern bool IsShuttingDown;
extern bool IsGameLaunched;
extern bool RestartRequested;
extern bool IsFocusPaused;
extern std::filesystem::path ConfigPath;
#if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS) || \
(defined(TARGET_OS_TV) && TARGET_OS_TV)
inline constexpr bool SupportsProcessRestart = false;
#else
inline constexpr bool SupportsProcessRestart = true;
#endif
void RequestRestart() noexcept;
}
#endif // DUSK_MAIN_H
-2
View File
@@ -1,7 +1,5 @@
#pragma once
#include <array>
struct RoomEntry {
u8 roomNo;
std::vector<s16> roomPoints = {};
+137 -1
View File
@@ -2,6 +2,9 @@
#define _SRC_DUSK_MATH_H_
#include <cmath>
#include <array>
#include <limits>
#include <bit>
#ifndef M_PI
#define M_PI 3.14159265358979323846f
@@ -16,6 +19,139 @@ inline float i_cosf(float x) { return cos(x); }
inline float i_tanf(float x) { return tan(x); }
inline float i_acosf(float x) { return acos(x); }
#include <dolphin/ppc_math.h>
// frsqrte matching courtesy of Geotale, with reference to https://achurch.org/cpu-tests/ppc750cl.s
struct BaseAndDec32 {
uint32_t base;
int32_t dec;
};
struct BaseAndDec64 {
uint64_t base;
int64_t dec;
};
union c32 {
constexpr c32(const float p) {
f = p;
}
constexpr c32(const uint32_t p) {
u = p;
}
uint32_t u;
float f;
};
union c64 {
constexpr c64(const double p) {
f = p;
}
constexpr c64(const uint64_t p) {
u = p;
}
uint64_t u;
double f;
};
static constexpr uint64_t EXPONENT_SHIFT_F64 = 52;
static constexpr uint64_t MANTISSA_MASK_F64 = 0x000fffffffffffffULL;
static constexpr uint64_t EXPONENT_MASK_F64 = 0x7ff0000000000000ULL;
static constexpr uint64_t SIGN_MASK_F64 = 0x8000000000000000ULL;
static constexpr std::array<BaseAndDec64, 32> RSQRTE_TABLE = {{
{0x69fa000000000ULL, -0x15a0000000LL},
{0x5f2e000000000ULL, -0x13cc000000LL},
{0x554a000000000ULL, -0x1234000000LL},
{0x4c30000000000ULL, -0x10d4000000LL},
{0x43c8000000000ULL, -0x0f9c000000LL},
{0x3bfc000000000ULL, -0x0e88000000LL},
{0x34b8000000000ULL, -0x0d94000000LL},
{0x2df0000000000ULL, -0x0cb8000000LL},
{0x2794000000000ULL, -0x0bf0000000LL},
{0x219c000000000ULL, -0x0b40000000LL},
{0x1bfc000000000ULL, -0x0aa0000000LL},
{0x16ae000000000ULL, -0x0a0c000000LL},
{0x11a8000000000ULL, -0x0984000000LL},
{0x0ce6000000000ULL, -0x090c000000LL},
{0x0862000000000ULL, -0x0898000000LL},
{0x0416000000000ULL, -0x082c000000LL},
{0xffe8000000000ULL, -0x1e90000000LL},
{0xf0a4000000000ULL, -0x1c00000000LL},
{0xe2a8000000000ULL, -0x19c0000000LL},
{0xd5c8000000000ULL, -0x17c8000000LL},
{0xc9e4000000000ULL, -0x1610000000LL},
{0xbedc000000000ULL, -0x1490000000LL},
{0xb498000000000ULL, -0x1330000000LL},
{0xab00000000000ULL, -0x11f8000000LL},
{0xa204000000000ULL, -0x10e8000000LL},
{0x9994000000000ULL, -0x0fe8000000LL},
{0x91a0000000000ULL, -0x0f08000000LL},
{0x8a1c000000000ULL, -0x0e38000000LL},
{0x8304000000000ULL, -0x0d78000000LL},
{0x7c48000000000ULL, -0x0cc8000000LL},
{0x75e4000000000ULL, -0x0c28000000LL},
{0x6fd0000000000ULL, -0x0b98000000LL},
}};
[[nodiscard]] static inline double frsqrte(const double val) {
c64 bits(val);
uint64_t mantissa = bits.u & MANTISSA_MASK_F64;
int64_t exponent = bits.u & EXPONENT_MASK_F64;
bool sign = (bits.u & SIGN_MASK_F64) != 0;
// Handle 0 case
if (mantissa == 0 && exponent == 0) {
return std::copysign(std::numeric_limits<double>::infinity(), bits.f);
}
// Handle NaN-like
if (exponent == EXPONENT_MASK_F64) {
if (mantissa == 0) {
return sign ? std::numeric_limits<double>::quiet_NaN() : 0.0;
}
return val;
}
// Handle negative inputs
if (sign) {
return std::numeric_limits<double>::quiet_NaN();
}
if (exponent == 0) {
// Shift so one bit goes to where the exponent would be,
// then clear that bit to mimic a not-subnormal number!
// Aka, if there are 12 leading zeroes, shift left once
uint32_t shift = std::countl_zero(mantissa) - static_cast<uint32_t>(63 - EXPONENT_SHIFT_F64);
mantissa <<= shift;
mantissa &= MANTISSA_MASK_F64;
// The shift is subtracted by 1 because denormals by default
// are offset by 1 (exponent 0 doesn't have implied 1 bit)
exponent -= static_cast<int64_t>(shift - 1) << EXPONENT_SHIFT_F64;
}
// In reality this doesn't get the full exponent -- Only the least significant bit
// Only that's needed because square roots of higher exponent bits simply multiply the
// result by 2!!
uint32_t key = static_cast<uint32_t>((static_cast<uint64_t>(exponent) | mantissa) >> 37);
uint64_t new_exp =
(static_cast<uint64_t>((0xbfcLL << EXPONENT_SHIFT_F64) - exponent) >> 1) & EXPONENT_MASK_F64;
// Remove the bits relating to anything higher than the LSB of the exponent
const auto &entry = RSQRTE_TABLE[0x1f & (key >> 11)];
// The result is given by an estimate then an adjustment based on the original
// key that was computed
uint64_t new_mantissa = static_cast<uint64_t>(entry.base + entry.dec * static_cast<int64_t>(key & 0x7ff));
return c64(new_exp | new_mantissa).f;
}
#endif // _SRC_DUSK_MATH_H_
+6 -37
View File
@@ -21,17 +21,6 @@ enum class GameLanguage : u8 {
Italian = OS_LANGUAGE_ITALIAN,
};
enum class DiscVerificationState : u8 {
Unknown = 0,
Success,
HashMismatch,
};
enum class GyroMode : u8 {
Sensor = 0,
Mouse = 1,
};
namespace config {
template <>
struct ConfigEnumRange<BloomMode> {
@@ -44,18 +33,6 @@ struct ConfigEnumRange<GameLanguage> {
static constexpr auto min = GameLanguage::English;
static constexpr auto max = GameLanguage::Italian;
};
template <>
struct ConfigEnumRange<DiscVerificationState> {
static constexpr auto min = DiscVerificationState::Unknown;
static constexpr auto max = DiscVerificationState::HashMismatch;
};
template <>
struct ConfigEnumRange<GyroMode> {
static constexpr auto min = GyroMode::Sensor;
static constexpr auto max = GyroMode::Mouse;
};
}
// Persistent user settings
@@ -68,8 +45,6 @@ struct UserSettings {
ConfigVar<bool> enableFullscreen;
ConfigVar<bool> enableVsync;
ConfigVar<bool> lockAspectRatio;
ConfigVar<bool> enableFpsOverlay;
ConfigVar<int> fpsOverlayCorner;
} video;
struct {
@@ -81,7 +56,6 @@ struct UserSettings {
ConfigVar<int> fanfareVolume;
ConfigVar<bool> enableReverb;
ConfigVar<bool> enableHrtf;
ConfigVar<bool> menuSounds;
} audio;
// Game settings
@@ -92,11 +66,13 @@ struct UserSettings {
// QoL
ConfigVar<bool> enableQuickTransform;
ConfigVar<bool> hideTvSettingsScreen;
ConfigVar<bool> skipWarningScreen;
ConfigVar<bool> biggerWallets;
ConfigVar<bool> noReturnRupees;
ConfigVar<bool> disableRupeeCutscenes;
ConfigVar<bool> noSwordRecoil;
ConfigVar<int> damageMultiplier;
ConfigVar<bool> hyperEnemies;
ConfigVar<bool> noHeartDrops;
ConfigVar<bool> instantDeath;
ConfigVar<bool> fastClimbing;
@@ -110,11 +86,11 @@ struct UserSettings {
// Preferences
ConfigVar<bool> enableMirrorMode;
ConfigVar<bool> minimalHUD;
ConfigVar<bool> disableMainHUD;
ConfigVar<bool> pauseOnFocusLost;
ConfigVar<bool> enableLinkDollRotation;
ConfigVar<bool> enableAchievementToasts;
ConfigVar<bool> enableControllerToasts;
ConfigVar<bool> enableAchievementNotifications;
// Graphics
ConfigVar<BloomMode> bloomMode;
@@ -131,7 +107,6 @@ struct UserSettings {
ConfigVar<bool> midnasLamentNonStop;
// Input
ConfigVar<GyroMode> gyroMode;
ConfigVar<bool> enableGyroAim;
ConfigVar<bool> enableGyroRollgoal;
ConfigVar<float> gyroSensitivityX;
@@ -145,9 +120,6 @@ struct UserSettings {
ConfigVar<bool> invertCameraXAxis;
ConfigVar<bool> invertCameraYAxis;
ConfigVar<float> freeCameraSensitivity;
ConfigVar<bool> debugFlyCam;
ConfigVar<bool> debugFlyCamLockEvents;
ConfigVar<bool> allowBackgroundInput;
// Cheats
ConfigVar<bool> infiniteHearts;
@@ -174,20 +146,17 @@ struct UserSettings {
// Tools
ConfigVar<bool> speedrunMode;
ConfigVar<bool> liveSplitEnabled;
ConfigVar<bool> recordingMode;
} game;
struct {
ConfigVar<std::string> isoPath;
ConfigVar<DiscVerificationState> isoVerification;
ConfigVar<std::string> graphicsBackend;
ConfigVar<bool> skipPreLaunchUI;
ConfigVar<bool> showPipelineCompilation;
ConfigVar<bool> wasPresetChosen;
ConfigVar<bool> enableCrashReporting;
ConfigVar<bool> checkForUpdates;
ConfigVar<bool> duskMenuOpen;
ConfigVar<int> cardFileType;
ConfigVar<bool> enableAdvancedSettings;
} backend;
};
-13
View File
@@ -5,7 +5,6 @@
#include "Z2AudioLib/Z2EnvSeMgr.h"
#include "Z2AudioLib/Z2LinkMgr.h"
#include "dusk/audio.h"
#include "dusk/settings.h"
class mDoAud_zelAudio_c : public Z2AudioMgr {
public:
@@ -133,18 +132,6 @@ inline void mDoAud_seStart(u32 i_sfxID, const Vec* i_sePos, u32 param_2, s8 i_re
-1.0f, -1.0f, 0);
}
#if TARGET_PC
inline void mDoAud_seStartMenu(u32 i_sfxID) {
if (!mDoAud_zelAudio_c::isInitFlag()) {
return;
}
if (!dusk::getSettings().audio.menuSounds.getValue()) {
return;
}
mDoAud_seStart(i_sfxID, nullptr, 0, 0);
}
#endif
inline void mDoAud_seStartLevel(u32 i_sfxID, const Vec* i_sePos, u32 param_2, s8 i_reverb) {
DUSK_AUDIO_SKIP()
Z2AudioMgr::getInterface()->seStartLevel(i_sfxID, i_sePos, param_2, i_reverb, 1.0f, 1.0f,
@@ -1,9 +1,9 @@
#ifndef J3DSTRUCT_H
#define J3DSTRUCT_H
#include <cstring>
#include <gx.h>
#include <mtx.h>
#include <mtx.h>
#include "global.h"
#include "JSystem/JMath/JMath.h"
@@ -11,7 +11,7 @@
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DLightInfo {
bool operator==(J3DLightInfo& other) const;
@@ -28,7 +28,7 @@ struct J3DLightInfo {
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DTextureSRTInfo {
// NOTE: Big endian when loaded from file!
@@ -79,7 +79,7 @@ enum J3DTexMtxMode {
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DTexMtxInfo {
bool operator==(J3DTexMtxInfo& other) const;
@@ -97,7 +97,7 @@ struct J3DTexMtxInfo {
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DIndTexMtxInfo {
J3DIndTexMtxInfo& operator=(J3DIndTexMtxInfo const&);
@@ -107,7 +107,7 @@ struct J3DIndTexMtxInfo {
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DFogInfo {
bool operator==(J3DFogInfo&) const;
@@ -126,7 +126,7 @@ struct J3DFogInfo {
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DNBTScaleInfo {
bool operator==(const J3DNBTScaleInfo& other) const;
@@ -153,7 +153,7 @@ struct J3DIndTexOrderInfo {
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DTevSwapModeInfo {
/* 0x0 */ u8 mRasSel;
@@ -164,7 +164,7 @@ struct J3DTevSwapModeInfo {
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DTevSwapModeTableInfo {
/* 0x0 */ u8 field_0x0;
@@ -175,7 +175,7 @@ struct J3DTevSwapModeTableInfo {
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DTevStageInfo {
/* 0x0 */ u8 field_0x0;
@@ -202,7 +202,7 @@ struct J3DTevStageInfo {
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DIndTevStageInfo {
/* 0x0 */ u8 mIndStage;
@@ -219,7 +219,7 @@ struct J3DIndTevStageInfo {
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DTexCoordInfo {
/* 0x0 */ u8 mTexGenType;
@@ -265,7 +265,7 @@ struct J3DBlendInfo {
/**
* @ingroup jsystem-j3d
*
*
*/
struct J3DTevOrderInfo {
void operator=(const J3DTevOrderInfo& other) {
@@ -556,8 +556,8 @@ void J3DModelLoader::readVertexData(const J3DVertexBlock& block, J3DVertexData&
if (attr == GX_VA_POS) {
// can be a little off due to 0x20 alignment, account for that
// u32 expect = ((data.mVtxNum * vertStride) + 0x1F) & ~0x1F;
// JUT_ASSERT(1234, expect == addrDiff);
u32 expect = ((data.mVtxNum * vertStride) + 0x1F) & ~0x1F;
JUT_ASSERT(1234, expect == addrDiff);
} else if (attr == GX_VA_NRM) {
data.mNrmNum = num;
} else if (attr == GX_VA_CLR0) {
+3 -17
View File
@@ -8,10 +8,6 @@
#include "JSystem/JUtility/JUTFader.h"
#include "JSystem/J2DGraph/J2DOrthoGraph.h"
#ifdef TARGET_PC
#include <algorithm>
#endif
JUTFader::JUTFader(int x, int y, int width, int height, JUtility::TColor pColor)
: mColor(pColor), mBox(x, y, x + width, y + height) {
mStatus = None;
@@ -67,24 +63,14 @@ void JUTFader::advance() {
void JUTFader::control() {
advance();
#ifndef TARGET_PC
// FRAME INTERP NOTE: Draw is called by JFWDisplay when interpolation is active
draw();
#endif
}
void JUTFader::draw() {
if (mColor.a != 0) {
#ifdef TARGET_PC
if (dusk::frame_interp::is_enabled() && mDuration != 0) {
const auto step = dusk::frame_interp::get_interpolation_step();
const auto progress = static_cast<f32>(mTimer) / static_cast<f32>(mDuration);
const auto timer = mTimer - 1 + step + progress;
auto alpha = timer / mDuration;
if (mStatus == FadeIn) {
alpha = 1.0f - alpha;
}
alpha = std::clamp(alpha, 0.0f, 1.0f);
mColor.a = static_cast<u8>(alpha * 255.0f);
}
#endif
J2DOrthoGraph orthograph;
orthograph.setColor(mColor);
orthograph.fillBox(mBox);
+3 -2
View File
@@ -66,11 +66,12 @@ Output APK:
You can pass command-line args through the activity intent:
```bash
adb shell am start -n dev.twilitrealm.dusk/.DuskActivity \
--es dusk_args "--backend vulkan"
adb shell am start -n com.twilitrealm.dusk/.DuskActivity \
--es dusk_args "'/sdcard/Download/The Legend of Zelda: Twilight Princess (USA).iso'"
```
Supported extras:
- `dusk_args`: single shell-like argument string
- `dusk_argv`: string-array argv
- `dusk_disc`: compatibility shortcut (single ISO path)
+3 -20
View File
@@ -2,22 +2,12 @@ plugins {
id 'com.android.application'
}
def duskRepoDir = rootProject.projectDir.parentFile.parentFile
def duskGeneratedAssetsDir = layout.buildDirectory.dir('generated/assets/dusk').get().asFile
def syncDuskAssets = tasks.register('syncDuskAssets', Sync) {
from(new File(duskRepoDir, 'res')) {
into 'res'
exclude '**/.DS_Store'
}
into duskGeneratedAssetsDir
}
android {
namespace 'dev.twilitrealm.dusk'
namespace 'com.twilitrealm.dusk'
compileSdk 36
defaultConfig {
applicationId 'dev.twilitrealm.dusk'
applicationId 'com.twilitrealm.dusk'
minSdk 26
targetSdk 36
versionCode 1
@@ -37,7 +27,7 @@ android {
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs']
assets.srcDirs = [duskGeneratedAssetsDir]
assets.srcDirs = ['../../assets']
}
}
@@ -58,10 +48,3 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
tasks.configureEach { task ->
if ((task.name.startsWith('merge') && task.name.endsWith('Assets')) ||
task.name.toLowerCase().contains('lint')) {
task.dependsOn(syncDuskAssets)
}
}
-2
View File
@@ -1,4 +1,2 @@
# Keep SDL activity and related JNI bridge methods.
-keep class org.libsdl.app.** { *; }
-keep class dev.twilitrealm.dusk.DuskHttpClient { *; }
-keep class dev.twilitrealm.dusk.DuskHttpClient$Response { *; }
@@ -10,7 +10,6 @@
<uses-feature android:name="android.hardware.type.pc" android:required="false" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
@@ -25,7 +24,7 @@
android:resource="@xml/game_mode_config" />
<activity
android:name="dev.twilitrealm.dusk.DuskActivity"
android:name="com.twilitrealm.dusk.DuskActivity"
android:alwaysRetainTaskState="true"
android:configChanges="layoutDirection|locale|grammaticalGender|fontScale|fontWeightAdjustment|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
android:exported="true"
@@ -1,28 +1,18 @@
package dev.twilitrealm.dusk;
package com.twilitrealm.dusk;
import android.app.ActionBar;
import android.content.ClipData;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.OpenableColumns;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import org.libsdl.app.SDLActivity;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class DuskActivity extends SDLActivity {
private static final String TAG = "DuskActivity";
private static String[] splitArgs(String raw) {
List<String> out = new ArrayList<>();
StringBuilder current = new StringBuilder();
@@ -71,46 +61,18 @@ public class DuskActivity extends SDLActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
hideSystemBars();
}
@Override
protected void onResume() {
super.onResume();
hideSystemBars();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
hideSystemBars();
}
}
private void hideSystemBars() {
Window window = getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.setDecorFitsSystemWindows(false);
WindowInsetsController ctrl = window.getDecorView().getWindowInsetsController();
if (ctrl != null) {
ctrl.setSystemBarsBehavior(
WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
ctrl.hide(WindowInsets.Type.systemBars());
}
} else {
View decorView = window.getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
getWindow().getDecorView().getWindowInsetsController().hide(WindowInsets.Type.systemBars());
}else {
View decorView = getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
// Remember that you should never show the action bar if the
// status bar is hidden, so hide that too if necessary.
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.hide();
}
actionBar.hide();
}
}
@@ -138,96 +100,12 @@ public class DuskActivity extends SDLActivity {
return splitArgs(trimmed);
}
}
String discPath = intent.getStringExtra("dusk_disc");
if (discPath != null && !discPath.isEmpty()) {
return new String[] { discPath };
}
}
return new String[0];
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
persistUriPermissions(data);
}
super.onActivityResult(requestCode, resultCode, data);
}
private void persistUriPermissions(Intent data) {
if (data == null) {
return;
}
int permissionFlags =
data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
if (permissionFlags == 0) {
return;
}
Uri uri = data.getData();
if (uri != null) {
persistUriPermission(uri, permissionFlags);
}
ClipData clipData = data.getClipData();
if (clipData == null) {
return;
}
for (int i = 0; i < clipData.getItemCount(); ++i) {
Uri itemUri = clipData.getItemAt(i).getUri();
if (itemUri != null) {
persistUriPermission(itemUri, permissionFlags);
}
}
}
private void persistUriPermission(Uri uri, int permissionFlags) {
if ((permissionFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
persistUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, "read");
}
if ((permissionFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
persistUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, "write");
}
}
private void persistUriPermission(Uri uri, int permissionFlag, String permissionName) {
try {
getContentResolver().takePersistableUriPermission(uri, permissionFlag);
} catch (SecurityException | IllegalArgumentException e) {
Log.w(TAG, "Unable to persist " + permissionName + " URI permission for " + uri, e);
}
}
public String getDisplayNameForUri(String uriString) {
if (uriString == null || uriString.isEmpty()) {
return "";
}
Uri uri = Uri.parse(uriString);
if ("content".equals(uri.getScheme())) {
try (Cursor cursor = getContentResolver().query(
uri, new String[] { OpenableColumns.DISPLAY_NAME }, null, null, null))
{
if (cursor != null && cursor.moveToFirst()) {
int displayNameColumn = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
if (displayNameColumn >= 0) {
String displayName = cursor.getString(displayNameColumn);
if (displayName != null && !displayName.isEmpty()) {
return displayName;
}
}
}
} catch (SecurityException | IllegalArgumentException e) {
Log.w(TAG, "Unable to query display name for " + uri, e);
}
} else if ("file".equals(uri.getScheme())) {
String path = uri.getPath();
if (path != null && !path.isEmpty()) {
String name = new File(path).getName();
if (!name.isEmpty()) {
return name;
}
}
}
String lastSegment = uri.getLastPathSegment();
return lastSegment != null ? lastSegment : "";
}
}
@@ -1,237 +0,0 @@
package dev.twilitrealm.dusk;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
public final class DuskHttpClient {
public static final int ERROR_NONE = 0;
public static final int ERROR_INVALID_URL = 1;
public static final int ERROR_UNSUPPORTED_SCHEME = 2;
public static final int ERROR_TIMEOUT = 3;
public static final int ERROR_TOO_LARGE = 4;
public static final int ERROR_NETWORK = 5;
private static final int MAX_REDIRECTS = 5;
public static final class Response {
public int error;
public String message;
public int statusCode;
public String[] headerNames;
public String[] headerValues;
public byte[] body;
Response(int error, String message, int statusCode, String[] headerNames,
String[] headerValues, byte[] body) {
this.error = error;
this.message = message;
this.statusCode = statusCode;
this.headerNames = headerNames != null ? headerNames : new String[0];
this.headerValues = headerValues != null ? headerValues : new String[0];
this.body = body != null ? body : new byte[0];
}
}
private DuskHttpClient() {
}
public static Response get(String url, String[] headerNames, String[] headerValues,
int timeoutMs, long maxBodyBytes) {
if (url == null || url.isEmpty()) {
return fail(ERROR_INVALID_URL, "URL is empty");
}
try {
URL currentUrl = new URL(url);
if (!isHttps(currentUrl)) {
return fail(ERROR_UNSUPPORTED_SCHEME, "Only https:// URLs are supported");
}
for (int redirect = 0; redirect <= MAX_REDIRECTS; ++redirect) {
HttpsURLConnection connection =
(HttpsURLConnection) currentUrl.openConnection();
try {
connection.setRequestMethod("GET");
connection.setConnectTimeout(timeoutMs);
connection.setReadTimeout(timeoutMs);
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(false);
applyHeaders(connection, headerNames, headerValues);
int statusCode = connection.getResponseCode();
if (isRedirect(statusCode)) {
String location = connection.getHeaderField("Location");
if (location == null || location.isEmpty()) {
return fail(ERROR_NETWORK, "Redirect response did not include Location",
statusCode, connection, new byte[0]);
}
URL nextUrl = new URL(currentUrl, location);
if (!isHttps(nextUrl)) {
return fail(ERROR_UNSUPPORTED_SCHEME,
"Only https:// redirects are supported", statusCode,
connection, new byte[0]);
}
currentUrl = nextUrl;
continue;
}
byte[] body = readBody(connection, statusCode, maxBodyBytes);
return success(statusCode, connection, body);
} catch (ResponseTooLargeException e) {
return fail(ERROR_TOO_LARGE, "Response body exceeded the configured limit",
safeStatusCode(connection), connection, e.partialBody);
} finally {
connection.disconnect();
}
}
return fail(ERROR_NETWORK, "Too many redirects");
} catch (MalformedURLException e) {
return fail(ERROR_INVALID_URL, "Failed to parse URL");
} catch (SocketTimeoutException e) {
return fail(ERROR_TIMEOUT, "Request timed out");
} catch (IOException e) {
String message = e.getMessage();
return fail(ERROR_NETWORK, message != null ? message : e.toString());
} catch (ClassCastException e) {
return fail(ERROR_UNSUPPORTED_SCHEME, "Only https:// URLs are supported");
}
}
private static void applyHeaders(HttpsURLConnection connection, String[] names,
String[] values) {
if (names == null || values == null) {
return;
}
int count = Math.min(names.length, values.length);
for (int i = 0; i < count; ++i) {
if (names[i] != null && values[i] != null) {
connection.setRequestProperty(names[i], values[i]);
}
}
}
private static boolean isHttps(URL url) {
return "https".equalsIgnoreCase(url.getProtocol());
}
private static boolean isRedirect(int statusCode) {
return statusCode == HttpURLConnection.HTTP_MOVED_PERM ||
statusCode == HttpURLConnection.HTTP_MOVED_TEMP ||
statusCode == HttpURLConnection.HTTP_SEE_OTHER ||
statusCode == 307 ||
statusCode == 308;
}
private static byte[] readBody(HttpsURLConnection connection, int statusCode,
long maxBodyBytes) throws IOException,
ResponseTooLargeException {
InputStream stream = statusCode >= HttpURLConnection.HTTP_BAD_REQUEST ?
connection.getErrorStream() : connection.getInputStream();
if (stream == null) {
return new byte[0];
}
try (InputStream bodyStream = stream;
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
byte[] buffer = new byte[8192];
long total = 0;
while (true) {
int read = bodyStream.read(buffer);
if (read < 0) {
return out.toByteArray();
}
if (read == 0) {
continue;
}
if (read > maxBodyBytes || total > maxBodyBytes - read) {
throw new ResponseTooLargeException(out.toByteArray());
}
out.write(buffer, 0, read);
total += read;
}
}
}
private static int safeStatusCode(HttpsURLConnection connection) {
try {
return connection.getResponseCode();
} catch (IOException e) {
return 0;
}
}
private static Response success(int statusCode, HttpsURLConnection connection, byte[] body) {
HeaderLists headers = readHeaders(connection);
return new Response(ERROR_NONE, "", statusCode, headers.names, headers.values, body);
}
private static Response fail(int error, String message) {
return new Response(error, message, 0, null, null, null);
}
private static Response fail(int error, String message, int statusCode,
HttpsURLConnection connection, byte[] body) {
HeaderLists headers = readHeaders(connection);
return new Response(error, message, statusCode, headers.names, headers.values, body);
}
private static HeaderLists readHeaders(HttpsURLConnection connection) {
List<String> names = new ArrayList<>();
List<String> values = new ArrayList<>();
Map<String, List<String>> headerFields = connection.getHeaderFields();
if (headerFields == null) {
return new HeaderLists(new String[0], new String[0]);
}
for (Map.Entry<String, List<String>> entry : headerFields.entrySet()) {
String name = entry.getKey();
if (name == null) {
continue;
}
List<String> entryValues = entry.getValue();
if (entryValues == null || entryValues.isEmpty()) {
names.add(name);
values.add("");
continue;
}
for (String value : entryValues) {
names.add(name);
values.add(value != null ? value : "");
}
}
return new HeaderLists(names.toArray(new String[0]), values.toArray(new String[0]));
}
private static final class HeaderLists {
final String[] names;
final String[] values;
HeaderLists(String[] names, String[] values) {
this.names = names;
this.values = values;
}
}
private static final class ResponseTooLargeException extends Exception {
final byte[] partialBody;
ResponseTooLargeException(byte[] partialBody) {
this.partialBody = partialBody;
}
}
}
@@ -256,7 +256,6 @@ public class HIDDeviceManager {
0x24c6, // PowerA
0x2c22, // Qanba
0x2dc8, // 8BitDo
0x37d7, // Flydigi
0x9886, // ASTRO Gaming
};
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 3;
private static final int SDL_MINOR_VERSION = 4;
private static final int SDL_MICRO_VERSION = 4;
private static final int SDL_MICRO_VERSION = 2;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
@@ -2032,7 +2032,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
try {
ParcelFileDescriptor pfd = mSingleton.getContentResolver().openFileDescriptor(Uri.parse(uri), mode);
return pfd != null ? pfd.detachFd() : -1;
} catch (FileNotFoundException | SecurityException e) {
} catch (FileNotFoundException e) {
e.printStackTrace();
return -1;
}
@@ -2227,3 +2227,4 @@ class SDLClipboardHandler implements
SDLActivity.onNativeClipboardChanged();
}
}
@@ -65,15 +65,17 @@ class SDLInputConnection extends BaseInputConnection
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
// Workaround to capture backspace key. Ref: http://stackoverflow.com/questions>/14560344/android-backspace-in-webview-baseinputconnection
// and https://bugzilla.libsdl.org/show_bug.cgi?id=2265
if (beforeLength > 0 && afterLength == 0) {
// backspace(s)
while (beforeLength-- > 0) {
nativeGenerateScancodeForUnichar('\b');
}
return true;
}
if (Build.VERSION.SDK_INT <= 29 /* Android 10.0 (Q) */) {
// Workaround to capture backspace key. Ref: http://stackoverflow.com/questions>/14560344/android-backspace-in-webview-baseinputconnection
// and https://bugzilla.libsdl.org/show_bug.cgi?id=2265
if (beforeLength > 0 && afterLength == 0) {
// backspace(s)
while (beforeLength-- > 0) {
nativeGenerateScancodeForUnichar('\b');
}
return true;
}
}
if (!super.deleteSurroundingText(beforeLength, afterLength)) {
return false;
@@ -35,8 +35,6 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
View.OnApplyWindowInsetsListener, View.OnKeyListener, View.OnTouchListener,
SensorEventListener, ScaleGestureDetector.OnScaleGestureListener {
private static native void auroraNativeSetSurfaceReady(boolean ready);
// Sensors
protected SensorManager mSensorManager;
protected Display mDisplay;
@@ -98,7 +96,6 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v("SDL", "surfaceCreated()");
auroraNativeSetSurfaceReady(false);
SDLActivity.onNativeSurfaceCreated();
}
@@ -106,7 +103,6 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v("SDL", "surfaceDestroyed()");
auroraNativeSetSurfaceReady(false);
// Transition to pause, if needed
SDLActivity.mNextNativeState = SDLActivity.NativeState.PAUSED;
@@ -196,7 +192,6 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
/* Surface is ready */
mIsSurfaceReady = true;
auroraNativeSetSurfaceReady(true);
SDLActivity.mNextNativeState = SDLActivity.NativeState.RESUMED;
SDLActivity.handleNativeState();
+16 -35
View File
@@ -14,22 +14,9 @@ if [[ -z "$ANDROID_NDK_VER" ]] && [[ -d "$ANDROID_HOME_DIR/ndk" ]]; then
fi
if [[ -n "$ANDROID_NDK_VER" ]]; then
case "$(uname -s)" in
Darwin) HOST_TAG="darwin-x86_64" ;;
Linux) HOST_TAG="linux-x86_64" ;;
*) HOST_TAG="" ;;
esac
PREBUILT_DIR="$ANDROID_HOME_DIR/ndk/$ANDROID_NDK_VER/toolchains/llvm/prebuilt"
if [[ -n "$HOST_TAG" && -x "$PREBUILT_DIR/$HOST_TAG/bin/llvm-strip" ]]; then
STRIP_TOOL="$PREBUILT_DIR/$HOST_TAG/bin/llvm-strip"
else
for candidate in "$PREBUILT_DIR"/*/bin/llvm-strip; do
if [[ -x "$candidate" ]]; then
STRIP_TOOL="$candidate"
break
fi
done
TOOLCHAIN_BIN="$ANDROID_HOME_DIR/ndk/$ANDROID_NDK_VER/toolchains/llvm/prebuilt/linux-x86_64/bin"
if [[ -x "$TOOLCHAIN_BIN/llvm-strip" ]]; then
STRIP_TOOL="$TOOLCHAIN_BIN/llvm-strip"
fi
fi
@@ -38,35 +25,29 @@ copy_lib() {
local src="$2"
local dst_dir="$APP_DIR/$abi"
local dst="$dst_dir/libmain.so"
local tmp="$dst_dir/.libmain.so.$$"
if [[ ! -f "$src" ]]; then
echo "Missing native library for $abi: $src" >&2
exit 1
fi
mkdir -p "$dst_dir"
cp -f "$src" "$tmp"
cp -f "$src" "$dst"
if [[ "$ANDROID_STAGE_STRIP" != "0" ]] && [[ -n "$STRIP_TOOL" ]]; then
"$STRIP_TOOL" --strip-unneeded "$tmp"
mv -f "$tmp" "$dst"
echo "Stripped and staged $src -> $dst"
"$STRIP_TOOL" --strip-debug "$dst"
echo "Staged and stripped $src -> $dst"
else
mv -f "$tmp" "$dst"
echo "Staged $src -> $dst (strip disabled or strip tool unavailable)"
fi
}
declare -A ABI_TO_LIB=(
["arm64-v8a"]="$ROOT_DIR/build/android-arm64/libmain.so"
["x86_64"]="$ROOT_DIR/build/android-x86_64/libmain.so"
)
# Drop any previously staged ABI directories to avoid stale APK contents.
rm -rf "$APP_DIR/x86" "$APP_DIR/arm64-v8a" "$APP_DIR/x86_64"
for abi in $ANDROID_STAGE_ABIS; do
case "$abi" in
arm64-v8a) src="$ROOT_DIR/build/android-arm64/libmain.so" ;;
x86_64) src="$ROOT_DIR/build/android-x86_64/libmain.so" ;;
*)
echo "Unsupported ABI '$abi'. Supported ABIs: arm64-v8a x86_64" >&2
exit 1
;;
esac
src="${ABI_TO_LIB[$abi]:-}"
if [[ -z "$src" ]]; then
echo "Unsupported ABI '$abi'. Supported ABIs: arm64-v8a x86_64" >&2
exit 1
fi
copy_lib "$abi" "$src"
done
Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1014 B

After

Width:  |  Height:  |  Size: 79 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 761 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 179 B

+1 -1
View File
@@ -6,4 +6,4 @@ Exec=dusk
Icon=dusk
Terminal=false
Type=Application
Categories=Game;
Categories=Graphics;3DGraphics;Game
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 95 KiB

+98 -242
View File
@@ -8,284 +8,140 @@ body {
height: 100%;
margin: 0;
padding: 0;
font-family: "Fira Sans";
font-weight: normal;
font-size: 20dp;
color: #E0DBC8;
font-family: "Fira Sans Condensed";
font-size: 24dp;
color: #FFFFFF;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
z-index: 1;
pointer-events: none;
}
fps,
toast {
position: absolute;
border: 1dp #92875B;
background-color: rgba(21, 22, 16, 80%);
}
toast {
top: 40dp;
right: 40dp;
.overlay-root {
width: 100%;
min-height: 45%;
display: flex;
flex-flow: column;
border-radius: 14dp;
overflow: hidden;
backdrop-filter: blur(5dp);
box-shadow: 0 0 15dp 3dp;
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
decorator: vertical-gradient(#00000000 #151610F2);
padding: 48dp 0 40dp 0;
filter: opacity(0);
transform: scale(0.9);
transform-origin: center;
transition: filter transform 0.2s cubic-in-out;
padding: 18dp 24dp;
gap: 8dp;
transition: filter 0.2s linear-in-out;
}
toast[open] {
.overlay-root[open] {
filter: opacity(1);
transform: scale(1);
}
/*toast:hover {
cursor: pointer;
background-color: rgba(61, 59, 36, 80%);
}
toast:active {
background-color: rgba(45, 43, 26, 80%);
}*/
toast heading {
display: flex;
gap: 18dp;
align-items: center;
font-family: "Fira Sans Condensed";
font-size: 18dp;
font-weight: bold;
text-transform: uppercase;
color: #92875B;
}
toast heading > span {
flex: 1 0 auto;
}
toast heading > row {
flex: 1 0 auto;
display: flex;
align-items: center;
gap: 4dp;
}
toast message {
display: flex;
flex-flow: column;
gap: 8dp;
}
toast message row {
display: flex;
}
toast message row.muted {
opacity: 0.5;
}
toast progress {
height: 4dp;
position: absolute;
left: 0;
bottom: 0;
.overlay {
width: 100%;
max-width: 1216dp;
margin-left: auto;
margin-right: auto;
display: flex;
flex-direction: column;
gap: 24dp;
padding: 0 32dp;
}
toast progress fill {
background-color: rgba(194, 164, 45, 80%);
@media (max-height: 800dp) {
.overlay-root {
min-height: 38%;
padding: 32dp 0 28dp 0;
}
.overlay {
gap: 16dp;
padding: 0 24dp;
}
}
toast.achievement {
border: 1dp #C2A42D;
}
toast.achievement heading {
color: #C2A42D;
}
toast.controller-warning {
top: auto;
right: auto;
bottom: 40dp;
left: 50%;
width: 440dp;
max-width: 90%;
transform: translateX(-50%) scale(0.9);
}
toast.controller-warning[open] {
transform: translateX(-50%) scale(1);
}
toast.controller-warning heading {
color: #C2A42D;
}
toast.menu-notification {
top: 40dp;
right: auto;
bottom: auto;
left: 50%;
max-width: 90%;
transform: translateX(-50%) scale(0.9);
}
toast.menu-notification[open] {
transform: translateX(-50%) scale(1);
}
toast.menu-notification message {
.header {
display: flex;
justify-content: space-between;
align-items: center;
text-align: center;
gap: 24dp;
}
toast.menu-notification message row {
align-items: center;
gap: 6dp;
.carousel-container {
flex: 1 1 auto;
display: flex;
justify-content: flex-end;
min-width: 0;
}
icon {
font-family: "Material Symbols Rounded";
font-weight: normal;
display: inline-block;
vertical-align: middle;
}
icon.arrow-forward {
width: 1.2em;
height: 1.2em;
font-size: 1.2em;
decorator: text("&#xe5c8;" center center);
}
icon.trophy {
width: 1.2em;
height: 1.2em;
font-size: 1.2em;
decorator: text("&#xe71a;" center center);
}
icon.controller {
width: 1.2em;
height: 1.2em;
font-size: 1.2em;
decorator: text("&#xf135;" center center);
}
icon.warning {
width: 1.2em;
height: 1.2em;
font-size: 1.2em;
decorator: text("&#xe002;" center center);
}
fps {
display: none;
z-index: 99;
.description {
font-size: 18dp;
font-weight: bold;
padding: 9dp 12dp;
border-radius: 7dp;
pointer-events: none;
white-space: nowrap;
line-height: 22dp;
color: rgba(255, 255, 255, 50%);
}
fps[open] {
.divider {
margin: 1dp 0;
border-top: 1dp rgba(217, 217, 217, 50%);
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
gap: 24dp;
}
footer-button {
display: block;
}
fps[corner=tl] {
top: 12dp;
left: 12dp;
}
fps[corner=tr] {
top: 12dp;
right: 12dp;
}
fps[corner=bl] {
bottom: 12dp;
left: 12dp;
}
fps[corner=br] {
bottom: 12dp;
right: 12dp;
}
logo {
position: absolute;
width: 100dp;
height: 100dp;
bottom: 40dp;
left: 40dp;
opacity: 0;
transition: opacity 0.5s linear-in-out;
}
logo[open] {
opacity: 0.65;
}
logo img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
filter: drop-shadow(#0008 0 0 14dp);
transform-origin: center;
max-width: 220dp;
border: 0;
padding: 0;
background-color: transparent;
font-family: "Fira Sans Condensed";
font-weight: bold;
font-size: 20dp;
line-height: 24dp;
text-transform: uppercase;
color: #FFFFFF;
opacity: 1;
cursor: pointer;
}
logo img.inner {
animation: 24s linear-in-out infinite logo-inner-spin;
footer-button.return {
text-align: left;
}
logo img.outer {
animation: 8s linear-in-out infinite logo-outer-spin;
footer-button.reset {
text-align: right;
}
@keyframes logo-inner-spin {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
.stepped-carousel {
display: flex;
align-items: center;
justify-content: center;
gap: 16dp;
width: auto;
min-width: 246dp;
padding: 0;
background-color: transparent;
font-family: "Fira Sans Condensed";
font-weight: bold;
}
@keyframes logo-outer-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
.stepped-carousel-value {
line-height: 29dp;
min-width: 166dp;
text-align: center;
white-space: nowrap;
opacity: 0.9;
}
@media (max-height: 640dp) {
toast {
top: 20dp;
right: 20dp;
}
toast.controller-warning {
bottom: 20dp;
}
toast.menu-notification {
top: 20dp;
}
.stepped-carousel-arrow {
width: 24dp;
height: 24dp;
min-width: 24dp;
padding: 0;
border: 0;
background-color: transparent;
opacity: 1;
cursor: pointer;
}
+20 -330
View File
@@ -9,44 +9,16 @@ body {
font-weight: normal;
font-size: 20dp;
color: #FFFFFF;
filter: opacity(0);
transition: filter 1s 0.2s linear-in-out;
z-index: -1;
}
.gradient {
position: absolute;
width: 100%;
height: 100%;
/* The color gradient from the Figma bands really badly. A fully black gradient does as well, but not as badly. */
decorator: horizontal-gradient(#000000FF #00000000);
}
body.mirrored .gradient {
decorator: horizontal-gradient(#00000000 #000000FF);
}
.background {
position: absolute;
width: 100%;
height: 100%;
background-color: #000000;
decorator: image(../prelaunch-bg.png cover left center);
opacity: 0;
transition: opacity 1s linear-in-out;
filter: opacity(0);
transition: filter 1s 0.1s linear-in-out;
}
body[open] {
filter: opacity(1);
}
body[open] .background {
opacity: 1;
}
body.disc-ready .background {
opacity: 0;
}
content {
display: block;
width: 100%;
@@ -62,7 +34,6 @@ content[open] {
menu {
position: absolute;
left: 96dp;
right: auto;
top: 50%;
transform: translateY(-50%);
/* Scale based on a reference screen width, 428/1216 */
@@ -75,11 +46,6 @@ menu {
gap: 48dp;
}
body.mirrored menu {
left: auto;
right: 96dp;
}
hero {
display: flex;
flex-direction: column;
@@ -88,10 +54,6 @@ hero {
gap: 8dp;
}
body.mirrored hero {
align-items: flex-end;
}
hero img {
width: 100%;
}
@@ -116,7 +78,6 @@ hero img {
display: flex;
flex-direction: column;
gap: 12dp;
align-items: flex-start;
}
#menu-list button {
@@ -124,7 +85,6 @@ hero img {
height: 54dp;
padding: 8dp 16dp;
border-radius: 8dp;
text-align: left;
text-transform: uppercase;
font-family: "Fira Sans Condensed";
font-size: 32dp;
@@ -134,14 +94,8 @@ hero img {
decorator: horizontal-gradient(#00000000 #00000000);
}
#menu-list button:disabled {
opacity: 0.75;
cursor: default;
decorator: horizontal-gradient(#00000000 #00000000);
}
#menu-list button.anim-done {
transition: decorator color opacity 0.1s linear-in-out;
transition: decorator color 0.1s linear-in-out;
}
#menu-list button:hover,
@@ -150,183 +104,52 @@ hero img {
decorator: horizontal-gradient(#FEE685FF #FEE68500);
}
body.mirrored #menu-list {
align-items: flex-end;
}
body.mirrored #menu-list button {
text-align: right;
}
body.mirrored #menu-list button:hover,
body.mirrored #menu-list button:focus-visible {
decorator: horizontal-gradient(#FEE68500 #FEE685FF);
}
disc-info {
disk-status {
position: absolute;
left: 96dp;
right: auto;
bottom: 72dp;
display: flex;
flex-direction: column;
gap: 12dp;
font-size: 24dp;
font-effect: glow(0dp 4dp 0dp 4dp black);
text-align: left;
}
body.mirrored disc-info {
left: auto;
right: 96dp;
text-align: right;
gap: 8dp;
}
version-info {
position: absolute;
right: 96dp;
left: auto;
bottom: 72dp;
display: flex;
flex-direction: column;
gap: 12dp;
text-align: right;
font-size: 24dp;
font-effect: glow(0dp 4dp 0dp 4dp black);
text-align: right;
}
body.mirrored version-info {
right: auto;
left: 96dp;
text-align: left;
}
#disc-status {
display: flex;
align-items: center;
gap: 8dp;
text-align: right;
}
#disc-status[status=good] {
.status,
.version {
font-size: 24dp;
}
.status,
.update {
color: #D8F999;
}
#disc-status[status=bad] {
.status[bad] {
color: #FFC9C9;
}
#disc-status[status=verifying] {
color: #FFFFFF;
}
#disc-status[status=mismatch] {
color: #FFD6A7;
}
#disc-status[status=unknown] {
color: rgba(224, 219, 200, 65%);
}
#disc-status[status=pending] {
color: #FEE685;
}
#disc-status icon {
display: none;
width: 24dp;
height: 24dp;
font-family: "Material Symbols Rounded";
font-weight: normal;
font-size: 24dp;
}
#disc-status[status] icon {
display: block;
}
#disc-status[status=good] icon {
decorator: text("&#xe5ca;" center center);
}
#disc-status[status=bad] icon {
decorator: text("&#xe5cd;" center center);
}
#disc-status[status=verifying] icon {
decorator: text("&#xe8b5;" center center);
}
#disc-status[status=mismatch] icon {
decorator: text("&#xe002;" center center);
}
#disc-status[status=unknown] icon {
decorator: text("&#xe887;" center center);
}
#disc-status[status=pending] icon {
decorator: text("&#xe863;" center center);
}
#disc-version {
font-size: 20dp;
}
/* TODO: Hidden until an actual update checker is introduced */
.update {
display: none;
color: #A6A09B;
align-items: center;
justify-content: flex-end;
gap: 8dp;
font-size: 20dp;
}
.update[state=checking],
.update[state=failed] {
display: block;
}
.update[state=available] {
display: flex;
}
#update-download {
display: none;
margin: 0dp;
padding: 0dp;
border-width: 0dp;
background-color: transparent;
color: #D8F999;
cursor: pointer;
text-transform: uppercase;
font-size: 16dp;
font-weight: bold;
decorator: horizontal-gradient(#00000000 #00000000);
cursor: pointer;
}
.update[state=available] #update-download {
display: flex;
align-items: center;
gap: 2dp;
}
#update-download icon {
display: block;
width: 18dp;
height: 18dp;
font-family: "Material Symbols Rounded";
font-weight: normal;
decorator: text("&#xe5c8;" center center);
}
.detail {
.detail,
.update span {
color: #A6A09B;
}
body.mirrored .update {
justify-content: flex-start;
}
/* Startup animation */
.intro-item {
opacity: 0;
@@ -362,136 +185,3 @@ body.animate-in .intro-item {
.delay-5 {
transition: opacity transform 0.3s 0.6s cubic-in-out;
}
/* Mobile layout */
@media (max-height: 640dp) {
.gradient {
decorator: horizontal-gradient(#00000000 #000000FF);
}
body.mirrored .gradient {
decorator: horizontal-gradient(#000000FF #00000000);
}
menu {
left: 32dp;
right: 32dp;
width: auto;
min-width: 0;
max-width: none;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 16dp;
}
body.mirrored menu {
left: 32dp;
right: 32dp;
flex-direction: row-reverse;
}
hero {
flex: 1 1 0;
min-width: 0;
max-width: 48%;
margin-left: 32dp;
}
body.mirrored hero {
align-items: flex-end;
}
hero img {
width: 100%;
}
#menu-list {
flex: 1 1 0;
min-width: 0;
max-width: 52%;
align-items: flex-end;
}
#menu-list button {
width: 100%;
max-width: 100%;
text-align: right;
}
#menu-list button:hover,
#menu-list button:focus-visible {
decorator: horizontal-gradient(#FEE68500 #FEE685FF);
}
body.mirrored #menu-list {
align-items: flex-start;
}
body.mirrored #menu-list button {
text-align: left;
}
body.mirrored #menu-list button:hover,
body.mirrored #menu-list button:focus-visible {
decorator: horizontal-gradient(#FEE685FF #FEE68500);
}
.eyebrow {
display: none;
}
disc-info {
right: 32dp;
left: auto;
bottom: 32dp;
top: auto;
text-align: right;
font-size: 16dp;
}
#disc-status {
justify-content: flex-end;
}
#disc-status icon {
font-size: 20dp;
}
#disc-version {
font-size: 16dp;
}
version-info {
right: 32dp;
left: auto;
bottom: auto;
top: 32dp;
text-align: right;
font-size: 16dp;
}
.update {
font-size: 16dp;
}
body.mirrored disc-info {
right: auto;
left: 32dp;
bottom: 32dp;
top: auto;
text-align: left;
}
body.mirrored version-info {
right: auto;
left: 32dp;
bottom: auto;
top: 32dp;
text-align: left;
}
body.mirrored #disc-status {
justify-content: flex-start;
}
}
-48
View File
@@ -1,21 +1,10 @@
tab-bar {
display: flex;
position: relative;
min-width: 0;
overflow: auto hidden;
clip: always;
text-transform: uppercase;
}
tab-bar scrollbarhorizontal,
tab-bar scrollbarhorizontal sliderarrowdec,
tab-bar scrollbarhorizontal sliderarrowinc,
tab-bar scrollbarhorizontal slidertrack,
tab-bar scrollbarhorizontal sliderbar {
width: 0;
height: 0;
}
tab-bar tab {
flex: 0 0 auto;
padding: 0 24dp;
@@ -42,40 +31,3 @@ tab-bar tab:hover {
tab-bar tab:active {
decorator: vertical-gradient(#c2a42d10 #c2a42d40);
}
tab-bar[closable] tab-end-spacer {
display: block;
flex: 0 0 64dp;
width: 64dp;
pointer-events: none;
}
tab-bar[closable] close {
display: block;
position: fixed;
top: 8dp;
right: 8dp;
z-index: 1;
width: 48dp;
height: 48dp;
font-family: "Material Symbols Rounded";
font-weight: normal;
font-size: 24dp;
color: rgba(224, 219, 200, 70%);
backdrop-filter: blur(2dp);
border-radius: 6dp;
decorator: text("&#xe5cd;" center center);
transition: color background-color 0.12s linear-in-out;
cursor: pointer;
}
tab-bar[closable] close:hover,
tab-bar[closable] close:focus-visible {
color: #fff;
background-color: rgba(194, 164, 45, 24%);
}
tab-bar[closable] close:active {
color: #fff;
background-color: rgba(194, 164, 45, 40%);
}
-147
View File
@@ -1,147 +0,0 @@
*, *:before, *:after {
box-sizing: border-box;
}
body {
overflow: visible;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
font-family: "Fira Sans Condensed";
font-size: 24dp;
color: #FFFFFF;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
}
.tuner-root {
width: 100%;
min-height: 45%;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
decorator: vertical-gradient(#00000000 #151610F2);
filter: opacity(0);
transition: filter 0.2s linear-in-out;
}
.tuner-root[open] {
filter: opacity(1);
}
.tuner {
width: 100%;
max-width: 1216dp;
margin-left: auto;
margin-right: auto;
display: flex;
flex-direction: column;
gap: 24dp;
padding: 48dp 64dp;
}
@media (max-height: 800dp) {
.tuner-root {
min-height: 38%;
}
.tuner {
gap: 16dp;
padding: 32dp 48dp;
}
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 24dp;
}
.carousel-container {
flex: 1 1 auto;
display: flex;
justify-content: flex-end;
min-width: 0;
}
.description {
font-size: 18dp;
line-height: 22dp;
color: rgba(255, 255, 255, 50%);
}
.divider {
margin: 1dp 0;
border-top: 1dp rgba(217, 217, 217, 50%);
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
gap: 24dp;
}
footer-button {
display: block;
width: 100%;
max-width: 220dp;
border: 0;
padding: 0;
background-color: transparent;
font-family: "Fira Sans Condensed";
font-weight: bold;
font-size: 20dp;
line-height: 24dp;
text-transform: uppercase;
color: #FFFFFF;
opacity: 1;
cursor: pointer;
}
footer-button.return {
text-align: left;
}
footer-button.reset {
text-align: right;
}
.stepped-carousel {
display: flex;
align-items: center;
justify-content: center;
gap: 16dp;
width: auto;
min-width: 246dp;
padding: 0;
background-color: transparent;
font-family: "Fira Sans Condensed";
font-weight: bold;
}
.stepped-carousel-value {
line-height: 29dp;
min-width: 166dp;
text-align: center;
white-space: nowrap;
opacity: 0.9;
}
.stepped-carousel-arrow {
width: 24dp;
height: 24dp;
min-width: 24dp;
padding: 0;
border: 0;
background-color: transparent;
opacity: 1;
cursor: pointer;
font-family: "Material Symbols Rounded";
font-weight: normal;
}
+4 -271
View File
@@ -3,7 +3,6 @@
}
body {
display: flex;
width: 100%;
height: 100%;
padding: 64dp;
@@ -17,9 +16,7 @@ body {
window {
display: flex;
flex-flow: column;
position: relative;
height: 100%;
width: 100%;
max-width: 1088dp;
max-height: 768dp;
margin: auto;
@@ -35,15 +32,6 @@ window {
transition: filter transform 0.2s cubic-in-out;
}
window.small {
height: auto;
width: auto;
}
window.modal {
max-width: 640dp;
}
window[open] {
filter: opacity(1);
transform: scale(1);
@@ -74,7 +62,7 @@ window tab-bar tab {
window content {
display: flex;
flex: 1 1 auto;
flex: 1 1 0;
min-width: 0;
min-height: 0;
overflow: hidden;
@@ -84,6 +72,7 @@ window content pane {
display: flex;
flex-flow: column;
flex: 1 1 0;
height: 100%;
min-width: 0;
min-height: 0;
padding: 24dp;
@@ -101,10 +90,6 @@ window content pane > * {
flex: 0 0 auto;
}
window content pane:last-of-type > div {
line-height: 1.625;
}
window content pane > spacer {
display: block;
/* Completes the 24dp bottom inset after the pane's 8dp gap. */
@@ -199,11 +184,6 @@ button:not(:disabled):active {
box-shadow: #C2A42D 0 0 0 2dp;
}
button.modal-btn {
flex: 1 1 0;
text-align: center;
}
select-button {
display: flex;
align-items: center;
@@ -245,262 +225,15 @@ select-button key {
font-weight: bold;
font-size: 18dp;
text-transform: uppercase;
flex: 0 1 auto;
flex: 1 0 auto;
}
select-button value {
flex: 1 1 auto;
text-align: right;
margin-left: auto;
font-size: 20dp;
}
select-button value.modified {
font-weight: bold;
}
select-button input {
text-align: right;
font-size: 20dp;
}
icon {
width: 1em;
height: 1em;
font-family: "Material Symbols Rounded";
font-weight: normal;
display: inline-block;
vertical-align: middle;
}
icon.warning {
decorator: text("&#xe002;" center center);
}
icon.error {
decorator: text("&#xe000;" center center);
}
icon.verifying {
decorator: text("&#xe8b5;" center center);
}
icon.celebration {
decorator: text("&#xea65;" center center);
}
icon.question-mark {
decorator: text("&#xeb8b;" center center);
}
.achievement-total {
position: absolute;
top: 0;
right: 64dp;
height: 64dp;
line-height: 64dp;
font-family: "Fira Sans Condensed";
font-weight: bold;
font-size: 16dp;
color: rgba(224, 219, 200, 55%);
pointer-events: none;
}
.achievement-row {
display: flex;
align-items: flex-start;
gap: 10dp;
padding: 12dp 0;
border-bottom: 1dp rgba(146, 135, 91, 30%);
}
.achievement-info {
display: block;
flex: 1 1 0;
min-width: 0;
}
.achievement-header {
display: flex;
align-items: center;
}
.achievement-name {
flex: 1;
font-weight: bold;
}
.achievement-name.unlocked {
color: #ffa826;
}
.achievement-badge {
font-size: 14dp;
opacity: 0.7;
}
.achievement-badge.unlocked {
color: #44cc55;
opacity: 1;
}
.achievement-badge.locked {
color: #cc4444;
opacity: 1;
}
.achievement-desc {
display: block;
color: rgba(224, 219, 200, 55%);
font-size: 16dp;
margin: 4dp 0 0 0;
}
.achievement-progress {
display: block;
font-size: 13dp;
color: rgba(224, 219, 200, 45%);
}
progress {
display: block;
width: 100%;
height: 6dp;
border-radius: 3dp;
background-color: rgba(255, 255, 255, 10%);
margin: 6dp 0 2dp 0;
}
progress.progress-done fill {
background-color: #44aa22;
border-radius: 3dp;
}
progress.progress-ongoing fill {
background-color: #2255bb;
border-radius: 3dp;
}
button.achievement-clear {
flex: 0 0 auto;
align-self: center;
font-size: 14dp;
padding: 2dp 8dp;
opacity: 0.45;
}
.preset-grid {
display: flex;
flex-direction: row;
gap: 20dp;
flex: 0 1 auto;
align-items: flex-start;
width: 100%;
}
.preset-col {
display: flex;
flex-flow: column;
gap: 12dp;
flex: 1 1 0;
}
.preset-desc {
display: block;
font-size: 16dp;
text-align: center;
}
.modal-dialog {
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 24dp;
gap: 20dp;
flex: 0 1 auto;
width: 100%;
text-align: left;
}
window.modal.danger {
border: 2dp #852221;
}
.modal-header {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 100%;
flex: 0 0 auto;
gap: 16dp;
}
.modal-header icon {
font-size: 24dp;
color: #92875B;
}
.modal-title {
display: block;
font-family: "Fira Sans Condensed";
font-weight: bold;
text-transform: uppercase;
font-size: 18dp;
color: #92875B;
flex: 1 1 auto;
}
window.modal.danger .modal-title,
window.modal.danger .modal-header icon {
color: #B3261E;
}
.modal-body {
display: block;
width: 100%;
flex: 0 1 auto;
min-width: 0;
font-size: 20dp;
color: #FFFFFF;
font-weight: normal;
}
.modal-body span.tip {
font-size: 14dp;
color: #92875B;
}
.verification-progress {
display: flex;
flex-direction: column;
gap: 10dp;
width: 100%;
}
.verification-file {
display: block;
font-size: 17dp;
color: #FFFFFF;
}
progress.verification-progress-bar {
height: 8dp;
margin: 2dp 0 0 0;
}
.verification-detail {
display: block;
font-size: 14dp;
color: rgba(224, 219, 200, 65%);
}
.modal-actions {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: stretch;
gap: 12dp;
width: 100%;
flex: 0 0 auto;
padding-top: 4dp;
}
-6
View File
@@ -2,7 +2,6 @@
#include "Z2AudioLib/Z2SoundInfo.h"
#if TARGET_PC
#include "dusk/audio/DuskDsp.hpp"
#include "dusk/settings.h"
#include <cmath>
#endif
#include "Z2AudioLib/Z2Calc.h"
@@ -706,11 +705,6 @@ f32 Z2Audience::calcRelPosVolume(const Vec& param_0, f32 param_1, int camID) {
f32 Z2Audience::calcRelPosPan(const Vec& param_0, int camID) {
Vec local_54 = param_0;
local_54.y = 0.0f;
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
local_54.x = -local_54.x;
}
#endif
f32 dVar6 = VECMag(&local_54);
if (dVar6 < 0.1f) {
-26
View File
@@ -51,7 +51,6 @@
#include "d/actor/d_a_ni.h"
#include "d/d_s_play.h"
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
#include "res/Object/Alink.h"
#include <cstring>
@@ -14788,10 +14787,6 @@ void daAlink_c::deleteEquipItem(BOOL i_isPlaySound, BOOL i_isDeleteKantera) {
mIronBallChainPos = NULL;
mIronBallChainAngle = NULL;
field_0x3848 = NULL;
#if TARGET_PC
mIBChainInterpPrevValid = false;
mIBChainInterpCurrValid = false;
#endif
field_0x0774 = NULL;
field_0x0778 = NULL;
mpHookshotLinChk = NULL;
@@ -19722,27 +19717,6 @@ int daAlink_c::draw() {
)
{
dComIfGd_getOpaListDark()->entryImm(mpHookChain, 0);
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation &&
mEquipItem == dItemNo_IRONBALL_e &&
mIronBallChainPos != NULL && mIronBallChainAngle != NULL)
{
if (mIBChainInterpCurrValid) {
memcpy(mIBChainInterpPrevPos, mIBChainInterpCurrPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpPrevAngle, mIBChainInterpCurrAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpPrevHandRoot = mIBChainInterpCurrHandRoot;
mIBChainInterpPrevValid = true;
}
memcpy(mIBChainInterpCurrPos, mIronBallChainPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpCurrAngle, mIronBallChainAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpCurrHandRoot = mHookshotTopPos;
mIBChainInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&ironBallChainInterpCallback, this);
}
#endif
}
}
-3
View File
@@ -205,9 +205,6 @@ int daAlink_c::setDamagePoint(int i_dmgAmount, BOOL i_checkZoraMag, BOOL i_setDm
dComIfGp_setItemLifeCount(-i_dmgAmount, 0);
}
#if TARGET_PC
dusk::AchievementSystem::get().signal("player_damaged");
#endif
onResetFlg1(RFLG1_DAMAGE_IMPACT);
mSwordUpTimer = 0;
+20 -16
View File
@@ -44,14 +44,16 @@ void daAlink_c::handleWolfHowl() {
bool canHowl = false;
if (mLinkAcch.ChkGroundHit() && !checkModeFlg(MODE_PLAYER_FLY) && !checkMagneBootsOn()) {
if (checkMidnaRide()) {
if ((checkWolf() &&
(checkModeFlg(MODE_UNK_1000) || dComIfGp_checkPlayerStatus0(0, 0x10))) ||
(!checkWolf() &&
(checkEventRun() || getMidnaActor()->checkMetamorphoseEnable()) &&
(checkModeFlg(4) || dComIfGp_checkPlayerStatus0(0, 0x10))))
{
canHowl = true;
if (!checkForestOldCentury()) {
if (checkMidnaRide()) {
if ((checkWolf() &&
(checkModeFlg(MODE_UNK_1000) || dComIfGp_checkPlayerStatus0(0, 0x10))) ||
(!checkWolf() &&
(checkEventRun() || getMidnaActor()->checkMetamorphoseEnable()) &&
(checkModeFlg(4) || dComIfGp_checkPlayerStatus0(0, 0x10))))
{
canHowl = true;
}
}
}
}
@@ -122,14 +124,16 @@ void daAlink_c::handleQuickTransform() {
bool canTransform = false;
if (mLinkAcch.ChkGroundHit() && !checkModeFlg(MODE_PLAYER_FLY) && !checkMagneBootsOn()) {
if (checkMidnaRide()) {
if ((checkWolf() &&
(checkModeFlg(MODE_UNK_1000) || dComIfGp_checkPlayerStatus0(0, 0x10))) ||
(!checkWolf() &&
(checkEventRun() || getMidnaActor()->checkMetamorphoseEnable()) &&
(checkModeFlg(4) || dComIfGp_checkPlayerStatus0(0, 0x10))))
{
canTransform = true;
if (!checkForestOldCentury()) {
if (checkMidnaRide()) {
if ((checkWolf() &&
(checkModeFlg(MODE_UNK_1000) || dComIfGp_checkPlayerStatus0(0, 0x10))) ||
(!checkWolf() &&
(checkEventRun() || getMidnaActor()->checkMetamorphoseEnable()) &&
(checkModeFlg(4) || dComIfGp_checkPlayerStatus0(0, 0x10))))
{
canTransform = true;
}
}
}
}
+6 -48
View File
@@ -8,8 +8,6 @@
#include "d/actor/d_a_obj_swhang.h"
#include "d/actor/d_a_obj_chandelier.h"
#include "JSystem/J3DGraphBase/J3DMaterial.h"
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
enum {
HS_MODE_NONE_e,
@@ -19,11 +17,11 @@ enum {
HS_MODE_RETURN_e = 6,
};
#if TARGET_PC
static const int HS_CHAIN_MAX_LINKS = 600;
#endif
void daAlink_c::hsChainShape_c::draw() {
if (dusk::getSettings().game.superClawshot) {
return;
}
static const int dummy = 0;
daAlink_c* alink = (daAlink_c*)getUserArea();
@@ -167,11 +165,7 @@ void daAlink_c::hsChainShape_c::draw() {
}
(void)0;
#if TARGET_PC
int chainLinks = 0;
#endif
while (maxDistanceF > var_f30 IF_DUSK(&&chainLinks < HS_CHAIN_MAX_LINKS)) {
while (maxDistanceF > var_f30) {
temp_f27 = var_f28 * cM_fsin(sp34 * var_f30);
s16 spC = cM_atan2s(temp_f27 - var_f26, 5.0f);
sp64.x = sp6C.x + spC;
@@ -193,10 +187,6 @@ void daAlink_c::hsChainShape_c::draw() {
var_f26 = temp_f27;
var_f30 += fabsf(cM_scos(spC)) * 5.0f;
#if TARGET_PC
chainLinks++;
#endif
}
}
@@ -212,11 +202,7 @@ void daAlink_c::hsChainShape_c::draw() {
sp98 = subChainTopPos;
sp6C.set(maxDistance.atan2sY_XZ(), maxDistance.atan2sX_Z(), 0);
#if TARGET_PC
int subChainLinks = 0;
#endif
while (maxDistanceF > var_f30 IF_DUSK(&&subChainLinks < HS_CHAIN_MAX_LINKS)) {
while (maxDistanceF > var_f30) {
mDoMtx_stack_c::copy(j3dSys.getViewMtx());
mDoMtx_stack_c::transM(sp98);
mDoMtx_stack_c::ZXYrotM(sp6C);
@@ -229,39 +215,11 @@ void daAlink_c::hsChainShape_c::draw() {
sp98 += maxDistance * 5.0f;
ANGLE_ADD_2(sp6C.z, 0x3000);
var_f30 += 5.0f;
#if TARGET_PC
subChainLinks++;
#endif
}
}
}
}
#if TARGET_PC
static void ironBallChainInterpCallback(bool isSimFrame, void* pUserWork) {
static_cast<daAlink_c*>(pUserWork)->onIronBallChainInterpCallback();
}
void daAlink_c::onIronBallChainInterpCallback() {
if (!mIBChainInterpPrevValid || !mIBChainInterpCurrValid) {
return;
}
if (mIronBallChainPos == NULL || mIronBallChainAngle == NULL) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
for (int i = 0; i < IRON_BALL_CHAIN_COUNT; i++) {
mIronBallChainPos[i] = mIBChainInterpPrevPos[i] + (mIBChainInterpCurrPos[i] - mIBChainInterpPrevPos[i]) * alpha;
mIronBallChainAngle[i].x = mIBChainInterpPrevAngle[i].x + (s16)((s16)(mIBChainInterpCurrAngle[i].x - mIBChainInterpPrevAngle[i].x) * alpha);
mIronBallChainAngle[i].y = mIBChainInterpPrevAngle[i].y + (s16)((s16)(mIBChainInterpCurrAngle[i].y - mIBChainInterpPrevAngle[i].y) * alpha);
mIronBallChainAngle[i].z = mIBChainInterpPrevAngle[i].z + (s16)((s16)(mIBChainInterpCurrAngle[i].z - mIBChainInterpPrevAngle[i].z) * alpha);
}
mHookshotTopPos = mIBChainInterpPrevHandRoot + (mIBChainInterpCurrHandRoot - mIBChainInterpPrevHandRoot) * alpha;
}
#endif
void daAlink_c::hookshotAtHitCallBack(dCcD_GObjInf* i_atObjInf, fopAc_ac_c* i_tgActor,
dCcD_GObjInf* i_tgObjInf) {
if (i_tgActor != NULL && fopAcM_IsActor(i_tgActor) && !i_tgObjInf->ChkTgHookshotThrough()) {
+2 -2
View File
@@ -2721,7 +2721,7 @@ int daAlink_c::procHorseRun() {
}
if (mProcVar2.field_0x300c == 0) {
set3DStatus(BUTTON_STATUS_HOLD_ON, IF_DUSK(dusk::getSettings().game.enableMirrorMode ? 1 :) 4);
set3DStatus(BUTTON_STATUS_HOLD_ON, 4);
}
} else {
if (mProcVar3.field_0x300e != 0) {
@@ -2731,7 +2731,7 @@ int daAlink_c::procHorseRun() {
}
if (mProcVar2.field_0x300c == 0) {
set3DStatus(BUTTON_STATUS_HOLD_ON, IF_DUSK(dusk::getSettings().game.enableMirrorMode ? 4 :) 1);
set3DStatus(BUTTON_STATUS_HOLD_ON, 1);
}
}
+1 -1
View File
@@ -41,7 +41,7 @@ void daAlink_c::setOriginalHeap(JKRExpHeap** i_ppheap, u32 i_size) {
u32 var_r28 = 0x10;
u32 size = ROUND(i_size, 16);
#if TARGET_PC
size *= 20; // Increase Link's heap size to prevent mods from crashing with higher-quality models.
size *= 2;
#endif
JKRHeap* parent = mDoExt_getGameHeap();
+1 -9
View File
@@ -17,9 +17,6 @@
#include "d/actor/d_a_e_pz.h"
#include "d/actor/d_a_horse.h"
#include "d/actor/d_a_hozelda.h"
#if TARGET_PC
#include "dusk/achievements.h"
#endif
int daArrow_c::createHeap() {
J3DModelData* model_data;
@@ -95,12 +92,7 @@ void daArrow_c::atHitCallBack(dCcD_GObjInf* i_atObjInf, fopAc_ac_c* i_tgActor, d
if (dist_to_hitpos < field_0x998) {
field_0x998 = dist_to_hitpos;
mHitAcID = fopAcM_GetID(i_tgActor);
#if TARGET_PC
if (fopAcM_GetGroup(i_tgActor) == fopAc_ENEMY_e &&
current.pos.abs(mStartPos) > 10000.0f) {
dusk::AchievementSystem::get().signal("arrow_hit_100m");
}
#endif
if (mArrowType == 1) {
field_0x9a8 = *hit_pos_p;
} else if (i_tgObjInf->ChkTgShield()) {
-6
View File
@@ -19,9 +19,6 @@
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
#if TARGET_PC
#include "dusk/achievements.h"
#endif
class daB_GND_HIO_c : public JORReflexible {
public:
@@ -1292,9 +1289,6 @@ static void b_gnd_g_wait(b_gnd_class* i_this) {
if (i_this->mMoveMode < 5 && i_this->mPlayerDistXZ < 600.0f) {
i_this->mMoveMode = 5;
i_this->field_0xc44[0] = 10;
#if TARGET_PC
dusk::AchievementSystem::get().signal("ganondorf_fishing_rod");
#endif
}
} else if (i_this->mMoveMode == 5) {
i_this->mMoveMode = 6;
-4
View File
@@ -254,11 +254,7 @@ BOOL daBdoor_c::checkArea() {
if (fabsf(vec.z) > 100.0f) {
return false;
}
#ifdef TARGET_PC
return (s16)((s32)fabs(current.angle.y - 0x7fff - player->current.angle.y) & 0xffff) <= 0x4000 ? 1 : 0;
#else
return (s16)fabs((f64)(current.angle.y - 0x7fff - player->current.angle.y)) <= 0x4000 ? 1 : 0;
#endif
}
BOOL daBdoor_c::checkFront() {
-4
View File
@@ -825,11 +825,7 @@ int daBdoorL1_c::checkArea() {
if (fabsf(local_48.z) > 100.0f) {
return 0;
}
#ifdef TARGET_PC
if ((s16)((s32)fabs(current.angle.y - 0x7fff - player->current.angle.y) & 0xffff) <= 0x4000) {
#else
if ((s16)fabs((f64)(current.angle.y - 0x7fff - player->current.angle.y)) <= 0x4000) {
#endif
return 1;
} else {
return 0;
-4
View File
@@ -348,11 +348,7 @@ int daBdoorL5_c::checkArea() {
if (fabsf(local_48.z) > 100.0f) {
return 0;
}
#ifdef TARGET_PC
if ((s16)((s32)fabs(current.angle.y - 0x7fff - player->current.angle.y) & 0xffff) <= 0x4000) {
#else
if ((s16)fabs((f64)(current.angle.y - 0x7fff - player->current.angle.y)) <= 0x4000) {
#endif
return 1;
} else {
return 0;
+1 -5
View File
@@ -1317,12 +1317,8 @@ int daMBdoorL1_c::checkArea() {
if (fabsf(local_48.z) > 110.0f) {
return 0;
}
#ifdef TARGET_PC
if ((s16)((s32)fabs(angle - 0x7fff - player->current.angle.y) & 0xffff) > 0x4000) {
#else
if ((s16)fabs((f64)(angle - 0x7fff - player->current.angle.y)) > 0x4000) {
#endif
return 0;
} else {
return 1;
-31
View File
@@ -10,10 +10,6 @@
#include "f_op/f_op_kankyo_mng.h"
#include "f_op/f_op_actor_enemy.h"
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#endif
class daE_DB_HIO_c : public JORReflexible {
public:
daE_DB_HIO_c();
@@ -70,22 +66,6 @@ static BOOL leaf_anm_init(e_db_class* i_this, int i_anm, f32 i_morf, u8 i_mode,
return FALSE;
}
#if TARGET_PC
static void daE_DB_interp_callback(bool isSimFrame, void* pUserWork) {
e_db_class* i_this = (e_db_class*)pUserWork;
if (!i_this->mStalkLineInterpPrevValid || !i_this->mStalkLineInterpCurrValid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
cXyz* dst = i_this->stalkLine.getPos(0);
for (int i = 0; i < 12; i++) {
const cXyz& p0 = i_this->mStalkLineInterpPrev[i];
const cXyz& p1 = i_this->mStalkLineInterpCurr[i];
dst[i] = p0 + (p1 - p0) * alpha;
}
}
#endif
static int daE_DB_Draw(e_db_class* i_this) {
fopAc_ac_c* actor = &i_this->enemy;
@@ -115,17 +95,6 @@ static int daE_DB_Draw(e_db_class* i_this) {
static GXColor l_color = {0x14, 0x0F, 0x00, 0xFF};
i_this->stalkLine.update(12, l_color, &actor->tevStr);
dComIfGd_set3DlineMat(&i_this->stalkLine);
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mStalkLineInterpCurrValid) {
memcpy(i_this->mStalkLineInterpPrev, i_this->mStalkLineInterpCurr, sizeof(i_this->mStalkLineInterpCurr));
i_this->mStalkLineInterpPrevValid = true;
}
memcpy(i_this->mStalkLineInterpCurr, i_this->stalkLine.getPos(0), 12 * sizeof(cXyz));
i_this->mStalkLineInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&daE_DB_interp_callback, i_this);
}
#endif
for (int i = 1; i < 11; i++) {
if (i_this->thornModel[i] != NULL) {
-31
View File
@@ -9,10 +9,6 @@
#include "d/actor/d_a_e_hb_leaf.h"
#include "f_op/f_op_actor_enemy.h"
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#endif
enum daE_HB_ACTION {
ACTION_STAY,
ACTION_APPEAR,
@@ -68,22 +64,6 @@ static BOOL leaf_anm_init(e_hb_class* i_this, int i_anm, f32 i_morf, u8 i_mode,
return FALSE;
}
#if TARGET_PC
static void daE_HB_interp_callback(bool isSimFrame, void* pUserWork) {
e_hb_class* i_this = (e_hb_class*)pUserWork;
if (!i_this->mStalkLineInterpPrevValid || !i_this->mStalkLineInterpCurrValid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
cXyz* dst = i_this->stalkLine.getPos(0);
for (int i = 0; i < 12; i++) {
const cXyz& p0 = i_this->mStalkLineInterpPrev[i];
const cXyz& p1 = i_this->mStalkLineInterpCurr[i];
dst[i] = p0 + (p1 - p0) * alpha;
}
}
#endif
static int daE_HB_Draw(e_hb_class* i_this) {
fopAc_ac_c* actor = &i_this->enemy;
@@ -102,17 +82,6 @@ static int daE_HB_Draw(e_hb_class* i_this) {
static GXColor l_color = {0x14, 0x0F, 0x00, 0xFF};
i_this->stalkLine.update(12, l_color, &actor->tevStr);
dComIfGd_set3DlineMat(&i_this->stalkLine);
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mStalkLineInterpCurrValid) {
memcpy(i_this->mStalkLineInterpPrev, i_this->mStalkLineInterpCurr, sizeof(i_this->mStalkLineInterpCurr));
i_this->mStalkLineInterpPrevValid = true;
}
memcpy(i_this->mStalkLineInterpCurr, i_this->stalkLine.getPos(0), 12 * sizeof(cXyz));
i_this->mStalkLineInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&daE_HB_interp_callback, i_this);
}
#endif
for (int i = 1; i < 11; i++) {
if (i_this->thornModel[i] != NULL) {
-6
View File
@@ -517,12 +517,6 @@ void daE_OctBg_c::core_fish_attack() {
field_0xbaf = cM_rndFX(80.0f) + 100.0f;
}
}
#if AVOID_UB
else {
in_f31 = cM_rndF(400.0f) + 80.0f;
field_0xbaf = cM_rndFX(80.0f) + 100.0f;
}
#endif
} else if (current.pos.abs(cStack_5c) < 400.0f) {
in_f31 = cM_rndF(50.0f) + 20.0f;
field_0xbaf = cM_rndFX(20.0f) + 40.0f;
-42
View File
@@ -14,8 +14,6 @@
#include "d/d_s_play.h"
#include "f_op/f_op_actor_enemy.h"
#include "f_op/f_op_camera_mng.h"
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
#include <cstring>
class daE_S1_HIO_c {
@@ -101,25 +99,6 @@ static void anm_init(e_s1_class* i_this, int i_resNo, f32 i_morf, u8 i_attr, f32
i_this->mAnm = i_resNo;
}
#if TARGET_PC
static void daE_S1_interp_callback(bool isSimFrame, void* pUserWork) {
e_s1_class* i_this = (e_s1_class*)pUserWork;
if (!i_this->mHairInterpPrevValid || !i_this->mHairInterpCurrValid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
for (int s = 0; s < e_s1_class::HAIR_STRAND_COUNT; s++) {
cXyz* dst = i_this->mLineMat.getPos(s);
for (int i = 0; i < e_s1_class::HAIR_SEGMENT_COUNT; i++) {
int idx = s * e_s1_class::HAIR_SEGMENT_COUNT + i;
const cXyz& p0 = i_this->mHairInterpPrev[idx];
const cXyz& p1 = i_this->mHairInterpCurr[idx];
dst[i] = p0 + (p1 - p0) * alpha;
}
}
}
#endif
static int daE_S1_Draw(e_s1_class* i_this) {
if (i_this->field_0x306c != 0) {
return 1;
@@ -153,22 +132,6 @@ static int daE_S1_Draw(e_s1_class* i_this) {
i_this->mLineMat.update(16, line_color, &i_this->tevStr);
dComIfGd_set3DlineMatDark(&i_this->mLineMat);
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mHairInterpCurrValid) {
memcpy(i_this->mHairInterpPrev, i_this->mHairInterpCurr, sizeof(i_this->mHairInterpCurr));
i_this->mHairInterpPrevValid = true;
}
for (int s = 0; s < e_s1_class::HAIR_STRAND_COUNT; s++) {
cXyz* src = i_this->mLineMat.getPos(s);
memcpy(&i_this->mHairInterpCurr[s * e_s1_class::HAIR_SEGMENT_COUNT], src,
e_s1_class::HAIR_SEGMENT_COUNT * sizeof(cXyz));
}
i_this->mHairInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&daE_S1_interp_callback, i_this);
}
#endif
dComIfGd_setList();
return 1;
}
@@ -2186,11 +2149,6 @@ static int daE_S1_Create(fopAc_ac_c* i_this) {
return cPhs_ERROR_e;
}
#if TARGET_PC
a_this->mHairInterpPrevValid = false;
a_this->mHairInterpCurrValid = false;
#endif
OS_REPORT("//////////////E_S1 SET 2 !!\n");
if (path_no != 0xFF) {
-9
View File
@@ -12,9 +12,6 @@
#include "c/c_damagereaction.h"
#include "f_op/f_op_actor_enemy.h"
#include "f_op/f_op_camera_mng.h"
#if TARGET_PC
#include "dusk/achievements.h"
#endif
class daE_TH_HIO_c : public JORReflexible {
public:
@@ -545,7 +542,6 @@ static void damage_check(e_th_class* i_this) {
if (i_this->field_0x6a4 == 0 && i_this->mAction != ACTION_SPIN) {
daPy_py_c* player = (daPy_py_c*)dComIfGp_getPlayer(0);
OS_REPORT("E_th HP1 %d\n", i_this->health);
s16 prevHealth = i_this->health;
cc_at_check(i_this, &i_this->mAtInfo);
OS_REPORT("E_th HP2 %d\n", i_this->health);
@@ -558,11 +554,6 @@ static void damage_check(e_th_class* i_this) {
dComIfGs_onOneZoneSwitch(3, -1);
if (i_this->health <= 0) {
#if TARGET_PC
if (prevHealth == i_this->field_0x560) {
dusk::AchievementSystem::get().signal("dark_hammer_one_hit");
}
#endif
i_this->mAction = ACTION_END;
i_this->mMode = 0;
i_this->field_0x68a |= 4;
-2
View File
@@ -5852,8 +5852,6 @@ static int daE_WB_Create(fopAc_ac_c* actor) {
daE_WB_Execute(i_this);
c_start = 0;
// Note: this flag makes king bulblin 1 instant die when set, as it only requires 2 laps
// for insta-kill to trigger.
if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[88])) {
i_this->lap_num = 1;
}
-31
View File
@@ -12,10 +12,6 @@
#include "d/d_cc_uty.h"
#include "f_op/f_op_actor_enemy.h"
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#endif
class daE_YD_HIO_c {
public:
daE_YD_HIO_c();
@@ -77,22 +73,6 @@ static s32 leaf_anm_init(e_yd_class* i_this, int param_1, f32 param_2, u8 param_
return false;
}
#if TARGET_PC
static void daE_YD_interp_callback(bool isSimFrame, void* pUserWork) {
e_yd_class* i_this = (e_yd_class*)pUserWork;
if (!i_this->mLineMatInterpPrevValid || !i_this->mLineMatInterpCurrValid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
cXyz* dst = i_this->mLineMat.getPos(0);
for (int i = 0; i < 12; i++) {
const cXyz& p0 = i_this->mLineMatInterpPrev[i];
const cXyz& p1 = i_this->mLineMatInterpCurr[i];
dst[i] = p0 + (p1 - p0) * alpha;
}
}
#endif
static s32 daE_YD_Draw(e_yd_class* i_this) {
static GXColor l_color = { 0x14, 0x0F, 0x00, 0xFF };
@@ -106,17 +86,6 @@ static s32 daE_YD_Draw(e_yd_class* i_this) {
i_this->mpMorf->entryDL();
i_this->mLineMat.update(12, l_color, &i_this->actor.tevStr);
dComIfGd_set3DlineMat(&i_this->mLineMat);
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mLineMatInterpCurrValid) {
memcpy(i_this->mLineMatInterpPrev, i_this->mLineMatInterpCurr, sizeof(i_this->mLineMatInterpCurr));
i_this->mLineMatInterpPrevValid = true;
}
memcpy(i_this->mLineMatInterpCurr, i_this->mLineMat.getPos(0), 12 * sizeof(cXyz));
i_this->mLineMatInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&daE_YD_interp_callback, i_this);
}
#endif
for (s32 i = 1; i < 11; i++) {
if (i_this->field_0x77c[i] != 0) {
g_env_light.setLightTevColorType_MAJI(i_this->field_0x77c[i], &i_this->actor.tevStr);
+1 -44
View File
@@ -10,8 +10,6 @@
#include "f_op/f_op_kankyo_mng.h"
#include "d/actor/d_a_obj_carry.h"
#include "Z2AudioLib/Z2Instances.h"
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
#include "f_op/f_op_actor_enemy.h"
enum E_yg_RES_File_ID {
@@ -136,26 +134,7 @@ static BOOL pl_check(e_yg_class* i_this, f32 i_dist) {
return FALSE;
}
#if TARGET_PC
static void daE_YG_interp_callback(bool isSimFrame, void* pUserWork) {
e_yg_class* i_this = (e_yg_class*)pUserWork;
if (!i_this->mTentacleInterpPrevValid || !i_this->mTentacleInterpCurrValid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
for (int s = 0; s < e_yg_class::TENTACLE_STRAND_COUNT; s++) {
cXyz* dst = i_this->mLineMat.getPos(s);
for (int i = 0; i < e_yg_class::TENTACLE_SEGMENT_COUNT; i++) {
int idx = s * e_yg_class::TENTACLE_SEGMENT_COUNT + i;
const cXyz& p0 = i_this->mTentacleInterpPrev[idx];
const cXyz& p1 = i_this->mTentacleInterpCurr[idx];
dst[i] = p0 + (p1 - p0) * alpha;
}
}
}
#endif
static int daE_YG_Draw(e_yg_class* i_this) {
static int daE_YG_Draw(e_yg_class* i_this) {
if (i_this->mDispFlag) {
return 1;
}
@@ -181,23 +160,6 @@ static int daE_YG_Draw(e_yg_class* i_this) {
color.a = 0xFF;
i_this->mLineMat.update(10, color, &actor->tevStr);
dComIfGd_set3DlineMatDark(&i_this->mLineMat);
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mTentacleInterpCurrValid) {
memcpy(i_this->mTentacleInterpPrev, i_this->mTentacleInterpCurr, sizeof(i_this->mTentacleInterpCurr));
i_this->mTentacleInterpPrevValid = true;
}
for (int s = 0; s < e_yg_class::TENTACLE_STRAND_COUNT; s++) {
cXyz* src = i_this->mLineMat.getPos(s);
memcpy(&i_this->mTentacleInterpCurr[s * e_yg_class::TENTACLE_SEGMENT_COUNT], src,
e_yg_class::TENTACLE_SEGMENT_COUNT * sizeof(cXyz));
}
i_this->mTentacleInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&daE_YG_interp_callback, i_this);
}
#endif
dComIfGd_setList();
return 1;
@@ -1416,11 +1378,6 @@ static cPhs_Step daE_YG_Create(fopAc_ac_c* actor) {
return cPhs_ERROR_e;
}
#if TARGET_PC
i_this->mTentacleInterpPrevValid = false;
i_this->mTentacleInterpCurrValid = false;
#endif
if (!hio_set) {
i_this->mIsFirstSpawn = 1;
hio_set = true;
-31
View File
@@ -12,10 +12,6 @@
#include "f_op/f_op_actor_enemy.h"
#include "f_op/f_op_kankyo_mng.h"
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#endif
class daE_YH_HIO_c : public JORReflexible {
public:
daE_YH_HIO_c();
@@ -89,22 +85,6 @@ static BOOL leaf_anm_init(e_yh_class* i_this, int param_2, f32 param_3, u8 param
return FALSE;
}
#if TARGET_PC
static void daE_YH_interp_callback(bool isSimFrame, void* pUserWork) {
e_yh_class* i_this = (e_yh_class*)pUserWork;
if (!i_this->mLineInterpPrevValid || !i_this->mLineInterpCurrValid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
cXyz* dst = i_this->mLine.getPos(0);
for (int i = 0; i < 12; i++) {
const cXyz& p0 = i_this->mLineInterpPrev[i];
const cXyz& p1 = i_this->mLineInterpCurr[i];
dst[i] = p0 + (p1 - p0) * alpha;
}
}
#endif
static int daE_YH_Draw(e_yh_class* i_this) {
fopAc_ac_c* a_this = (fopAc_ac_c*)i_this;
@@ -134,17 +114,6 @@ static int daE_YH_Draw(e_yh_class* i_this) {
i_this->mLine.update(12, l_color, &a_this->tevStr);
dComIfGd_set3DlineMat(&i_this->mLine);
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->mLineInterpCurrValid) {
memcpy(i_this->mLineInterpPrev, i_this->mLineInterpCurr, sizeof(i_this->mLineInterpCurr));
i_this->mLineInterpPrevValid = true;
}
memcpy(i_this->mLineInterpCurr, i_this->mLine.getPos(0), 12 * sizeof(cXyz));
i_this->mLineInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&daE_YH_interp_callback, i_this);
}
#endif
for (int i = 1; i < 11; i++) {
if (i_this->mModels[i] != NULL) {
-8
View File
@@ -3519,15 +3519,7 @@ void daKago_c::action() {
checkSizeBg();
setFlyEffect();
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
mStickX = -mDoCPd_c::getStickX3D(PAD_1);
} else {
mStickX = mDoCPd_c::getStickX3D(PAD_1);
}
#else
mStickX = mDoCPd_c::getStickX3D(PAD_1);
#endif
mStickY = mDoCPd_c::getStickY(PAD_1);
u8 prevIsWaterfall = mIsWaterfall;
+3 -5
View File
@@ -729,12 +729,10 @@ static void koro2_game(fshop_class* i_this) {
cLib_addCalcAngleS2(&i_this->field_0x4020.z, 0, 2, 0x200);
case 2:
#if TARGET_PC
if (dusk::gyro::rollgoal_gyro_enabled()) {
if (dusk::getSettings().game.enableGyroRollgoal) {
if (!dusk::gyro::get_sensor_keep_alive()) {
dusk::gyro::set_sensor_keep_alive(true);
}
} else if (dusk::gyro::get_sensor_keep_alive()) {
dusk::gyro::set_sensor_keep_alive(false);
}
#endif
@@ -755,7 +753,7 @@ static void koro2_game(fshop_class* i_this) {
old_stick_x = mDoCPd_c::getSubStickX(PAD_1);
cLib_addCalcAngleS2(&i_this->field_0x4060, i_this->field_0x4062, 4, 0x1000);
#if TARGET_PC
if (dusk::gyro::rollgoal_gyro_enabled()) {
if (dusk::getSettings().game.enableGyroRollgoal) {
dusk::gyro::rollgoalTick(true, i_this->field_0x4060);
}
#endif
@@ -793,7 +791,7 @@ static void koro2_game(fshop_class* i_this) {
s16 gyro_ax = 0;
s16 gyro_az = 0;
#if TARGET_PC
if (dusk::gyro::rollgoal_gyro_enabled()) {
if (dusk::getSettings().game.enableGyroRollgoal) {
dusk::gyro::rollgoalTableOffset(gyro_ax, gyro_az);
}
#endif
-36
View File
@@ -419,30 +419,9 @@ int daMidna_c::createHeap() {
return 0;
}
#if TARGET_PC
if (mpDemoFCTongueBmd != NULL) {
if(!daAlink_c::initDemoBck(&mpDemoFCTmpBck, "demo00_Midna_cut00_FC_tmp.bck")) {
return 0;
}
// Update Midna's eye maxLOD to prevent the eyes from disappearing
J3DTexture* tex = mpDemoFCTongueBmd->getModelData()->getTexture();
JUTNameTab* nametable = mpDemoFCTongueBmd->getModelData()->getTextureName();
if (tex != nullptr && nametable != nullptr) {
for (u16 i = 0; i < tex->getNum(); i++) {
const char* tex_name = nametable->getName(i);
if (tex_name != NULL && strcmp(tex_name, "midona_eyeball") == 0) {
ResTIMG* timg = tex->getResTIMG(i);
timg->maxLOD = 0;
}
}
}
}
#else
if (mpDemoFCTongueBmd != NULL && !daAlink_c::initDemoBck(&mpDemoFCTmpBck, "demo00_Midna_cut00_FC_tmp.bck")) {
return 0;
}
#endif
modelData =
(J3DModelData*)dComIfG_getObjectRes(dStage_roomControl_c::getDemoArcName(), "demo00_Midna_cut00_BD_tmp.bmd");
@@ -454,21 +433,6 @@ int daMidna_c::createHeap() {
modelData->getMaterialNodePointer(2)->setMaterialAnm(mpEyeMatAnm[0]);
modelData->getMaterialNodePointer(3)->setMaterialAnm(mpEyeMatAnm[1]);
#if TARGET_PC
// Update Midna's eye maxLOD to prevent the eyes from disappearing
J3DTexture* tex = modelData->getTexture();
JUTNameTab* nametable = modelData->getTextureName();
if (tex != nullptr && nametable != nullptr) {
for (u16 i = 0; i < tex->getNum(); i++) {
const char* tex_name = nametable->getName(i);
if (tex_name != NULL && strcmp(tex_name, "midona_eyeball") == 0) {
ResTIMG* timg = tex->getResTIMG(i);
timg->maxLOD = 0;
}
}
}
#endif
}
if (!initDemoModel(&mpDemoBDMaskBmd, "demo00_Midna_cut00_BD_mask.bmd", 0)) {
-2
View File
@@ -14,7 +14,6 @@
#include "d/actor/d_a_obj_automata.h"
#include "d/d_msg_object.h"
#include "d/actor/d_a_obj_scannon.h"
#include "dusk/frame_interpolation.h"
#include <cstring>
const daNpc_Toby_HIOParam daNpc_Toby_Param_c::m = {
@@ -1399,7 +1398,6 @@ int daNpc_Toby_c::cutRepairSCannon(int arg0) {
old.pos = current.pos;
setAngle(cM_deg2s(5.0f * f32(mPath.getArg0())));
mEventTimer = mPath.getArg2();
dusk::frame_interp::request_presentation_sync();
}
} else if (!mHide) {
mHide = 1;
-39
View File
@@ -10,8 +10,6 @@
#include "JSystem/J3DGraphBase/J3DDrawBuffer.h"
#include "SSystem/SComponent/c_math.h"
#include "d/d_com_inf_game.h"
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
#include <cstring>
static char const l_arcName[] = "Fchain";
@@ -67,10 +65,6 @@ int daObjFchain_c::create() {
local_48++;
}
rv = cPhs_COMPLEATE_e;
#if TARGET_PC
mChainInterpPrevValid = false;
mChainInterpCurrValid = false;
#endif
break;
}
return rv;
@@ -295,26 +289,6 @@ void daObjFchain_shape_c::draw() {
}
}
#if TARGET_PC
static void fchain_interp_callback(bool isSimFrame, void* pUserWork) {
static_cast<daObjFchain_c*>(pUserWork)->onInterpCallback();
}
void daObjFchain_c::onInterpCallback() {
if (!mChainInterpPrevValid || !mChainInterpCurrValid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
for (int i = 0; i < CHAIN_COUNT; i++) {
const cXyz& p0 = mChainInterpPrev[i];
const cXyz& p1 = mChainInterpCurr[i];
field_0x694[i] = p0 + (p1 - p0) * alpha;
}
}
#endif
int daObjFchain_c::draw() {
if (field_0x584 != 0) {
g_env_light.settingTevStruct(0, &current.pos, &tevStr);
@@ -323,19 +297,6 @@ int daObjFchain_c::draw() {
return 1;
}
dComIfGd_getOpaListDark()->entryImm(&mShape, 0);
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
if (mChainInterpCurrValid) {
memcpy(mChainInterpPrev, mChainInterpCurr, sizeof(mChainInterpCurr));
mChainInterpPrevValid = true;
}
memcpy(mChainInterpCurr, field_0x694, sizeof(mChainInterpCurr));
mChainInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&fchain_interp_callback, this);
}
#endif
}
return 1;
}
-51
View File
@@ -11,8 +11,6 @@
#include "d/d_bg_w.h"
#include "d/d_cc_uty.h"
#include "d/d_com_inf_game.h"
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
struct daObjKLift00_HIO_c : public mDoHIO_entry_c {
daObjKLift00_HIO_c();
@@ -297,11 +295,6 @@ int daObjKLift00_c::Create() {
if(getLock())
mStopSwingingFrames = 5;
#if TARGET_PC
mChainInterpPrevValid = false;
mChainInterpCurrValid = false;
#endif
return 1;
}
@@ -443,34 +436,6 @@ int daObjKLift00_c::Execute(Mtx** i_mtx) {
return 1;
}
#if TARGET_PC
static void klift00_interp_callback(bool isSimFrame, void* pUserWork) {
static_cast<daObjKLift00_c*>(pUserWork)->onInterpCallback();
}
void daObjKLift00_c::onInterpCallback() {
if (!mChainInterpPrevValid || !mChainInterpCurrValid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
cXyz savedPositions[64];
for (int i = 0; i < mNumChains; i++) {
savedPositions[i] = mChainPositions[i].mCurrentPos;
const cXyz& p0 = mChainInterpPrev[i];
const cXyz& p1 = mChainInterpCurr[i];
mChainPositions[i].mCurrentPos = p0 + (p1 - p0) * alpha;
}
setMtx();
for (int i = 0; i < mNumChains; i++) {
mChainPositions[i].mCurrentPos = savedPositions[i];
}
}
#endif
int daObjKLift00_c::Draw() {
g_env_light.settingTevStruct(16, &current.pos, &tevStr);
g_env_light.setLightTevColorType_MAJI(mpLiftPlatform, &tevStr);
@@ -492,22 +457,6 @@ int daObjKLift00_c::Draw() {
dComIfGd_setList();
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
if (mChainInterpCurrValid) {
memcpy(mChainInterpPrev, mChainInterpCurr, mNumChains * sizeof(cXyz));
mChainInterpPrevValid = true;
}
for (int i = 0; i < mNumChains; i++) {
mChainInterpCurr[i] = mChainPositions[i].mCurrentPos;
}
mChainInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&klift00_interp_callback, this);
}
#endif
return 1;
}
-9
View File
@@ -12,10 +12,6 @@
#include "SSystem/SComponent/c_counter.h"
#include <cstring>
#if TARGET_PC
#include "dusk/settings.h"
#endif
#define DRAW_TYPE_YELLOW 0
#define DRAW_TYPE_RED 1
@@ -1426,11 +1422,6 @@ int dAttention_c::Run() {
}
void dAttention_c::Draw() {
#if TARGET_PC
if (dusk::getSettings().game.recordingMode) {
return;
}
#endif
if (mAttParam.CheckFlag(dAttParam_c::EFlag_ARROW_OFF)) {
draw[0].field_0x173 = 3;
draw[1].field_0x173 = 3;
+12 -205
View File
@@ -31,7 +31,6 @@
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#include "dusk/logging.h"
#include "imgui.h"
#endif
namespace {
@@ -1041,11 +1040,6 @@ void dCamera_c::debugDrawInit() {
bool dCamera_c::Run() {
#if TARGET_PC
ResetView();
if (executeDebugFlyCam()) {
mFrameCounter++;
mTicks++;
return true;
}
#endif
daAlink_c* link = daAlink_getAlinkActorClass();
@@ -7480,155 +7474,7 @@ bool dCamera_c::test2Camera(s32 param_0) {
return false;
}
static constexpr f32 FLYCAM_SPEED = 0.5f;
static constexpr f32 FLYCAM_FAST_SPEED = 4.0f;
static constexpr f32 FLYCAM_ROTATION_SPEED = 0.002f;
static constexpr f32 FLYCAM_TRIGGER_DEADZONE = 20.0f;
static constexpr s16 FLYCAM_ROLL_SPEED = 256;
static ImVec2 sFlyCamLastMousePos = {-1.f, -1.f};
#if TARGET_PC
bool dCamera_c::executeDebugFlyCam() {
if (!dusk::getSettings().game.debugFlyCam) {
if (mDebugFlyCam.initialized) {
deactivateDebugFlyCam();
}
sFlyCamLastMousePos = {-1.f, -1.f};
return false;
}
dEvt_control_c* event = dComIfGp_getEvent();
if (event == nullptr) {
return false;
}
if (!mDebugFlyCam.initialized && (event->mEventStatus != 0 || dComIfGp_isPauseFlag())) {
dusk::getSettings().game.debugFlyCam.setValue(false);
return false;
}
if (!mDebugFlyCam.initialized) {
mDebugFlyCam.savedCenter = mCenter;
mDebugFlyCam.savedEye = mEye;
mDebugFlyCam.savedFovy = mFovy;
mDebugFlyCam.savedBank = mBank;
f32 dx = mCenter.x - mEye.x;
f32 dy = mCenter.y - mEye.y;
f32 dz = mCenter.z - mEye.z;
mDebugFlyCam.yaw = atan2f(dz, dx);
f32 horizontal = sqrtf(dx * dx + dz * dz);
mDebugFlyCam.pitch = atan2f(dy, horizontal);
mDebugFlyCam.initialized = true;
}
if (dusk::getSettings().game.debugFlyCamLockEvents) {
event->mEventStatus = 1;
dComIfGp_getEventManager().setCameraPlay(1);
} else {
if (event->mEventStatus != 0) {
event->mEventStatus = 0;
}
dComIfGp_getEventManager().setCameraPlay(0);
}
f32 stickY = 0.f;
f32 stickX = 0.f;
f32 cStickY = 0.f;
f32 cStickX = 0.f;
f32 trigL = 0.f;
f32 trigR = 0.f;
f32 rollInput = 0.f;
bool fast = false;
if (dusk::getSettings().game.debugFlyCamLockEvents) {
interface_of_controller_pad& pad = mDoCPd_c::getCpadInfo(0);
stickY = pad.mMainStickPosY * 72.0f;
stickX = pad.mMainStickPosX * 72.0f;
cStickY = pad.mCStickPosY * 59.0f;
cStickX = pad.mCStickPosX * 59.0f;
trigL = pad.mTriggerLeft * 150.0f;
trigR = pad.mTriggerRight * 150.0f;
fast = mDoCPd_c::getHoldZ(PAD_1);
if (mDoCPd_c::getHoldY(PAD_1)) rollInput -= 1.f;
if (mDoCPd_c::getHoldX(PAD_1)) rollInput += 1.f;
}
{
ImGuiIO& io = ImGui::GetIO();
if (!io.WantCaptureKeyboard) {
f32 kbX = 0.0f, kbY = 0.0f;
if (ImGui::IsKeyDown(ImGuiKey_W) || ImGui::IsKeyDown(ImGuiKey_UpArrow)) kbY += 1.f;
if (ImGui::IsKeyDown(ImGuiKey_S) || ImGui::IsKeyDown(ImGuiKey_DownArrow)) kbY -= 1.f;
if (ImGui::IsKeyDown(ImGuiKey_D) || ImGui::IsKeyDown(ImGuiKey_RightArrow)) kbX += 1.f;
if (ImGui::IsKeyDown(ImGuiKey_A) || ImGui::IsKeyDown(ImGuiKey_LeftArrow)) kbX -= 1.f;
f32 len = sqrtf(kbX * kbX + kbY * kbY);
if (len > 1.f) { kbX /= len; kbY /= len; }
stickX += kbX * 72.0f;
stickY += kbY * 72.0f;
if (ImGui::IsKeyDown(ImGuiKey_Space)) trigR += 150.0f;
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) trigL += 150.0f;
if (ImGui::IsKeyDown(ImGuiKey_LeftShift)) fast = true;
if (ImGui::IsKeyDown(ImGuiKey_Q)) rollInput -= 1.0f;
if (ImGui::IsKeyDown(ImGuiKey_E)) rollInput += 1.0f;
}
bool mouseValid = !io.WantCaptureMouse && io.MousePos.x >= 0.0f && io.MousePos.y >= 0.0f;
if (mouseValid && sFlyCamLastMousePos.x >= 0.0f) {
cStickX -= (io.MousePos.x - sFlyCamLastMousePos.x) * 2.0f;
cStickY -= (io.MousePos.y - sFlyCamLastMousePos.y) * 2.0f;
}
sFlyCamLastMousePos = mouseValid ? io.MousePos : ImVec2{-1.0f, -1.0f};
}
f32 verticalDisp = 0.0f;
if (trigR >= FLYCAM_TRIGGER_DEADZONE) {
verticalDisp += trigR;
}
if (trigL >= FLYCAM_TRIGGER_DEADZONE) {
verticalDisp -= trigL;
}
f32 moveDy = stickY * sinf(mDebugFlyCam.pitch) + verticalDisp;
f32 moveDx = stickY * cosf(mDebugFlyCam.yaw) * cosf(mDebugFlyCam.pitch) - stickX * sinf(mDebugFlyCam.yaw);
f32 moveDz = stickY * sinf(mDebugFlyCam.yaw) * cosf(mDebugFlyCam.pitch) + stickX * cosf(mDebugFlyCam.yaw);
f32 speed = fast ? FLYCAM_FAST_SPEED : FLYCAM_SPEED;
mEye.x += speed * moveDx;
mEye.y += speed * moveDy;
mEye.z += speed * moveDz;
static constexpr f32 FLYCAM_TARGET_DIST = 100.0f;
mCenter.x = mEye.x + cosf(mDebugFlyCam.yaw) * cosf(mDebugFlyCam.pitch) * FLYCAM_TARGET_DIST;
mCenter.z = mEye.z + sinf(mDebugFlyCam.yaw) * cosf(mDebugFlyCam.pitch) * FLYCAM_TARGET_DIST;
mCenter.y = mEye.y + sinf(mDebugFlyCam.pitch) * FLYCAM_TARGET_DIST;
mBank = mBank + static_cast<s16>(rollInput * FLYCAM_ROLL_SPEED * (fast ? FLYCAM_FAST_SPEED / FLYCAM_SPEED : 1.f));
Reset(mCenter, mEye);
f32 yawInput = dusk::getSettings().game.invertCameraXAxis ? cStickX : -cStickX;
mDebugFlyCam.yaw += yawInput * FLYCAM_ROTATION_SPEED;
mDebugFlyCam.yaw = fmodf(mDebugFlyCam.yaw + 2.0f * (f32)M_PI, 2.0f * (f32)M_PI);
f32 maxPitch = (f32)M_PI / 2.0f - 0.1f;
f32 minPitch = -(f32)M_PI / 2.0f + 0.1f;
mDebugFlyCam.pitch = std::clamp(mDebugFlyCam.pitch + cStickY * FLYCAM_ROTATION_SPEED, minPitch, maxPitch);
return true;
}
void dCamera_c::deactivateDebugFlyCam() {
Reset(mDebugFlyCam.savedCenter, mDebugFlyCam.savedEye, mDebugFlyCam.savedFovy, mDebugFlyCam.savedBank.Val());
dEvt_control_c* event = dComIfGp_getEvent();
if (event != nullptr && event->mEventStatus != 0) {
event->mEventStatus = 0;
}
dComIfGp_getEventManager().setCameraPlay(0);
mDebugFlyCam.initialized = false;
}
bool dCamera_c::freeCamera() {
if (dusk::getSettings().game.freeCamera && mGear == 1) {
mGear = 0;
@@ -11262,26 +11108,6 @@ static int camera_execute(camera_process_class* i_this) {
return 1;
}
#ifdef TARGET_PC
void set_ar_corrected_trim(dDlst_window_c* window, float trim_height) {
const auto viewport = window->getViewPort();
if (mDoGph_gInf_c::isWideZoom()) {
const auto target_ar = FB_WIDTH / (FB_HEIGHT - trim_height * 2.0f);
const auto current_ar = mDoGph_gInf_c::m_safeWidthF / mDoGph_gInf_c::m_safeHeightF;
if (current_ar < target_ar) {
trim_height = FB_HEIGHT / 2.0f * (1.0f - current_ar / target_ar);
} else {
trim_height = 0.0f;
}
}
trim_height *= viewport->height / FB_HEIGHT;
window->setScissor(0.0f, trim_height, viewport->width, viewport->height - trim_height * 2.0f);
}
#endif
static int camera_draw(camera_process_class* i_this) {
camera_class* a_this = (camera_class*)i_this;
dCamera_c* body = &i_this->mCamera;
@@ -11335,40 +11161,21 @@ static int camera_draw(camera_process_class* i_this) {
#endif
#if TARGET_PC
set_ar_corrected_trim(window, body->TrimHeight());
auto trim_height = body->TrimHeight();
if (dusk::getSettings().game.enableFrameInterpolation) {
dusk::frame_interp::add_interpolation_callback([](bool _, void* pUserWork) {
const auto i_this = static_cast<camera_process_class*>(pUserWork);
const auto camera = &i_this->mCamera;
if (mDoGph_gInf_c::isWideZoom()) {
const auto target_ar = FB_WIDTH / (FB_HEIGHT - trim_height * 2.0f);
const auto current_ar = mDoGph_gInf_c::m_safeWidthF / mDoGph_gInf_c::m_safeHeightF;
const auto trim_size = camera->mTrimSize;
if (camera->mCurState != 2 && trim_size >= 0 && trim_size <= 3) {
// derive trim height at previous tick using current camera state
f32 target;
switch (trim_size) {
case 0:
target = 0.0f;
break;
case 1:
target = camera->mCamSetup.VistaTrimHeight();
break;
case 2:
case 3:
target = camera->mCamSetup.CinemaScopeTrimHeight();
break;
}
const auto step = dusk::frame_interp::get_interpolation_step();
const auto cur = camera->TrimHeight();
const auto prev = (4.0f * cur - target) / 3.0f;
const auto trim_height = prev + (cur - prev) * step;
set_ar_corrected_trim(get_window((camera_class*)i_this), trim_height);
}
}, i_this);
if (current_ar < target_ar) {
trim_height = FB_HEIGHT / 2.0f * (1.0f - current_ar / target_ar);
} else {
trim_height = 0.0f;
}
}
trim_height *= viewport->height / FB_HEIGHT;
window->setScissor(0.0f, trim_height, viewport->width, viewport->height - trim_height * 2.0f);
#else
int trim_height = body->TrimHeight();
-8
View File
@@ -13,9 +13,6 @@
#include "d/d_s_play.h"
#include "d/d_com_inf_game.h"
#include "f_op/f_op_actor_mng.h"
#if TARGET_PC
#include "dusk/achievements.h"
#endif
static int plCutLRC[58] = {
0, //
@@ -437,11 +434,6 @@ fopAc_ac_c* cc_at_check(fopAc_ac_c* i_enemy, dCcU_AtInfo* i_AtInfo) {
if (i_AtInfo->mAttackPower != 0 && i_enemy->health <= 0) {
i_AtInfo->mHitStatus = 2;
i_enemy->health = 0;
#if TARGET_PC
if (fopAcM_GetGroup(i_enemy) == fopAc_ENEMY_e) {
dusk::AchievementSystem::get().signal("enemy_killed");
}
#endif
}
int uvar8;
-73
View File
@@ -11,62 +11,6 @@
#include "JSystem/JGadget/define.h"
#include <cstring>
#include "dusk/logging.h"
#if TARGET_PC
#include "dusk/ui/ui.hpp"
namespace {
static int sJaiSkip = -1;
static JSUList<JAIStream>* get_stream_list() {
return Z2GetSoundMgr()->getStreamMgr()->getStreamList();
}
static int get_stream_count(JSUList<JAIStream>* list) {
int i = 0;
for (JSULink<JAIStream>* l = list != nullptr ? list->getFirst() : nullptr; l != nullptr;
l = l->getNext()) {
i++;
}
return i;
}
static void pause_stream(int skip_first, bool paused) {
int i = 0;
JSUList<JAIStream>* list = get_stream_list();
for (JSULink<JAIStream>* l = list->getFirst(); l != nullptr; l = l->getNext(), ++i) {
if (i >= skip_first) {
l->getObject()->pause(paused);
}
}
}
static void pause_streams(int skip_first) {
if (!dusk::ui::is_prelaunch_open()) {
return;
}
JSUList<JAIStream>* list = get_stream_list();
if (list == nullptr || get_stream_count(list) <= skip_first) {
return;
}
pause_stream(skip_first, true);
sJaiSkip = skip_first;
}
static void unpause_streams(bool require_prelaunch_hidden) {
if (sJaiSkip < 0) {
return;
}
if (require_prelaunch_hidden && dusk::ui::is_prelaunch_open()) {
return;
}
pause_stream(sJaiSkip, false);
sJaiSkip = -1;
}
} // namespace
#endif
s16 dDemo_c::m_branchId = -1;
namespace {
@@ -1062,16 +1006,7 @@ int dDemo_c::start(u8 const* p_data, cXyz* p_translation, f32 rotationY) {
m_control->setSuspend(0);
}
#if TARGET_PC
const int existing_streams = get_stream_count(get_stream_list());
#endif
m_control->forward(0);
#if TARGET_PC
pause_streams(existing_streams);
#endif
m_translation = p_translation;
if (m_translation != NULL) {
@@ -1099,10 +1034,6 @@ static void dummyString2() {
void dDemo_c::end() {
JUT_ASSERT(1956, m_system != NULL);
#if TARGET_PC
unpause_streams(false);
#endif
m_control->destroyObject_all();
m_object->remove();
m_data = NULL;
@@ -1123,10 +1054,6 @@ void dDemo_c::branch() {
int dDemo_c::update() {
JUT_ASSERT(2064, m_system != NULL);
#if TARGET_PC
unpause_streams(true);
#endif
if (m_data == NULL) {
if (m_branchData == NULL) {
return 0;
+4 -4
View File
@@ -1595,7 +1595,7 @@ void dMap_c::_move(f32 i_centerX, f32 i_centerZ, int i_roomNo, f32 param_3) {
calcMapCmPerTexel(field_0x80, &field_0x58);
getPack(field_0x80, &mPackX, &mPackZ);
mCenterX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -mPackX :) mPackX;
mCenterX += mPackX;
mCenterZ -= mPackZ;
mCenterX += field_0x64;
mCenterZ += mPackPlusZ;
@@ -1657,7 +1657,7 @@ void dMap_c::_move(f32 i_centerX, f32 i_centerZ, int i_roomNo, f32 param_3) {
calcMapCmPerTexel(field_0x80, &field_0x58);
getPack(field_0x80, &mPackX, &mPackZ);
mCenterX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -mPackX :) mPackX;
mCenterX += mPackX;
mCenterZ -= mPackZ;
}
break;
@@ -1737,7 +1737,7 @@ void dMap_c::_move(f32 i_centerX, f32 i_centerZ, int i_roomNo, f32 param_3) {
calcMapCmPerTexel(field_0x80, &field_0x58);
getPack(field_0x80, &mPackX, &mPackZ);
mCenterX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -mPackX :) mPackX;
mCenterX += mPackX;
mCenterZ -= mPackZ;
field_0x8f = 4;
#if DEBUG
@@ -1829,7 +1829,7 @@ void dMap_c::_move(f32 i_centerX, f32 i_centerZ, int i_roomNo, f32 param_3) {
sp14 += temp_f31_2 * (spC - sp14);
sp10 += temp_f31_2 * (sp8 - sp10);
mCenterX += IF_DUSK(dusk::getSettings().game.enableMirrorMode ? -sp14 :) sp14;
mCenterX += sp14;
mCenterZ -= sp10;
break;
}
+31 -121
View File
@@ -15,47 +15,13 @@
#include <cstring>
#ifdef TARGET_PC
#include <span>
#include <numbers>
#include <array>
constexpr u16 kMapResolutionMultiplier = 4;
constexpr u16 kMapImageSide = 16 * kMapResolutionMultiplier;
constexpr u32 kMapImageTotalPixels = kMapImageSide * kMapImageSide;
typedef std::function<u8(size_t, size_t)> PaintI8Fn;
void paint_i8(std::span<u8> dst, size_t width, PaintI8Fn paint) {
const auto blocksAcross = width >> 3;
for (size_t i = 0; i < dst.size(); i++) {
// 8x4 block swizzling for I8
const auto blockIdx = i >> 5;
const auto localIdx = i & 31;
const auto blockY = blockIdx / blocksAcross;
const auto blockX = blockIdx % blocksAcross;
const auto localY = localIdx >> 3;
const auto localX = localIdx & 7;
const auto x = (blockX << 3) + localX;
const auto y = (blockY << 2) + localY;
dst[i] = paint(x, y);
}
}
constexpr u16 kMapCircleSize = 16 * kMapResolutionMultiplier;
#endif
void dMpath_n::dTexObjAggregate_c::create() {
static int const data[7] = {
79, // 0: im_map_icon_square_4i.bti
80, // 1: im_map_icon_tresurebox_4i.bti
77, // 2: im_map_icon_enter_4i.bti
78, // 3: im_map_icon_nijumaru_4i.bti
76, // 4: im_map_icon_circle_4i.bti
81, // 5: im_map_icon_try_force_4i.bti
82, // 6: map_icon_circle16x16_4i.bti
79, 80, 77, 78, 76, 81, 82,
};
for (int lp1 = 0; lp1 < 7; lp1++) {
@@ -69,101 +35,45 @@ void dMpath_n::dTexObjAggregate_c::create() {
}
#if TARGET_PC
static bool hqTexsDrawn = false;
auto hqCircle = JKR_NEW TGXTexObj();
static u8 hqCircleData[kMapImageTotalPixels];
static u8 hqCircleAltData[kMapImageTotalPixels];
static u8 hqNijumaruData[kMapImageTotalPixels];
static u8 hqEnterData[kMapImageTotalPixels];
static u8 hqTryForceData[kMapImageTotalPixels];
static bool hqCircleDrawn = false;
static u8 hqCircleData[kMapCircleSize * kMapCircleSize];
if (!hqTexsDrawn) {
constexpr auto center = kMapImageSide / 2.0f;
constexpr auto radiusSq = center * center;
if (!hqCircleDrawn) {
const auto center = kMapCircleSize / 2.0f;
const auto radiusSq = center * center;
const auto blocksAcross = kMapCircleSize >> 3;
const auto totalPixels = sizeof(hqCircleData);
// 6: map_icon_circle16x16_4i.bti - simple circle
paint_i8(std::span{hqCircleData}, kMapImageSide, [=](auto x, auto y) {
const auto dx = (x + 0.5f) - center;
const auto dy = (y + 0.5f) - center;
return (dx * dx + dy * dy < radiusSq) ? 0x11 : 0;
});
for (size_t i = 0; i < totalPixels; i++) {
// 8x4 block swizzling for I8
const auto blockIdx = i >> 5;
const auto localIdx = i & 31;
// 4: im_map_icon_circle_4i.bti - outlined circle
paint_i8(std::span{hqCircleAltData}, kMapImageSide, [=](auto x, auto y) {
constexpr auto innerRadius = kMapImageSide * 3.0f / 8.0f;
constexpr auto innerRadiusSq = innerRadius * innerRadius;
const auto blockY = blockIdx / blocksAcross;
const auto blockX = blockIdx % blocksAcross;
const auto localY = localIdx >> 3;
const auto localX = localIdx & 7;
const auto x = (blockX << 3) + localX;
const auto y = (blockY << 2) + localY;
const auto dx = (x + 0.5f) - center;
const auto dy = (y + 0.5f) - center;
const auto dSq = dx * dx + dy * dy;
return dSq < radiusSq ? (dSq < innerRadiusSq ? 0x22 : 0x11) : 0;
});
// 3: im_map_icon_nijumaru_4i.bti - concentric rings
paint_i8(std::span{hqNijumaruData}, kMapImageSide, [=](auto x, auto y) {
constexpr u8 nijumaruRings[] = {0x11, 0x22, 0x11, 0x11, 0x22, 0x22};
const auto dx = (x + 0.5f) - center;
const auto dy = (y + 0.5f) - center;
const auto dSq = dx * dx + dy * dy;
if (dSq < radiusSq) {
const auto ringIndex =
static_cast<size_t>(std::trunc(std::sqrt(dSq) / kMapImageSide * 12));
return nijumaruRings[ringIndex];
}
return u8{0};
});
// 2: im_map_icon_enter_4i.bti - outlined octagram
paint_i8(std::span{hqEnterData}, kMapImageSide, [=](auto x, auto y) {
constexpr auto outlineWidth = kMapImageSide / 6.0f;
const auto adx = std::abs((x + 0.5f) - center);
const auto ady = std::abs((y + 0.5f) - center);
const auto dist =
std::min(adx + ady, std::max(adx, ady) * std::numbers::sqrt2_v<float>) -
kMapImageSide / 2.0f;
return dist > 0.0f ? 0 : (dist > -outlineWidth ? 0x22 : 0x33);
});
// 5: im_map_icon_try_force_4i.bti - outlined circle with triangle
paint_i8(std::span{hqTryForceData}, kMapImageSide, [=](auto x, auto y) {
constexpr auto innerRadiusNorm = 5.0f / 12.0f;
constexpr auto innerRadius = kMapImageSide * innerRadiusNorm;
constexpr auto innerRadiusSq = innerRadius * innerRadius;
constexpr auto triRadius = kMapImageSide * innerRadiusNorm / 2.0f;
const auto dx = (x + 0.5f) - center;
const auto dy = (y + 0.5f) - center;
const auto dSq = dx * dx + dy * dy;
const auto triSideDist = (std::numbers::sqrt3_v<float> * std::abs(dx) - dy) * 0.5f;
const auto insideTri = std::max(dy, triSideDist) < triRadius;
return insideTri ? 0x22 : (dSq < radiusSq ? (dSq < innerRadiusSq ? 0x33 : 0x22) : 0);
});
hqTexsDrawn = true;
// the original texture is in I4 format and uses 1 to indicate if inside the circle
// so we scale to I8 range: 255 / 15 = 17
hqCircleData[i] = (dx * dx + dy * dy < radiusSq) ? 17 : 0;
}
hqCircleDrawn = true;
}
constexpr auto replacements = std::to_array<std::pair<size_t, const u8*> >({
{2, hqEnterData},
{3, hqNijumaruData},
{4, hqCircleAltData},
{5, hqTryForceData},
{6, hqCircleData},
});
for (const auto& [idx, data] : replacements) {
JKR_DELETE(mp_texObj[idx]);
const auto texobj = JKR_NEW TGXTexObj();
GXInitTexObj(
texobj, data, kMapImageSide, kMapImageSide, GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(texobj, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
mp_texObj[idx] = texobj;
}
GXInitTexObj(hqCircle, hqCircleData, kMapCircleSize, kMapCircleSize, GX_TF_I8, GX_CLAMP,
GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(hqCircle, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
mp_texObj[6] = hqCircle;
#endif
}

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