mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-20 13:24:40 -04:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 99ea28e9f7 | |||
| 31dd069879 | |||
| a499877c37 | |||
| b91a58feab | |||
| c710ea5b38 | |||
| cd4b29f8a1 | |||
| 6faa4a3330 | |||
| eed81e9ecc | |||
| a773e5489e | |||
| db6a1835d2 | |||
| e10e1f74d5 | |||
| ff3eb9aa48 | |||
| 513fdd2312 | |||
| f33c3bdf72 | |||
| e08b427650 | |||
| 9f0fa12c6e | |||
| ad4f75bbb6 | |||
| 5d2811955c | |||
| 3b30c09e79 | |||
| 8adc40708e | |||
| 2541c3f293 | |||
| 30b003c9d9 | |||
| c77ed40208 | |||
| af8300a77c | |||
| 1ce1003e1a | |||
| 10e2181692 | |||
| 424d1d7b71 | |||
| 26be454999 | |||
| cf89da811a | |||
| f02c7bd1ac | |||
| 53abb8b96d | |||
| 6a27fa23c8 | |||
| 025a425884 | |||
| 5064385c8c | |||
| e52d9e9b71 | |||
| 3520bb746c | |||
| 1e10d95936 | |||
| a923aa24e1 | |||
| 9c4f61678e | |||
| 7967ee1f66 | |||
| 2bdc7b6c09 | |||
| 232f73365c | |||
| a913f1699f | |||
| 01b4eaa2fa | |||
| 9d2ba3eb49 | |||
| 6026b4bb9b |
@@ -1,6 +1,7 @@
|
|||||||
# IDE folders
|
# IDE folders
|
||||||
.idea/
|
.idea/
|
||||||
.vs/
|
.vs/
|
||||||
|
.zed/
|
||||||
|
|
||||||
# Caches
|
# Caches
|
||||||
__pycache__
|
__pycache__
|
||||||
|
|||||||
@@ -276,6 +276,12 @@ if (DUSK_ENABLE_SENTRY_NATIVE)
|
|||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
# Use signed char on ARM to match the original game (and x86)
|
||||||
|
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" _arch)
|
||||||
|
if(_arch MATCHES "^(arm|aarch64)" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
|
||||||
|
add_compile_options(-fsigned-char)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
|
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
|
||||||
set(PLATFORM_NAME win32)
|
set(PLATFORM_NAME win32)
|
||||||
elseif (CMAKE_SYSTEM_NAME STREQUAL Darwin)
|
elseif (CMAKE_SYSTEM_NAME STREQUAL Darwin)
|
||||||
|
|||||||
+183
-53
@@ -1,50 +1,164 @@
|
|||||||
### Building
|
# Building Dusklight
|
||||||
#### Prerequisites
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
The following dependencies are required:
|
||||||
|
|
||||||
* [CMake 3.25+](https://cmake.org)
|
* [CMake 3.25+](https://cmake.org)
|
||||||
* Windows: Install `CMake Tools` in Visual Studio
|
|
||||||
* macOS: `brew install cmake`
|
|
||||||
* [Python 3+](https://python.org)
|
* [Python 3+](https://python.org)
|
||||||
* Windows: [Microsoft Store](https://go.microsoft.com/fwlink?linkID=2082640)
|
|
||||||
* Verify it's added to `%PATH%` by typing `python` in `cmd`.
|
### Windows
|
||||||
* macOS: `brew install python@3`
|
|
||||||
* **[Windows]** [Visual Studio 2026 Community](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx)
|
* Install [CMake 3.25+](https://cmake.org) by searching `CMake Tools` in Visual Studio
|
||||||
* Select `C++ Development` and verify the following packages are included:
|
* Install Python 3 from the [Microsoft Store](https://go.microsoft.com/fwlink?linkID=2082640) and verify it's added to `%PATH%` by typing `python` in `cmd`.
|
||||||
* `Windows 11 SDK`
|
|
||||||
* `CMake Tools`
|
Recommended IDEs:
|
||||||
* `C++ Clang Compiler`
|
|
||||||
* `C++ Clang-cl`
|
* [Visual Studio 2026 Community](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx). During installation:
|
||||||
* **[macOS]** [Xcode 16.4+](https://developer.apple.com/xcode/download/)
|
* Select `C++ Development` and verify the following packages are included:
|
||||||
* **[Linux]** Actively tested on Ubuntu 24.04, Arch Linux & derivatives.
|
* `Windows 11 SDK`
|
||||||
* Ubuntu 24.04+ packages
|
* `CMake Tools`
|
||||||
```
|
* `C++ Clang Compiler`
|
||||||
build-essential curl git ninja-build clang lld zlib1g-dev libcurl4-openssl-dev \
|
* `C++ Clang-cl`
|
||||||
libglu1-mesa-dev libdbus-1-dev libvulkan-dev libxi-dev libxrandr-dev libasound2-dev libpulse-dev \
|
|
||||||
libudev-dev libpng-dev libncurses5-dev cmake libx11-xcb-dev python3 python-is-python3 \
|
### macOS
|
||||||
libclang-dev libfreetype-dev libxinerama-dev libxcursor-dev python3-markupsafe libgtk-3-dev \
|
|
||||||
libxss-dev libxtst-dev
|
* Make sure [Homebrew](https://brew.sh) is installed
|
||||||
```
|
* Install [CMake 3.25+](https://cmake.org)
|
||||||
* Arch Linux packages
|
|
||||||
```
|
|
||||||
base-devel cmake ninja llvm vulkan-headers python python-markupsafe clang lld alsa-lib libpulse libxrandr freetype2
|
|
||||||
```
|
|
||||||
* Fedora packages
|
|
||||||
```
|
|
||||||
cmake vulkan-headers ninja-build clang-devel llvm-devel libpng-devel
|
|
||||||
```
|
|
||||||
* It's also important that you install the developer tools and libraries
|
|
||||||
```
|
|
||||||
sudo dnf groupinstall "Development Tools" "Development Libraries"
|
|
||||||
```
|
|
||||||
#### Setup
|
|
||||||
Clone and initialize the Dusklight repository
|
|
||||||
```sh
|
```sh
|
||||||
git clone --recursive https://github.com/TwilitRealm/dusklight.git
|
brew install cmake
|
||||||
cd dusklight
|
|
||||||
git pull
|
|
||||||
git submodule update --init --recursive
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Building
|
* Install Python 3
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew install python@3
|
||||||
|
```
|
||||||
|
|
||||||
|
Recommended IDEs:
|
||||||
|
|
||||||
|
* [Xcode 16.4 or later](https://developer.apple.com/xcode/)
|
||||||
|
* [Visual Studio Code](https://code.visualstudio.com/download/)
|
||||||
|
* [CLion](https://www.jetbrains.com/clion/)
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
Actively tested on Ubuntu 24.04, Arch Linux & derivatives.
|
||||||
|
|
||||||
|
**Ubuntu 24.04+ packages**
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Click to expand</summary>
|
||||||
|
|
||||||
|
* Run the following command to install the required dependencies:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo apt update && sudo apt install -y \
|
||||||
|
build-essential \
|
||||||
|
clang \
|
||||||
|
cmake \
|
||||||
|
curl \
|
||||||
|
git \
|
||||||
|
libasound2-dev \
|
||||||
|
libclang-dev \
|
||||||
|
libcurl4-openssl-dev \
|
||||||
|
libdbus-1-dev \
|
||||||
|
libfreetype-dev \
|
||||||
|
libglu1-mesa-dev \
|
||||||
|
libgtk-3-dev \
|
||||||
|
libncurses5-dev \
|
||||||
|
libpng-dev \
|
||||||
|
libpulse-dev \
|
||||||
|
libudev-dev \
|
||||||
|
libvulkan-dev \
|
||||||
|
libx11-xcb-dev \
|
||||||
|
libxcursor-dev \
|
||||||
|
libxi-dev \
|
||||||
|
libxinerama-dev \
|
||||||
|
libxrandr-dev \
|
||||||
|
libxss-dev \
|
||||||
|
libxtst-dev \
|
||||||
|
lld \
|
||||||
|
ninja-build \
|
||||||
|
python-is-python3 \
|
||||||
|
python3 \
|
||||||
|
python3-markupsafe \
|
||||||
|
zlib1g-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
**Arch Linux packages**
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Click to expand</summary>
|
||||||
|
|
||||||
|
* Run the following command to install the required dependencies:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo pacman -S --needed \
|
||||||
|
alsa-lib \
|
||||||
|
base-devel \
|
||||||
|
clang \
|
||||||
|
cmake \
|
||||||
|
freetype2 \
|
||||||
|
libpulse \
|
||||||
|
libxrandr \
|
||||||
|
lld \
|
||||||
|
llvm \
|
||||||
|
ninja \
|
||||||
|
python \
|
||||||
|
python-markupsafe \
|
||||||
|
vulkan-headers
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
**Fedora packages**
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Click to expand</summary>
|
||||||
|
|
||||||
|
* Run the following command to install the required dependencies:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo dnf install -y \
|
||||||
|
clang-devel \
|
||||||
|
cmake \
|
||||||
|
libpng-devel \
|
||||||
|
llvm-devel \
|
||||||
|
ninja-build \
|
||||||
|
vulkan-headers
|
||||||
|
```
|
||||||
|
|
||||||
|
* It's also important that you install the developer tools and libraries
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo dnf groupinstall \
|
||||||
|
"Development Libraries" "Development Tools"
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
Recommended IDEs:
|
||||||
|
|
||||||
|
* [CLion](https://www.jetbrains.com/clion/)
|
||||||
|
* [Visual Studio Code](https://code.visualstudio.com/download/)
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
* Clone and initialize the Dusklight repository:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone --recursive https://github.com/TwilitRealm/dusklight.git
|
||||||
|
git pull
|
||||||
|
cd dusklight
|
||||||
|
git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
|
||||||
**CLion (Windows / macOS / Linux)**
|
**CLion (Windows / macOS / Linux)**
|
||||||
|
|
||||||
@@ -64,7 +178,8 @@ cmake --build --preset macos-default-relwithdebinfo
|
|||||||
```
|
```
|
||||||
|
|
||||||
Alternate presets available:
|
Alternate presets available:
|
||||||
- `macos-default-debug`: Clang, Debug
|
|
||||||
|
* `macos-default-debug`: Clang, Debug
|
||||||
|
|
||||||
**ninja (Linux)**
|
**ninja (Linux)**
|
||||||
|
|
||||||
@@ -74,9 +189,10 @@ cmake --build --preset linux-default-relwithdebinfo
|
|||||||
```
|
```
|
||||||
|
|
||||||
Alternate presets available:
|
Alternate presets available:
|
||||||
- `linux-default-debug`: GCC, Debug
|
|
||||||
- `linux-clang-relwithdebinfo`: Clang, RelWithDebInfo
|
* `linux-default-debug`: GCC, Debug
|
||||||
- `linux-clang-debug`: Clang, Debug
|
* `linux-clang-relwithdebinfo`: Clang, RelWithDebInfo
|
||||||
|
* `linux-clang-debug`: Clang, Debug
|
||||||
|
|
||||||
**ninja (Windows)**
|
**ninja (Windows)**
|
||||||
|
|
||||||
@@ -86,13 +202,27 @@ cmake --build --preset windows-msvc-relwithdebinfo
|
|||||||
```
|
```
|
||||||
|
|
||||||
Alternate presets available:
|
Alternate presets available:
|
||||||
- `windows-msvc-debug`: MSVC, Debug
|
|
||||||
- `windows-clang-relwithdebinfo`: Clang-cl, RelWithDebInfo
|
|
||||||
- `windows-clang-debug`: Clang-cl, Debug
|
|
||||||
|
|
||||||
#### Running
|
* `windows-msvc-debug`: MSVC, Debug
|
||||||
Pass the disc image as a positional argument. Supported formats: ISO (GCM), RVZ, WIA, WBFS, CISO, GCZ
|
* `windows-clang-relwithdebinfo`: Clang-cl, RelWithDebInfo
|
||||||
|
* `windows-clang-debug`: Clang-cl, Debug
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
**Windows / Linux**
|
||||||
|
|
||||||
|
* Pass the disc image as a positional argument using the `--dvd` flag. Supported formats are: ISO (GCM), RVZ, WIA, WBFS, CISO, GCZ
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
build/{preset}/dusklight/path/to/game.rvz
|
build/{preset}/dusklight --dvd /path/to/game.iso
|
||||||
|
```
|
||||||
|
|
||||||
|
**macOS**
|
||||||
|
|
||||||
|
macOS builds an `.app` bundle which contains the executable and all necessary resources.
|
||||||
|
|
||||||
|
* Pass the disc image as a positional argument using the `--dvd` flag. Supported formats are: ISO (GCM), RVZ, WIA, WBFS, CISO, GCZ
|
||||||
|
|
||||||
|
```sh
|
||||||
|
build/{preset}/Dusklight.app/Contents/MacOS/Dusklight --dvd /path/to/game.iso
|
||||||
```
|
```
|
||||||
If no path is specified, Dusklight defaults to `game.iso` in the current working directory.
|
|
||||||
|
|||||||
@@ -1,33 +1,40 @@
|
|||||||
# Installing Dusklight on iOS via AltStore
|
# Installing Dusklight on iOS via iloader
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Mac with Homebrew installed
|
- A Windows, Linux, or macOS device
|
||||||
- iPhone connected via USB
|
- iOS device connected to computer via USB
|
||||||
- Dusklight IPA file (download the latest `Dusklight-vX.X.X-ios-arm64.ipa` from the [releases page](https://github.com/TwilitRealm/dusk/releases))
|
- Dusklight IPA file (download the latest `Dusklight-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)
|
- Game disc - `GZ2E01` (Gamecube USA) or `GZ2PE01` (Gamecube PAL)
|
||||||
|
|
||||||
## 1. Install AltServer
|
## 1. Install AltServer
|
||||||
|
|
||||||
```sh
|
- Executable bundles can be installed from [iloader's main page](https://iloader.app/) or [their GitHub](https://github.com/nab138/iloader) for Windows, Linux, and macOS.
|
||||||
brew install altserver
|
- Windows WILL require iTunes to be installed
|
||||||
open -a AltServer
|
- Linux WILL require usbmuxd to be installed, this is installed by default in most distros though
|
||||||
```
|
|
||||||
|
|
||||||
AltServer will appear in your menu bar.
|
|
||||||
|
|
||||||
## 2. Enable Developer Mode (iOS 16+)
|
## 2. Enable Developer Mode (iOS 16+)
|
||||||
|
|
||||||
- On your iPhone, go to **Settings > Privacy & Security > Developer Mode**
|
- On your iPhone, go to **Settings > Privacy & Security > Developer Mode**
|
||||||
- Toggle it on and restart when prompted
|
- Toggle it on and restart when prompted
|
||||||
|
|
||||||
## 3. Install AltStore on Your iPhone
|
## 3. Install Dusklight on Your iPhone
|
||||||
|
|
||||||
- Click AltServer in the menu bar
|
1. Sign into your Apple ID (this is required for registering app IDs, it is sent securely and not stored by iloader)
|
||||||
- Click **Install AltStore > [Your iPhone]**
|
* You may be prompted to put in a code from your iOS device, do so
|
||||||
- Enter your Apple ID credentials when prompted
|
2. Plug in your iOS device via USB into your PC. If you're missing a dependency, an error pop-up will tell you to install it
|
||||||
- On your iPhone, go to **Settings > General > VPN & Device Management**
|
* You will need to hit `Refresh` after plugging it in at this stage so that it can be detected, it does not automatically refresh
|
||||||
- Tap your Apple ID under "Developer App" and tap **Trust**
|
3. Leave settings unchanged (the Anisette server should stay Sidestore (.io))
|
||||||
|
3.(a) Installing SideStore directly is not required, but provides you a way to install Dusklight on your phone without being plugged into a computer later
|
||||||
|
4. Press `Import IPA` and choose your downloaded `Dusk-v.X.X.X-ios-arm64.ipa`, it will begin installing on your device
|
||||||
|
|
||||||
|
**NOTE:** *At various stages, you may be prompted to trust your device, do so*
|
||||||
|
|
||||||
|
## 3. Getting Dusk trusted
|
||||||
|
When installing sideloaded iOS applications, at first you will need to manually trust the app due to Apple's security policies
|
||||||
|
* Go to **Settings > General > VPN & Device Management**
|
||||||
|
* Tap the Apple ID you signed into iloader with under "Developer App" and tap **Trust**
|
||||||
|
* Tap **Allow** on the pop-up
|
||||||
|
|
||||||
## 4. Copy Files to Your iPhone
|
## 4. Copy Files to Your iPhone
|
||||||
|
|
||||||
@@ -38,9 +45,4 @@ Transfer the IPA and game disc to your iPhone so they're accessible in the Files
|
|||||||
- **USB transfer** - Connect your iPhone and drag files via Finder's sidebar
|
- **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
|
- **Cloud storage** - Upload to Google Drive, Dropbox, etc. and download on your iPhone
|
||||||
|
|
||||||
## 5. Install via AltStore
|
You may now use Dusklight on iOS, iPadOS!
|
||||||
|
|
||||||
- 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
|
|
||||||
Vendored
+1
-1
Submodule extern/aurora updated: 3643a369ad...f93b9e5bc2
@@ -15,12 +15,6 @@
|
|||||||
|
|
||||||
# Dependencies that are not packaged in nixpkgs (used by the Linux package build):
|
# Dependencies that are not packaged in nixpkgs (used by the Linux package build):
|
||||||
buildSources = pkgs: {
|
buildSources = pkgs: {
|
||||||
aurora-src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "encounter";
|
|
||||||
repo = "aurora";
|
|
||||||
rev = "63606a43265a3bc18dafd500ab4d7a2108f109e6";
|
|
||||||
hash = "sha256-xBvnAwGwNzav67Ac6oUz7RqDUwqgL2bsME3OOMn8Tqw=";
|
|
||||||
};
|
|
||||||
dawn-src = pkgs.fetchzip {
|
dawn-src = pkgs.fetchzip {
|
||||||
url = "https://github.com/encounter/dawn-build/releases/download/v20260423.175430/dawn-linux-x86_64.tar.gz";
|
url = "https://github.com/encounter/dawn-build/releases/download/v20260423.175430/dawn-linux-x86_64.tar.gz";
|
||||||
hash = "sha256-HXfKTLHtMPwupnFnaflCARtXVPuS/0PoCePXidjE5xs=";
|
hash = "sha256-HXfKTLHtMPwupnFnaflCARtXVPuS/0PoCePXidjE5xs=";
|
||||||
@@ -59,9 +53,6 @@
|
|||||||
name = "dusklight";
|
name = "dusklight";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
postUnpack = ''
|
postUnpack = ''
|
||||||
mkdir -p $sourceRoot/extern/aurora
|
|
||||||
cp -r ${srcs.aurora-src}/. $sourceRoot/extern/aurora/
|
|
||||||
chmod -R u+w $sourceRoot/extern/aurora
|
|
||||||
sed -i '/add_subdirectory(tests)/d' $sourceRoot/extern/aurora/CMakeLists.txt
|
sed -i '/add_subdirectory(tests)/d' $sourceRoot/extern/aurora/CMakeLists.txt
|
||||||
'';
|
'';
|
||||||
# Remove last line to re-enable tests
|
# Remove last line to re-enable tests
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <m_Do/m_Do_MemCardRWmng.h>
|
#include <m_Do/m_Do_MemCardRWmng.h>
|
||||||
#include <m_Do/m_Do_MemCard.h>
|
#include <m_Do/m_Do_MemCard.h>
|
||||||
|
#include <d/actor/d_a_alink.h>
|
||||||
|
|
||||||
void noAutoSave();
|
void noAutoSave();
|
||||||
void triggerAutoSave();
|
void triggerAutoSave();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ void ensure_initialized();
|
|||||||
void begin_record();
|
void begin_record();
|
||||||
void end_record();
|
void end_record();
|
||||||
void begin_sim_tick();
|
void begin_sim_tick();
|
||||||
|
uint64_t sim_tick_seq();
|
||||||
void begin_frame(bool enabled, bool is_sim_frame, float step);
|
void begin_frame(bool enabled, bool is_sim_frame, float step);
|
||||||
void interpolate();
|
void interpolate();
|
||||||
float get_interpolation_step();
|
float get_interpolation_step();
|
||||||
|
|||||||
@@ -72,6 +72,10 @@ struct UserSettings {
|
|||||||
ConfigVar<bool> lockAspectRatio;
|
ConfigVar<bool> lockAspectRatio;
|
||||||
ConfigVar<bool> enableFpsOverlay;
|
ConfigVar<bool> enableFpsOverlay;
|
||||||
ConfigVar<int> fpsOverlayCorner;
|
ConfigVar<int> fpsOverlayCorner;
|
||||||
|
ConfigVar<int> windowPositionX;
|
||||||
|
ConfigVar<int> windowPositionY;
|
||||||
|
ConfigVar<int> windowWidth;
|
||||||
|
ConfigVar<int> windowHeight;
|
||||||
} video;
|
} video;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -123,6 +127,7 @@ struct UserSettings {
|
|||||||
ConfigVar<BloomMode> bloomMode;
|
ConfigVar<BloomMode> bloomMode;
|
||||||
ConfigVar<float> bloomMultiplier;
|
ConfigVar<float> bloomMultiplier;
|
||||||
ConfigVar<bool> disableWaterRefraction;
|
ConfigVar<bool> disableWaterRefraction;
|
||||||
|
ConfigVar<bool> enableTextureReplacements;
|
||||||
ConfigVar<bool> enableFrameInterpolation;
|
ConfigVar<bool> enableFrameInterpolation;
|
||||||
ConfigVar<int> internalResolutionScale;
|
ConfigVar<int> internalResolutionScale;
|
||||||
ConfigVar<int> shadowResolutionMultiplier;
|
ConfigVar<int> shadowResolutionMultiplier;
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ struct fopAcM_search_prm {
|
|||||||
struct fOpAcm_HIO_entry_c : public mDoHIO_entry_c {
|
struct fOpAcm_HIO_entry_c : public mDoHIO_entry_c {
|
||||||
virtual ~fOpAcm_HIO_entry_c() {}
|
virtual ~fOpAcm_HIO_entry_c() {}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG && !TARGET_PC
|
||||||
void removeHIO(const fopAc_ac_c* i_this) { removeHIO(*i_this); }
|
void removeHIO(const fopAc_ac_c* i_this) { removeHIO(*i_this); }
|
||||||
void removeHIO(const fopAc_ac_c& i_this) { removeHIO(i_this.base); }
|
void removeHIO(const fopAc_ac_c& i_this) { removeHIO(i_this.base); }
|
||||||
void removeHIO(const fopEn_enemy_c& i_this) { removeHIO(i_this.base); }
|
void removeHIO(const fopEn_enemy_c& i_this) { removeHIO(i_this.base); }
|
||||||
|
|||||||
@@ -28,7 +28,9 @@
|
|||||||
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||||
<key>NSHighResolutionCapable</key>
|
<key>NSHighResolutionCapable</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>LSApplicationCategoryType</key>
|
||||||
|
<string>public.app-category.adventure-games</string>
|
||||||
<key>LSSupportsGameMode</key>
|
<key>LSSupportsGameMode</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -58,6 +58,10 @@ toast:active {
|
|||||||
background-color: rgba(45, 43, 26, 80%);
|
background-color: rgba(45, 43, 26, 80%);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
b {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
toast heading {
|
toast heading {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 18dp;
|
gap: 18dp;
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ body {
|
|||||||
color: #E0DBC8;
|
color: #E0DBC8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
window {
|
window {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
|
|||||||
@@ -7562,12 +7562,7 @@ void daAlink_c::setBlendMoveAnime(f32 i_morf) {
|
|||||||
f32 sp2C;
|
f32 sp2C;
|
||||||
f32 sp28 = mpHIO->mMove.m.mFootPositionRatio;
|
f32 sp28 = mpHIO->mMove.m.mFootPositionRatio;
|
||||||
BOOL sp24 = checkEventRun();
|
BOOL sp24 = checkEventRun();
|
||||||
BOOL sp20 = checkBootsMoveAnime(1);
|
BOOL sp20 = checkBootsMoveAnime(1) IF_DUSK(&& !dusk::getSettings().game.enableFastIronBoots);
|
||||||
#if TARGET_PC
|
|
||||||
if (dusk::getSettings().game.enableFastIronBoots) {
|
|
||||||
sp20 = FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
f32 var_f29;
|
f32 var_f29;
|
||||||
|
|
||||||
@@ -8080,7 +8075,7 @@ void daAlink_c::setBlendAtnBackMoveAnime(f32 i_morf) {
|
|||||||
daAlink_ANM var_r27;
|
daAlink_ANM var_r27;
|
||||||
daAlink_ANM var_r29;
|
daAlink_ANM var_r29;
|
||||||
|
|
||||||
if (checkBootsMoveAnime(1)) {
|
if (checkBootsMoveAnime(1) IF_DUSK(&& !dusk::getSettings().game.enableFastIronBoots)) {
|
||||||
mMaxSpeed = mpHIO->mAtnMove.m.mMaxBackwardsSpeed;
|
mMaxSpeed = mpHIO->mAtnMove.m.mMaxBackwardsSpeed;
|
||||||
var_f27 = mpHIO->mAtnMove.m.mMinBackWalkFrame;
|
var_f27 = mpHIO->mAtnMove.m.mMinBackWalkFrame;
|
||||||
var_f31 = mpHIO->mAtnMove.m.mBackWalkChangeRate;
|
var_f31 = mpHIO->mAtnMove.m.mBackWalkChangeRate;
|
||||||
|
|||||||
@@ -157,6 +157,21 @@ static void* s_h_sub(void* i_actor, void* i_data) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
static void sort_target_info_by_id() {
|
||||||
|
for (int i = 1; i < target_info_count; i++) {
|
||||||
|
void* key = target_info[i];
|
||||||
|
fpc_ProcID key_id = fopAcM_GetID(key);
|
||||||
|
int j = i - 1;
|
||||||
|
while (j >= 0 && fopAcM_GetID(target_info[j]) > key_id) {
|
||||||
|
target_info[j + 1] = target_info[j];
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
target_info[j + 1] = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static daPillar_c* search_hasira(e_mk_class* i_this) {
|
static daPillar_c* search_hasira(e_mk_class* i_this) {
|
||||||
fopEn_enemy_c* actor = (fopEn_enemy_c*)&i_this->actor;
|
fopEn_enemy_c* actor = (fopEn_enemy_c*)&i_this->actor;
|
||||||
daPillar_c* pillar_p;
|
daPillar_c* pillar_p;
|
||||||
@@ -170,6 +185,9 @@ static daPillar_c* search_hasira(e_mk_class* i_this) {
|
|||||||
|
|
||||||
if (i_this->firstHasiraFlag == 0) {
|
if (i_this->firstHasiraFlag == 0) {
|
||||||
i_this->firstHasiraFlag++;
|
i_this->firstHasiraFlag++;
|
||||||
|
#if TARGET_PC
|
||||||
|
sort_target_info_by_id();
|
||||||
|
#endif
|
||||||
return (daPillar_c*)target_info[TREG_S(7) + 5];
|
return (daPillar_c*)target_info[TREG_S(7) + 5];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7053,6 +7053,12 @@ static int daE_RD_IsDelete(e_rd_class*) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int daE_RD_Delete(e_rd_class* i_this) {
|
static int daE_RD_Delete(e_rd_class* i_this) {
|
||||||
|
#if TARGET_PC
|
||||||
|
if (boss == i_this) {
|
||||||
|
boss = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fopEn_enemy_c* enemy = (fopEn_enemy_c*)&i_this->enemy;
|
fopEn_enemy_c* enemy = (fopEn_enemy_c*)&i_this->enemy;
|
||||||
fopAcM_RegisterDeleteID(i_this, "E_RD");
|
fopAcM_RegisterDeleteID(i_this, "E_RD");
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
#include "dusk/dusk.h"
|
#include "dusk/dusk.h"
|
||||||
|
#include "dusk/frame_interpolation.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// FRAME INTERP NOTE: Sim tick control point snapshots for interpolation
|
// FRAME INTERP NOTE: Sim tick control point snapshots for interpolation
|
||||||
@@ -32,6 +33,7 @@ int s_horseReinSimNumPrev;
|
|||||||
int s_horseReinSimNumCurr;
|
int s_horseReinSimNumCurr;
|
||||||
bool s_horseReinSimPrevValid;
|
bool s_horseReinSimPrevValid;
|
||||||
bool s_horseReinSimCurrValid;
|
bool s_horseReinSimCurrValid;
|
||||||
|
uint64_t s_horseReinSimRolledSeq;
|
||||||
} // namespace
|
} // namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -3033,10 +3035,14 @@ void daHorse_c::copyReinPos() {
|
|||||||
}
|
}
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
if (field_0x1204 > 0) {
|
if (field_0x1204 > 0) {
|
||||||
if (s_horseReinSimCurrValid && s_horseReinSimNumCurr > 0) {
|
const uint64_t simSeq = dusk::frame_interp::sim_tick_seq();
|
||||||
memcpy(s_horseReinSimPrev, s_horseReinSimCurr, s_horseReinSimNumCurr * sizeof(cXyz));
|
if (simSeq != s_horseReinSimRolledSeq) {
|
||||||
s_horseReinSimNumPrev = s_horseReinSimNumCurr;
|
s_horseReinSimRolledSeq = simSeq;
|
||||||
s_horseReinSimPrevValid = true;
|
if (s_horseReinSimCurrValid && s_horseReinSimNumCurr > 0) {
|
||||||
|
memcpy(s_horseReinSimPrev, s_horseReinSimCurr, s_horseReinSimNumCurr * sizeof(cXyz));
|
||||||
|
s_horseReinSimNumPrev = s_horseReinSimNumCurr;
|
||||||
|
s_horseReinSimPrevValid = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
memcpy(s_horseReinSimCurr, m_reinLine.getPos(0), field_0x1204 * sizeof(cXyz));
|
memcpy(s_horseReinSimCurr, m_reinLine.getPos(0), field_0x1204 * sizeof(cXyz));
|
||||||
s_horseReinSimNumCurr = field_0x1204;
|
s_horseReinSimNumCurr = field_0x1204;
|
||||||
|
|||||||
@@ -1967,7 +1967,11 @@ static void demo_camera_shop(npc_henna_class* i_this) {
|
|||||||
i_this->mMsgFlow.init(actor, 0x365, 0, NULL);
|
i_this->mMsgFlow.init(actor, 0x365, 0, NULL);
|
||||||
/* dSv_event_flag_c::KORO2_ALLCLEAR - Fishing - After all stages (8-8) of roll goal game cleared */
|
/* dSv_event_flag_c::KORO2_ALLCLEAR - Fishing - After all stages (8-8) of roll goal game cleared */
|
||||||
dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[0x335]);
|
dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[0x335]);
|
||||||
|
#if TARGET_PC
|
||||||
|
dComIfGp_setItemRupeeCount(dComIfGs_getRupeeMax());
|
||||||
|
#else
|
||||||
dComIfGp_setItemRupeeCount(1000);
|
dComIfGp_setItemRupeeCount(1000);
|
||||||
|
#endif
|
||||||
} else if ((lbl_82_bss_91 & 0x38) == 0) {
|
} else if ((lbl_82_bss_91 & 0x38) == 0) {
|
||||||
i_this->mMsgFlow.init(actor, 0x34f, 0, NULL);
|
i_this->mMsgFlow.init(actor, 0x34f, 0, NULL);
|
||||||
/* dSv_event_flag_c::F_0469 - Fishing Pond - Reserved for fishing */
|
/* dSv_event_flag_c::F_0469 - Fishing Pond - Reserved for fishing */
|
||||||
|
|||||||
@@ -299,7 +299,8 @@ int daObjDrop_c::modeParentWait() {
|
|||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
static inline BOOL checkGetCargoRide() {
|
static inline BOOL checkGetCargoRide() {
|
||||||
if ((daPy_getPlayerActorClass()->checkCargoCarry() && strcmp(dComIfGp_getStartStageName(), "F_SP112") == 0) ||
|
if (daPy_getPlayerActorClass()->checkCargoCarry() &&
|
||||||
|
strcmp(dComIfGp_getStartStageName(), "F_SP112") == 0 &&
|
||||||
dComIfGs_isLightDropGetFlag(dComIfGp_getStartStageDarkArea()))
|
dComIfGs_isLightDropGetFlag(dComIfGp_getStartStageDarkArea()))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -143,13 +143,12 @@ void dBrightCheck_c::modeMove() {
|
|||||||
if (mDoCPd_c::getTrigA(PAD_1) || mDoCPd_c::getTrigStart(PAD_1)) {
|
if (mDoCPd_c::getTrigA(PAD_1) || mDoCPd_c::getTrigStart(PAD_1)) {
|
||||||
mDoAud_seStart(Z2SE_ENTER_GAME, NULL, 0, 0);
|
mDoAud_seStart(Z2SE_ENTER_GAME, NULL, 0, 0);
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
dusk::speedrun::start();
|
|
||||||
|
|
||||||
if (dusk::getSettings().game.speedrunMode && !dusk::getSettings().game.hideTvSettingsScreen) {
|
if (dusk::getSettings().game.speedrunMode && !dusk::getSettings().game.hideTvSettingsScreen) {
|
||||||
// start a new run if a run isn't already in progress
|
// start a new run if a run isn't already in progress
|
||||||
if (!dusk::m_speedrunInfo.m_isRunStarted) {
|
if (!dusk::m_speedrunInfo.m_isRunStarted) {
|
||||||
dusk::resetForSpeedrunMode();
|
dusk::resetForSpeedrunMode();
|
||||||
dusk::m_speedrunInfo.startRun();
|
dusk::m_speedrunInfo.startRun();
|
||||||
|
dusk::speedrun::start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "d/d_timer.h"
|
#include "d/d_timer.h"
|
||||||
#include "f_op/f_op_msg_mng.h"
|
#include "f_op/f_op_msg_mng.h"
|
||||||
#include "f_op/f_op_scene_mng.h"
|
#include "f_op/f_op_scene_mng.h"
|
||||||
|
#include "m_Do/m_Do_MemCard.h"
|
||||||
#include "m_Do/m_Do_Reset.h"
|
#include "m_Do/m_Do_Reset.h"
|
||||||
#include "m_Do/m_Do_controller_pad.h"
|
#include "m_Do/m_Do_controller_pad.h"
|
||||||
#include "m_Do/m_Do_graphic.h"
|
#include "m_Do/m_Do_graphic.h"
|
||||||
@@ -1238,6 +1239,13 @@ BOOL dComIfG_resetToOpening(scene_class* i_scene) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
if (!mDoMemCd_isCardCommNone()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
g_mDoMemCd_control.SaveSync();
|
||||||
|
#endif
|
||||||
|
|
||||||
dComIfG_changeOpeningScene(i_scene, fpcNm_OPENING_SCENE_e);
|
dComIfG_changeOpeningScene(i_scene, fpcNm_OPENING_SCENE_e);
|
||||||
mDoAud_bgmStop(30);
|
mDoAud_bgmStop(30);
|
||||||
mDoAud_resetProcess();
|
mDoAud_resetProcess();
|
||||||
|
|||||||
@@ -26,6 +26,10 @@
|
|||||||
#include "f_op/f_op_overlap_mng.h"
|
#include "f_op/f_op_overlap_mng.h"
|
||||||
#include "m_Do/m_Do_controller_pad.h"
|
#include "m_Do/m_Do_controller_pad.h"
|
||||||
|
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
#include "dusk/frame_interpolation.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class dDlst_MENU_CAPTURE_c : public dDlst_base_c {
|
class dDlst_MENU_CAPTURE_c : public dDlst_base_c {
|
||||||
public:
|
public:
|
||||||
virtual void draw() {
|
virtual void draw() {
|
||||||
@@ -1088,6 +1092,10 @@ void dMw_c::dMw_ring_create(u8 i_origin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mpCapture->setCaptureFlag();
|
mpCapture->setCaptureFlag();
|
||||||
|
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
dusk::frame_interp::request_presentation_sync();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dMw_c::dMw_ring_delete() {
|
bool dMw_c::dMw_ring_delete() {
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
#include "d/d_pane_class.h"
|
#include "d/d_pane_class.h"
|
||||||
#include "dusk/frame_interpolation.h"
|
#include "dusk/frame_interpolation.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#if TARGET_PC
|
||||||
|
#include "dusk/string.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if VERSION == VERSION_GCN_JPN
|
#if VERSION == VERSION_GCN_JPN
|
||||||
#define STR_BUF_LEN 528
|
#define STR_BUF_LEN 528
|
||||||
@@ -2927,6 +2930,12 @@ bool dMeterButton_c::isClose() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dMeterButton_c::setString(char* i_string, u8 i_button, u8 param_2, u8 param_3) {
|
void dMeterButton_c::setString(char* i_string, u8 i_button, u8 param_2, u8 param_3) {
|
||||||
|
#if TARGET_PC
|
||||||
|
char* i_string_full = i_string;
|
||||||
|
char i_string_buf[sizeof(mButtonText[0])];
|
||||||
|
dusk::SafeStringCopyTruncate(i_string_buf, i_string);
|
||||||
|
i_string = i_string_buf;
|
||||||
|
#endif
|
||||||
if (strcmp(mButtonText[param_2], i_string) != 0 || field_0x4be[param_2] != i_button) {
|
if (strcmp(mButtonText[param_2], i_string) != 0 || field_0x4be[param_2] != i_button) {
|
||||||
if (param_2 == 0 && strcmp(mButtonText[1], i_string) == 0 &&
|
if (param_2 == 0 && strcmp(mButtonText[1], i_string) == 0 &&
|
||||||
((i_button == BUTTON_A_e && field_0x4be[1] == BUTTON_A_e) ||
|
((i_button == BUTTON_A_e && field_0x4be[1] == BUTTON_A_e) ||
|
||||||
@@ -3022,6 +3031,10 @@ void dMeterButton_c::setString(char* i_string, u8 i_button, u8 param_2, u8 param
|
|||||||
|
|
||||||
strcpy(mButtonText[param_2], i_string);
|
strcpy(mButtonText[param_2], i_string);
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
i_string = i_string_full;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (param_2 == 0) {
|
if (param_2 == 0) {
|
||||||
if (param_3 != 0) {
|
if (param_3 != 0) {
|
||||||
field_0x4d9 = param_2;
|
field_0x4d9 = param_2;
|
||||||
|
|||||||
+10
-7
@@ -77,16 +77,16 @@ static const char* l_mojiEisu[65] = {
|
|||||||
// That can't work on a modern platform, so instead I've filled them out ahead of time.
|
// That can't work on a modern platform, so instead I've filled them out ahead of time.
|
||||||
static const char* l_mojiEisuPal_1[65] = {
|
static const char* l_mojiEisuPal_1[65] = {
|
||||||
"A", "N", "\xC0", "\xCF", "1", "B", "O", "\xC1", "\xD0", "2", "C", "P", "\xC2", "\xD1", "3", "D", "Q",
|
"A", "N", "\xC0", "\xCF", "1", "B", "O", "\xC1", "\xD0", "2", "C", "P", "\xC2", "\xD1", "3", "D", "Q",
|
||||||
"\xC3", "\xD2", "4", "E", "R", "\xC4", "\xD3", "5", "F", "S", "\xC5", "\xD4", "6", "G", "T", "\xC6", "\xD5",
|
"\xC4", "\xD2", "4", "E", "R", "\xC6", "\xD3", "5", "F", "S", "\xC7", "\xD4", "6", "G", "T", "\xC8", "\xD6",
|
||||||
"7", "H", "U", "\xC7", "\xD6", "8", "I", "V", "\xC8", "\xD7", "9", "J", "W", "\xC9", "\xD8", "0", "K",
|
"7", "H", "U", "\xC9", "\x8C", "8", "I", "V", "\xCA", "\xD9", "9", "J", "W", "\xCB", "\xDA", "0", "K",
|
||||||
"X", "\xCA", "\xD9", ",", "L", "Y", "\xCB", "\xDA", ".", "M", "Z", "\xCC", "\xDB", " ",
|
"X", "\xCC", "\xDB", ",", "L", "Y", "\xCD", "\xDC", ".", "M", "Z", "\xCE", "\x2D", " ",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* l_mojiEisuPal_2[65] = {
|
static const char* l_mojiEisuPal_2[65] = {
|
||||||
"a", "n", "\xE0", "\xEF", "1", "b", "o", "\xE1", "\xF0", "2", "c", "p", "\xE2", "\xF1", "3", "d", "q",
|
"a", "n", "\xE0", "\xEF", "1", "b", "o", "\xE1", "\xF0", "2", "c", "p", "\xE2", "\xF1", "3", "d", "q",
|
||||||
"\xE3", "\xF2", "4", "e", "r", "\xE4", "\xF3", "5", "f", "s", "\xE5", "\xF4", "6", "g", "t", "\xE6",
|
"\xE4", "\xF2", "4", "e", "r", "\xE6", "\xF3", "5", "f", "s", "\xE7", "\xF4", "6", "g", "t", "\xE8",
|
||||||
"\xF5", "7", "h", "u", "\xE7", "\xF6", "8", "i", "v", "\xE8", "\xF7", "9", "j", "w", "\xE9", "\xF8", "0",
|
"\xF6", "7", "h", "u", "\xE9", "\x9C", "8", "i", "v", "\xEA", "\xF9", "9", "j", "w", "\xEB", "\xFA", "0",
|
||||||
"k", "x", "\xEA", "\xF9", ",", "l", "y", "\xEB", "\xFA", ".", "m", "z", "\xEC", "\xFB", " ",
|
"k", "x", "\xEC", "\xFB", ",", "l", "y", "\xED", "\xFC", ".", "m", "z", "\xEE", "\xDF", " ",
|
||||||
};
|
};
|
||||||
#elif REGION_PAL
|
#elif REGION_PAL
|
||||||
static const char* l_mojiEisuPal_1[65] = {
|
static const char* l_mojiEisuPal_1[65] = {
|
||||||
@@ -295,6 +295,7 @@ void dName_c::_move() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
|
#if !TARGET_PC
|
||||||
if (mDoCPd_c::getTrigRight(PAD_1)) {
|
if (mDoCPd_c::getTrigRight(PAD_1)) {
|
||||||
// BUG: this check only fails if the cursor is at exactly 7
|
// BUG: this check only fails if the cursor is at exactly 7
|
||||||
// setMoji allows the cursor to reach 8, which is out of bounds here
|
// setMoji allows the cursor to reach 8, which is out of bounds here
|
||||||
@@ -311,7 +312,9 @@ void dName_c::_move() {
|
|||||||
mCurPos--;
|
mCurPos--;
|
||||||
nameCursorMove();
|
nameCursorMove();
|
||||||
}
|
}
|
||||||
} else if (mDoCPd_c::getTrigB(PAD_1)) {
|
} else
|
||||||
|
#endif
|
||||||
|
if (mDoCPd_c::getTrigB(PAD_1)) {
|
||||||
if (mCurPos == 0) {
|
if (mCurPos == 0) {
|
||||||
mDoAud_seStart(Z2SE_SY_MENU_BACK, 0, 0, 0);
|
mDoAud_seStart(Z2SE_SY_MENU_BACK, 0, 0, 0);
|
||||||
field_0x2ac = mSelProc;
|
field_0x2ac = mSelProc;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "d/d_meter2_info.h"
|
#include "d/d_meter2_info.h"
|
||||||
#include "d/d_s_name.h"
|
#include "d/d_s_name.h"
|
||||||
#include "dusk/imgui/ImGuiConsole.hpp"
|
#include "dusk/imgui/ImGuiConsole.hpp"
|
||||||
|
#include "dusk/livesplit.h"
|
||||||
#include "dusk/memory.h"
|
#include "dusk/memory.h"
|
||||||
#include "dusk/speedrun.h"
|
#include "dusk/speedrun.h"
|
||||||
#include "dusk/settings.h"
|
#include "dusk/settings.h"
|
||||||
@@ -422,6 +423,7 @@ void dScnName_c::changeGameScene() {
|
|||||||
if (!dusk::m_speedrunInfo.m_isRunStarted) {
|
if (!dusk::m_speedrunInfo.m_isRunStarted) {
|
||||||
dusk::resetForSpeedrunMode();
|
dusk::resetForSpeedrunMode();
|
||||||
dusk::m_speedrunInfo.startRun();
|
dusk::m_speedrunInfo.startRun();
|
||||||
|
dusk::speedrun::start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-5
@@ -30,7 +30,9 @@
|
|||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
#include "dusk/settings.h"
|
#include "dusk/settings.h"
|
||||||
#include <f_ap/f_ap_game.h>
|
#include <f_ap/f_ap_game.h>
|
||||||
#include <dusk/autosave.h>
|
|
||||||
|
#include "dusk/string.hpp"
|
||||||
|
#define strcpy dusk::SafeStringCopy
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static u8 dSv_item_rename(u8 i_itemNo) {
|
static u8 dSv_item_rename(u8 i_itemNo) {
|
||||||
@@ -349,10 +351,6 @@ void dSv_player_item_c::setItem(int i_slotNo, u8 i_itemNo) {
|
|||||||
dComIfGp_setSelectItem(i);
|
dComIfGp_setSelectItem(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
triggerAutoSave();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 dSv_player_item_c::getItem(int i_slotNo, bool i_checkCombo) const {
|
u8 dSv_player_item_c::getItem(int i_slotNo, bool i_checkCombo) const {
|
||||||
|
|||||||
@@ -191,13 +191,17 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool hasJewelRod = false;
|
bool hasJewelRod = false;
|
||||||
for (int slot = 0; slot < 24 && !hasJewelRod; ++slot) {
|
bool hasAncientDoc = false;
|
||||||
|
for (int slot = 0; slot < 24; ++slot) {
|
||||||
const u8 item = dComIfGs_getItem(slot, false);
|
const u8 item = dComIfGs_getItem(slot, false);
|
||||||
if (item == dItemNo_JEWEL_ROD_e || item == dItemNo_JEWEL_BEE_ROD_e || item == dItemNo_JEWEL_WORM_ROD_e) {
|
if (item == dItemNo_JEWEL_ROD_e || item == dItemNo_JEWEL_BEE_ROD_e || item == dItemNo_JEWEL_WORM_ROD_e) {
|
||||||
hasJewelRod = true;
|
hasJewelRod = true;
|
||||||
}
|
}
|
||||||
|
if (item == dItemNo_ANCIENT_DOCUMENT_e || item == dItemNo_ANCIENT_DOCUMENT2_e || item == dItemNo_AIR_LETTER_e) {
|
||||||
|
hasAncientDoc = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!hasJewelRod) {
|
if (!hasJewelRod || !hasAncientDoc) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +216,6 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
|||||||
dItemNo_KANTERA_e,
|
dItemNo_KANTERA_e,
|
||||||
dItemNo_PACHINKO_e,
|
dItemNo_PACHINKO_e,
|
||||||
dItemNo_HAWK_EYE_e,
|
dItemNo_HAWK_EYE_e,
|
||||||
dItemNo_ANCIENT_DOCUMENT_e,
|
|
||||||
dItemNo_HORSE_FLUTE_e,
|
dItemNo_HORSE_FLUTE_e,
|
||||||
};
|
};
|
||||||
for (u8 required : requiredWheelItems) {
|
for (u8 required : requiredWheelItems) {
|
||||||
|
|||||||
+16
-2
@@ -14,9 +14,23 @@ static AutoSaveFuncs AutoSaveFuncsProc[] = {
|
|||||||
|
|
||||||
void noAutoSave() {}
|
void noAutoSave() {}
|
||||||
|
|
||||||
|
bool canAutoSave() {
|
||||||
|
daAlink_c* player = (daAlink_c*)daAlink_getAlinkActorClass();
|
||||||
|
if (player == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player->checkCargoCarry() || player->checkCanoeRide()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dusk::getSettings().game.autoSave && shouldAutoSave && mAutoSaveProc == 0 &&
|
||||||
|
strcmp(dComIfGp_getStartStageName(), "F_SP102") != 0 &&
|
||||||
|
strcmp(dComIfGp_getStartStageName(), "F_SP112") != 0;
|
||||||
|
}
|
||||||
|
|
||||||
void triggerAutoSave() {
|
void triggerAutoSave() {
|
||||||
if (dusk::getSettings().game.autoSave && shouldAutoSave && mAutoSaveProc == 0 &&
|
if (canAutoSave())
|
||||||
strcmp(dComIfGp_getStartStageName(), "F_SP102") != 0)
|
|
||||||
{
|
{
|
||||||
mAutoSaveProc = 1;
|
mAutoSaveProc = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ bool g_sync_presentation = false;
|
|||||||
float g_step = 0.0f;
|
float g_step = 0.0f;
|
||||||
bool g_is_sim_frame = false;
|
bool g_is_sim_frame = false;
|
||||||
bool g_ui_tick_pending = false;
|
bool g_ui_tick_pending = false;
|
||||||
|
uint64_t g_sim_tick_seq = 0;
|
||||||
|
|
||||||
Recording g_current_recording;
|
Recording g_current_recording;
|
||||||
Recording g_previous_recording;
|
Recording g_previous_recording;
|
||||||
@@ -66,19 +67,18 @@ void copy_view_to_snap(CameraSnapshot* dst, const view_class& v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void lerp_matrix(Mtx out, const Mtx lhs, const Mtx rhs, float step) {
|
inline void lerp_matrix(Mtx out, const Mtx lhs, const Mtx rhs, float step) {
|
||||||
const float old_weight = 1.0f - step;
|
|
||||||
for (size_t row = 0; row < 3; ++row) {
|
for (size_t row = 0; row < 3; ++row) {
|
||||||
for (size_t col = 0; col < 4; ++col) {
|
for (size_t col = 0; col < 4; ++col) {
|
||||||
out[row][col] = lhs[row][col] * old_weight + rhs[row][col] * step;
|
const float l = lhs[row][col];
|
||||||
|
out[row][col] = l + (rhs[row][col] - l) * step;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void lerp_xyz(cXyz* out, const cXyz& lhs, const cXyz& rhs, float step) {
|
inline void lerp_xyz(cXyz* out, const cXyz& lhs, const cXyz& rhs, float step) {
|
||||||
const float old_weight = 1.0f - step;
|
out->x = lhs.x + (rhs.x - lhs.x) * step;
|
||||||
out->x = lhs.x * old_weight + rhs.x * step;
|
out->y = lhs.y + (rhs.y - lhs.y) * step;
|
||||||
out->y = lhs.y * old_weight + rhs.y * step;
|
out->z = lhs.z + (rhs.z - lhs.z) * step;
|
||||||
out->z = lhs.z * old_weight + rhs.z * step;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static s16 lerp_bank(s16 a, s16 b, f32 t) {
|
static s16 lerp_bank(s16 a, s16 b, f32 t) {
|
||||||
@@ -135,6 +135,11 @@ void begin_sim_tick() {
|
|||||||
|
|
||||||
s_interpolationCallBackWork.clear();
|
s_interpolationCallBackWork.clear();
|
||||||
s_cam_prev = std::move(s_cam_curr);
|
s_cam_prev = std::move(s_cam_curr);
|
||||||
|
++g_sim_tick_seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t sim_tick_seq() {
|
||||||
|
return g_sim_tick_seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
void begin_frame(bool enabled, bool is_sim_frame, float step) {
|
void begin_frame(bool enabled, bool is_sim_frame, float step) {
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ namespace dusk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getSettings().game.enableResetKeybind && ImGui::GetIO().KeyCtrl &&
|
if (getSettings().game.enableResetKeybind && ImGui::GetIO().KeyCtrl &&
|
||||||
ImGui::IsKeyPressed(ImGuiKey_R) && !fpcM_SearchByName(fpcNm_LOGO_SCENE_e))
|
ImGui::IsKeyReleased(ImGuiKey_R) && !fpcM_SearchByName(fpcNm_LOGO_SCENE_e))
|
||||||
{
|
{
|
||||||
JUTGamePad::C3ButtonReset::sResetSwitchPushing = true;
|
JUTGamePad::C3ButtonReset::sResetSwitchPushing = true;
|
||||||
}
|
}
|
||||||
@@ -322,8 +322,8 @@ namespace dusk {
|
|||||||
}
|
}
|
||||||
ImGui::PushFont(ImGuiEngine::fontLarge);
|
ImGui::PushFont(ImGuiEngine::fontLarge);
|
||||||
ImGuiTextCenter("Failed to initialize any graphics backend.");
|
ImGuiTextCenter("Failed to initialize any graphics backend.");
|
||||||
ImGuiTextCenter("\nYour system may be misconfigured, or your hardware may not support the required versions of any of the available backends.");
|
ImGuiTextCenter("\nDusklight requires Vulkan 1.1+, or Direct X 12.0.");
|
||||||
ImGuiTextCenter("\nA clean reinstall of Dusklight may help. For further assistance, please visit #tech-support on the Twilit Realm Discord server.");
|
ImGuiTextCenter("\nTry updating your Operating System and GPU drivers.");
|
||||||
const auto& style = ImGui::GetStyle();
|
const auto& style = ImGui::GetStyle();
|
||||||
const auto retrySize = ImGui::CalcTextSize("Retry (Auto backend)");
|
const auto retrySize = ImGui::CalcTextSize("Retry (Auto backend)");
|
||||||
const auto quitSize = ImGui::CalcTextSize("Quit");
|
const auto quitSize = ImGui::CalcTextSize("Quit");
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#include "dusk/settings.h"
|
#include "dusk/settings.h"
|
||||||
#include "dusk/config.hpp"
|
#include "dusk/config.hpp"
|
||||||
|
#include "dusk/dusk.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL_video.h>
|
||||||
|
|
||||||
namespace dusk {
|
namespace dusk {
|
||||||
|
|
||||||
@@ -10,6 +13,10 @@ UserSettings g_userSettings = {
|
|||||||
.lockAspectRatio {"video.lockAspectRatio", false},
|
.lockAspectRatio {"video.lockAspectRatio", false},
|
||||||
.enableFpsOverlay {"game.enableFpsOverlay", false},
|
.enableFpsOverlay {"game.enableFpsOverlay", false},
|
||||||
.fpsOverlayCorner {"game.fpsOverlayCorner", 0},
|
.fpsOverlayCorner {"game.fpsOverlayCorner", 0},
|
||||||
|
.windowPositionX {"video.windowPositionX", SDL_WINDOWPOS_UNDEFINED},
|
||||||
|
.windowPositionY {"video.windowPositionY", SDL_WINDOWPOS_UNDEFINED},
|
||||||
|
.windowWidth {"video.windowWidth", defaultWindowWidth * 2},
|
||||||
|
.windowHeight {"video.windowHeight", defaultWindowHeight * 2},
|
||||||
},
|
},
|
||||||
|
|
||||||
.audio = {
|
.audio = {
|
||||||
@@ -58,6 +65,7 @@ UserSettings g_userSettings = {
|
|||||||
.bloomMode {"game.bloomMode", BloomMode::Dusk},
|
.bloomMode {"game.bloomMode", BloomMode::Dusk},
|
||||||
.bloomMultiplier {"game.bloomMultiplier", 1.0f},
|
.bloomMultiplier {"game.bloomMultiplier", 1.0f},
|
||||||
.disableWaterRefraction {"game.disableWaterRefraction", false},
|
.disableWaterRefraction {"game.disableWaterRefraction", false},
|
||||||
|
.enableTextureReplacements {"game.enableTextureReplacements", true},
|
||||||
.enableFrameInterpolation {"game.enableFrameInterpolation", false},
|
.enableFrameInterpolation {"game.enableFrameInterpolation", false},
|
||||||
.internalResolutionScale {"game.internalResolutionScale", 0},
|
.internalResolutionScale {"game.internalResolutionScale", 0},
|
||||||
.shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1},
|
.shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1},
|
||||||
@@ -177,6 +185,10 @@ void registerSettings() {
|
|||||||
Register(g_userSettings.video.lockAspectRatio);
|
Register(g_userSettings.video.lockAspectRatio);
|
||||||
Register(g_userSettings.video.enableFpsOverlay);
|
Register(g_userSettings.video.enableFpsOverlay);
|
||||||
Register(g_userSettings.video.fpsOverlayCorner);
|
Register(g_userSettings.video.fpsOverlayCorner);
|
||||||
|
Register(g_userSettings.video.windowPositionX);
|
||||||
|
Register(g_userSettings.video.windowPositionY);
|
||||||
|
Register(g_userSettings.video.windowWidth);
|
||||||
|
Register(g_userSettings.video.windowHeight);
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
Register(g_userSettings.audio.masterVolume);
|
Register(g_userSettings.audio.masterVolume);
|
||||||
@@ -218,6 +230,7 @@ void registerSettings() {
|
|||||||
Register(g_userSettings.game.bloomMode);
|
Register(g_userSettings.game.bloomMode);
|
||||||
Register(g_userSettings.game.bloomMultiplier);
|
Register(g_userSettings.game.bloomMultiplier);
|
||||||
Register(g_userSettings.game.disableWaterRefraction);
|
Register(g_userSettings.game.disableWaterRefraction);
|
||||||
|
Register(g_userSettings.game.enableTextureReplacements);
|
||||||
Register(g_userSettings.game.internalResolutionScale);
|
Register(g_userSettings.game.internalResolutionScale);
|
||||||
Register(g_userSettings.game.shadowResolutionMultiplier);
|
Register(g_userSettings.game.shadowResolutionMultiplier);
|
||||||
Register(g_userSettings.game.enableDepthOfField);
|
Register(g_userSettings.game.enableDepthOfField);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ Rml::String current_controller_name(int port) {
|
|||||||
Rml::String controller_index_name(u32 index) {
|
Rml::String controller_index_name(u32 index) {
|
||||||
const char* name = PADGetNameForControllerIndex(index);
|
const char* name = PADGetNameForControllerIndex(index);
|
||||||
if (name == nullptr) {
|
if (name == nullptr) {
|
||||||
return fmt::format("Controller {}", index + 1);
|
return fmt::format("Device {}", index + 1);
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ Rml::String native_axis_name(const PADAxisMapping& mapping, SDL_Gamepad* gamepad
|
|||||||
return native_button_name(gamepad, static_cast<u32>(mapping.nativeButton));
|
return native_button_name(gamepad, static_cast<u32>(mapping.nativeButton));
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Not bound";
|
return "Not Bound";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_dpad_button(PADButton button) {
|
bool is_dpad_button(PADButton button) {
|
||||||
@@ -162,7 +162,7 @@ bool keyboard_escape_pressed() {
|
|||||||
|
|
||||||
Rml::String keyboard_key_name(s32 scancode) {
|
Rml::String keyboard_key_name(s32 scancode) {
|
||||||
if (scancode == PAD_KEY_INVALID) {
|
if (scancode == PAD_KEY_INVALID) {
|
||||||
return "Not bound";
|
return "Not Bound";
|
||||||
}
|
}
|
||||||
switch (scancode) {
|
switch (scancode) {
|
||||||
case PAD_KEY_MOUSE_LEFT:
|
case PAD_KEY_MOUSE_LEFT:
|
||||||
@@ -303,7 +303,7 @@ void ControllerConfigWindow::build_port_tab(Rml::Element* content, int port) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
addPageButton(Page::Controller, "Controller", [port] { return current_controller_name(port); }, [] { return false; });
|
addPageButton(Page::Controller, "Device", [port] { return current_controller_name(port); }, [] { return false; });
|
||||||
addPageButton(Page::Buttons, "Buttons", [] { return Rml::String(">"); }, [] { return false; });
|
addPageButton(Page::Buttons, "Buttons", [] { return Rml::String(">"); }, [] { return false; });
|
||||||
addPageButton(Page::Triggers, "Triggers", [] { return Rml::String(">"); }, [] { return false; });
|
addPageButton(Page::Triggers, "Triggers", [] { return Rml::String(">"); }, [] { return false; });
|
||||||
addPageButton(Page::Sticks, "Sticks", [] { return Rml::String(">"); }, [] { return false; });
|
addPageButton(Page::Sticks, "Sticks", [] { return Rml::String(">"); }, [] { return false; });
|
||||||
@@ -349,7 +349,14 @@ void ControllerConfigWindow::build_port_tab(Rml::Element* content, int port) {
|
|||||||
rightPane, [](Pane& pane) {
|
rightPane, [](Pane& pane) {
|
||||||
pane.add_text("Treat analog trigger movement as digital L and R button input.");
|
pane.add_text("Treat analog trigger movement as digital L and R button input.");
|
||||||
});
|
});
|
||||||
|
leftPane.register_control(leftPane.add_button("Restore Default Controls").on_pressed([this, port] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
|
PADRestoreDefaultMapping(port);
|
||||||
|
}),
|
||||||
|
rightPane, [](Pane& pane) {
|
||||||
|
pane.clear();
|
||||||
|
pane.add_text("Restores all binding configurations for the currently selected device to their defaults.");
|
||||||
|
});
|
||||||
render_page(rightPane, port, mPage);
|
render_page(rightPane, port, mPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +372,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
[port] { return PADGetIndexForPort(port) < 0 && !keyboard_active(port); },
|
[port] { return PADGetIndexForPort(port) < 0 && !keyboard_active(port); },
|
||||||
})
|
})
|
||||||
.on_pressed([this, port] {
|
.on_pressed([this, port] {
|
||||||
mDoAud_seStartMenu(kSoundItemChange);
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
PADClearPort(port);
|
PADClearPort(port);
|
||||||
PADSetKeyboardActive(static_cast<u32>(port), FALSE);
|
PADSetKeyboardActive(static_cast<u32>(port), FALSE);
|
||||||
@@ -378,7 +385,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
.isSelected = [port] { return keyboard_active(port); },
|
.isSelected = [port] { return keyboard_active(port); },
|
||||||
})
|
})
|
||||||
.on_pressed([this, port] {
|
.on_pressed([this, port] {
|
||||||
mDoAud_seStartMenu(kSoundItemChange);
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
PADClearPort(port);
|
PADClearPort(port);
|
||||||
PADSetKeyboardActive(static_cast<u32>(port), TRUE);
|
PADSetKeyboardActive(static_cast<u32>(port), TRUE);
|
||||||
@@ -388,7 +395,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
|
|
||||||
const u32 controllerCount = PADCount();
|
const u32 controllerCount = PADCount();
|
||||||
if (controllerCount == 0) {
|
if (controllerCount == 0) {
|
||||||
pane.add_text("No controllers detected");
|
pane.add_text("No Device Detected");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,7 +407,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
[port, i] { return PADGetIndexForPort(port) == static_cast<s32>(i); },
|
[port, i] { return PADGetIndexForPort(port) == static_cast<s32>(i); },
|
||||||
})
|
})
|
||||||
.on_pressed([this, port, i] {
|
.on_pressed([this, port, i] {
|
||||||
mDoAud_seStartMenu(kSoundItemChange);
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
PADSetKeyboardActive(static_cast<u32>(port), FALSE);
|
PADSetKeyboardActive(static_cast<u32>(port), FALSE);
|
||||||
PADSetPortForIndex(i, port);
|
PADSetPortForIndex(i, port);
|
||||||
@@ -425,17 +432,18 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
PADKeyButtonBinding* bindings =
|
PADKeyButtonBinding* bindings =
|
||||||
PADGetKeyButtonBindings(static_cast<u32>(port), &count);
|
PADGetKeyButtonBindings(static_cast<u32>(port), &count);
|
||||||
if (bindings == nullptr) {
|
if (bindings == nullptr) {
|
||||||
return Rml::String("Not bound");
|
return Rml::String("Not Bound");
|
||||||
}
|
}
|
||||||
for (u32 i = 0; i < PAD_BUTTON_COUNT; ++i) {
|
for (u32 i = 0; i < PAD_BUTTON_COUNT; ++i) {
|
||||||
if (bindings[i].padButton == button) {
|
if (bindings[i].padButton == button) {
|
||||||
return keyboard_key_name(bindings[i].scancode);
|
return keyboard_key_name(bindings[i].scancode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Rml::String("Not bound");
|
return Rml::String("Not Bound");
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.on_pressed([this, port, button] {
|
.on_pressed([this, port, button] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
mPendingPort = port;
|
mPendingPort = port;
|
||||||
mPendingBindingArmed = false;
|
mPendingBindingArmed = false;
|
||||||
@@ -462,7 +470,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
u32 buttonCount = 0;
|
u32 buttonCount = 0;
|
||||||
PADButtonMapping* mappings = PADGetButtonMappings(port, &buttonCount);
|
PADButtonMapping* mappings = PADGetButtonMappings(port, &buttonCount);
|
||||||
if (mappings == nullptr) {
|
if (mappings == nullptr) {
|
||||||
pane.add_text("No controller selected");
|
pane.add_text("No Device Selected");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,6 +494,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.on_pressed([this, port, &mapping] {
|
.on_pressed([this, port, &mapping] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
mPendingPort = port;
|
mPendingPort = port;
|
||||||
mPendingBindingArmed = false;
|
mPendingBindingArmed = false;
|
||||||
@@ -512,6 +521,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.on_pressed([this, port, &mapping] {
|
.on_pressed([this, port, &mapping] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
mPendingPort = port;
|
mPendingPort = port;
|
||||||
mPendingBindingArmed = false;
|
mPendingBindingArmed = false;
|
||||||
@@ -535,17 +545,18 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
PADKeyButtonBinding* bindings =
|
PADKeyButtonBinding* bindings =
|
||||||
PADGetKeyButtonBindings(static_cast<u32>(port), &count);
|
PADGetKeyButtonBindings(static_cast<u32>(port), &count);
|
||||||
if (bindings == nullptr) {
|
if (bindings == nullptr) {
|
||||||
return Rml::String("Not bound");
|
return Rml::String("Not Bound");
|
||||||
}
|
}
|
||||||
for (u32 i = 0; i < PAD_BUTTON_COUNT; ++i) {
|
for (u32 i = 0; i < PAD_BUTTON_COUNT; ++i) {
|
||||||
if (bindings[i].padButton == button) {
|
if (bindings[i].padButton == button) {
|
||||||
return keyboard_key_name(bindings[i].scancode);
|
return keyboard_key_name(bindings[i].scancode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Rml::String("Not bound");
|
return Rml::String("Not Bound");
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.on_pressed([this, port, button] {
|
.on_pressed([this, port, button] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
mPendingPort = port;
|
mPendingPort = port;
|
||||||
mPendingBindingArmed = false;
|
mPendingBindingArmed = false;
|
||||||
@@ -566,17 +577,18 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
PADKeyAxisBinding* bindings =
|
PADKeyAxisBinding* bindings =
|
||||||
PADGetKeyAxisBindings(static_cast<u32>(port), &count);
|
PADGetKeyAxisBindings(static_cast<u32>(port), &count);
|
||||||
if (bindings == nullptr) {
|
if (bindings == nullptr) {
|
||||||
return Rml::String("Not bound");
|
return Rml::String("Not Bound");
|
||||||
}
|
}
|
||||||
for (u32 i = 0; i < PAD_AXIS_COUNT; ++i) {
|
for (u32 i = 0; i < PAD_AXIS_COUNT; ++i) {
|
||||||
if (bindings[i].padAxis == axis) {
|
if (bindings[i].padAxis == axis) {
|
||||||
return keyboard_key_name(bindings[i].scancode);
|
return keyboard_key_name(bindings[i].scancode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Rml::String("Not bound");
|
return Rml::String("Not Bound");
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.on_pressed([this, port, axis] {
|
.on_pressed([this, port, axis] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
mPendingPort = port;
|
mPendingPort = port;
|
||||||
mPendingBindingArmed = false;
|
mPendingBindingArmed = false;
|
||||||
@@ -599,7 +611,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
u32 buttonCount = 0;
|
u32 buttonCount = 0;
|
||||||
PADButtonMapping* buttons = PADGetButtonMappings(port, &buttonCount);
|
PADButtonMapping* buttons = PADGetButtonMappings(port, &buttonCount);
|
||||||
if (axes == nullptr && buttons == nullptr) {
|
if (axes == nullptr && buttons == nullptr) {
|
||||||
pane.add_text("No controller selected");
|
pane.add_text("No Device Selected");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,6 +635,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.on_pressed([this, port, &mapping] {
|
.on_pressed([this, port, &mapping] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
mPendingPort = port;
|
mPendingPort = port;
|
||||||
mPendingBindingArmed = false;
|
mPendingBindingArmed = false;
|
||||||
@@ -631,30 +644,33 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pane.add_section("Digital");
|
if (getSettings().backend.enableAdvancedSettings) {
|
||||||
if (buttons != nullptr) {
|
pane.add_section("Digital");
|
||||||
for (u32 i = 0; i < buttonCount; ++i) {
|
if (buttons != nullptr) {
|
||||||
PADButtonMapping& mapping = buttons[i];
|
for (u32 i = 0; i < buttonCount; ++i) {
|
||||||
if (mapping.padButton != PAD_TRIGGER_L && mapping.padButton != PAD_TRIGGER_R) {
|
PADButtonMapping& mapping = buttons[i];
|
||||||
continue;
|
if (mapping.padButton != PAD_TRIGGER_L && mapping.padButton != PAD_TRIGGER_R) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pane.add_select_button({
|
||||||
|
.key = PADGetButtonName(mapping.padButton),
|
||||||
|
.getValue =
|
||||||
|
[this, &mapping, gamepad] {
|
||||||
|
if (mPendingButtonMapping == &mapping) {
|
||||||
|
return pending_button_label();
|
||||||
|
}
|
||||||
|
return native_button_name(
|
||||||
|
gamepad, mapping.nativeButton);
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.on_pressed([this, port, &mapping] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
|
cancel_pending_binding();
|
||||||
|
mPendingPort = port;
|
||||||
|
mPendingBindingArmed = false;
|
||||||
|
mPendingButtonMapping = &mapping;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
pane.add_select_button({
|
|
||||||
.key = PADGetButtonName(mapping.padButton),
|
|
||||||
.getValue =
|
|
||||||
[this, &mapping, gamepad] {
|
|
||||||
if (mPendingButtonMapping == &mapping) {
|
|
||||||
return pending_button_label();
|
|
||||||
}
|
|
||||||
return native_button_name(
|
|
||||||
gamepad, mapping.nativeButton);
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.on_pressed([this, port, &mapping] {
|
|
||||||
cancel_pending_binding();
|
|
||||||
mPendingPort = port;
|
|
||||||
mPendingBindingArmed = false;
|
|
||||||
mPendingButtonMapping = &mapping;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -706,17 +722,18 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
PADKeyAxisBinding* bindings =
|
PADKeyAxisBinding* bindings =
|
||||||
PADGetKeyAxisBindings(static_cast<u32>(port), &count);
|
PADGetKeyAxisBindings(static_cast<u32>(port), &count);
|
||||||
if (bindings == nullptr) {
|
if (bindings == nullptr) {
|
||||||
return Rml::String("Not bound");
|
return Rml::String("Not Bound");
|
||||||
}
|
}
|
||||||
for (u32 i = 0; i < PAD_AXIS_COUNT; ++i) {
|
for (u32 i = 0; i < PAD_AXIS_COUNT; ++i) {
|
||||||
if (bindings[i].padAxis == axis) {
|
if (bindings[i].padAxis == axis) {
|
||||||
return keyboard_key_name(bindings[i].scancode);
|
return keyboard_key_name(bindings[i].scancode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Rml::String("Not bound");
|
return Rml::String("Not Bound");
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.on_pressed([this, port, axis] {
|
.on_pressed([this, port, axis] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
mPendingPort = port;
|
mPendingPort = port;
|
||||||
mPendingBindingArmed = false;
|
mPendingBindingArmed = false;
|
||||||
@@ -741,7 +758,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
u32 axisCount = 0;
|
u32 axisCount = 0;
|
||||||
PADAxisMapping* axes = PADGetAxisMappings(port, &axisCount);
|
PADAxisMapping* axes = PADGetAxisMappings(port, &axisCount);
|
||||||
if (axes == nullptr) {
|
if (axes == nullptr) {
|
||||||
pane.add_text("No controller selected");
|
pane.add_text("No Device Selected");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -762,6 +779,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.on_pressed([this, port, &mapping] {
|
.on_pressed([this, port, &mapping] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
mPendingPort = port;
|
mPendingPort = port;
|
||||||
mPendingBindingArmed = false;
|
mPendingBindingArmed = false;
|
||||||
@@ -907,6 +925,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.on_pressed([this, port, actionBind] {
|
.on_pressed([this, port, actionBind] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
mPendingPort = port;
|
mPendingPort = port;
|
||||||
mPendingBindingArmed = false;
|
mPendingBindingArmed = false;
|
||||||
@@ -926,7 +945,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
u32 buttonCount = 0;
|
u32 buttonCount = 0;
|
||||||
PADButtonMapping* mappings = PADGetButtonMappings(port, &buttonCount);
|
PADButtonMapping* mappings = PADGetButtonMappings(port, &buttonCount);
|
||||||
if (mappings == nullptr) {
|
if (mappings == nullptr) {
|
||||||
pane.add_text("No controller selected");
|
pane.add_text("No Device Selected");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -950,6 +969,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.on_pressed([this, port, actionBind] {
|
.on_pressed([this, port, actionBind] {
|
||||||
|
mDoAud_seStartMenu(kSoundClick);
|
||||||
cancel_pending_binding();
|
cancel_pending_binding();
|
||||||
mPendingPort = port;
|
mPendingPort = port;
|
||||||
mPendingBindingArmed = false;
|
mPendingBindingArmed = false;
|
||||||
@@ -1013,6 +1033,12 @@ void ControllerConfigWindow::poll_pending_binding() {
|
|||||||
const s32 nativeButton = PADGetNativeButtonPressed(mPendingPort);
|
const s32 nativeButton = PADGetNativeButtonPressed(mPendingPort);
|
||||||
if (nativeButton != -1) {
|
if (nativeButton != -1) {
|
||||||
const int completedPort = mPendingPort;
|
const int completedPort = mPendingPort;
|
||||||
|
if (mPendingButtonMapping->nativeButton == static_cast<u32>(nativeButton) &&
|
||||||
|
(mPendingButtonMapping->padButton != PAD_BUTTON_A &&
|
||||||
|
mPendingButtonMapping->padButton != PAD_BUTTON_B)) {
|
||||||
|
unmap_pending_binding();
|
||||||
|
return;
|
||||||
|
}
|
||||||
mPendingButtonMapping->nativeButton = static_cast<u32>(nativeButton);
|
mPendingButtonMapping->nativeButton = static_cast<u32>(nativeButton);
|
||||||
finish_pending_binding(completedPort);
|
finish_pending_binding(completedPort);
|
||||||
}
|
}
|
||||||
@@ -1023,6 +1049,10 @@ void ControllerConfigWindow::poll_pending_binding() {
|
|||||||
const PADSignedNativeAxis nativeAxis = PADGetNativeAxisPulled(mPendingPort);
|
const PADSignedNativeAxis nativeAxis = PADGetNativeAxisPulled(mPendingPort);
|
||||||
if (nativeAxis.nativeAxis != -1) {
|
if (nativeAxis.nativeAxis != -1) {
|
||||||
const int completedPort = mPendingPort;
|
const int completedPort = mPendingPort;
|
||||||
|
if (mPendingAxisMapping->nativeAxis.nativeAxis == nativeAxis.nativeAxis) {
|
||||||
|
unmap_pending_binding();
|
||||||
|
return;
|
||||||
|
}
|
||||||
mPendingAxisMapping->nativeAxis = nativeAxis;
|
mPendingAxisMapping->nativeAxis = nativeAxis;
|
||||||
mPendingAxisMapping->nativeButton = -1;
|
mPendingAxisMapping->nativeButton = -1;
|
||||||
finish_pending_binding(completedPort);
|
finish_pending_binding(completedPort);
|
||||||
@@ -1049,6 +1079,10 @@ void ControllerConfigWindow::poll_pending_binding() {
|
|||||||
|
|
||||||
if (button != -1) {
|
if (button != -1) {
|
||||||
const int completedPort = mPendingPort;
|
const int completedPort = mPendingPort;
|
||||||
|
if (mPendingActionBinding->getValue() == button) {
|
||||||
|
unmap_pending_binding();
|
||||||
|
return;
|
||||||
|
}
|
||||||
mPendingActionBinding->setValue(button);
|
mPendingActionBinding->setValue(button);
|
||||||
config::Save();
|
config::Save();
|
||||||
finish_pending_binding(completedPort);
|
finish_pending_binding(completedPort);
|
||||||
@@ -1058,6 +1092,7 @@ void ControllerConfigWindow::poll_pending_binding() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ControllerConfigWindow::finish_pending_binding(int completedPort) {
|
void ControllerConfigWindow::finish_pending_binding(int completedPort) {
|
||||||
|
mDoAud_seStartMenu(kSoundBindingChanged);
|
||||||
mPendingButtonMapping = nullptr;
|
mPendingButtonMapping = nullptr;
|
||||||
mPendingAxisMapping = nullptr;
|
mPendingAxisMapping = nullptr;
|
||||||
mPendingActionBinding = nullptr;
|
mPendingActionBinding = nullptr;
|
||||||
@@ -1110,11 +1145,11 @@ bool ControllerConfigWindow::pending_input_neutral() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rml::String ControllerConfigWindow::pending_button_label() const {
|
Rml::String ControllerConfigWindow::pending_button_label() const {
|
||||||
return mPendingBindingArmed ? "Press a button..." : "Waiting...";
|
return mPendingBindingArmed ? "Press a Key or Button..." : "Waiting...";
|
||||||
}
|
}
|
||||||
|
|
||||||
Rml::String ControllerConfigWindow::pending_axis_label() const {
|
Rml::String ControllerConfigWindow::pending_axis_label() const {
|
||||||
return mPendingBindingArmed ? "Move axis or press a button..." : "Waiting...";
|
return mPendingBindingArmed ? "Move Axis or press a Key or Button..." : "Waiting...";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerConfigWindow::cancel_pending_binding() {
|
void ControllerConfigWindow::cancel_pending_binding() {
|
||||||
@@ -1143,7 +1178,7 @@ void ControllerConfigWindow::finish_pending_key_binding() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rml::String ControllerConfigWindow::pending_key_label() const {
|
Rml::String ControllerConfigWindow::pending_key_label() const {
|
||||||
return mPendingBindingArmed ? "Press a key or mouse button..." : "Waiting...";
|
return mPendingBindingArmed ? "Press a Key or Mouse Button..." : "Waiting...";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerConfigWindow::stop_rumble_test() {
|
void ControllerConfigWindow::stop_rumble_test() {
|
||||||
@@ -1159,7 +1194,7 @@ void ControllerConfigWindow::stop_rumble_test() {
|
|||||||
|
|
||||||
Rml::String native_button_name(SDL_Gamepad* gamepad, u32 buttonUntyped) {
|
Rml::String native_button_name(SDL_Gamepad* gamepad, u32 buttonUntyped) {
|
||||||
if (buttonUntyped == PAD_NATIVE_BUTTON_INVALID) {
|
if (buttonUntyped == PAD_NATIVE_BUTTON_INVALID) {
|
||||||
return "Not bound";
|
return "Not Bound";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto button = static_cast<SDL_GamepadButton>(buttonUntyped);
|
auto button = static_cast<SDL_GamepadButton>(buttonUntyped);
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ Rml::String format_graphics_setting_value(GraphicsOption option, int value) {
|
|||||||
case BloomMode::Classic:
|
case BloomMode::Classic:
|
||||||
return "Classic";
|
return "Classic";
|
||||||
case BloomMode::Dusk:
|
case BloomMode::Dusk:
|
||||||
return "Dusk";
|
return "Dusklight";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GraphicsOption::BloomMultiplier:
|
case GraphicsOption::BloomMultiplier:
|
||||||
@@ -211,7 +211,7 @@ GraphicsTuner::GraphicsTuner(GraphicsTunerProps props, bool prelaunch)
|
|||||||
SteppedCarousel::Props{
|
SteppedCarousel::Props{
|
||||||
.min = mValueMin,
|
.min = mValueMin,
|
||||||
.max = mValueMax,
|
.max = mValueMax,
|
||||||
.step = 1,
|
.step = props.step,
|
||||||
.getValue = [this] { return get_value(mOption); },
|
.getValue = [this] { return get_value(mOption); },
|
||||||
.onChange = [this](int value) { set_value(mOption, value); },
|
.onChange = [this](int value) { set_value(mOption, value); },
|
||||||
.formatValue =
|
.formatValue =
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ struct GraphicsTunerProps {
|
|||||||
int valueMin = 0;
|
int valueMin = 0;
|
||||||
int valueMax = 0;
|
int valueMax = 0;
|
||||||
int defaultValue = 0;
|
int defaultValue = 0;
|
||||||
|
int step = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GraphicsTuner : public Document {
|
class GraphicsTuner : public Document {
|
||||||
|
|||||||
+20
-11
@@ -454,10 +454,18 @@ bool touch_moved_too_far(
|
|||||||
return delta.SquaredMagnitude() > threshold * threshold;
|
return delta.SquaredMagnitude() > threshold * threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_menu_key(Rml::Context& context) noexcept {
|
void emit_key_press(Rml::Context& context, Rml::Input::KeyIdentifier key) noexcept {
|
||||||
context.ProcessMouseLeave();
|
context.ProcessMouseLeave();
|
||||||
context.ProcessKeyDown(Rml::Input::KI_F1, 0);
|
context.ProcessKeyDown(key, 0);
|
||||||
context.ProcessKeyUp(Rml::Input::KI_F1, 0);
|
}
|
||||||
|
|
||||||
|
void emit_key_tap(Rml::Context& context, Rml::Input::KeyIdentifier key) noexcept {
|
||||||
|
emit_key_press(context, key);
|
||||||
|
context.ProcessKeyUp(key, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispatch_menu_key(Rml::Context& context) noexcept {
|
||||||
|
emit_key_tap(context, Rml::Input::KI_F1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handle_touch_menu_tap(Rml::Context& context, const SDL_Event& event) noexcept {
|
bool handle_touch_menu_tap(Rml::Context& context, const SDL_Event& event) noexcept {
|
||||||
@@ -627,7 +635,9 @@ void process_axis_direction(
|
|||||||
|
|
||||||
if (repeat->held) {
|
if (repeat->held) {
|
||||||
if (released) {
|
if (released) {
|
||||||
if (!repeat->pending) {
|
if (repeat->pending) {
|
||||||
|
emit_key_tap(context, repeat->key);
|
||||||
|
} else {
|
||||||
context.ProcessKeyUp(repeat->key, 0);
|
context.ProcessKeyUp(repeat->key, 0);
|
||||||
}
|
}
|
||||||
set_pad_button_held(port, heldPadButton, false);
|
set_pad_button_held(port, heldPadButton, false);
|
||||||
@@ -658,8 +668,7 @@ void process_axis_direction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
begin_gamepad_key(*repeat, key);
|
begin_gamepad_key(*repeat, key);
|
||||||
context.ProcessMouseLeave();
|
emit_key_press(context, key);
|
||||||
context.ProcessKeyDown(key, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -747,8 +756,7 @@ void handle_event(const SDL_Event& event) noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!deferred) {
|
if (!deferred) {
|
||||||
context->ProcessMouseLeave();
|
emit_key_press(*context, key);
|
||||||
context->ProcessKeyDown(key, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -760,7 +768,9 @@ void handle_event(const SDL_Event& event) noexcept {
|
|||||||
if (repeat != nullptr) {
|
if (repeat != nullptr) {
|
||||||
*repeat = {};
|
*repeat = {};
|
||||||
}
|
}
|
||||||
if (!wasPending) {
|
if (wasPending) {
|
||||||
|
emit_key_tap(*context, key);
|
||||||
|
} else {
|
||||||
context->ProcessKeyUp(key, 0);
|
context->ProcessKeyUp(key, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -787,8 +797,7 @@ void update_input() noexcept {
|
|||||||
repeat.pressedAt = now;
|
repeat.pressedAt = now;
|
||||||
repeat.nextRepeatAt =
|
repeat.nextRepeatAt =
|
||||||
repeat.repeatable ? now + kGamepadRepeatInitialDelay : 0.0;
|
repeat.repeatable ? now + kGamepadRepeatInitialDelay : 0.0;
|
||||||
context->ProcessMouseLeave();
|
emit_key_press(*context, repeat.key);
|
||||||
context->ProcessKeyDown(repeat.key, 0);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,13 +103,13 @@ Rml::Element* create_controller_warning(Rml::Element* parent) {
|
|||||||
|
|
||||||
auto* heading = append(elem, "heading");
|
auto* heading = append(elem, "heading");
|
||||||
auto* title = append(heading, "span");
|
auto* title = append(heading, "span");
|
||||||
title->SetInnerRML("No controller assigned");
|
title->SetInnerRML("No Device Assigned");
|
||||||
auto* icon = append(heading, "icon");
|
auto* icon = append(heading, "icon");
|
||||||
icon->SetClass("warning", true);
|
icon->SetClass("warning", true);
|
||||||
|
|
||||||
auto* message = append(elem, "message");
|
auto* message = append(elem, "message");
|
||||||
auto* content = append(message, "span");
|
auto* content = append(message, "span");
|
||||||
content->SetInnerRML("Configure controller port 1 in Settings.");
|
content->SetInnerRML("Configure <b>Port 1</b> in Settings.");
|
||||||
|
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
@@ -147,7 +147,7 @@ Rml::String back_button_name() {
|
|||||||
#if defined(TARGET_ANDROID) || (defined(__APPLE__) && TARGET_OS_IOS && !TARGET_OS_MACCATALYST)
|
#if defined(TARGET_ANDROID) || (defined(__APPLE__) && TARGET_OS_IOS && !TARGET_OS_MACCATALYST)
|
||||||
constexpr auto kMenuNotificationPrefix = "3-finger tap or";
|
constexpr auto kMenuNotificationPrefix = "3-finger tap or";
|
||||||
#else
|
#else
|
||||||
constexpr auto kMenuNotificationPrefix = "Press F1 or";
|
constexpr auto kMenuNotificationPrefix = "Press <b>F1</b> or";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Rml::Element* create_menu_notification(Rml::Element* parent) {
|
Rml::Element* create_menu_notification(Rml::Element* parent) {
|
||||||
@@ -169,7 +169,7 @@ Rml::Element* create_menu_notification(Rml::Element* parent) {
|
|||||||
append(row, "span")->SetInnerRML(kMenuNotificationPrefix);
|
append(row, "span")->SetInnerRML(kMenuNotificationPrefix);
|
||||||
auto* icon = append(row, "icon");
|
auto* icon = append(row, "icon");
|
||||||
icon->SetClass("controller", true);
|
icon->SetClass("controller", true);
|
||||||
append(row, "span")->SetInnerRML(escape(padButton));
|
append(row, "span")->SetInnerRML("<b>" + escape(padButton) + "</b>");
|
||||||
append(row, "span")->SetInnerRML("to open menu");
|
append(row, "span")->SetInnerRML("to open menu");
|
||||||
|
|
||||||
return elem;
|
return elem;
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ PresetWindow::PresetWindow() : WindowSmall("modal", "modal-dialog") {
|
|||||||
"Enhancements disabled to match the GameCube version. "
|
"Enhancements disabled to match the GameCube version. "
|
||||||
"Good for speedrunning or simple nostalgia!",
|
"Good for speedrunning or simple nostalgia!",
|
||||||
applyPresetClassic},
|
applyPresetClassic},
|
||||||
{"Dusk",
|
{"Dusklight",
|
||||||
"Graphics & quality of life tweaks, including some from the Wii U version. "
|
"Graphics & quality of life tweaks, including some from the Wii U version. "
|
||||||
"Our recommended way to play!",
|
"Our recommended way to play!",
|
||||||
applyPresetDusk},
|
applyPresetDusk},
|
||||||
|
|||||||
+16
-10
@@ -793,9 +793,16 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
|
|||||||
.valueMin = 0,
|
.valueMin = 0,
|
||||||
.valueMax = 100,
|
.valueMax = 100,
|
||||||
.defaultValue = 100,
|
.defaultValue = 100,
|
||||||
|
.step = 10,
|
||||||
}, mPrelaunch);
|
}, mPrelaunch);
|
||||||
|
|
||||||
leftPane.add_section("Rendering");
|
leftPane.add_section("Rendering");
|
||||||
|
config_bool_select(leftPane, rightPane, getSettings().game.enableTextureReplacements,
|
||||||
|
{
|
||||||
|
.key = "Use Texture Pack",
|
||||||
|
.helpText = "Enable installed texture replacements.",
|
||||||
|
.onChange = [](bool value) { aurora_set_texture_replacements_enabled(value); },
|
||||||
|
});
|
||||||
config_bool_select(leftPane, rightPane, getSettings().game.enableFrameInterpolation,
|
config_bool_select(leftPane, rightPane, getSettings().game.enableFrameInterpolation,
|
||||||
{
|
{
|
||||||
.key = "Unlock Framerate",
|
.key = "Unlock Framerate",
|
||||||
@@ -829,18 +836,18 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
leftPane.add_section("Controller");
|
leftPane.add_section("Inputs");
|
||||||
leftPane.register_control(leftPane.add_button("Configure Controller").on_pressed([this] {
|
leftPane.register_control(leftPane.add_button("Configure Inputs").on_pressed([this] {
|
||||||
push(std::make_unique<ControllerConfigWindow>(mPrelaunch));
|
push(std::make_unique<ControllerConfigWindow>(mPrelaunch));
|
||||||
}),
|
}),
|
||||||
rightPane, [](Pane& pane) {
|
rightPane, [](Pane& pane) {
|
||||||
pane.clear();
|
pane.clear();
|
||||||
pane.add_text("Open controller binding configuration.");
|
pane.add_text("Open input binding configuration.");
|
||||||
});
|
});
|
||||||
config_bool_select(leftPane, rightPane, getSettings().game.allowBackgroundInput,
|
config_bool_select(leftPane, rightPane, getSettings().game.allowBackgroundInput,
|
||||||
{
|
{
|
||||||
.key = "Allow Background Input",
|
.key = "Allow Background Inputs",
|
||||||
.helpText = "Allow controller input even when the game window is not focused.",
|
.helpText = "Allow inputs even when the game window is not focused.",
|
||||||
.onChange = [](bool value) { aurora_set_background_input(value); },
|
.onChange = [](bool value) { aurora_set_background_input(value); },
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1068,8 +1075,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
|
|||||||
addOption("Faster Tears of Light", getSettings().game.fastTears,
|
addOption("Faster Tears of Light", getSettings().game.fastTears,
|
||||||
"Tears of Light dropped by Shadow Insects pop out faster like the HD version.");
|
"Tears of Light dropped by Shadow Insects pop out faster like the HD version.");
|
||||||
addSpeedrunDisabledOption("Autosave", getSettings().game.autoSave,
|
addSpeedrunDisabledOption("Autosave", getSettings().game.autoSave,
|
||||||
"Autosaves the game when going to a new area, opening a dungeon door, "
|
"Autosaves the game when going to a new area or opening a dungeon door.");
|
||||||
"or getting a new item.");
|
|
||||||
addOption("Instant Saves", getSettings().game.instantSaves,
|
addOption("Instant Saves", getSettings().game.instantSaves,
|
||||||
"Skips the delay when writing to the Memory Card.");
|
"Skips the delay when writing to the Memory Card.");
|
||||||
addOption("Hold B for Instant Text", getSettings().game.instantText,
|
addOption("Hold B for Instant Text", getSettings().game.instantText,
|
||||||
@@ -1166,7 +1172,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
|
|||||||
addCheat("Always Greatspin", getSettings().game.alwaysGreatspin,
|
addCheat("Always Greatspin", getSettings().game.alwaysGreatspin,
|
||||||
"Allows the Great Spin attack without requiring full health.");
|
"Allows the Great Spin attack without requiring full health.");
|
||||||
addCheat("Fast Iron Boots", getSettings().game.enableFastIronBoots,
|
addCheat("Fast Iron Boots", getSettings().game.enableFastIronBoots,
|
||||||
"Speeds up movement while wearing the Iron Boots.");
|
"Speeds up movement while heavy, including wearing the Iron Boots, holding the Ball and Chain, wearing Magic Armor without rupees, etc.");
|
||||||
addCheat("Can Transform Anywhere", getSettings().game.canTransformAnywhere,
|
addCheat("Can Transform Anywhere", getSettings().game.canTransformAnywhere,
|
||||||
"Allows transforming even if NPCs are looking.");
|
"Allows transforming even if NPCs are looking.");
|
||||||
addCheat("Fast Roll", getSettings().game.fastRoll,
|
addCheat("Fast Roll", getSettings().game.fastRoll,
|
||||||
@@ -1248,7 +1254,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
|
|||||||
});
|
});
|
||||||
pane.add_button(
|
pane.add_button(
|
||||||
{
|
{
|
||||||
.text = "Controller",
|
.text = "Missing Device",
|
||||||
.isSelected =
|
.isSelected =
|
||||||
[] { return getSettings().game.enableControllerToasts.getValue(); },
|
[] { return getSettings().game.enableControllerToasts.getValue(); },
|
||||||
})
|
})
|
||||||
@@ -1301,7 +1307,7 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
|
|||||||
config_bool_select(leftPane, rightPane, getSettings().game.enableDiscordPresence,
|
config_bool_select(leftPane, rightPane, getSettings().game.enableDiscordPresence,
|
||||||
{
|
{
|
||||||
.key = "Enable Discord Rich Presence",
|
.key = "Enable Discord Rich Presence",
|
||||||
.helpText = "Enable Dusk to integrate with Discord Rich Presence. This allows Discord to show your status in-game.",
|
.helpText = "Enable Dusklight to integrate with Discord Rich Presence. This allows Discord to show your status in-game.",
|
||||||
.onChange = [](bool enabled) {
|
.onChange = [](bool enabled) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
dusk::discord::initialize();
|
dusk::discord::initialize();
|
||||||
|
|||||||
+16
-2
@@ -11,7 +11,9 @@
|
|||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
#include "aurora/lib/window.hpp"
|
#include "aurora/lib/window.hpp"
|
||||||
|
#include "dusk/dusk.h"
|
||||||
#include "dusk/io.hpp"
|
#include "dusk/io.hpp"
|
||||||
|
#include "dusk/config.hpp"
|
||||||
#include "input.hpp"
|
#include "input.hpp"
|
||||||
#include "prelaunch.hpp"
|
#include "prelaunch.hpp"
|
||||||
#include "window.hpp"
|
#include "window.hpp"
|
||||||
@@ -130,7 +132,7 @@ void handle_event(const SDL_Event& event) noexcept {
|
|||||||
if (getSettings().game.enableControllerToasts) {
|
if (getSettings().game.enableControllerToasts) {
|
||||||
const char* name = SDL_GetGamepadName(gamepad);
|
const char* name = SDL_GetGamepadName(gamepad);
|
||||||
Rml::String content = fmt::format("<span>{}</span>", name ? name : "[Unknown]");
|
Rml::String content = fmt::format("<span>{}</span>", name ? name : "[Unknown]");
|
||||||
Rml::String title = "Controller connected";
|
Rml::String title = "Device Connected";
|
||||||
if (const char* icon = connection_state_icon(SDL_GetGamepadConnectionState(gamepad))) {
|
if (const char* icon = connection_state_icon(SDL_GetGamepadConnectionState(gamepad))) {
|
||||||
title = fmt::format(
|
title = fmt::format(
|
||||||
"<row><span>{}</span> <icon class=\"connection\">&#x{};</icon></row>", title,
|
"<row><span>{}</span> <icon class=\"connection\">&#x{};</icon></row>", title,
|
||||||
@@ -163,12 +165,24 @@ void handle_event(const SDL_Event& event) noexcept {
|
|||||||
const char* name = SDL_GetGamepadNameForID(event.gdevice.which);
|
const char* name = SDL_GetGamepadNameForID(event.gdevice.which);
|
||||||
push_toast({
|
push_toast({
|
||||||
.type = "controller",
|
.type = "controller",
|
||||||
.title = "Controller disconnected",
|
.title = "Device Disconnected",
|
||||||
.content = name ? name : "[Unknown]",
|
.content = name ? name : "[Unknown]",
|
||||||
.duration = std::chrono::seconds(4),
|
.duration = std::chrono::seconds(4),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
sConnectedGamepads.erase(event.gdevice.which);
|
sConnectedGamepads.erase(event.gdevice.which);
|
||||||
|
} else if (event.type == SDL_EVENT_WINDOW_MOVED || event.type == SDL_EVENT_WINDOW_RESIZED) {
|
||||||
|
int x, y;
|
||||||
|
if (SDL_GetWindowPosition(aurora::window::get_sdl_window(), &x, &y)) {
|
||||||
|
getSettings().video.windowPositionX.setValue(x);
|
||||||
|
getSettings().video.windowPositionY.setValue(y);
|
||||||
|
}
|
||||||
|
int width, height;
|
||||||
|
if (SDL_GetWindowSize(aurora::window::get_sdl_window(), &width, &height)) {
|
||||||
|
getSettings().video.windowWidth.setValue(width);
|
||||||
|
getSettings().video.windowHeight.setValue(height);
|
||||||
|
}
|
||||||
|
config::Save();
|
||||||
}
|
}
|
||||||
input::handle_event(event);
|
input::handle_event(event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ struct Toast {
|
|||||||
constexpr u32 kSoundClick = Z2SE_SY_CURSOR_OK;
|
constexpr u32 kSoundClick = Z2SE_SY_CURSOR_OK;
|
||||||
// "Play" button clicked/pressed
|
// "Play" button clicked/pressed
|
||||||
constexpr u32 kSoundPlay = Z2SE_SY_ITEM_COMBINE_ON;
|
constexpr u32 kSoundPlay = Z2SE_SY_ITEM_COMBINE_ON;
|
||||||
|
// Input binding changed
|
||||||
|
constexpr u32 kSoundBindingChanged = Z2SE_SY_ITEM_SET_X;
|
||||||
|
|
||||||
// Menu button pressed (open/close menu bar or hide/show the active window)
|
// Menu button pressed (open/close menu bar or hide/show the active window)
|
||||||
constexpr u32 kSoundMenuOpen = Z2SE_SY_MENU_SUB_IN;
|
constexpr u32 kSoundMenuOpen = Z2SE_SY_MENU_SUB_IN;
|
||||||
@@ -49,6 +51,8 @@ constexpr u32 kSoundItemDisable = Z2SE_SUBJ_VIEW_OUT;
|
|||||||
|
|
||||||
// Achievement unlocked
|
// Achievement unlocked
|
||||||
constexpr u32 kSoundAchievementUnlock = Z2SE_NAVI_FLY;
|
constexpr u32 kSoundAchievementUnlock = Z2SE_NAVI_FLY;
|
||||||
|
// Warning prompt
|
||||||
|
constexpr u32 kSoundWarning = Z2SE_SY_COW_GET_IN;
|
||||||
|
|
||||||
struct Insets {
|
struct Insets {
|
||||||
float top = 0.0f;
|
float top = 0.0f;
|
||||||
|
|||||||
@@ -807,7 +807,7 @@ static void duskExecute() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dusk::getSettings().game.infiniteRupees) {
|
if (dusk::getSettings().game.infiniteRupees) {
|
||||||
dComIfGs_setRupee(9999);
|
dComIfGs_setRupee(dComIfGs_getRupeeMax());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dusk::getSettings().game.infiniteOxygen) {
|
if (dusk::getSettings().game.infiniteOxygen) {
|
||||||
|
|||||||
@@ -12,6 +12,12 @@
|
|||||||
|
|
||||||
|
|
||||||
static int fpcLnIt_MethodCall(create_tag_class* i_createTag, method_filter* i_filter) {
|
static int fpcLnIt_MethodCall(create_tag_class* i_createTag, method_filter* i_filter) {
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
// on init_state==3 fpcEx_ExecuteQTo already ran (layer_tag.layer is NULL)
|
||||||
|
if (static_cast<base_process_class*>(i_createTag->mpTagData)->state.init_state == 3) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
layer_class* layer = static_cast<base_process_class*>(i_createTag->mpTagData)->layer_tag.layer;
|
layer_class* layer = static_cast<base_process_class*>(i_createTag->mpTagData)->layer_tag.layer;
|
||||||
layer_class* save_layer = fpcLy_CurrentLayer();
|
layer_class* save_layer = fpcLy_CurrentLayer();
|
||||||
int ret;
|
int ret;
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ void mDoLib_project(Vec* src, Vec* dst) {
|
|||||||
xSize = FB_WIDTH;
|
xSize = FB_WIDTH;
|
||||||
} else {
|
} else {
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
xOffset = mDoGph_gInf_c::getSafeMinXF();
|
xOffset = mDoGph_gInf_c::getMinXF();
|
||||||
xSize = viewPort->width * mDoGph_gInf_c::hudAspectScaleUp;
|
xSize = mDoGph_gInf_c::getWidthF();
|
||||||
#else
|
#else
|
||||||
xOffset = viewPort->x_orig;
|
xOffset = viewPort->x_orig;
|
||||||
xSize = viewPort->width;
|
xSize = viewPort->width;
|
||||||
|
|||||||
@@ -551,10 +551,10 @@ int game_main(int argc, char* argv[]) {
|
|||||||
config.cachePath = reinterpret_cast<const char*>(cachePathString.c_str());
|
config.cachePath = reinterpret_cast<const char*>(cachePathString.c_str());
|
||||||
config.vsync = dusk::getSettings().video.enableVsync;
|
config.vsync = dusk::getSettings().video.enableVsync;
|
||||||
config.startFullscreen = dusk::getSettings().video.enableFullscreen;
|
config.startFullscreen = dusk::getSettings().video.enableFullscreen;
|
||||||
config.windowPosX = -1;
|
config.windowPosX = dusk::getSettings().video.windowPositionX;
|
||||||
config.windowPosY = -1;
|
config.windowPosY = dusk::getSettings().video.windowPositionY;
|
||||||
config.windowWidth = defaultWindowWidth * 2;
|
config.windowWidth = dusk::getSettings().video.windowWidth;
|
||||||
config.windowHeight = defaultWindowHeight * 2;
|
config.windowHeight = dusk::getSettings().video.windowHeight;
|
||||||
config.desiredBackend = ResolveDesiredBackend(parsed_arg_options);
|
config.desiredBackend = ResolveDesiredBackend(parsed_arg_options);
|
||||||
config.logCallback = &aurora_log_callback;
|
config.logCallback = &aurora_log_callback;
|
||||||
config.logLevel = startupLogLevel;
|
config.logLevel = startupLogLevel;
|
||||||
@@ -563,7 +563,7 @@ int game_main(int argc, char* argv[]) {
|
|||||||
config.allowJoystickBackgroundEvents = dusk::getSettings().game.allowBackgroundInput;
|
config.allowJoystickBackgroundEvents = dusk::getSettings().game.allowBackgroundInput;
|
||||||
config.pauseOnFocusLost = dusk::getSettings().game.pauseOnFocusLost;
|
config.pauseOnFocusLost = dusk::getSettings().game.pauseOnFocusLost;
|
||||||
config.imGuiInitCallback = &aurora_imgui_init_callback;
|
config.imGuiInitCallback = &aurora_imgui_init_callback;
|
||||||
config.allowTextureReplacements = true;
|
config.allowTextureReplacements = dusk::getSettings().game.enableTextureReplacements;
|
||||||
config.allowTextureDumps = false;
|
config.allowTextureDumps = false;
|
||||||
auroraInfo = aurora_initialize(argc, argv, &config);
|
auroraInfo = aurora_initialize(argc, argv, &config);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user