Compare commits

..

77 Commits

Author SHA1 Message Date
Luke Street bc651d2592 (TEMP) Update aurora 2026-06-16 11:50:04 -06:00
Luke Street 3798ce2810 (TEMP) Enable Tracy in CI builds 2026-06-16 09:54:49 -06:00
Luke Street facbf35343 Update aurora 2026-06-16 01:53:04 -06:00
Luke Street 7a34830dc7 Update aurora 2026-06-16 01:40:00 -06:00
Luke Street e4557efb23 Disable PkgConfig on Windows 2026-06-16 01:39:54 -06:00
Luke Street 42e12eb5ab Update aurora & fix RCSS warning 2026-06-16 00:14:19 -06:00
Luke Street 16cc37ca10 Android: Call Surface.setFrameRate & update it 2026-06-15 23:39:36 -06:00
Luke Street 44cb2c84ba Update aurora 2026-06-15 23:07:00 -06:00
Luke Street 8e9d4d624a Fix hookshot hanging w/ touch controls 2026-06-15 22:55:30 -06:00
Luke Street db87b91954 Update aurora & redraw hearts guage on HUD scale change 2026-06-15 22:46:50 -06:00
Luke Street ad53af5c78 Touch controls (#2053)
* WIP touch controls

* Action icons

* Updates

* Don't mutate freeCamera config; allow switching between touch and controller cam

* Wow

* Fix build & add Skip button

* Fix build & add settings

* RCSS cleanup

* Dpad and fishing, might redo

* Add menu mouse controls

* More pointer & fix icons

* Optimizations & introduce layout system

* Update aurora

* Implement touch controls layout editor

* Cleanup & fixes

* Allow disabling mouse/touch in menus

* More fixes
2026-06-15 12:48:04 -06:00
qubitnano a6e5160c71 flake.nix: xxHash -> xxhash (#2058)
warning: 'xxHash' has been renamed to 'xxhash'
2026-06-15 12:47:40 -06:00
doop 38a0a7be0b Always create a save file if one doesn't exist (#2028)
* Always create a save file if one doesn't exist

* Fix MSVC build

* Re-add accidentally deleted line

* Integrate into d_file_select state machine & put behind instantSaves

---------

Co-authored-by: Luke Street <luke@street.dev>
2026-06-15 12:47:23 -06:00
Luke Street 02fdde3768 Scale map rendering with IR (#2056)
* Scale map rendering with IR + scale config

* Remove config option
2026-06-14 22:41:33 -06:00
Luke Street 33e13d508b Use Aurora-provided FPS for overlay 2026-06-14 11:28:19 -06:00
Luke Street afc3376aec Update aurora 2026-06-14 01:11:14 -06:00
matthewdavidrichardanderson b07fb50128 monkey crash fix (#2034)
* monkey fix 🐒

* wrap saru_p clear in target_pc

* Clear monkey leader pointer on delete

---------

Co-authored-by: matthewdavidrichardanderson <matthewdavidrichardanderson@mfb.com>
Co-authored-by: Luke Street <luke@street.dev>
2026-06-13 22:39:30 -06:00
Kyrio d0894853d7 Add setting to memorize window size (#2025)
* Add "Memorize Window Size" setting

* Code review #2025

* memorize -> remember, helpText revision

---------

Co-authored-by: Irastris <irastris15@gmail.com>
2026-06-13 22:47:18 -04:00
Luke Street cacb768725 Updatea aurora & set DOWNLOAD_EXTRACT_TIMESTAMP FALSE 2026-06-13 10:44:51 -06:00
Luke Street 00707024bb Update aurora & flower/grass draw batching 2026-06-13 10:40:57 -06:00
Luke Street 7c5ed6a0e1 Fix OSWaitCond implementation 2026-06-10 00:18:14 -06:00
Luke Street 131a09f317 Implement JPA particle batching 2026-06-09 23:47:45 -06:00
Luke Street a58f9c7b43 Update Android shell to SDL 3.4.10 2026-06-09 22:51:23 -06:00
Luke Street 7290649bb8 Prune old logs & dawn_cache.db entries 2026-06-09 00:58:17 -06:00
Luke Street 34e1e740ab Update aurora 2026-06-08 23:14:51 -06:00
Luke Street a58f64ed80 Update aurora 2026-06-08 22:49:28 -06:00
Luke Street 28a37f6b4f Check for sNoUseDrawMtxPtr in J3DModel::entry 2026-06-08 22:14:34 -06:00
Luke Street 285691cd19 Add -debug-asan presets with AddressSanitizer 2026-06-08 22:14:10 -06:00
Luke Street 93e33ecf1a Cap map resolution multiplier
Resolves #1058
Resolves #1422
Resolves #1668
2026-06-08 00:08:00 -06:00
Reilly Brogan e26fab71d6 Add DUSK_PACKAGE_INSTALL (#1966)
Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>
2026-06-07 23:33:49 -06:00
Luke Street 824389f871 Remove embedded gamecontrollerdb.txt (#2018)
But still load from the data dir if
it exists there (for user overrides)
2026-06-07 22:30:07 -06:00
Luke Street aa42265041 Fix Impaz expression animation OOB read (#2017)
Resolves #1152
2026-06-07 22:29:52 -06:00
BoLThompson 8b7ed4b5da Interpolation fixes (fishing rod, key door chains, hookshot chain) (#2008)
* fishing rod line (item and minigame) interpolated

* small key, big key door chains interpolated

* hookshot chain interpolated
2026-06-08 00:28:48 -04:00
SuperDude88 f33746f373 Alternate Config Variable Migration Method (#1577)
* Use Explicit Template Specialization

- Move migration of FrameInterpMode to use a unique specialization of loadFromJson

This avoids coding special cases into the main template, which I think is more sustainable in the long-run if we need to migrate other settings ever

* Error for Default Migration

- Add error message in the config log for default migration

Not a fatal, just a clear signal that you should handle your enum cases explicitly to make sure they're right
2026-06-07 21:39:02 -06:00
Nathan Mena 18c1d11335 Fix mirror mode sign arrows (#1704)
* Manually defined specific Wii messages to be returned when mirror mode is enabled

* Fixed random hanging on some messages
2026-06-07 21:18:58 -06:00
SuperDude88 710f252d53 Fix Respawning in Final Zant Phase (#2013)
Zant was trying to get the player's position before the player was even created

Based on the fix for camera/peahat load order
2026-06-07 21:18:45 -06:00
SuperDude88 2a92a67b87 Fix Mirror Mode Poe Counter (#1997)
Fixes #1817
2026-06-07 21:18:33 -06:00
SuperDude88 0d05f9b75b More Magic Armor Options (#1691)
* More Magic Armor Options

- Add a 3rd option to lose rupees only on damage

* More Choices

- Add cosmetic and double defense options

These both have been requested a couple times

* Shorten Description

The description was very, very long before

* Web Editor Got Me

Fix my syntax
2026-06-07 21:18:23 -06:00
ZipoLabs e27cce0e3c Add Green Chu merging functionality to "Restore Wii 1.0 Glitches" setting (#2000) 2026-06-07 21:18:10 -06:00
SuperDude88 511721f4d5 Fix Ganondorf's Cape Texture (#2016)
* Cape Texture Fix

- Load pos/norm/texcoord data directly from the REL

Before the hardcoded array was LE but being treated as BE, now we load it directly from the REL so treating it as BE is the correct behavior

* Fix Cape Tearing

- Update the cached textures when the cape is torn, reset the texture when creating the actor
2026-06-07 21:14:10 -06:00
Luke Street 08e0f4a2ee Update aurora & remove old pipeline cache handling 2026-06-06 09:41:07 -06:00
doop 7a900471bf Clamp flycam FOV (#1996) 2026-06-05 17:05:54 -04:00
MelonSpeedruns d9d9966f8f Time Freezing Camera (#1787)
Thanks to @bkd89 for the idea!

Co-authored-by: MelonSpeedruns <melonspeedruns@stratobox.net>
2026-06-05 00:17:06 -06:00
Kevin Lema 8705e75b9d Add HUD scale setting (#1387)
* Add HUD scale setting

Adds a "HUD Scale" preference (50%–200%) that scales the gameplay HUD
(hearts, magic/lantern meter, light drops, rupees/keys, action buttons
and the mini-map) without affecting dialog boxes or menus.

Each HUD group is scaled around its own pane origin and nudged toward
its anchor corner (via dApplyHudCorner) so it stays put against the
screen edge instead of drifting toward the centre when shrunk. The
mini-map is scaled and shifted in d_meter_map so its bottom-left corner
stays anchored. The setting is clamped to a safe range and is a no-op on
non-PC targets. It is disabled in the menu while Minimal HUD is enabled.

Signed-off-by: kevin Lema <kevin.soesto@gmail.com>

* Scale remaining gameplay HUD elements with HUD scale

Extends the HUD Scale setting to the item ammo counters, the lantern oil
  gauge and the small-key counter, and gives the oil/magic meter a reduced
  horizontal anchor pull so it stays on-screen at small scales.

Signed-off-by: kevin Lema <kevin.soesto@gmail.com>

* Update settings.cpp

Signed-off-by: kevin Lema <kevin.soesto@gmail.com>

---------

Signed-off-by: kevin Lema <kevin.soesto@gmail.com>
2026-06-05 00:14:09 -06:00
Luke Street 1b42c4ecac ci: Build Android w/ release & LTO 2026-06-05 00:12:59 -06:00
SuperDude88 24ca190029 Adjust Total Achievement Count (#1924)
- Don't count the glitched achievements towards the total so that they appear over 100%
2026-06-05 00:05:47 -06:00
doop eefa69b53d Re-enable JParticle interpolation and fix emitter direction issue (#1968)
* Re-enable JParticle interpolation

* Ensure emitter direction is valid for JPA interp

Fixes #618.

* Don't `calcWorkData` if we don't need to
2026-06-05 00:05:20 -06:00
Luke Street da3ac9f546 ci: Build with shared vcruntime 2026-06-05 00:03:43 -06:00
Luke Street 7f306fe1ec Update aurora 2026-06-05 00:03:29 -06:00
Luke Street 358de64570 ci: Use mold linker on Linux 2026-06-04 23:30:30 -06:00
Luke Street e484a10018 tvOS fixes 2026-06-04 23:28:44 -06:00
Luke Street 0936115483 Optimize display lists in J3DShapeDraw
This is a stop-gap until DL optimization
is upstreamed to Aurora.
2026-06-04 23:27:30 -06:00
Luke Street b00b7f8f1b More texture caching 2026-06-04 23:21:13 -06:00
Luke Street 08c4442fdf Update aurora 2026-06-03 21:01:39 -06:00
Pieter-Jan Briers 74f20c38e0 Don't send debug groups to Aurora if not enabled (#1984)
Intended together with https://github.com/encounter/aurora/pull/221
2026-06-03 20:58:35 -06:00
Pieter-Jan Briers b7d32918bd Fix a warning (#1985)
Lol
2026-06-03 20:29:54 -06:00
Joshua Trees e99b604dd2 Fix flake.nix for systems where nod must build from source (#1987)
This should actually be fixed upstream, but until then...

See here for more details:

https://github.com/NixOS/nixpkgs/issues/144170

Co-authored-by: Joshua Trees <gh@jtrees.io>
2026-06-03 20:29:41 -06:00
MelonSpeedruns 2376e0102e TPHD Button Fishing (#1949)
Co-authored-by: MelonSpeedruns <melonspeedruns@stratobox.net>
2026-06-03 13:35:51 -04:00
Luke Street 5a9bd6f8dc Update aurora 2026-06-03 02:17:58 -06:00
Luke Street 62a26a639d Bump CMAKE_OSX_DEPLOYMENT_TARGET to 12.0 2026-06-03 02:17:54 -06:00
Luke Street 1a247c2977 Pass CMAKE_OSX_* to libjpeg-turbo build 2026-06-03 02:17:46 -06:00
Luke Street ef122efccd Update aurora 2026-06-03 00:56:44 -06:00
Luke Street deadde352c Update aurora 2026-06-03 00:02:47 -06:00
Luke Street 460b96c709 More Tracy zones 2026-06-03 00:01:34 -06:00
Pieter-Jan Briers f8ba14ea8f Optimize some special kankyo draw packets (housi, snow, odour) (#1970)
* Slight dKankyo_housi_Packet documentation

* Optimize dKyr_drawHousi (twilight squares)

Now a single draw call rather than like 300

* Optimize dKyr_drawSnow

Snowpeak stonks rising

* Optimize dKyr_odour_draw
2026-06-02 23:47:34 -06:00
Irastris bd9b81f700 Add mouse input option for the third-person camera (#1011)
* Untie existing mouse logic from gyro

* A bit more mouse cleanup before I start building off it

* Rebase and last bit of cleanup

* Fix rebase mistake, don't apply invertFirstPerson to gyro or mouse input

* Remove the deprecated ImGui toast system

* Add Mouse Camera option in preparation for its use

* WIP, add mouse controls for the third-person camera

* Various helpText revisions

* Enable free camera on horseback

* Untie mouse camera and free camera options
Either being enabled now allows the underlying freecam logic to run

* Allow simultaneous C-stick and mouse input

* Combine mouse sensitivities for both aim and camera

* Add option for inverting mouse Y

* Refactor cursor visibility handling

* Tighten aim capture condition and constrain cursor to window region

* Tidying my trash

* Last bit of housekeeping so I'm satisfied

* Don't write code while sleep deprived

* Fix my sloppy merge and a few helpText updates

* Disable control stick aim when mouse aim is active

* Use same conditions for cursor grabbing as for capture
2026-06-01 23:37:53 -06:00
Reilly Brogan b531936a1f linux: Add metainfo file (#1860)
* linux: Add metainfo file

Split from https://github.com/TwilitRealm/dusklight/pull/1191 and adjusted for the correct appId and to remove any trademarks.

Credit to @Gabantax

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>

* Update metainfo per suggestions

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>

---------

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>
2026-06-01 20:24:02 -06:00
Pieter-Jan Briers 21692d5a78 Fix portable mode Unicode (#1893)
* Fix portable mode Unicode

Fixes https://github.com/TwilitRealm/dusklight/issues/1839

* Use path_from_utf8 instead

Huh yeah sure we have that apparently
2026-06-01 20:23:28 -06:00
Reilly Brogan 7af51e53bd Update aurora and adapt for libzstd changes (#1950)
* Update aurora and adapt for libzstd changes

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>

* Fix android build failure with zstd

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>

* Another attempt at fixing Android

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>

---------

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>
2026-06-01 20:23:13 -06:00
qubitnano bd90c3fc69 flake.nix: devendor aurora, add BUILD_SHARED_LIBS=OFF (#1956)
* flake.nix: devendor aurora

* flake.nix: nixfmt

* flake.nix: add BUILD_SHARED_LIBS=OFF
2026-06-01 20:22:45 -06:00
Luke Street 37abcaf616 Use BUILD_SHARED_LIBS=OFF on base linux/macos presets 2026-05-31 21:30:25 -06:00
Luke Street b26f3f7f51 Update aurora & fix rebuilding on iOS reconfigure 2026-05-31 17:18:11 -06:00
Pieter-Jan Briers 81caa89e12 Update Aurora & use new texture replacements API (#1935)
Cherry picked from TPHD branch

Co-authored-by: Luke Street <luke@street.dev>
2026-05-30 19:57:17 -06:00
Luke Street bc3cdcc955 Revert "Adds a new cheat that let you transform from the start of the game. (…" (#1927)
This reverts commit 62c19c0f64.
2026-05-29 21:20:15 -06:00
tomlube bf0dc85468 Revert "Added Sword and Shield skip Achievement" (#1917) 2026-05-29 15:14:05 -04:00
tomlube 656346a900 Merge pull request #1909 from 5upern1ce/sword-and-shield-skip
Added Sword and Shield skip Achievement
2026-05-29 15:11:46 -04:00
Supern_Ice 5269eadfaf Added Sword and Shield skip Achievement 2026-05-29 15:26:26 +01:00
189 changed files with 10808 additions and 5474 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install ninja-build clang lld openssl libcurl4-openssl-dev \
sudo apt-get -y install ninja-build clang lld mold openssl libcurl4-openssl-dev \
zlib1g-dev libglu1-mesa-dev libdbus-1-dev libvulkan-dev libxi-dev libxrandr-dev libasound2-dev \
libpulse-dev libudev-dev libpng-dev libncurses5-dev libx11-xcb-dev libfreetype-dev \
libxinerama-dev libxcursor-dev python3-markupsafe libgtk-3-dev libssl-dev \
+1 -1
View File
@@ -1,3 +1,3 @@
[submodule "extern/aurora"]
path = extern/aurora
url = https://github.com/Lurs/aurora.git
url = https://github.com/encounter/aurora.git
+64 -15
View File
@@ -126,28 +126,57 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "_cmake")
option(ENABLE_ASAN "Enable AddressSanitizer" OFF)
if (ENABLE_ASAN)
if (CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" AND
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/fsanitize=address>)
add_link_options(/fsanitize=address /INCREMENTAL:NO)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "ProgramDatabase")
foreach (_lang C CXX)
foreach (_rtc_flag /RTC1 /RTCc /RTCs /RTCu)
string(REPLACE "${_rtc_flag}" "" CMAKE_${_lang}_FLAGS_DEBUG "${CMAKE_${_lang}_FLAGS_DEBUG}")
endforeach ()
endforeach ()
elseif (CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "GNU" AND
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
add_compile_options(
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fsanitize=address>
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fno-omit-frame-pointer>
)
add_link_options(-fsanitize=address)
else ()
message(FATAL_ERROR "ENABLE_ASAN requires GNU-like or MSVC-like C/C++ compiler frontends")
endif ()
add_compile_definitions(NDEBUG_SANITIZER) # Avoids absl issue with SwissTable debug code
message(STATUS "dusklight: Enabled AddressSanitizer")
endif ()
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
set(DAWN_USE_WAYLAND ON CACHE BOOL "Enable support for Wayland surface" FORCE)
endif ()
set(AURORA_ENABLE_DVD ON CACHE BOOL "Enable DVD API support" FORCE)
set(AURORA_ENABLE_CARD ON CACHE BOOL "Enable CARD API support" FORCE)
set(AURORA_ENABLE_RMLUI ON CACHE BOOL "Enable RmlUi UI support" FORCE)
# Force Freetype (pulled by aurora/RmlUi) to use its bundled mini-zlib.
# Otherwise its find_package(ZLIB) latches onto our FetchContent'd shared zlib,
# duplicating inflate*/inflateInit2_ symbols against zlibstatic.
set(FT_DISABLE_ZLIB TRUE CACHE BOOL "" FORCE)
add_subdirectory(extern/aurora EXCLUDE_FROM_ALL)
target_compile_definitions(aurora_mtx PRIVATE MTX_USE_PS=1)
add_subdirectory(libs/freeverb)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DUSK_GFX_DEBUG_GROUPS_DEFAULT ON)
else ()
set(DUSK_GFX_DEBUG_GROUPS_DEFAULT OFF)
endif ()
option(DUSK_BUILD_WARNINGS "Enable compiler warnings (off by default)")
option(DUSK_SELECTED_OPT "If on, selected parts of the project will be compiled with optimizations on Debug, intending to make the game run at 30 FPS. Note for MSVC: you will need to remove '/RTC1' from your debug flags in CMake.")
option(DUSK_MOVIE_SUPPORT "If on, compile against libjpeg-turbo to enable THP file decoding" ON)
option(DUSK_ENABLE_UPDATE_CHECKER "Enable update checking support" ON)
option(DUSK_TPHD "Enable TPHD asset support" ON)
option(DUSK_ENABLE_SENTRY_NATIVE "Enable sentry-native crash reporting support" OFF)
option(DUSK_PACKAGE_INSTALL "Install Dusklight with a Linux-native file structure" OFF)
option(DUSK_GFX_DEBUG_GROUPS "Report debug groups to the native graphics API" ${DUSK_GFX_DEBUG_GROUPS_DEFAULT})
set(DUSK_SENTRY_DSN "" CACHE STRING "Sentry DSN")
set(DUSK_SENTRY_ENVIRONMENT "development" CACHE STRING "Sentry environment")
@@ -195,6 +224,8 @@ if (DUSK_MOVIE_SUPPORT)
CMAKE_MSVC_RUNTIME_LIBRARY
CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
CMAKE_OSX_ARCHITECTURES
CMAKE_OSX_DEPLOYMENT_TARGET
CMAKE_OSX_SYSROOT
DEPLOYMENT_TARGET
ENABLE_ARC
ENABLE_BITCODE
@@ -260,13 +291,13 @@ message(STATUS "dusklight: Fetching cxxopts")
FetchContent_Declare(cxxopts
URL https://github.com/jarro2783/cxxopts/archive/refs/tags/v3.3.1.tar.gz
URL_HASH SHA256=3bfc70542c521d4b55a46429d808178916a579b28d048bd8c727ee76c39e2072
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
)
message(STATUS "dusklight: Fetching nlohmann/json")
FetchContent_Declare(json
URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz
URL_HASH SHA256=42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
)
FetchContent_MakeAvailable(cxxopts json)
@@ -333,9 +364,6 @@ source_group("dolzel" FILES ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${REL_FILES})
source_group("dusklight" FILES ${DUSK_FILES} ${DUSK_HTTP_BACKEND_FILES})
set(GAME_COMPILE_DEFS TARGET_PC WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0 MTX_USE_PS=1)
if (DUSK_TPHD)
list(APPEND GAME_COMPILE_DEFS DUSK_TPHD=1)
endif ()
set(GAME_INCLUDE_DIRS
include
@@ -350,7 +378,7 @@ set(GAME_INCLUDE_DIRS
find_package(Threads REQUIRED)
set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd
aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt
Threads::Threads libzstd_static ZLIB::ZLIB)
Threads::Threads zstd::libzstd)
if (DUSK_ENABLE_SENTRY_NATIVE)
list(APPEND GAME_LIBS sentry)
@@ -422,6 +450,16 @@ if(ANDROID)
list(APPEND GAME_COMPILE_DEFS TARGET_ANDROID=1)
endif ()
if (DUSK_PACKAGE_INSTALL)
include(GNUInstallDirs)
list(APPEND GAME_COMPILE_DEFS DUSK_ASSET_DIR="${CMAKE_INSTALL_FULL_DATADIR}/dusklight/")
endif ()
if (DUSK_GFX_DEBUG_GROUPS)
list(APPEND GAME_COMPILE_DEFS DUSK_GFX_DEBUG_GROUPS=1)
target_compile_definitions(aurora_gx PRIVATE AURORA_GFX_DEBUG_GROUPS)
endif ()
# game_debug is for game code files that we know work when compiled with DEBUG=1
# Of course, if building a release build, this distinction is irrelevant
set(GAME_DEBUG_FILES
@@ -478,6 +516,9 @@ if(ANDROID)
else ()
add_executable(dusklight ${DUSK_FILES})
endif ()
if (ENABLE_ASAN)
target_sources(dusklight PRIVATE src/dusk/asan_options.c)
endif ()
target_compile_definitions(dusklight PRIVATE ${GAME_COMPILE_DEFS})
target_include_directories(dusklight PRIVATE ${GAME_INCLUDE_DIRS})
@@ -640,12 +681,20 @@ set(EXTRA_TARGETS "")
if (TARGET crashpad_handler)
list(APPEND EXTRA_TARGETS crashpad_handler)
endif ()
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX})
if (DUSK_PACKAGE_INSTALL)
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_BINDIR})
else()
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX})
endif()
aurora_install_runtime_dlls(dusklight ${CMAKE_INSTALL_PREFIX})
if (NOT APPLE)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_PREFIX})
if (DUSK_PACKAGE_INSTALL)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/dusklight)
else()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_PREFIX})
endif()
endif ()
if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo AND NOT DUSK_PACKAGE_INSTALL)
set(DEBUG_FILES_LIST "")
foreach (target IN LISTS BINARY_TARGETS EXTRA_TARGETS)
get_target_output_name(${target} output_name)
+125 -22
View File
@@ -19,7 +19,19 @@
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded"
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDLL"
}
},
{
"name": "release",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDLL",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": {
"type": "BOOL",
"value": true
}
}
},
{
@@ -40,12 +52,26 @@
}
}
},
{
"name": "asan",
"hidden": true,
"cacheVariables": {
"ENABLE_ASAN": {
"type": "BOOL",
"value": true
}
}
},
{
"name": "linux-default",
"displayName": "Linux (default)",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
},
"vendor": {
@@ -67,6 +93,15 @@
"linux-default"
]
},
{
"name": "linux-default-debug-asan",
"displayName": "Linux (default) Debug ASan",
"inherits": [
"debug",
"linux-default",
"asan"
]
},
{
"name": "linux-default-relwithdebinfo",
"displayName": "Linux (default) RelWithDebInfo",
@@ -94,6 +129,15 @@
"linux-clang"
]
},
{
"name": "linux-clang-debug-asan",
"displayName": "Linux (Clang) Debug ASan",
"inherits": [
"debug",
"linux-clang",
"asan"
]
},
{
"name": "linux-clang-relwithdebinfo",
"displayName": "Linux (Clang) RelWithDebInfo",
@@ -114,7 +158,11 @@
"cacheVariables": {
"CMAKE_C_COMPILER": "cl",
"CMAKE_CXX_COMPILER": "cl",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install",
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
}
},
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": {
@@ -132,6 +180,15 @@
"windows-msvc"
]
},
{
"name": "windows-msvc-debug-asan",
"displayName": "Windows (MSVC) Debug ASan",
"inherits": [
"debug",
"windows-msvc",
"asan"
]
},
{
"name": "windows-msvc-relwithdebinfo",
"displayName": "Windows (MSVC) RelWithDebInfo",
@@ -201,6 +258,10 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
},
"vendor": {
@@ -219,6 +280,15 @@
"macos-default"
]
},
{
"name": "macos-default-debug-asan",
"displayName": "macOS (default) Debug ASan",
"inherits": [
"debug",
"macos-default",
"asan"
]
},
{
"name": "macos-default-relwithdebinfo",
"displayName": "macOS (default) RelWithDebInfo",
@@ -284,24 +354,21 @@
"type": "BOOL",
"value": false
},
"ENABLE_ARC": {
"type": "BOOL",
"value": false
},
"Rust_CARGO_TARGET": "aarch64-apple-tvos",
"Rust_TOOLCHAIN": "nightly",
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_DISABLE_FIND_PACKAGE_BZip2": {
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_LibLZMA": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_zstd": {
"type": "BOOL",
"value": true
}
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew"
},
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": {
@@ -327,8 +394,14 @@
"type": "BOOL",
"value": false
},
"AURORA_SDL3_VERSION": "3.4.8",
"AURORA_SDL3_REF": "refs/tags/release-3.4.8"
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_zstd": {
"type": "BOOL",
"value": true
}
}
},
{
@@ -356,7 +429,8 @@
"hidden": true,
"inherits": [
"android-base",
"ci"
"ci",
"release"
],
"cacheVariables": {
"DUSK_ENABLE_SENTRY_NATIVE": {
@@ -384,7 +458,8 @@
"ci"
],
"cacheVariables": {
"AURORA_SDL3_PROVIDER": "vendor"
"AURORA_SDL3_PROVIDER": "vendor",
"CMAKE_LINKER_TYPE": "MOLD"
}
},
{
@@ -413,12 +488,8 @@
"type": "BOOL",
"value": true
},
"CMAKE_OSX_DEPLOYMENT_TARGET": "11.0",
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew",
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
}
"CMAKE_OSX_DEPLOYMENT_TARGET": "12.0",
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew"
}
},
{
@@ -473,7 +544,15 @@
"type": "FILEPATH",
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
},
"VCPKG_TARGET_TRIPLET": "x64-windows"
"VCPKG_TARGET_TRIPLET": "x64-windows",
"TRACY_ENABLE": {
"type": "BOOL",
"value": true
},
"TRACY_ON_DEMAND": {
"type": "BOOL",
"value": true
}
}
},
{
@@ -508,6 +587,12 @@
"description": "Linux (default) debug build",
"displayName": "Linux (default) Debug"
},
{
"name": "linux-default-debug-asan",
"configurePreset": "linux-default-debug-asan",
"description": "Linux (default) debug build with AddressSanitizer",
"displayName": "Linux (default) Debug ASan"
},
{
"name": "linux-default-relwithdebinfo",
"configurePreset": "linux-default-relwithdebinfo",
@@ -520,6 +605,12 @@
"description": "Linux (Clang) debug build",
"displayName": "Linux (Clang) Debug"
},
{
"name": "linux-clang-debug-asan",
"configurePreset": "linux-clang-debug-asan",
"description": "Linux (Clang) debug build with AddressSanitizer",
"displayName": "Linux (Clang) Debug ASan"
},
{
"name": "linux-clang-relwithdebinfo",
"configurePreset": "linux-clang-relwithdebinfo",
@@ -532,6 +623,12 @@
"description": "macOS debug build",
"displayName": "macOS Debug"
},
{
"name": "macos-default-debug-asan",
"configurePreset": "macos-default-debug-asan",
"description": "macOS debug build with AddressSanitizer",
"displayName": "macOS Debug ASan"
},
{
"name": "macos-default-relwithdebinfo",
"configurePreset": "macos-default-relwithdebinfo",
@@ -589,6 +686,12 @@
"description": "Windows (MSVC) debug build",
"displayName": "Windows (MSVC) Debug"
},
{
"name": "windows-msvc-debug-asan",
"configurePreset": "windows-msvc-debug-asan",
"description": "Windows (MSVC) debug build with AddressSanitizer",
"displayName": "Windows (MSVC) Debug ASan"
},
{
"name": "windows-msvc-relwithdebinfo",
"configurePreset": "windows-msvc-relwithdebinfo",
+4
View File
@@ -180,6 +180,7 @@ cmake --build --preset macos-default-relwithdebinfo
Alternate presets available:
* `macos-default-debug`: Clang, Debug
* `macos-default-debug-asan`: Clang, Debug, AddressSanitizer
**ninja (Linux)**
@@ -191,8 +192,10 @@ cmake --build --preset linux-default-relwithdebinfo
Alternate presets available:
* `linux-default-debug`: GCC, Debug
* `linux-default-debug-asan`: GCC, Debug, AddressSanitizer
* `linux-clang-relwithdebinfo`: Clang, RelWithDebInfo
* `linux-clang-debug`: Clang, Debug
* `linux-clang-debug-asan`: Clang, Debug, AddressSanitizer
**ninja (Windows)**
@@ -204,6 +207,7 @@ cmake --build --preset windows-msvc-relwithdebinfo
Alternate presets available:
* `windows-msvc-debug`: MSVC, Debug
* `windows-msvc-debug-asan`: MSVC, Debug, AddressSanitizer
* `windows-clang-relwithdebinfo`: Clang-cl, RelWithDebInfo
* `windows-clang-debug`: Clang-cl, Debug
+1 -1
+19 -12
View File
@@ -246,18 +246,6 @@ set(DOLZEL_FILES
if(DEBUG)
list(APPEND DOLZEL_FILES src/d/d_event_debug.cpp)
endif(DEBUG)
if (DUSK_TPHD)
list(APPEND DOLZEL_FILES
src/dusk/tphd/TphdPack.hpp
src/dusk/tphd/TphdPack.cpp
src/dusk/tphd/GtxParser.hpp
src/dusk/tphd/GtxParser.cpp
src/dusk/tphd/AddrLib.hpp
src/dusk/tphd/AddrLib.cpp
src/dusk/tphd/HdAssetLayer.hpp
src/dusk/tphd/HdAssetLayer.cpp
)
endif(DUSK_TPHD)
set(Z2AUDIOLIB_FILES
src/Z2AudioLib/Z2Calc.cpp
@@ -1430,7 +1418,11 @@ set(DUSK_FILES
include/dusk/scope_guard.hpp
src/dusk/dvd_asset.cpp
src/d/actor/d_a_alink_dusk.cpp
src/dusk/android_frame_rate.hpp
src/dusk/android_frame_rate.cpp
src/dusk/asserts.cpp
src/dusk/batch.cpp
src/dusk/batch.hpp
src/dusk/config.cpp
src/dusk/crash_handler.cpp
src/dusk/crash_reporting.cpp
@@ -1444,6 +1436,9 @@ set(DUSK_FILES
src/dusk/game_clock.cpp
src/dusk/globals.cpp
src/dusk/gyro.cpp
include/dusk/menu_pointer.h
src/dusk/menu_pointer.cpp
src/dusk/mouse.cpp
src/dusk/gamepad_color.cpp
src/dusk/autosave.cpp
src/dusk/http/http.hpp
@@ -1454,6 +1449,9 @@ set(DUSK_FILES
src/dusk/speedrun.cpp
src/dusk/string.cpp
src/dusk/stubs.cpp
include/dusk/texture_replacements.hpp
src/dusk/texture_replacements.cpp
src/dusk/touch_camera.cpp
src/dusk/update_check.cpp
src/dusk/update_check.hpp
#src/dusk/m_Do_ext_dusk.cpp
@@ -1483,6 +1481,7 @@ set(DUSK_FILES
src/dusk/ui/button.hpp
src/dusk/ui/component.cpp
src/dusk/ui/component.hpp
src/dusk/ui/controls.hpp
src/dusk/ui/controller_config.cpp
src/dusk/ui/controller_config.hpp
src/dusk/ui/document.cpp
@@ -1495,6 +1494,8 @@ set(DUSK_FILES
src/dusk/ui/graphics_tuner.hpp
src/dusk/ui/input.cpp
src/dusk/ui/input.hpp
src/dusk/ui/icon_provider.cpp
src/dusk/ui/icon_provider.hpp
src/dusk/ui/modal.cpp
src/dusk/ui/modal.hpp
src/dusk/ui/nav_types.hpp
@@ -1520,6 +1521,12 @@ set(DUSK_FILES
src/dusk/ui/string_button.hpp
src/dusk/ui/tab_bar.cpp
src/dusk/ui/tab_bar.hpp
src/dusk/ui/touch_controls_common.cpp
src/dusk/ui/touch_controls_common.hpp
src/dusk/ui/touch_controls.cpp
src/dusk/ui/touch_controls.hpp
src/dusk/ui/touch_controls_editor.cpp
src/dusk/ui/touch_controls_editor.hpp
src/dusk/ui/ui.cpp
src/dusk/ui/ui.hpp
src/dusk/ui/warp.cpp
+32
View File
@@ -0,0 +1,32 @@
From f69d29614644f9963f5cb3f828b58575d60a1c5a Mon Sep 17 00:00:00 2001
From: Joshua Trees <gh@jtrees.io>
Date: Thu, 4 Jun 2026 01:04:04 +0100
Subject: [PATCH] fix cmake paths
---
cmake/nodConfig.cmake.in | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/cmake/nodConfig.cmake.in b/cmake/nodConfig.cmake.in
index 0969382..2a24a88 100644
--- a/cmake/nodConfig.cmake.in
+++ b/cmake/nodConfig.cmake.in
@@ -1,12 +1,12 @@
@PACKAGE_INIT@
-set(_nod_libdir "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_LIBDIR@")
-set(_nod_incdir "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@")
+set(_nod_libdir "@CMAKE_INSTALL_FULL_LIBDIR@")
+set(_nod_incdir "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
if (NOT TARGET nod::nod_shared AND NOT TARGET nod::nod_static)
# Shared library
if (WIN32)
- set(_nod_dll "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_BINDIR@/${CMAKE_SHARED_LIBRARY_PREFIX}nod${CMAKE_SHARED_LIBRARY_SUFFIX}")
+ set(_nod_dll "@CMAKE_INSTALL_FULL_BINDIR@/${CMAKE_SHARED_LIBRARY_PREFIX}nod${CMAKE_SHARED_LIBRARY_SUFFIX}")
set(_nod_implib "${_nod_libdir}/${CMAKE_IMPORT_LIBRARY_PREFIX}nod${CMAKE_IMPORT_LIBRARY_SUFFIX}")
if (EXISTS "${_nod_dll}")
add_library(nod::nod_shared SHARED IMPORTED)
--
2.53.0
+128 -116
View File
@@ -57,12 +57,22 @@
inherit (pkgs.stdenv.hostPlatform) isDarwin;
hasNodPrebuilt = nodPrebuiltInfo ? ${system};
aurora = pkgs.fetchFromGitHub {
owner = "encounter";
repo = "aurora";
rev = "10006618ee493f248b8597e4dfa1d2871d76a1d9";
hash = "sha256-lY2xuVyB7aPJ9+2wwLRB3F5U/BuPSxdSpegdG+qNd9o=";
};
aurora = builtins.pathExists "${self}/extern/aurora/CMakeLists.txt";
needSubmodules = ''
dusklight: The aurora submodule is not vendored. Add submodules=1 to build.
As a flake input:
dusklight.url = "git+https://github.com/TwilitRealm/dusklight?ref=main&submodules=1";
nix command:
nix run 'git+https://github.com/TwilitRealm/dusklight?submodules=1'
Local checkout:
nix run '.?submodules=1#dusklight'
'';
dawn = pkgs.fetchzip {
url = "https://github.com/encounter/dawn-build/releases/download/${dawnVersion}/dawn-${dawnInfo.${system}.triple}.tar.gz";
@@ -86,6 +96,7 @@
rev = nodVersion;
hash = "sha256-+zrtVzjo0+X/6uMcNUn1+FaSR+jOhrcQSDNBFjw0NDs=";
};
patches = [ ./fix-cmake-paths.patch ];
cargoDeps = pkgs.rustPlatform.importCargoLock {
lockFile = "${finalAttrs.src}/Cargo.lock";
};
@@ -127,7 +138,7 @@
NOD_PREBUILT = nod;
CXXOPTS = pkgs.cxxopts.src;
JSON = pkgs.nlohmann_json.src;
XXHASH = pkgs.xxHash.src;
XXHASH = pkgs.xxhash.src;
ZSTD = pkgs.zstd.src;
FMT = pkgs.fetchzip {
url = "https://github.com/fmtlib/fmt/archive/refs/tags/11.1.4.tar.gz";
@@ -153,119 +164,120 @@
};
};
dusklight = pkgs.stdenv.mkDerivation {
pname = "dusklight";
version = versionSuffix;
src = ./.;
dusklight =
if !aurora then
throw needSubmodules
else
pkgs.stdenv.mkDerivation {
pname = "dusklight";
version = versionSuffix;
src = ./.;
postUnpack = ''
chmod -R u+w "$sourceRoot"
rm -rf "$sourceRoot/extern/aurora"
mkdir -p "$sourceRoot/extern"
cp -r ${aurora} "$sourceRoot/extern/aurora"
chmod -R u+w "$sourceRoot/extern/aurora"
substituteInPlace "$sourceRoot/extern/aurora/CMakeLists.txt" \
--replace-warn "add_subdirectory(tests)" ""
'';
nativeBuildInputs = [
pkgs.cmake
pkgs.ninja
pkgs.pkg-config
pkgs.python3
pkgs.python3Packages.markupsafe
]
++ lib.optionals (!isDarwin) [ pkgs.autoPatchelfHook ];
buildInputs = [
pkgs.sdl3
pkgs.freetype
pkgs.zstd
pkgs.cxxopts
pkgs.nlohmann_json
pkgs.xxHash
pkgs.abseil-cpp
pkgs.zlib
pkgs.libpng
pkgs.libjpeg_turbo
pkgs.curl
pkgs.openssl
]
++ lib.optionals isDarwin [
pkgs.apple-sdk_15
pkgs.libiconv
]
++ lib.optionals (!isDarwin) [
pkgs.libGL
pkgs.libGLU
pkgs.libglvnd
pkgs.vulkan-loader
pkgs.libX11
pkgs.libxcb
pkgs.libXcursor
pkgs.libxi
pkgs.libxrandr
pkgs.libxscrnsaver
pkgs.libxtst
pkgs.libxinerama
pkgs.libxkbcommon
pkgs.wayland
pkgs.libdecor
pkgs.alsa-lib
pkgs.libpulseaudio
pkgs.pipewire
pkgs.dbus
pkgs.udev
pkgs.libusb1
pkgs.libunwind
pkgs.gtk3
];
cmakeBuildType = "RelWithDebInfo";
ninjaFlags = [ "dusklight" ];
cmakeFlags = [
"-DDUSK_VERSION_OVERRIDE=${versionSuffix}"
"-DFETCHCONTENT_FULLY_DISCONNECTED=ON"
"-DAURORA_DAWN_PROVIDER=package"
"-DAURORA_DAWN_LINKAGE=static"
"-DAURORA_NOD_PROVIDER=package"
"-DAURORA_NOD_LINKAGE=static"
"-DAURORA_SDL3_PROVIDER=system"
]
++ lib.mapAttrsToList (key: src: "-DFETCHCONTENT_SOURCE_DIR_${key}=${src}") fetchContentDirs;
installPhase =
if isDarwin then
''
runHook preInstall
mkdir -p "$out/Applications"
cp -r Dusklight.app "$out/Applications/Dusklight.app"
runHook postInstall
''
else
''
runHook preInstall
install -Dm755 dusklight "$out/bin/dusklight"
cp -r "$src/res" "$out/bin/res"
install -Dm644 "$src/platforms/freedesktop/dev.twilitrealm.dusk.desktop" \
"$out/share/applications/dev.twilitrealm.dusk.desktop"
for size in 16 32 48 64 128 256 512 1024; do
install -Dm644 "$src/platforms/freedesktop/''${size}x''${size}/apps/dev.twilitrealm.dusk.png" \
"$out/share/icons/hicolor/''${size}x''${size}/apps/dev.twilitrealm.dusk.png"
done
runHook postInstall
postUnpack = ''
chmod -R u+w "$sourceRoot"
substituteInPlace "$sourceRoot/extern/aurora/CMakeLists.txt" \
--replace-warn "add_subdirectory(tests)" ""
'';
dontStrip = true;
nativeBuildInputs = [
pkgs.cmake
pkgs.ninja
pkgs.pkg-config
pkgs.python3
pkgs.python3Packages.markupsafe
]
++ lib.optionals (!isDarwin) [ pkgs.autoPatchelfHook ];
meta = {
description = "Dusklight native PC port of the Twilight Princess decompilation";
homepage = "https://github.com/zeldaret/tp";
platforms = supportedSystems;
mainProgram = "dusklight";
};
};
buildInputs = [
pkgs.sdl3
pkgs.freetype
pkgs.zstd
pkgs.cxxopts
pkgs.nlohmann_json
pkgs.xxhash
pkgs.abseil-cpp
pkgs.zlib
pkgs.libpng
pkgs.libjpeg_turbo
pkgs.curl
pkgs.openssl
]
++ lib.optionals isDarwin [
pkgs.apple-sdk_15
pkgs.libiconv
]
++ lib.optionals (!isDarwin) [
pkgs.libGL
pkgs.libGLU
pkgs.libglvnd
pkgs.vulkan-loader
pkgs.libX11
pkgs.libxcb
pkgs.libXcursor
pkgs.libxi
pkgs.libxrandr
pkgs.libxscrnsaver
pkgs.libxtst
pkgs.libxinerama
pkgs.libxkbcommon
pkgs.wayland
pkgs.libdecor
pkgs.alsa-lib
pkgs.libpulseaudio
pkgs.pipewire
pkgs.dbus
pkgs.udev
pkgs.libusb1
pkgs.libunwind
pkgs.gtk3
nod
];
cmakeBuildType = "RelWithDebInfo";
ninjaFlags = [ "dusklight" ];
cmakeFlags = [
"-DDUSK_VERSION_OVERRIDE=${versionSuffix}"
"-DFETCHCONTENT_FULLY_DISCONNECTED=ON"
"-DAURORA_DAWN_PROVIDER=package"
"-DAURORA_DAWN_LINKAGE=static"
"-DAURORA_NOD_PROVIDER=system"
"-DAURORA_SDL3_PROVIDER=system"
"-DBUILD_SHARED_LIBS=OFF"
]
++ lib.mapAttrsToList (key: src: "-DFETCHCONTENT_SOURCE_DIR_${key}=${src}") fetchContentDirs;
installPhase =
if isDarwin then
''
runHook preInstall
mkdir -p "$out/Applications"
cp -r Dusklight.app "$out/Applications/Dusklight.app"
runHook postInstall
''
else
''
runHook preInstall
install -Dm755 dusklight "$out/bin/dusklight"
cp -r "$src/res" "$out/bin/res"
install -Dm644 "$src/platforms/freedesktop/dev.twilitrealm.dusk.desktop" \
"$out/share/applications/dev.twilitrealm.dusk.desktop"
for size in 16 32 48 64 128 256 512 1024; do
install -Dm644 "$src/platforms/freedesktop/''${size}x''${size}/apps/dev.twilitrealm.dusk.png" \
"$out/share/icons/hicolor/''${size}x''${size}/apps/dev.twilitrealm.dusk.png"
done
runHook postInstall
'';
dontStrip = true;
meta = {
description = "Dusklight native PC port of the Twilight Princess decompilation";
homepage = "https://github.com/zeldaret/tp";
platforms = supportedSystems;
mainProgram = "dusklight";
};
};
# Tooling common to every supported host (Linux and macOS).
commonDevTools = [
+18 -1
View File
@@ -88,6 +88,10 @@ public:
/* 0x02C */ cXyz field_0x2c;
/* 0x038 */ cXyz field_0x38[60];
/* 0x308 */ cXyz field_0x308[60];
#if TARGET_PC
TGXTexObj mBlurTexObj;
ResTIMG* mpCachedBlurTex = nullptr;
#endif
}; // Size = 0x5D8
class dAlink_bottleWaterPcallBack_c : public JPAParticleCallBack {
@@ -4551,7 +4555,8 @@ public:
#if TARGET_PC
void handleWolfHowl();
void handleQuickTransform();
bool checkGyroAimContext();
bool checkAimContext();
bool checkTouchAimCaptureContext();
void onIronBallChainInterpCallback();
@@ -4564,6 +4569,18 @@ public:
cXyz mIBChainInterpCurrHandRoot;
bool mIBChainInterpPrevValid;
bool mIBChainInterpCurrValid;
cXyz mHsChainInterpPrevTop;
cXyz mHsChainInterpCurrTop;
cXyz mHsChainInterpPrevRoot;
cXyz mHsChainInterpCurrRoot;
cXyz mHsChainInterpPrevSubRoot;
cXyz mHsChainInterpCurrSubRoot;
cXyz mHsChainInterpPrevSubTop;
cXyz mHsChainInterpCurrSubTop;
bool mHsChainInterpPrevValid;
bool mHsChainInterpCurrValid;
bool mIsRollstab = false;
#endif
}; // Size: 0x385C
+7 -2
View File
@@ -299,8 +299,13 @@ public:
/* 0x168C */ u8 field_0x168c;
/* 0x168D */ u8 field_0x168d;
/* 0x168E */ u8 HIOInit;
#if TARGET_PC
cXyz mLineInterpPrev[MG_ROD_LURE_LINE_LEN];
cXyz mLineInterpCurr[MG_ROD_LURE_LINE_LEN];
bool mLineInterpPrevValid;
bool mLineInterpCurrValid;
#endif
};
STATIC_ASSERT(sizeof(dmg_rod_class) == 0x1690);
#endif /* D_A_MG_ROD_H */
+9
View File
@@ -66,9 +66,18 @@ public:
/* 0x2CA7 */ s8 hide_lock;
/* 0x2CA8 */ cXyz field_0x2ca8;
/* 0x2CB4 */ u8 field_0x2cb4;
#if TARGET_PC
Mtx mChainInterpPrev[6][16];
Mtx mChainInterpCurr[6][16];
bool mChainInterpPrevValid;
bool mChainInterpCurrValid;
#endif
};
#if !TARGET_PC
STATIC_ASSERT(sizeof(obj_keyhole_class) == 0x2CB8);
#endif
class daObj_Keyhole_HIO_c : public JORReflexible {
public:
+4
View File
@@ -50,6 +50,10 @@ public:
/* 0x14 */ Mtx mProjMtx;
/* 0x44 */ ResTIMG* mpImg;
/* 0x48 */ u8* mpData;
#if TARGET_PC
TGXTexObj mTexObj;
ResTIMG* mpCachedImg = nullptr;
#endif
};
class daPy_boomerangMove_c {
+10
View File
@@ -4,6 +4,10 @@
#include "JSystem/J3DGraphBase/J3DPacket.h"
#include "SSystem/SComponent/c_xyz.h"
#if TARGET_PC
#include "dusk/batch.hpp"
#endif
class cCcD_Obj;
class dCcMassS_HitInf;
class fopAc_ac_c;
@@ -107,6 +111,12 @@ public:
#if TARGET_PC
TGXTexObj mTexObj_l_J_Ohana00_64TEX;
TGXTexObj mTexObj_l_J_Ohana01_64128_0419TEX;
dusk::batch::LeafTemplate mTplHana00; // l_J_hana00DL
dusk::batch::LeafTemplate mTplHana00Cut; // l_J_hana00_cDL
dusk::batch::LeafTemplate mTplHana01; // l_J_hana01DL
dusk::batch::LeafTemplate mTplHana01Cut00; // l_J_hana01_c_00DL
dusk::batch::LeafTemplate mTplHana01Cut; // l_J_hana01_c_01DL
#endif
}; // Size: 0x12A54
+8
View File
@@ -4,6 +4,10 @@
#include "JSystem/J3DGraphBase/J3DPacket.h"
#include "SSystem/SComponent/c_xyz.h"
#if TARGET_PC
#include "../../../src/dusk/batch.hpp"
#endif
class cCcD_Obj;
class csXyz;
class dCcMassS_HitInf;
@@ -110,6 +114,10 @@ public:
#if TARGET_PC
TGXTexObj mTexObj_l_M_Hijiki00TEX;
TGXTexObj mTexObj_l_M_kusa05_RGBATEX;
dusk::batch::LeafTemplate mTplKusa9q; // l_M_Kusa_9qDL
dusk::batch::LeafTemplate mTplKusa9qCut; // l_M_Kusa_9q_cDL
dusk::batch::LeafTemplate mTplTengusa; // l_M_TenGusaDL
#endif
}; // Size: 0x1D718
+1
View File
@@ -1037,6 +1037,7 @@ public:
bool test1Camera(s32);
bool test2Camera(s32);
#if TARGET_PC
static bool isAimActive();
bool freeCamera();
bool executeDebugFlyCam();
void deactivateDebugFlyCam();
+13
View File
@@ -287,6 +287,11 @@ public:
MEMCARDCHECKPROC_ERR_YESNO_CURSOR_MOVE_ANM,
MEMCARDCHECKPROC_SAVEDATA_CLEAR,
#if TARGET_PC
MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE,
MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE_ERR_WAIT,
#endif
#if PLATFORM_WII || PLATFORM_SHIELD
MEMCARDCHECKPROC_NAND_STAT_CHECK,
MEMCARDCHECKPROC_GAMEFILE_INIT_SEL,
@@ -411,6 +416,10 @@ public:
bool yesnoWakuAlpahAnm(u8);
#if TARGET_PC
void fileSelectWide();
bool pointerDataSelect();
bool pointerMenuSelect();
bool pointerCopyDataToSelect();
bool pointerYesNoSelect(bool errorSelect);
#endif
void _draw();
void errorMoveAnmInitSet(int, int);
@@ -445,6 +454,10 @@ public:
void MemCardMakeGameFile();
void MemCardMakeGameFileWait();
void MemCardMakeGameFileCheck();
#if TARGET_PC
void MemCardAutoMakeGameFile();
void MemCardAutoMakeGameFileErrWait();
#endif
void MemCardMsgWindowInitOpen();
void MemCardMsgWindowOpen();
void MemCardMsgWindowClose();
+2 -1
View File
@@ -198,6 +198,7 @@ struct HOUSI_EFF {
/* 0x4C */ u16 field_0x4c;
}; // Size: 0x50
// Housi is the rising square particles in Twilight
class dKankyo_housi_Packet : public J3DPacket {
public:
virtual void draw();
@@ -208,7 +209,7 @@ public:
/* 0x0020 */ HOUSI_EFF mHousiEff[300];
/* 0x5DE0 */ u8 field_0x5de0[8];
/* 0x5DE8 */ f32 field_0x5de8;
/* 0x5DEC */ s16 field_0x5dec;
/* 0x5DEC */ s16 mHousiCount;
}; // Size: 0x5DF0
struct CLOUD_EFF {
+3
View File
@@ -157,6 +157,9 @@ public:
int getDispType() const;
void _move(f32, f32, int, f32);
void _draw();
#if TARGET_PC
bool refreshTextureSize();
#endif
virtual ~dMap_c() {
#if DEBUG
+2
View File
@@ -74,6 +74,8 @@ public:
#if TARGET_PC
void menuCollectWide();
bool pointerWait();
void pointerActivateCurrent();
#endif
void _create();
+4
View File
@@ -51,6 +51,10 @@ public:
void setBButtonString(u16);
void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Insect_c();
+4
View File
@@ -55,6 +55,10 @@ public:
u8 getLetterNum();
void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Letter_c();
+3
View File
@@ -80,6 +80,9 @@ public:
void setBButtonString(u16);
bool isRumbleSupported();
bool dpdMenuMove();
#if TARGET_PC
bool pointerConfirmSelect();
#endif
void paneResize(u64);
void initialize();
void yesnoMenuMoveAnmInitSet(int, int);
+3
View File
@@ -74,6 +74,9 @@ public:
void clacEllipsePlotAverage(int, f32, f32);
bool dpdMove();
u8 openExplain(u8);
#if TARGET_PC
bool pointerMove();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Ring_c();
+2
View File
@@ -266,6 +266,8 @@ public:
#if TARGET_PC
void menuSaveWide();
bool pointerSaveSelect();
bool pointerYesNoSelect(bool errorSelect, u8 errParam = 0, u8 soundParam = 0);
#endif
void _draw2();
+4
View File
@@ -49,6 +49,10 @@ public:
u8 getSkillNum();
void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Skill_c();
+4
View File
@@ -49,6 +49,10 @@ public:
void selectScale();
void selectTrans();
void selectAnimeTransform(int);
#if TARGET_PC
bool pointerMove();
bool consumePointerClick();
#endif
void setOffsetX(f32 i_offsetX) { mOffsetX = i_offsetX; }
bool isAnimeUpdate(int param_0) { return (field_0x114 & (u8)(1 << param_0)) ? TRUE : FALSE; }
+8
View File
@@ -9,6 +9,8 @@ namespace dusk {
enum class ActionBinds {
FIRST_PERSON_CAMERA,
CALL_MIDNA,
OPEN_MAP_SCREEN,
TOGGLE_MINIMAP,
OPEN_DUSKLIGHT_MENU,
TURBO_SPEED_BUTTON,
COUNT,
@@ -32,6 +34,12 @@ bool isActionBound(ActionBinds action, u32 port);
void updateActionBindings();
void setVirtualActionBind(ActionBinds action, u32 port, bool pressed, bool available = true);
void clearVirtualActionBind(ActionBinds action, u32 port);
void clearAllVirtualActionBinds();
bool getActionBindTrig(ActionBinds action, u32 port);
bool getActionBindHold(ActionBinds action, u32 port);
+9 -2
View File
@@ -4,6 +4,7 @@
#include "dolphin/types.h"
#include <type_traits>
#include <cstdlib>
#include <limits>
#include <string>
/**
@@ -139,11 +140,16 @@ concept ConfigValueInteger =
|| std::is_same_v<T, s64>
|| std::is_same_v<T, u64>;
template <typename T>
struct ConfigValueTraits {
static constexpr bool enabled = false;
};
/**
* \brief Concept that defines the legal set of types that can be used for CVar values.
*
* Valid types cannot be cv-qualified and must be basic primitive types (int, float, bool),
* strings, or enums of the basic primitives.
* strings, enums of the basic primitives, or explicitly-enabled structured settings.
*/
template <typename T>
concept ConfigValue =
@@ -154,7 +160,8 @@ concept ConfigValue =
|| std::is_same_v<T, f32>
|| std::is_same_v<T, f64>
|| std::is_same_v<T, std::string>
|| (std::is_enum_v<T> && ConfigValueInteger<std::underlying_type_t<T>>));
|| (std::is_enum_v<T> && ConfigValueInteger<std::underlying_type_t<T>>)
|| ConfigValueTraits<T>::enabled);
template <ConfigValue T>
const ConfigImplBase* GetConfigImpl();
+25
View File
@@ -7,12 +7,16 @@
#include <dolphin/gx/GXExtra.h>
#include "tracy/Tracy.hpp"
#if DUSK_GFX_DEBUG_GROUPS
#define GX_DEBUG_GROUP(name, ...) \
do { \
GXPushDebugGroup(#name); \
name(__VA_ARGS__); \
GXPopDebugGroup(); \
} while (0)
#else
#define GX_DEBUG_GROUP(name, ...) name(__VA_ARGS__)
#endif
#ifdef TARGET_PC
class GXTexObjRAII : public GXTexObj {
@@ -39,16 +43,37 @@ public:
static_assert(sizeof(GXTexObjRAII) == sizeof(GXTexObj),
"GXTexObjRAII should have the same size as GXTexObj");
typedef GXTexObjRAII TGXTexObj;
class GXTlutObjRAII : public GXTlutObj {
public:
GXTlutObjRAII() : GXTlutObj() {}
~GXTlutObjRAII() { GXDestroyTlutObj(this); }
void reset() { GXDestroyTlutObj(this); }
GXTlutObjRAII(const GXTlutObjRAII&) = delete;
GXTlutObjRAII& operator=(const GXTlutObjRAII&) = delete;
GXTlutObjRAII(GXTlutObjRAII&&) = delete;
GXTlutObjRAII& operator=(GXTlutObjRAII&&) = delete;
};
static_assert(sizeof(GXTlutObjRAII) == sizeof(GXTlutObj),
"GXTlutObjRAII should have the same size as GXTlutObj");
typedef GXTlutObjRAII TGXTlutObj;
#else
typedef GXTexObj TGXTexObj;
typedef GXTlutObj TGXTlutObj;
#endif
struct GXScopedDebugGroup {
explicit GXScopedDebugGroup(const char* text) {
#if DUSK_GFX_DEBUG_GROUPS
GXPushDebugGroup(text);
#endif
}
~GXScopedDebugGroup() {
#if DUSK_GFX_DEBUG_GROUPS
GXPopDebugGroup();
#endif
}
};
+1 -4
View File
@@ -1,5 +1,4 @@
#ifndef DUSK_GYRO_H
#define DUSK_GYRO_H
#pragma once
namespace dusk::gyro {
void read(float dt);
@@ -14,5 +13,3 @@ bool get_sensor_keep_alive();
void set_sensor_keep_alive(bool value);
bool rollgoal_gyro_enabled();
} // namespace dusk::gyro
#endif
+60
View File
@@ -0,0 +1,60 @@
#pragma once
#include "dolphin/types.h"
class CPaneMgr;
namespace dusk::menu_pointer {
enum class Context {
None,
FileSelect,
Save,
ItemWheel,
Collection,
Options,
Dialog,
};
enum class Phase {
Move,
Press,
Release,
Cancel,
};
struct State {
f32 x = 0.0f;
f32 y = 0.0f;
bool valid = false;
bool down = false;
bool pressed = false;
bool released = false;
bool clicked = false;
bool touch = false;
};
void begin_game_frame() noexcept;
void end_game_frame() noexcept;
void begin_context(Context context) noexcept;
bool handle_fallthrough_pointer(f32 x, f32 y, Phase phase, bool touch, s32 mouseButton = -1) noexcept;
bool active() noexcept;
bool enabled() noexcept;
bool mouse_capture_active() noexcept;
const State& state() noexcept;
bool consume_click() noexcept;
void set_dialog_choice(u8 choice, bool clicked) noexcept;
bool get_dialog_choice(u8& choice) noexcept;
bool consume_dialog_click(u8& choice) noexcept;
void defer_activation(Context context, u8 target) noexcept;
bool consume_deferred_activation(Context context, u8 target) noexcept;
void clear_deferred_activation(Context context) noexcept;
u32 suppressed_pad_buttons(u32 port) noexcept;
void finish_pad_suppression_read(u32 port) noexcept;
bool hit_rect(f32 left, f32 top, f32 right, f32 bottom, f32 padding = 0.0f) noexcept;
bool hit_pane(CPaneMgr* pane, f32 padding = 0.0f) noexcept;
bool hit_pane(J2DPane* pane, f32 padding = 0.0f) noexcept;
} // namespace dusk::menu_pointer
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include <SDL3/SDL_events.h>
namespace dusk::mouse {
void read();
void getAimDeltas(float& out_yaw, float& out_pitch);
void getCameraDeltas(float& out_yaw, float& out_pitch);
void handle_event(const SDL_Event& event) noexcept;
void onFocusLost();
void onFocusGained();
} // namespace dusk::mouse
+40 -24
View File
@@ -1,9 +1,9 @@
#ifndef DUSK_CONFIG_H
#define DUSK_CONFIG_H
#pragma once
#include <array>
#include "dusk/config_var.hpp"
#include "dusk/ui/controls.hpp"
namespace dusk {
@@ -40,11 +40,6 @@ enum class DiscVerificationState : u8 {
HashMismatch,
};
enum class GyroMode : u8 {
Sensor = 0,
Mouse = 1,
};
enum class FrameInterpMode : u8 {
Off = 0,
Capped = 1,
@@ -57,6 +52,14 @@ enum class MenuScaling : u8 {
Dusklight = 2,
};
enum class MagicArmorMode : u8 {
NORMAL = 0,
ON_DAMAGE = 1,
DOUBLE_DEFENSE = 2,
INVINCIBLE = 3,
COSMETIC = 4,
};
namespace config {
template <>
struct ConfigEnumRange<BloomMode> {
@@ -88,12 +91,6 @@ struct ConfigEnumRange<DiscVerificationState> {
static constexpr auto max = DiscVerificationState::HashMismatch;
};
template <>
struct ConfigEnumRange<GyroMode> {
static constexpr auto min = GyroMode::Sensor;
static constexpr auto max = GyroMode::Mouse;
};
template <>
struct ConfigEnumRange<FrameInterpMode> {
static constexpr auto min = FrameInterpMode::Off;
@@ -105,6 +102,17 @@ struct ConfigEnumRange<MenuScaling> {
static constexpr auto min = MenuScaling::GameCube;
static constexpr auto max = MenuScaling::Dusklight;
};
template <>
struct ConfigEnumRange<MagicArmorMode> {
static constexpr auto min = MagicArmorMode::NORMAL;
static constexpr auto max = MagicArmorMode::COSMETIC;
};
template <>
struct ConfigValueTraits<ui::ControlLayout> {
static constexpr bool enabled = true;
};
} // namespace config
// Persistent user settings
@@ -120,6 +128,9 @@ struct UserSettings {
ConfigVar<bool> enableFpsOverlay;
ConfigVar<int> fpsOverlayCorner;
ConfigVar<int> maxFrameRate;
ConfigVar<bool> rememberWindowSize;
ConfigVar<int> lastWindowWidth;
ConfigVar<int> lastWindowHeight;
} video;
struct {
@@ -153,6 +164,7 @@ struct UserSettings {
ConfigVar<bool> noMissClimbing;
ConfigVar<bool> fastTears;
ConfigVar<bool> no2ndFishForCat;
ConfigVar<bool> buttonFishing;
ConfigVar<bool> instantSaves;
ConfigVar<bool> instantText;
ConfigVar<bool> sunsSong;
@@ -162,6 +174,7 @@ struct UserSettings {
// Preferences
ConfigVar<bool> enableMirrorMode;
ConfigVar<bool> minimalHUD;
ConfigVar<float> hudScale;
ConfigVar<bool> pauseOnFocusLost;
ConfigVar<bool> enableLinkDollRotation;
ConfigVar<bool> enableAchievementToasts;
@@ -187,7 +200,6 @@ struct UserSettings {
ConfigVar<bool> midnasLamentNonStop;
// Input
ConfigVar<GyroMode> gyroMode;
ConfigVar<bool> enableGyroAim;
ConfigVar<bool> enableGyroRollgoal;
ConfigVar<float> gyroSensitivityX;
@@ -197,7 +209,15 @@ struct UserSettings {
ConfigVar<float> gyroDeadband;
ConfigVar<bool> gyroInvertPitch;
ConfigVar<bool> gyroInvertYaw;
ConfigVar<bool> enableMouseCamera;
ConfigVar<bool> enableMouseAim;
ConfigVar<float> mouseAimSensitivity;
ConfigVar<float> mouseCameraSensitivity;
ConfigVar<bool> invertMouseY;
ConfigVar<bool> freeCamera;
ConfigVar<bool> enableTouchControls;
ConfigVar<bool> enableMenuPointer;
ConfigVar<ui::ControlLayout> touchControlsLayout;
ConfigVar<bool> invertCameraXAxis;
ConfigVar<bool> invertCameraYAxis;
ConfigVar<bool> invertFirstPersonXAxis;
@@ -206,6 +226,8 @@ struct UserSettings {
ConfigVar<bool> invertAirSwimY;
ConfigVar<float> freeCameraXSensitivity;
ConfigVar<float> freeCameraYSensitivity;
ConfigVar<float> touchCameraXSensitivity;
ConfigVar<float> touchCameraYSensitivity;
ConfigVar<bool> debugFlyCam;
ConfigVar<bool> debugFlyCamLockEvents;
ConfigVar<bool> allowBackgroundInput;
@@ -228,9 +250,8 @@ struct UserSettings {
ConfigVar<bool> canTransformAnywhere;
ConfigVar<bool> fastRoll;
ConfigVar<bool> fastSpinner;
ConfigVar<bool> freeMagicArmor;
ConfigVar<MagicArmorMode> armorRupeeDrain;
ConfigVar<bool> invincibleEnemies;
ConfigVar<bool> transformWithoutShadowCrystal;
// Technical
ConfigVar<bool> restoreWiiGlitches;
@@ -252,9 +273,6 @@ struct UserSettings {
struct {
ConfigVar<std::string> isoPath;
ConfigVar<DiscVerificationState> isoVerification;
#if DUSK_TPHD
ConfigVar<std::string> hdContentPath;
#endif
ConfigVar<std::string> graphicsBackend;
ConfigVar<bool> skipPreLaunchUI;
ConfigVar<bool> showPipelineCompilation;
@@ -268,6 +286,8 @@ struct UserSettings {
struct {
std::array<ActionBindConfigVar, 4> firstPersonCamera;
std::array<ActionBindConfigVar, 4> callMidna;
std::array<ActionBindConfigVar, 4> openMapScreen;
std::array<ActionBindConfigVar, 4> toggleMinimap;
std::array<ActionBindConfigVar, 4> openDusklightMenu;
std::array<ActionBindConfigVar, 4> turboSpeedButton;
} actionBindings;
@@ -275,8 +295,6 @@ struct UserSettings {
UserSettings& getSettings();
bool tphd_active();
void registerSettings();
// Transient settings
@@ -301,6 +319,4 @@ struct TransientSettings {
TransientSettings& getTransientSettings();
}
#endif // DUSK_CONFIG_H
} // namespace dusk
+12
View File
@@ -0,0 +1,12 @@
#ifndef DUSK_TEXTURE_REPLACEMENTS_HPP
#define DUSK_TEXTURE_REPLACEMENTS_HPP
namespace dusk::texture_replacements {
void reload();
void set_enabled(bool enabled);
void shutdown();
}
#endif
+12
View File
@@ -0,0 +1,12 @@
#pragma once
namespace dusk::touch_camera {
constexpr float YAW_DEGREES_PER_DP = 0.34f;
constexpr float PITCH_DEGREES_PER_DP = 0.22f;
void add_delta(float yaw_dp, float pitch_dp) noexcept;
bool consume_delta(float& yaw_dp, float& pitch_dp) noexcept;
void clear() noexcept;
} // namespace dusk::touch_camera
+1 -1
View File
@@ -44,7 +44,7 @@ struct mDoLib_clipper {
void mDoLib_project(Vec* src, Vec* dst);
u32 mDoLib_setResTimgObj(ResTIMG const* res, TGXTexObj* o_texObj, u32 tlut_name,
GXTlutObj* o_tlutObj);
TGXTlutObj* o_tlutObj);
void mDoLib_pos2camera(Vec* src, Vec* dst);
#if PLATFORM_WII
+41 -16
View File
@@ -952,45 +952,70 @@ if(DEFINED APPLE_TARGET_TRIPLE)
set(APPLE_TARGET_TRIPLE_FLAG "-target ${APPLE_TARGET_TRIPLE}")
endif()
function(ios_toolchain_set_cached_flags variable description)
set(clean_flags "${${variable}}")
foreach(toolchain_flag IN LISTS ARGN)
if(NOT "${toolchain_flag}" STREQUAL "")
string(REPLACE "${toolchain_flag}" "" clean_flags "${clean_flags}")
endif()
endforeach()
string(REGEX REPLACE "[ \t]+" " " clean_flags "${clean_flags}")
string(STRIP "${clean_flags}" clean_flags)
set(final_flags "")
foreach(toolchain_flag IN LISTS ARGN)
if(NOT "${toolchain_flag}" STREQUAL "")
string(APPEND final_flags " ${toolchain_flag}")
endif()
endforeach()
if(NOT "${clean_flags}" STREQUAL "")
string(APPEND final_flags " ${clean_flags}")
endif()
string(REGEX REPLACE "[ \t]+" " " final_flags "${final_flags}")
string(STRIP "${final_flags}" final_flags)
set(${variable} "${final_flags}" CACHE INTERNAL "${description}")
endfunction()
#Check if Xcode generator is used since that will handle these flags automagically
if(CMAKE_GENERATOR MATCHES "Xcode")
message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as the generator. Modifying the Xcode build-settings directly instead.")
else()
set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_C_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all C build types.")
ios_toolchain_set_cached_flags(CMAKE_C_FLAGS "Flags used by the compiler during all C build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${OBJC_LEGACY_VARS}" "${BITCODE}" "${VISIBILITY}")
set(CMAKE_C_FLAGS_DEBUG "-O0 -g ${CMAKE_C_FLAGS_DEBUG}")
set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_C_FLAGS_MINSIZEREL}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_C_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_CXX_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all CXX build types.")
ios_toolchain_set_cached_flags(CMAKE_CXX_FLAGS "Flags used by the compiler during all CXX build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${OBJC_LEGACY_VARS}" "${BITCODE}" "${VISIBILITY}")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g ${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_CXX_FLAGS_MINSIZEREL}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_CXX_FLAGS_RELEASE}")
if(NAMED_LANGUAGE_SUPPORT_INT)
set(CMAKE_OBJC_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJC_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all OBJC build types.")
ios_toolchain_set_cached_flags(CMAKE_OBJC_FLAGS "Flags used by the compiler during all OBJC build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${BITCODE}" "${VISIBILITY}" "${FOBJC_ARC}" "${OBJC_VARS}")
set(CMAKE_OBJC_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJC_FLAGS_DEBUG}")
set(CMAKE_OBJC_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJC_FLAGS_MINSIZEREL}")
set(CMAKE_OBJC_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJC_FLAGS_RELWITHDEBINFO}")
set(CMAKE_OBJC_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJC_FLAGS_RELEASE}")
set(CMAKE_OBJCXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJCXX_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all OBJCXX build types.")
ios_toolchain_set_cached_flags(CMAKE_OBJCXX_FLAGS "Flags used by the compiler during all OBJCXX build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${BITCODE}" "${VISIBILITY}" "${FOBJC_ARC}" "${OBJC_VARS}")
set(CMAKE_OBJCXX_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJCXX_FLAGS_DEBUG}")
set(CMAKE_OBJCXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJCXX_FLAGS_MINSIZEREL}")
set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_OBJCXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}")
endif()
set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all C link types.")
set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all CXX link types.")
ios_toolchain_set_cached_flags(CMAKE_C_LINK_FLAGS "Flags used by the compiler for all C link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
ios_toolchain_set_cached_flags(CMAKE_CXX_LINK_FLAGS "Flags used by the compiler for all CXX link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
if(NAMED_LANGUAGE_SUPPORT_INT)
set(CMAKE_OBJC_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJC_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all OBJC link types.")
set(CMAKE_OBJCXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJCXX_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all OBJCXX link types.")
ios_toolchain_set_cached_flags(CMAKE_OBJC_LINK_FLAGS "Flags used by the compiler for all OBJC link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
ios_toolchain_set_cached_flags(CMAKE_OBJCXX_LINK_FLAGS "Flags used by the compiler for all OBJCXX link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
endif()
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp" CACHE INTERNAL
"Flags used by the compiler for all ASM build types.")
@@ -212,6 +212,9 @@ public:
void setCornerColor(JUtility::TColor c0) {
setCornerColor(c0, c0, c0, c0);
}
#if TARGET_PC
JUtility::TColor corner(size_t index) const { return mCornerColor[index]; }
#endif
protected:
/* 0x100 */ JUTTexture* mTexture[2];
@@ -1761,16 +1761,6 @@ public:
virtual ~J3DIndBlockNull() {}
};
#ifdef DUSK_TPHD
struct PolygonOffset {
BE(f32) mFrontOffset;
BE(f32) mFrontScale;
BE(f32) mBackOffset;
BE(f32) mBackScale;
BE(f32) mClamp;
};
#endif
/**
* @ingroup jsystem-j3d
*
@@ -1803,10 +1793,6 @@ public:
virtual void setDither(u8 const*) {}
virtual void setDither(u8) {}
virtual u8 getDither() const { return 0; }
#ifdef DUSK_TPHD
virtual void setPolygonOffset(const PolygonOffset&) {}
virtual PolygonOffset* getPolygonOffset() { return NULL; }
#endif
virtual u32 getFogOffset() const { return 0; }
virtual void setFogOffset(u32) {}
virtual ~J3DPEBlock() {}
@@ -1970,25 +1956,12 @@ public:
virtual void setFogOffset(u32 fogOffset) { mFogOffset = fogOffset; }
virtual ~J3DPEBlockFull() {}
#ifdef DUSK_TPHD
virtual void setPolygonOffset(const PolygonOffset& offset) {
mPolygonOffset = offset;
}
virtual PolygonOffset* getPolygonOffset() {
return &mPolygonOffset;
}
#endif
/* 0x04 */ J3DFog mFog;
/* 0x30 */ J3DAlphaComp mAlphaComp;
/* 0x34 */ J3DBlend mBlend;
/* 0x38 */ J3DZMode mZMode;
/* 0x3A */ u8 mZCompLoc;
/* 0x3B */ u8 mDither;
#ifdef DUSK_TPHD
PolygonOffset mPolygonOffset;
#endif
/* 0x3C */ u32 mFogOffset;
}; // Size: 0x40
@@ -1,6 +1,7 @@
#ifndef J3DSHAPEDRAW_H
#define J3DSHAPEDRAW_H
#include <gx.h>
#include <types.h>
/**
@@ -12,6 +13,9 @@ public:
u32 countVertex(u32);
void addTexMtxIndexInDL(u32, u32, u32);
J3DShapeDraw(u8 const*, u32);
#if TARGET_PC
J3DShapeDraw(u8 const*, u32, const GXVtxDescList*);
#endif
void draw() const;
virtual ~J3DShapeDraw();
@@ -46,13 +46,6 @@ struct J3DMaterialInitData {
/* 0x14A */ BE(u16) mNBTScaleIdx;
}; // size 0x14C
#ifdef DUSK_TPHD
struct J3DMaterialInitData_MAT4 : public J3DMaterialInitData {
/* 0x14C */ BE(u16) mPolygonOffsetIdx;
}; // size 0x14E
#endif
/**
* @ingroup jsystem-j3d
*
@@ -150,29 +143,10 @@ public:
J3DNBTScale newNBTScale(int) const;
u16 getMaterialID(int idx) const { return mpMaterialID[idx]; }
#ifdef DUSK_TPHD
u8 getMaterialMode(int idx) const { return getMatInitData(idx)->mMaterialMode; }
#else
u8 getMaterialMode(int idx) const { return mpMaterialInitData[mpMaterialID[idx]].mMaterialMode; }
#endif
#if DUSK_TPHD
const PolygonOffset newPolygonOffset(int) const;
J3DMaterialInitData* getMatInitData(int idx) const {
static const u32 sInitDataSizes[] = {0, 0, 0x138, 0x14C, 0x14E};
return (J3DMaterialInitData*)((u8*)mpMaterialInitData + sInitDataSizes[mBlockType] * getMaterialID(idx));
}
u16 mBlockType;
#endif
/* 0x00 */ u16 mMaterialNum;
#if DUSK_TPHD
/* 0x04 */ void* mpMaterialInitData;
#else
/* 0x04 */ J3DMaterialInitData* mpMaterialInitData;
#endif
/* 0x08 */ BE(u16)* mpMaterialID;
/* 0x0C */ J3DIndInitData* mpIndInitData;
/* 0x10 */ GXColor* mpMatColor;
@@ -201,9 +175,6 @@ public:
/* 0x6C */ u8* mpZCompLoc;
/* 0x70 */ u8* mpDither;
/* 0x74 */ J3DNBTScaleInfo* mpNBTScaleInfo;
#ifdef DUSK_TPHD
PolygonOffset* mpPolygonOffsets;
#endif
/* 0x78 */ J3DDisplayListInit* mpDisplayListInit;
/* 0x7C */ J3DPatchingInfo* mpPatchingInfo;
/* 0x80 */ J3DCurrentMtxInfo* mpCurrentMtxInfo;
@@ -169,12 +169,6 @@ struct J3DMaterialBlock_v21 : public J3DModelBlock {
/* 0x74 */ OFFSET_PTR_V0 mpNBTScaleInfo;
};
#ifdef DUSK_TPHD
struct J3DMaterialBlock_MAT4 : public J3DMaterialBlock {
/* 0x84 */ OFFSET_PTR_V0 mpPolygonOffsets;
};
#endif
/**
* @ingroup jsystem-j3d
*
@@ -3,6 +3,20 @@
#include <gx.h>
#if TARGET_PC
#include <mtx.h>
struct ParticleDrawCtx {
bool batch; // off = immediate mode
bool useTexMtx; // UVs transformed by texMtx
bool useClr0; // prm color in GX_VA_CLR0
bool useClr1; // env color in GX_VA_CLR1
Mtx texMtx;
GXColor clr0;
GXColor clr1;
};
#endif
struct JPAEmitterWorkData;
class JPABaseParticle;
class JKRHeap;
@@ -75,6 +89,9 @@ public:
const GXTevColorArg* getTevColorArg() const { return st_ca[(pBsd->mFlags >> 0x0F) & 0x07]; }
const GXTevAlphaArg* getTevAlphaArg() const { return st_aa[(pBsd->mFlags >> 0x12) & 0x01]; }
#if TARGET_PC
u32 getTevColorArgSel() const { return (pBsd->mFlags >> 0x0F) & 0x07; }
#endif
u32 getType() const { return (pBsd->mFlags >> 0) & 0x0F; }
u32 getDirType() const { return (pBsd->mFlags >> 4) & 0x07; }
@@ -186,26 +203,34 @@ void JPARegistPrm(JPAEmitterWorkData*);
void JPARegistEnv(JPAEmitterWorkData*);
void JPARegistPrmEnv(JPAEmitterWorkData*);
void JPADrawPoint(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawLine(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotDirection(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawDirection(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotation(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawDBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotYBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawYBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawParticleCallBack(JPAEmitterWorkData*, JPABaseParticle*);
void JPALoadTexAnm(JPAEmitterWorkData*, JPABaseParticle*);
void JPASetPointSize(JPAEmitterWorkData*, JPABaseParticle*);
void JPASetLineWidth(JPAEmitterWorkData*, JPABaseParticle*);
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistAlpha(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistEnv(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistPrmAlpha(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistPrmAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
#if TARGET_PC
#define JPA_DRAW_PARTICLE_ARGS JPAEmitterWorkData*, JPABaseParticle*, ParticleDrawCtx*
#else
#define JPA_DRAW_PARTICLE_ARGS JPAEmitterWorkData*, JPABaseParticle*
#endif
void JPADrawPoint(JPA_DRAW_PARTICLE_ARGS);
void JPADrawLine(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotDirection(JPA_DRAW_PARTICLE_ARGS);
void JPADrawDirection(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotation(JPA_DRAW_PARTICLE_ARGS);
void JPADrawDBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotYBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawYBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawParticleCallBack(JPA_DRAW_PARTICLE_ARGS);
void JPALoadTexAnm(JPA_DRAW_PARTICLE_ARGS);
void JPASetPointSize(JPA_DRAW_PARTICLE_ARGS);
void JPASetLineWidth(JPA_DRAW_PARTICLE_ARGS);
void JPALoadCalcTexCrdMtxAnm(JPA_DRAW_PARTICLE_ARGS);
void JPARegistAlpha(JPA_DRAW_PARTICLE_ARGS);
void JPARegistEnv(JPA_DRAW_PARTICLE_ARGS);
void JPARegistAlphaEnv(JPA_DRAW_PARTICLE_ARGS);
void JPARegistPrmAlpha(JPA_DRAW_PARTICLE_ARGS);
void JPARegistPrmAlphaEnv(JPA_DRAW_PARTICLE_ARGS);
#undef JPA_DRAW_PARTICLE_ARGS
#if TARGET_PC
void JPAInterpBillboard(JPAEmitterWorkData*, JPABaseParticle*);
@@ -17,6 +17,10 @@ class JPADynamicsBlock;
class JPAFieldBlock;
class JPAKeyBlock;
#if TARGET_PC
struct ParticleDrawCtx;
#endif
/**
* @ingroup jsystem-jparticle
*
@@ -50,13 +54,19 @@ public:
public:
typedef void (*EmitterFunc)(JPAEmitterWorkData*);
typedef void (*ParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*);
#if TARGET_PC
typedef void (*DrawParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*,
ParticleDrawCtx*);
#else
typedef ParticleFunc DrawParticleFunc;
#endif
/* 0x00 */ EmitterFunc* mpCalcEmitterFuncList;
/* 0x04 */ EmitterFunc* mpDrawEmitterFuncList;
/* 0x08 */ EmitterFunc* mpDrawEmitterChildFuncList;
/* 0x0C */ ParticleFunc* mpCalcParticleFuncList;
/* 0x10 */ ParticleFunc* mpDrawParticleFuncList;
/* 0x10 */ DrawParticleFunc* mpDrawParticleFuncList;
/* 0x14 */ ParticleFunc* mpCalcParticleChildFuncList;
/* 0x18 */ ParticleFunc* mpDrawParticleChildFuncList;
/* 0x18 */ DrawParticleFunc* mpDrawParticleChildFuncList;
/* 0x1C */ JPABaseShape* pBsp;
/* 0x20 */ JPAExtraShape* pEsp;
@@ -77,6 +87,20 @@ public:
/* 0x45 */ u8 mpDrawParticleFuncListNum;
/* 0x46 */ u8 mpCalcParticleChildFuncListNum;
/* 0x47 */ u8 mpDrawParticleChildFuncListNum;
#if TARGET_PC
struct BatchInfo {
f32 vtxPos[8][3];
f32 vtxUv[8][2];
u8 vtxCount; // 4 (quad) or 8 (cross)
bool supported; // draw func list contains only batchable funcs
bool hasPtclColor; // per-particle JPARegist* func is present
bool hasPtclTexMtx; // JPALoadCalcTexCrdMtxAnm is present
};
BatchInfo mBatchInfo;
void initBatchInfo();
#endif
};
#endif /* JPARESOURCE_H */
@@ -3,6 +3,8 @@
#include "JSystem/J2DGraph/J2DGrafContext.h"
#include <gx.h>
#include <tracy/Tracy.hpp>
J2DGrafContext::J2DGrafContext(f32 x, f32 y, f32 width, f32 height)
: mBounds(x, y, x + width, y + height), mScissorBounds(x, y, x + width, y + height) {
if (x < 0.0f || y < 0.0f) {
@@ -137,6 +139,7 @@ void J2DGrafContext::setLineWidth(u8 lineWidth) {
}
void J2DGrafContext::fillBox(JGeometry::TBox2<f32> const& box) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mBoxPart.mType, (GXBlendFactor)mBoxPart.mSrcFactor,
(GXBlendFactor)mBoxPart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
@@ -155,6 +158,7 @@ void J2DGrafContext::fillBox(JGeometry::TBox2<f32> const& box) {
}
void J2DGrafContext::drawFrame(JGeometry::TBox2<f32> const& box) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mBoxPart.mType, (GXBlendFactor)mBoxPart.mSrcFactor,
(GXBlendFactor)mBoxPart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
@@ -175,6 +179,7 @@ void J2DGrafContext::drawFrame(JGeometry::TBox2<f32> const& box) {
}
void J2DGrafContext::line(JGeometry::TVec2<f32> start, JGeometry::TVec2<f32> end) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mLinePart.mType, (GXBlendFactor)mLinePart.mSrcFactor,
(GXBlendFactor)mLinePart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
@@ -542,8 +542,11 @@ void J3DModel::viewCalc() {
}
#ifdef TARGET_PC
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
dusk::frame_interp::record_final_mtx(getDrawMtxPtr()[i]);
Mtx* drawMtx = getDrawMtxPtr();
if (drawMtx != J3DMtxBuffer::sNoUseDrawMtxPtr) {
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
dusk::frame_interp::record_final_mtx(drawMtx[i]);
}
}
#endif
@@ -222,9 +222,6 @@ void J3DMatPacket::draw() {
}
#endif
PolygonOffset* temp = mpMaterial->getPEBlock()->getPolygonOffset();
GX2SetPolygonOffset(temp->mFrontOffset, temp->mFrontScale, temp->mBackOffset, temp->mBackScale, temp->mClamp);
callDL();
J3DShapePacket* packet = getShapePacket();
@@ -233,8 +230,6 @@ void J3DMatPacket::draw() {
#endif
packet->getShape()->loadPreDrawSetting();
// TODO: MAT4 sets polygon offset here in HD
while (packet != NULL) {
if (packet->getDisplayListObj() != NULL) {
packet->getDisplayListObj()->callDL();
+2 -2
View File
@@ -136,8 +136,8 @@ void J3DLoadCPCmd(u8 addr, u32 val) {
#if TARGET_PC
static void J3DLoadArrayBasePtr(GXAttr attr, void* data, u32 size, bool le) {
u32 idx = (attr == GX_VA_NBT) ? 1 : (attr - GX_VA_POS);
GXCmd1u8(GX_LOAD_AURORA);
GXCmd1u16(GX_LOAD_AURORA_ARRAYBASE | idx);
GXCmd1u8(GX_AURORA);
GXCmd1u16(GX_AURORA_LOAD_ARRAYBASE | idx);
GXCmd1u64((u64)data);
GXCmd1u32(size);
GXCmd1u8(le ? 1 : 0);
+101 -4
View File
@@ -1,15 +1,47 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include <cstring>
#include <gx.h>
#include <stdint.h>
#include "JSystem/J3DGraphBase/J3DShapeDraw.h"
#include "JSystem/JKernel/JKRHeap.h"
#include <cstring>
#include <stdint.h>
#include <gx.h>
#if TARGET_PC
#include <aurora/dl.hpp>
#include <tracy/Tracy.hpp>
namespace {
void set_display_list_copy(void*& displayList, u32& displayListSize, const u8* data, u32 size) {
const u32 alignedSize = ALIGN_NEXT(size, 0x20);
u8* newDL = JKR_NEW_ARRAY_ARGS(u8, alignedSize, 0x20);
if (size != 0) {
std::memcpy(newDL, data, size);
}
for (u32 i = size; i < alignedSize; i++) {
newDL[i] = 0;
}
displayList = newDL;
displayListSize = alignedSize;
DCStoreRange(newDL, displayListSize);
}
} // namespace
#endif
u32 J3DShapeDraw::countVertex(u32 stride) {
u32 count = 0;
u8* dlStart = (u8*)getDisplayList();
#if TARGET_PC
aurora::gx::dl::Reader reader{dlStart, getDisplayListSize(), static_cast<u8>(stride)};
while (const auto cmd = reader.next()) {
if (cmd->kind != aurora::gx::dl::Command::Kind::Passthrough) {
count += cmd->draw.vtxCount;
}
}
#else
for (u8* dl = dlStart; (dl - dlStart) < getDisplayListSize();) {
u8 cmd = *(u8*)dl;
dl++;
@@ -20,10 +52,58 @@ u32 J3DShapeDraw::countVertex(u32 stride) {
count += vtxNum;
dl = (u8*)dl + stride * vtxNum;
}
#endif
return count;
}
#if TARGET_PC
void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
u32 byteNum = countVertex(stride);
u32 oldSize = mDisplayListSize;
u32 newSize = ALIGN_NEXT(oldSize + byteNum, 0x20);
u8* newDLStart = JKR_NEW_ARRAY_ARGS(u8, newSize, 0x20);
u8* oldDLStart = (u8*)mDisplayList;
u8* newDL = newDLStart;
aurora::gx::dl::Reader reader{oldDLStart, mDisplayListSize, static_cast<u8>(stride)};
while (const auto cmd = reader.next()) {
if (cmd->kind == aurora::gx::dl::Command::Kind::Passthrough) {
std::memcpy(newDL, cmd->data, cmd->size);
newDL += cmd->size;
continue;
}
const auto& draw = cmd->draw;
const u32 headerSize = draw.vertices - cmd->data;
std::memcpy(newDL, cmd->data, headerSize);
newDL += headerSize;
for (u32 i = 0; i < draw.vtxCount; i++) {
const u8* oldVtx = draw.vertices + stride * i;
u8 pnmtxidx = oldVtx[0];
std::memcpy(newDL, oldVtx, attrOffs);
newDL += attrOffs;
*newDL++ = valueBase + pnmtxidx;
std::memcpy(newDL, oldVtx + attrOffs, stride - attrOffs);
newDL += stride - attrOffs;
}
}
if (reader.failed()) {
// preserve the remainder untouched
std::memcpy(newDL, oldDLStart + reader.pos(), mDisplayListSize - reader.pos());
newDL += mDisplayListSize - reader.pos();
}
u32 realSize = ALIGN_NEXT((uintptr_t)newDL - (uintptr_t)newDLStart, 0x20);
for (; (newDL - newDLStart) < newSize; newDL++)
*newDL = 0;
mDisplayListSize = realSize;
mDisplayList = newDLStart;
DCStoreRange(newDLStart, mDisplayListSize);
}
#else
void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
u32 byteNum = countVertex(stride);
u32 oldSize = mDisplayListSize;
@@ -69,13 +149,30 @@ void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
mDisplayList = newDLStart;
DCStoreRange(newDLStart, mDisplayListSize);
}
#endif
J3DShapeDraw::J3DShapeDraw(const u8* displayList, u32 displayListSize) {
#if TARGET_PC
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
#else
mDisplayList = (void*)displayList;
mDisplayListSize = displayListSize;
#endif
}
#if TARGET_PC
J3DShapeDraw::J3DShapeDraw(
const u8* displayList, u32 displayListSize, const GXVtxDescList* vtxDesc) {
if (const auto optimized = aurora::gx::dl::optimize(displayList, displayListSize, vtxDesc)) {
set_display_list_copy(mDisplayList, mDisplayListSize, optimized->data(), optimized->size());
} else {
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
}
}
#endif
void J3DShapeDraw::draw() const {
ZoneScoped;
GXCallDisplayList(mDisplayList, mDisplayListSize);
}
@@ -12,9 +12,6 @@
#include "dusk/logging.h"
J3DMaterialFactory::J3DMaterialFactory(J3DMaterialBlock const& i_block) {
#ifdef DUSK_TPHD
mBlockType = (i_block.mBlockType & 0xFF) - 0x30; // get number at last byte of block name
#endif
mMaterialNum = i_block.mMaterialNum;
mpMaterialInitData = JSUConvertOffsetToPtr<J3DMaterialInitData>(&i_block, i_block.mpMaterialInitData);
mpMaterialID = JSUConvertOffsetToPtr<BE(u16)>(&i_block, i_block.mpMaterialID);
@@ -49,11 +46,6 @@ J3DMaterialFactory::J3DMaterialFactory(J3DMaterialBlock const& i_block) {
mpZCompLoc = JSUConvertOffsetToPtr<u8>(&i_block, i_block.mpZCompLoc);
mpDither = JSUConvertOffsetToPtr<u8>(&i_block, i_block.mpDither);
mpNBTScaleInfo = JSUConvertOffsetToPtr<J3DNBTScaleInfo>(&i_block, i_block.mpNBTScaleInfo);
#ifdef DUSK_TPHD
if(mBlockType >= 4) {
mpPolygonOffsets = JSUConvertOffsetToPtr<PolygonOffset>(&i_block, reinterpret_cast<const J3DMaterialBlock_MAT4&>(i_block).mpPolygonOffsets);
}
#endif
mpDisplayListInit = NULL;
mpPatchingInfo = NULL;
mpCurrentMtxInfo = NULL;
@@ -82,11 +74,7 @@ u16 J3DMaterialFactory::countUniqueMaterials() {
}
u32 J3DMaterialFactory::countTexGens(int i_idx) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mTexGenNumIdx != 0xff) {
return mpTexGenNum[mtl_init_data->mTexGenNumIdx];
}
@@ -94,11 +82,7 @@ u32 J3DMaterialFactory::countTexGens(int i_idx) const {
}
u32 J3DMaterialFactory::countStages(int i_idx) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
u32 count1 = 0;
u32 count2 = 0;
if (mtl_init_data->mTevStageNumIdx != 0xff) {
@@ -173,9 +157,6 @@ J3DMaterial* J3DMaterialFactory::createNormalMaterial(J3DMaterial* i_material, i
i_material->mPEBlock->setZMode(newZMode(i_idx));
i_material->mPEBlock->setZCompLoc(newZCompLoc(i_idx));
i_material->mPEBlock->setDither(newDither(i_idx));
#ifdef DUSK_TPHD
i_material->mPEBlock->setPolygonOffset(newPolygonOffset(i_idx));
#endif
i_material->mTevBlock->setTevStageNum(newTevStageNum(i_idx));
for (u8 i = 0; i < tex_num; i++) {
i_material->mTevBlock->setTexNo(i, newTexNo(i_idx, i));
@@ -184,11 +165,7 @@ J3DMaterial* J3DMaterialFactory::createNormalMaterial(J3DMaterial* i_material, i
i_material->mTevBlock->setTevOrder(i, newTevOrder(i_idx, i));
}
for (u8 i = 0; i < tev_stage_num_max; i++) {
#ifdef DUSK_TPHD
J3DMaterialInitData* material_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
i_material->mTevBlock->setTevStage(i, newTevStage(i_idx, i));
if (material_init_data->mTevSwapModeIdx[i] != 0xffff) {
i_material->mTevBlock->getTevStage(i)->setTexSel(
@@ -223,11 +200,7 @@ J3DMaterial* J3DMaterialFactory::createNormalMaterial(J3DMaterial* i_material, i
for (u8 i = 0; i < 8; i++) {
i_material->mTexGenBlock->setTexMtx(i, newTexMtx(i_idx, i));
}
#ifdef DUSK_TPHD
J3DMaterialInitData* material_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
for (u8 i = 0; i < tev_stage_num_max; i++) {
if (material_init_data->mTevKColorSel[i] != 0xff) {
i_material->mTevBlock->setTevKColorSel(i, material_init_data->mTevKColorSel[i]);
@@ -300,11 +273,7 @@ J3DMaterial* J3DMaterialFactory::createPatchedMaterial(J3DMaterial* i_material,
i_material->mTevBlock->setTevColor(i, newTevColor(i_idx, i));
}
for (u8 i = 0; i < tev_stage_num; i++) {
#ifdef DUSK_TPHD
J3DMaterialInitData* material_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
i_material->mTevBlock->setTevStage(i, newTevStage(i_idx, i));
if (material_init_data->mTevSwapModeIdx[i] != 0xffff) {
i_material->mTevBlock->getTevStage(i)->setTexSel(
@@ -313,11 +282,7 @@ J3DMaterial* J3DMaterialFactory::createPatchedMaterial(J3DMaterial* i_material,
mpTevSwapModeInfo[material_init_data->mTevSwapModeIdx[i]].mRasSel);
}
}
#ifdef DUSK_TPHD
J3DMaterialInitData* init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
for (u8 i = 0; i < tev_stage_num; i++) {
if (init_data->mTevKColorSel[i] != 0xff) {
i_material->mTevBlock->setTevKColorSel(i, init_data->mTevKColorSel[i]);
@@ -458,11 +423,7 @@ u32 J3DMaterialFactory::calcSizeNormalMaterial(J3DMaterial* i_material, int i_id
size += J3DMaterial::calcSizeTevBlock((u16)tev_stage_num_max);
size += J3DMaterial::calcSizeIndBlock(ind_flag);
size += J3DMaterial::calcSizePEBlock(pe_flag, getMaterialMode(i_idx));
#ifdef DUSK_TPHD
J3DMaterialInitData* init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
for (u32 i = 0; i < 8; i++) {
if (init_data->mTexMtxIdx[i] != 0xffff) {
size += sizeof(J3DTexMtx);
@@ -483,11 +444,7 @@ u32 J3DMaterialFactory::calcSizePatchedMaterial(J3DMaterial* i_material, int i_i
size += sizeof(J3DTevBlockPatched);
size += J3DMaterial::calcSizeIndBlock(ind_flag);
size += J3DMaterial::calcSizePEBlock(0x10000000, getMaterialMode(i_idx));
#ifdef DUSK_TPHD
J3DMaterialInitData* init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
for (u32 i = 0; i < 8; i++) {
if (init_data->mTexMtxIdx[i] != 0xffff) {
size += sizeof(J3DTexMtx);
@@ -517,11 +474,7 @@ J3DGXColor J3DMaterialFactory::newMatColor(int i_idx, int i_no) const {
#else
J3DGXColor dflt = GXColor{0xff, 0xff, 0xff, 0xff};
#endif
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mMatColorIdx[i_no] != 0xffff) {
return (GXColor) mpMatColor[mtl_init_data->mMatColorIdx[i_no]];
} else {
@@ -530,11 +483,7 @@ J3DGXColor J3DMaterialFactory::newMatColor(int i_idx, int i_no) const {
}
const u8 J3DMaterialFactory::newColorChanNum(int i_idx) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mColorChanNumIdx != 0xff) {
return mpColorChanNum[mtl_init_data->mColorChanNumIdx];
} else {
@@ -544,11 +493,7 @@ const u8 J3DMaterialFactory::newColorChanNum(int i_idx) const {
J3DColorChan J3DMaterialFactory::newColorChan(int i_idx, int i_no) const {
u32 r29 = 0;
#ifdef DUSK_TPHD
J3DMaterialInitData* init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (init_data->mColorChanIdx[i_no] != 0xffff) {
return J3DColorChan(mpColorChanInfo[init_data->mColorChanIdx[i_no]]);
} else {
@@ -562,11 +507,7 @@ J3DGXColor J3DMaterialFactory::newAmbColor(int i_idx, int i_no) const {
#else
J3DGXColor dflt = GXColor{0x32, 0x32, 0x32, 0x32};
#endif
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mAmbColorIdx[i_no] != 0xffff) {
return (GXColor) mpAmbColor[mtl_init_data->mAmbColorIdx[i_no]];
} else {
@@ -576,11 +517,7 @@ J3DGXColor J3DMaterialFactory::newAmbColor(int i_idx, int i_no) const {
u32 J3DMaterialFactory::newTexGenNum(int i_idx) const {
u32 r30 = 0;
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mTexGenNumIdx != 0xff) {
return mpTexGenNum[mtl_init_data->mTexGenNumIdx];
} else {
@@ -589,11 +526,7 @@ u32 J3DMaterialFactory::newTexGenNum(int i_idx) const {
}
J3DTexCoord J3DMaterialFactory::newTexCoord(int i_idx, int i_no) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mTexCoordIdx[i_no] != 0xffff) {
return J3DTexCoord(mpTexCoordInfo[mtl_init_data->mTexCoordIdx[i_no]]);
} else {
@@ -603,11 +536,7 @@ J3DTexCoord J3DMaterialFactory::newTexCoord(int i_idx, int i_no) const {
J3DTexMtx* J3DMaterialFactory::newTexMtx(int i_idx, int i_no) const {
J3DTexMtx* tex_mtx = NULL;
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mTexMtxIdx[i_no] != 0xffff) {
#if TARGET_LITTLE_ENDIAN
auto tex_mtx_info = mpTexMtxInfo[mtl_init_data->mTexMtxIdx[i_no]];
@@ -629,11 +558,7 @@ J3DTexMtx* J3DMaterialFactory::newTexMtx(int i_idx, int i_no) const {
u8 J3DMaterialFactory::newCullMode(int i_idx) const {
u32 r30 = 0;
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mCullModeIdx != 0xff) {
return mpCullMode[mtl_init_data->mCullModeIdx];
} else {
@@ -642,11 +567,7 @@ u8 J3DMaterialFactory::newCullMode(int i_idx) const {
}
u16 J3DMaterialFactory::newTexNo(int i_idx, int i_no) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mTexNoIdx[i_no] != 0xffff) {
return mpTexNo[mtl_init_data->mTexNoIdx[i_no]];
} else {
@@ -655,11 +576,7 @@ u16 J3DMaterialFactory::newTexNo(int i_idx, int i_no) const {
}
J3DTevOrder J3DMaterialFactory::newTevOrder(int i_idx, int i_no) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mTevOrderIdx[i_no] != 0xffff) {
return J3DTevOrder(mpTevOrderInfo[mtl_init_data->mTevOrderIdx[i_no]]);
} else {
@@ -670,11 +587,7 @@ J3DTevOrder J3DMaterialFactory::newTevOrder(int i_idx, int i_no) const {
J3DGXColorS10 J3DMaterialFactory::newTevColor(int i_idx, int i_no) const {
GXColorS10 _dflt = {0, 0, 0, 0};
J3DGXColorS10 dflt = _dflt;
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mTevColorIdx[i_no] != 0xffff) {
return (GXColorS10) mpTevColor[mtl_init_data->mTevColorIdx[i_no]];
} else {
@@ -688,11 +601,7 @@ J3DGXColor J3DMaterialFactory::newTevKColor(int i_idx, int i_no) const {
#else
J3DGXColor dflt = GXColor{0xff, 0xff, 0xff, 0xff};
#endif
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mTevKColorIdx[i_no] != 0xffff) {
return (GXColor) mpTevKColor[mtl_init_data->mTevKColorIdx[i_no]];
} else {
@@ -701,11 +610,7 @@ J3DGXColor J3DMaterialFactory::newTevKColor(int i_idx, int i_no) const {
}
const u8 J3DMaterialFactory::newTevStageNum(int i_idx) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mTevStageNumIdx != 0xff) {
return mpTevStageNum[mtl_init_data->mTevStageNumIdx];
} else {
@@ -714,11 +619,7 @@ const u8 J3DMaterialFactory::newTevStageNum(int i_idx) const {
}
J3DTevStage J3DMaterialFactory::newTevStage(int i_idx, int i_no) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mTevStageIdx[i_no] != 0xffff) {
return J3DTevStage(mpTevStageInfo[mtl_init_data->mTevStageIdx[i_no]]);
} else {
@@ -727,11 +628,7 @@ J3DTevStage J3DMaterialFactory::newTevStage(int i_idx, int i_no) const {
}
J3DTevSwapModeTable J3DMaterialFactory::newTevSwapModeTable(int i_idx, int i_no) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mTevSwapModeTableIdx[i_no] != 0xffff) {
return J3DTevSwapModeTable(mpTevSwapModeTableInfo[mtl_init_data->mTevSwapModeTableIdx[i_no]]);
} else {
@@ -792,11 +689,7 @@ J3DIndTexCoordScale J3DMaterialFactory::newIndTexCoordScale(int i_idx, int i_no)
J3DFog J3DMaterialFactory::newFog(int i_idx) const {
J3DFog fog;
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mFogIdx != 0xffff) {
#if TARGET_LITTLE_ENDIAN
J3DFogInfo fogInfo = mpFogInfo[mtl_init_data->mFogIdx];
@@ -816,11 +709,7 @@ J3DFog J3DMaterialFactory::newFog(int i_idx) const {
}
J3DAlphaComp J3DMaterialFactory::newAlphaComp(int i_idx) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mAlphaCompIdx != 0xffff) {
return J3DAlphaComp(mpAlphaCompInfo[mtl_init_data->mAlphaCompIdx]);
} else {
@@ -829,11 +718,7 @@ J3DAlphaComp J3DMaterialFactory::newAlphaComp(int i_idx) const {
}
J3DBlend J3DMaterialFactory::newBlend(int i_idx) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mBlendIdx != 0xffff) {
return J3DBlend(mpBlendInfo[mtl_init_data->mBlendIdx]);
} else {
@@ -843,11 +728,7 @@ J3DBlend J3DMaterialFactory::newBlend(int i_idx) const {
J3DZMode J3DMaterialFactory::newZMode(int i_idx) const {
u32 r29 = 0;
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mZModeIdx != 0xff) {
return J3DZMode(mpZModeInfo[mtl_init_data->mZModeIdx]);
} else {
@@ -856,11 +737,7 @@ J3DZMode J3DMaterialFactory::newZMode(int i_idx) const {
}
const u8 J3DMaterialFactory::newZCompLoc(int i_idx) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mZCompLocIdx != 0xff){
return mpZCompLoc[mtl_init_data->mZCompLocIdx];
} else {
@@ -869,11 +746,7 @@ const u8 J3DMaterialFactory::newZCompLoc(int i_idx) const {
}
const u8 J3DMaterialFactory::newDither(int i_idx) const {
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mDitherIdx != 0xff){
return mpDither[mtl_init_data->mDitherIdx];
} else {
@@ -881,24 +754,9 @@ const u8 J3DMaterialFactory::newDither(int i_idx) const {
}
}
#ifdef DUSK_TPHD
const PolygonOffset J3DMaterialFactory::newPolygonOffset(int i_idx) const {
J3DMaterialInitData_MAT4* mtl_init_data = (J3DMaterialInitData_MAT4*)getMatInitData(i_idx);
if (mBlockType >= 4 && mtl_init_data->mPolygonOffsetIdx != 0xffff){
return mpPolygonOffsets[mtl_init_data->mPolygonOffsetIdx];
} else {
return PolygonOffset{0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
}
}
#endif
J3DNBTScale J3DMaterialFactory::newNBTScale(int i_idx) const {
J3DNBTScale dflt(j3dDefaultNBTScaleInfo);
#ifdef DUSK_TPHD
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
#else
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
#endif
if (mtl_init_data->mNBTScaleIdx != 0xffff) {
return J3DNBTScale(mpNBTScaleInfo[mtl_init_data->mNBTScaleIdx]);
} else {
@@ -103,9 +103,6 @@ J3DModelData* J3DModelLoader::load(void const* i_data, u32 i_flags) {
readJoint((J3DJointBlock*)block);
break;
case 'MAT3':
#if DUSK_TPHD
case 'MAT4':
#endif
readMaterial((J3DMaterialBlock*)block, (s32)i_flags);
break;
case 'MAT2':
@@ -150,9 +147,6 @@ J3DMaterialTable* J3DModelLoader::loadMaterialTable(void const* i_data) {
for (u32 block_no = 0; block_no < data->mBlockNum; block_no++) {
switch (block->mBlockType) {
case 'MAT3':
#if DUSK_TPHD
case 'MAT4':
#endif
readMaterialTable((J3DMaterialBlock*)block, flags);
break;
case 'MAT2':
@@ -218,9 +212,6 @@ J3DModelData* J3DModelLoader::loadBinaryDisplayList(void const* i_data, u32 i_fl
modifyMaterial(i_flags);
break;
case 'MAT3':
#if DUSK_TPHD
case 'MAT4':
#endif
flags = 0x50100000;
flags |= (i_flags & 0x3000000);
mpMaterialBlock = (J3DMaterialBlock*)block;
@@ -317,22 +308,8 @@ static GXVtxAttrFmtList getFmt(GXVtxAttrFmtList* i_fmtList, GXAttr i_attr) {
return *i_fmtList;
}
}
#if DUSK_TPHD
// HD BMDs occasionally have vertex arrays without a format entry. Mirror
// the GC runtime: fall back to J3DSys::initGX defaults.
GXVtxAttrFmtList def{};
def.attr = i_attr;
def.frac = 0;
if (i_attr == GX_VA_POS) { def.cnt = GX_POS_XYZ; def.type = GX_F32; }
else if (i_attr == GX_VA_NRM) { def.cnt = GX_NRM_XYZ; def.type = GX_F32; }
else if (i_attr == GX_VA_NBT) { def.cnt = GX_NRM_NBT; def.type = GX_F32; }
else if (i_attr >= GX_VA_CLR0 &&
i_attr <= GX_VA_CLR1) { def.cnt = GX_CLR_RGBA; def.type = GX_RGBA8; }
else { def.cnt = GX_TEX_ST; def.type = GX_F32; }
return def;
#else
OSPanic(__FILE__, __LINE__, "Unable to find vertex attribute format!");
#endif
}
#endif
@@ -16,7 +16,7 @@ u16 J3DModelLoader::countMaterialNum(const void* stream) {
const J3DModelBlock* block = header->mBlocks;
for (int i = 0; i < header->mBlockNum; i++)
{
if (block->mBlockType == 'MAT3' || block->mBlockType == 'MAT4') {
if (block->mBlockType == 'MAT3') {
const J3DMaterialBlock* materialBlock = (const J3DMaterialBlock*)block;
return materialBlock->mMaterialNum;
}
@@ -45,7 +45,6 @@ u32 J3DModelLoader::calcLoadSize(void const* stream, u32 flags_) {
size += calcSizeJoint((const J3DJointBlock*)nextBlock);
break;
case 'MAT3':
case 'MAT4':
size += calcSizeMaterial((const J3DMaterialBlock*)nextBlock, flags);
break;
case 'SHP1':
@@ -87,7 +86,6 @@ u32 J3DModelLoader::calcLoadMaterialTableSize(const void* stream) {
for (u32 i = 0; i < header->mBlockNum; i++) {
switch (nextBlock->mBlockType) {
case 'MAT3':
case 'MAT4':
size += calcSizeMaterialTable((const J3DMaterialBlock*)nextBlock, flags);
break;
case 'TEX1':
@@ -137,8 +135,7 @@ u32 J3DModelLoader::calcLoadBinaryDisplayListSize(const void* stream, u32 flags)
case 'MDL3':
size += calcSizeMaterialDL((const J3DMaterialDLBlock*)nextBlock, flags);
break;
case 'MAT3':
case 'MAT4': {
case 'MAT3': {
u32 flags2 = (J3DMLF_21 | J3DMLF_Material_PE_Full | J3DMLF_Material_Color_LightOn);
flags2 |= (u32)flags & (J3DMLF_Material_UseIndirect | J3DMLF_26);
mpMaterialBlock = (const J3DMaterialBlock*)nextBlock;
@@ -132,7 +132,12 @@ J3DShapeDraw* J3DShapeFactory::newShapeDraw(int shapeNo, int mtxGroupNo) const {
const J3DShapeInitData& shapeInitData = mShapeInitData[mIndexTable[shapeNo]];
const J3DShapeDrawInitData& drawInitData =
(&mDrawInitData[shapeInitData.mDrawInitDataIndex])[mtxGroupNo];
#if TARGET_PC
shapeDraw = JKR_NEW J3DShapeDraw(&mDisplayListData[drawInitData.mDisplayListIndex], drawInitData.mDisplayListSize,
getVtxDescList(shapeNo));
#else
shapeDraw = JKR_NEW J3DShapeDraw(&mDisplayListData[drawInitData.mDisplayListIndex], drawInitData.mDisplayListSize);
#endif
J3D_ASSERT_ALLOCMEM(193, shapeDraw);
return shapeDraw;
}
@@ -154,7 +159,7 @@ s32 J3DShapeFactory::calcSize(int shapeNo, u32 flag) {
for (u32 i = 0; i < mtxGroupNo; i++) {
size += calcSizeShapeMtx(flag, shapeNo, i);
size += 0x0C;
size += sizeof(J3DShapeDraw);
}
return size;
@@ -9,10 +9,6 @@
#include "JSystem/JKernel/JKRMemArchive.h"
#include "JSystem/JUtility/JUTAssert.h"
#if TARGET_PC && DUSK_TPHD
#include "dusk/tphd/HdAssetLayer.hpp"
#endif
JKRArchive* JKRArchive::check_mount_already(s32 entryNum, JKRHeap* heap) {
if (heap == NULL) {
heap = JKRGetCurrentHeap();
@@ -33,15 +29,6 @@ JKRArchive* JKRArchive::check_mount_already(s32 entryNum, JKRHeap* heap) {
JKRArchive* JKRArchive::mount(const char* path, EMountMode mountMode, JKRHeap* heap,
EMountDirection mountDirection) {
#if TARGET_PC && DUSK_TPHD
// TPHD arc redirect.
if (path != NULL) {
if (auto hdBuf = dusk::tphd::tryLoadHdArchive(path)) {
return mount((*hdBuf)->data(), heap, mountDirection);
}
}
#endif
s32 entryNum = DVDConvertPathToEntrynum(path);
if (entryNum < 0)
return NULL;
@@ -10,23 +10,10 @@
#include <stdint.h>
#include "os_report.h"
#if DUSK_TPHD
#include "dusk/tphd/HdAssetLayer.hpp"
#endif
JKRMemArchive::JKRMemArchive(s32 entryNum, JKRArchive::EMountDirection mountDirection)
: JKRArchive(entryNum, MOUNT_MEM) {
mIsMounted = false;
mMountDirection = mountDirection;
#if DUSK_TPHD
// TPHD arc redirect by entrynum.
if (const auto* hd = dusk::tphd::getHdBytesForEntryNum(entryNum)) {
if (!open(const_cast<u8*>(hd->data()), static_cast<u32>(hd->size()),
JKRMEMBREAK_FLAG_UNKNOWN0)) {
return;
}
} else
#endif
if (!open(entryNum, mMountDirection)) {
return;
}
+269 -30
View File
@@ -14,6 +14,33 @@
#endif
#include "tracy/Tracy.hpp"
#if TARGET_PC
#define JPA_DRAW_CTX_PARAM , ParticleDrawCtx* ctx
namespace {
GXColor emitter_prm_color(JPAEmitterWorkData* work) {
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g);
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
return prm;
}
GXColor emitter_env_color(JPAEmitterWorkData* work) {
JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = emtr->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
return env;
}
} // namespace
#else
#define JPA_DRAW_CTX_PARAM
#endif
void JPASetPointSize(JPAEmitterWorkData* work) {
GXSetPointSize((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
}
@@ -22,15 +49,16 @@ void JPASetLineWidth(JPAEmitterWorkData* work) {
GXSetLineWidth((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
}
void JPASetPointSize(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPASetPointSize(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
GXSetPointSize((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
}
void JPASetLineWidth(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPASetLineWidth(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
GXSetLineWidth((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
}
void JPARegistPrm(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
@@ -41,6 +69,7 @@ void JPARegistPrm(JPAEmitterWorkData* work) {
}
void JPARegistEnv(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = emtr->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
@@ -50,6 +79,7 @@ void JPARegistEnv(JPAEmitterWorkData* work) {
}
void JPARegistPrmEnv(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
GXColor env = emtr->mEnvClr;
@@ -64,7 +94,8 @@ void JPARegistPrmEnv(JPAEmitterWorkData* work) {
GXSetTevColor(GX_TEVREG1, env);
}
void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
@@ -72,10 +103,19 @@ void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
if (ctx->useClr1) {
ctx->clr1 = emitter_env_color(work);
}
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
}
void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = ptcl->mPrmClr;
@@ -84,10 +124,19 @@ void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
if (ctx->useClr1) {
ctx->clr1 = emitter_env_color(work);
}
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
}
void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = ptcl->mPrmClr;
@@ -100,11 +149,19 @@ void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
GXSetTevColor(GX_TEVREG1, env);
}
void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
GXColor env = ptcl->mEnvClr;
@@ -116,16 +173,31 @@ void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
GXSetTevColor(GX_TEVREG1, env);
}
void JPARegistEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPARegistEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = ptcl->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = emitter_prm_color(work);
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG1, env);
}
@@ -258,7 +330,7 @@ void JPAGenCalcTexCrdMtxAnm(JPAEmitterWorkData* work) {
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
}
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseShape* shape = work->mpRes->getBsp();
f32 dVar16 = param_1->mAge;
@@ -286,6 +358,12 @@ void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1)
local_108[2][1] = 0.0f;
local_108[2][2] = 1.0f;
local_108[2][3] = 0.0f;
#if TARGET_PC
if (ctx->batch) {
MTXCopy(local_108, ctx->texMtx);
return;
}
#endif
GXLoadTexMtxImm(local_108, 0x1e, GX_MTX2x4);
}
@@ -299,7 +377,7 @@ void JPALoadTexAnm(JPAEmitterWorkData* work) {
work->mpResMgr->load(work->mpRes->getTexIdx(work->mpEmtr->mTexAnmIdx), GX_TEXMAP0);
}
void JPALoadTexAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPALoadTexAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
work->mpResMgr->load(work->mpRes->getTexIdx(ptcl->mTexAnmIdx), GX_TEXMAP0);
}
@@ -429,6 +507,47 @@ static projectionFunc p_prj[3] = {
};
#if TARGET_PC
static void emit_batch_quad(JPAEmitterWorkData* work, const ParticleDrawCtx* ctx,
const Mtx posMtx) {
const JPAResource::BatchInfo& info = work->mpRes->mBatchInfo;
for (int i = 0; i < info.vtxCount; i++) {
Vec localPos = {info.vtxPos[i][0], info.vtxPos[i][1], info.vtxPos[i][2]};
Vec drawPos;
MTXMultVec(posMtx, &localPos, &drawPos);
f32 texS = info.vtxUv[i][0];
f32 texT = info.vtxUv[i][1];
if (ctx->useTexMtx) {
f32 srcS = texS;
f32 srcT = texT;
texS = ctx->texMtx[0][0] * srcS + ctx->texMtx[0][1] * srcT + ctx->texMtx[0][3];
texT = ctx->texMtx[1][0] * srcS + ctx->texMtx[1][1] * srcT + ctx->texMtx[1][3];
}
GXPosition3f32(drawPos.x, drawPos.y, drawPos.z);
if (ctx->useClr0) {
GXColor4u8(ctx->clr0.r, ctx->clr0.g, ctx->clr0.b, ctx->clr0.a);
}
if (ctx->useClr1) {
GXColor4u8(ctx->clr1.r, ctx->clr1.g, ctx->clr1.b, ctx->clr1.a);
}
GXTexCoord2f32(texS, texT);
}
}
static void submit_particle_quad(
JPAEmitterWorkData* work, ParticleDrawCtx* ctx, const Mtx posMtx, const u8* dl, u32 dlSize) {
if (ctx->batch) {
emit_batch_quad(work, ctx, posMtx);
return;
}
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(dl, dlSize);
}
void JPAInterpBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
Mtx ptclPosMtx;
MTXTrans(ptclPosMtx, ptcl->mPosition.x, ptcl->mPosition.y, ptcl->mPosition.z);
@@ -448,7 +567,7 @@ void JPAInterpRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
}
#endif
void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -473,12 +592,16 @@ void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
posMtx[2][2] = 1.0f;
posMtx[2][3] = pos.z;
posMtx[0][1] = posMtx[0][2] = posMtx[1][0] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -517,12 +640,16 @@ void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
posMtx[2][2] = 1.0f;
posMtx[2][3] = pos.z;
posMtx[0][2] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -542,12 +669,16 @@ void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
local_38[2][2] = work->mYBBCamMtx[2][2];
local_38[2][3] = local_48.z;
local_38[0][1] = local_38[0][2] = local_38[1][0] = local_38[2][0] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, local_38, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(local_38, GX_PNMTX0);
p_prj[work->mPrjType](work, local_38);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -576,9 +707,13 @@ void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
local_38[2][1] = local_94 * fVar1;
local_38[2][2] = local_90;
local_38[2][3] = local_48.z;
#if TARGET_PC
submit_particle_quad(work, ctx, local_38, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(local_38, GX_PNMTX0);
p_prj[work->mPrjType](work, local_38);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void dirTypeVel(JPAEmitterWorkData const* work, JPABaseParticle const* param_1,
@@ -741,6 +876,88 @@ static u8* p_dl[2] = {
};
#if TARGET_PC
static bool make_direction_mtx(JPAEmitterWorkData* work, JPABaseParticle* ptcl, Mtx posMtx) {
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
JGeometry::TVec3<f32> baseAxis(ptcl->mBaseAxis);
p_direction[work->mDirType](work, ptcl, &axisY);
if (axisY.isZero()) {
return false;
}
axisY.normalize();
axisZ.cross(baseAxis, axisY);
if (axisZ.isZero()) {
return false;
}
axisZ.normalize();
baseAxis.cross(axisY, axisZ);
baseAxis.normalize();
ptcl->mBaseAxis.set(baseAxis);
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
posMtx[0][0] = baseAxis.x;
posMtx[0][1] = axisY.x;
posMtx[0][2] = axisZ.x;
posMtx[0][3] = ptcl->mPosition.x;
posMtx[1][0] = baseAxis.y;
posMtx[1][1] = axisY.y;
posMtx[1][2] = axisZ.y;
posMtx[1][3] = ptcl->mPosition.y;
posMtx[2][0] = baseAxis.z;
posMtx[2][1] = axisY.z;
posMtx[2][2] = axisZ.z;
posMtx[2][3] = ptcl->mPosition.z;
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
return true;
}
static bool make_rot_direction_mtx(JPAEmitterWorkData* work, JPABaseParticle* ptcl, Mtx posMtx) {
f32 sinRot = JMASSin(ptcl->mRotateAngle);
f32 cosRot = JMASCos(ptcl->mRotateAngle);
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
JGeometry::TVec3<f32> baseAxis(ptcl->mBaseAxis);
p_direction[work->mDirType](work, ptcl, &axisY);
if (axisY.isZero()) {
return false;
}
axisY.normalize();
axisZ.cross(baseAxis, axisY);
if (axisZ.isZero()) {
return false;
}
axisZ.normalize();
baseAxis.cross(axisY, axisZ);
baseAxis.normalize();
ptcl->mBaseAxis.set(baseAxis);
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
Mtx rotMtx;
Mtx dirMtx;
p_rot[work->mRotType](sinRot, cosRot, rotMtx);
p_plane[work->mPlaneType](rotMtx, scaleX, scaleY);
dirMtx[0][0] = baseAxis.x;
dirMtx[0][1] = axisY.x;
dirMtx[0][2] = axisZ.x;
dirMtx[0][3] = ptcl->mPosition.x;
dirMtx[1][0] = baseAxis.y;
dirMtx[1][1] = axisY.y;
dirMtx[1][2] = axisZ.y;
dirMtx[1][3] = ptcl->mPosition.y;
dirMtx[2][0] = baseAxis.z;
dirMtx[2][1] = axisY.z;
dirMtx[2][2] = axisZ.z;
dirMtx[2][3] = ptcl->mPosition.z;
MTXConcat(dirMtx, rotMtx, posMtx);
return true;
}
void JPAInterpDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
@@ -823,7 +1040,7 @@ void JPAInterpRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
}
#endif
void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -832,8 +1049,12 @@ void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
Mtx posMtx;
#if TARGET_PC
if (!dusk::frame_interp::lookup_replacement(ptcl, posMtx))
#endif
if (!dusk::frame_interp::lookup_replacement(ptcl, posMtx) &&
!make_direction_mtx(work, ptcl, posMtx))
{
return;
}
#else
{
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
@@ -869,14 +1090,19 @@ void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
posMtx[2][3] = ptcl->mPosition.z;
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
}
#endif
MTXConcat(work->mPosCamMtx, posMtx, posMtx);
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, p_dl[work->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
#endif
}
void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -886,8 +1112,12 @@ void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
Mtx mtx1;
Mtx mtx2;
#if TARGET_PC
if (!dusk::frame_interp::lookup_replacement(ptcl, mtx1))
#endif
if (!dusk::frame_interp::lookup_replacement(ptcl, mtx1) &&
!make_rot_direction_mtx(work, ptcl, mtx1))
{
return;
}
#else
{
f32 sinRot = JMASSin(ptcl->mRotateAngle);
f32 cosRot = JMASCos(ptcl->mRotateAngle);
@@ -927,13 +1157,18 @@ void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
mtx2[2][3] = ptcl->mPosition.z;
MTXConcat(mtx2, mtx1, mtx1);
}
#endif
MTXConcat(work->mPosCamMtx, mtx1, mtx2);
#if TARGET_PC
submit_particle_quad(work, ctx, mtx2, p_dl[work->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(mtx2, GX_PNMTX0);
p_prj[work->mPrjType](work, mtx2);
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
#endif
}
void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -970,7 +1205,7 @@ void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
}
void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -988,12 +1223,16 @@ void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
auStack_88[1][3] = param_1->mPosition.y;
auStack_88[2][3] = param_1->mPosition.z;
MTXConcat(param_0->mPosCamMtx, auStack_88, auStack_88);
#if TARGET_PC
submit_particle_quad(param_0, ctx, auStack_88, p_dl[param_0->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(auStack_88, 0);
p_prj[param_0->mPrjType](param_0, auStack_88);
GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl));
#endif
}
void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -1010,7 +1249,7 @@ void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
}
void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -1086,7 +1325,7 @@ void JPADrawStripe(JPAEmitterWorkData* param_0) {
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) {
param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject();
@@ -1111,7 +1350,7 @@ void JPADrawStripe(JPAEmitterWorkData* param_0) {
}
particle->mBaseAxis.cross(local_f8, local_104);
particle->mBaseAxis.normalize();
local_c8[0][0] = local_104.x;
local_c8[0][1] = local_f8.x;
local_c8[0][2] = particle->mBaseAxis.x;
@@ -1177,7 +1416,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) {
param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject();
@@ -1202,7 +1441,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
}
particle->mBaseAxis.cross(local_c0, local_cc);
particle->mBaseAxis.normalize();
local_90[0][0] = local_cc.x;
local_90[0][1] = local_c0.x;
local_90[0][2] = particle->mBaseAxis.x;
@@ -1227,7 +1466,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
coord = start_coord;
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) {
param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject();
@@ -1252,7 +1491,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
}
particle->mBaseAxis.cross(local_c0, local_cc);
particle->mBaseAxis.normalize();
local_90[0][0] = local_cc.x;
local_90[0][1] = local_c0.x;
local_90[0][2] = particle->mBaseAxis.x;
@@ -1289,7 +1528,7 @@ void JPADrawEmitterCallBackB(JPAEmitterWorkData* work) {
emtr->mpEmtrCallBack->draw(emtr);
}
void JPADrawParticleCallBack(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawParticleCallBack(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
JPABaseEmitter* emtr = work->mpEmtr;
if (emtr->mpPtclCallBack == NULL) {
return;
+1 -2
View File
@@ -206,8 +206,7 @@ void JPABaseParticle::init_c(JPAEmitterWorkData* work, JPABaseParticle* parent)
#if TARGET_PC
void JPABaseParticle::interp(JPAEmitterWorkData* work, void const* drawFunc) {
static bool enable = false;
if (!enable)
if (!dusk::frame_interp::is_enabled())
return;
// don't interpolate the first frame
+284 -6
View File
@@ -18,9 +18,21 @@
#include "global.h"
#include "tracy/Tracy.hpp"
#if TARGET_PC
#define JPA_DRAW_CTX_ARG , &ctx
#else
#define JPA_DRAW_CTX_ARG
#endif
JPAResource::JPAResource() {
mpCalcEmitterFuncList = mpDrawEmitterFuncList = mpDrawEmitterChildFuncList = NULL;
#if TARGET_PC
mpCalcParticleFuncList = mpCalcParticleChildFuncList = NULL;
mpDrawParticleFuncList = mpDrawParticleChildFuncList = NULL;
mBatchInfo = {};
#else
mpCalcParticleFuncList = mpDrawParticleFuncList = mpCalcParticleChildFuncList = mpDrawParticleChildFuncList = NULL;
#endif
pBsp = NULL;
pEsp = NULL;
pCsp = NULL;
@@ -61,6 +73,60 @@ static u8 jpa_crd[32] ATTRIBUTE_ALIGN(32) = {
0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02,
};
#if TARGET_PC
void JPAResource::initBatchInfo() {
mBatchInfo = {};
bool hasDrawFunc = false;
for (int i = 0; i < mpDrawParticleFuncListNum; i++) {
DrawParticleFunc func = mpDrawParticleFuncList[i];
if (func == JPADrawBillboard || func == JPADrawRotBillboard ||
func == JPADrawYBillboard || func == JPADrawRotYBillboard ||
func == JPADrawDirection || func == JPADrawRotDirection || func == JPADrawRotation)
{
hasDrawFunc = true;
} else if (func == JPADrawParticleCallBack) {
// Batchable only for emitters without a particle callback; checked per draw
} else if (func == JPALoadCalcTexCrdMtxAnm) {
mBatchInfo.hasPtclTexMtx = true;
} else if (func == JPARegistAlpha || func == JPARegistPrmAlpha ||
func == JPARegistPrmAlphaEnv || func == JPARegistAlphaEnv ||
func == static_cast<DrawParticleFunc>(JPARegistEnv)) // overloaded
{
mBatchInfo.hasPtclColor = true;
} else {
// JPADrawPoint, JPADrawLine, JPADrawDBillboard, JPALoadTexAnm,
// JPASetPointSize, JPASetLineWidth
return;
}
}
if (!hasDrawFunc) {
return;
}
// Template array offsets, same math as setPTev
int base_plane_type = (pBsp->getType() == 3 || pBsp->getType() == 7) ?
pBsp->getBasePlaneType() : 0;
int center_offset = pEsp != nullptr ? (pEsp->getScaleCenterX() + 3 * pEsp->getScaleCenterY()) * 0xC : 0x30;
const s8* pos = reinterpret_cast<const s8*>(jpa_pos) + center_offset + base_plane_type * 0x6C;
const s8* crd = reinterpret_cast<const s8*>(jpa_crd) + (pBsp->getTilingS() + 2 * pBsp->getTilingT()) * 8;
bool cross = pBsp->getType() == 4 || pBsp->getType() == 8;
mBatchInfo.vtxCount = cross ? 8 : 4;
for (int i = 0; i < mBatchInfo.vtxCount; i++) {
int posIdx = i < 4 ? i : 72 + (i - 4);
int crdIdx = i & 3;
mBatchInfo.vtxPos[i][0] = pos[posIdx * 3 + 0];
mBatchInfo.vtxPos[i][1] = pos[posIdx * 3 + 1];
mBatchInfo.vtxPos[i][2] = pos[posIdx * 3 + 2];
mBatchInfo.vtxUv[i][0] = crd[crdIdx * 2 + 0];
mBatchInfo.vtxUv[i][1] = crd[crdIdx * 2 + 1];
}
mBatchInfo.supported = true;
}
#endif
void JPAResource::init(JKRHeap* heap) {
BOOL is_glbl_clr_anm = pBsp->isGlblClrAnm();
BOOL is_glbl_tex_anm = pBsp->isGlblTexAnm();
@@ -525,7 +591,10 @@ void JPAResource::init(JKRHeap* heap) {
if (mpDrawParticleFuncListNum != 0) {
mpDrawParticleFuncList =
(ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleFuncListNum * sizeof(ParticleFunc), alignof(ParticleFunc));
(DrawParticleFunc*)JKRAllocFromHeap(
heap,
mpDrawParticleFuncListNum * sizeof(DrawParticleFunc),
alignof(DrawParticleFunc));
}
func_no = 0;
@@ -635,7 +704,10 @@ void JPAResource::init(JKRHeap* heap) {
if (mpDrawParticleChildFuncListNum != 0) {
mpDrawParticleChildFuncList =
(ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleChildFuncListNum * sizeof(ParticleFunc), sizeof(EmitterFunc));
(DrawParticleFunc*)JKRAllocFromHeap(
heap,
mpDrawParticleChildFuncListNum * sizeof(DrawParticleFunc),
alignof(DrawParticleFunc));
}
func_no = 0;
@@ -699,6 +771,10 @@ void JPAResource::init(JKRHeap* heap) {
mpDrawParticleChildFuncList[func_no] = &JPARegistPrmAlphaEnv;
func_no++;
}
#if TARGET_PC
initBatchInfo();
#endif
}
bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
@@ -761,6 +837,15 @@ bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
}
}
#ifdef TARGET_PC
if (((pBsp && pBsp->getDirType() == 3) || (pCsp && pCsp->getDirType() == 3)) &&
dusk::frame_interp::is_enabled())
{
// ensure mGlobalEmtrDir is valid
calcWorkData_d(work);
}
#endif
JPANode<JPABaseParticle>* next = NULL;
for (JPANode<JPABaseParticle>* node = emtr->mAlivePtclBase.getFirst(); node != emtr->mAlivePtclBase.getEnd(); node = next) {
next = node->getNext();
@@ -799,6 +884,183 @@ void JPAResource::draw(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
}
}
#if TARGET_PC
static GXTevAlphaArg to_vtx_alpha_arg(GXTevAlphaArg arg) {
return arg == GX_CA_A0 ? GX_CA_RASA : arg;
}
static void batch_set_tev_op(GXTevStageID stage) {
GXSetTevColorOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
}
static void batch_setup_tev(JPAEmitterWorkData* work, bool useClr1) {
JPABaseShape* shape = work->mpRes->getBsp();
JPAExTexShape* ets = work->mpRes->getEts();
bool useIndirect = ets != nullptr && ets->isUseIndirect();
// JPAEmitterManager::draw configures both channels to pass vertex color through
GXSetNumChans(useClr1 ? 2 : 1);
const GXTevAlphaArg* alphaArg = shape->getTevAlphaArg();
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GXSetTevAlphaIn(GX_TEVSTAGE0, to_vtx_alpha_arg(alphaArg[0]), to_vtx_alpha_arg(alphaArg[1]),
to_vtx_alpha_arg(alphaArg[2]), to_vtx_alpha_arg(alphaArg[3]));
batch_set_tev_op(GX_TEVSTAGE0);
if (!useIndirect) {
GXSetTevDirect(GX_TEVSTAGE0);
}
GXTevStageID nextStage = GX_TEVSTAGE1;
switch (shape->getTevColorArgSel()) {
case 0: // TEXC
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_ONE, GX_CC_ZERO);
break;
case 1: // C0 * TEXC
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
break;
case 2: // lerp(C0, 1, TEXC)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO);
break;
case 3: // lerp(C1, C0, TEXC) = C0 * TEXC (stage 0) + C1 * (1 - TEXC) (stage 1)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
GXSetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR1A1);
GXSetTevColorIn(nextStage, GX_CC_RASC, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
break;
case 4: // TEXC * C0 + C1: C0 * TEXC (stage 0), + C1 (stage 1)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
GXSetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR1A1);
GXSetTevColorIn(nextStage, GX_CC_CPREV, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
break;
case 5: // C0
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
break;
}
if (ets != nullptr && ets->isUseSecTex()) {
// Mirrors setPTev's secondary texture stage, at the next free stage
GXTexCoordID texCoord = useIndirect ? GX_TEXCOORD2 : GX_TEXCOORD1;
GXSetTevOrder(nextStage, texCoord, GX_TEXMAP3, GX_COLOR_NULL);
GXSetTevColorIn(nextStage, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_ZERO);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
}
GXSetNumTevStages(nextStage);
}
static void batch_setup_vtx_desc(bool useClr0, bool useClr1) {
static Mtx identityMtx = {
{1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, 0.0f},
};
GXLoadPosMtxImm(identityMtx, GX_PNMTX0);
GXSetCurrentMtx(GX_PNMTX0);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
if (useClr0) {
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
}
if (useClr1) {
GXSetVtxDesc(GX_VA_CLR1, GX_DIRECT);
}
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
if (useClr0) {
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
}
if (useClr1) {
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0);
}
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
}
static void batch_restore_gx(JPAEmitterWorkData* work, bool changedTev, bool changedTexMtx) {
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSetCurrentMtx(GX_PNMTX0);
if (changedTexMtx) {
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
}
if (changedTev) {
GXSetNumChans(0);
work->mpRes->getBsp()->setGX(work);
work->mpRes->setPTev();
}
}
static bool draw_particle_batch(JPAEmitterWorkData* work) {
ZoneScoped;
JPAResource* res = work->mpRes;
const JPAResource::BatchInfo& info = res->mBatchInfo;
if (!info.supported || work->mPrjType != 0 || work->mpEmtr->mpPtclCallBack != nullptr) {
return false;
}
bool useClr0 = false;
bool useClr1 = false;
if (info.hasPtclColor) {
u32 colorSel = res->getBsp()->getTevColorArgSel();
if (colorSel >= 6) {
return false;
}
useClr0 = true;
useClr1 = colorSel == 3 || colorSel == 4;
batch_setup_tev(work, useClr1);
}
if (info.hasPtclTexMtx) {
// UVs are CPU-transformed; drop the texgen
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
}
batch_setup_vtx_desc(useClr0, useClr1);
ParticleDrawCtx ctx{};
ctx.batch = true;
ctx.useTexMtx = info.hasPtclTexMtx;
ctx.useClr0 = useClr0;
ctx.useClr1 = useClr1;
bool fwdAhead = res->getBsp()->isDrawFwdAhead();
JPANode<JPABaseParticle>* node = fwdAhead ? work->mpEmtr->mAlivePtclBase.getLast() :
work->mpEmtr->mAlivePtclBase.getFirst();
GXBegin(GX_QUADS, GX_VTXFMT1, GX_AUTO);
while (node != work->mpEmtr->mAlivePtclBase.getEnd()) {
work->mpCurNode = node;
for (int i = res->mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*res->mpDrawParticleFuncList[i])(work, node->getObject(), &ctx);
}
node = fwdAhead ? node->getPrev() : node->getNext();
}
GXEnd();
batch_restore_gx(work, useClr0, info.hasPtclTexMtx);
return true;
}
#endif
void JPAResource::drawP(JPAEmitterWorkData* work) {
ZoneScoped;
work->mpEmtr->clearStatus(0x80);
@@ -833,13 +1095,25 @@ void JPAResource::drawP(JPAEmitterWorkData* work) {
(*mpDrawEmitterFuncList[i])(work);
}
#if TARGET_PC
if (draw_particle_batch(work)) {
GXSetMisc(GX_MT_XF_FLUSH, 0);
if (work->mpEmtr->mpEmtrCallBack != nullptr) {
work->mpEmtr->mpEmtrCallBack->drawAfter(work->mpEmtr);
}
return;
}
ParticleDrawCtx ctx{}; // immediate mode
#endif
if (pBsp->isDrawFwdAhead()) {
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclBase.getLast();
for (; node != work->mpEmtr->mAlivePtclBase.getEnd(); node = node->getPrev()) {
work->mpCurNode = node;
if (mpDrawParticleFuncList != NULL) {
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleFuncList[i])(work, node->getObject());
(*mpDrawParticleFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
}
}
}
@@ -849,7 +1123,7 @@ void JPAResource::drawP(JPAEmitterWorkData* work) {
work->mpCurNode = node;
if (mpDrawParticleFuncList != NULL) {
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleFuncList[i])(work, node->getObject());
(*mpDrawParticleFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
}
}
}
@@ -896,13 +1170,17 @@ void JPAResource::drawC(JPAEmitterWorkData* work) {
(*mpDrawEmitterChildFuncList[i])(work);
}
#if TARGET_PC
ParticleDrawCtx ctx{}; // immediate mode
#endif
if (pBsp->isDrawFwdAhead()) {
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclChld.getLast();
for (; node != work->mpEmtr->mAlivePtclChld.getEnd(); node = node->getPrev()) {
work->mpCurNode = node;
if (mpDrawParticleChildFuncList != NULL) {
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleChildFuncList[i])(work, node->getObject());
(*mpDrawParticleChildFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
}
}
}
@@ -912,7 +1190,7 @@ void JPAResource::drawC(JPAEmitterWorkData* work) {
work->mpCurNode = node;
if (mpDrawParticleChildFuncList != NULL) {
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleChildFuncList[i])(work, node->getObject());
(*mpDrawParticleChildFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
}
}
}
+1
View File
@@ -249,6 +249,7 @@ f32 JUTResFont::drawChar_scale(f32 pos_x, f32 pos_y, f32 scale_x, f32 scale_y, i
f32 x2;
f32 y1;
ZoneScoped;
JUT_ASSERT(378, mValid);
JUTFont::TWidth width;
loadFont(str_int, GX_TEXMAP0, &width FONT_DRAW_CTX_ARG);
@@ -4,6 +4,7 @@ import android.app.ActionBar;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
@@ -14,12 +15,16 @@ import android.provider.DocumentsContract;
import android.provider.OpenableColumns;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import org.libsdl.app.SDLActivity;
import org.libsdl.app.SDLSurface;
import java.io.File;
import java.util.ArrayList;
@@ -27,6 +32,7 @@ import java.util.List;
public class DuskActivity extends SDLActivity {
private static final String TAG = "DuskActivity";
private static final float DEFAULT_SURFACE_FRAME_RATE = 60.0f;
private static final int FOLDER_DIALOG_REQUEST_CODE = 0x4455;
private static final int MANAGE_STORAGE_REQUEST_CODE = 0x4456;
private static final String EXTERNAL_STORAGE_AUTHORITY =
@@ -88,6 +94,11 @@ public class DuskActivity extends SDLActivity {
hideSystemBars();
}
@Override
protected SDLSurface createSDLSurface(Context context) {
return new DuskSurface(context);
}
@Override
protected void onResume() {
super.onResume();
@@ -139,6 +150,77 @@ public class DuskActivity extends SDLActivity {
};
}
public void setPreferredSurfaceFrameRate(float frameRate) {
runOnUiThread(() -> {
if (mSurface instanceof DuskSurface) {
((DuskSurface)mSurface).setPreferredFrameRate(frameRate);
}
});
}
private static final class DuskSurface extends SDLSurface {
private float preferredFrameRate = DEFAULT_SURFACE_FRAME_RATE;
DuskSurface(Context context) {
super(context);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.surfaceChanged(holder, format, width, height);
setTargetFrameRate(holder);
}
void setPreferredFrameRate(float frameRate) {
preferredFrameRate = frameRate;
setTargetFrameRate(getHolder());
}
private void setTargetFrameRate(SurfaceHolder holder) {
if (!mIsSurfaceReady || Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
return;
}
Surface surface = holder != null ? holder.getSurface() : getHolder().getSurface();
if (surface == null || !surface.isValid()) {
return;
}
float targetFrameRate = getMaxSupportedFrameRate();
if (preferredFrameRate > 0.0f) {
targetFrameRate = preferredFrameRate;
}
if (targetFrameRate <= 0.0f) {
return;
}
try {
surface.setFrameRate(
targetFrameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
Log.v(TAG, "Requested surface frame rate " + targetFrameRate + " fps");
} catch (RuntimeException e) {
Log.w(TAG, "Failed to request surface frame rate", e);
}
}
private float getMaxSupportedFrameRate() {
if (mDisplay == null) {
return 0.0f;
}
float maxFrameRate = mDisplay.getRefreshRate();
Display.Mode[] modes = mDisplay.getSupportedModes();
if (modes == null) {
return maxFrameRate;
}
for (Display.Mode mode : modes) {
maxFrameRate = Math.max(maxFrameRate, mode.getRefreshRate());
}
return maxFrameRate;
}
}
@Override
protected String[] getArguments() {
Intent intent = getIntent();
@@ -19,9 +19,13 @@ import android.os.*;
import java.lang.Runnable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDevice {
private static final String TAG = "hidapi";
@@ -33,10 +37,19 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
private boolean mIsConnected = false;
private boolean mIsChromebook = false;
private boolean mIsReconnecting = false;
private boolean mHasEnabledNotifications = false;
private boolean mHasSeenInputUpdate = false;
private boolean mFrozen = false;
private LinkedList<GattOperation> mOperations;
GattOperation mCurrentOperation = null;
private Handler mHandler;
private int mProductId = -1;
private int mReportId = 0;
private UUID mInputCharacteristic;
private static final int D0G_BLE2_PID = 0x1106;
private static final int TRITON_BLE_PID = 0x1303;
private static final int TRANSPORT_AUTO = 0;
private static final int TRANSPORT_BREDR = 1;
@@ -45,10 +58,14 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000;
static final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristic = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicD0G = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicTriton_0x45 = UUID.fromString("100F6C7A-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicTriton_0x47 = UUID.fromString("100F6C7C-1735-4313-B402-38567131E5F3");
static final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3");
static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 };
private HashMap<Integer, BluetoothGattCharacteristic> mOutputReportChars = new HashMap<Integer, BluetoothGattCharacteristic>();
static class GattOperation {
private enum Operation {
CHR_READ,
@@ -61,6 +78,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
byte[] mValue;
BluetoothGatt mGatt;
boolean mResult = true;
int mDelayMs = 0;
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid) {
mGatt = gatt;
@@ -68,6 +86,13 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mUuid = uuid;
}
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, int delayMs) {
mGatt = gatt;
mOp = operation;
mUuid = uuid;
mDelayMs = delayMs;
}
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value) {
mGatt = gatt;
mOp = operation;
@@ -75,6 +100,14 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mValue = value;
}
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value, int delayMs) {
mGatt = gatt;
mOp = operation;
mUuid = uuid;
mValue = value;
mDelayMs = delayMs;
}
public void run() {
// This is executed in main thread
BluetoothGattCharacteristic chr;
@@ -136,6 +169,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
return mResult;
}
public int getDelayMs() { return mDelayMs; }
private BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
BluetoothGattService valveService = mGatt.getService(steamControllerService);
if (valveService == null)
@@ -154,6 +189,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid) {
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid);
}
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid, int delayMs) {
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid, delayMs);
}
}
HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) {
@@ -166,6 +205,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mHandler = new Handler(Looper.getMainLooper());
mGatt = connectGatt();
mHasEnabledNotifications = false;
mHasSeenInputUpdate = false;
// final HIDDeviceBLESteamController finalThis = this;
// mHandler.postDelayed(new Runnable() {
// @Override
@@ -314,8 +355,45 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
Log.v(TAG, "Found Valve steam controller service " + service.getUuid());
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
if (chr.getUuid().equals(inputCharacteristic)) {
Log.v(TAG, "Found input characteristic");
if (chr.getUuid().equals(inputCharacteristicTriton_0x45)) {
Log.v(TAG, "Found Triton input characteristic 0x45");
mProductId = TRITON_BLE_PID;
mReportId = 0x45;
mInputCharacteristic = chr.getUuid();
} else if (chr.getUuid().equals(inputCharacteristicTriton_0x47)) {
Log.v(TAG, "Found Triton input characteristic 0x47");
mProductId = TRITON_BLE_PID;
mReportId = 0x47;
mInputCharacteristic = chr.getUuid();
} else if (chr.getUuid().equals(inputCharacteristicD0G)) {
Log.v(TAG, "Found D0G input characteristic");
mProductId = D0G_BLE2_PID;
mReportId = 0x03;
mInputCharacteristic = chr.getUuid();
} else {
Pattern reportPattern = Pattern.compile("100F6C([0-9A-Z]{2})", Pattern.CASE_INSENSITIVE);
Matcher matcher = reportPattern.matcher(chr.getUuid().toString());
if (matcher.find()) {
try {
int reportId = Integer.parseInt(matcher.group(1), 16);
reportId -= 0x35;
if (reportId >= 0x80) {
// This is a Triton output report characteristic that we need to care about.
Log.v(TAG, "Found Triton output report 0x" + Integer.toString(reportId, 16));
mOutputReportChars.put(reportId, chr);
}
}
catch (NumberFormatException nfe) {
Log.w(TAG, "Could not parse report characteristic " + chr.getUuid().toString() + ": " + nfe.toString());
}
}
}
}
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
if (chr.getUuid().equals(mInputCharacteristic)) {
// Start notifications
BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
if (cccd != null) {
@@ -372,21 +450,30 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mCurrentOperation = mOperations.removeFirst();
}
// Run in main thread
mHandler.post(new Runnable() {
@Override
public void run() {
synchronized (mOperations) {
if (mCurrentOperation == null) {
Log.e(TAG, "Current operation null in executor?");
return;
}
Runnable gattOperationRunnable = new Runnable() {
@Override
public void run() {
synchronized (mOperations) {
if (mCurrentOperation == null) {
Log.e(TAG, "Current operation null in executor?");
return;
}
mCurrentOperation.run();
// now wait for the GATT callback and when it comes, finish this operation
mCurrentOperation.run();
// now wait for the GATT callback and when it comes, finish this operation
}
}
}
});
};
if (mCurrentOperation.getDelayMs() == 0) {
// Run in main thread
mHandler.post(gattOperationRunnable);
}
else {
// If we have a delay on this operation, wait before we post it.
mHandler.postDelayed(gattOperationRunnable, mCurrentOperation.getDelayMs());
}
}
private void queueGattOperation(GattOperation op) {
@@ -397,8 +484,39 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
}
private void enableNotification(UUID chrUuid) {
GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid);
// Add a 500ms delay to notification write for Amazon Fire TV devices, as otherwise if we do this too quickly after connecting
// it will return success and then silently drop the operation on the floor.
GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid, 500);
queueGattOperation(op);
// Amazon Fire devices can also silently timeout on writeDescriptor, so
// set up a little delayed check that will attempt to write a second time.
//
// While this only seems to be needed on Amazon Fire TV devices at present, it
// doesn't hurt to have a retry on other devices as well.
//
final HIDDeviceBLESteamController finalThis = this;
final UUID finalUuid = chrUuid;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (!finalThis.mHasEnabledNotifications) {
if (finalThis.mHasSeenInputUpdate) {
// Amazon Five devices may have enabled notifications on the input characteristic and not given us a callback. If we've seen
// input reports, though, somewhat by definition notifications are enabled.
Log.w(TAG, "WriteDescriptor has never returned, but we've seen input reports. Moving on with controller initialization.");
finalThis.mHasEnabledNotifications = true;
finalThis.enableValveMode();
return;
}
// Give one more try.
GattOperation retry = HIDDeviceBLESteamController.GattOperation.enableNotification(finalThis.mGatt, finalUuid, 500);
finalThis.queueGattOperation(retry);
}
}
}, 1000);
}
void writeCharacteristic(UUID uuid, byte[] value) {
@@ -448,8 +566,16 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mIsConnected = false;
gatt.disconnect();
mGatt = connectGatt(false);
}
else {
} else {
if (getProductId() == TRITON_BLE_PID) {
// Android will not properly play well with Data Length Extensions without manually requesting a large MTU,
// and Triton controllers require DLE support.
//
// 517 is basically a "magic number" as far as Android's bluetooth code is concerned, so do not change
// this value. It is functionally "please enable data length extensions" on some Android builds.
mGatt.requestMtu(517);
}
probeService(this);
}
}
@@ -474,7 +600,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
// Only register controller with the native side once it has been fully configured
if (!isRegistered()) {
Log.v(TAG, "Registering Steam Controller with ID: " + getId());
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true);
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId);
setRegistered();
}
}
@@ -487,7 +613,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
// Enable this for verbose logging of controller input reports
//Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue()));
if (characteristic.getUuid().equals(inputCharacteristic) && !mFrozen) {
if (characteristic.getUuid().equals(mInputCharacteristic) && !mFrozen) {
mHasSeenInputUpdate = true;
mManager.HIDDeviceInputReport(getId(), characteristic.getValue());
}
}
@@ -497,19 +624,36 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
//Log.v(TAG, "onDescriptorRead status=" + status);
}
private void enableValveMode()
{
BluetoothGattService valveService = mGatt.getService(steamControllerService);
if (valveService == null)
return;
BluetoothGattCharacteristic reportChr = valveService.getCharacteristic(reportCharacteristic);
if (reportChr != null) {
if (getProductId() == TRITON_BLE_PID) {
// For Triton we just mark things registered.
Log.v(TAG, "Registering Triton Steam Controller with ID: " + getId());
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId);
setRegistered();
} else {
// For the original controller, we need to manually enter Valve mode.
Log.v(TAG, "Writing report characteristic to enter valve mode");
reportChr.setValue(enterValveMode);
mGatt.writeCharacteristic(reportChr);
}
}
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
BluetoothGattCharacteristic chr = descriptor.getCharacteristic();
//Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid());
if (chr.getUuid().equals(inputCharacteristic)) {
boolean hasWrittenInputDescriptor = true;
BluetoothGattCharacteristic reportChr = chr.getService().getCharacteristic(reportCharacteristic);
if (reportChr != null) {
Log.v(TAG, "Writing report characteristic to enter valve mode");
reportChr.setValue(enterValveMode);
gatt.writeCharacteristic(reportChr);
}
if (chr.getUuid().equals(mInputCharacteristic)) {
mHasEnabledNotifications = true;
enableValveMode();
}
finishCurrentGattOperation();
@@ -548,9 +692,20 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
@Override
public int getProductId() {
// We don't have an easy way to query from the Bluetooth device, but we know what it is
final int D0G_BLE2_PID = 0x1106;
return D0G_BLE2_PID;
if (mProductId > 0) {
// We've already set a product ID.
return mProductId;
}
if (mDevice.getName().startsWith("Steam Ctrl")) {
// We're a newer Triton device
mProductId = TRITON_BLE_PID;
} else {
// We're an OG Steam Controller
mProductId = D0G_BLE2_PID;
}
return mProductId;
}
@Override
@@ -601,10 +756,29 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
writeCharacteristic(reportCharacteristic, actual_report);
return report.length;
} else {
//Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report));
writeCharacteristic(reportCharacteristic, report);
return report.length;
// If we're an original-recipe Steam Controller we just write to the characteristic directly.
if (getProductId() == D0G_BLE2_PID) {
//Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report));
writeCharacteristic(reportCharacteristic, report);
return report.length;
}
// If we're a Triton, we need to find the correct report characteristic.
if (report.length > 0) {
int reportId = report[0] & 0xFF;
BluetoothGattCharacteristic targetedReportCharacteristic = mOutputReportChars.get(reportId);
if (targetedReportCharacteristic != null) {
byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1);
//Log.v(TAG, "writeOutputReport 0x" + Integer.toString(reportId, 16) + " " + HexDump.dumpHexString(report));
writeCharacteristic(targetedReportCharacteristic.getUuid(), actual_report);
return report.length;
} else {
Log.w(TAG, "Got report write request for unknown report type 0x" + Integer.toString(reportId, 16));
}
}
}
return -1;
}
@Override
@@ -256,6 +256,7 @@ public class HIDDeviceManager {
0x24c6, // PowerA
0x2c22, // Qanba
0x2dc8, // 8BitDo
0x3537, // GameSir
0x37d7, // Flydigi
0x9886, // ASTRO Gaming
};
@@ -360,7 +361,7 @@ public class HIDDeviceManager {
HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index);
int id = device.getId();
mDevicesById.put(id, device);
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false);
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false, 0);
}
}
}
@@ -529,7 +530,13 @@ public class HIDDeviceManager {
return false;
}
return bluetoothDevice.getName().equals("SteamController") && ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) != 0);
// Steam Controllers will always support Bluetooth Low Energy
if ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) == 0) {
return false;
}
// Match on the name either the original Steam Controller or the new second-generation one advertise with.
return bluetoothDevice.getName().equals("SteamController") || bluetoothDevice.getName().startsWith("Steam Ctrl");
}
private void close() {
@@ -681,7 +688,7 @@ public class HIDDeviceManager {
private native void HIDDeviceRegisterCallback();
private native void HIDDeviceReleaseCallback();
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth);
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth, int reportID);
native void HIDDeviceOpenPending(int deviceID);
native void HIDDeviceOpenResult(int deviceID, boolean opened);
native void HIDDeviceDisconnected(int deviceID);
@@ -21,6 +21,7 @@ class HIDDeviceUSB implements HIDDevice {
protected InputThread mInputThread;
protected boolean mRunning;
protected boolean mFrozen;
protected boolean mClaimed;
public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) {
mManager = manager;
@@ -29,6 +30,7 @@ class HIDDeviceUSB implements HIDDevice {
mInterface = mDevice.getInterface(mInterfaceIndex).getId();
mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier());
mRunning = false;
mClaimed = false;
}
String getIdentifier() {
@@ -114,6 +116,7 @@ class HIDDeviceUSB implements HIDDevice {
close();
return false;
}
mClaimed = true;
// Find the endpoints
for (int j = 0; j < iface.getEndpointCount(); j++) {
@@ -132,9 +135,12 @@ class HIDDeviceUSB implements HIDDevice {
}
}
// Make sure the required endpoints were present
if (mInputEndpoint == null || mOutputEndpoint == null) {
// Make sure the required endpoints were present. The original Steam Controller and the wireless dongle for it do NOT
// actually have -- or require -- output endpoints, so we need to accept only an input one for them or else we'll fall
// back to the Android system gamepad functionality (and lose our paddles et al).
if (mInputEndpoint == null) {
Log.w(TAG, "Missing required endpoint on USB device " + getDeviceName());
mConnection.releaseInterface(iface);
close();
return false;
}
@@ -154,6 +160,11 @@ class HIDDeviceUSB implements HIDDevice {
return -1;
}
if (!mClaimed) {
Log.w(TAG, "writeReport() called but some other process currently owns the USB device");
return -1;
}
if (feature) {
int res = -1;
int offset = 0;
@@ -185,6 +196,11 @@ class HIDDeviceUSB implements HIDDevice {
}
return length;
} else {
if (mOutputEndpoint == null)
{
Log.e(TAG, "Tried to write an output report to an interface with no output endpoint!");
return -1;
}
int res = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
if (res != report.length) {
Log.w(TAG, "writeOutputReport() returned " + res + " on device " + getDeviceName());
@@ -205,6 +221,12 @@ class HIDDeviceUSB implements HIDDevice {
Log.w(TAG, "readReport() called with no device connection");
return false;
}
if (!mClaimed) {
if (feature) {
return false;
}
return true;
}
if (report_number == 0x0) {
/* Offset the return buffer by 1, so that the report ID
@@ -258,10 +280,13 @@ class HIDDeviceUSB implements HIDDevice {
mInputThread = null;
}
if (mConnection != null) {
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
mConnection.releaseInterface(iface);
if (mClaimed) {
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
mConnection.releaseInterface(iface);
}
mConnection.close();
mConnection = null;
mClaimed = false;
}
}
@@ -274,6 +299,22 @@ class HIDDeviceUSB implements HIDDevice {
@Override
public void setFrozen(boolean frozen) {
mFrozen = frozen;
/* If we have a valid device connection and the claim state doesn't match what we want, try to correct that. */
if (mConnection != null && mClaimed == mFrozen) {
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
if (frozen) {
mClaimed = !mConnection.releaseInterface(iface);
if (mClaimed) {
Log.e(TAG, "Tried to release claim on USB device, but failed!");
}
} else {
mClaimed = mConnection.claimInterface(iface, true);
if (!mClaimed) {
Log.e(TAG, "Tried to regain claim on USB device, but failed!");
}
}
}
}
protected class InputThread extends Thread {
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 3;
private static final int SDL_MINOR_VERSION = 4;
private static final int SDL_MICRO_VERSION = 8;
private static final int SDL_MICRO_VERSION = 10;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
@@ -530,7 +530,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(true);
}
}
if (!mHasMultiWindow) {
pauseNativeThread();
}
@@ -543,7 +544,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(false);
}
}
if (!mHasMultiWindow) {
resumeNativeThread();
}
@@ -616,6 +618,14 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
super.onWindowFocusChanged(hasFocus);
Log.v(TAG, "onWindowFocusChanged(): " + hasFocus);
// If we are gaining focus, we can always try to restore our USB devices. If we are losing focus,
// only try to relinquish them if we don't have background events allowed (for multi-window Android setups).
if (hasFocus || !SDLActivity.nativeGetHintBoolean("SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", false)) {
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(!hasFocus);
}
}
if (SDLActivity.mBrokenLibraries) {
return;
}
@@ -1481,11 +1491,11 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
// Note that we process events with specific key codes here
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLControllerManager.onNativePadDown(deviceId, keyCode)) {
if (SDLControllerManager.onNativePadDown(deviceId, keyCode, event.getScanCode())) {
return true;
}
} else if (event.getAction() == KeyEvent.ACTION_UP) {
if (SDLControllerManager.onNativePadUp(deviceId, keyCode)) {
if (SDLControllerManager.onNativePadUp(deviceId, keyCode, event.getScanCode())) {
return true;
}
}
@@ -1963,7 +1973,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
| Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
i.addFlags(flags);
@@ -2227,3 +2237,4 @@ class SDLClipboardHandler implements
SDLActivity.onNativeClipboardChanged();
}
}
@@ -10,6 +10,10 @@ import android.hardware.lights.Light;
import android.hardware.lights.LightsRequest;
import android.hardware.lights.LightsManager;
import android.hardware.lights.LightState;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.graphics.Color;
import android.os.Build;
import android.os.VibrationEffect;
@@ -30,16 +34,18 @@ public class SDLControllerManager
static native void nativeAddJoystick(int device_id, String name, String desc,
int vendor_id, int product_id,
int button_mask,
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led);
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led,
boolean has_accelerometer, boolean has_gyroscope);
static native void nativeRemoveJoystick(int device_id);
static native void nativeAddHaptic(int device_id, String name);
static native void nativeRemoveHaptic(int device_id);
static public native boolean onNativePadDown(int device_id, int keycode);
static public native boolean onNativePadUp(int device_id, int keycode);
static public native boolean onNativePadDown(int device_id, int keycode, int scancode);
static public native boolean onNativePadUp(int device_id, int keycode, int scancode);
static native void onNativeJoy(int device_id, int axis,
float value);
static native void onNativeHat(int device_id, int hat_id,
int x, int y);
static native void onNativeJoySensor(int device_id, int sensor_type, long sensor_timestamp, float x, float y, float z);
protected static SDLJoystickHandler mJoystickHandler;
protected static SDLHapticHandler mHapticHandler;
@@ -81,6 +87,13 @@ public class SDLControllerManager
mJoystickHandler.setLED(device_id, red, green, blue);
}
/**
* This method is called by SDL using JNI.
*/
static void joystickSetSensorsEnabled(int device_id, boolean enabled) {
mJoystickHandler.setSensorsEnabled(device_id, enabled);
}
/**
* This method is called by SDL using JNI.
*/
@@ -153,6 +166,10 @@ class SDLJoystickHandler {
ArrayList<InputDevice.MotionRange> hats;
ArrayList<Light> lights;
LightsManager.LightsSession lightsSession;
SensorManager sensorManager;
SDLJoySensorListener sensorListener;
Sensor accelerometerSensor;
Sensor gyroscopeSensor;
}
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
@Override
@@ -225,12 +242,13 @@ class SDLJoystickHandler {
joystick.desc = getJoystickDescriptor(joystickDevice);
joystick.axes = new ArrayList<InputDevice.MotionRange>();
joystick.hats = new ArrayList<InputDevice.MotionRange>();
java.util.Set<Integer> axisStrsSet = new java.util.HashSet<Integer>();
joystick.lights = new ArrayList<Light>();
List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
Collections.sort(ranges, new RangeComparator());
for (InputDevice.MotionRange range : ranges) {
if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
if (((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) && axisStrsSet.add(range.getAxis())) {
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
joystick.hats.add(range);
} else {
@@ -241,6 +259,8 @@ class SDLJoystickHandler {
boolean can_rumble = false;
boolean has_rgb_led = false;
boolean has_accelerometer = false;
boolean has_gyroscope = false;
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
VibratorManager vibratorManager = joystickDevice.getVibratorManager();
int[] vibrators = vibratorManager.getVibratorIds();
@@ -258,12 +278,26 @@ class SDLJoystickHandler {
joystick.lightsSession = lightsManager.openSession();
has_rgb_led = true;
}
SensorManager sensorManager = joystickDevice.getSensorManager();
if (sensorManager != null) {
joystick.sensorManager = sensorManager;
joystick.sensorListener = new SDLJoySensorListener(joystick.device_id);
joystick.accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (joystick.accelerometerSensor != null) {
has_accelerometer = true;
}
joystick.gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
if (joystick.gyroscopeSensor != null) {
has_gyroscope = true;
}
}
}
mJoysticks.add(joystick);
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
getVendorId(joystickDevice), getProductId(joystickDevice),
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led);
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led,
has_accelerometer, has_gyroscope);
}
}
}
@@ -508,6 +542,31 @@ class SDLJoystickHandler {
}
joystick.lightsSession.requestLights(lightsRequest.build());
}
void setSensorsEnabled(int device_id, boolean enabled) {
if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
return;
}
SDLJoystick joystick = getJoystick(device_id);
if (joystick == null || joystick.sensorManager == null) {
return;
}
if (enabled) {
if (joystick.accelerometerSensor != null) {
SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
}
if (joystick.gyroscopeSensor != null) {
SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor, SensorManager.SENSOR_DELAY_GAME);
}
} else {
if (joystick.accelerometerSensor != null) {
SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor);
}
if (joystick.gyroscopeSensor != null) {
SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor);
}
}
}
}
class SDLHapticHandler_API31 extends SDLHapticHandler {
@@ -933,3 +992,19 @@ class SDLGenericMotionListener_API29 extends SDLGenericMotionListener_API26 {
return penDevice.isExternal() ? SDL_PEN_DEVICE_TYPE_INDIRECT : SDL_PEN_DEVICE_TYPE_DIRECT;
}
}
class SDLJoySensorListener implements SensorEventListener {
int device_id;
public SDLJoySensorListener(int device_id) {
this.device_id = device_id;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
@Override
public void onSensorChanged(SensorEvent event) {
SDLControllerManager.onNativeJoySensor(device_id, event.sensor.getType(), event.timestamp, event.values[0], event.values[1], event.values[2]);
}
}
@@ -0,0 +1,32 @@
package org.libsdl.app;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
// This class coordinates synchronized access to sensor manager registration
//
// This prevents a java.util.ConcurrentModificationException exception on
// Android 16, specifically on the Samsung Tab S9 Ultra.
class SDLSensorManager
{
static private SDLSensorManager mManager = new SDLSensorManager();
public static void registerListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
mManager.RegisterListener(manager, listener, sensor, samplingPeriodUs);
}
public static void unregisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor) {
mManager.UnregisterListener(manager, listener, sensor);
}
private synchronized void RegisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
manager.registerListener(listener, sensor, samplingPeriodUs, null);
}
private synchronized void UnregisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor) {
manager.unregisterListener(listener, sensor);
}
}
@@ -47,6 +47,9 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// Is SurfaceView ready for rendering
protected boolean mIsSurfaceReady;
// Is on-screen keyboard visible
protected boolean mKeyboardVisible;
// Pinch events
private final ScaleGestureDetector scaleGestureDetector;
@@ -213,6 +216,18 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
WindowInsets.Type.displayCutout());
SDLActivity.onNativeInsetsChanged(combined.left, combined.right, combined.top, combined.bottom);
if (insets.isVisible(WindowInsets.Type.ime())) {
if (!mKeyboardVisible) {
mKeyboardVisible = true;
SDLActivity.onNativeScreenKeyboardShown();
}
} else {
if (mKeyboardVisible) {
mKeyboardVisible = false;
SDLActivity.onNativeScreenKeyboardHidden();
}
}
}
// Pass these to any child views in case they need them
@@ -318,11 +333,11 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
protected void enableSensor(int sensortype, boolean enabled) {
// TODO: This uses getDefaultSensor - what if we have >1 accels?
if (enabled) {
mSensorManager.registerListener(this,
SDLSensorManager.registerListener(mSensorManager, this,
mSensorManager.getDefaultSensor(sensortype),
SensorManager.SENSOR_DELAY_GAME, null);
SensorManager.SENSOR_DELAY_GAME);
} else {
mSensorManager.unregisterListener(this,
SDLSensorManager.unregisterListener(mSensorManager, this,
mSensorManager.getDefaultSensor(sensortype));
}
}
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>dev.twilitrealm.dusk</id>
<launchable type="desktop-id">dev.twilitrealm.dusk.desktop</launchable>
<name>Dusklight</name>
<summary>Native port of a classic adventure game</summary>
<developer id="dev.twilitrealm">
<name>Twilit Realm</name>
</developer>
<url type="homepage">https://twilitrealm.dev</url>
<url type="bugtracker">https://github.com/TwilitRealm/dusklight/issues</url>
<metadata_license>CC0-1.0</metadata_license>
<project_license>CC0-1.0</project_license>
<content_rating type="oars-1.0"/>
<supports>
<control>console</control>
<control>gamepad</control>
</supports>
<description>
<p>
Dusklight is a reverse-engineered reimplementation of a classic adventure game.
It aims to be as accurate as possible to the original while also providing new options, enhancements, and tools to customize your experience.
</p>
</description>
<provides>
<binary>dusklight</binary>
<id>dev.twilitrealm.dusk.desktop</id>
</provides>
<releases>
<release version="UNRELEASED" date="2026-12-31">
<description>
<p>Initial Flatpak release.</p>
</description>
</release>
</releases>
</component>
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -16,7 +16,7 @@ body {
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
z-index: 1;
z-index: 2;
pointer-events: none;
}
+339
View File
@@ -0,0 +1,339 @@
*, *:before, *:after {
box-sizing: border-box;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
font-family: "Fira Sans Condensed";
font-weight: bold;
color: rgba(248, 244, 232, 90%);
z-index: 1;
filter: opacity(0);
transition: filter 0.2s linear-in-out;
}
body[open] {
filter: opacity(1);
}
body:not([open]) {
pointer-events: none;
}
button {
display: flex;
align-items: center;
justify-content: center;
decorator: none;
padding: 0;
border: 1dp rgba(255, 255, 255, 22%);
background-color: rgba(22, 24, 28, 48%);
color: rgba(248, 244, 232, 90%);
text-align: center;
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 6dp 18dp rgba(0, 0, 0, 28%); */
transform-origin: center;
transition: background-color border-color filter transform 0.08s linear-in-out,
opacity 0.2s linear-in-out;
}
button.pressed,
button.active {
background-color: rgba(63, 78, 90, 68%);
border-color: rgba(255, 255, 255, 48%);
filter: brightness(1.18);
}
button:hidden {
opacity: 0;
pointer-events: none;
}
button span {
display: block;
line-height: 1;
}
button icon {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
button icon glyph {
display: block;
font-family: "Material Symbols Rounded";
font-weight: normal;
font-size: 24dp;
line-height: 1;
}
.midna-icon,
.item-icon,
.item-count,
.oil-meter {
display: none;
}
.midna-icon.visible,
.item-icon.visible,
.item-count.visible,
.oil-meter.visible {
display: block;
}
.control {
position: absolute;
}
.trigger-l.active {
background-color: rgba(57, 116, 133, 74%);
border-color: rgba(128, 222, 234, 72%);
}
.trigger,
.skip {
border-radius: 23dp;
}
.trigger {
font-size: 22dp;
}
.button-z {
background-color: rgba(118, 79, 158, 58%);
border-color: rgba(203, 170, 255, 36%);
}
.midna-icon {
position: absolute;
left: 9dp;
top: -1dp;
height: 48dp;
}
.button-z.has-icon span,
.face.has-item span {
position: absolute;
font-size: 13dp;
line-height: 1;
}
.button-z.has-icon span {
right: 9dp;
bottom: 7dp;
}
.button-z.pressed {
background-color: rgba(139, 91, 187, 82%);
border-color: rgba(220, 194, 255, 70%);
}
action-bar {
position: absolute;
display: flex;
align-items: center;
border: 1dp rgba(255, 255, 255, 22%);
border-radius: 23dp;
background-color: rgba(22, 24, 28, 48%);
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 -6dp 18dp rgba(0, 0, 0, 28%); */
overflow: hidden;
opacity: 1;
transform-origin: center;
transition: opacity 0.2s linear-in-out;
}
action-bar:hidden,
action-bar:hidden button,
action-bar:hidden separator {
opacity: 0;
pointer-events: none;
}
.utility {
position: relative;
flex: 1 1 auto;
width: 56dp;
height: 44dp;
margin: 0;
border-width: 0dp;
border-radius: 0;
background-color: transparent;
box-shadow: none;
}
.utility,
.skip {
opacity: 0.55;
}
.utility.pressed {
background-color: rgba(63, 78, 90, 68%);
}
.utility.pressed,
.skip.pressed {
opacity: 1;
}
.skip {
z-index: 1;
border-color: rgba(255, 255, 255, 36%);
}
separator {
display: block;
flex: 0 0 1dp;
width: 1dp;
height: 24dp;
background-color: rgba(255, 255, 255, 18%);
opacity: 1;
transition: opacity 0.2s linear-in-out;
}
.face {
position: absolute;
border-radius: 29dp;
font-size: 24dp;
overflow: visible;
}
.item-icon {
width: auto;
height: auto;
max-width: 76%;
max-height: 76%;
}
.item-count {
position: absolute;
left: 6dp;
bottom: 5dp;
min-width: 17dp;
height: 15dp;
padding: 1dp 3dp;
border-radius: 7dp;
background-color: rgba(0, 0, 0, 52%);
color: rgba(255, 255, 255, 92%);
font-size: 12dp;
line-height: 13dp;
text-align: center;
}
.oil-meter {
position: absolute;
left: 12dp;
bottom: -5dp;
width: 34dp;
height: 8dp;
padding: 2dp;
border: 1dp rgba(42, 32, 18, 82%);
border-radius: 4dp;
background-color: rgba(18, 14, 10, 70%);
/* box-shadow: 0 2dp 6dp rgba(0, 0, 0, 35%); */
}
oil-fill {
display: block;
width: 0%;
height: 100%;
border-radius: 2dp;
background-color: rgb(255, 232, 74);
}
.face.has-item span {
right: 6dp;
bottom: 6dp;
color: rgba(255, 255, 255, 88%);
}
.face.a {
border-radius: 37dp;
font-size: 31dp;
background-color: rgba(34, 112, 123, 62%);
}
.face.b {
background-color: rgba(161, 61, 66, 58%);
}
.face.x {
background-color: rgba(83, 115, 151, 56%);
}
.face.y {
background-color: rgba(113, 91, 150, 54%);
}
button.control.docked-top,
action-bar.docked-top {
border-top-width: 0dp;
border-top-left-radius: 0dp;
border-top-right-radius: 0dp;
}
button.control.docked-bottom,
action-bar.docked-bottom {
border-bottom-width: 0dp;
border-bottom-left-radius: 0dp;
border-bottom-right-radius: 0dp;
}
button.control.docked-left,
action-bar.docked-left {
border-left-width: 0dp;
border-top-left-radius: 0dp;
border-bottom-left-radius: 0dp;
}
button.control.docked-right,
action-bar.docked-right {
border-right-width: 0dp;
border-top-right-radius: 0dp;
border-bottom-right-radius: 0dp;
}
touch-stick {
display: block;
position: absolute;
width: 124dp;
height: 124dp;
border-radius: 62dp;
background-color: rgba(18, 20, 24, 35%);
border: 1dp rgba(255, 255, 255, 20%);
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 8dp 24dp rgba(0, 0, 0, 24%); */
opacity: 0;
pointer-events: none;
transition: opacity 0.18s linear-in-out;
}
touch-stick.active {
opacity: 1;
}
stick-ring {
position: absolute;
left: 18dp;
top: 18dp;
width: 88dp;
height: 88dp;
border-radius: 44dp;
border: 1dp rgba(255, 255, 255, 18%);
}
stick-knob {
position: absolute;
width: 48dp;
height: 48dp;
border-radius: 24dp;
background-color: rgba(238, 236, 226, 55%);
border: 1dp rgba(255, 255, 255, 45%);
}
+138
View File
@@ -0,0 +1,138 @@
body.touch-editor {
background-color: rgba(4, 6, 8, 34%);
z-index: 8;
}
body.touch-editor .control,
body.touch-editor action-bar {
opacity: 0.88;
cursor: move;
pointer-events: auto;
}
body.touch-editor .control:hover,
body.touch-editor action-bar:hover,
body.touch-editor .control.editor-selected,
body.touch-editor action-bar.editor-selected {
border-color: rgba(255, 232, 128, 80%);
filter: brightness(1.15);
}
body.touch-editor action-bar button,
body.touch-editor action-bar separator {
pointer-events: none;
}
selection-frame {
display: none;
position: absolute;
z-index: 20;
border: 2dp rgba(255, 232, 128, 88%);
background-color: rgba(255, 232, 128, 7%);
pointer-events: none;
}
selection-frame.visible {
display: block;
}
resize-handle {
display: block;
position: absolute;
width: 22dp;
height: 22dp;
border: 2dp rgba(255, 244, 190, 96%);
border-radius: 11dp;
background-color: rgba(34, 37, 42, 86%);
pointer-events: auto;
}
resize-handle.left {
left: -12dp;
}
resize-handle.right {
right: -12dp;
}
resize-handle.top {
top: -12dp;
}
resize-handle.bottom {
bottom: -12dp;
}
resize-handle.horizontal {
top: 50%;
margin-top: -11dp;
}
resize-handle.vertical {
left: 50%;
margin-left: -11dp;
}
resize-handle.corner.left {
left: -12dp;
}
resize-handle.corner.right {
right: -12dp;
}
resize-handle.corner.top {
top: -12dp;
}
resize-handle.corner.bottom {
bottom: -12dp;
}
editor-toolbar {
display: flex;
position: absolute;
left: 24dp;
right: 24dp;
top: 50%;
z-index: 30;
height: 48dp;
margin-top: -24dp;
gap: 8dp;
justify-content: center;
pointer-events: auto;
}
editor-toolbar button.editor-command {
flex: 0 1 150dp;
min-width: 96dp;
height: 48dp;
padding: 0 14dp;
border-radius: 8dp;
border: 1dp rgba(255, 255, 255, 26%);
background-color: rgba(17, 19, 24, 88%);
color: rgba(255, 250, 232, 94%);
font-family: "Fira Sans";
font-size: 18dp;
line-height: 48dp;
opacity: 1;
cursor: pointer;
}
editor-toolbar button.editor-command span {
display: block;
width: 100%;
line-height: 48dp;
text-align: center;
}
editor-toolbar button.editor-command.primary {
border-color: rgba(255, 232, 128, 70%);
background-color: rgba(96, 82, 38, 90%);
}
editor-toolbar button.editor-command:hover,
editor-toolbar button.editor-command:focus-visible {
border-color: rgba(255, 244, 190, 92%);
background-color: rgba(78, 85, 96, 92%);
}
+46 -18
View File
@@ -12734,7 +12734,19 @@ void daAlink_c::setMagicArmorBrk(int i_status) {
BOOL daAlink_c::checkMagicArmorHeavy() const {
#if TARGET_PC
return checkMagicArmorWearAbility() && (dComIfGs_getRupee() == 0 && !dusk::getSettings().game.freeMagicArmor);
if(!checkMagicArmorWearAbility()) {
return false;
}
switch(dusk::getSettings().game.armorRupeeDrain) {
case dusk::MagicArmorMode::NORMAL:
return dComIfGs_getRupee() == 0;
case dusk::MagicArmorMode::ON_DAMAGE:
case dusk::MagicArmorMode::DOUBLE_DEFENSE:
case dusk::MagicArmorMode::INVINCIBLE:
case dusk::MagicArmorMode::COSMETIC:
return false;
}
#else
return checkMagicArmorWearAbility() && dComIfGs_getRupee() == 0;
#endif
@@ -14796,6 +14808,8 @@ void daAlink_c::deleteEquipItem(BOOL i_isPlaySound, BOOL i_isDeleteKantera) {
#if TARGET_PC
mIBChainInterpPrevValid = false;
mIBChainInterpCurrValid = false;
mHsChainInterpPrevValid = false;
mHsChainInterpCurrValid = false;
#endif
field_0x0774 = NULL;
field_0x0778 = NULL;
@@ -18707,7 +18721,7 @@ int daAlink_c::execute() {
#if TARGET_PC
// This handles rupee drain and transitions between rupees/no rupees
// We can skip all of that if the magic armor doesn't use rupees
if (!dusk::getSettings().game.freeMagicArmor && checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
if (dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::NORMAL && checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
#else
if (checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
#endif
@@ -19768,23 +19782,37 @@ int daAlink_c::draw() {
dComIfGd_getOpaListDark()->entryImm(mpHookChain, 0);
#if TARGET_PC
if (dusk::frame_interp::is_enabled() &&
mEquipItem == dItemNo_IRONBALL_e &&
mIronBallChainPos != NULL && mIronBallChainAngle != NULL)
{
if (mIBChainInterpCurrValid) {
memcpy(mIBChainInterpPrevPos, mIBChainInterpCurrPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpPrevAngle, mIBChainInterpCurrAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpPrevHandRoot = mIBChainInterpCurrHandRoot;
mIBChainInterpPrevValid = true;
if (dusk::frame_interp::is_enabled()) {
if (mEquipItem == dItemNo_IRONBALL_e &&
mIronBallChainPos != NULL && mIronBallChainAngle != NULL)
{
if (mIBChainInterpCurrValid) {
memcpy(mIBChainInterpPrevPos, mIBChainInterpCurrPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpPrevAngle, mIBChainInterpCurrAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpPrevHandRoot = mIBChainInterpCurrHandRoot;
mIBChainInterpPrevValid = true;
}
memcpy(mIBChainInterpCurrPos, mIronBallChainPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpCurrAngle, mIronBallChainAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpCurrHandRoot = mHookshotTopPos;
mIBChainInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&ironBallChainInterpCallback, this);
} else {
if (mHsChainInterpCurrValid) {
mHsChainInterpPrevTop = mHsChainInterpCurrTop;
mHsChainInterpPrevRoot = mHsChainInterpCurrRoot;
mHsChainInterpPrevSubRoot = mHsChainInterpCurrSubRoot;
mHsChainInterpPrevSubTop = mHsChainInterpCurrSubTop;
mHsChainInterpPrevValid = true;
}
mHsChainInterpCurrTop = mHookshotTopPos;
mHsChainInterpCurrRoot = mHeldItemRootPos;
mHsChainInterpCurrSubRoot = field_0x3810;
mHsChainInterpCurrSubTop = mIronBallBgChkPos;
mHsChainInterpCurrValid = true;
}
memcpy(mIBChainInterpCurrPos, mIronBallChainPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpCurrAngle, mIronBallChainAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpCurrHandRoot = mHookshotTopPos;
mIBChainInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&ironBallChainInterpCallback, this);
}
#endif
}
+25 -1
View File
@@ -192,7 +192,7 @@ int daAlink_c::setDamagePoint(int i_dmgAmount, BOOL i_checkZoraMag, BOOL i_setDm
if (checkMagicArmorNoDamage()) {
#if TARGET_PC
if(dusk::getSettings().game.freeMagicArmor) {
if(dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::INVINCIBLE) {
i_dmgAmount = 0;
}
#endif
@@ -202,6 +202,11 @@ int daAlink_c::setDamagePoint(int i_dmgAmount, BOOL i_checkZoraMag, BOOL i_setDm
if (!mpHIO->mDamage.m.mInvincible && g_debugHpMode == 0)
#endif
{
#if TARGET_PC
if(checkMagicArmorWearAbility() && dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::DOUBLE_DEFENSE) {
i_dmgAmount /= 2;
}
#endif
dComIfGp_setItemLifeCount(-i_dmgAmount, 0);
}
@@ -281,7 +286,26 @@ BOOL daAlink_c::checkIcePolygonDamage(cBgS_PolyInfo* i_poly) {
}
BOOL daAlink_c::checkMagicArmorNoDamage() {
#ifdef TARGET_PC
if (!checkMagicArmorWearAbility()) {
return false;
}
switch(dusk::getSettings().game.armorRupeeDrain) {
case dusk::MagicArmorMode::NORMAL:
return !checkMagicArmorHeavy();
case dusk::MagicArmorMode::ON_DAMAGE:
return dComIfGs_getRupee() != 0;
case dusk::MagicArmorMode::DOUBLE_DEFENSE:
return false;
case dusk::MagicArmorMode::INVINCIBLE:
return true;
case dusk::MagicArmorMode::COSMETIC:
return false;
}
#else
return checkMagicArmorWearAbility() && !checkMagicArmorHeavy();
#endif
}
int daAlink_c::checkPolyDamage() {
+14 -4
View File
@@ -72,7 +72,7 @@ void daAlink_c::handleQuickTransform() {
}
// Check to see if Link has the ability to transform.
if (!dComIfGs_isEventBit(dSv_event_flag_c::M_077) && !dusk::getSettings().game.transformWithoutShadowCrystal) {
if (!dComIfGs_isEventBit(dSv_event_flag_c::M_077)) {
return;
}
@@ -102,7 +102,7 @@ void daAlink_c::handleQuickTransform() {
}
// Ensure that the Z Button is not dimmed
if (meterDrawPtr->getButtonZAlpha() != 1.f && !dusk::getSettings().game.transformWithoutShadowCrystal) {
if (meterDrawPtr->getButtonZAlpha() != 1.f) {
Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
return;
}
@@ -122,7 +122,7 @@ void daAlink_c::handleQuickTransform() {
bool canTransform = false;
if (mLinkAcch.ChkGroundHit() && !checkModeFlg(MODE_PLAYER_FLY) && !checkMagneBootsOn()) {
if (checkMidnaRide() || dusk::getSettings().game.transformWithoutShadowCrystal) {
if (checkMidnaRide()) {
if ((checkWolf() &&
(checkModeFlg(MODE_UNK_1000) || dComIfGp_checkPlayerStatus0(0, 0x10))) ||
(!checkWolf() &&
@@ -144,7 +144,7 @@ void daAlink_c::handleQuickTransform() {
procCoMetamorphoseInit();
}
bool daAlink_c::checkGyroAimContext() {
bool daAlink_c::checkAimContext() {
switch (mProcID) {
case PROC_SUBJECTIVITY:
case PROC_SWIM_SUBJECTIVITY:
@@ -175,3 +175,13 @@ bool daAlink_c::checkGyroAimContext() {
return false;
}
}
bool daAlink_c::checkTouchAimCaptureContext() {
switch (mProcID) {
case PROC_HOOKSHOT_ROOF_WAIT:
case PROC_HOOKSHOT_WALL_WAIT:
return false;
default:
return checkAimContext();
}
}
+16 -3
View File
@@ -2028,11 +2028,10 @@ void daAlink_blur_c::traceBlur(cXyz const* param_0, cXyz const* param_1, s16 par
}
void daAlink_blur_c::draw() {
ZoneScoped;
j3dSys.reinitGX();
#ifdef TARGET_PC
TGXTexObj texObj;
#else
#if !TARGET_PC
static TGXTexObj texObj;
#endif
static GXColor nColor0 = {0xFF, 0xFF, 0xFF, 0x14};
@@ -2040,11 +2039,25 @@ void daAlink_blur_c::draw() {
GXSetNumIndStages(0);
nColor0.a = field_0x20;
#if TARGET_PC
if (mpCachedBlurTex != m_blurTex) {
mBlurTexObj.reset();
GXInitTexObj(&mBlurTexObj,
reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(m_blurTex) + m_blurTex->imageOffset),
16, 4, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(
&mBlurTexObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
mpCachedBlurTex = m_blurTex;
}
GXLoadTexObj(&mBlurTexObj, GX_TEXMAP0);
#else
GXInitTexObj(&texObj, (void*)((uintptr_t)m_blurTex + m_blurTex->imageOffset), 16, 4, GX_TF_I4,
GX_CLAMP, GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(&texObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE,
GX_ANISO_1);
GXLoadTexObj(&texObj, GX_TEXMAP0);
#endif
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBA4, 8);
GXClearVtxDesc();
+23
View File
@@ -136,8 +136,26 @@ void daAlink_c::hsChainShape_c::draw() {
}
}
} else {
#if TARGET_PC
cXyz hsInterpTop, hsInterpRoot, hsInterpSubRoot, hsInterpSubTop;
if (dusk::frame_interp::is_enabled() && alink->mHsChainInterpPrevValid && alink->mHsChainInterpCurrValid) {
const f32 alpha = dusk::frame_interp::get_interpolation_step();
hsInterpTop = alink->mHsChainInterpPrevTop + (alink->mHsChainInterpCurrTop - alink->mHsChainInterpPrevTop) * alpha;
hsInterpRoot = alink->mHsChainInterpPrevRoot + (alink->mHsChainInterpCurrRoot - alink->mHsChainInterpPrevRoot) * alpha;
hsInterpSubRoot = alink->mHsChainInterpPrevSubRoot + (alink->mHsChainInterpCurrSubRoot - alink->mHsChainInterpPrevSubRoot) * alpha;
hsInterpSubTop = alink->mHsChainInterpPrevSubTop + (alink->mHsChainInterpCurrSubTop - alink->mHsChainInterpPrevSubTop) * alpha;
} else {
hsInterpTop = alink->getHsChainTopPos();
hsInterpRoot = alink->getHsChainRootPos();
hsInterpSubRoot = alink->getHsSubChainRootPos();
hsInterpSubTop = alink->getHsSubChainTopPos();
}
const cXyz& chainRootPos = hsInterpRoot;
const cXyz& chainTopPos = hsInterpTop;
#else
const cXyz& chainRootPos = alink->getHsChainRootPos();
const cXyz& chainTopPos = alink->getHsChainTopPos();
#endif
cXyz maxDistance = chainRootPos - chainTopPos;
f32 maxDistanceF = maxDistance.abs();
@@ -200,8 +218,13 @@ void daAlink_c::hsChainShape_c::draw() {
}
}
#if TARGET_PC
const cXyz& subChainRootPos = hsInterpSubRoot;
const cXyz& subChainTopPos = hsInterpSubTop;
#else
const cXyz& subChainRootPos = alink->getHsSubChainRootPos();
const cXyz& subChainTopPos = alink->getHsSubChainTopPos();
#endif
maxDistance = subChainRootPos - subChainTopPos;
maxDistanceF = maxDistance.abs();
+58 -11
View File
@@ -11,8 +11,10 @@
#include "d/actor/d_a_tag_mhint.h"
#if TARGET_PC
#include "dusk/gyro.h"
#include "dusk/action_bindings.h"
#include "dusk/gyro.h"
#include "dusk/mouse.h"
#include "dusk/touch_camera.h"
#endif
bool daAlink_c::checkNoSubjectModeCamera() {
@@ -120,18 +122,28 @@ BOOL daAlink_c::setBodyAngleToCamera() {
var_f31 /= dComIfGp_getCameraZoomScale(field_0x317c);
}
shape_angle.y = shape_angle.y + (var_f31 * cM_ssin(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonXAxis ? -1.0f : 1.0f)));
sp8 = mBodyAngle.x + (var_f31 * cM_scos(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonYAxis ? -1.0f : 1.0f)));
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
#if TARGET_PC
if (dusk::getSettings().game.enableMouseAim && checkAimContext()) {
sp8 = mBodyAngle.x;
} else
#endif
{
shape_angle.y = shape_angle.y + (var_f31 * cM_ssin(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonXAxis ? -1.0f : 1.0f)));
sp8 = mBodyAngle.x + (var_f31 * cM_scos(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonYAxis ? -1.0f : 1.0f)));
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
}
} else {
sp8 = mBodyAngle.x;
}
#if TARGET_PC
if (dusk::getSettings().game.enableGyroAim && checkGyroAimContext()) {
if ((dusk::getSettings().game.enableGyroAim ||
dusk::getSettings().game.enableMouseAim) &&
checkAimContext())
{
f32 gyro_scale = 1.0f;
if (checkWolfEyeUp()) {
gyro_scale *= 0.6f;
@@ -141,17 +153,52 @@ BOOL daAlink_c::setBodyAngleToCamera() {
gyro_scale /= dComIfGp_getCameraZoomScale(field_0x317c);
}
f32 gy_yaw = 0.f;
f32 gy_pitch = 0.f;
dusk::gyro::getAimDeltas(gy_yaw, gy_pitch);
f32 final_yaw = 0.f;
f32 final_pitch = 0.f;
if (dusk::getSettings().game.enableMouseAim) {
dusk::mouse::getAimDeltas(final_yaw, final_pitch);
}
if (dusk::getSettings().game.enableGyroAim) {
f32 gyro_yaw = 0.f;
f32 gyro_pitch = 0.f;
dusk::gyro::getAimDeltas(gyro_yaw, gyro_pitch);
final_yaw += gyro_yaw;
final_pitch += gyro_pitch;
}
shape_angle.y = shape_angle.y + cM_rad2s(gy_yaw * gyro_scale);
sp8 = sp8 + cM_rad2s(gy_pitch * gyro_scale);
shape_angle.y = shape_angle.y + cM_rad2s(final_yaw * gyro_scale);
sp8 = sp8 + cM_rad2s(final_pitch * gyro_scale);
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
}
if (dusk::getSettings().game.enableTouchControls && checkAimContext()) {
f32 touchYawDp = 0.0f;
f32 touchPitchDp = 0.0f;
if (dusk::touch_camera::consume_delta(touchYawDp, touchPitchDp)) {
f32 scale = 1.0f;
if (checkWolfEyeUp()) {
scale *= 0.6f;
}
if (dComIfGp_checkPlayerStatus0(0, 0x200000)) {
scale /= dComIfGp_getCameraZoomScale(field_0x317c);
}
const f32 yawDeg = -touchYawDp * dusk::touch_camera::YAW_DEGREES_PER_DP * scale *
dusk::getSettings().game.touchCameraXSensitivity;
const f32 pitchDeg = touchPitchDp * dusk::touch_camera::PITCH_DEGREES_PER_DP *
scale * dusk::getSettings().game.touchCameraYSensitivity;
shape_angle.y = shape_angle.y + cM_deg2s(yawDeg);
sp8 = sp8 + cM_deg2s(pitchDeg);
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
}
}
#endif
if (checkNotItemSinkLimit() && sp8 > 0) {
-11
View File
@@ -85,17 +85,6 @@ int daAlink_c::loadModelDVD() {
}
cPhs_Reset(&mPhaseReq);
mpArcHeap->freeAll();
#if TARGET_PC
field_0x06d0 = NULL;
field_0x06d4 = NULL;
field_0x06d8 = NULL;
field_0x06dc = NULL;
field_0x06e0 = NULL;
field_0x06e4 = NULL;
field_0x06e8 = NULL;
field_0x06ec = NULL;
field_0x06f0 = NULL;
#endif
if (mProcID == PROC_METAMORPHOSE || mProcID == PROC_METAMORPHOSE_ONLY) {
setArcName(!checkWolf());
+2 -2
View File
@@ -348,7 +348,7 @@ void daAlink_c::changeLink(int param_0) {
initModel(static_cast<J3DModelData*>(dComIfG_getObjectRes(l_mArcName, "al_hands.bmd")), 0);
#if TARGET_PC
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.freeMagicArmor)
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.armorRupeeDrain.getValue() != dusk::MagicArmorMode::NORMAL)
#else
if (dComIfGs_getRupee() != 0)
#endif
@@ -458,7 +458,7 @@ void daAlink_c::changeLink(int param_0) {
field_0x06f0 = field_0x064C->getMaterialNodePointer(2)->getShape();
#if TARGET_PC
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.freeMagicArmor) {
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.armorRupeeDrain.getValue() != dusk::MagicArmorMode::NORMAL) {
#else
if (dComIfGs_getRupee() != 0) {
#endif
+9
View File
@@ -5472,6 +5472,15 @@ int daB_ZANT_c::create() {
fopAcM_ct(this, daB_ZANT_c);
OS_REPORT("B_ZANT PARAM %x\n", fopAcM_GetParam(this));
#if TARGET_PC
// Due to our loads being so much faster, Zant can initialize *before* the player
// This breaks respawning in the final phase of the fight when it tries
// to load the player's position
if (daPy_getPlayerActorClass() == NULL) {
return cPhs_INIT_e;
}
#endif
mSwbit = fopAcM_GetParam(this);
if (mSwbit != 0xFF) {
if (dComIfGs_isSwitch(mSwbit, fopAcM_GetRoomNo(this))) {
-12
View File
@@ -144,11 +144,7 @@ bool daBgObj_c::spec_data_c::Set(void* i_ptr) {
default:
// Invalid data block type
OS_REPORT_ERROR("データブロックタイプが不正です<%d>\n", block_type);
#if DUSK_TPHD
return 0; // HD-port: skip actor instead of asserting.
#else
JUT_ASSERT(527, FALSE);
#endif
}
if (block_type == 0) {
@@ -189,11 +185,7 @@ bool daBgObj_c::spec_data_c::Set(void* i_ptr) {
default:
// Invalid data block type
OS_REPORT_ERROR("データブロックタイプが不正です<%d>\n", block_type);
#if DUSK_TPHD
return 0;
#else
JUT_ASSERT(570, FALSE);
#endif
}
if (block_type == 0) {
@@ -234,12 +226,8 @@ bool daBgObj_c::spec_data_c::Set(void* i_ptr) {
default:
// "Data Block type invalid<%d>\n"
OSReport_Error("データブロックタイプが不正です<%d>\n", block_type);
#if DUSK_TPHD
return 0;
#else
JUT_ASSERT(619, FALSE);
break;
#endif
}
if (block_type == 0) {
+8
View File
@@ -923,6 +923,14 @@ static void damage_check(e_sm2_class* i_this) {
sm_hit_actor->mode = 10;
u8 new_color_type = new_col_d[(sm_hit_actor->type * 7) + i_this->type];
#if TARGET_PC
if (dusk::getSettings().game.restoreWiiGlitches &&
((sm_hit_actor->type == TYPE_BLUE && i_this->type == TYPE_YELLOW) ||
(sm_hit_actor->type == TYPE_YELLOW && i_this->type == TYPE_BLUE)))
{
new_color_type = TYPE_GREEN;
}
#endif
i_this->type = new_color_type;
sm_hit_actor->type = new_color_type;
-14
View File
@@ -10,7 +10,6 @@
#include "d/actor/d_a_player.h"
#include "d/d_com_inf_game.h"
#include <cstring>
#include <dusk/ui/settings.hpp>
static int daKytag04_Draw(kytag04_class* i_this) {
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
@@ -261,25 +260,12 @@ static int daKytag04_Create(fopAc_ac_c* i_this) {
a_this->mNeedDropNum = i_this->current.angle.z & 0xFF;
#if TARGET_PC
if (dusk::tphd_active()) {
a_this->mNeedDropNum = 12;
}
#endif
int phase_state = dComIfG_resLoad(&a_this->mPhase, "Kytag04");
if (phase_state == cPhs_COMPLEATE_e) {
a_this->field_0x5b4 = (fopAcM_GetParam(i_this) >> 8) & 7;
a_this->mStageNo = (i_this->current.angle.z >> 8) & 0xFF;
a_this->mExitID = fopAcM_GetParam(i_this) & 0xFF;
a_this->mNeedDropNum = i_this->current.angle.z & 0xFF;
#if TARGET_PC
if (dusk::tphd_active()) {
a_this->mNeedDropNum = 12;
}
#endif
a_this->field_0x5b5 = fopAcM_GetParam(i_this) >> 0x10;
a_this->field_0x5b6 = fopAcM_GetParam(i_this) >> 0x18;
+60 -231
View File
@@ -16,12 +16,30 @@
using GameVersion = dusk::version::GameVersion;
static u8* l_Egnd_mantTEX_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x1C00}, {GameVersion::GcnPal, 0x1C00}}, 0x4000), true); return buf; }
// keep the original version of the cape texture const so we don't need to reload the file
static u8 const * l_Egnd_mantTEX_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x1C00}, {GameVersion::GcnPal, 0x1C00}}, 0x4000), true); return buf; }
static u8* l_Egnd_mantTEX_U_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x5C00}, {GameVersion::GcnPal, 0x5C00}}, 0x4000), true); return buf; }
static u8* l_Egnd_mantPAL_get() { alignas(32) static u8 buf[0x60]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x9C00}, {GameVersion::GcnPal, 0x9C00}}, 0x60), true); return buf; }
#define l_Egnd_mantTEX (l_Egnd_mantTEX_get())
#define l_Egnd_mantTEX_U (l_Egnd_mantTEX_U_get())
#define l_Egnd_mantPAL (l_Egnd_mantPAL_get())
// make a copy of the cape texture that can be overwritten with the tears
static u8 l_Egnd_mantTEX_copy[0x4000];
// keep our cached texture objects out here so that we can update them from multiple places
static bool textureObjsInitialized = false;
static TGXTlutObj tlutObj;
static TGXTexObj mainTexObj;
static TGXTexObj undersideTexObj;
// l_pos is unused
//static f32* l_pos_get() { alignas(32) static f32 buf[507]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0xA44C}, {GameVersion::GcnPal, 0xA44C}}, sizeof(buf)), true); return buf; }
static f32* l_normal_get() { alignas(32) static f32 buf[3]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x9C60}, {GameVersion::GcnPal, 0x9C60}}, sizeof(buf)), true); return buf; }
static f32* l_texCoord_get() { alignas(32) static f32 buf[338]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0xA458}, {GameVersion::GcnPal, 0xA458}}, sizeof(buf)), true); return buf; }
//#define l_pos (l_pos_get())
#define l_normal (l_normal_get())
#define l_texCoord (l_texCoord_get())
#else
#include "assets/l_Egnd_mantTEX.h"
@@ -31,228 +49,6 @@ static u8* l_Egnd_mantPAL_get() { alignas(32) static u8 buf[0x60]; static bo
#endif
#include "d/d_s_play.h"
static u32 l_pos[507] = {
0x42480000, 0x3F5CFC93, 0xC365BD9C, 0x4226AAAA,
0x3F5CFC93, 0xC365BD9C, 0x42055556, 0x3F5CFC93,
0xC365BD9C, 0x41C80000, 0x3F5CFC93, 0xC365BD9C,
0x41855556, 0x3F5CFC93, 0xC365BD9C, 0x41055556,
0x3F5CFC93, 0xC365BD9C, 0x358637BD, 0x3F5CFC93,
0xC365BD9C, 0xC1055554, 0x3F5CFC93, 0xC365BD9C,
0xC1855554, 0x3F5CFC93, 0xC365BD9C, 0xC1C7FFFF,
0x3F5CFC93, 0xC365BD9C, 0xC2055554, 0x3F5CFC93,
0xC365BD9C, 0xC226AAAA, 0x3F5CFC93, 0xC365BD9C,
0xC2480000, 0x3F5CFC93, 0xC365BD9C, 0x42480000,
0x3F5CFC93, 0xC35292F0, 0x4226AAAA, 0x3F5CFC93,
0xC35292F0, 0x42055556, 0x3F5CFC93, 0xC35292F0,
0x41C80000, 0x3F5CFC93, 0xC35292F0, 0x41855556,
0x3F5CFC93, 0xC35292F0, 0x41055556, 0x3F5CFC93,
0xC35292F0, 0x358637BD, 0x3F5CFC93, 0xC35292F0,
0xC1055554, 0x3F5CFC93, 0xC35292F0, 0xC1855554,
0x3F5CFC93, 0xC35292F0, 0xC1C7FFFF, 0x3F5CFC93,
0xC35292F0, 0xC2055554, 0x3F5CFC93, 0xC35292F0,
0xC226AAAA, 0x3F5CFC93, 0xC35292F0, 0xC2480000,
0x3F5CFC93, 0xC35292F0, 0x42480000, 0x3F5CFC93,
0xC33F6846, 0x4226AAAA, 0x3F5CFC93, 0xC33F6846,
0x42055556, 0x3F5CFC93, 0xC33F6846, 0x41C80000,
0x3F5CFC93, 0xC33F6846, 0x41855556, 0x3F5CFC93,
0xC33F6846, 0x41055556, 0x3F5CFC93, 0xC33F6846,
0x358637BD, 0x3F5CFC93, 0xC33F6846, 0xC1055554,
0x3F5CFC93, 0xC33F6846, 0xC1855554, 0x3F5CFC93,
0xC33F6846, 0xC1C7FFFF, 0x3F5CFC93, 0xC33F6846,
0xC2055554, 0x3F5CFC93, 0xC33F6846, 0xC226AAAA,
0x3F5CFC93, 0xC33F6846, 0xC2480000, 0x3F5CFC93,
0xC33F6846, 0x42480000, 0x3F5CFC93, 0xC32C3D9C,
0x4226AAAA, 0x3F5CFC93, 0xC32C3D9C, 0x42055556,
0x3F5CFC93, 0xC32C3D9C, 0x41C80000, 0x3F5CFC93,
0xC32C3D9C, 0x41855556, 0x3F5CFC93, 0xC32C3D9C,
0x41055556, 0x3F5CFC93, 0xC32C3D9C, 0x358637BD,
0x3F5CFC93, 0xC32C3D9C, 0xC1055554, 0x3F5CFC93,
0xC32C3D9C, 0xC1855554, 0x3F5CFC93, 0xC32C3D9C,
0xC1C7FFFF, 0x3F5CFC93, 0xC32C3D9C, 0xC2055554,
0x3F5CFC93, 0xC32C3D9C, 0xC226AAAA, 0x3F5CFC93,
0xC32C3D9C, 0xC2480000, 0x3F5CFC93, 0xC32C3D9C,
0x42480000, 0x3F5CFC93, 0xC31912F1, 0x4226AAAA,
0x3F5CFC93, 0xC31912F1, 0x42055556, 0x3F5CFC93,
0xC31912F1, 0x41C80000, 0x3F5CFC93, 0xC31912F1,
0x41855556, 0x3F5CFC93, 0xC31912F1, 0x41055556,
0x3F5CFC93, 0xC31912F1, 0x358637BD, 0x3F5CFC93,
0xC31912F1, 0xC1055554, 0x3F5CFC93, 0xC31912F1,
0xC1855554, 0x3F5CFC93, 0xC31912F1, 0xC1C7FFFF,
0x3F5CFC93, 0xC31912F1, 0xC2055554, 0x3F5CFC93,
0xC31912F1, 0xC226AAAA, 0x3F5CFC93, 0xC31912F1,
0xC2480000, 0x3F5CFC93, 0xC31912F1, 0x42480000,
0x3F5CFC93, 0xC305E846, 0x4226AAAA, 0x3F5CFC93,
0xC305E846, 0x42055556, 0x3F5CFC93, 0xC305E846,
0x41C80000, 0x3F5CFC93, 0xC305E846, 0x41855556,
0x3F5CFC93, 0xC305E846, 0x41055556, 0x3F5CFC93,
0xC305E846, 0x358637BD, 0x3F5CFC93, 0xC305E846,
0xC1055554, 0x3F5CFC93, 0xC305E846, 0xC1855554,
0x3F5CFC93, 0xC305E846, 0xC1C7FFFF, 0x3F5CFC93,
0xC305E846, 0xC2055554, 0x3F5CFC93, 0xC305E846,
0xC226AAAA, 0x3F5CFC93, 0xC305E846, 0xC2480000,
0x3F5CFC93, 0xC305E846, 0x42480000, 0x3F5CFC93,
0xC2E57B38, 0x4226AAAA, 0x3F5CFC93, 0xC2E57B38,
0x42055556, 0x3F5CFC93, 0xC2E57B38, 0x41C80000,
0x3F5CFC93, 0xC2E57B38, 0x41855556, 0x3F5CFC93,
0xC2E57B38, 0x41055556, 0x3F5CFC93, 0xC2E57B38,
0x358637BD, 0x3F5CFC93, 0xC2E57B38, 0xC1055554,
0x3F5CFC93, 0xC2E57B38, 0xC1855554, 0x3F5CFC93,
0xC2E57B38, 0xC1C7FFFF, 0x3F5CFC93, 0xC2E57B38,
0xC2055554, 0x3F5CFC93, 0xC2E57B38, 0xC226AAAA,
0x3F5CFC93, 0xC2E57B38, 0xC2480000, 0x3F5CFC93,
0xC2E57B38, 0x42480000, 0x3F5CFC93, 0xC2BF25E2,
0x4226AAAA, 0x3F5CFC93, 0xC2BF25E2, 0x42055556,
0x3F5CFC93, 0xC2BF25E2, 0x41C80000, 0x3F5CFC93,
0xC2BF25E2, 0x41855556, 0x3F5CFC93, 0xC2BF25E2,
0x41055556, 0x3F5CFC93, 0xC2BF25E2, 0x358637BD,
0x3F5CFC93, 0xC2BF25E2, 0xC1055554, 0x3F5CFC93,
0xC2BF25E2, 0xC1855554, 0x3F5CFC93, 0xC2BF25E2,
0xC1C7FFFF, 0x3F5CFC93, 0xC2BF25E2, 0xC2055554,
0x3F5CFC93, 0xC2BF25E2, 0xC226AAAA, 0x3F5CFC93,
0xC2BF25E2, 0xC2480000, 0x3F5CFC93, 0xC2BF25E2,
0x42480000, 0x3F5CFC93, 0xC298D08D, 0x4226AAAA,
0x3F5CFC93, 0xC298D08D, 0x42055556, 0x3F5CFC93,
0xC298D08D, 0x41C80000, 0x3F5CFC93, 0xC298D08D,
0x41855556, 0x3F5CFC93, 0xC298D08D, 0x41055556,
0x3F5CFC93, 0xC298D08D, 0x358637BD, 0x3F5CFC93,
0xC298D08D, 0xC1055554, 0x3F5CFC93, 0xC298D08D,
0xC1855554, 0x3F5CFC93, 0xC298D08D, 0xC1C7FFFF,
0x3F5CFC93, 0xC298D08D, 0xC2055554, 0x3F5CFC93,
0xC298D08D, 0xC226AAAA, 0x3F5CFC93, 0xC298D08D,
0xC2480000, 0x3F5CFC93, 0xC298D08D, 0x42480000,
0x3F5CFC93, 0xC264F66F, 0x4226AAAA, 0x3F5CFC93,
0xC264F66F, 0x42055556, 0x3F5CFC93, 0xC264F66F,
0x41C80000, 0x3F5CFC93, 0xC264F66F, 0x41855556,
0x3F5CFC93, 0xC264F66F, 0x41055556, 0x3F5CFC93,
0xC264F66F, 0x358637BD, 0x3F5CFC93, 0xC264F66F,
0xC1055554, 0x3F5CFC93, 0xC264F66F, 0xC1855554,
0x3F5CFC93, 0xC264F66F, 0xC1C7FFFF, 0x3F5CFC93,
0xC264F66F, 0xC2055554, 0x3F5CFC93, 0xC264F66F,
0xC226AAAA, 0x3F5CFC93, 0xC264F66F, 0xC2480000,
0x3F5CFC93, 0xC264F66F, 0x42480000, 0x3F5CFC93,
0xC2184BC4, 0x4226AAAA, 0x3F5CFC93, 0xC2184BC4,
0x42055556, 0x3F5CFC93, 0xC2184BC4, 0x41C80000,
0x3F5CFC93, 0xC2184BC4, 0x41855556, 0x3F5CFC93,
0xC2184BC4, 0x41055556, 0x3F5CFC93, 0xC2184BC4,
0x358637BD, 0x3F5CFC93, 0xC2184BC4, 0xC1055554,
0x3F5CFC93, 0xC2184BC4, 0xC1855554, 0x3F5CFC93,
0xC2184BC4, 0xC1C7FFFF, 0x3F5CFC93, 0xC2184BC4,
0xC2055554, 0x3F5CFC93, 0xC2184BC4, 0xC226AAAA,
0x3F5CFC93, 0xC2184BC4, 0xC2480000, 0x3F5CFC93,
0xC2184BC4, 0x42480000, 0x3F5CFC93, 0xC1974231,
0x4226AAAA, 0x3F5CFC93, 0xC1974231, 0x42055556,
0x3F5CFC93, 0xC1974231, 0x41C80000, 0x3F5CFC93,
0xC1974231, 0x41855556, 0x3F5CFC93, 0xC1974231,
0x41055556, 0x3F5CFC93, 0xC1974231, 0x358637BD,
0x3F5CFC93, 0xC1974231, 0xC1055554, 0x3F5CFC93,
0xC1974231, 0xC1855554, 0x3F5CFC93, 0xC1974231,
0xC1C7FFFF, 0x3F5CFC93, 0xC1974231, 0xC2055554,
0x3F5CFC93, 0xC1974231, 0xC226AAAA, 0x3F5CFC93,
0xC1974231, 0xC2480000, 0x3F5CFC93, 0xC1974231,
0x42480000, 0x3F5CFC93, 0x3E84C964, 0x4226AAAA,
0x3F5CFC93, 0x3E84C964, 0x42055556, 0x3F5CFC93,
0x3E84C964, 0x41C80000, 0x3F5CFC93, 0x3E84C964,
0x41855556, 0x3F5CFC93, 0x3E84C964, 0x41055556,
0x3F5CFC93, 0x3E84C964, 0x358637BD, 0x3F5CFC93,
0x3E84C964, 0xC1055554, 0x3F5CFC93, 0x3E84C964,
0xC1855554, 0x3F5CFC93, 0x3E84C964, 0xC1C7FFFF,
0x3F5CFC93, 0x3E84C964, 0xC2055554, 0x3F5CFC93,
0x3E84C964, 0xC226AAAA, 0x3F5CFC93, 0x3E84C964,
0xC2480000, 0x3F5CFC93, 0x3E84C964,
};
static u32 l_normal[3] = {
0x00000000, 0x3F800000, 0x00000000,
};
static u32 l_texCoord[338] = {
0x00000000, 0x3F6AAAB0, 0x3DAAAA7E, 0x3F6AAAB0,
0x3DAAAA7E, 0x3F800000, 0x00000000, 0x3F800000,
0x3E2AAAC1, 0x3F6AAAB0, 0x3E2AAAC1, 0x3F800000,
0x3E800000, 0x3F6AAAB0, 0x3E800000, 0x3F800000,
0x3EAAAA9F, 0x3F6AAAB0, 0x3EAAAA9F, 0x3F800000,
0x3ED55561, 0x3F6AAAB0, 0x3ED55561, 0x3F800000,
0x3F000000, 0x3F6AAAB0, 0x3F000000, 0x3F800000,
0x3F155550, 0x3F6AAAB0, 0x3F155550, 0x3F800000,
0x3F2AAAB0, 0x3F6AAAB0, 0x3F2AAAB0, 0x3F800000,
0x3F400000, 0x3F6AAAB0, 0x3F400000, 0x3F800000,
0x3F555550, 0x3F6AAAB0, 0x3F555550, 0x3F800000,
0x3F6AAAB0, 0x3F6AAAB0, 0x3F6AAAB0, 0x3F800000,
0x3F800000, 0x3F6AAAB0, 0x3F800000, 0x3F800000,
0x00000000, 0x3F555550, 0x3DAAAA7E, 0x3F555550,
0x3E2AAAC1, 0x3F555550, 0x3E800000, 0x3F555550,
0x3EAAAA9F, 0x3F555550, 0x3ED55561, 0x3F555550,
0x3F000000, 0x3F555550, 0x3F155550, 0x3F555550,
0x3F2AAAB0, 0x3F555550, 0x3F400000, 0x3F555550,
0x3F555550, 0x3F555550, 0x3F6AAAB0, 0x3F555550,
0x3F800000, 0x3F555550, 0x00000000, 0x3F400000,
0x3DAAAA7E, 0x3F400000, 0x3E2AAAC1, 0x3F400000,
0x3E800000, 0x3F400000, 0x3EAAAA9F, 0x3F400000,
0x3ED55561, 0x3F400000, 0x3F000000, 0x3F400000,
0x3F155550, 0x3F400000, 0x3F2AAAB0, 0x3F400000,
0x3F400000, 0x3F400000, 0x3F555550, 0x3F400000,
0x3F6AAAB0, 0x3F400000, 0x3F800000, 0x3F400000,
0x00000000, 0x3F2AAAB0, 0x3DAAAA7E, 0x3F2AAAB0,
0x3E2AAAC1, 0x3F2AAAB0, 0x3E800000, 0x3F2AAAB0,
0x3EAAAA9F, 0x3F2AAAB0, 0x3ED55561, 0x3F2AAAB0,
0x3F000000, 0x3F2AAAB0, 0x3F155550, 0x3F2AAAB0,
0x3F2AAAB0, 0x3F2AAAB0, 0x3F400000, 0x3F2AAAB0,
0x3F555550, 0x3F2AAAB0, 0x3F6AAAB0, 0x3F2AAAB0,
0x3F800000, 0x3F2AAAB0, 0x00000000, 0x3F155550,
0x3DAAAA7E, 0x3F155550, 0x3E2AAAC1, 0x3F155550,
0x3E800000, 0x3F155550, 0x3EAAAA9F, 0x3F155550,
0x3ED55561, 0x3F155550, 0x3F000000, 0x3F155550,
0x3F155550, 0x3F155550, 0x3F2AAAB0, 0x3F155550,
0x3F400000, 0x3F155550, 0x3F555550, 0x3F155550,
0x3F6AAAB0, 0x3F155550, 0x3F800000, 0x3F155550,
0x00000000, 0x3F000000, 0x3DAAAA7E, 0x3F000000,
0x3E2AAAC1, 0x3F000000, 0x3E800000, 0x3F000000,
0x3EAAAA9F, 0x3F000000, 0x3ED55561, 0x3F000000,
0x3F000000, 0x3F000000, 0x3F155550, 0x3F000000,
0x3F2AAAB0, 0x3F000000, 0x3F400000, 0x3F000000,
0x3F555550, 0x3F000000, 0x3F6AAAB0, 0x3F000000,
0x3F800000, 0x3F000000, 0x00000000, 0x3ED55561,
0x3DAAAA7E, 0x3ED55561, 0x3E2AAAC1, 0x3ED55561,
0x3E800000, 0x3ED55561, 0x3EAAAA9F, 0x3ED55561,
0x3ED55561, 0x3ED55561, 0x3F000000, 0x3ED55561,
0x3F155550, 0x3ED55561, 0x3F2AAAB0, 0x3ED55561,
0x3F400000, 0x3ED55561, 0x3F555550, 0x3ED55561,
0x3F6AAAB0, 0x3ED55561, 0x3F800000, 0x3ED55561,
0x00000000, 0x3EAAAA9F, 0x3DAAAA7E, 0x3EAAAA9F,
0x3E2AAAC1, 0x3EAAAA9F, 0x3E800000, 0x3EAAAA9F,
0x3EAAAA9F, 0x3EAAAA9F, 0x3ED55561, 0x3EAAAA9F,
0x3F000000, 0x3EAAAA9F, 0x3F155550, 0x3EAAAA9F,
0x3F2AAAB0, 0x3EAAAA9F, 0x3F400000, 0x3EAAAA9F,
0x3F555550, 0x3EAAAA9F, 0x3F6AAAB0, 0x3EAAAA9F,
0x3F800000, 0x3EAAAA9F, 0x00000000, 0x3E800000,
0x3DAAAA7E, 0x3E800000, 0x3E2AAAC1, 0x3E800000,
0x3E800000, 0x3E800000, 0x3EAAAA9F, 0x3E800000,
0x3ED55561, 0x3E800000, 0x3F000000, 0x3E800000,
0x3F155550, 0x3E800000, 0x3F2AAAB0, 0x3E800000,
0x3F400000, 0x3E800000, 0x3F555550, 0x3E800000,
0x3F6AAAB0, 0x3E800000, 0x3F800000, 0x3E800000,
0x00000000, 0x3E2AAAC1, 0x3DAAAA7E, 0x3E2AAAC1,
0x3E2AAAC1, 0x3E2AAAC1, 0x3E800000, 0x3E2AAAC1,
0x3EAAAA9F, 0x3E2AAAC1, 0x3ED55561, 0x3E2AAAC1,
0x3F000000, 0x3E2AAAC1, 0x3F155550, 0x3E2AAAC1,
0x3F2AAAB0, 0x3E2AAAC1, 0x3F400000, 0x3E2AAAC1,
0x3F555550, 0x3E2AAAC1, 0x3F6AAAB0, 0x3E2AAAC1,
0x3F800000, 0x3E2AAAC1, 0x00000000, 0x3DAAAA7E,
0x3DAAAA7E, 0x3DAAAA7E, 0x3E2AAAC1, 0x3DAAAA7E,
0x3E800000, 0x3DAAAA7E, 0x3EAAAA9F, 0x3DAAAA7E,
0x3ED55561, 0x3DAAAA7E, 0x3F000000, 0x3DAAAA7E,
0x3F155550, 0x3DAAAA7E, 0x3F2AAAB0, 0x3DAAAA7E,
0x3F400000, 0x3DAAAA7E, 0x3F555550, 0x3DAAAA7E,
0x3F6AAAB0, 0x3DAAAA7E, 0x3F800000, 0x3DAAAA7E,
0x00000000, 0x00000000, 0x3DAAAA7E, 0x00000000,
0x3E2AAAC1, 0x00000000, 0x3E800000, 0x00000000,
0x3EAAAA9F, 0x00000000, 0x3ED55561, 0x00000000,
0x3F000000, 0x00000000, 0x3F155550, 0x00000000,
0x3F2AAAB0, 0x00000000, 0x3F400000, 0x00000000,
0x3F555550, 0x00000000, 0x3F6AAAB0, 0x00000000,
0x3F800000, 0x00000000,
};
#if TARGET_PC
using GameVersion = dusk::version::GameVersion;
@@ -305,8 +101,9 @@ static void mant_build_anchor_frame(const cXyz& anchor_a, const cXyz& anchor_b,
#endif
void daMant_packet_c::draw() {
ZoneScoped;
#if TARGET_PC
void* image = l_Egnd_mantTEX;
void* image = l_Egnd_mantTEX_copy;
void* lut = l_Egnd_mantPAL;
#else
void* image = tex_d[0];
@@ -388,12 +185,12 @@ void daMant_packet_c::draw() {
}
}
GXSETARRAY(GX_VA_POS, draw_pos, sizeof(mNrm[0]), 12, true);
GXSETARRAY(GX_VA_NRM, &l_normal, sizeof(l_normal), 12, false);
GXSETARRAY(GX_VA_NRM, l_normal, sizeof(f32) * 3, 12, false);
#else
GXSETARRAY(GX_VA_POS, this->getPos(), sizeof(mPos[0]), 12, true);
GXSETARRAY(GX_VA_NRM, this->getNrm(), sizeof(mNrm[0]), 12, true);
#endif
GXSETARRAY(GX_VA_TEX0, &l_texCoord, sizeof(l_texCoord), 8, false); // TODO: set to true when converted to float literals
GXSETARRAY(GX_VA_TEX0, l_texCoord, sizeof(f32) * 338, 8, false);
GXSetZCompLoc(0);
GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_ENABLE);
@@ -418,15 +215,32 @@ void daMant_packet_c::draw() {
GXSetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K3_A);
GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
#if TARGET_PC
if (!textureObjsInitialized) {
GXInitTlutObj(&tlutObj, lut, GX_TL_RGB5A3, 0x100);
GXInitTexObjCI(&mainTexObj, image, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&mainTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
GXInitTexObjCI(
&undersideTexObj, l_Egnd_mantTEX_U, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&undersideTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
textureObjsInitialized = true;
}
#else
GXTlutObj GStack_80;
GXInitTlutObj(&GStack_80, lut, GX_TL_RGB5A3, 0x100);
TGXTexObj GStack_74;
GXInitTexObjCI(&GStack_74, image, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&GStack_74, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
#endif
GXLoadTlut(&GStack_80, 0);
#if TARGET_PC
GXLoadTlut(&tlutObj, GX_TLUT0);
GXLoadTexObj(&mainTexObj, GX_TEXMAP0);
#else
GXLoadTlut(&GStack_80, GX_TLUT0);
GXLoadTexObj(&GStack_74, GX_TEXMAP0);
#endif
GXSetCullMode(GX_CULL_BACK);
@@ -442,12 +256,13 @@ void daMant_packet_c::draw() {
GXLoadNrmMtxImm(MStack_54, GX_PNMTX0);
GXCallDisplayList(l_Egnd_mantDL, 0x3e0);
#ifdef TARGET_PC
GStack_74.reset();
#endif
#if TARGET_PC
GXLoadTexObj(&undersideTexObj, GX_TEXMAP0);
#else
GXInitTexObjCI(&GStack_74, l_Egnd_mantTEX_U, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&GStack_74, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
GXLoadTexObj(&GStack_74, GX_TEXMAP0);
#endif
GXSetTevColor(GX_TEVREG0, COMPOUND_LITERAL(GXColor){0, 0, 0, 0});
GXSetTevKColor(GX_KCOLOR0, COMPOUND_LITERAL(GXColor){0, 0, 0, 0});
@@ -894,8 +709,14 @@ static int daMant_Execute(mant_class* i_this) {
if (0 <= uVar1 && uVar1 < 0x4000) {
int iVar5 = (uVar1 & 7) + (uVar1 & 0x78) * 4 + (uVar1 >> 4 & 0x18) + (uVar1 & 0x3e00);
l_Egnd_mantTEX[iVar5] = l_Egnd_mantTEX_U[iVar5] = 0;
DUSK_IF_ELSE(l_Egnd_mantTEX_copy[iVar5], l_Egnd_mantTEX[iVar5]) = l_Egnd_mantTEX_U[iVar5] = 0;
}
#if TARGET_PC
if(textureObjsInitialized) {
GXInitTlutObjData(&tlutObj, l_Egnd_mantPAL); // make sure the cached textures are updated
}
#endif
}
}
@@ -933,6 +754,14 @@ static int daMant_Create(fopAc_ac_c* i_this) {
l_Egnd_mantTEX_U[i] = 6;
}
#if TARGET_PC
memcpy(l_Egnd_mantTEX_copy, l_Egnd_mantTEX, sizeof(l_Egnd_mantTEX_copy));
if(textureObjsInitialized) {
GXInitTlutObjData(&tlutObj, l_Egnd_mantPAL); // make sure the cached textures are updated
}
#endif
lbl_277_bss_0 = 0;
daMant_Execute(m_this);
return 4;
+66
View File
@@ -26,6 +26,7 @@
#include <cstring>
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
#include "dusk/version.hpp"
#endif
@@ -180,6 +181,25 @@ static int Worm_nodeCallBack(J3DJoint* i_joint, int param_1) {
return 1;
}
#if TARGET_PC
static void dmg_rod_interp_callback(bool isSimFrame, void* pUserWork) {
dmg_rod_class* i_this = (dmg_rod_class*)pUserWork;
if (!i_this->mLineInterpPrevValid || !i_this->mLineInterpCurrValid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
const int count = i_this->kind == MG_ROD_KIND_LURE ? MG_ROD_LURE_LINE_LEN : MG_ROD_UKI_LINE_LEN;
cXyz* dst = i_this->linemat.getPos(0);
for (int i = 0; i < count; i++) {
const cXyz& p0 = i_this->mLineInterpPrev[i];
const cXyz& p1 = i_this->mLineInterpCurr[i];
dst[i] = p0 + (p1 - p0) * alpha;
}
static GXColor l_color = {0xFF, 0xFF, 0x96, 0xFF};
i_this->linemat.update(count, l_color, &i_this->actor.tevStr);
}
#endif
static int dmg_rod_Draw(dmg_rod_class* i_this) {
int unused;
fopAc_ac_c* actor = &i_this->actor;
@@ -220,6 +240,18 @@ static int dmg_rod_Draw(dmg_rod_class* i_this) {
i_this->linemat.update(MG_ROD_LURE_LINE_LEN, l_color, &i_this->actor.tevStr);
dComIfGd_set3DlineMat(&i_this->linemat);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (i_this->mLineInterpCurrValid) {
memcpy(i_this->mLineInterpPrev, i_this->mLineInterpCurr, MG_ROD_LURE_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpPrevValid = true;
}
memcpy(i_this->mLineInterpCurr, i_this->linemat.getPos(0), MG_ROD_LURE_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&dmg_rod_interp_callback, i_this);
}
#endif
model = i_this->rod_modelMorf->getModel();
g_env_light.setLightTevColorType_MAJI(model, &i_this->actor.tevStr);
i_this->rod_modelMorf->entryDL();
@@ -244,6 +276,18 @@ static int dmg_rod_Draw(dmg_rod_class* i_this) {
i_this->linemat.update(MG_ROD_UKI_LINE_LEN, l_color, &i_this->actor.tevStr);
dComIfGd_set3DlineMat(&i_this->linemat);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (i_this->mLineInterpCurrValid) {
memcpy(i_this->mLineInterpPrev, i_this->mLineInterpCurr, MG_ROD_UKI_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpPrevValid = true;
}
memcpy(i_this->mLineInterpCurr, i_this->linemat.getPos(0), MG_ROD_UKI_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&dmg_rod_interp_callback, i_this);
}
#endif
for (int i = 0; i < 15; i++) {
g_env_light.setLightTevColorType_MAJI(i_this->rod_uki_model[i], &actor->tevStr);
mDoExt_modelUpdateDL(i_this->rod_uki_model[i]);
@@ -5755,6 +5799,12 @@ static void play_camera_u(dmg_rod_class* i_this) {
}
}
#if TARGET_PC
BOOL item_any_fishing_rod(int itemId) {
return itemId == dItemNo_FISHING_ROD_1_e || (itemId >= dItemNo_BEE_ROD_e && itemId <= dItemNo_JEWEL_WORM_ROD_e);
}
#endif
static int dmg_rod_Execute(dmg_rod_class* i_this) {
fopAc_ac_c* actor = &i_this->actor;
@@ -5821,6 +5871,17 @@ static int dmg_rod_Execute(dmg_rod_class* i_this) {
i_this->prev_rod_substick_y = i_this->rod_substick_y;
i_this->rod_substick_y = mDoCPd_c::getSubStickY(PAD_1);
#if TARGET_PC
if (dusk::getSettings().game.buttonFishing) {
if ((item_any_fishing_rod(dComIfGp_getSelectItem(0)) && mDoCPd_c::getHoldX(PAD_1)) ||
(item_any_fishing_rod(dComIfGp_getSelectItem(1)) && mDoCPd_c::getHoldY(PAD_1)))
{
i_this->rod_stick_y = -1.0f;
i_this->rod_substick_y = -1.0f;
}
}
#endif
i_this->reel_speed = 5.0f;
i_this->reel_btn_flags = mDoCPd_c::getHoldB(PAD_1) | mDoCPd_c::getHoldDown(PAD_1);
if (mDoCPd_c::getHoldDown(PAD_1)) {
@@ -6388,6 +6449,11 @@ static int dmg_rod_Create(fopAc_ac_c* i_this) {
return cPhs_ERROR_e;
}
#if TARGET_PC
rod->mLineInterpPrevValid = false;
rod->mLineInterpCurrValid = false;
#endif
OS_REPORT("//////////////MG_ROD SET 2 !!\n");
if (!hio_set) {
rod->HIOInit = TRUE;
+6 -10
View File
@@ -3106,18 +3106,14 @@ void daMidna_c::setMidnaNoDrawFlg() {
BOOL daMidna_c::checkMetamorphoseEnableBase() {
BOOL tmp;
if (!daAlink_getAlinkActorClass()->checkMidnaRide() || (g_env_light.mEvilInitialized & 0x80) ||
/* dSv_event_flag_c::M_077 - Main Event - Get shadow crystal (can now transform) */
!dComIfGs_isEventBit(0xD04) ||
#if TARGET_PC
if (((!daAlink_getAlinkActorClass()->checkMidnaRide() || (g_env_light.mEvilInitialized & 0x80) ||
/* dSv_event_flag_c::M_077 - Main Event - Get shadow crystal (can now transform) */
!dComIfGs_isEventBit(0xD04)) &&
!dusk::getSettings().game.transformWithoutShadowCrystal) ||
(fopAcIt_Judge((fopAcIt_JudgeFunc)daMidna_searchNpc, &tmp) &&
!dusk::getSettings().game.canTransformAnywhere)
(fopAcIt_Judge((fopAcIt_JudgeFunc)daMidna_searchNpc, &tmp) &&
!dusk::getSettings().game.canTransformAnywhere)
#else
if (!daAlink_getAlinkActorClass()->checkMidnaRide() || (g_env_light.mEvilInitialized & 0x80) ||
/* dSv_event_flag_c::M_077 - Main Event - Get shadow crystal (can now transform) */
!dComIfGs_isEventBit(0xD04) ||
fopAcIt_Judge((fopAcIt_JudgeFunc)daMidna_searchNpc, &tmp)
fopAcIt_Judge((fopAcIt_JudgeFunc)daMidna_searchNpc, &tmp)
#endif
)
{
+2
View File
@@ -105,6 +105,7 @@ int dMirror_packet_c::entryModel(J3DModel* i_model) {
void dMirror_packet_c::mirrorZdraw(f32* param_0, f32* param_1, f32 param_2, f32 param_3,
f32 param_4, f32 param_5, f32 param_6, f32 param_7) {
ZoneScoped;
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE);
GXSetNumTexGens(0);
@@ -265,6 +266,7 @@ void dMirror_packet_c::modelDraw(J3DModel* i_model, Mtx param_1) {
}
void dMirror_packet_c::mainDraw() {
ZoneScoped;
j3dSys.reinitGX();
cXyz sp19C[5];
+4 -4
View File
@@ -328,13 +328,13 @@ int daNpcImpal_c::step(s16 i_angle, int i_animate) {
}
void daNpcImpal_c::playExpression() {
daNpcF_anmPlayData dat0 = {ANM_1, mpHIO->m.common.morf_frame, 1};
daNpcF_anmPlayData dat0 = {ANM_1, mpHIO->m.common.morf_frame, DUSK_IF_ELSE(0, 1)};
daNpcF_anmPlayData* pDat0[1] = {&dat0};
daNpcF_anmPlayData dat1 = {ANM_5, mpHIO->m.common.morf_frame, 1};
daNpcF_anmPlayData dat1 = {ANM_5, mpHIO->m.common.morf_frame, DUSK_IF_ELSE(0, 1)};
daNpcF_anmPlayData* pDat1[1] = {&dat1};
daNpcF_anmPlayData dat2 = {ANM_4, mpHIO->m.common.morf_frame, 1};
daNpcF_anmPlayData dat2 = {ANM_4, mpHIO->m.common.morf_frame, DUSK_IF_ELSE(0, 1)};
daNpcF_anmPlayData* pDat2[1] = {&dat2};
daNpcF_anmPlayData dat3 = {ANM_6, mpHIO->m.common.morf_frame, 1};
daNpcF_anmPlayData dat3 = {ANM_6, mpHIO->m.common.morf_frame, DUSK_IF_ELSE(0, 1)};
daNpcF_anmPlayData* pDat3[1] = {&dat3};
daNpcF_anmPlayData dat4 = {ANM_8, mpHIO->m.common.morf_frame, 0};
daNpcF_anmPlayData* pDat4[1] = {&dat4};
+11 -1
View File
@@ -178,7 +178,7 @@ static void anm_init(npc_ks_class* i_this, int param_2, f32 i_morf, u8 i_attr, f
param_2 = 42;
} else {
// bug: developers meant to set equal to 44?
param_2 == 44;
IF_NOT_DUSK(param_2 == 44);
dComIfGs_shake_kandelaar();
}
}
@@ -6882,6 +6882,16 @@ static int daNpc_Ks_Delete(npc_ks_class* i_this) {
i_this->model->stopZelAnime();
}
#if TARGET_PC
if (leader == i_this) {
leader = NULL;
}
if (saru_p[i_this->set_id] == i_this) {
saru_p[i_this->set_id] = NULL;
}
#endif
return 1;
}
+1 -11
View File
@@ -26,8 +26,6 @@
daObjDrop_HIO_c l_HIO;
#endif
#include <dusk/ui/settings.hpp>
static void* searchParentSub(void* pproc, void* pdata) {
daObjDrop_c* pdrop = (daObjDrop_c*)pdata;
fopAc_ac_c* pym = (fopAc_ac_c*)pproc;
@@ -105,17 +103,9 @@ void daObjDrop_c::dropGet() {
dComIfGs_setLightDropNum(dComIfGp_getStartStageDarkArea(), num + 1);
if (dComIfGp_getStartStageDarkArea() == 2 &&
#if TARGET_PC
((dusk::tphd_active() &&
dComIfGs_getLightDropNum(dComIfGp_getStartStageDarkArea()) == 11) ||
!dusk::tphd_active() &&
dComIfGs_getLightDropNum(dComIfGp_getStartStageDarkArea()) == 15
))
#else
dComIfGs_getLightDropNum(dComIfGp_getStartStageDarkArea()) == 15)
#endif
{
/* dSv_event_flag_c::F_0005 - Misc. - Gathered 15 Tears of Light in area 4 */
/* dSv_event_flag_c::F_0005 - Misc. - Gathered 14 Tears of Light in area 4 */
dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[9]);
}
+1
View File
@@ -261,6 +261,7 @@ void FlagCloth_c::execute() {
}
void FlagCloth_c::draw() {
ZoneScoped;
j3dSys.reinitGX();
GXSetNumIndStages(0);
dKy_setLight_again();
+1
View File
@@ -220,6 +220,7 @@ void FlagCloth2_c::initCcSphere(fopAc_ac_c*) {
}
inline void FlagCloth2_c::draw() {
ZoneScoped;
j3dSys.reinitGX();
GXSetNumIndStages(0);
dKy_setLight_again();
+38
View File
@@ -10,6 +10,9 @@
#include "d/d_s_play.h"
#include "d/actor/d_a_player.h"
#include "Z2AudioLib/Z2Instances.h"
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#endif
daObj_Keyhole_HIO_c::daObj_Keyhole_HIO_c() {
id = -1;
@@ -53,6 +56,21 @@ static int daObj_Keyhole_Draw(obj_keyhole_class* i_this) {
for (int i = 0; i < 6; i++) {
kh_chain_s* chain_s = &i_this->chain_s[i];
for (int j = 0; j < i_this->chain_num; j++) {
#if TARGET_PC
if (dusk::frame_interp::is_enabled() && i_this->mChainInterpPrevValid && i_this->mChainInterpCurrValid) {
const f32 alpha = dusk::frame_interp::get_interpolation_step();
Mtx mtx;
const f32* p0 = (const f32*)i_this->mChainInterpPrev[i][j];
const f32* p1 = (const f32*)i_this->mChainInterpCurr[i][j];
f32* dst = (f32*)mtx;
for (int k = 0; k < 12; k++) {
dst[k] = p0[k] + (p1[k] - p0[k]) * alpha;
}
chain_s->model[j]->setBaseTRMtx(mtx);
g_env_light.setLightTevColorType_MAJI(chain_s->model[j], &actor->tevStr);
mDoExt_modelUpdateDL(chain_s->model[j]);
} else
#endif
dComIfGp_entrySimpleModel(chain_s->model[j], fopAcM_GetRoomNo(actor));
}
}
@@ -370,6 +388,21 @@ static void chain_move(obj_keyhole_class* i_this) {
ANGLE_ADD(sp8, TREG_S(0) + 0x3D00);
}
}
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (i_this->mChainInterpCurrValid) {
memcpy(i_this->mChainInterpPrev, i_this->mChainInterpCurr, sizeof(i_this->mChainInterpCurr));
i_this->mChainInterpPrevValid = true;
}
for (int i = 0; i < 6; i++) {
for (int j = 0; j < i_this->chain_num; j++) {
MTXCopy(i_this->chain_s[i].model[j]->getBaseTRMtx(), i_this->mChainInterpCurr[i][j]);
}
}
i_this->mChainInterpCurrValid = true;
}
#endif
}
static void open(obj_keyhole_class* i_this) {
@@ -750,6 +783,11 @@ static int daObj_Keyhole_Create(fopAc_ac_c* a_this) {
return cPhs_ERROR_e;
}
#if TARGET_PC
i_this->mChainInterpPrevValid = false;
i_this->mChainInterpCurrValid = false;
#endif
OS_REPORT("//////////////OBJ_KEYHOLE SET 2 !!\n");
if (i_this->arg0 == 3) {
+17
View File
@@ -392,7 +392,10 @@ static const u8* l_sightDL_get() {
#endif
void daPy_sightPacket_c::draw() {
ZoneScoped;
#if !TARGET_PC
TGXTexObj texObj;
#endif
j3dSys.reinitGX();
GXSetNumIndStages(0);
@@ -407,10 +410,24 @@ void daPy_sightPacket_c::draw() {
GXSetTevColor(GX_TEVREG0, reg0);
GXSetTevColor(GX_TEVREG1, reg1);
#if TARGET_PC
if (mpCachedImg != mpImg) {
mTexObj.reset();
GXInitTexObj(&mTexObj, mpData, mpImg->width, mpImg->height,
static_cast<GXTexFmt>(mpImg->format), static_cast<GXTexWrapMode>(mpImg->wrapS),
static_cast<GXTexWrapMode>(mpImg->wrapT),
mpImg->mipmapCount > 1 ? GX_ENABLE : GX_DISABLE);
GXInitTexObjLOD(
&mTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, GX_FALSE, GX_FALSE, GX_ANISO_1);
mpCachedImg = mpImg;
}
GXLoadTexObj(&mTexObj, GX_TEXMAP0);
#else
GXInitTexObj(&texObj, mpData, mpImg->width, mpImg->height, (GXTexFmt)mpImg->format,
(GXTexWrapMode)mpImg->wrapS, (GXTexWrapMode)mpImg->wrapT, mpImg->mipmapCount > 1 ? GX_ENABLE : GX_DISABLE);
GXInitTexObjLOD(&texObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, GX_FALSE, GX_FALSE, GX_ANISO_1);
GXLoadTexObj(&texObj, GX_TEXMAP0);
#endif
GXLoadPosMtxImm(mProjMtx, GX_PNMTX0);
GXSetCurrentMtx(0);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
+379
View File
@@ -15,6 +15,12 @@ const u16 l_J_Ohana00_64TEX__height = 63;
using GameVersion = dusk::version::GameVersion;
static u8* l_J_Ohana00_64TEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x9060}, {GameVersion::GcnPal, 0x9060}}, 0x800), true); return buf; }
#define l_J_Ohana00_64TEX (l_J_Ohana00_64TEX_get())
// from d_grass.inc
static MtxP get_model_mtx(Mtx modelMtx, Mtx storage);
static void transform_positions(
const dusk::batch::LeafTemplate& tpl, const Vec* posArray, const Mtx mtx, Vec* xfPos);
static void split_batch(u32& emitted, u32 vtxCount);
#else
#include "assets/l_J_Ohana00_64TEX.h"
#endif
@@ -588,6 +594,12 @@ dFlower_packet_c::dFlower_packet_c() {
GXInitTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, l_J_Ohana01_64128_0419TEX,
l_J_Ohana01_64128_0419TEX__width + 1, l_J_Ohana01_64128_0419TEX__height + 1, GX_TF_CMPR, GX_MIRROR, GX_MIRROR, GX_FALSE
);
dusk::batch::decode_leaf_template(l_J_hana00DL, 0x140, mTplHana00);
dusk::batch::decode_leaf_template(l_J_hana00_cDL, 0xC0, mTplHana00Cut);
dusk::batch::decode_leaf_template(l_J_hana01DL, 0x120, mTplHana01);
dusk::batch::decode_leaf_template(l_J_hana01_c_00DL, 0xC0, mTplHana01Cut00);
dusk::batch::decode_leaf_template(l_J_hana01_c_01DL, 0x120, mTplHana01Cut);
#endif
m_deleteRoom = &dFlower_packet_c::deleteRoom;
@@ -597,7 +609,373 @@ dFlower_packet_c::dFlower_packet_c() {
#endif
}
#if TARGET_PC
static void batch_setup_tev(u32 lightMask) {
GXSetCullMode(GX_CULL_NONE);
GXSetNumChans(2);
GXSetChanCtrl(GX_COLOR0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE);
GXSetChanCtrl(GX_COLOR1, GX_TRUE, GX_SRC_VTX, GX_SRC_REG, lightMask, GX_DF_CLAMP, GX_AF_SPOT);
GXSetNumTevStages(3);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR1A1);
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_CPREV, GX_CC_RASC, GX_CC_ZERO);
GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);
GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
GXSetTevColorIn(GX_TEVSTAGE2, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_C0);
GXSetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaIn(GX_TEVSTAGE2, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA);
GXSetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
}
static GXColor hana00_amb_color(const dFlower_data_c* flower, const dKy_tevstr_c* tevstr) {
GXColor amb = {0, 0, 0, 0xFF};
if (DEBUG && g_kankyoHIO.navy.grass_adjust_ON != 0) {
amb.r = g_kankyoHIO.navy.grass_ambcol.r * 2;
amb.g = g_kankyoHIO.navy.grass_ambcol.g * 2;
amb.b = g_kankyoHIO.navy.grass_ambcol.b * 2;
} else {
amb.r = (flower->field_0x04 & 0x1F) * 2;
amb.g = ((flower->field_0x04 >> 5) & 0x1F) * 2;
amb.b = ((flower->field_0x04 >> 0xA) & 0x1F) * 2;
}
if (daPy_py_c::checkNowWolfPowerUp()) {
f32 ambRate = g_env_light.bg_amb_col[0].r / 255.0f;
f32 col = (((flower->field_0x04 & 0x1F) * 2 + 0x10));
amb.r = col * (ambRate * 4.0f);
ambRate = g_env_light.bg_amb_col[0].g / 255.0f;
f32 col2 = (((flower->field_0x04 >> 5) & 0x1F) * 2 + 0x10);
amb.g = col2 * (4.0f * ambRate);
ambRate = g_env_light.bg_amb_col[0].b / 255.0f;
f32 col3 = (((flower->field_0x04 >> 10) & 0x1F) * 2 + 0x10);
amb.b = col3 * (4.0f * ambRate);
}
if (amb.r == 0x3E) {
amb.r = tevstr->AmbCol.r;
}
if (amb.g == 0x3E) {
amb.g = tevstr->AmbCol.g;
}
if (amb.b == 0x3E) {
amb.b = tevstr->AmbCol.b;
}
return amb;
}
static GXColor hana01_amb_color(int idx, const dKy_tevstr_c* tevstr) {
f32 rRate = tevstr->AmbCol.r * 0.03125f;
if (rRate > 1.0f) {
rRate = 1.0f;
}
f32 gRate = tevstr->AmbCol.g * 0.03125f;
if (gRate > 1.0f) {
gRate = 1.0f;
}
f32 bRate = tevstr->AmbCol.b * 0.03125f;
if (bRate > 1.0f) {
bRate = 1.0f;
}
GXColor amb = {1, 1, 1, 1};
GXColor sub;
sub.r = -0.4f * tevstr->AmbCol.r * rRate;
sub.g = -0.4f * tevstr->AmbCol.g * gRate;
sub.b = -0.4f * tevstr->AmbCol.b * bRate;
switch (idx & 7) {
case 0:
amb.r = tevstr->AmbCol.r + sub.r;
amb.g = tevstr->AmbCol.g;
amb.b = tevstr->AmbCol.b;
break;
case 1:
amb.r = tevstr->AmbCol.r;
amb.g = tevstr->AmbCol.g + sub.g;
amb.b = tevstr->AmbCol.b;
break;
case 2:
amb.r = tevstr->AmbCol.r;
amb.g = tevstr->AmbCol.g;
amb.b = tevstr->AmbCol.b + sub.b;
break;
case 3:
amb.r = tevstr->AmbCol.r + sub.r;
amb.g = tevstr->AmbCol.g + sub.g;
amb.b = tevstr->AmbCol.b;
break;
case 4:
amb.r = tevstr->AmbCol.r;
amb.g = tevstr->AmbCol.g + sub.g;
amb.b = tevstr->AmbCol.b + sub.b;
break;
case 5:
amb.r = tevstr->AmbCol.r + sub.r;
amb.g = tevstr->AmbCol.g;
amb.b = tevstr->AmbCol.b + sub.b;
break;
case 6:
amb.r = tevstr->AmbCol.r + sub.r;
amb.g = tevstr->AmbCol.g + sub.g;
amb.b = tevstr->AmbCol.b + sub.b;
break;
case 7:
break;
}
if (daPy_py_c::checkNowWolfPowerUp()) {
f32 ambRate = g_env_light.bg_amb_col[0].r / 255.0f;
amb.r = (amb.r + 8) * (6.0f * ambRate);
ambRate = g_env_light.bg_amb_col[0].g / 255.0f;
amb.g = (amb.g + 8) * (6.0f * ambRate);
ambRate = g_env_light.bg_amb_col[0].b / 255.0f;
amb.b = (amb.b + 8) * (6.0f * ambRate);
}
amb.a = 0xFF;
return amb;
}
static void flower_emit(const dusk::batch::LeafTemplate& tpl, const Vec* xformedPos, GXColor amb) {
for (u32 i = 0; i < tpl.vtxCount; i++) {
const dusk::batch::LeafTemplate::Vtx& v = tpl.vtx[i];
const Vec& p = xformedPos[v.pos];
GXPosition3f32(p.x, p.y, p.z);
GXNormal1x8(v.nrm);
GXColor1x8(v.clr);
GXColor4u8(amb.r, amb.g, amb.b, amb.a);
GXTexCoord1x8(v.tex);
}
}
void dFlower_packet_c::draw() {
ZoneScoped;
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
j3dSys.reinitGX();
GXSetNumIndStages(0);
dKy_setLight_again();
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);
GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSETARRAY(GX_VA_POS, &l_flowerPos, sizeof(l_flowerPos), sizeof(Vec), true);
GXSETARRAY(GX_VA_NRM, &l_flowerNormal, sizeof(l_flowerNormal), sizeof(Vec), true);
GXSETARRAY(GX_VA_CLR0, &l_flowerColor, sizeof(l_flowerColor), sizeof(GXColor), true);
GXSETARRAY(GX_VA_TEX0, &l_flowerTexCoord, sizeof(l_flowerTexCoord), 8, true);
static GXVtxDescList vtxDescList[] = {
{GX_VA_POS, GX_DIRECT},
{GX_VA_NRM, GX_INDEX8},
{GX_VA_CLR0, GX_INDEX8},
{GX_VA_CLR1, GX_DIRECT},
{GX_VA_TEX0, GX_INDEX8},
{GX_VA_NULL, GX_NONE},
};
static Vec xfPos[256];
Mtx identity;
MTXIdentity(identity);
// --- hana00 ---
for (int i = 0; i < 64; i++) {
dFlower_data_c* first = m_room[i].getData();
if (first == nullptr || !dComIfGp_roomControl_checkStatusFlag(i, 0x10)) {
continue;
}
dKy_tevstr_c* tevstr = dComIfGp_roomControl_getTevStr(i);
int lightCount = 6;
if (dComIfGp_roomControl_getStatusRoomDt(i) != nullptr) {
lightCount = dComIfGp_roomControl_getStatusRoomDt(i)->getLightVecInfoNum();
}
if (dKy_SunMoon_Light_Check() && lightCount < 2) {
lightCount = 2;
}
for (int j = 0; j < 6; j++) {
if (kankyo->field_0x0c18[j].field_0x26 == 1) {
lightCount++;
}
}
if (lightCount <= 2) {
GXCallDisplayList(l_matLight4DL, 0x80);
} else {
GXCallDisplayList(l_matDL, 0x80);
}
GXSetTevColorS10(GX_TEVREG0, {0, 0, 0, 0});
dKy_Global_amb_set(tevstr);
dKy_GxFog_tevstr_set(tevstr);
dKy_setLight_nowroom_grass(tevstr->room_no, 1.0f);
GXLoadTexObj(&mTexObj_l_J_Ohana00_64TEX, GX_TEXMAP0);
batch_setup_tev(lightCount <= 2 ? (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4) :
(GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4 |
GX_LIGHT5 | GX_LIGHT6 | GX_LIGHT7));
GXSetVtxDescv(vtxDescList);
GXLoadPosMtxImm(identity, GX_PNMTX0);
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
for (int bucket = 0; bucket < 2; bucket++) {
const bool cut = bucket != 0;
const dusk::batch::LeafTemplate& tpl = cut ? mTplHana00Cut : mTplHana00;
bool open = false;
u32 emitted = 0;
for (dFlower_data_c* flower = first; flower != nullptr; flower = flower->mp_next) {
if (cLib_checkBit<u8>(flower->m_state, 4) ||
cLib_checkBit<u8>(flower->m_state, 0x40))
{
continue;
}
if ((cLib_checkBit<u8>(flower->m_state, 8) != 0) != cut) {
continue;
}
if (!open) {
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
open = true;
}
split_batch(emitted, tpl.vtxCount);
Mtx interpMtx;
MtxP mtx = get_model_mtx(flower->m_modelMtx, interpMtx);
transform_positions(tpl, reinterpret_cast<Vec*>(l_flowerPos), mtx, xfPos);
flower_emit(tpl, xfPos, hana00_amb_color(flower, tevstr));
}
if (open) {
GXEnd();
}
}
}
// --- hana01 ---
GXSETARRAY(GX_VA_POS, mp_pos, sizeof(l_flowerPos2), sizeof(Vec), true);
GXSETARRAY(GX_VA_NRM, &l_flowerNormal2, sizeof(l_flowerNormal2), sizeof(Vec), true);
GXSETARRAY(GX_VA_CLR0, mp_colors, sizeof(l_flowerColor2), sizeof(GXColor), true);
GXSETARRAY(GX_VA_TEX0, mp_texCoords, sizeof(l_flowerTexCoord2), 8, true);
for (int i = 0; i < 64; i++) {
dFlower_data_c* first = m_room[i].getData();
if (first == NULL) {
continue;
}
dKy_tevstr_c* tevstr = dComIfGp_roomControl_getTevStr(i);
int lightCount = 6;
if (dComIfGp_roomControl_getStatusRoomDt(i) != NULL) {
lightCount = dComIfGp_roomControl_getStatusRoomDt(i)->getLightVecInfoNum();
}
#if DEBUG
if (g_kankyoHIO.light.m_HOSTIO_setting != 0) {
lightCount = g_kankyoHIO.dungeonLight.usedLights;
}
#endif
if (dKy_SunMoon_Light_Check() == TRUE && lightCount < 2) {
lightCount = 2;
}
if (lightCount <= 2) {
GXCallDisplayList(mp_mat2Light4DL, m_mat2Light4DL_size);
} else {
GXCallDisplayList(mp_mat2DL, m_mat2DL_size);
}
GXSetTevColorS10(GX_TEVREG0, {0, 0, 0, 0});
dKy_Global_amb_set(tevstr);
dKy_GxFog_tevstr_set(tevstr);
dKy_setLight_nowroom_grass(tevstr->room_no, 1.0f);
GXLoadTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, GX_TEXMAP0);
batch_setup_tev(lightCount <= 2 ? (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4) :
(GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4 |
GX_LIGHT5 | GX_LIGHT6 | GX_LIGHT7));
GXSetVtxDescv(vtxDescList);
GXLoadPosMtxImm(identity, GX_PNMTX0);
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
const dusk::batch::LeafTemplate* const buckets[3] = {
&mTplHana01, &mTplHana01Cut00, &mTplHana01Cut};
for (int bucket = 0; bucket < 3; bucket++) {
const dusk::batch::LeafTemplate& tpl = *buckets[bucket];
bool open = false;
u32 emitted = 0;
int idx = 0;
for (dFlower_data_c* flower = first; flower != NULL; flower = flower->mp_next, idx++) {
if (cLib_checkBit<u8>(flower->m_state, 4) ||
!cLib_checkBit<u8>(flower->m_state, 0x40))
{
continue;
}
const int flowerBucket = cLib_checkBit<u8>(flower->m_state, 8) ? 2 :
cLib_checkBit<u8>(flower->m_state, 0x10) ? 1 :
0;
if (flowerBucket != bucket) {
continue;
}
if (!open) {
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
open = true;
}
split_batch(emitted, tpl.vtxCount);
Mtx interpMtx;
MtxP mtx = get_model_mtx(flower->m_modelMtx, interpMtx);
transform_positions(tpl, mp_pos, mtx, xfPos);
flower_emit(tpl, xfPos, hana01_amb_color(idx, tevstr));
}
if (open) {
GXEnd();
}
}
}
GXSetNumTevStages(1);
GXSetNumChans(1);
J3DShape::resetVcdVatCache();
}
#else
void dFlower_packet_c::draw() {
ZoneScoped;
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
j3dSys.reinitGX();
@@ -885,6 +1263,7 @@ void dFlower_packet_c::draw() {
J3DShape::resetVcdVatCache();
}
#endif
void dFlower_packet_c::calc() {
dFlower_anm_c* anm_p = getAnm();
+357
View File
@@ -512,12 +512,368 @@ dGrass_packet_c::dGrass_packet_c() {
m_Mkusa_9q_cDL_size = 0xC0;
field_0x1d714 = 0;
#if TARGET_PC
dusk::batch::decode_leaf_template(mp_Mkusa_9q_DL, m_Mkusa_9q_DL_size, mTplKusa9q);
dusk::batch::decode_leaf_template(mp_Mkusa_9q_cDL, m_Mkusa_9q_cDL_size, mTplKusa9qCut);
dusk::batch::decode_leaf_template(l_M_TenGusaDL, 0xC0, mTplTengusa);
#endif
OS_REPORT("草群メモリ=%f\n", 117.7734375f);
m_deleteRoom = &dGrass_packet_c::deleteRoom;
}
#if TARGET_PC
static MtxP get_model_mtx(Mtx modelMtx, Mtx storage) {
if (dusk::frame_interp::lookup_replacement(modelMtx, storage)) {
cMtx_concat(j3dSys.getViewMtx(), storage, storage);
return storage;
}
return modelMtx;
}
static void transform_positions(
const dusk::batch::LeafTemplate& tpl, const Vec* posArray, const Mtx mtx, Vec* xfPos) {
for (u32 i = 0; i < tpl.posRefCount; i++) {
const u8 idx = tpl.posRefs[i];
MTXMultVec(mtx, &posArray[idx], &xfPos[idx]);
}
}
static void split_batch(u32& emitted, u32 vtxCount) {
if (emitted + vtxCount > 0xFFFF) {
GXEnd();
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
emitted = 0;
}
emitted += vtxCount;
}
static GXColor blade_amb_color(const dGrass_data_c* blade, const dKy_tevstr_c* tevstr) {
GXColor amb;
amb.a = 0;
#if DEBUG
if (g_kankyoHIO.navy.grass_adjust_ON) {
amb.r = g_kankyoHIO.navy.grass_ambcol.r * 2;
amb.g = g_kankyoHIO.navy.grass_ambcol.g * 2;
amb.b = g_kankyoHIO.navy.grass_ambcol.b * 2;
return amb;
}
#endif
amb.r = (blade->m_addCol & 0x1F) * 2;
amb.g = ((blade->m_addCol >> 5) & 0x1F) * 2;
amb.b = ((blade->m_addCol >> 0xA) & 0x1F) * 2;
if (daPy_py_c::checkNowWolfPowerUp()) {
f32 ambRate = g_env_light.bg_amb_col[0].r / 255.0f;
f32 col = (((blade->m_addCol & 0x1F) * 2 + 0x10));
amb.r = col * (ambRate * 4.0f);
ambRate = g_env_light.bg_amb_col[0].g / 255.0f;
f32 col2 = (((blade->m_addCol >> 5) & 0x1F) * 2 + 0x10);
amb.g = col2 * (4.0f * ambRate);
ambRate = g_env_light.bg_amb_col[0].b / 255.0f;
f32 col3 = (((blade->m_addCol >> 10) & 0x1F) * 2 + 0x10);
amb.b = col3 * (4.0f * ambRate);
}
f32 roomAmbScale = 1.0f - (static_cast<int>(blade->m_pos.x) & 0xFF) * 0.001953125f;
f32 colScale = 1.1f - (static_cast<u8>(static_cast<int>(blade->m_pos.x)) & 0xFF) / 2000.0f;
colScale -= (static_cast<int>(blade->m_pos.z) & 0xFF) / 2000.0f;
if (colScale > 1.0f) {
colScale = 1.0f;
}
if (amb.r == 0x3E) {
amb.r = tevstr->AmbCol.r * roomAmbScale;
} else {
amb.r = amb.r * colScale;
}
if (amb.g == 0x3E) {
amb.g = tevstr->AmbCol.g * roomAmbScale;
} else {
amb.g = amb.g * colScale;
}
if (amb.b == 0x3E) {
amb.b = tevstr->AmbCol.b * roomAmbScale;
} else {
amb.b = amb.b * colScale;
}
return amb;
}
static void blade_emit(const dusk::batch::LeafTemplate& tpl, const Vec* xformedPos,
const GXColor* colors, GXColor amb) {
for (u32 i = 0; i < tpl.vtxCount; i++) {
const dusk::batch::LeafTemplate::Vtx& v = tpl.vtx[i];
const Vec& p = xformedPos[v.pos];
GXPosition3f32(p.x, p.y, p.z);
GXNormal1x8(v.nrm);
GXColor4u8(amb.r, amb.g, amb.b, colors[v.clr].a);
GXTexCoord1x8(v.tex);
}
}
void dGrass_packet_c::draw() {
ZoneScoped;
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
j3dSys.reinitGX();
GXSetNumIndStages(0);
dKy_setLight_again();
GXClearVtxDesc();
static GXVtxDescList l_vtxDescList[] = {
{GX_VA_POS, GX_INDEX8},
{GX_VA_NRM, GX_INDEX8},
{GX_VA_CLR0, GX_INDEX8},
{GX_VA_TEX0, GX_INDEX8},
{GX_VA_NULL, GX_NONE},
};
static GXVtxDescList l_batchVtxDescList[] = {
{GX_VA_POS, GX_DIRECT},
{GX_VA_NRM, GX_INDEX8},
{GX_VA_CLR0, GX_DIRECT},
{GX_VA_TEX0, GX_INDEX8},
{GX_VA_NULL, GX_NONE},
};
GXSetVtxDescv(l_vtxDescList);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSETARRAY(GX_VA_POS, mp_pos, sizeof(l_pos), sizeof(Vec), true);
GXSETARRAY(GX_VA_NRM, mp_normal, sizeof(l_normal), sizeof(Vec), true);
GXSETARRAY(GX_VA_CLR0, mp_colors, sizeof(l_color), sizeof(GXColor), true);
GXSETARRAY(GX_VA_TEX0, mp_texCoords, sizeof(l_texCoord), 8, true);
GXColorS10 reg1 = {0, 0, 0, 0};
// daytime "shine" alpha curve (TEVREG1 alpha)
f32 daytime = g_env_light.getDaytime();
f32 ratio;
f32 shine;
if (daytime >= 90.0f && daytime < 135.0f) {
ratio = 1.0f - (0.022222223f * (135.0f - daytime));
shine = 100.0f - (18.0f * ratio);
} else if (daytime >= 135.0f && daytime < 225.0f) {
ratio = 1.0f - (0.011111111f * (225.0f - daytime));
shine = 82.0f - (25.0f * ratio);
} else if (daytime >= 225.0f && daytime < 270.0f) {
ratio = 1.0f - (0.022222223f * (270.0f - daytime));
shine = 57.0f - (-25.0f * ratio);
} else if (daytime >= 270.0f && daytime < 315.0f) {
ratio = (1.0f - (0.022222223f * (315.0f - daytime)));
shine = 82.0f - (-18.0f * ratio);
} else {
shine = 100.0f;
}
#if DEBUG
if (g_kankyoHIO.navy.grass_shine_value != 0.0f) {
shine = g_kankyoHIO.navy.grass_shine_value;
}
#endif
static Vec xfPos[256];
Mtx identity;
PSMTXIdentity(identity);
for (int i = 0; i < 64; i++) {
dGrass_data_c* first = m_room[i].getData();
if (first == NULL || !dComIfGp_roomControl_checkStatusFlag(i, 0x10)) {
continue;
}
int lightCount = 6;
dKy_tevstr_c* tevstr = dComIfGp_roomControl_getTevStr(i);
f32 lightInf = g_env_light.grass_light_inf_rate * g_env_light.bg_light_influence;
lightInf += 0.5f * (1.0f - lightInf);
J3DLightInfo* lightInfo = tevstr->mLights[0].getLightInfo();
reg1.r = lightInfo->mColor.r * lightInf;
reg1.g = lightInfo->mColor.g * lightInf;
reg1.b = lightInfo->mColor.b * lightInf;
reg1.a = shine;
if (memcmp(dComIfGp_getStartStageName(), "D_MN01", 6) == 0) {
reg1.r = 0;
reg1.g = 0x1E;
reg1.b = 5;
reg1.a = 0x50;
}
GFSetTevColorS10(GX_TEVREG1, reg1);
if (dComIfGp_roomControl_getStatusRoomDt(i) != nullptr) {
lightCount = dComIfGp_roomControl_getStatusRoomDt(i)->getLightVecInfoNum();
}
#if DEBUG
if (g_kankyoHIO.light.m_HOSTIO_setting != 0) {
lightCount = g_kankyoHIO.dungeonLight.usedLights;
}
#endif
if (dKy_SunMoon_Light_Check() == TRUE && lightCount < 2) {
lightCount = 2;
}
for (int j = 0; j < 6; j++) {
if (kankyo->field_0x0c18[j].field_0x26 == 1) {
lightCount++;
}
}
// room-level setup
if (first->field_0x05 <= 3 || first->field_0x05 >= 10) {
GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0);
if (lightCount <= 3) {
GXCallDisplayList(mp_kusa9q_14_DL, m_kusa9q_DL_14_size);
} else {
GXCallDisplayList(mp_kusa9q_DL, m_kusa9q_DL_size);
}
} else {
GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0);
GXCallDisplayList(l_Tengusa_matDL, 0xA0);
}
GFSetTevColorS10(GX_TEVREG2, {0, 0, 0, 0});
dKy_Global_amb_set(tevstr);
dKy_GfFog_tevstr_set(tevstr);
dKy_setLight_nowroom_grass(tevstr->room_no, 0.0f);
GXSetVtxDescv(l_batchVtxDescList);
GXLoadPosMtxImm(identity, GX_PNMTX0);
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
// buckets: (kusa05 vs tengusa) x (standing vs cut)
bool hasRegrowing = false;
for (int bucket = 0; bucket < 4; bucket++) {
const bool kusaTex = bucket < 2;
const bool cut = (bucket & 1) != 0;
const dusk::batch::LeafTemplate& tpl =
cut ? mTplKusa9qCut : (kusaTex ? mTplKusa9q : mTplTengusa);
bool open = false;
u32 emitted = 0;
for (dGrass_data_c* blade = first; blade != NULL; blade = blade->mp_next) {
if (cLib_checkBit<u8>(blade->field_0x01, 2)) {
continue; // clipped
}
if (blade->field_0x02 < -1) {
hasRegrowing = true;
continue;
}
const bool bladeKusaTex = blade->field_0x05 <= 3 || blade->field_0x05 >= 10;
if (bladeKusaTex != kusaTex || (blade->field_0x02 < 0) != cut) {
continue;
}
if (!open) {
if (kusaTex) {
GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0);
if (lightCount <= 2) {
GXCallDisplayList(mp_kusa9q_14_DL, m_kusa9q_DL_14_size);
} else {
GXCallDisplayList(mp_kusa9q_DL, m_kusa9q_DL_size);
}
} else {
GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0);
GXCallDisplayList(l_Tengusa_matDL, 0xA0);
}
// change amb_src to GX_SRC_VTX
const u32 lightMask =
(kusaTex && lightCount <= 2)
? (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4)
: (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4 | GX_LIGHT5 |
GX_LIGHT6 | GX_LIGHT7);
GXSetChanCtrl(GX_COLOR0, GX_TRUE, GX_SRC_VTX, GX_SRC_REG, lightMask,
GX_DF_CLAMP, GX_AF_SPOT);
reg1.a = cut ? 0 : shine;
GFSetTevColorS10(GX_TEVREG1, reg1);
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
open = true;
}
split_batch(emitted, tpl.vtxCount);
Mtx interpMtx;
MtxP mtx = get_model_mtx(blade->m_modelMtx, interpMtx);
transform_positions(tpl, mp_pos, mtx, xfPos);
blade_emit(tpl, xfPos, mp_colors, blade_amb_color(blade, tevstr));
}
if (open) {
GXEnd();
}
}
// regrowing blades have per-blade TEVREG2 alpha
// draw them with the original immediate path
if (hasRegrowing) {
GXSetVtxDescv(l_vtxDescList);
for (dGrass_data_c* blade = first; blade != NULL; blade = blade->mp_next) {
if (blade->field_0x02 >= -1 || cLib_checkBit<u8>(blade->field_0x01, 2)) {
continue;
}
const bool kusaTex = blade->field_0x05 <= 3 || blade->field_0x05 >= 10;
if (kusaTex) {
GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0);
if (lightCount <= 2) {
GXCallDisplayList(mp_kusa9q_14_DL, m_kusa9q_DL_14_size);
} else {
GXCallDisplayList(mp_kusa9q_DL, m_kusa9q_DL_size);
}
} else {
GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0);
GXCallDisplayList(l_Tengusa_matDL, 0xA0);
}
reg1.a = 0;
GFSetTevColorS10(GX_TEVREG1, reg1);
GXSetChanAmbColor(GX_COLOR0A0, blade_amb_color(blade, tevstr));
Mtx modelMtx;
GXLoadPosMtxImm(get_model_mtx(blade->m_modelMtx, modelMtx), GX_PNMTX0);
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
GFSetTevColorS10(GX_TEVREG2,
{0, 0, 0, static_cast<s16>(-0x100 - (blade->field_0x02 << 8) / 40)});
if (blade->field_0x02 != -2) {
if (kusaTex) {
GXCallDisplayList(mp_Mkusa_9q_DL, m_Mkusa_9q_DL_size);
} else {
GXCallDisplayList(l_M_TenGusaDL, 0xC0);
}
} else {
GXCallDisplayList(mp_Mkusa_9q_cDL, m_Mkusa_9q_cDL_size);
}
GFSetTevColorS10(GX_TEVREG2, {0, 0, 0, 0});
}
}
}
J3DShape::resetVcdVatCache();
}
#else
void dGrass_packet_c::draw() {
ZoneScoped;
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
cXyz spB4;
cXyz spA8;
@@ -810,6 +1166,7 @@ void dGrass_packet_c::draw() {
J3DShape::resetVcdVatCache();
}
#endif
void dGrass_packet_c::calc() {
cXyz* temp_r29 = dKyw_get_wind_vec();
+63 -3
View File
@@ -32,6 +32,9 @@
#include "dusk/frame_interpolation.h"
#include "dusk/logging.h"
#include "dusk/action_bindings.h"
#include "dusk/mouse.h"
#include "dusk/settings.h"
#include "dusk/touch_camera.h"
#include "imgui.h"
#endif
@@ -7497,6 +7500,15 @@ static constexpr s16 FLYCAM_ROLL_SPEED = 256;
static ImVec2 sFlyCamLastMousePos = {-1.f, -1.f};
#if TARGET_PC
static constexpr f32 TOUCH_CAMERA_CSTICK_EXIT_THRESHOLD = 0.05f;
static bool sTouchFreeCameraActive = false;
bool dCamera_c::isAimActive() {
auto* link = daAlink_getAlinkActorClass();
return link != nullptr && link->checkAimContext() &&
dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10);
}
bool dCamera_c::executeDebugFlyCam() {
if (!dusk::getSettings().game.debugFlyCam) {
if (mDebugFlyCam.initialized) {
@@ -7639,11 +7651,29 @@ void dCamera_c::deactivateDebugFlyCam() {
}
bool dCamera_c::freeCamera() {
if (dusk::getSettings().game.freeCamera && mGear == 1) {
f32 touchYawDp = 0.0f;
f32 touchPitchDp = 0.0f;
bool touchCameraMoved = false;
const bool touchControlsEnabled = dusk::getSettings().game.enableTouchControls;
if (touchControlsEnabled && !isAimActive()) {
touchCameraMoved = dusk::touch_camera::consume_delta(touchYawDp, touchPitchDp);
}
if (!touchControlsEnabled ||
mPadInfo.mCStick.mLastValue > TOUCH_CAMERA_CSTICK_EXIT_THRESHOLD)
{
sTouchFreeCameraActive = false;
}
if (touchCameraMoved) {
sTouchFreeCameraActive = true;
}
const bool useFreeCamera = dusk::getSettings().game.freeCamera ||
dusk::getSettings().game.enableMouseCamera || sTouchFreeCameraActive;
if (useFreeCamera && mGear == 1) {
mGear = 0;
}
if (!dusk::getSettings().game.freeCamera || mCamStyle == 70)
if (!useFreeCamera || mCamStyle == 70)
{
mCamParam.mManualMode = 0;
return false;
@@ -7654,6 +7684,17 @@ bool dCamera_c::freeCamera() {
mCamParam.freeYAngle = mViewCache.mDirection.mInclination.Degree();
}
if (touchCameraMoved) {
mCamParam.mManualMode = 1;
const f32 yawInput = dusk::getSettings().game.invertCameraXAxis ? -touchYawDp : touchYawDp;
const f32 pitchInput =
touchPitchDp * (dusk::getSettings().game.invertCameraYAxis ? -1.0f : 1.0f);
mCamParam.freeXAngle += yawInput * dusk::getSettings().game.touchCameraXSensitivity *
dusk::touch_camera::YAW_DEGREES_PER_DP;
mCamParam.freeYAngle += pitchInput * dusk::getSettings().game.touchCameraYSensitivity *
dusk::touch_camera::PITCH_DEGREES_PER_DP;
}
cXyz camMovement = {mPadInfo.mCStick.mLastPosX, mPadInfo.mCStick.mLastPosY, 0.0f};
f32 magnitude = sqrt(mPadInfo.mCStick.mLastPosX * mPadInfo.mCStick.mLastPosX + mPadInfo.mCStick.mLastPosY * mPadInfo.mCStick.mLastPosY);
@@ -7669,6 +7710,17 @@ bool dCamera_c::freeCamera() {
mCamParam.freeYAngle += camMovement.y * magnitude * dusk::getSettings().game.freeCameraYSensitivity * 5.0f;
}
f32 yaw_rad = 0.0f;
f32 pitch_rad = 0.0f;
dusk::mouse::getCameraDeltas(yaw_rad, pitch_rad);
if (dusk::getSettings().game.enableMouseCamera && (yaw_rad != 0.0f || pitch_rad != 0.0f) &&
!dComIfGp_checkCameraAttentionStatus(dComIfGp_getPlayerCameraID(0), 0x8))
{
mCamParam.mManualMode = 1;
mCamParam.freeXAngle += MTXRadToDeg(yaw_rad);
mCamParam.freeYAngle += -MTXRadToDeg(pitch_rad);
}
fopAc_ac_c* player = dComIfGp_getPlayer(0);
if (!mCamParam.mManualMode || player == nullptr) {
return false;
@@ -9350,6 +9402,10 @@ bool dCamera_c::rideCamera(s32 param_0) {
mStyleSettle.mFinished = true;
}
#if TARGET_PC
freeCamera();
#endif
return true;
}
@@ -9479,6 +9535,10 @@ bool dCamera_c::rideCamera(s32 param_0) {
setFlag(0x400);
}
#if TARGET_PC
freeCamera();
#endif
return true;
}
@@ -11334,7 +11394,7 @@ static int camera_execute(camera_process_class* i_this) {
const auto target = get_target_trim_height(i_this);
const auto step = dusk::frame_interp::get_interpolation_step();
const auto cur = camera->TrimHeight();
const auto prev = (4.0f * cur - target) / 3.0f;
const auto prev = (4.0f * cur - target) / 3.0f;
const auto trim_height = prev + (cur - prev) * step;
widezoom_correction(i_this, trim_height);
+1 -13
View File
@@ -25,7 +25,6 @@
#include "m_Do/m_Do_graphic.h"
#include <cstdio>
#include <cstring>
#include <dusk/ui/settings.hpp>
#include "dusk/string.hpp"
@@ -2574,14 +2573,7 @@ u8 dComIfG_getNowCalcRegion() {
bool dComIfGp_isLightDropMapVisible() {
for (int i = 0; i < 3; i++) {
#if TARGET_PC
if (dComIfGs_isLightDropGetFlag(i) != FALSE &&
((dusk::tphd_active() && dComIfGs_getLightDropNum(i) < 12) ||
(!dusk::tphd_active() && dComIfGs_getLightDropNum(i) < 16)))
{
#else
if (dComIfGs_isLightDropGetFlag(i) != FALSE && dComIfGs_getLightDropNum(i) < 16) {
#endif
return true;
}
}
@@ -2851,11 +2843,7 @@ BOOL dComIfGs_Wolf_Change_Check() {
BOOL is_wolf = false;
// Transforming Unlocked
if (dComIfGs_isEventBit(0x0D04)
#if TARGET_PC
|| dusk::getSettings().game.transformWithoutShadowCrystal
#endif
) {
if (dComIfGs_isEventBit(0x0D04)) {
is_wolf = dComIfGs_getTransformStatus();
} else if (dComIfGs_isTransformLV(0) && !dComIfGs_isDarkClearLV(0)) {
is_wolf = true;

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