Compare commits

...

142 Commits

Author SHA1 Message Date
Irastris 1fea4f02ed Fix camera bouncing with interp enabled 2026-04-24 14:26:56 -04:00
Luke Street 35ea13c53a Update aurora 2026-04-24 12:25:15 -06:00
PJB3005 5fab665f21 Don't allocate giant unused stacks for movie player
How to save 800 KiB of commit charge easy
2026-04-24 15:25:14 +02:00
madeline 109f0a50e5 fix sun song again 2026-04-24 03:37:35 -07:00
Irastris 746910c59f Register interp callback for d_a_obj_item
Fixes rupee color changes
2026-04-24 05:13:31 -04:00
CraftyBoss ae4806ae4f Merge remote-tracking branch 'origin/main' 2026-04-23 23:40:36 -07:00
CraftyBoss 1c00e2cdde fix unsafe cstr usage in flag editor, remove stray backslash 2026-04-23 23:40:20 -07:00
Luke Street 78301a8a83 Restore half-size in drawDepth2 2026-04-24 00:39:20 -06:00
CraftyBoss ca798049b3 Merge remote-tracking branch 'origin/main' 2026-04-23 23:31:24 -07:00
CraftyBoss daf4b1dfeb update aurora, add pre launch option to determine save file type (gci or raw) 2026-04-23 23:31:07 -07:00
TakaRikka 5bdd31a5af Merge pull request #517 from TwilitRealm/midna-eye
Clamp max LOD for Wolf Link and Midna eyes
2026-04-23 22:43:16 -07:00
Luke Street 3cb5e5172b Add Adult Link eye LOD fix 2026-04-23 23:42:15 -06:00
TakaRikka d625c7ab0c fix save editor clothes change crash 2026-04-23 20:26:50 -07:00
Luke Street c2045391c8 Fix a couple issues for Xcode projects (#513)
* Link separate JSystem libraries due to control.cpp

This allows the Xcode generator to work, otherwise
it breaks on the duplicate control.o files within
the game_debug library.

* Fix __memcpy define on GCC

* Try LINK_GROUP:RESCAN for GNU ld

* Combine dusk/game_base/game_debug targets

* Fix compile defs syntax
2026-04-23 21:05:38 -06:00
TakaRikka f04a0ffcf1 forgot pic oops 2026-04-23 15:12:40 -07:00
TakaRikka dfdac1c1cd update setup instructions 2026-04-23 15:11:51 -07:00
TakaRikka f4b361ab02 Merge pull request #510 from TwilitRealm/feature/thinner-map-lines
Thinner map lines at higher resolution
2026-04-23 14:36:02 -07:00
TakaRikka 5f3d3012ff Merge pull request #509 from TwilitRealm/fix/ring_menu_cursor_interp
Frame interp: interpolate ring menu cursor along arc
2026-04-23 14:09:35 -07:00
TakaRikka 0897ef1132 Merge pull request #508 from TwilitRealm/fix/wolf-dive-fix
Fix Sun Song check
2026-04-23 14:08:44 -07:00
TakaRikka 8b89dbcbf0 Merge pull request #506 from TwilitRealm/instant-text-responsiveness
Instant Text: Fix holding B in the middle of a textbox
2026-04-23 14:08:09 -07:00
TakaRikka f24e944ab0 Merge pull request #492 from TwilitRealm/feature/gamepad-color
Gamepad Colors for DS4/DS5
2026-04-23 14:07:43 -07:00
MelonSpeedruns 23130d5a57 Thinner map lines at higher resolution
Affects both the Map Menu and the Mini-Map.
2026-04-23 15:08:34 -04:00
Luke Street 1e6e1976e3 Clamp max LOD for Wolf Link and Midna eyes 2026-04-23 13:07:42 -06:00
MelonSpeedruns 4453316bb0 Separated gamepad color into its own files 2026-04-23 14:25:50 -04:00
Pheenoh 14aeefb813 Frame interp: interpolate ring menu cursor along arc 2026-04-23 08:38:47 -06:00
MelonSpeedruns c991c7c407 Fixes sun songing underwater 2026-04-23 09:42:02 -04:00
madeline 251c6e7aec more precise link debug info 2026-04-23 06:28:16 -07:00
madeline cf2357fff2 Merge branch 'main' of https://github.com/TakaRikka/dusk 2026-04-23 03:58:38 -07:00
madeline 06e6b0d47e fix safety bit on interp fixes #507 2026-04-23 03:58:35 -07:00
gymnast86 a83b4186af fix holding B in the middle of text 2026-04-23 03:25:19 -07:00
TakaRikka dc5de83436 Merge pull request #503 from TwilitRealm/feature/rotate-link-doll
Add ability to rotate link on the collection screen
2026-04-22 23:36:55 -07:00
TakaRikka 77425b4b25 Merge pull request #500 from TwilitRealm/fix/interp_dselect_cursor_ring_menu
Frame Interp: dselect_cursor_c in d_menu_ring
2026-04-22 23:31:16 -07:00
Phillip Stephens 5a109313cb Minor tooltip cleanup 2026-04-22 23:02:11 -07:00
Phillip Stephens d8a7927602 Clarify tooltip 2026-04-22 22:59:56 -07:00
Phillip Stephens cccddee106 Add ability to rotate link on the collection screen 2026-04-22 22:58:38 -07:00
madeline 6c252c6d26 disallow breaking share state by overlapping loads 2026-04-22 22:37:21 -07:00
madeline b06c1911c6 Merge branch 'main' of https://github.com/TakaRikka/dusk 2026-04-22 22:33:59 -07:00
madeline 7c9e99220a better impl of insta state shares 2026-04-22 22:33:55 -07:00
madeline bfd8b9f453 make state share loads basically instant 2026-04-22 22:27:14 -07:00
Pheenoh 53e8662335 frame interp: dselect_cursor_c in d_menu_ring 2026-04-22 21:57:36 -06:00
Luke Street ae54f024cd Update aurora 2026-04-22 21:48:58 -06:00
TakaRikka 9aa391c5bf Merge pull request #499 from TwilitRealm/fix/dmap_frame_interp
Frame interp: Fix dmap scroll arrows
2026-04-22 17:41:56 -07:00
TakaRikka ec48249934 Merge pull request #495 from TwilitRealm/limiter
Limiter: Use SDL_GetTicksNS instead of std::chrono
2026-04-22 17:40:47 -07:00
Pheenoh 6a8f3516f9 Frame interp: Fix dmap scroll arrows 2026-04-22 18:35:07 -06:00
TakaRikka 79d4835784 Merge pull request #496 from TwilitRealm/feat/esc_fs
Press esc to exit full screen
2026-04-22 17:00:54 -07:00
TakaRikka b1a4783e38 Merge pull request #494 from TwilitRealm/fix/wide-fused-shadows
Widescreenified Fused Shadow Animations for all first 3 bosses
2026-04-22 16:59:45 -07:00
Pheenoh 0038afa392 Press esc to exit full screen 2026-04-22 17:51:16 -06:00
Luke Street 5fcffa0b4f Use SDL_GetTicksNS instead of std::chrono 2026-04-22 17:18:18 -06:00
MelonSpeedruns 9e9d11ae89 Widescreenified Fused Shadow Animations for all first 3 bosses 2026-04-22 18:47:51 -04:00
TakaRikka 97bd84725c Merge pull request #491 from TwilitRealm/gyro-roll
Incorporate roll into gyro horizontal aiming
2026-04-22 14:45:57 -07:00
Captain Kitty Cat 19c86b1b73 Items Don't Despawn (#488)
* Indefinite Item Drops

* Preserve Disappear Effect when Disabled

* Changed to "Items Don't Despawn". Under "Cheats"

* SetItemTooltip for description
2026-04-22 12:27:54 -06:00
Luke Street ca247095da Reset gravity baseline on aim start 2026-04-22 12:20:44 -06:00
MelonSpeedruns c350b7b8ed fix building on linux 2026-04-22 13:52:14 -04:00
Luke Street ac3d3314c4 Incorporate roll into gyro horizontal aiming 2026-04-22 11:47:40 -06:00
MelonSpeedruns f916a48db0 optimized code and removed bugs 2026-04-22 13:36:06 -04:00
MelonSpeedruns 6963a4b554 Merge remote-tracking branch 'origin/main' into feature/gamepad-color
# Conflicts:
#	src/f_ap/f_ap_game.cpp
2026-04-22 13:01:03 -04:00
MelonSpeedruns 4466bf4e12 wip 2026-04-22 13:00:35 -04:00
madeline c4d01b82a6 get rid of old logs 2026-04-22 03:16:13 -07:00
madeline 42e8d9ab9d name fix 2026-04-22 02:50:49 -07:00
madeline 9c562ff740 state packs and partial states 2026-04-22 02:44:58 -07:00
madeline 1787de517c properly set oxygen in share states 2026-04-22 01:55:23 -07:00
madeline 832e567620 better share states 2026-04-22 01:50:17 -07:00
Luke Street 319efbe662 Reset game clock with over 250ms frame gap 2026-04-22 00:30:11 -06:00
Luke Street 6f34bb050a Call J3DModel::diff in mDoExt_modelEntryDL when interpolating
Fixes #355
2026-04-22 00:17:52 -06:00
Irastris a2a56122e2 Gyro: Hawk Aiming 2026-04-22 01:46:10 -04:00
Irastris 58f2679def Rollgoal: Gyro & Mirror Mode Fixes 2026-04-22 01:41:35 -04:00
Luke Street 396ea02fe5 Fix flowers with interpolation on (#486) 2026-04-21 23:33:03 -06:00
TakaRikka 8100ddb990 Merge pull request #485 from TwilitRealm/frame-pacing-2
Rework interpolation pacing; interpolate every frame
2026-04-21 22:05:33 -07:00
Luke Street d78c46a628 Rework interpolation pacing; interpolate every frame 2026-04-21 22:45:18 -06:00
Phillip Stephens 1e93657ab5 Update aurora for fix 2026-04-21 19:25:28 -07:00
madeline 366e47245e make sun song play the correct notes 2026-04-21 19:23:53 -07:00
madeline 4c53ba91be Merge branch 'main' of https://github.com/TakaRikka/dusk 2026-04-21 18:59:23 -07:00
madeline cf080523cb dsp oscillator channels fixes #471 fixes #131 2026-04-21 18:59:11 -07:00
Luke Street a15d0af139 Better fix for mirror crashes 2026-04-21 17:39:53 -06:00
Luke Street d99205ecc6 Update aurora 2026-04-21 17:12:28 -06:00
TakaRikka dd3a61d84c fix dmap background 2026-04-21 15:13:55 -07:00
Luke Street 595a6f1c9e Enable DoF (+ setting) & fix texture cache leak 2026-04-21 14:52:26 -06:00
MelonSpeedruns 18d70df188 Small Imgui changes for better visibility by end user (#473)
Co-authored-by: MelonSpeedruns <melonspeedruns@stratobox.net>
2026-04-21 10:17:56 -06:00
TakaRikka 46f6dc67c1 make file select card wait times obey instantSaves setting 2026-04-21 00:46:22 -07:00
madeline 6267b79da3 Merge branch 'main' of https://github.com/TakaRikka/dusk 2026-04-20 20:22:12 -07:00
madeline 62f3d09076 fix incorrect eldin field name on map 2026-04-20 20:22:06 -07:00
Luke Street 4b3c559df3 CMake: Don't build a game static lib 2026-04-20 20:47:03 -06:00
Luke Street 30a99c22f1 Reorganize ImGui menus (#456)
* Reorganize ImGui menus

* Fix crash_reporting.cpp

* Update aurora
2026-04-20 20:45:16 -06:00
TakaRikka 360cb37028 Merge pull request #463 from TwilitRealm/fix/interp_map_save
Frame Interp: d_menu_save and d_menu_fmap2D
2026-04-20 19:17:56 -07:00
TakaRikka 4b6b41a6aa Merge pull request #461 from TwilitRealm/26-04-21-thp-shutdown-crash
Fix THP shutdown crash
2026-04-20 18:45:29 -07:00
Pheenoh faa8618124 Fix frame interpolation on save and world map menus 2026-04-20 19:37:38 -06:00
PJB3005 89acf923e0 Fix THP shutdown crash
Cleanly shut down movie player threads on exit.

I'm not 100% fond of having to manually insert a call like this into the shutdown logic, but the other solution is shutting down all processes and that's likely to result in causing more crashes.
2026-04-21 01:11:49 +02:00
Irastris c42a33154c Frame Interp: Fix flickering refraction in cutscenes 2026-04-20 18:11:27 -04:00
madeline a074e30147 Merge branch 'main' of https://github.com/TakaRikka/dusk 2026-04-20 06:45:09 -07:00
madeline 2ce272d586 fix some menus scaling wrong 2026-04-20 06:45:05 -07:00
TakaRikka e1636e20bd Merge branch 'main' of https://github.com/TakaRikka/dusk 2026-04-20 06:14:28 -07:00
TakaRikka 9904720e5a better lv5key fix 2026-04-20 06:14:21 -07:00
madeline 9910320fb4 Merge branch 'main' of https://github.com/TakaRikka/dusk 2026-04-20 06:10:22 -07:00
madeline b43a9e2ccc menu cursor resizing fixes #313 closes #314 2026-04-20 06:10:18 -07:00
TakaRikka 23d81492e6 Merge branch 'main' of https://github.com/TakaRikka/dusk 2026-04-20 06:02:11 -07:00
TakaRikka 65b0ec3f90 add failsafes to lv5key to avoid reverse unlock softlock 2026-04-20 06:02:03 -07:00
madeline 91248d10db disable water refraction in debug, fixes #422 2026-04-20 05:36:31 -07:00
TakaRikka f76a4d7087 add dMsgUnit_c::setTag bug fix 2026-04-20 05:15:02 -07:00
TakaRikka c7b609945b fix option menu widescreen regression 2026-04-20 04:48:58 -07:00
TakaRikka 6ca6ea8065 fix crawl arrow direction with mirror mode 2026-04-20 04:16:35 -07:00
TakaRikka 315f621176 Merge pull request #450 from TwilitRealm/discord
Discord rich presence
2026-04-20 03:36:03 -07:00
madeline 10d9a818c2 fix apple ci? 2026-04-20 00:31:41 -07:00
madeline e3761784af rich presence 2026-04-20 00:21:09 -07:00
Phillip Stephens d85556a063 Use vendored SDL on ubuntu for libusb (#448) 2026-04-19 23:27:29 -06:00
madeline c43f33a5bc Merge branch 'main' of https://github.com/TakaRikka/dusk 2026-04-19 21:43:32 -07:00
madeline e63897d1f7 add --console to launch.json 2026-04-19 21:43:29 -07:00
Howard Luck 35a69e7ff1 Frame interp pacing/camera cuts, King Bulblin reins, and crash fixes
* misc fixes round 1

* kb1 fixes

* fixes for encounter/ira
2026-04-20 00:34:13 -04:00
Luke Street 8b9f09bda5 Frame interp: Fix cloud shadow flickering (#446) 2026-04-19 21:31:34 -06:00
Jasper St. Pierre 32cddc725b mirror flicker fix 2 2026-04-19 16:21:30 -07:00
Jasper St. Pierre 55eec3b0de hitstun camera interp fix 2026-04-19 16:01:51 -07:00
TakaRikka 1cf14f176c Merge pull request #438 from TwilitRealm/frame-interp-simplify
Frame interp simplify
2026-04-19 14:58:38 -07:00
TakaRikka 74550b031f Merge pull request #436 from TwilitRealm/feat/pause_on_unfocus
Add pause on unfocus feature
2026-04-19 14:26:58 -07:00
Jasper St. Pierre 2f84f0eaa4 j3d small cleanup 2026-04-19 14:16:38 -07:00
Jasper St. Pierre 3ed7ef1c88 fix stone shadow flicker 2026-04-19 13:22:00 -07:00
Jasper St. Pierre eace147652 mirror interp fix 2026-04-19 12:57:30 -07:00
Jasper St. Pierre 53c005c4f1 jutfader doc 2026-04-19 12:48:50 -07:00
Jasper St. Pierre a4ff97564c minor cleanup 2026-04-19 12:39:08 -07:00
Jasper St. Pierre c6beeba14f proct 2026-04-19 11:56:48 -07:00
Jasper St. Pierre e470278717 grass/flower/shadow interp fixes 2026-04-19 10:27:37 -07:00
Pheenoh 783230b654 Add pause on unfocus feature 2026-04-19 10:02:55 -06:00
TakaRikka 4e7711725a attempt to fix clawshot aim model position 2026-04-19 03:58:22 -07:00
Jasper St. Pierre e5bf7606ec run d_a_bg::draw on interp frames
to set up lights. this is a somewhat hacky workaround for lighting setup, but it might be good enough?
2026-04-19 03:19:44 -07:00
Jasper St. Pierre aa377cd5c1 add alternate to interp callbacks, flags on the leafdraw 2026-04-19 02:43:25 -07:00
Jasper St. Pierre bb9a88d7dc frame interp camera cleanups 2026-04-19 02:25:00 -07:00
Jasper St. Pierre 341e97ba82 simple shadow interp fix 2026-04-19 01:14:58 -07:00
Jasper St. Pierre 8d3cb51157 frame interp simplify 2026-04-18 23:26:28 -07:00
TakaRikka 7fff3b5ae0 Merge pull request #430 from TwilitRealm/fix/JAISeqMgr
Fix JAISeqMgr
2026-04-18 22:57:57 -07:00
TakaRikka 6beb73b7a6 Merge pull request #429 from TwilitRealm/fix/d_menu_fmap2d_interp
Fix d_menu_fmap2d interpolation for tears of light
2026-04-18 22:57:45 -07:00
Jasper St. Pierre c239a5a226 freelook fix 2026-04-18 22:45:54 -07:00
Jasper St. Pierre b3f8fecfe4 water interpolation fix 2026-04-18 22:17:35 -07:00
Phillip Stephens 6dcf4942f5 Update aurora for CARDFormat speedup 2026-04-18 21:51:28 -07:00
Phillip Stephens cd7e429a66 Fix memory card not properly attaching on init. (#433)
* Fix memory card not properly attaching on init.

Previously the card status was forced to ready which caused quite a bit of default state getting set properly,
reverting that and setting mCardCommand to `COMM_ATTACH_e` allows the memory card system to properly probe and
detect the card status.

A companion fix in aurora addresses the "Memory Card corrupted" error message.

* Update aurora
2026-04-18 21:33:02 -07:00
Pheenoh fcfcb35929 fix JAISeqMgr beginStartSeq_ to check free memory before allocation 2026-04-18 19:53:40 -06:00
Pheenoh 82b20be436 Merge remote-tracking branch 'origin/main' into fix/d_menu_fmap2d_interp 2026-04-18 19:34:57 -06:00
Pheenoh 33101d8050 fix minimap tear of light flash not respecting interpolation 2026-04-18 19:34:38 -06:00
TakaRikka 05160a968c Merge branch 'main' of https://github.com/TakaRikka/dusk 2026-04-18 18:08:40 -07:00
TakaRikka 623f29eb24 volume setting effects movie now 2026-04-18 18:08:33 -07:00
TakaRikka 0a3833818a Merge pull request #427 from TwilitRealm/fix/interp_d_file_select
Fix file select fade not rendering with frame interpolation
2026-04-18 16:17:54 -07:00
TakaRikka 4f276252a3 Merge branch 'main' of https://github.com/TakaRikka/dusk 2026-04-18 15:54:47 -07:00
TakaRikka d17c629ce0 fix bulblin eye glow 2026-04-18 15:54:42 -07:00
Pheenoh 5bcc969778 fix file select fade not rendering with frame interpolation 2026-04-18 16:53:48 -06:00
MelonSpeedruns 31c5397ae3 Gamepad Color Implementation 2026-04-15 14:36:20 -04:00
120 changed files with 3054 additions and 1384 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
"type": "cppvsdbg",
"request": "launch",
"program": "${command:cmake.launchTargetPath}",
"args": ["-l", "1", "--dvd", "${workspaceRoot}/orig/GZ2E01/GZ2E01.iso"],
"args": ["-l", "1", "--dvd", "${workspaceRoot}/orig/GZ2E01/GZ2E01.iso", "--console"],
"MIMode": "gdb",
"miDebuggerPath": "gdb",
"symbolSearchPath": "${command:cmake.launchTargetPath}",
+96 -31
View File
@@ -90,6 +90,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
# Folder-based instead of target-based organization
# in Visual Studio and Xcode generators
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "_cmake")
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
set(DAWN_USE_WAYLAND ON CACHE BOOL "Enable support for Wayland surface" FORCE)
endif ()
@@ -281,7 +286,7 @@ set(DUSK_TP_VERSION ${DUSK_GAME_NAME}${DUSK_GAME_VERSION})
message(STATUS "dusk: Game Version: ${DUSK_TP_VERSION}")
source_group("dolzel" FILES ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${JSYSTEM_FILES} ${JSYSTEM_DEBUG_FILES} ${REL_FILES})
source_group("dolzel" FILES ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${REL_FILES})
source_group("dusk" FILES ${DUSK_FILES})
set(GAME_COMPILE_DEFS TARGET_PC WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0
@@ -316,6 +321,48 @@ if (DUSK_MOVIE_SUPPORT)
list(APPEND GAME_COMPILE_DEFS MOVIE_SUPPORT=1)
endif ()
option(DUSK_ENABLE_DISCORD_RPC "Enable Discord Rich Presence support" ON)
if (DUSK_ENABLE_DISCORD_RPC AND NOT ANDROID AND NOT IOS AND NOT TVOS)
FetchContent_Populate(discord_rpc
URL https://github.com/discord/discord-rpc/archive/refs/tags/v3.4.0.tar.gz
URL_HASH SHA256=e13427019027acd187352dacba6c65953af66fdf3c35fcf38fc40b454a9d7855
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)
# RapidJSON is a git submodule absent from the discord-rpc tarball; fetch separately.
FetchContent_Populate(rapidjson
URL https://github.com/Tencent/rapidjson/archive/refs/tags/v1.1.0.tar.gz
URL_HASH SHA256=bf7ced29704a1e696fbccf2a2b4ea068e7774fa37f6d7dd4039d0787f8bed98e
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)
if (NOT TARGET discord-rpc)
set(_drpc ${discord_rpc_SOURCE_DIR}/src)
set(_drpc_src
${_drpc}/discord_rpc.cpp
${_drpc}/rpc_connection.cpp
${_drpc}/serialization.cpp
)
if (WIN32)
list(APPEND _drpc_src ${_drpc}/connection_win.cpp ${_drpc}/discord_register_win.cpp)
elseif (APPLE)
list(APPEND _drpc_src ${_drpc}/connection_unix.cpp ${_drpc}/discord_register_osx.m)
else ()
list(APPEND _drpc_src ${_drpc}/connection_unix.cpp ${_drpc}/discord_register_linux.cpp)
endif ()
add_library(discord-rpc STATIC ${_drpc_src})
target_include_directories(discord-rpc PUBLIC
${discord_rpc_SOURCE_DIR}/include
${rapidjson_SOURCE_DIR}/include
)
if (UNIX)
target_link_libraries(discord-rpc PUBLIC pthread)
endif ()
endif ()
list(APPEND GAME_LIBS discord-rpc)
list(APPEND GAME_COMPILE_DEFS DUSK_DISCORD_RPC=1)
endif ()
# Edit & Continue
if (MSVC)
if ("${CMAKE_MSVC_DEBUG_INFORMATION_FORMAT}" STREQUAL "" AND CMAKE_BUILD_TYPE STREQUAL "Debug")
@@ -332,47 +379,65 @@ 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
add_library(game_debug OBJECT ${JSYSTEM_DEBUG_FILES} ${SSYSTEM_FILES}
set(GAME_DEBUG_FILES
${SSYSTEM_FILES}
src/dusk/audio/DuskAudioSystem.cpp
src/dusk/audio/JASCriticalSection.cpp
src/dusk/audio/DuskDsp.cpp
src/dusk/audio/Adpcm.cpp
src/dusk/audio/DspStub.cpp
src/dusk/imgui/ImGuiAudio.cpp)
src/dusk/imgui/ImGuiAudio.cpp
)
set_source_files_properties(
${GAME_DEBUG_FILES}
PROPERTIES
COMPILE_DEFINITIONS "$<$<CONFIG:Debug>:DEBUG=1>;$<$<CONFIG:Debug>:PARTIAL_DEBUG=1>"
)
# game_base is for all other game code files
add_library(game_base OBJECT ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${JSYSTEM_FILES} ${REL_FILES} ${DUSK_FILES} ${DOLPHIN_FILES})
set(GAME_BASE_FILES
${DOLZEL_FILES}
${Z2AUDIOLIB_FILES}
${REL_FILES}
${DUSK_FILES}
${DOLPHIN_FILES}
)
set_source_files_properties(
${GAME_BASE_FILES}
PROPERTIES
COMPILE_DEFINITIONS "NDEBUG=1;NDEBUG_DEFINED=1;DEBUG_DEFINED=0;$<$<CONFIG:Debug>:PARTIAL_DEBUG=1>"
)
target_compile_definitions(game_debug PRIVATE ${GAME_COMPILE_DEFS} $<$<CONFIG:Debug>:DEBUG=1> $<$<CONFIG:Debug>:PARTIAL_DEBUG=1>)
target_compile_definitions(game_base PRIVATE ${GAME_COMPILE_DEFS} NDEBUG=1 NDEBUG_DEFINED=1 DEBUG_DEFINED=0 $<$<CONFIG:Debug>:PARTIAL_DEBUG=1>)
foreach(jsystem_lib IN LISTS JSYSTEM_LIBRARIES)
target_compile_definitions(${jsystem_lib} PRIVATE
${GAME_COMPILE_DEFS}
$<$<CONFIG:Debug>:DEBUG=1>
$<$<CONFIG:Debug>:PARTIAL_DEBUG=1>
)
target_include_directories(${jsystem_lib} PRIVATE ${GAME_INCLUDE_DIRS})
target_link_libraries(${jsystem_lib} PRIVATE ${GAME_LIBS})
set_target_properties(${jsystem_lib} PROPERTIES FOLDER "JSystem")
endforeach()
# only apply PCH to game_base since not all headers are necessarily validated with DEBUG=1
target_precompile_headers(game_base PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_SOURCE_DIR}/include/dusk_pch.hpp>")
target_include_directories(game_debug PRIVATE ${GAME_INCLUDE_DIRS})
target_include_directories(game_base PRIVATE ${GAME_INCLUDE_DIRS})
# This implicitly pulls in the library include directories even though no
# linking actually takes place for object libraries
target_link_libraries(game_debug PRIVATE ${GAME_LIBS})
target_link_libraries(game_base PRIVATE ${GAME_LIBS})
# Combined game library
add_library(game STATIC
$<TARGET_OBJECTS:game_base>
$<TARGET_OBJECTS:game_debug>)
target_link_libraries(game PUBLIC ${GAME_LIBS})
if(ANDROID)
add_library(dusk SHARED src/dusk/main.cpp)
set_target_properties(dusk PROPERTIES OUTPUT_NAME main)
else ()
add_executable(dusk src/dusk/main.cpp)
set(JSYSTEM_LINK_LIBRARIES ${JSYSTEM_LIBRARIES})
if (CMAKE_CXX_LINK_GROUP_USING_RESCAN_SUPPORTED OR CMAKE_LINK_GROUP_USING_RESCAN_SUPPORTED)
# GNU ld resolves static archives in a single left-to-right pass. The split
# JSystem libraries reference each other, so they need a RESCAN group there.
set(JSYSTEM_LINK_LIBRARIES "$<LINK_GROUP:RESCAN,${JSYSTEM_LIBRARIES}>")
endif ()
target_compile_definitions(dusk PRIVATE TARGET_PC AVOID_UB=1 VERSION=0)
target_include_directories(dusk PRIVATE include)
target_link_libraries(dusk PRIVATE game aurora::main)
set(DUSK_FILES src/dusk/main.cpp ${GAME_BASE_FILES} ${GAME_DEBUG_FILES})
if(ANDROID)
add_library(dusk SHARED ${DUSK_FILES})
set_target_properties(dusk PROPERTIES OUTPUT_NAME main)
else ()
add_executable(dusk ${DUSK_FILES})
endif ()
target_compile_definitions(dusk PRIVATE ${GAME_COMPILE_DEFS})
target_include_directories(dusk PRIVATE ${GAME_INCLUDE_DIRS})
target_link_libraries(dusk PRIVATE aurora::main ${GAME_LIBS} ${JSYSTEM_LINK_LIBRARIES})
target_precompile_headers(dusk PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_SOURCE_DIR}/include/dusk_pch.hpp>")
if (TARGET crashpad_handler)
add_dependencies(dusk crashpad_handler)
endif ()
+4 -1
View File
@@ -358,7 +358,10 @@
"inherits": [
"relwithdebinfo",
"ci"
]
],
"cacheVariables": {
"AURORA_SDL3_PROVIDER": "vendor"
}
},
{
"name": "x-linux-ci-gcc",
+6 -15
View File
@@ -10,28 +10,19 @@
First make sure your dump of the game is clean and supported by Dusk. You can do this by checking the sha1 hash of your dump against this list of supported versions.
| Version | sha1 hash |
| ------------ | ---------------------------------------- |
|--------------| ---------------------------------------- |
| GameCube USA | 75edd3ddff41f125d1b4ce1a40378f1b565519e7 |
| GameCube PAL | 2601822a488eeb86fb89db16ca8f29c2c953e1ca |
### 2. Download [Dusk](https://github.com/TwilitRealm/dusk/releases)
### 3. Setup the game
#### Windows
- Extract the zip folder
- Place your dump of the game into the same folder where you extracted to
- Launch `dusk.exe`
- Launch Dusk
- Select Options, then set the ISO Path to your supported game dump
- Press Start Game to play!
#### macOS
- TODO
#### Linux
- TODO
#### iOS
- TODO
#### android
- TODO
![DuskOptions](assets/dusk_options.png)
# Building
If you'd like to build Dusk from source, please read the [build instructions](docs/building.md).
Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

+1 -1
+85 -6
View File
@@ -15,7 +15,6 @@ set(DOLZEL_FILES
src/m_Do/m_Do_DVDError.cpp
src/m_Do/m_Do_MemCard.cpp
src/m_Do/m_Do_MemCardRWmng.cpp
src/m_Do/m_Do_machine_exception.cpp
src/m_Do/m_Do_hostIO.cpp
src/c/c_damagereaction.cpp
src/c/c_dylink.cpp
@@ -315,7 +314,7 @@ set(SSYSTEM_FILES
src/SSystem/SStandard/s_basic.cpp
)
set(JSYSTEM_DEBUG_FILES
add_library(JSystem_JParticle STATIC
libs/JSystem/src/JParticle/JPAResourceManager.cpp
libs/JSystem/src/JParticle/JPAResource.cpp
libs/JSystem/src/JParticle/JPABaseShape.cpp
@@ -331,10 +330,19 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/JParticle/JPAEmitter.cpp
libs/JSystem/src/JParticle/JPAParticle.cpp
libs/JSystem/src/JParticle/JPAMath.cpp
)
add_library(JSystem_JFramework STATIC
libs/JSystem/src/JFramework/JFWSystem.cpp
libs/JSystem/src/JFramework/JFWDisplay.cpp
)
add_library(JSystem_J3DU STATIC
libs/JSystem/src/J3DU/J3DUClipper.cpp
libs/JSystem/src/J3DU/J3DUDL.cpp
)
add_library(JSystem_JKernel STATIC
libs/JSystem/src/JKernel/JKRHeap.cpp
libs/JSystem/src/JKernel/JKRExpHeap.cpp
libs/JSystem/src/JKernel/JKRSolidHeap.cpp
@@ -360,14 +368,23 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/JKernel/JKRDvdRipper.cpp
libs/JSystem/src/JKernel/JKRDvdAramRipper.cpp
libs/JSystem/src/JKernel/JKRDecomp.cpp
)
add_library(JSystem_JMath STATIC
libs/JSystem/src/JMath/JMath.cpp
libs/JSystem/src/JMath/random.cpp
libs/JSystem/src/JMath/JMATrigonometric.cpp
)
add_library(JSystem_JSupport STATIC
libs/JSystem/src/JSupport/JSUList.cpp
libs/JSystem/src/JSupport/JSUInputStream.cpp
libs/JSystem/src/JSupport/JSUOutputStream.cpp
libs/JSystem/src/JSupport/JSUMemoryStream.cpp
libs/JSystem/src/JSupport/JSUFileStream.cpp
)
add_library(JSystem_JUtility STATIC
libs/JSystem/src/JUtility/JUTCacheFont.cpp
libs/JSystem/src/JUtility/JUTResource.cpp
libs/JSystem/src/JUtility/JUTTexture.cpp
@@ -388,6 +405,9 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/JUtility/JUTConsole.cpp
libs/JSystem/src/JUtility/JUTDirectFile.cpp
libs/JSystem/src/JUtility/JUTFontData_Ascfont_fix12.cpp
)
add_library(JSystem_JStage STATIC
libs/JSystem/src/JStage/JSGActor.cpp
libs/JSystem/src/JStage/JSGAmbientLight.cpp
libs/JSystem/src/JStage/JSGCamera.cpp
@@ -395,6 +415,9 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/JStage/JSGLight.cpp
libs/JSystem/src/JStage/JSGObject.cpp
libs/JSystem/src/JStage/JSGSystem.cpp
)
add_library(JSystem_J2DGraph STATIC
libs/JSystem/src/J2DGraph/J2DGrafContext.cpp
libs/JSystem/src/J2DGraph/J2DOrthoGraph.cpp
libs/JSystem/src/J2DGraph/J2DTevs.cpp
@@ -413,6 +436,9 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/J2DGraph/J2DAnmLoader.cpp
libs/JSystem/src/J2DGraph/J2DAnimation.cpp
libs/JSystem/src/J2DGraph/J2DManage.cpp
)
add_library(JSystem_J3DGraphBase STATIC
libs/JSystem/src/J3DGraphBase/J3DGD.cpp
libs/JSystem/src/J3DGraphBase/J3DSys.cpp
libs/JSystem/src/J3DGraphBase/J3DVertex.cpp
@@ -427,6 +453,9 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/J3DGraphBase/J3DTevs.cpp
libs/JSystem/src/J3DGraphBase/J3DDrawBuffer.cpp
libs/JSystem/src/J3DGraphBase/J3DStruct.cpp
)
add_library(JSystem_J3DGraphAnimator STATIC
libs/JSystem/src/J3DGraphAnimator/J3DShapeTable.cpp
libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp
libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp
@@ -438,6 +467,9 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/J3DGraphAnimator/J3DCluster.cpp
libs/JSystem/src/J3DGraphAnimator/J3DJoint.cpp
libs/JSystem/src/J3DGraphAnimator/J3DMaterialAttach.cpp
)
add_library(JSystem_J3DGraphLoader STATIC
libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory.cpp
libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory_v21.cpp
libs/JSystem/src/J3DGraphLoader/J3DClusterLoader.cpp
@@ -446,6 +478,9 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/J3DGraphLoader/J3DJointFactory.cpp
libs/JSystem/src/J3DGraphLoader/J3DShapeFactory.cpp
libs/JSystem/src/J3DGraphLoader/J3DAnmLoader.cpp
)
add_library(JSystem_JStudio STATIC
libs/JSystem/src/JStudio/JStudio/ctb.cpp
libs/JSystem/src/JStudio/JStudio/ctb-data.cpp
libs/JSystem/src/JStudio/JStudio/functionvalue.cpp
@@ -460,6 +495,9 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/JStudio/JStudio/stb.cpp
libs/JSystem/src/JStudio/JStudio/stb-data-parse.cpp
libs/JSystem/src/JStudio/JStudio/stb-data.cpp
)
add_library(JSystem_JStudio_JStage STATIC
libs/JSystem/src/JStudio/JStudio_JStage/control.cpp
libs/JSystem/src/JStudio/JStudio_JStage/object.cpp
libs/JSystem/src/JStudio/JStudio_JStage/object-actor.cpp
@@ -467,10 +505,19 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/JStudio/JStudio_JStage/object-camera.cpp
libs/JSystem/src/JStudio/JStudio_JStage/object-fog.cpp
libs/JSystem/src/JStudio/JStudio_JStage/object-light.cpp
)
add_library(JSystem_JStudio_JAudio2 STATIC
libs/JSystem/src/JStudio/JStudio_JAudio2/control.cpp
libs/JSystem/src/JStudio/JStudio_JAudio2/object-sound.cpp
)
add_library(JSystem_JStudio_JParticle STATIC
libs/JSystem/src/JStudio/JStudio_JParticle/control.cpp
libs/JSystem/src/JStudio/JStudio_JParticle/object-particle.cpp
)
add_library(JSystem_JAudio2 STATIC
libs/JSystem/src/JAudio2/JASCalc.cpp
libs/JSystem/src/JAudio2/JASTaskThread.cpp
libs/JSystem/src/JAudio2/JASDvdThread.cpp
@@ -535,22 +582,34 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/JAudio2/JAUSoundAnimator.cpp
libs/JSystem/src/JAudio2/JAUSoundTable.cpp
libs/JSystem/src/JAudio2/JAUStreamFileTable.cpp
)
add_library(JSystem_JMessage STATIC
libs/JSystem/src/JMessage/control.cpp
libs/JSystem/src/JMessage/data.cpp
libs/JSystem/src/JMessage/processor.cpp
libs/JSystem/src/JMessage/resource.cpp
libs/JSystem/src/JMessage/locale.cpp
)
add_library(JSystem_JGadget STATIC
libs/JSystem/src/JGadget/binary.cpp
libs/JSystem/src/JGadget/define.cpp
libs/JSystem/src/JGadget/linklist.cpp
libs/JSystem/src/JGadget/search.cpp
libs/JSystem/src/JGadget/std-vector.cpp
)
add_library(JSystem_JAHostIO STATIC
libs/JSystem/src/JAHostIO/JAHFrameNode.cpp
libs/JSystem/src/JAHostIO/JAHioMessage.cpp
libs/JSystem/src/JAHostIO/JAHioMgr.cpp
libs/JSystem/src/JAHostIO/JAHioNode.cpp
libs/JSystem/src/JAHostIO/JAHioUtil.cpp
libs/JSystem/src/JAHostIO/JAHVirtualNode.cpp
)
add_library(JSystem_JHostIO STATIC
libs/JSystem/src/JHostIO/JORFile.cpp
libs/JSystem/src/JHostIO/JORHostInfo.cpp
libs/JSystem/src/JHostIO/JORMessageBox.cpp
@@ -560,7 +619,28 @@ set(JSYSTEM_DEBUG_FILES
libs/JSystem/src/JHostIO/JHIMccBuf.cpp
)
set(JSYSTEM_FILES
set(JSYSTEM_LIBRARIES
JSystem_JParticle
JSystem_JFramework
JSystem_J3DU
JSystem_JKernel
JSystem_JMath
JSystem_JSupport
JSystem_JUtility
JSystem_JStage
JSystem_J2DGraph
JSystem_J3DGraphBase
JSystem_J3DGraphAnimator
JSystem_J3DGraphLoader
JSystem_JStudio
JSystem_JStudio_JStage
JSystem_JStudio_JAudio2
JSystem_JStudio_JParticle
JSystem_JAudio2
JSystem_JMessage
JSystem_JGadget
JSystem_JAHostIO
JSystem_JHostIO
)
set(REL_FILES
@@ -1342,13 +1422,13 @@ set(DUSK_FILES
src/dusk/crash_reporting.cpp
src/dusk/endian.cpp
src/dusk/extras.c
src/dusk/extras.cpp
src/dusk/file_select.cpp
src/dusk/file_select.hpp
src/dusk/frame_interpolation.cpp
src/dusk/game_clock.cpp
src/dusk/globals.cpp
src/dusk/gyro.cpp
src/dusk/gamepad_color.cpp
src/dusk/io.cpp
src/dusk/layout.cpp
src/dusk/logging.cpp
@@ -1366,8 +1446,6 @@ set(DUSK_FILES
src/dusk/imgui/ImGuiBloomWindow.hpp
src/dusk/imgui/ImGuiMenuTools.cpp
src/dusk/imgui/ImGuiMenuTools.hpp
src/dusk/imgui/ImGuiMenuEnhancements.cpp
src/dusk/imgui/ImGuiMenuEnhancements.hpp
src/dusk/imgui/ImGuiPreLaunchWindow.cpp
src/dusk/imgui/ImGuiPreLaunchWindow.hpp
src/dusk/imgui/ImGuiFirstRunPreset.hpp
@@ -1387,4 +1465,5 @@ set(DUSK_FILES
src/dusk/OSContext.cpp
src/dusk/OSThread.cpp
src/dusk/OSMutex.cpp
src/dusk/discord_presence.cpp
)
+9
View File
@@ -220,6 +220,15 @@ public:
/* 0x17E2 */ s16 wait_roll_angle; ///< @brief Roll angle during wait state.
/* 0x17E4 */ u8 field_0x17e4[0x17e8 - 0x17e4];
/* 0x17E8 */ f32 ride_speed_max; ///< @brief Speed rate for riding calculations.
#if TARGET_PC
cXyz himo_mat_interp_prev[2][16];
cXyz himo_mat_interp_curr[2][16];
cXyz himo_tex_interp_prev[2];
cXyz himo_tex_interp_curr[2];
bool himo_interp_prev_valid;
bool himo_interp_curr_valid;
s8 demo_cam_sync_ticks;
#endif
};
STATIC_ASSERT(sizeof(e_wb_class) == 0x17EC);
+3
View File
@@ -25,6 +25,9 @@ public:
/* 0x164 */ cXyz mMinVal;
/* 0x170 */ cXyz mMaxVal;
/* 0x17C */ cXyz mViewScale;
#if TARGET_PC
bool mbReset = false;
#endif
};
/**
+6
View File
@@ -94,6 +94,12 @@ static void __THPAudioInitialize(THPAudioDecodeInfo* info, u8* ptr);
#define THP_TEXTURE_SET_COUNT 3
#endif
#if TARGET_PC
namespace dusk {
void MoviePlayerShutdown();
}
#endif
struct daMP_THPPlayer {
/* 0x000 */ DVDFileInfo fileInfo;
/* 0x03C */ THPHeader header;
+2 -4
View File
@@ -68,10 +68,8 @@ public:
/* 0x904 */ cXyz field_0x904[2];
/* 0x91C */ int field_0x91c;
/* 0x920 */ cXyz field_0x920[63];
/* 0xC14 */ f32 field_0xc14[4];
/* 0xC24 */ u8 field_0xc24[0xd10 - 0xc24];
/* 0xD10 */ s8 field_0xd10[4];
/* 0xD14 */ u8 field_0xd14[0xd50 - 0xd14];
/* 0xC14 */ f32 field_0xc14[63];
/* 0xD10 */ s8 field_0xd10[64];
/* 0xD50 */ mDoExt_3DlineMat1_c field_0xd50;
/* 0xD8C */ int field_0xd8c;
};
+2 -4
View File
@@ -4834,8 +4834,7 @@ inline void dComIfGd_drawXluListDark() {
inline void dComIfGd_drawXluListInvisible() {
ZoneScoped;
#ifdef TARGET_PC
if (dusk::getSettings().game.enableWaterRefraction &&
!dusk::getSettings().game.enableFrameInterpolation) {
if (!dusk::getSettings().game.disableWaterRefraction) {
#endif
g_dComIfG_gameInfo.drawlist.drawXluListInvisible();
#ifdef TARGET_PC
@@ -4846,8 +4845,7 @@ inline void dComIfGd_drawXluListInvisible() {
inline void dComIfGd_drawOpaListInvisible() {
ZoneScoped;
#ifdef TARGET_PC
if (dusk::getSettings().game.enableWaterRefraction &&
!dusk::getSettings().game.enableFrameInterpolation) {
if (!dusk::getSettings().game.disableWaterRefraction) {
#endif
g_dComIfG_gameInfo.drawlist.drawOpaListInvisible();
#ifdef TARGET_PC
+4
View File
@@ -209,6 +209,10 @@ public:
/* 0x04 */ TGXTexObj* mpTexObj;
/* 0x08 */ Mtx mVolumeMtx;
/* 0x38 */ Mtx mMtx;
#if TARGET_PC
const void* mVolumeMtxKey;
const void* mMtxKey;
#endif
}; // Size: 0x68
struct cBgD_Vtx_t;
+16
View File
@@ -10,6 +10,7 @@
#include "JSystem/J3DGraphLoader/J3DAnmLoader.h"
class dFile_info_c;
class J2DPicture;
class dDlst_FileSel_c : public dDlst_base_c {
public:
@@ -113,6 +114,14 @@ public:
/* 0x04 */ J2DScreen* Scr3m;
};
class dDlst_FileSelFade_c : public dDlst_base_c {
public:
void draw();
virtual ~dDlst_FileSelFade_c() {}
/* 0x04 */ J2DPicture* mpPict;
};
class dFs_HIO_c : public JORReflexible {
public:
dFs_HIO_c();
@@ -676,6 +685,9 @@ public:
#if PLATFORM_GCN
/* 0x2378 */ J2DPicture* mpFadePict;
#endif
#ifdef TARGET_PC
dDlst_FileSelFade_c mFadeDlst;
#endif
#if PLATFORM_WII || PLATFORM_SHIELD
/* 0x2376 */ u8 field_0x2376[SAVEFILE_SIZE];
@@ -684,6 +696,10 @@ public:
#endif
};
#ifdef TARGET_PC
STATIC_ASSERT(sizeof(dFile_select_c) == 0x237C + sizeof(dDlst_FileSelFade_c));
#else
STATIC_ASSERT(sizeof(dFile_select_c) == 0x237C);
#endif
#endif /* D_FILE_D_FILE_SELECT_H */
+4
View File
@@ -103,6 +103,10 @@ public:
field_0xd98 = param_1;
}
#if TARGET_PC
void resetScrollArrowMask() { field_0xdda = 0; }
#endif
/* 0xC98 */ JKRExpHeap* mpHeap;
/* 0xC9C */ JKRExpHeap* mpTalkHeap;
/* 0xCA0 */ STControl* mpStick;
+3 -1
View File
@@ -75,7 +75,9 @@ public:
/* 0x8 */ BE(u16) mAreaName;
/* 0xA */ u8 mCount;
#ifdef _MSVC_LANG
u8* __get_mRoomNos() const { return (u8*)(this + 1); }
// Room numbers start at offset 0xB (right after mCount), NOT at sizeof(data)=12.
// (u8*)(this+1) would give offset 12 because MSVC sizeof=12; use &mCount+1 instead.
u8* __get_mRoomNos() const { return (u8*)&mCount + 1; }
__declspec(property(get = __get_mRoomNos)) u8* mRoomNos;
#else
/* 0xB */ u8 mRoomNos[0];
+9
View File
@@ -206,6 +206,15 @@ private:
/* 0x6D3 */ u8 field_0x6d3;
#if TARGET_PC
f32 mSelectItemSlideElapsed[4];
f32 mCursorInterpPrevX;
f32 mCursorInterpPrevY;
f32 mCursorInterpCurrX;
f32 mCursorInterpCurrY;
s16 mCursorInterpPrevAngle;
s16 mCursorInterpCurrAngle;
bool mCursorInterpPrevAngular;
bool mCursorInterpCurrAngular;
bool mCursorInterpInit;
#endif
};
+10
View File
@@ -47,6 +47,13 @@ public:
mPositionY = y;
}
#ifdef TARGET_PC
f32 getPositionX() const { return mPositionX; }
f32 getPositionY() const { return mPositionY; }
void refreshAspectScale();
#endif
void onUpdateFlag() { mUpdateFlag = true; }
void resetUpdateFlag() { mUpdateFlag = false; }
@@ -79,6 +86,9 @@ private:
/* 0x58 */ f32 mPositionX;
/* 0x5C */ f32 mPositionY;
/* 0x60 */ f32 mParam1;
#ifdef TARGET_PC
f32 mBaseParam1;
#endif
/* 0x64 */ f32 mParam2;
/* 0x68 */ f32 mParam3;
/* 0x6C */ f32 mParam4;
+2
View File
@@ -12,6 +12,8 @@ namespace dusk::audio {
void SetMasterVolume(f32 value);
void SetPaused(bool paused);
u32 GetResetCount(int channelIdx);
f32 VolumeFromU16(u16 value);
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#ifdef DUSK_DISCORD_RPC
namespace dusk {
namespace discord {
void Initialize();
void RunCallbacks();
void UpdatePresence();
void Shutdown();
}
}
#endif // DUSK_DISCORD_RPC
-1
View File
@@ -6,7 +6,6 @@
#include "aurora/gfx.h"
extern AuroraInfo auroraInfo;
extern const char* configPath;
namespace dusk {
extern AuroraStats lastFrameAuroraStats;
+18 -21
View File
@@ -1,5 +1,4 @@
#ifndef DUSK_FRAME_INTERP_H
#define DUSK_FRAME_INTERP_H
#pragma once
#include <dolphin/mtx.h>
#include <stdbool.h>
@@ -7,6 +6,7 @@
#include <stdint.h>
class camera_process_class;
class view_class;
#ifdef __cplusplus
namespace dusk {
@@ -16,40 +16,37 @@ void ensure_initialized();
void begin_record();
void end_record();
void interpolate(float step);
void begin_sim_tick();
void begin_frame(bool enabled, bool is_sim_frame, float step);
void interpolate();
float get_interpolation_step();
void request_presentation_sync();
bool presentation_sync_active();
bool is_enabled();
// TODO: These should be phased out as UI is progressively updated to use game_clock
void set_ui_tick_pending(bool value);
bool get_ui_tick_pending();
void open_child(const void* key, int32_t id);
void close_child();
void record_camera(::camera_process_class* cam, int camera_id);
void record_final_mtx_raw(const Mtx* dest, const Mtx src);
void record_final_mtx_raw_tagged(const Mtx* dest, const Mtx src, uint64_t stable_tag);
bool is_sim_frame();
bool lookup_replacement(const void* source, Mtx out);
void record_camera(::camera_process_class* cam, int camera_id);
void interp_view(::view_class* view);
void record_final_mtx(Mtx m, const void *key);
void record_final_mtx(Mtx m);
bool lookup_replacement(const void* key, Mtx out);
bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out);
typedef void (*InterpolationCallBack)(bool isSimFrame, void* pUserWork);
// call on a sim tick, will get called during presentation
void add_interpolation_callback(InterpolationCallBack pCallBack, void* pUserWork);
void begin_presentation_camera();
void end_presentation_camera();
struct PresentationCameraScope {
PresentationCameraScope() { begin_presentation_camera(); }
~PresentationCameraScope() { end_presentation_camera(); }
PresentationCameraScope(const PresentationCameraScope&) = delete;
PresentationCameraScope& operator=(const PresentationCameraScope&) = delete;
PresentationCameraScope(PresentationCameraScope&&) = delete;
PresentationCameraScope& operator=(PresentationCameraScope&&) = delete;
};
uint64_t alloc_simple_shadow_pair_base();
} // namespace frame_interp
} // namespace dusk
#endif
#endif
+7 -13
View File
@@ -1,13 +1,9 @@
#ifndef DUSK_GAME_CLOCK_H
#define DUSK_GAME_CLOCK_H
#pragma once
#include <stddef.h>
namespace dusk {
namespace game_clock {
namespace dusk::game_clock {
void ensure_initialized();
void reset_accumulator();
void reset_frame_timer();
constexpr float sim_pace() { return 1.0f / 30.0f; }
constexpr float period_for_original_frames(float frame_count) { return frame_count * sim_pace(); }
@@ -17,16 +13,14 @@ constexpr float ui_initial_dt() { return 1.0f / 60.0f; }
struct MainLoopPacer {
float presentation_dt_seconds;
bool is_interpolating;
bool do_sim_tick;
float interpolation_step;
int sim_ticks_to_run;
float sim_pace;
};
MainLoopPacer advance_main_loop();
void commit_sim_tick();
float sample_interpolation_step();
float consume_interval(const void* consumer);
} // namespace game_clock
} // namespace dusk
#endif // DUSK_GAME_CLOCK_H
} // namespace dusk::game_clock
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#ifndef GAMEPAD_COLOR_H
#define GAMEPAD_COLOR_H
void handleGamepadColor();
#endif
+3 -1
View File
@@ -4,10 +4,12 @@
#include <aurora/aurora.h>
#include <aurora/lib/logging.hpp>
#include <filesystem>
void aurora_log_callback(AuroraLogLevel level, const char* module, const char* message, unsigned int len);
namespace dusk {
void InitializeFileLogging(const char* configDir, AuroraLogLevel logLevel);
void InitializeFileLogging(const std::filesystem::path& configDir, AuroraLogLevel logLevel);
void ShutdownFileLogging();
const char* GetLogFilePath();
void SendToStubLog(AuroraLogLevel level, const char* module, const char* message);
+4
View File
@@ -1,10 +1,14 @@
#ifndef DUSK_MAIN_H
#define DUSK_MAIN_H
#include <filesystem>
namespace dusk {
extern bool IsRunning;
extern bool IsShuttingDown;
extern bool IsGameLaunched;
extern bool IsFocusPaused;
extern std::filesystem::path ConfigPath;
}
#endif // DUSK_MAIN_H
+8 -1
View File
@@ -68,14 +68,18 @@ struct UserSettings {
ConfigVar<bool> enableMirrorMode;
ConfigVar<bool> invertCameraXAxis;
ConfigVar<bool> disableMainHUD;
ConfigVar<bool> pauseOnFocusLost;
ConfigVar<bool> enableLinkDollRotation;
// Graphics
ConfigVar<BloomMode> bloomMode;
ConfigVar<float> bloomMultiplier;
ConfigVar<bool> enableWaterRefraction;
ConfigVar<bool> disableWaterRefraction;
ConfigVar<bool> enableFrameInterpolation;
ConfigVar<int> internalResolutionScale;
ConfigVar<int> shadowResolutionMultiplier;
ConfigVar<bool> enableDepthOfField;
// Audio
ConfigVar<bool> noLowHpSound;
@@ -99,6 +103,7 @@ struct UserSettings {
ConfigVar<bool> infiniteOil;
ConfigVar<bool> infiniteOxygen;
ConfigVar<bool> infiniteRupees;
ConfigVar<bool> enableIndefiniteItemDrops;
ConfigVar<bool> moonJump;
ConfigVar<bool> superClawshot;
ConfigVar<bool> alwaysGreatspin;
@@ -122,6 +127,7 @@ struct UserSettings {
ConfigVar<bool> wasPresetChosen;
ConfigVar<bool> enableCrashReporting;
ConfigVar<bool> duskMenuOpen;
ConfigVar<int> cardFileType;
} backend;
};
@@ -146,6 +152,7 @@ struct TransientSettings {
CollisionViewSettings collisionView;
bool skipFrameRateLimit;
bool moveLinkActive;
bool stateShareLoadActive;
};
TransientSettings& getTransientSettings();
+25 -25
View File
@@ -1,9 +1,10 @@
#ifndef DUSK_TIME_H
#define DUSK_TIME_H
#include <chrono>
#include <numeric>
#include <array>
#include <numeric>
#include "SDL3/SDL_timer.h"
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
@@ -15,28 +16,26 @@
#include <Windows.h>
#include <shellapi.h>
#include <intrin.h>
#else
#include "SDL3/SDL_timer.h"
#endif
class Limiter {
using delta_clock = std::chrono::high_resolution_clock;
using duration_t = std::chrono::nanoseconds;
public:
void Reset() { m_oldTime = delta_clock::now(); }
using duration_t = Uint64;
void Reset() { m_oldTime = SDL_GetTicksNS(); }
void Sleep(duration_t targetFrameTime) {
if (targetFrameTime.count() == 0) {
if (targetFrameTime == 0) {
return;
}
auto start = delta_clock::now();
const Uint64 start = SDL_GetTicksNS();
duration_t adjustedSleepTime = SleepTime(targetFrameTime);
if (adjustedSleepTime.count() > 0) {
if (adjustedSleepTime > 0) {
NanoSleep(adjustedSleepTime);
duration_t overslept = TimeSince(start) - adjustedSleepTime;
if (overslept < duration_t{targetFrameTime}) {
const duration_t elapsed = TimeSince(start);
const duration_t overslept = elapsed > adjustedSleepTime ? elapsed - adjustedSleepTime : 0;
if (overslept < targetFrameTime) {
m_overheadTimes[m_overheadTimeIdx] = overslept;
m_overheadTimeIdx = (m_overheadTimeIdx + 1) % m_overheadTimes.size();
}
@@ -45,23 +44,23 @@ public:
}
duration_t SleepTime(duration_t targetFrameTime) {
const auto sleepTime = duration_t{targetFrameTime} - TimeSince(m_oldTime);
m_overhead = std::accumulate(m_overheadTimes.begin(), m_overheadTimes.end(), duration_t{}) / m_overheadTimes.size();
const duration_t elapsed = TimeSince(m_oldTime);
const duration_t sleepTime = elapsed < targetFrameTime ? targetFrameTime - elapsed : 0;
m_overhead = std::accumulate(m_overheadTimes.begin(), m_overheadTimes.end(), duration_t{0}) /
m_overheadTimes.size();
if (sleepTime > m_overhead) {
return sleepTime - m_overhead;
}
return duration_t{0};
return 0;
}
private:
delta_clock::time_point m_oldTime;
Uint64 m_oldTime = 0;
std::array<duration_t, 4> m_overheadTimes{};
size_t m_overheadTimeIdx = 0;
duration_t m_overhead = duration_t{0};
duration_t m_overhead = 0;
duration_t TimeSince(delta_clock::time_point start) {
return std::chrono::duration_cast<duration_t>(delta_clock::now() - start);
}
duration_t TimeSince(Uint64 start) const { return SDL_GetTicksNS() - start; }
#if _WIN32
void NanoSleep(const duration_t duration) {
@@ -85,9 +84,10 @@ private:
LARGE_INTEGER start, current;
QueryPerformanceCounter(&start);
LONGLONG ticksToWait = static_cast<LONGLONG>(duration.count() * countPerNs);
if (DWORD ms = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); ms > 1) {
::Sleep(ms - 1);
const LONGLONG ticksToWait = static_cast<LONGLONG>(duration * countPerNs);
const Uint64 ms = duration / 1'000'000ULL;
if (ms > 1) {
::Sleep(static_cast<DWORD>(ms - 1));
}
do {
QueryPerformanceCounter(&current);
@@ -99,7 +99,7 @@ private:
} while (current.QuadPart - start.QuadPart < ticksToWait);
}
#else
void NanoSleep(const duration_t duration) { SDL_DelayPrecise(duration.count()); }
void NanoSleep(const duration_t duration) { SDL_DelayPrecise(duration); }
#endif
};
+1 -1
View File
@@ -25,7 +25,7 @@ typedef struct leafdraw_class : base_process_class {
#endif
/* 0xB8 */ leafdraw_method_class* leaf_methods;
/* 0xBC */ s8 unk_0xBC;
/* 0xBD */ u8 unk_0xBD;
/* 0xBD */ u8 draw_interp_frame;
/* 0xBE */ draw_priority_class draw_priority;
} leafdraw_class;
+1
View File
@@ -18,6 +18,7 @@ typedef struct process_node_class {
/* 0x0BC */ layer_class layer;
/* 0x0E8 */ node_list_class layer_nodelist[16];
/* 0x1A8 */ s8 unk_0x1A8;
/* 0x1A9 */ s8 draw_interp_frame;
} process_node_class;
typedef struct node_process_profile_definition {
+11 -1
View File
@@ -73,6 +73,9 @@
#endif
#ifndef __MWERKS__
#ifdef __cplusplus
extern "C" {
#endif
// Silence clangd errors about MWCC PPC intrinsics by declaring them here.
extern int __cntlzw(unsigned int);
extern int __rlwimi(int, int, int, int, int);
@@ -80,7 +83,14 @@ extern void __dcbf(void*, int);
extern void __dcbz(void*, int);
extern void __sync();
extern int __abs(int);
void* __memcpy(void*, const void*, int);
#if defined(__has_builtin) && __has_builtin(__builtin_memcpy)
#define __memcpy __builtin_memcpy
#else
#define __memcpy memcpy
#endif
#ifdef __cplusplus
}
#endif
#endif
#ifndef M_PI
@@ -79,6 +79,10 @@ public:
virtual void viewCalc();
virtual ~J3DModel() {}
#if TARGET_PC
static void interp_callback(bool isSimFrame, void* pUserWork);
#endif
J3DModelData* getModelData() { return mModelData; }
void onFlag(u32 flag) { mFlags |= flag; }
@@ -105,9 +109,7 @@ public:
void setAnmMtx(int jointNo, Mtx m) {
mMtxBuffer->setAnmMtx(jointNo, m);
#ifdef TARGET_PC
dusk::frame_interp::record_final_mtx_raw(
reinterpret_cast<const Mtx*>(mMtxBuffer->getAnmMtx(jointNo)),
mMtxBuffer->getAnmMtx(jointNo));
dusk::frame_interp::record_final_mtx(mMtxBuffer->getAnmMtx(jointNo));
#endif
}
MtxP getAnmMtx(int jointNo) { return mMtxBuffer->getAnmMtx(jointNo); }
@@ -23,6 +23,10 @@ public:
void syncJ3DSysPointers() const;
void syncJ3DSysFlags() const;
#if TARGET_PC
bool needsInterpCallBack() const;
#endif
virtual ~J3DModelData() {}
void simpleCalcMaterial(Mtx mtx) { simpleCalcMaterial(0, mtx); }
@@ -33,6 +33,9 @@ public:
void copy(J3DMaterial*);
s32 newSharedDisplayList(u32);
s32 newSingleSharedDisplayList(u32);
#if TARGET_PC
bool needsInterpCallBack() const;
#endif
virtual void calc(f32 const (*)[4]);
virtual void calcDiffTexMtx(f32 const (*)[4]);
@@ -46,7 +49,6 @@ public:
virtual void change();
J3DMaterial() { initialize(); }
~J3DMaterial() {}
J3DMaterial* getNext() { return mNext; }
J3DShape* getShape() { return mShape; }
J3DTevBlock* getTevBlock() { return mTevBlock; }
@@ -11,8 +11,10 @@
class JUTFader {
public:
enum EStatus {
UNKSTATUS_M1 = -1,
UNKSTATUS_0 = 0,
None,
Wait,
FadeIn,
FadeOut,
};
JUTFader(int, int, int, int, JUtility::TColor);
@@ -29,12 +31,12 @@ public:
void setColor(JUtility::TColor color) { mColor.set(color); }
/* 0x04 */ s32 mStatus;
/* 0x08 */ u16 field_0x8;
/* 0x0A */ u16 field_0xa;
/* 0x08 */ u16 mDuration;
/* 0x0A */ u16 mTimer;
/* 0x0C */ JUtility::TColor mColor;
/* 0x10 */ JGeometry::TBox2<f32> mBox;
/* 0x20 */ int mEStatus;
/* 0x24 */ u32 field_0x24;
/* 0x20 */ int mStatusTimer;
/* 0x24 */ u32 mNextStatus;
};
#endif /* JUTFADER_H */
@@ -263,6 +263,9 @@ public:
/* 0x9C */ u8 field_0x9c[4];
/* 0xA0 */ OSTime mResetHoldStartTime;
/* 0xA8 */ u8 field_0xa8;
#if TARGET_PC
u32 mResetHoldFrameCount;
#endif
};
/**
+20 -5
View File
@@ -97,6 +97,16 @@ s32 J3DModel::entryModelData(J3DModelData* pModelData, u32 mdlFlags, u32 mtxNum)
return kJ3DError_Success;
}
#if TARGET_PC
void J3DModel::interp_callback(bool isSimFrame, void* pUserWork) {
J3DModel* i_this = static_cast<J3DModel*>(pUserWork);
if (!isSimFrame) {
i_this->calcMaterial();
i_this->diff();
}
}
#endif
s32 J3DModel::createShapePacket(J3DModelData* pModelData) {
J3D_ASSERTMSG(173, pModelData != NULL, "Error : null pointer.");
@@ -452,11 +462,11 @@ void J3DModel::calc() {
#ifdef TARGET_PC
for (u16 i = 0; i < mModelData->getJointNum(); ++i) {
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(getAnmMtx(i)), getAnmMtx(i));
dusk::frame_interp::record_final_mtx(getAnmMtx(i));
}
for (u16 i = 0; i < mModelData->getWEvlpMtxNum(); ++i) {
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(getWeightAnmMtx(i)), getWeightAnmMtx(i));
dusk::frame_interp::record_final_mtx(getWeightAnmMtx(i));
}
#endif
}
@@ -485,6 +495,11 @@ void J3DModel::entry() {
joint->entryIn();
}
}
#if TARGET_PC
if (mModelData->needsInterpCallBack())
dusk::frame_interp::add_interpolation_callback(&J3DModel::interp_callback, this);
#endif
}
void J3DModel::viewCalc() {
@@ -496,7 +511,7 @@ void J3DModel::viewCalc() {
J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx,
(MtxP)&mInternalView);
#ifdef TARGET_PC
dusk::frame_interp::record_final_mtx_raw(&mInternalView, mInternalView);
dusk::frame_interp::record_final_mtx(mInternalView);
#endif
}
} else if (isCpuSkinningOn()) {
@@ -504,7 +519,7 @@ void J3DModel::viewCalc() {
J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx,
(MtxP)&mInternalView);
#ifdef TARGET_PC
dusk::frame_interp::record_final_mtx_raw(&mInternalView, mInternalView);
dusk::frame_interp::record_final_mtx(mInternalView);
#endif
}
} else if (checkFlag(J3DMdlFlag_SkinPosCpu)) {
@@ -528,7 +543,7 @@ void J3DModel::viewCalc() {
#ifdef TARGET_PC
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
dusk::frame_interp::record_final_mtx_raw(&getDrawMtxPtr()[i], getDrawMtxPtr()[i]);
dusk::frame_interp::record_final_mtx(getDrawMtxPtr()[i]);
}
#endif
@@ -84,6 +84,15 @@ void J3DModelData::simpleCalcMaterial(u16 idx, Mtx param_1) {
}
}
#if TARGET_PC
bool J3DModelData::needsInterpCallBack() const {
for (u16 i = 0, n = getMaterialNum(); i < n; i++)
if (getMaterialNodePointer(i)->needsInterpCallBack())
return true;
return false;
}
#endif
void J3DModelData::syncJ3DSysPointers() const {
j3dSys.setTexture(getTexture());
j3dSys.setVtxPos(getVtxPosArray(), getVtxNum());
+27 -3
View File
@@ -265,7 +265,7 @@ void J3DMaterial::diff(u32 diffFlags) {
}
void J3DMaterial::calc(f32 const (*param_0)[4]) {
if (j3dSys.checkFlag(0x40000000)) {
if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
mTexGenBlock->calcPostTexMtx(param_0);
} else {
mTexGenBlock->calc(param_0);
@@ -276,7 +276,7 @@ void J3DMaterial::calc(f32 const (*param_0)[4]) {
}
void J3DMaterial::calcDiffTexMtx(f32 const (*param_0)[4]) {
if (j3dSys.checkFlag(0x40000000)) {
if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
mTexGenBlock->calcPostTexMtxWithoutViewMtx(param_0);
} else {
mTexGenBlock->calcWithoutViewMtx(param_0);
@@ -288,7 +288,7 @@ void J3DMaterial::setCurrentMtx() {
}
void J3DMaterial::calcCurrentMtx() {
if (!j3dSys.checkFlag(0x40000000)) {
if (!j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
mCurrentMtx.setCurrentTexMtx(
getTexCoord(0)->getTexGenMtx(),
getTexCoord(1)->getTexGenMtx(),
@@ -371,6 +371,30 @@ s32 J3DMaterial::newSingleSharedDisplayList(u32 dlSize) {
return kJ3DError_Success;
}
#if TARGET_PC
bool J3DMaterial::needsInterpCallBack() const {
for (int i = 0, n = getTexGenNum(); i < n; i++) {
J3DTexMtx* pTexMtx = mTexGenBlock->getTexMtx(i);
if (pTexMtx != NULL) {
u32 texMtxMode = pTexMtx->getTexMtxInfo().mInfo & 0x3f;
// uses j3dSys.getViewMtx()
switch (texMtxMode) {
case J3DTexMtxMode_EnvmapBasic:
case J3DTexMtxMode_EnvmapOld:
case J3DTexMtxMode_Envmap:
case J3DTexMtxMode_ProjmapBasic:
case J3DTexMtxMode_Projmap:
case J3DTexMtxMode_ViewProjmap:
case J3DTexMtxMode_ViewProjmapBasic:
return true;
}
}
}
return false;
}
#endif
void J3DPatchedMaterial::initialize() {
J3DMaterial::initialize();
}
+2 -2
View File
@@ -37,9 +37,9 @@ void loadTexCoordGens(u32 texGenNum, J3DTexCoord* texCoords) {
var_r28 = 61;
J3DGDWriteXFCmdHdr(GX_XF_REG_DUALTEX0, texGenNum);
if (j3dSys.checkFlag(0x40000000)) {
if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
for (int i = 0; i < texGenNum; i++) {
if (texCoords[i].getTexGenMtx() != 60) {
if (texCoords[i].getTexGenMtx() != GX_IDENTITY) {
var_r28 = i * 3;
} else {
var_r28 = 61;
+9 -1
View File
@@ -120,11 +120,19 @@ void JAISeqMgr::mixOut() {
}
JAISeq* JAISeqMgr::beginStartSeq_() {
JAISeq* seq = JKR_NEW JAISeq(this, field_0x10);
#ifdef TARGET_PC
if (JAISeq::getFreeMemCount() == 0) {
JUT_WARN(273, "%s", "JASPoolAllocObject::<JAISeq>::operator new failed .\n");
return NULL;
}
return JKR_NEW JAISeq(this, field_0x10);
#else
JAISeq* seq = new JAISeq(this, field_0x10);
if (seq == NULL) {
JUT_WARN(273, "%s", "JASPoolAllocObject::<JAISeq>::operator new failed .\n");
}
return seq;
#endif
}
bool JAISeqMgr::endStartSeq_(JAISeq* seq, JAISoundHandle* handle) {
+14 -5
View File
@@ -18,6 +18,7 @@
#include "dusk/logging.h"
#include "dusk/settings.h"
#include "dusk/time.h"
#include "f_op/f_op_overlap_mng.h"
#include "SDL3/SDL_timer.h"
#include "tracy/Tracy.hpp"
@@ -219,7 +220,7 @@ void JFWDisplay::endGX() {
if (dusk::frame_interp::get_ui_tick_pending()) {
mFader->advance();
}
if (mFader->getStatus() != 1) {
if (mFader->getStatus() != JUTFader::Wait) {
mFader->draw();
}
#else
@@ -368,22 +369,30 @@ constexpr auto FRAME_PERIOD = std::chrono::duration_cast<std::chrono::nanosecond
std::chrono::duration<double>(1001.0 / 30000.0));
constexpr auto RETRACE_PERIOD = FRAME_PERIOD / 2;
static void waitPrecise(Limiter& limiter, Uint64 targetNs) {
const auto sleepTime = limiter.SleepTime(std::chrono::nanoseconds(targetNs));
static void waitPrecise(Limiter& limiter, Limiter::duration_t targetNs) {
const auto sleepTime = limiter.SleepTime(targetNs);
dusk::frameUsagePct =
100.0f * (1.0f - static_cast<float>(sleepTime.count()) / static_cast<float>(targetNs));
limiter.Sleep(std::chrono::nanoseconds(targetNs));
100.0f * (1.0f - static_cast<float>(sleepTime) / static_cast<float>(targetNs));
limiter.Sleep(targetNs);
}
#endif
static void waitForTick(u32 p1, u16 p2) {
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation && !dusk::getTransientSettings().skipFrameRateLimit) {
dusk::frameUsagePct = 0.f;
return;
}
if (dusk::getTransientSettings().skipFrameRateLimit) {
p1 = OS_TIMER_CLOCK / 120;
}
#if TARGET_PC
if (fopOvlpM_IsPeek() && dusk::getTransientSettings().stateShareLoadActive) {
return;
}
#endif
ZoneScopedC(tracy::Color::DimGray);
#endif
+44 -44
View File
@@ -10,51 +10,51 @@
JUTFader::JUTFader(int x, int y, int width, int height, JUtility::TColor pColor)
: mColor(pColor), mBox(x, y, x + width, y + height) {
mStatus = 0;
field_0x8 = 0;
field_0xa = 0;
field_0x24 = 0;
mEStatus = UNKSTATUS_M1;
mStatus = None;
mDuration = 0;
mTimer = 0;
mNextStatus = 0;
mStatusTimer = -1;
}
void JUTFader::advance() {
if (0 <= mEStatus && mEStatus-- == 0) {
mStatus = field_0x24;
if (0 <= mStatusTimer && mStatusTimer-- == 0) {
mStatus = mNextStatus;
}
if (mStatus == 1) {
if (mStatus == Wait) {
return;
}
switch (mStatus) {
case 0:
case None:
mColor.a = 0xFF;
break;
case 2:
case FadeIn:
#if AVOID_UB
if (field_0x8 == 0) {
mStatus = 1;
if (mDuration == 0) {
mStatus = Wait;
break;
}
#endif
mColor.a = 0xFF - ((++field_0xa * 0xFF) / field_0x8);
mColor.a = 0xFF - ((++mTimer * 0xFF) / mDuration);
if (field_0xa >= field_0x8) {
mStatus = 1;
if (mTimer >= mDuration) {
mStatus = Wait;
}
break;
case 3:
case FadeOut:
#if AVOID_UB
if (field_0x8 == 0) {
mStatus = 0;
if (mDuration == 0) {
mStatus = None;
break;
}
#endif
mColor.a = ((++field_0xa * 0xFF) / field_0x8);
mColor.a = ((++mTimer * 0xFF) / mDuration);
if (field_0xa >= field_0x8) {
mStatus = 0;
if (mTimer >= mDuration) {
mStatus = None;
}
break;
@@ -77,53 +77,53 @@ void JUTFader::draw() {
}
}
bool JUTFader::startFadeIn(int param_0) {
bool JUTFader::startFadeIn(int duration) {
bool statusCheck = mStatus == 0;
if (statusCheck) {
mStatus = 2;
field_0xa = 0;
field_0x8 = param_0;
mStatus = FadeIn;
mTimer = 0;
mDuration = duration;
}
return statusCheck;
}
bool JUTFader::startFadeOut(int param_0) {
bool JUTFader::startFadeOut(int duration) {
bool statusCheck = mStatus == 1;
if (statusCheck) {
mStatus = 3;
field_0xa = 0;
field_0x8 = param_0;
mStatus = FadeOut;
mTimer = 0;
mDuration = duration;
}
return statusCheck;
}
void JUTFader::setStatus(JUTFader::EStatus i_status, int param_1) {
void JUTFader::setStatus(JUTFader::EStatus i_status, int timer) {
switch (i_status) {
case 0:
if (param_1 != 0) {
field_0x24 = 0;
mEStatus = param_1;
case None:
if (timer != 0) {
mNextStatus = None;
mStatusTimer = timer;
break;
}
mStatus = 0;
field_0x24 = 0;
mEStatus = 0;
mStatus = None;
mNextStatus = None;
mStatusTimer = 0;
break;
case 1:
if (param_1 != 0) {
field_0x24 = 1;
mEStatus = param_1;
case Wait:
if (timer != 0) {
mNextStatus = Wait;
mStatusTimer = timer;
break;
}
mStatus = 1;
field_0x24 = 1;
mEStatus = 0;
mStatus = Wait;
mNextStatus = Wait;
mStatusTimer = 0;
break;
}
}
+11
View File
@@ -64,6 +64,9 @@ BOOL JUTGamePad::init() {
void JUTGamePad::clear() {
mButtonReset.mReset = false;
field_0xa8 = 1;
#if TARGET_PC
mResetHoldFrameCount = 0;
#endif
}
PADStatus JUTGamePad::mPadStatus[4];
@@ -219,11 +222,19 @@ void JUTGamePad::update() {
mButtonReset.mReset = false;
} else if (!JUTGamePad::C3ButtonReset::sResetOccurred) {
if (mButtonReset.mReset == true) {
#if TARGET_PC
checkResetCallback(++mResetHoldFrameCount * (OS_TIMER_CLOCK / 30));
#else
OSTime hold_time = OSGetTime() - mResetHoldStartTime;
checkResetCallback(hold_time);
#endif
} else {
mButtonReset.mReset = true;
#if TARGET_PC
mResetHoldFrameCount = 0;
#else
mResetHoldStartTime = OSGetTime();
#endif
}
}
+5 -5
View File
@@ -117,8 +117,8 @@ static Z2WolfHowlLine sNewSong3[9] = {
#if TARGET_PC
static Z2WolfHowlLine sHowlTimeSong[6] = {
{HOWL_LINE_MID, 20}, {HOWL_LINE_LOW, 20}, {HOWL_LINE_HIGH, 40},
{HOWL_LINE_MID, 20}, {HOWL_LINE_LOW, 20}, {HOWL_LINE_HIGH, 40},
{HOWL_LINE_MID, 15}, {HOWL_LINE_LOW, 15}, {HOWL_LINE_HIGH, 30},
{HOWL_LINE_MID, 15}, {HOWL_LINE_LOW, 15}, {HOWL_LINE_HIGH, 30},
};
#endif
@@ -368,9 +368,9 @@ void Z2WolfHowlMgr::setCorrectData(s8 curveID, Z2WolfHowlData* data) {
break;
#if TARGET_PC
case Z2WOLFHOWL_TIMESONG:
cPitchUp = 1.259906f;
cPitchCenter = 0.94387f;
cPitchDown = 0.840885f;
cPitchUp = 1.3348f;
cPitchCenter = 0.8909f;
cPitchDown = 0.7937f;
break;
#endif
default:
+30 -8
View File
@@ -37,18 +37,40 @@ void daAlink_c::setCrawlMoveDirectionArrow() {
}
if (field_0x3198 & 4) {
if (!bvar) {
direction |= data_80452F38;
} else {
direction |= data_80452F39;
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
if (!bvar) {
direction |= data_80452F39;
} else {
direction |= data_80452F38;
}
} else
#endif
{
if (!bvar) {
direction |= data_80452F38;
} else {
direction |= data_80452F39;
}
}
}
if (field_0x3198 & 8) {
if (!bvar) {
direction |= data_80452F39;
} else {
direction |= data_80452F38;
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
if (!bvar) {
direction |= data_80452F38;
} else {
direction |= data_80452F39;
}
} else
#endif
{
if (!bvar) {
direction |= data_80452F39;
} else {
direction |= data_80452F38;
}
}
}
+8 -2
View File
@@ -41,7 +41,7 @@ void daAlink_c::handleWolfHowl() {
return;
}
bool canTransform = false;
bool canHowl = false;
if (mLinkAcch.ChkGroundHit() && !checkModeFlg(MODE_PLAYER_FLY) && !checkMagneBootsOn()) {
if (!checkForestOldCentury()) {
@@ -52,12 +52,17 @@ void daAlink_c::handleWolfHowl() {
(checkEventRun() || getMidnaActor()->checkMetamorphoseEnable()) &&
(checkModeFlg(4) || dComIfGp_checkPlayerStatus0(0, 0x10))))
{
canTransform = true;
canHowl = true;
}
}
}
}
if (!canHowl) {
Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
return;
}
getWolfHowlMgrP()->setCorrectCurve(9);
procWolfHowlDemoInit();
}
@@ -154,6 +159,7 @@ bool daAlink_c::checkGyroAimContext() {
case PROC_BOW_SUBJECT:
case PROC_BOOMERANG_SUBJECT:
case PROC_COPY_ROD_SUBJECT:
case PROC_HAWK_SUBJECT:
case PROC_HOOKSHOT_SUBJECT:
case PROC_SWIM_HOOKSHOT_SUBJECT:
case PROC_HORSE_BOW_SUBJECT:
+54
View File
@@ -149,6 +149,23 @@ void daAlink_c::changeWolf() {
mpLinkModel = initModel(static_cast<J3DModelData*>(dComIfG_getObjectRes(l_wArcName, 14)), 0x20200);
#ifdef TARGET_PC
// Update Wolf Link's eye maxLOD to prevent the eyes from disappearing
{
J3DTexture* tex = mpLinkModel->getModelData()->getTexture();
JUTNameTab* nametable = mpLinkModel->getModelData()->getTextureName();
if (tex != nullptr && nametable != nullptr) {
for (u16 i = 0; i < tex->getNum(); i++) {
const char* tex_name = nametable->getName(i);
if (tex_name != NULL && strcmp(tex_name, "wl_eyeball") == 0) {
ResTIMG* timg = tex->getResTIMG(i);
timg->maxLOD = 0;
}
}
}
}
#endif
J3DModelData* chainModelData = static_cast<J3DModelData*>(dComIfG_getObjectRes(l_wArcName, 15));
for (u16 i = 0; i < 4; i++) {
mpWlChainModels[i] = initModel(chainModelData, 0);
@@ -162,6 +179,23 @@ void daAlink_c::changeWolf() {
mpWlMidnaHairModel =
initModelEnv(static_cast<J3DModelData*>(dComIfG_getObjectRes(l_wArcName, 11)), 0x1000000);
#ifdef TARGET_PC
// Update Midna's eye maxLOD to prevent the eyes from disappearing
{
J3DTexture* tex = mpWlMidnaModel->getModelData()->getTexture();
JUTNameTab* nametable = mpWlMidnaModel->getModelData()->getTextureName();
if (tex != nullptr && nametable != nullptr) {
for (u16 i = 0; i < tex->getNum(); i++) {
const char* tex_name = nametable->getName(i);
if (tex_name != NULL && strcmp(tex_name, "midona_eyeball") == 0) {
ResTIMG* timg = tex->getResTIMG(i);
timg->maxLOD = 0;
}
}
}
}
#endif
mpDMidnaBrk = static_cast<J3DAnmTevRegKey*>(dComIfG_getObjectRes(l_wArcName, 18));
mpDMidnaBrk->searchUpdateMaterialID(mpWlMidnaModel->getModelData());
mpWlMidnaModel->getModelData()->entryTevRegAnimator(mpDMidnaBrk);
@@ -342,6 +376,26 @@ void daAlink_c::changeLink(int param_0) {
initModel(static_cast<J3DModelData*>(dComIfG_getObjectRes(mArcName, "zl_face.bmd")), 0x20200);
}
#ifdef TARGET_PC
// Update Adult Link's eye maxLOD to prevent the eyes from disappearing
{
J3DTexture* tex = mpLinkFaceModel->getModelData()->getTexture();
JUTNameTab* nametable = mpLinkFaceModel->getModelData()->getTextureName();
if (tex != nullptr && nametable != nullptr) {
for (u16 i = 0; i < tex->getNum(); i++) {
const char* tex_name = nametable->getName(i);
if (tex_name != nullptr &&
(strcmp(tex_name, "al_eyeball") == 0 || strcmp(tex_name, "highlight02") == 0 ||
strcmp(tex_name, "eye_kage01") == 0))
{
ResTIMG* timg = tex->getResTIMG(i);
timg->maxLOD = 0;
}
}
}
}
#endif
modelData = static_cast<J3DModelData*>(dComIfG_getObjectRes(mArcName, "al_bootsH.bmd"));
u16 i;
for (i = 0; i < 2; i++) {
+9 -1
View File
@@ -2059,7 +2059,15 @@ static void demo_camera(b_bq_class* i_this) {
for (int i = 0; i < 5; i++) {
static u16 g_e_i[] = {0x83EB, 0x83EC, 0x83ED, 0x83EE, 0x83EF};
dComIfGp_particle_set(g_e_i[i], &pos, NULL, NULL);
#if TARGET_PC
if (i == 0) {
static const cXyz effWideScale = {mDoGph_gInf_c::getAspect(), 1.0f, 1.0f};
dComIfGp_particle_set(g_e_i[i], &pos, NULL, &effWideScale);
} else
#endif
{
dComIfGp_particle_set(g_e_i[i], &pos, NULL, NULL);
}
}
i_this->mSound.startCreatureSound(Z2SE_EN_BOSS_CONVERGE, 0, 0);
+10 -1
View File
@@ -2725,7 +2725,16 @@ static void demo_camera(b_ob_class* i_this) {
for (int i = 0; i < 5; i++) {
static u16 ex_eff[] = {dPa_RM(ID_ZI_S_OI_CONVERGE_FILTER), dPa_RM(ID_ZI_S_OI_CONVERGE_FILTEROUT), dPa_RM(ID_ZI_S_OI_CONVERGE_HIDE), dPa_RM(ID_ZI_S_OI_CONVERGE_POLYGON_A), dPa_RM(ID_ZI_S_OI_CONVERGE_POLYGON_B)};
dComIfGp_particle_set(ex_eff[i], &room_pos, NULL, &sc);
#if TARGET_PC
if (i == 0) {
static const cXyz effWideScale = {mDoGph_gInf_c::getAspect() * 10.0f, 10.0f, 10.0f};
dComIfGp_particle_set(ex_eff[i], &room_pos, NULL, &effWideScale);
} else
#endif
{
dComIfGp_particle_set(ex_eff[i], &room_pos, NULL, &sc);
}
}
i_this->mDemoCamEye.set(-4820.0f, -18600.0f, -510.0f);
+5
View File
@@ -623,6 +623,11 @@ int daBg_c::create() {
dComIfGp_roomControl_onStatusFlag(roomNo, 0x10);
OS_REPORT("<BG> room%d\n", roomNo);
#if TARGET_PC
draw_interp_frame = true;
#endif
return cPhs_COMPLEATE_e;
}
+7 -8
View File
@@ -215,15 +215,14 @@ int daDsh_c::create() {
mType = getType();
#ifdef TARGET_PC
const char* l_resName[] = {l_arcName[mType], ""};
#else
// !@bug By making this static, it is only initialized the first time it runs
// If gate types that use other arcs are loaded later (without reloading the code)
// this array never gets updated and will load the incorrect arc
// On GC/Wii, REL loading causes this to reset/reinitialize so the bug is avoided
// but TPHD is all statically linked so daDsh_c::CreateHeap fails to get model data and the gate unloads
// !@bug Static-init only runs once, so slot 0 keeps the first mType's arc name forever.
// GC/Wii dodges this via REL reload; TPHD is statically linked so later gates of a
// different type load the wrong arc and CreateHeap fails. The storage must stay static
// because mResLoader.load holds the pointer past create(), so we just overwrite slot 0
// each call instead.
static const char* l_resName[] = {l_arcName[mType], ""};
#ifdef TARGET_PC
l_resName[0] = l_arcName[mType];
#endif
int phase = mResLoader.load(l_resName, NULL);
+10 -1
View File
@@ -1677,7 +1677,16 @@ static void demo_camera(e_fm_class* i_this) {
cXyz spBC(0.0f, 0.0f, 0.0f);
for (int i = 0; i < 4; i++) {
static u16 g_e_i[] = {0x847B, 0x847C, 0x847D, 0x847E};
dComIfGp_particle_set(g_e_i[i], &spBC, NULL, NULL);
#if TARGET_PC
if (i == 0) {
static const cXyz effWideScale = {mDoGph_gInf_c::getAspect(), 1.0f, 1.0f};
dComIfGp_particle_set(g_e_i[i], &spBC, NULL, &effWideScale);
} else
#endif
{
dComIfGp_particle_set(g_e_i[i], &spBC, NULL, NULL);
}
}
i_this->mDemoCamFovy = 55.0f + NREG_F(10);
+5 -4
View File
@@ -6601,13 +6601,14 @@ static int daE_RD_Execute(e_rd_class* i_this) {
1.2f,
};
#if AVOID_UB
s16 x = 0;
s16 y = 0;
#endif
for (int i = 0; i < 2; i++) {
MtxPush();
#if !AVOID_UB
s16 x, y;
#if AVOID_UB
x = 0;
y = 0;
#endif
if (i == 0) {
+62
View File
@@ -18,6 +18,8 @@
#include "m_Do/m_Do_controller_pad.h"
#include "m_Do/m_Do_graphic.h"
#include "res/Object/Always.h"
#include "dusk/dusk.h"
#include "dusk/frame_interpolation.h"
#include <cstring>
@@ -184,6 +186,30 @@ static bool hio_set;
static daE_WB_HIO_c l_HIO;
#if TARGET_PC
static void e_wb_rein_interp_callback(bool isSimFrame, void* pUserWork) {
e_wb_class* i_this = (e_wb_class*)pUserWork;
if (!i_this->himo_interp_prev_valid || !i_this->himo_interp_curr_valid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
for (int r = 0; r < 2; r++) {
cXyz* dst = i_this->himo_mat[r].getPos(0);
for (int i = 0; i < 16; i++) {
const cXyz& p0 = i_this->himo_mat_interp_prev[r][i];
const cXyz& p1 = i_this->himo_mat_interp_curr[r][i];
dst[i] = p0 + (p1 - p0) * alpha;
}
}
cXyz* dst = i_this->himo_tex.getPos(0);
for (int i = 0; i < 2; i++) {
const cXyz& p0 = i_this->himo_tex_interp_prev[i];
const cXyz& p1 = i_this->himo_tex_interp_curr[i];
dst[i] = p0 + (p1 - p0) * alpha;
}
}
#endif
static void himo_control1(e_wb_class* i_this, cXyz* i_pos, int i_no, s8 param_3) {
fopEn_enemy_c* enemy = &i_this->enemy;
cXyz mae, ato;
@@ -508,6 +534,21 @@ static int daE_WB_Draw(e_wb_class* i_this) {
dComIfGd_set3DlineMat(&i_this->himo_mat[1]);
i_this->himo_tex.update(2, l_color, &actor->tevStr);
dComIfGd_set3DlineMat(&i_this->himo_tex);
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
if (i_this->himo_interp_curr_valid) {
memcpy(i_this->himo_mat_interp_prev, i_this->himo_mat_interp_curr, sizeof(i_this->himo_mat_interp_curr));
memcpy(i_this->himo_tex_interp_prev, i_this->himo_tex_interp_curr, sizeof(i_this->himo_tex_interp_curr));
i_this->himo_interp_prev_valid = true;
}
for (int r = 0; r < 2; r++) {
memcpy(i_this->himo_mat_interp_curr[r], i_this->himo_mat[r].getPos(0), 16 * sizeof(cXyz));
}
memcpy(i_this->himo_tex_interp_curr, i_this->himo_tex.getPos(0), 2 * sizeof(cXyz));
i_this->himo_interp_curr_valid = true;
dusk::frame_interp::add_interpolation_callback(&e_wb_rein_interp_callback, i_this);
}
#endif
}
return 1;
@@ -3726,6 +3767,9 @@ static void demo_camera(e_wb_class* i_this) {
boss = (e_rdb_class*)fopAcM_SearchByName(fpcNm_E_RDB_e);
}
cXyz mae, ato, eye, center;
#if TARGET_PC
const s16 entry_demo_mode = i_this->demo_mode;
#endif
switch (i_this->demo_mode) {
case 1: {
@@ -4255,6 +4299,9 @@ static void demo_camera(e_wb_class* i_this) {
if (i_this->demo_timer == 325) {
fpcM_Search(s_wbZrevise_sub, i_this);
#if TARGET_PC
i_this->demo_cam_sync_ticks = 2;
#endif
}
if (i_this->demo_timer == 335) {
@@ -4495,6 +4542,9 @@ static void demo_camera(e_wb_class* i_this) {
i_this->demo_cam_way_spd.z = fabsf(i_this->demo_cam_way.z - i_this->demo_cam_ctr.z);
i_this->demo_cam_morf = 0;
pla->setPlayerPosAndAngle(&pla->current.pos, pla->shape_angle.y - 4000, 0);
#if TARGET_PC
dusk::frame_interp::request_presentation_sync();
#endif
}
if (i_this->demo_timer == 345) {
daPy_getPlayerActorClass()->setThrowDamage(boss->enemy.shape_angle.y - 8000 + TREG_S(8),
@@ -4741,6 +4791,9 @@ static void demo_camera(e_wb_class* i_this) {
i_this->demo_cam_eye.x += 300.0f + VREG_F(8);
i_this->demo_cam_eye.y += 150.0f + VREG_F(9);
i_this->demo_cam_eye.z -= 1400.0f + VREG_F(10);
#if TARGET_PC
dusk::frame_interp::request_presentation_sync();
#endif
}
} else {
i_this->demo_cam_eye = enemy->current.pos;
@@ -4996,6 +5049,15 @@ static void demo_camera(e_wb_class* i_this) {
}
}
}
#if TARGET_PC
if (entry_demo_mode != i_this->demo_mode) {
i_this->demo_cam_sync_ticks = 2;
}
if (i_this->demo_cam_sync_ticks > 0) {
dusk::frame_interp::request_presentation_sync();
i_this->demo_cam_sync_ticks--;
}
#endif
}
static void anm_se_eff_set(e_wb_class* i_this) {
+10 -10
View File
@@ -761,6 +761,11 @@ static void koro2_game(fshop_class* i_this) {
sp5C.x = mDoCPd_c::getStickX3D(PAD_1);
sp5C.y = 0.0f;
sp5C.z = mDoCPd_c::getStickY(PAD_1);
#if TARGET_PC
if (dusk::getSettings().game.enableMirrorMode) {
sp5C.x = -sp5C.x;
}
#endif
MtxPosition(&sp5C, &sp68);
f32 reg_f31 = sp68.x;
@@ -782,20 +787,15 @@ static void koro2_game(fshop_class* i_this) {
reg_f30 = 0.0f;
}
s16 gyro_ax = 0;
s16 gyro_az = 0;
#if TARGET_PC
if (dusk::getSettings().game.enableGyroRollgoal) {
s16 rg_add_x;
s16 rg_add_z;
dusk::gyro::rollgoalTableOffset(rg_add_x, rg_add_z);
s16 tgt_x = static_cast<s16>(reg_f30 * (-6000.0f + JREG_F(7))) + rg_add_x;
s16 tgt_z = static_cast<s16>(reg_f31 * (-6000.0f + JREG_F(8))) + rg_add_z;
cLib_addCalcAngleS2(&i_this->field_0x4020.x, tgt_x, 4, 0x200);
cLib_addCalcAngleS2(&i_this->field_0x4020.z, tgt_z, 4, 0x200);
dusk::gyro::rollgoalTableOffset(gyro_ax, gyro_az);
}
#else
cLib_addCalcAngleS2(&i_this->field_0x4020.x, reg_f30 * (-6000.0f + JREG_F(7)), 4, 0x200);
cLib_addCalcAngleS2(&i_this->field_0x4020.z, reg_f31 * (-6000.0f + JREG_F(8)), 4, 0x200);
#endif
cLib_addCalcAngleS2(&i_this->field_0x4020.x, reg_f30 * (-6000.0f + JREG_F(7)) + gyro_ax, 4, 0x200);
cLib_addCalcAngleS2(&i_this->field_0x4020.z, reg_f31 * (-6000.0f + JREG_F(8)) + gyro_az, 4, 0x200);
}
#if TARGET_PC
if (i_this->field_0x4010 != 2) {
+1 -1
View File
@@ -1056,7 +1056,7 @@ void daMidna_c::setBodyPartMatrix() {
#ifdef TARGET_PC
// FRAME INTERP NOTE: Record weight envelopes for Midna here, as they are otherwise missed causing distortion
for (u16 i = 0; i < mpModel->getModelData()->getWEvlpMtxNum(); i++) {
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(mpModel->getWeightAnmMtx(i)), mpModel->getWeightAnmMtx(i));
dusk::frame_interp::record_final_mtx(mpModel->getWeightAnmMtx(i));
}
#endif
}
+18
View File
@@ -13,6 +13,9 @@
#include <gf/GFGeometry.h>
#include <gf/GFLight.h>
#include "m_Do/m_Do_lib.h"
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#endif
#ifndef __MWERKS__
#include "dusk/math.h"
@@ -27,11 +30,19 @@ static char* l_arcName = "Mirror";
static char* l_arcName2 = "MR-Table";
dMirror_packet_c::dMirror_packet_c() {
#ifdef TARGET_PC
GXInitTexObj(&mTexObj, nullptr, 0, 0, static_cast<GXTexFmt>(-1), GX_MAX_TEXWRAPMODE,
GX_MAX_TEXWRAPMODE, GX_FALSE);
#endif
reset();
}
void dMirror_packet_c::reset() {
#if TARGET_PC
mbReset = true;
#else
mModelCount = 0;
#endif
}
void dMirror_packet_c::calcMinMax() {
@@ -73,6 +84,13 @@ void dMirror_packet_c::calcMinMax() {
}
int dMirror_packet_c::entryModel(J3DModel* i_model) {
#if TARGET_PC
if (mbReset) {
mModelCount = 0;
mbReset = false;
}
#endif
if (mModelCount >= 0x40) {
return 0;
}
+14 -3
View File
@@ -2855,7 +2855,7 @@ void* daMP_Reader(void*) {
#endif
}
static u8 daMP_ReadThreadStack[0x2000];
static u8 daMP_ReadThreadStack[DUSK_IF_ELSE(8, 0x2000)];
#if TARGET_PC
static BOOL VideoThreadCancelled;
@@ -2880,7 +2880,7 @@ static BOOL daMP_CreateReadThread(s32 param_0) {
static OSThread daMP_VideoDecodeThread;
static u8 daMP_VideoDecodeThreadStack[0x64000];
static u8 daMP_VideoDecodeThreadStack[DUSK_IF_ELSE(8, 0x64000)];
static OSMessageQueue daMP_FreeTextureSetQueue;
@@ -3132,7 +3132,7 @@ static BOOL AudioThreadCancelled;
static OSThread daMP_AudioDecodeThread;
static u8 daMP_AudioDecodeThreadStack[0x64000];
static u8 daMP_AudioDecodeThreadStack[DUSK_IF_ELSE(8, 0x64000)];
static OSMessageQueue daMP_FreeAudioBufferQueue;
@@ -4378,6 +4378,8 @@ static void daMP_ActivePlayer_Draw() {
daMP_DrawPosX = static_cast<u32>(rect.PosX);
daMP_DrawPosY = static_cast<u32>(rect.PosY);
daMP_THPPlayerSetVolume((dusk::getSettings().audio.masterVolume / 100.0f) * 127.0f, 0);
#endif
int frame = daMP_THPPlayerDrawCurrentFrame(
@@ -4578,3 +4580,12 @@ actor_process_profile_definition g_profile_MOVIE_PLAYER = {
};
AUDIO_INSTANCES;
#if TARGET_PC
void dusk::MoviePlayerShutdown() {
// We need to cleanly shut down the threads to avoid crashes on shutdown.
if (daMP_c::m_myObj) {
daMP_c::m_myObj->daMP_c_Finish();
}
}
#endif
+2 -2
View File
@@ -170,7 +170,7 @@ void daObjLv5Key_c::Fall(int param_0) {
OS_REPORT("FALL SPD = %f\n", speed.y);
if (mAcch.ChkGroundHit()) {
if (mAcch.ChkGroundHit() IF_DUSK(|| current.pos.abs(home.pos) > 200.0f)) {
fopAcM_GetSpeed(this);
fopAcM_SetSpeedF(this, 4.0f);
fopAcM_SetSpeed(this, 0.0f, 22.0f, 0.0f);
@@ -192,7 +192,7 @@ void daObjLv5Key_c::Fall(int param_0) {
mAcch.CrrPos(dComIfG_Bgsp());
current.pos.y = prev_y;
if (mAcch.ChkGroundHit()) {
if (mAcch.ChkGroundHit() IF_DUSK(|| current.pos.abs(home.pos) > 200.0f)) {
setAction(&daObjLv5Key_c::Land, 1);
}
}
+43 -1
View File
@@ -16,6 +16,10 @@
#include "f_op/f_op_camera_mng.h"
#include "m_Do/m_Do_mtx.h"
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#endif
static f32 Reflect(cXyz* i_vec, cBgS_PolyInfo const& i_polyinfo, f32 i_scale) {
cM3dGPla plane;
@@ -31,6 +35,27 @@ static f32 Reflect(cXyz* i_vec, cBgS_PolyInfo const& i_polyinfo, f32 i_scale) {
return 0.0f;
}
#if TARGET_PC
static void d_a_obj_item_interp_callback(bool isSimFrame, void* pUserWork) {
daItem_c* item = static_cast<daItem_c*>(pUserWork);
if (item == NULL || item->mpModel == NULL || !item->chkDraw()) {
return;
}
item->setTevStr();
if (item->mpBrkAnm != NULL) {
s8 tevFrm = item->getTevFrm();
if (tevFrm != -1) {
item->mpBrkAnm->entry(item->mpModel->getModelData(), tevFrm);
} else {
item->mpBrkAnm->entry(item->mpModel->getModelData());
}
}
if (item->chkFlag(4)) {
fopAcM_setEffectMtx(item, item->mpModel->getModelData());
}
}
#endif
const daItemBase_data& daItemBase_c::getData() {
return m_data;
}
@@ -353,6 +378,10 @@ int daItem_c::_daItem_draw() {
return 1;
}
#if TARGET_PC
dusk::frame_interp::add_interpolation_callback(&d_a_obj_item_interp_callback, this);
#endif
if (chkDraw()) {
return DrawBase();
}
@@ -390,6 +419,9 @@ void daItem_c::procMainNormal() {
cLib_chaseF(&scale.z, mItemScale.z, step_z);
}
#if TARGET_PC
if (!dusk::getSettings().game.enableIndefiniteItemDrops) {
#endif
if (mWaitTimer == 0) {
if (mDisappearTimer == 0) {
deleteItem();
@@ -399,6 +431,9 @@ void daItem_c::procMainNormal() {
changeDraw();
}
}
#if TARGET_PC
}
#endif
mCcCyl.SetC(current.pos);
dComIfG_Ccsp()->Set(&mCcCyl);
@@ -1058,9 +1093,16 @@ int daItem_c::CountTimer() {
if (checkCountTimer()) {
if (mWaitTimer > 0) {
mWaitTimer--;
} else if (mDisappearTimer > 0) {
}
#if TARGET_PC
else if (!dusk::getSettings().game.enableIndefiniteItemDrops && mDisappearTimer > 0) {
mDisappearTimer--;
}
#else
else if (mDisappearTimer > 0) {
mDisappearTimer--;
}
#endif
}
cLib_calcTimer<u8>(&mBoomWindTgTimer);
+1 -3
View File
@@ -981,9 +981,7 @@ int daObjStone_c::draw() {
if (!model) {
f32 shadow_size = l_shadow_size[mStoneType];
TGXTexObj* pTex = dDlst_shadowControl_c::getSimpleTex();
cXyz pos = current.pos;
dComIfGd_setSimpleShadow(&pos, mChkObj.GetGroundH(), shadow_size, mChkObj.m_gnd, 0,
dComIfGd_setSimpleShadow(&current.pos, mChkObj.GetGroundH(), shadow_size, mChkObj.m_gnd, 0,
1.0f, pTex);
}
return 1;
+9 -11
View File
@@ -699,14 +699,14 @@ void dFlower_packet_c::draw() {
if (!cLib_checkBit<u8>(sp44->m_state, 4) && !cLib_checkBit<u8>(sp44->m_state, 0x40)) {
#ifdef TARGET_PC
Mtx flower_mtx;
if (dusk::frame_interp::lookup_replacement(reinterpret_cast<const void*>(&sp44->m_modelMtx), flower_mtx)) {
if (dusk::frame_interp::lookup_replacement(&sp44->m_modelMtx, flower_mtx)) {
cMtx_concat(j3dSys.getViewMtx(), flower_mtx, flower_mtx);
GXLoadPosMtxImm(flower_mtx, 0);
} else {
} else
#endif
{
GXLoadPosMtxImm(sp44->m_modelMtx, 0);
#ifdef TARGET_PC
}
#endif
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
#if TARGET_PC
@@ -854,20 +854,18 @@ void dFlower_packet_c::draw() {
if (!cLib_checkBit<u8>(sp34->m_state, 4) && cLib_checkBit<u8>(sp34->m_state, 0x40)) {
#ifdef TARGET_PC
Mtx flower_mtx;
if (dusk::frame_interp::lookup_replacement(reinterpret_cast<const void*>(&sp34->m_modelMtx), flower_mtx)) {
if (dusk::frame_interp::lookup_replacement(&sp34->m_modelMtx, flower_mtx)) {
cMtx_concat(j3dSys.getViewMtx(), flower_mtx, flower_mtx);
GXLoadPosMtxImm(flower_mtx, 0);
} else {
} else
#endif
{
GXLoadPosMtxImm(sp34->m_modelMtx, 0);
#ifdef TARGET_PC
}
#endif
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
#if TARGET_PC
GXLoadTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, GX_TEXMAP0);
#endif
if (!cLib_checkBit<u8>(sp34->m_state, 8)) {
if (!cLib_checkBit<u8>(sp34->m_state, 0x10)) {
GXCallDisplayList(mp_Jhana01DL, m_Jhana01DL_size);
@@ -994,7 +992,7 @@ void dFlower_packet_c::update() {
mDoMtx_stack_c::scaleM(temp_f31, temp_f31, temp_f31);
cMtx_concat(j3dSys.getViewMtx(), temp_r28, data_p->m_modelMtx);
#ifdef TARGET_PC
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(&data_p->m_modelMtx), data_p->m_modelMtx);
dusk::frame_interp::record_final_mtx(temp_r28, data_p->m_modelMtx);
#endif
}
}
+4 -4
View File
@@ -756,13 +756,13 @@ void dGrass_packet_c::draw() {
#ifdef TARGET_PC
Mtx grass_mtx;
if (dusk::frame_interp::lookup_replacement(reinterpret_cast<const void*>(&var_r29->m_modelMtx), grass_mtx)) {
cMtx_concat(j3dSys.getViewMtx(), grass_mtx, grass_mtx);
GXLoadPosMtxImm(grass_mtx, 0);
} else {
} else
#endif
{
GXLoadPosMtxImm(var_r29->m_modelMtx, 0);
#ifdef TARGET_PC
}
#endif
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
if (var_r29->field_0x05 <= 3 || var_r29->field_0x05 >= 10) {
if (var_r29->field_0x02 < -1) {
@@ -1018,7 +1018,7 @@ void dGrass_packet_c::update() {
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), data_p->m_modelMtx);
}
#ifdef TARGET_PC
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(&data_p->m_modelMtx), data_p->m_modelMtx);
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), data_p->m_modelMtx);
#endif
}
}
+18 -3
View File
@@ -7063,6 +7063,15 @@ bool dCamera_c::subjectCamera(s32 param_0) {
}
cXyz sp1E0(val0, val2, val1);
#if TARGET_PC
f32 aspect = mDoGph_gInf_c::getAspect();
f32 baseAspect = FB_WIDTH / FB_HEIGHT;
if (aspect > baseAspect) {
sp1E0.z += (aspect - baseAspect) * 4;
}
#endif
sp1D4 = dCamMath::xyzRotateX(sp1E0, angle_x);
sp1E0 = dCamMath::xyzRotateY(sp1D4, angle_y);
f32 sp6C = sp12 ? 40.0f : 0.0f;
@@ -11009,6 +11018,15 @@ static int camera_execute(camera_process_class* i_this) {
i_this->mCamera.CalcTrimSize();
store(i_this);
#ifdef TARGET_PC
// record new camera for our sim frame
dusk::frame_interp::record_camera(i_this, get_camera_id(i_this));
// interpolate the view now so that this sim frame's view matrix matches what
// we'll be rendering with later
dusk::frame_interp::interp_view(&i_this->view);
#endif
view_setup(i_this);
return 1;
}
@@ -11077,9 +11095,6 @@ static int camera_draw(camera_process_class* i_this) {
C_MTXPerspective(process->view.projMtx, process->view.fovy, process->view.aspect, process->view.near_, process->view.far_);
mDoMtx_lookAt(process->view.viewMtx, &process->view.lookat.eye, &process->view.lookat.center,
&process->view.lookat.up, process->view.bank);
#ifdef TARGET_PC
dusk::frame_interp::record_camera(process, camera_id);
#endif
#if WIDESCREEN_SUPPORT
mDoGph_gInf_c::setWideZoomProjection(process->view.projMtx);
+23 -32
View File
@@ -1096,16 +1096,7 @@ void dDlst_shadowReal_c::draw() {
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetCurrentMtx(GX_PNMTX0);
#ifdef TARGET_PC
Mtx receiver_proj_mtx;
if (dusk::frame_interp::lookup_replacement(&mReceiverProjMtx, receiver_proj_mtx)) {
GXLoadTexMtxImm(receiver_proj_mtx, GX_TEXMTX0, GX_MTX3x4);
} else {
#endif
GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4);
#ifdef TARGET_PC
}
#endif
GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4);
mShadowRealPoly.draw();
}
@@ -1263,14 +1254,9 @@ u8 dDlst_shadowReal_c::setShadowRealMtx(cXyz* param_0, cXyz* param_1, f32 param_
C_MTXOrtho(mRenderProjMtx, param_2, -param_2, -param_2, param_2, 1.0f, 10000.0f);
C_MTXLightOrtho(mReceiverProjMtx, param_2, -param_2, -param_2, param_2, 0.5f, -0.5f, 0.5f, 0.5f);
cMtx_concat(mReceiverProjMtx, mViewMtx, mReceiverProjMtx);
#ifdef TARGET_PC
dusk::frame_interp::record_final_mtx_raw(&mViewMtx, mViewMtx);
dusk::frame_interp::record_final_mtx_raw(&mReceiverProjMtx, mReceiverProjMtx);
#endif
return r29;
}
u32 dDlst_shadowReal_c::set(u32 i_key, J3DModel* i_model, cXyz* param_2, f32 param_3, f32 param_4,
dKy_tevstr_c* param_5, f32 i_cameraZ, f32 param_7) {
dScnKy_env_light_c* env_light = dKy_getEnvlight();
@@ -1292,6 +1278,7 @@ u32 dDlst_shadowReal_c::set(u32 i_key, J3DModel* i_model, cXyz* param_2, f32 par
}
field_0x1 = setShadowRealMtx(&sp60, param_2, param_3, param_4, param_7, param_5);
if (!field_0x1) {
return 0;
}
@@ -1331,14 +1318,14 @@ void dDlst_shadowSimple_c::draw() {
GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
#ifdef TARGET_PC
Mtx volume_mtx;
if (dusk::frame_interp::lookup_replacement(&mVolumeMtx, volume_mtx)) {
if (dusk::frame_interp::lookup_replacement(mVolumeMtxKey, volume_mtx)) {
cMtx_concat(j3dSys.getViewMtx(), volume_mtx, volume_mtx);
GXLoadPosMtxImm(volume_mtx, GX_PNMTX0);
} else {
} else
#endif
{
GXLoadPosMtxImm(mVolumeMtx, GX_PNMTX0);
#ifdef TARGET_PC
}
#endif
GXSetCurrentMtx(GX_PNMTX0);
GXCallDisplayList(l_frontMat, 0x40);
GXCallDisplayList(l_shadowVolumeDL, 0x40);
@@ -1346,14 +1333,14 @@ void dDlst_shadowSimple_c::draw() {
GXCallDisplayList(l_shadowVolumeDL, 0x40);
#ifdef TARGET_PC
Mtx shadow_mtx;
if (dusk::frame_interp::lookup_replacement(&mMtx, shadow_mtx)) {
if (dusk::frame_interp::lookup_replacement(mMtxKey, shadow_mtx)) {
cMtx_concat(j3dSys.getViewMtx(), shadow_mtx, shadow_mtx);
GXLoadPosMtxImm(shadow_mtx, GX_PNMTX1);
} else {
} else
#endif
{
GXLoadPosMtxImm(mMtx, GX_PNMTX1);
#ifdef TARGET_PC
}
#endif
GXSetCurrentMtx(GX_PNMTX1);
if (mpTexObj != NULL) {
@@ -1383,6 +1370,12 @@ void dDlst_shadowSimple_c::draw() {
GXCallDisplayList(l_shadowVolumeDL, 0x40);
}
#if TARGET_PC
static const void* getInterpKey(const void* base, int idx) {
return reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(base) ^ idx);
}
#endif
void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* param_3,
s16 param_4, f32 param_5, TGXTexObj* param_6) {
if (param_5 < 0.0f) {
@@ -1406,6 +1399,10 @@ void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* pa
mDoMtx_stack_c::transS(param_0->x, param_1 + f30, param_0->z);
mDoMtx_stack_c::YrotM(param_4);
mDoMtx_stack_c::scaleM(param_2, f30 + f30 + 16.0f, param_2 * param_5);
#if TARGET_PC
mVolumeMtxKey = getInterpKey(param_0, 0x1);
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), mVolumeMtxKey);
#endif
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mVolumeMtx);
f32 f31 = JMAFastSqrt(1.0f - param_3->x * param_3->x);
f32 f29;
@@ -1431,17 +1428,11 @@ void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* pa
mDoMtx_stack_c::get()[2][3] = param_0->z;
mDoMtx_stack_c::YrotM(param_4);
mDoMtx_stack_c::scaleM(param_2, 1.0f, param_2 * param_5);
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mMtx);
#ifdef TARGET_PC
const uint64_t shadow_tag_base = dusk::frame_interp::alloc_simple_shadow_pair_base();
if (shadow_tag_base != 0) {
dusk::frame_interp::record_final_mtx_raw_tagged(&mVolumeMtx, mVolumeMtx, shadow_tag_base);
dusk::frame_interp::record_final_mtx_raw_tagged(&mMtx, mMtx, shadow_tag_base + 1u);
} else {
dusk::frame_interp::record_final_mtx_raw(&mVolumeMtx, mVolumeMtx);
dusk::frame_interp::record_final_mtx_raw(&mMtx, mMtx);
}
mMtxKey = getInterpKey(param_0, 0x2);
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), mMtxKey);
#endif
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mMtx);
mpTexObj = param_6;
}
+27 -31
View File
@@ -70,11 +70,7 @@ dFs_HIO_c::dFs_HIO_c() {
select_icon_appear_frames = 5;
appear_display_wait_frames = 15;
field_0x000d = 15;
#if TARGET_PC
card_wait_frames = 0;
#else
card_wait_frames = 90;
#endif
test_frame_counts[0] = 1.11f;
test_frame_counts[1] = 1.11f;
test_frame_counts[2] = 1.11f;
@@ -2102,11 +2098,7 @@ void dFile_select_c::yesnoCursorShow() {
mSelIcon->setPos(pos.x, pos.y, mYnSelPane[field_0x0268]->getPanePtr(), true);
mSelIcon->setAlphaRate(1.0f);
#if TARGET_PC
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f);
#else
mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f);
#endif
}
}
@@ -2259,11 +2251,7 @@ void dFile_select_c::YesNoCancelMove() {
m3mSelPane[mSelectMenuNum]->getPanePtr(), true);
mSelIcon->setAlphaRate(1.0f);
#if TARGET_PC
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f);
#else
mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f);
#endif
#if PLATFORM_WII || PLATFORM_SHIELD
field_0x4333 = mSelectMenuNum;
@@ -2375,7 +2363,7 @@ void dFile_select_c::CommandExec() {
break;
}
mWaitTimer = g_fsHIO.card_wait_frames;
mWaitTimer = IF_DUSK(dusk::getSettings().game.instantSaves ? 0 :) g_fsHIO.card_wait_frames;
}
void dFile_select_c::DataEraseWait() {
@@ -3147,11 +3135,7 @@ void dFile_select_c::screenSet() {
mSelIcon = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL);
JUT_ASSERT(5209, mSelIcon != NULL);
#if TARGET_PC
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f);
#else
mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f);
#endif
Vec vtxCenter;
vtxCenter = mSelFilePanes[mSelectNum]->getGlobalVtxCenter(false, 0);
@@ -3204,6 +3188,9 @@ void dFile_select_c::screenSet() {
timg, NULL);
mpFadePict->setBlackWhite(black, white);
mpFadePict->setAlpha(0);
#ifdef TARGET_PC
mFadeDlst.mpPict = mpFadePict;
#endif
#endif
}
@@ -3284,11 +3271,7 @@ void dFile_select_c::screenSetCopySel() {
mSelIcon2 = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL);
JUT_ASSERT(5406, mSelIcon2 != NULL);
#if TARGET_PC
mSelIcon2->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f);
#else
mSelIcon2->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f);
#endif
Vec center = mCpSelPane[0]->getGlobalVtxCenter(false, 0);
mSelIcon2->setPos(center.x, center.y, mCpSelPane[0]->getPanePtr(), true);
@@ -3680,11 +3663,7 @@ void dFile_select_c::selFileCursorShow() {
mSelIcon->setPos(local_1c.x, local_1c.y, mSelFilePanes[mSelectNum]->getPanePtr(), true);
mSelIcon->setAlphaRate(1.0f);
#if TARGET_PC
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f);
#else
mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f);
#endif
}
void dFile_select_c::menuWakuAlpahAnmInit(u8 i_idx, u8 param_1, u8 param_2, u8 param_3) {
@@ -3727,11 +3706,7 @@ void dFile_select_c::menuCursorShow() {
mSelIcon->setPos(local_24.x, local_24.y, m3mSelPane[mSelectMenuNum]->getPanePtr(), true);
mSelIcon->setAlphaRate(1.0f);
#if TARGET_PC
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f);
#else
mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f);
#endif
}
}
@@ -3833,6 +3808,16 @@ void dFile_select_c::fileSelectWide() {
fileSel.Scr->search(MULTI_CHAR('w_uzu07'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
fileSel.Scr->search(MULTI_CHAR('w_uzu08'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
fileSel.Scr->search(MULTI_CHAR('w_uzu09'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
#if TARGET_PC
if (mSelIcon) {
mSelIcon->refreshAspectScale();
}
if (mSelIcon2) {
mSelIcon2->refreshAspectScale();
}
#endif
}
#endif
@@ -3870,10 +3855,14 @@ void dFile_select_c::_draw() {
dComIfGd_set2DOpa(mSelIcon2);
#if PLATFORM_GCN
#if TARGET_PC
dComIfGd_set2DOpaTop(&mFadeDlst);
#else
mpFadePict->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(),
mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), false, false,
false);
#endif
#endif
}
}
@@ -3917,6 +3906,13 @@ void dDlst_FileSel3m_c::draw() {
Scr3m->draw(0.0f, 0.0f, graf);
}
#ifdef TARGET_PC
void dDlst_FileSelFade_c::draw() {
mpPict->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(),
mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), false, false, false);
}
#endif
void dFile_select_c::errorMoveAnmInitSet(int param_1, int param_2) {
mErrorMsgPane->setAnimation(field_0x0090);
field_0x0130 = param_1;
@@ -4759,7 +4755,7 @@ void dFile_select_c::MemCardFormatYesSel2Disp() {
bool isErrorTxtChange = errorTxtChangeAnm();
bool isYnMenuMove = yesnoMenuMoveAnm();
if (isErrorTxtChange == true && isYnMenuMove == true) {
mWaitTimer = g_fsHIO.card_wait_frames;
mWaitTimer = IF_DUSK(dusk::getSettings().game.instantSaves ? 0 :) g_fsHIO.card_wait_frames;
mDoMemCd_Format();
mCardCheckProc = MEMCARDCHECKPROC_FORMAT;
}
@@ -4830,7 +4826,7 @@ void dFile_select_c::MemCardMakeGameFileSelDisp() {
if (isErrorTxtChange == true && isYnMenuMove == true && isKetteiTxtDisp == true) {
if (field_0x0268 != 0) {
mWaitTimer = g_fsHIO.card_wait_frames;
mWaitTimer = IF_DUSK(dusk::getSettings().game.instantSaves ? 0 :) g_fsHIO.card_wait_frames;
setInitSaveData();
dataSave();
mCardCheckProc = MEMCARDCHECKPROC_MAKE_GAMEFILE;
+5
View File
@@ -35,6 +35,7 @@
#if TARGET_PC
#include "dusk/imgui/ImGuiBloomWindow.hpp"
#include "dusk/settings.h"
#include "dusk/frame_interpolation.h"
#endif
static void GxXFog_set();
@@ -8251,6 +8252,10 @@ static int dKy_Create(void* i_this) {
kankyo_class* kankyo = (kankyo_class*)i_this;
BOOL next_time_set = false;
#if TARGET_PC
kankyo->base.draw_interp_frame = true;
#endif
stage_envr_info_class* stage_envr_p = dComIfGp_getStageEnvrInfo();
if (stage_envr_p != NULL && dComIfGp_getStartStageRoomNo() != -1) {
stage_envr_p += dComIfGp_getStartStageRoomNo();
+7
View File
@@ -237,6 +237,13 @@ void dDrawPath_c::rendering(dDrawPath_c::line_class const* p_line) {
if (isDrawType(p_line->field_0x0)) {
int width = getLineWidth(p_line->field_0x1);
#if TARGET_PC
f32 height = JUTVideo::getManager()->getRenderHeight() / 448.0f;
if (height > 1.0f) {
width /= 2;
}
#endif
if (width > 0 && p_line->mDataNum >= 2) {
GXSetLineWidth(width, GX_TO_ZERO);
GXSetTevColor(GX_TEVREG0, *getLineColor(p_line->field_0x0 & 0x3F, p_line->field_0x1));
+18 -12
View File
@@ -164,11 +164,22 @@ void dMenu_Collect2D_c::menuCollectWide() {
// Item Description Text
mpScreen->search(MULTI_CHAR('infotxtn'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
#if TARGET_PC
if (mpDrawCursor) {
mpDrawCursor->refreshAspectScale();
}
#endif
}
#endif
void dMenu_Collect2D_c::_create() {
mpHeap->getTotalFreeSize();
#if TARGET_PC
mpDrawCursor = NULL;
#endif
mpScreen = JKR_NEW J2DScreen();
mpScreen->setPriority("zelda_collect_soubi_screen.blo", 0x1020000,
dComIfGp_getCollectResArchive());
@@ -1100,23 +1111,11 @@ void dMenu_Collect2D_c::cursorPosSet() {
Vec pos = mpSelPm[mCursorX][mCursorY]->getGlobalVtxCenter(false, 0);
mpDrawCursor->setPos(pos.x, pos.y, mpSelPm[mCursorX][mCursorY]->getPanePtr(), false);
if (mCursorY == 5) {
#if TARGET_PC
mpDrawCursor->setParam(1.1f * mDoGph_gInf_c::hudAspectScaleUp, 0.85f, 0.05f, 0.5f, 0.5f);
#else
mpDrawCursor->setParam(1.1f, 0.85f, 0.05f, 0.5f, 0.5f);
#endif
} else if (mCursorX == 6 && mCursorY == 0) {
#if TARGET_PC
mpDrawCursor->setParam(0.6f * mDoGph_gInf_c::hudAspectScaleUp, 0.85f, 0.03f, 0.6f, 0.6f);
#else
mpDrawCursor->setParam(0.6f, 0.85f, 0.03f, 0.6f, 0.6f);
#endif
} else {
#if TARGET_PC
mpDrawCursor->setParam(1.0f * mDoGph_gInf_c::hudAspectScaleUp, 1.0f, 0.1f, 0.7f, 0.7f);
#else
mpDrawCursor->setParam(1.0f, 1.0f, 0.1f, 0.7f, 0.7f);
#endif
}
}
@@ -2400,6 +2399,13 @@ void dMenu_Collect3D_c::_move(u8 param_0, u8 param_1) {
posZ = 550.0f;
}
toItem3Dpos(linkPos.x, posY, posZ, &itemPos);
#if TARGET_PC
if (dusk::getSettings().game.enableLinkDollRotation) {
const f32 angle = mDoCPd_c::getSubStickX3D(PAD_1) * 2048;
ANGLE_ADD(mLinkAngle, angle);
} else
#endif
if (param_0 == 0 && param_1 == 0) {
f32 temp = 450.0f;
ANGLE_ADD(mLinkAngle, temp);
+42 -1
View File
@@ -21,6 +21,7 @@
#include "d/d_msg_string.h"
#include "d/d_meter_haihai.h"
#include "d/d_menu_window.h"
#include "dusk/settings.h"
#include "f_op/f_op_msg_mng.h"
#include "m_Do/m_Do_graphic.h"
#include <cstring>
@@ -945,9 +946,15 @@ void dMenu_DmapBg_c::draw() {
mpMeterHaihai->drawHaihai(field_0xdda,
x1 + (local_224.x + local_218.x) / 2,
y1 + (local_224.y + local_218.y) / 2,
-35.0f + (local_224.x - local_218.x),
-35.0f + (local_224.x - local_218.x),
-35.0f + (local_224.y - local_218.y));
#if TARGET_PC
if (!dusk::getSettings().game.enableFrameInterpolation) {
field_0xdda = 0;
}
#else
field_0xdda = 0;
#endif
}
dMenu_Dmap_c::myclass->drawFloorScreenTop(mFloorScreen, field_0xd94, field_0xd98, grafContext);
@@ -984,7 +991,36 @@ void dMenu_DmapBg_c::update() {
JUT_ASSERT(2323, mpBackTexture != NULL);
void* spec = mpArchive->getResource("spec/spec.dat");
#if TARGET_PC
struct dmap_spec {
/* 0x00 */ BE(f32) field_0x0;
/* 0x04 */ BE(f32) field_0x4;
/* 0x08 */ BE(f32) field_0x8;
/* 0x0C */ u8 field_0xc;
/* 0x0D */ u8 field_0xd;
/* 0x0E */ u8 field_0xe;
/* 0x0F */ u8 field_0xf;
/* 0x10 */ u8 field_0x10;
/* 0x11 */ u8 field_0x11;
/* 0x12 */ u8 field_0x12;
/* 0x13 */ u8 field_0x13;
};
dmap_spec* dspec = (dmap_spec*)spec;
field_0xd80 = dspec->field_0x0;
field_0xd84 = dspec->field_0x4;
field_0xd88 = dspec->field_0x8;
field_0xd8c = dspec->field_0xc;
field_0xd8d = dspec->field_0xd;
field_0xd8e = dspec->field_0xe;
field_0xd8f = dspec->field_0xf;
field_0xd90 = dspec->field_0x10;
field_0xd91 = dspec->field_0x11;
field_0xd92 = dspec->field_0x12;
field_0xd93 = dspec->field_0x13;
#else
memcpy(&field_0xd80, spec, 20);
#endif
}
}
@@ -2545,6 +2581,11 @@ void dMenu_Dmap_c::zoomIn_proc() {
}
void dMenu_Dmap_c::zoomOut_init_proc() {
#if TARGET_PC
if (dusk::getSettings().game.enableFrameInterpolation) {
mpDrawBg->resetScrollArrowMask();
}
#endif
Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_ZOOMOUT, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
mMapCtrl->initZoomOut(10);
mpDrawBg->iconScaleAnmInit(1.0f, 0.0f, 10);
+19 -9
View File
@@ -342,8 +342,13 @@ void dMenu_Fmap2DBack_c::draw() {
scrollAreaDraw();
}
blinkMove(30);
moveLightDropAnime();
#ifdef TARGET_PC
if (dusk::frame_interp::get_ui_tick_pending())
#endif
{
blinkMove(30);
moveLightDropAnime();
}
setCenterPosX(field_0x11dc, 1);
drawIcon(mTransX, mTransZ, mAlphaRate, field_0xfa8 * mSpotTextureFadeAlpha);
@@ -1764,14 +1769,19 @@ void dMenu_Fmap2DBack_c::calcBlink() {
t * (g_fmapHIO.mMapBlink[i + 1].mUnselectedRegion.mBlinkSpeed -
g_fmapHIO.mMapBlink[i].mUnselectedRegion.mBlinkSpeed);
field_0x1218++;
if (field_0x1218 >= selected_blink_speed) {
field_0x1218 = 0;
}
#if TARGET_PC
if (dusk::frame_interp::get_ui_tick_pending())
#endif
{
field_0x1218++;
if (field_0x1218 >= selected_blink_speed) {
field_0x1218 = 0;
}
field_0x121a++;
if (field_0x121a >= unselected_blink_speed) {
field_0x121a = 0;
field_0x121a++;
if (field_0x121a >= unselected_blink_speed) {
field_0x121a = 0;
}
}
f32 t_selected = 0.0f;
+12
View File
@@ -555,11 +555,23 @@ void dMenu_Option_c::_draw() {
#endif
mpBlackTex->setAlpha(0xff);
#if TARGET_PC
mpBlackTex->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), 0, 0, 0);
#else
mpBlackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0, 0, 0);
#endif
mpBackScreen->draw(0.0f, 0.0f, ctx);
f32 alpha = (f32)g_drawHIO.mOptionScreen.mBackgroundAlpha * (f32)field_0x374;
mpBlackTex->setAlpha(alpha);
#if TARGET_PC
mpBlackTex->draw(mDoGph_gInf_c::getMinXF(), mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), mDoGph_gInf_c::getHeightF(), 0, 0, 0);
#else
mpBlackTex->draw(0.0f, 0.0f, FB_WIDTH, FB_HEIGHT, 0, 0, 0);
#endif
mpScreen->draw(0.0f, 0.0f, ctx);
mpClipScreen->draw(0.0f, 0.0f, ctx);
#if TARGET_PC
+75
View File
@@ -185,6 +185,17 @@ dMenu_Ring_c::dMenu_Ring_c(JKRExpHeap* i_heap, STControl* i_stick, CSTControl* i
field_0x682 = 0xc000;
break;
}
#if TARGET_PC
mCursorInterpPrevX = 0.0f;
mCursorInterpPrevY = 0.0f;
mCursorInterpCurrX = 0.0f;
mCursorInterpCurrY = 0.0f;
mCursorInterpPrevAngle = 0;
mCursorInterpCurrAngle = 0;
mCursorInterpPrevAngular = false;
mCursorInterpCurrAngular = false;
mCursorInterpInit = false;
#endif
for (int i = 0; i < 4; i++) {
field_0x674[i] = 0;
#if TARGET_PC
@@ -631,7 +642,71 @@ void dMenu_Ring_c::_draw() {
} else {
drawSelectItem();
drawItem2();
#if TARGET_PC
f32 simX = 0.0f;
f32 simY = 0.0f;
bool restoreSimPos = false;
if (dusk::frame_interp::is_enabled() && mAlphaRate >= 1.0f) {
simX = mpDrawCursor->getPositionX();
simY = mpDrawCursor->getPositionY();
const bool isAngular = (mStatus == STATUS_MOVE) && !mDirectSelectActive;
if (dusk::frame_interp::get_ui_tick_pending()) {
mCursorInterpPrevX = mCursorInterpCurrX;
mCursorInterpPrevY = mCursorInterpCurrY;
mCursorInterpPrevAngle = mCursorInterpCurrAngle;
mCursorInterpPrevAngular = mCursorInterpCurrAngular;
mCursorInterpCurrX = simX;
mCursorInterpCurrY = simY;
mCursorInterpCurrAngle = field_0x66e;
mCursorInterpCurrAngular = isAngular;
// reset prev = curr for first render pass or
// when angle modes prev/curr differ
// to prevent arrival jitter
if (!mCursorInterpInit ||
mCursorInterpPrevAngular != mCursorInterpCurrAngular) {
mCursorInterpPrevX = mCursorInterpCurrX;
mCursorInterpPrevY = mCursorInterpCurrY;
mCursorInterpPrevAngle = mCursorInterpCurrAngle;
mCursorInterpPrevAngular = mCursorInterpCurrAngular;
mCursorInterpInit = true;
}
}
if (mCursorInterpInit) {
const f32 step = dusk::frame_interp::get_interpolation_step();
if (mCursorInterpPrevAngular && mCursorInterpCurrAngular) {
const s16 delta = mCursorInterpCurrAngle - mCursorInterpPrevAngle;
const s16 lerpedAngle = mCursorInterpPrevAngle + (s16)(delta * step);
// yoinked from stick_move_proc()
const f32 x = g_ringHIO.mItemRingPosX + FB_WIDTH_BASE / 2 +
mRingRadiusH * cM_ssin(lerpedAngle);
const f32 y = g_ringHIO.mItemRingPosY + FB_HEIGHT_BASE / 2 +
mRingRadiusV * cM_scos(lerpedAngle);
mpDrawCursor->setPos(x, y);
} else {
mpDrawCursor->setPos(
mCursorInterpPrevX + (mCursorInterpCurrX - mCursorInterpPrevX) * step,
mCursorInterpPrevY + (mCursorInterpCurrY - mCursorInterpPrevY) * step
);
}
restoreSimPos = true;
}
} else {
mCursorInterpInit = false;
}
#endif
mpDrawCursor->draw();
#if TARGET_PC
// prevents offsetting at destination on the next frame
// since stick_wait_proc doesn't call setPos and we clobbered mPositionX/Y
if (restoreSimPos) {
mpDrawCursor->setPos(simX, simY);
}
#endif
mpItemExplain->trans(mCenterPosX, mCenterPosY);
mpItemExplain->draw((J2DOrthoGraph*)grafPort);
drawFlag0();
+43 -33
View File
@@ -18,6 +18,7 @@
#include "m_Do/m_Do_controller_pad.h"
#include "m_Do/m_Do_graphic.h"
#include "d/d_msg_scrn_explain.h"
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
#include "JSystem/J2DGraph/J2DAnmLoader.h"
#include "f_op/f_op_msg_mng.h"
@@ -386,11 +387,7 @@ void dMenu_save_c::screenSet() {
mSelectedFile = dComIfGs_getDataNum();
mSelIcon = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL);
#if TARGET_PC
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f);
#else
mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f);
#endif
Vec pos;
pos = mpSelData[mSelectedFile]->getGlobalVtxCenter(false, 0);
@@ -719,7 +716,9 @@ void dMenu_save_c::_move() {
}
(this->*MenuSaveProc[mMenuProc])();
#if !TARGET_PC
saveSelAnm();
#endif
if (mWarning != NULL) {
mWarning->_move();
@@ -736,36 +735,46 @@ void dMenu_save_c::saveSelAnm() {
}
void dMenu_save_c::selFileWakuAnm() {
mFileWakuAnmFrame += 2;
if (mFileWakuAnmFrame >= mpFileWakuAnm->getFrameMax()) {
mFileWakuAnmFrame -= mpFileWakuAnm->getFrameMax();
#if TARGET_PC
if (dusk::frame_interp::get_ui_tick_pending())
#endif
{
mFileWakuAnmFrame += 2;
if (mFileWakuAnmFrame >= mpFileWakuAnm->getFrameMax()) {
mFileWakuAnmFrame -= mpFileWakuAnm->getFrameMax();
}
mFileWakuRotAnmFrame += 2;
if (mFileWakuRotAnmFrame >= mpFileWakuRotAnm->getFrameMax()) {
mFileWakuRotAnmFrame -= mpFileWakuRotAnm->getFrameMax();
}
}
mpFileWakuAnm->setFrame(mFileWakuAnmFrame);
mFileWakuRotAnmFrame += 2;
if (mFileWakuRotAnmFrame >= mpFileWakuRotAnm->getFrameMax()) {
mFileWakuRotAnmFrame -= mpFileWakuRotAnm->getFrameMax();
}
mpFileWakuRotAnm->setFrame(mFileWakuRotAnmFrame);
}
void dMenu_save_c::bookIconAnm() {
field_0x154 += 2;
if (field_0x154 >= field_0x150->getFrameMax()) {
field_0x154 -= field_0x150->getFrameMax();
#if TARGET_PC
if (dusk::frame_interp::get_ui_tick_pending())
#endif
{
field_0x154 += 2;
if (field_0x154 >= field_0x150->getFrameMax()) {
field_0x154 -= field_0x150->getFrameMax();
}
field_0x15c += 2;
if (field_0x15c >= field_0x158->getFrameMax()) {
field_0x15c -= field_0x158->getFrameMax();
}
field_0x164 += 2;
if (field_0x164 >= field_0x160->getFrameMax()) {
field_0x164 -= field_0x160->getFrameMax();
}
}
field_0x150->setFrame(field_0x154);
field_0x15c += 2;
if (field_0x15c >= field_0x158->getFrameMax()) {
field_0x15c -= field_0x158->getFrameMax();
}
field_0x158->setFrame(field_0x15c);
field_0x164 += 2;
if (field_0x164 >= field_0x160->getFrameMax()) {
field_0x164 -= field_0x160->getFrameMax();
}
field_0x160->setFrame(field_0x164);
}
@@ -2523,11 +2532,7 @@ void dMenu_save_c::yesnoCursorShow() {
mSelIcon->setPos(pos.x, pos.y, mpNoYes[mYesNoCursor]->getPanePtr(), true);
mSelIcon->setAlphaRate(1.0f);
#if TARGET_PC
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.84f, 0.06f, 0.5f, 0.5f);
#else
mSelIcon->setParam(0.96f, 0.84f, 0.06f, 0.5f, 0.5f);
#endif
}
}
@@ -2676,11 +2681,7 @@ void dMenu_save_c::selFileCursorShow() {
mSelIcon->setPos(pos.x, pos.y, mpSelData[mSelectedFile]->getPanePtr(), true);
mSelIcon->setAlphaRate(1.0f);
#if TARGET_PC
mSelIcon->setParam(0.96f * mDoGph_gInf_c::hudAspectScaleUp, 0.94f, 0.03f, 0.7f, 0.7f);
#else
mSelIcon->setParam(0.96f, 0.94f, 0.03f, 0.7f, 0.7f);
#endif
}
void dMenu_save_c::yesnoWakuAlpahAnmInit(u8 yesnoIdx, u8 startAlpha, u8 endAlpha, u8 anmTimer) {
@@ -2813,11 +2814,20 @@ void dMenu_save_c::menuSaveWide() {
mSaveSel.Scr->search(MULTI_CHAR('w_uzu07'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
mSaveSel.Scr->search(MULTI_CHAR('w_uzu08'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
mSaveSel.Scr->search(MULTI_CHAR('w_uzu09'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
#if TARGET_PC
if (mSelIcon) {
mSelIcon->refreshAspectScale();
}
#endif
}
#endif
void dMenu_save_c::_draw2() {
if (field_0x21a1 == 0) {
#if TARGET_PC
saveSelAnm();
#endif
if (mpScrnExplain != NULL) {
dComIfGd_set2DOpa(&mMenuSaveExplain);
}
+7 -7
View File
@@ -699,7 +699,7 @@ void dMw_c::collect_open_proc() {
dMeter2Info_set2DVibrationM();
}
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
mMenuProc = COLLECT_MOVE;
}
}
@@ -914,7 +914,7 @@ void dMw_c::collect_letter_move_proc() {
}
void dMw_c::collect_letter_close_proc() {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
mMenuProc = COLLECT_MOVE;
}
}
@@ -946,7 +946,7 @@ void dMw_c::collect_fishing_move_proc() {
}
void dMw_c::collect_fishing_close_proc() {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
mMenuProc = COLLECT_MOVE;
}
}
@@ -977,7 +977,7 @@ void dMw_c::collect_skill_move_proc() {
}
void dMw_c::collect_skill_close_proc() {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
mMenuProc = COLLECT_MOVE;
}
}
@@ -1008,13 +1008,13 @@ void dMw_c::collect_insect_move_proc() {
}
void dMw_c::collect_insect_close_proc() {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
mMenuProc = COLLECT_MOVE;
}
}
void dMw_c::insect_open_proc() {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
field_0x152 = 0;
dComIfGp_setHeapLockFlag(1);
dMw_insect_create(1);
@@ -1050,7 +1050,7 @@ void dMw_c::insect_move_proc() {
}
void dMw_c::insect_close_proc() {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
mMenuProc = NO_MENU;
}
}
+7
View File
@@ -1987,6 +1987,13 @@ bool jmessage_tSequenceProcessor::do_isReady() {
}
#endif
#if TARGET_PC
if (dusk::getSettings().game.instantText && mDoCPd_c::getHoldB(0)) {
field_0xb2 = 1;
pReference->setSendTimer(0);
}
#endif
if (dComIfGp_checkMesgBgm()) {
bool isItemMusicPlaying = true;
if (mDoAud_checkPlayingSubBgmFlag() != Z2BGM_ITEM_GET &&
+25
View File
@@ -271,6 +271,30 @@ void dMsgUnit_c::setTag(int i_type, int i_value, char* o_buffer, bool param_4) {
u32 filesize = pHeader->size;
u8* pSection = ((u8*)pHeader) + filepos;
#if TARGET_PC
// patch bug in the original game where filepos would be incremented by the next section's size rather than the current section size.
// in certain scenarios this would read past the end of the file, incrementing filepos by 0 in an infinite loop
while (filepos < filesize) {
switch (((bmg_section_t*)pSection)->magic) {
case 'FLW1':
break;
case 'FLI1':
break;
case 'INF1':
pInfoBlock = (bmg_section_t*)pSection;
break;
case 'DAT1':
pMsgDataBlock = pSection;
break;
case 'STR1':
pStrAttributeBlock = (str1_section_t*)pSection;
break;
}
filepos += ((bmg_section_t*)pSection)->size;
pSection += ((bmg_section_t*)pSection)->size;
}
#else
for (; filepos < filesize; filepos += ((bmg_section_t*)pSection)->size) {
switch (((bmg_section_t*)pSection)->magic) {
case 'FLW1':
@@ -289,6 +313,7 @@ void dMsgUnit_c::setTag(int i_type, int i_value, char* o_buffer, bool param_4) {
}
pSection += ((bmg_section_t*)pSection)->size;
}
#endif
// This section is weird. The debug seems like entriesStr is outside the condition
// but the normal build doesn't really work with that. Same for pInfoBlock->entries.
+5 -5
View File
@@ -1288,7 +1288,11 @@ void dName_c::selectCursorPosSet(int row) {
#if TARGET_PC
void dName_c::nameWide() {
//Resize Select Icon
mSelIcon->setParam(0.82f * mDoGph_gInf_c::hudAspectScaleUp, 0.77f, 0.05f, 0.4f, 0.4f);
#if TARGET_PC
if (mSelIcon) {
mSelIcon->refreshAspectScale();
}
#endif
// List of Characters Box
static u64 l_tagName[65] = {
@@ -1540,11 +1544,7 @@ void dName_c::screenSet() {
mSelIcon = JKR_NEW dSelect_cursor_c(0, 1.0f, NULL);
JUT_ASSERT(0, mSelIcon != NULL);
#if TARGET_PC
mSelIcon->setParam(0.82f * mDoGph_gInf_c::hudAspectScaleUp, 0.77f, 0.05f, 0.4f, 0.4f);
#else
mSelIcon->setParam(0.82f, 0.77f, 0.05f, 0.4f, 0.4f);
#endif
Vec pos = mMojiIcon[mCharRow + mCharColumn * 5]->getGlobalVtxCenter(false, 0);
mSelIcon->setPos(pos.x, pos.y, mMojiIcon[mCharRow + mCharColumn * 5]->getPanePtr(), true);
+2 -2
View File
@@ -26,8 +26,8 @@ static void dOvlpFd_startFadeIn(int param_0) {
JUTFader* fader = JFWDisplay::getManager()->getFader();
JUT_ASSERT(0, fader != NULL);
fader->setStatus(JUTFader::UNKSTATUS_0, 0);
fader->setStatus(JUTFader::UNKSTATUS_0, -1);
fader->setStatus(JUTFader::None, 0);
fader->setStatus(JUTFader::None, -1);
fader->startFadeIn(param_0);
}
+5 -1
View File
@@ -296,7 +296,11 @@ J3DModelData* dRes_info_c::loaderBasicBmd(u32 i_tag, void* i_data) {
addWarpMaterial(modelData);
}
if (i_tag == 'BMDR' || i_tag == 'BMWR') {
// FRAME INTERP NOTE: Always create shared DL buffers so we can use J3DMaterial::diff()
#ifndef TARGET_PC
if (i_tag == 'BMDR' || i_tag == 'BMWR')
#endif
{
s32 result = modelData->newSharedDisplayList(J3DMdlFlag_UseSingleDL);
if (result != kJ3DError_Success) {
return NULL;
+19
View File
@@ -69,6 +69,9 @@ dSelect_cursor_c::dSelect_cursor_c(u8 param_0, f32 param_1, JKRArchive* param_2)
field_0x84[i] = 0.0f;
}
mParam1 = mpCursorHIO->mXAxisExpansion;
#ifdef TARGET_PC
mBaseParam1 = mParam1;
#endif
mParam2 = mpCursorHIO->mYAxisExpansion;
mParam3 = mpCursorHIO->mOscillation;
mParam4 = mpCursorHIO->mRatioX;
@@ -259,6 +262,13 @@ void dSelect_cursor_c::update() {
if (field_0xb6 == 3) {
fVar1 = 0.5f;
}
#ifdef TARGET_PC
if (mpPane) {
Vec pos = mpPaneMgr->getGlobalVtxCenter(mpPane, false, 0);
mPositionX = pos.x;
mPositionY = pos.y;
}
#endif
mpPaneMgr->translate(mPositionX, mPositionY);
if (mpCursorHIO->mDebugON) {
mParam1 = mpCursorHIO->mXAxisExpansion;
@@ -404,6 +414,9 @@ void dSelect_cursor_c::setPos(f32 i_posX, f32 i_posY, J2DPane* i_pane, bool i_sc
void dSelect_cursor_c::setParam(f32 i_param1, f32 i_param2, f32 i_param3, f32 i_param4,
f32 i_param5) {
mParam1 = i_param1;
#ifdef TARGET_PC
mBaseParam1 = i_param1;
#endif
mParam2 = i_param2;
mParam3 = i_param3;
mParam4 = i_param4;
@@ -562,3 +575,9 @@ void dSelect_cursor_c::setBckAnimation(J2DAnmTransformKey* param_0) {
void dSelect_cursor_c::moveCenter(J2DPane* i_pane, f32 i_x, f32 i_y) {
i_pane->translate(i_x,i_y);
}
#ifdef TARGET_PC
void dSelect_cursor_c::refreshAspectScale() {
mParam1 = mBaseParam1 * mDoGph_gInf_c::hudAspectScaleUp;
}
#endif
+8
View File
@@ -77,6 +77,14 @@ void dusk::audio::SetMasterVolume(const f32 value) {
MasterVolume = value;
}
void dusk::audio::SetPaused(const bool paused) {
if (paused) {
SDL_PauseAudioStreamDevice(PlaybackStream);
} else {
SDL_ResumeAudioStreamDevice(PlaybackStream);
}
}
void dusk::audio::SetEnableReverb(const bool value) {
JASCriticalSection section;
+132 -10
View File
@@ -5,14 +5,15 @@
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <span>
#include "Adpcm.hpp"
#include "freeverb/revmodel.hpp"
#include "JSystem/JAudio2/JASDriverIF.h"
#include "dusk/audio/DuskAudioSystem.h"
#include "dusk/endian.h"
#include "dusk/logging.h"
#include "global.h"
#include "tracy/Tracy.hpp"
@@ -95,6 +96,13 @@ static void RenderChannel(
ChannelAuxData& channelAux,
OutputSubframe& subframe);
static void RenderOutputChannel(
const JASDsp::TChannel& sourceChannel,
ChannelAuxData& aux,
OutputChannel outputChannel,
const std::span<f32> inputSamples,
OutputSubframe& fullOutputSubframe);
/**
* Converts a pitch value on a DSP channel to a sample rate.
*/
@@ -117,6 +125,8 @@ static void ResetChannel(JASDsp::TChannel& channel, ChannelAuxData& aux) {
aux.resamplePos = 0.0;
aux.resamplePrev = 0;
aux.oscPhase = 0;
aux.prev_lp_out = 0.0f;
aux.prev_lp_in = 0.0f;
@@ -141,6 +151,119 @@ static void MixSubframe(DspSubframe& dst, const DspSubframe& src) {
}
}
enum class OscType : u16 {
SQUARE_WAVE_PW_50 = 0,
SAW_WAVE = 1,
SQUARE_WAVE_PW_25 = 3,
TRIANGLE_WAVE = 4,
// idk what 5 and 6 are
SINE_WAVE = 7,
// idk what 8 and 9 are
SINE_WAVE_VAR_STEP = 10,
EVOLVING_HARMONIC = 11,
EVOLVING_RAMP = 12,
};
static s16 gEvolvingHarmonic[64];
static void GenerateEvolvingHarmonic() {
static bool initialized = false;
if (!initialized) {
gEvolvingHarmonic[62] = 8191;
gEvolvingHarmonic[63] = 16383;
initialized = true;
}
u32 prev2 = (u32)gEvolvingHarmonic[62];
u32 prev1 = (u32)gEvolvingHarmonic[63];
for (int i = 0; i < 64; i += 2) {
u32 cur = (u32)gEvolvingHarmonic[i];
gEvolvingHarmonic[i] = (s16)((s32)(prev2 * prev1 - (cur << 16)) >> 16);
prev2 = prev1;
prev1 = cur;
cur = (u32)gEvolvingHarmonic[i + 1];
gEvolvingHarmonic[i + 1] = (s16)((s32)(2u * (prev2 * prev1 + (cur << 16))) >> 16);
prev2 = prev1;
prev1 = cur;
}
}
static void RenderOscChannel(
JASDsp::TChannel& channel,
ChannelAuxData& channelAux,
OutputSubframe& subframe) {
if (channel.mResetFlag)
ResetChannel(channel, channelAux);
const u32 pitch = channel.mPitch;
DspSubframe buf = {};
const auto oscType = static_cast<OscType>(channel.mBytesPerBlock);
switch (oscType) {
case OscType::SQUARE_WAVE_PW_50: {
std::generate(buf.begin(), buf.end(), [&] {
f32 s = channelAux.oscPhase < 0x8000u ? 0.5f : -0.5f;
channelAux.oscPhase += pitch >> 1;
return s;
});
break;
}
case OscType::SQUARE_WAVE_PW_25: {
std::generate(buf.begin(), buf.end(), [&] {
f32 s = channelAux.oscPhase < 0x4000u ? 0.5f : -0.5f;
channelAux.oscPhase += pitch >> 1;
return s;
});
break;
}
case OscType::SAW_WAVE:
case OscType::EVOLVING_RAMP: {
std::generate(buf.begin(), buf.end(), [&] {
f32 s = (f32)(s16)channelAux.oscPhase / 32768.0f;
channelAux.oscPhase += pitch >> 1;
return s;
});
break;
}
case OscType::SINE_WAVE:
case OscType::SINE_WAVE_VAR_STEP: {
std::generate(buf.begin(), buf.end(), [&] {
f32 s = sinf((f32)channelAux.oscPhase * (2.0f * M_PI / 65536.0f)) * 0.5f;
channelAux.oscPhase += pitch >> 1;
return s;
});
break;
}
case OscType::TRIANGLE_WAVE: {
std::generate(buf.begin(), buf.end(), [&] {
f32 s = 0.5f - fabsf((f32)(s16)channelAux.oscPhase / 32768.0f);
channelAux.oscPhase += pitch >> 1;
return s;
});
break;
}
case OscType::EVOLVING_HARMONIC: {
std::generate(buf.begin(), buf.end(), [&] {
f32 s = gEvolvingHarmonic[channelAux.oscPhase >> 10] / 32768.0f;
channelAux.oscPhase += pitch >> 1;
return s;
});
break;
}
default:
DuskLog.error("RenderOscChannel: unimplemented oscillator type {}", channel.mBytesPerBlock);
break;
}
auto samples = std::span(buf).subspan(0, DSP_SUBFRAME_SIZE);
RenderOutputChannel(channel, channelAux, OutputChannel::LEFT, samples, subframe);
RenderOutputChannel(channel, channelAux, OutputChannel::RIGHT, samples, subframe);
}
void dusk::audio::DspRender(OutputSubframe& subframe) {
ZoneScoped;
if (DumpAudio != sDumpWasActive) {
@@ -152,6 +275,8 @@ void dusk::audio::DspRender(OutputSubframe& subframe) {
}
}
GenerateEvolvingHarmonic();
std::span channels(JASDsp::CH_BUF, DSP_CHANNELS);
DspSubframe reverbInputL = {};
@@ -174,17 +299,14 @@ void dusk::audio::DspRender(OutputSubframe& subframe) {
channel.mIsFinished = true;
continue;
}
else if (channel.mWaveAramAddress == 0) {
// I think these are oscillator channels? Not backed by audio.
// No idea how to implement these yet, so skip them.
channel.mIsFinished = true;
continue;
}
ValidateChannel(channel);
OutputSubframe channelSubframe = {};
RenderChannel(channel, channelAux, channelSubframe);
if (channel.mWaveAramAddress == 0) {
RenderOscChannel(channel, channelAux, channelSubframe);
} else {
ValidateChannel(channel);
RenderChannel(channel, channelAux, channelSubframe);
}
if (EnableReverb) {
// scale the input to the reverb rather than using wet/dry on the output.
+3
View File
@@ -53,6 +53,9 @@ namespace dusk::audio {
// last consumed sample from decodeBuf
s16 resamplePrev;
// phase of oscillator channels
u16 oscPhase;
// low pass previous state
f32 prev_lp_out; // out[n-1]
f32 prev_lp_in; // in[n-1]
+2 -2
View File
@@ -10,7 +10,7 @@
#include <limits>
#include <string>
#include "dusk/dusk.h"
#include "dusk/main.h"
using namespace dusk::config;
@@ -24,7 +24,7 @@ static absl::flat_hash_map<std::string_view, ConfigVarBase*> RegisteredConfigVar
static bool RegistrationDone = false;
static std::string GetConfigJsonPath() {
return fmt::format("{}{}", configPath, ConfigFileName);
return (dusk::ConfigPath / ConfigFileName).string();
}
ConfigVarBase::ConfigVarBase(const char* name, const ConfigImplBase* impl) : name(name), registered(false), layer(ConfigVarLayer::Default), impl(impl) {
+2 -1
View File
@@ -3,6 +3,7 @@
#include "dusk/app_info.hpp"
#include "dusk/dusk.h"
#include "dusk/logging.h"
#include "dusk/main.h"
#include "dusk/settings.h"
#include "version.h"
@@ -66,7 +67,7 @@ std::string GetReleaseName() {
}
std::filesystem::path GetSentryDatabasePath() {
return std::filesystem::path(configPath) / "sentry";
return dusk::ConfigPath / "sentry";
}
std::filesystem::path GetLogAttachmentPath() {
+122
View File
@@ -0,0 +1,122 @@
#ifdef DUSK_DISCORD_RPC
#include "dusk/discord_presence.hpp"
#include "dusk/logging.h"
#include "dusk/main.h"
#include "dusk/map_loader_definitions.h"
#include "d/d_com_inf_game.h"
#include "discord_rpc.h"
#include "fmt/format.h"
#include <chrono>
#include <cstring>
#include <string>
namespace dusk {
namespace discord {
static int64_t g_startTime = 0;
static bool g_initialized = false;
static const char* APPLICATION_ID = "1495632471994405035";
static void OnReady(const DiscordUser* user) {
DuskLog.info("Discord: Connected as {}", user->username);
}
static void OnDisconnected(int errorCode, const char* message) {
DuskLog.warn("Discord: Disconnected ({}: {})", errorCode, message);
}
static void OnError(int errorCode, const char* message) {
DuskLog.warn("Discord: Error ({}: {})", errorCode, message);
}
static const char* LookupMapName(const char* mapFile) {
if (!mapFile || mapFile[0] == '\0') return nullptr;
for (const auto& region : gameRegions) {
for (const auto& map : region.maps) {
if (map.mapFile && strcmp(mapFile, map.mapFile) == 0) {
return map.mapName;
}
}
}
return nullptr;
}
void Initialize() {
g_startTime = static_cast<int64_t>(
std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()
).count()
);
DiscordEventHandlers handlers{};
handlers.ready = OnReady;
handlers.disconnected = OnDisconnected;
handlers.errored = OnError;
Discord_Initialize(APPLICATION_ID, &handlers, 0, nullptr);
g_initialized = true;
DuskLog.info("Discord Rich Presence initialized");
}
void RunCallbacks() {
if (!g_initialized) return;
Discord_RunCallbacks();
}
void UpdatePresence() {
if (!g_initialized) return;
static auto lastUpdate = std::chrono::steady_clock::time_point{};
const auto now = std::chrono::steady_clock::now();
if (now - lastUpdate < std::chrono::seconds(15)) return;
lastUpdate = now;
static std::string detailsBuf;
static std::string stateBuf;
DiscordRichPresence presence{};
presence.startTimestamp = g_startTime;
presence.largeImageKey = "icon";
presence.largeImageText = "Dusk";
if (dusk::IsGameLaunched) {
const char* stageName = dComIfGp_getLastPlayStageName();
// stageName is empty until a room is actually entered
if (stageName[0] != '\0') {
const char* locationName = LookupMapName(stageName);
if (locationName) {
detailsBuf = locationName;
}
else {
detailsBuf = "Twilight Princess";
}
presence.details = detailsBuf.c_str();
stateBuf = fmt::format(FMT_STRING("{}/{} \u2665 | {} Rupees"),
dComIfGs_getLife() / 4, dComIfGs_getMaxLife() / 5, dComIfGs_getRupee());
presence.state = stateBuf.c_str();
}
}
Discord_UpdatePresence(&presence);
DuskLog.debug("Discord Rich Presence sent");
}
void Shutdown() {
if (!g_initialized) return;
Discord_ClearPresence();
Discord_Shutdown();
g_initialized = false;
DuskLog.info("Discord Rich Presence shut down");
}
} // namespace discord
} // namespace dusk
#endif // DUSK_DISCORD_RPC
+21 -5
View File
@@ -3,6 +3,27 @@
#include <string.h>
#include <stdint.h>
#ifdef _MSC_VER
#include <intrin.h>
#endif
void __dcbz(void* addr, int offset) {
// Gekko cache lines are 32 bytes.
// dcbz usually requires addr to be 32-byte aligned.
memset((char*)addr + offset, 0, 32);
}
int __cntlzw(unsigned int val) {
if (val == 0) return 32; // PowerPC returns 32 if the input is 0
#ifdef _MSC_VER
unsigned long idx;
_BitScanReverse(&idx, val);
return 31 - (int)idx;
#else
return __builtin_clz(val);
#endif
}
#ifndef _MSC_VER
int stricmp(const char* str1, const char* str2) {
char a_var;
@@ -48,11 +69,6 @@ int strnicmp(const char* str1, const char* str2, int n) {
}
#endif
void *_memcpy(void* dest, void const* src, int n) {
return memcpy(dest, src, n);
}
void DCZeroRange(void* addr, uint32_t nBytes) {
#if defined(_MSC_VER) || TARGET_ANDROID
memset(addr, 0, nBytes);
-27
View File
@@ -1,27 +0,0 @@
// C++ Mangled version of extras.c
#include <cstring>
#include <cstdint>
#ifdef _MSC_VER
#include <intrin.h>
#endif
void *__memcpy(void* dest, void const* src, int n) {
return memcpy(dest, src, n);
}
void __dcbz(void* addr, int offset) {
// Gekko cache lines are 32 bytes.
// dcbz usually requires addr to be 32-byte aligned.
memset((char*)addr + offset, 0, 32);
}
int __cntlzw(unsigned int val) {
if (val == 0) return 32; // PowerPC returns 32 if the input is 0
#ifdef _MSC_VER
unsigned long idx;
_BitScanReverse(&idx, val);
return 31 - (int)idx;
#else
return __builtin_clz(val);
#endif
}
+129 -306
View File
@@ -1,63 +1,16 @@
#include "dusk/frame_interpolation.h"
#include <memory>
#include "mtx.h"
#include "f_op/f_op_camera_mng.h"
#include "m_Do/m_Do_graphic.h"
namespace {
enum class Op : uint8_t {
OpenChild,
FinalMtx,
};
struct Label {
const void* key = nullptr;
int32_t id = 0;
bool operator==(const Label& other) const {
return key == other.key && id == other.id;
}
};
struct Data {
Label child_label{};
size_t child_index = 0;
Mtx matrix{};
const Mtx* dest = nullptr;
uint64_t stable_tag = 0;
};
struct Path;
struct ChildBucket {
Label label{};
std::vector<std::unique_ptr<Path>> nodes;
};
struct OpBucket {
Op op = Op::OpenChild;
std::vector<Data> values;
};
struct Path {
std::vector<ChildBucket> children;
std::vector<OpBucket> ops;
std::vector<std::pair<Op, size_t>> items;
Label draw_scope{};
uint32_t simple_shadow_pair_seq = 0;
};
struct Recording {
Path root;
std::unordered_map<uintptr_t, Mtx> matrix_values;
};
struct MatrixValue {
Mtx value;
};
using FinalMtxLookup = std::unordered_map<const Mtx*, const Data*>;
using FinalMtxLookupTagged = std::unordered_map<uint64_t, const Data*>;
bool s_initialized = false;
bool g_enabled = false;
@@ -66,13 +19,13 @@ bool g_interpolating = false;
bool g_sync_presentation = false;
float g_step = 0.0f;
bool g_is_sim_frame = false;
bool g_ui_tick_pending = false;
Recording g_current_recording;
Recording g_previous_recording;
std::vector<Path*> g_current_path;
std::unordered_map<const Mtx*, MatrixValue> g_replacements;
std::unordered_map<uintptr_t, Mtx> g_replacements;
struct CameraSnapshot {
cXyz eye{};
@@ -93,6 +46,13 @@ CameraSnapshot s_cam_curr{};
view_class s_presentation_view_backup{};
int s_presentation_depth = 0;
struct InterpolationCallBackWork {
dusk::frame_interp::InterpolationCallBack pCallBack;
void* pUserWork;
};
std::vector<InterpolationCallBackWork> s_interpolationCallBackWork;
void copy_view_to_snap(CameraSnapshot* dst, const view_class& v) {
dst->eye = v.lookat.eye;
dst->center = v.lookat.center;
@@ -105,14 +65,6 @@ void copy_view_to_snap(CameraSnapshot* dst, const view_class& v) {
dst->valid = true;
}
inline void copy_matrix(const Mtx src, Mtx dst) {
MTXCopy(src, dst);
}
inline void concat_matrix(const Mtx lhs, const Mtx rhs, Mtx out) {
MTXConcat(lhs, rhs, out);
}
inline void lerp_matrix(Mtx out, const Mtx lhs, const Mtx rhs, float step) {
const float old_weight = 1.0f - step;
for (size_t row = 0; row < 3; ++row) {
@@ -146,162 +98,22 @@ inline bool matrix_differs(const Mtx lhs, const Mtx rhs, float epsilon = 0.0001f
return false;
}
Data& append_op(Op op) {
auto& items = g_current_path.back()->items;
auto& buckets = g_current_path.back()->ops;
auto it = std::find_if(buckets.begin(), buckets.end(),
[op](const OpBucket& bucket) { return bucket.op == op; });
if (it == buckets.end()) {
buckets.push_back({op, {}});
it = buckets.end() - 1;
}
items.emplace_back(op, it->values.size());
return it->values.emplace_back();
}
const Data* find_matching_data(const Path& path, Op op, size_t index) {
auto it = std::find_if(path.ops.begin(), path.ops.end(),
[op](const OpBucket& bucket) { return bucket.op == op; });
if (it == path.ops.end() || index >= it->values.size()) {
return nullptr;
}
return &it->values[index];
}
const OpBucket* find_op_bucket(const Path& path, Op op) {
auto it = std::find_if(path.ops.begin(), path.ops.end(),
[op](const OpBucket& bucket) { return bucket.op == op; });
if (it == path.ops.end()) {
return nullptr;
}
return &*it;
}
void build_final_mtx_lookups(const Path& path, FinalMtxLookup& dest_lookup, FinalMtxLookupTagged& tag_lookup) {
dest_lookup.clear();
tag_lookup.clear();
const OpBucket* bucket = find_op_bucket(path, Op::FinalMtx);
if (bucket == nullptr) {
return;
}
for (const Data& data : bucket->values) {
if (data.dest != nullptr) {
dest_lookup[data.dest] = &data;
}
if (data.stable_tag != 0) {
tag_lookup[data.stable_tag] = &data;
}
}
}
const Data* find_matching_final_mtx(const FinalMtxLookup& lookup, const Data& new_data) {
if (new_data.dest == nullptr) {
return nullptr;
}
auto it = lookup.find(new_data.dest);
if (it == lookup.end()) {
return nullptr;
}
return it->second;
}
ChildBucket& get_child_bucket(Path& path, const Label& label) {
auto it = std::find_if(path.children.begin(), path.children.end(),
[&label](const ChildBucket& bucket) { return bucket.label == label; });
if (it == path.children.end()) {
path.children.push_back({});
it = path.children.end() - 1;
it->label = label;
}
return *it;
}
const ChildBucket* find_child_bucket(const Path& path, const Label& label) {
auto it = std::find_if(path.children.begin(), path.children.end(),
[&label](const ChildBucket& bucket) { return bucket.label == label; });
if (it == path.children.end()) {
return nullptr;
}
return &*it;
}
void store_replacement(const Data& old_data, const Data& new_data, float step) {
if (new_data.dest == nullptr) {
return;
}
auto& replacement = g_replacements[new_data.dest];
lerp_matrix(replacement.value, old_data.matrix, new_data.matrix, step);
}
void interpolate_branch(const Path& old_path, const Path& new_path, float step) {
FinalMtxLookup old_final_mtx_lookup;
FinalMtxLookupTagged old_final_mtx_lookup_tagged;
build_final_mtx_lookups(old_path, old_final_mtx_lookup, old_final_mtx_lookup_tagged);
for (const auto& item : new_path.items) {
const Op op = item.first;
const size_t index = item.second;
const Data* new_data = find_matching_data(new_path, op, index);
if (new_data == nullptr) {
continue;
}
if (op == Op::OpenChild) {
const ChildBucket* new_children = find_child_bucket(new_path, new_data->child_label);
if (new_children == nullptr || new_data->child_index >= new_children->nodes.size())
{
continue;
}
const Path& new_child = *new_children->nodes[new_data->child_index];
const ChildBucket* old_children = find_child_bucket(old_path, new_data->child_label);
if (old_children != nullptr && new_data->child_index < old_children->nodes.size())
{
interpolate_branch(*old_children->nodes[new_data->child_index], new_child, step);
} else {
interpolate_branch(new_child, new_child, step);
}
continue;
}
const Data* indexed_old_data = find_matching_data(old_path, op, index);
const Data* old_data = nullptr;
if (op == Op::FinalMtx) {
if (new_data->stable_tag != 0) {
const auto it = old_final_mtx_lookup_tagged.find(new_data->stable_tag);
old_data = it != old_final_mtx_lookup_tagged.end() ? it->second : nullptr;
} else {
old_data = find_matching_final_mtx(old_final_mtx_lookup, *new_data);
}
} else {
old_data = indexed_old_data;
}
if (op == Op::FinalMtx) {
store_replacement(old_data != nullptr ? *old_data : *new_data, *new_data, step);
}
}
}
const Mtx* resolve_replacement(const Mtx* source, Mtx* scratch) {
if (!g_interpolating || source == nullptr || dusk::frame_interp::presentation_sync_active()) {
return source;
}
auto it = g_replacements.find(source);
auto it = g_replacements.find(reinterpret_cast<uintptr_t>(source));
if (it == g_replacements.end()) {
return source;
}
copy_matrix(it->second.value, *scratch);
MTXCopy(it->second, *scratch);
return scratch;
}
bool has_recording_data(const Recording& recording) {
return !recording.root.items.empty() || !recording.root.children.empty();
return !recording.matrix_values.empty();
}
void clear_replacements() {
@@ -312,10 +124,33 @@ void clear_replacements() {
namespace dusk::frame_interp {
void ensure_initialized() {
g_enabled = getSettings().game.enableFrameInterpolation;
s_initialized = true;
}
void begin_sim_tick() {
ensure_initialized();
if (!g_enabled) {
return;
}
s_interpolationCallBackWork.clear();
s_cam_prev = std::move(s_cam_curr);
}
void begin_frame(bool enabled, bool is_sim_frame, float step) {
g_enabled = enabled;
g_is_sim_frame = is_sim_frame;
g_step = std::clamp(step, 0.0f, 1.0f);
}
bool is_enabled() {
return g_enabled;
}
bool is_sim_frame() {
return g_is_sim_frame;
}
void begin_record() {
ensure_initialized();
@@ -324,7 +159,6 @@ void begin_record() {
g_sync_presentation = false;
g_previous_recording = {};
g_current_recording = {};
g_current_path.clear();
clear_replacements();
s_cam_prev.valid = false;
s_cam_curr.valid = false;
@@ -334,8 +168,6 @@ void begin_record() {
g_sync_presentation = false;
g_previous_recording = std::move(g_current_recording);
g_current_recording = {};
g_current_path.clear();
g_current_path.push_back(&g_current_recording.root);
g_recording = true;
g_interpolating = false;
clear_replacements();
@@ -345,11 +177,6 @@ void begin_record() {
s_cam_prev.valid = false;
s_cam_curr.valid = false;
return;
} else {
copy_view_to_snap(&s_cam_prev, cam->view);
#if WIDESCREEN_SUPPORT
s_cam_prev.wideZoom = s_cam_curr.valid ? s_cam_curr.wideZoom : false;
#endif
}
}
@@ -357,16 +184,20 @@ void end_record() {
g_recording = false;
}
void interpolate(float step) {
void interpolate() {
ensure_initialized();
clear_replacements();
g_step = std::clamp(step, 0.0f, 1.0f);
g_interpolating = g_enabled && !g_recording && !g_sync_presentation && has_recording_data(g_current_recording);
if (!g_interpolating) {
return;
}
const Path& old_root = has_recording_data(g_previous_recording) ? g_previous_recording.root : g_current_recording.root;
interpolate_branch(old_root, g_current_recording.root, g_step);
for (auto const& old : g_previous_recording.matrix_values) {
if (auto it = g_current_recording.matrix_values.find(old.first);
it != g_current_recording.matrix_values.end())
{
lerp_matrix(g_replacements[old.first], old.second, it->second, g_step);
}
}
}
void request_presentation_sync() {
@@ -399,63 +230,30 @@ bool get_ui_tick_pending() {
return g_enabled ? g_ui_tick_pending : true;
}
void open_child(const void* key, int32_t id) {
if (!s_initialized || !g_recording) {
void record_final_mtx(Mtx m, const void* key) {
if (!s_initialized || !g_recording || m == nullptr) {
return;
}
Label label{key, id};
auto& siblings = get_child_bucket(*g_current_path.back(), label).nodes;
Data& data = append_op(Op::OpenChild);
data.child_label = label;
data.child_index = siblings.size();
siblings.emplace_back(std::make_unique<Path>());
Path* const child = siblings.back().get();
child->draw_scope = label;
g_current_path.push_back(child);
auto& it = g_current_recording.matrix_values[reinterpret_cast<uintptr_t>(key)];
MTXCopy(m, it);
}
void close_child() {
if (!s_initialized || !g_recording || g_current_path.size() <= 1) {
return;
}
g_current_path.pop_back();
void record_final_mtx(Mtx m) {
record_final_mtx(m, m);
}
void record_final_mtx_raw(const Mtx* dest, const Mtx src) {
if (!s_initialized || !g_recording || dest == nullptr) {
return;
}
Data& data = append_op(Op::FinalMtx);
data.dest = dest;
data.stable_tag = 0;
copy_matrix(src, data.matrix);
}
void record_final_mtx_raw_tagged(const Mtx* dest, const Mtx src, uint64_t stable_tag) {
if (!s_initialized || !g_recording || dest == nullptr) {
return;
}
Data& data = append_op(Op::FinalMtx);
data.dest = dest;
data.stable_tag = stable_tag;
copy_matrix(src, data.matrix);
}
bool lookup_replacement(const void* source, Mtx out) {
if (presentation_sync_active() || !g_interpolating || source == nullptr) {
bool lookup_replacement(const void* key, Mtx out) {
if (presentation_sync_active() || !g_interpolating || key == nullptr) {
return false;
}
auto it = g_replacements.find(reinterpret_cast<const Mtx*>(source));
auto it = g_replacements.find(reinterpret_cast<uintptr_t>(key));
if (it == g_replacements.end()) {
return false;
}
copy_matrix(it->second.value, out);
MTXCopy(it->second, out);
return true;
}
@@ -472,7 +270,7 @@ bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out) {
return false;
}
concat_matrix(*resolved_lhs, *resolved_rhs, out);
MTXConcat(*resolved_lhs, *resolved_rhs, out);
return true;
}
@@ -486,6 +284,74 @@ void record_camera(::camera_process_class* cam, int camera_id) {
#endif
}
void interp_view(::view_class* view) {
if (!g_enabled)
return;
if (!s_cam_prev.valid || !s_cam_curr.valid)
return;
const f32 step = get_interpolation_step();
const bool is_cam_curr_authoritative = g_is_sim_frame && step <= 0.0f;
cXyz eye;
cXyz center;
cXyz up;
if (is_cam_curr_authoritative) {
eye = s_cam_curr.eye;
center = s_cam_curr.center;
up = s_cam_curr.up;
} else {
lerp_xyz(&eye, s_cam_prev.eye, s_cam_curr.eye, step);
lerp_xyz(&center, s_cam_prev.center, s_cam_curr.center, step);
lerp_xyz(&up, s_cam_prev.up, s_cam_curr.up, step);
}
if (!up.normalizeRS()) {
up = s_cam_curr.up;
up.normalizeRS();
}
view->lookat.eye = eye;
view->lookat.center = center;
view->lookat.up = up;
if (is_cam_curr_authoritative) {
view->bank = s_cam_curr.bank;
view->fovy = s_cam_curr.fovy;
view->aspect = s_cam_curr.aspect;
view->near_ = s_cam_curr.near_;
view->far_ = s_cam_curr.far_;
} else {
view->bank = lerp_bank(s_cam_prev.bank, s_cam_curr.bank, step);
view->fovy = s_cam_prev.fovy + (s_cam_curr.fovy - s_cam_prev.fovy) * step;
view->aspect = s_cam_prev.aspect + (s_cam_curr.aspect - s_cam_prev.aspect) * step;
view->near_ = s_cam_prev.near_ + (s_cam_curr.near_ - s_cam_prev.near_) * step;
view->far_ = s_cam_prev.far_ + (s_cam_curr.far_ - s_cam_prev.far_) * step;
}
// FRAME INTERP TODO: It might be better if I rewired the game to not clear this flag until the
// next sim frame, but I don't care enough to right now
#if WIDESCREEN_SUPPORT
const f32 wide_step = is_cam_curr_authoritative ? 1.0f : step;
if (mDoGph_gInf_c::isWide() && !mDoGph_gInf_c::isWideZoom() && wide_step >= 0.5f ? s_cam_curr.wideZoom : s_cam_prev.wideZoom) {
mDoGph_gInf_c::onWideZoom();
}
#endif
}
static void run_interpolation_callbacks() {
for (size_t i = 0; i < s_interpolationCallBackWork.size(); i++) {
auto const& work = s_interpolationCallBackWork[i];
work.pCallBack(g_is_sim_frame, work.pUserWork);
}
}
void add_interpolation_callback(InterpolationCallBack pCallBack, void* pUserWork) {
if (!is_enabled() || s_presentation_depth > 0 || !g_is_sim_frame)
return;
s_interpolationCallBackWork.emplace_back(pCallBack, pUserWork);
}
void begin_presentation_camera() {
ensure_initialized();
if (!g_enabled) {
@@ -505,34 +371,7 @@ void begin_presentation_camera() {
}
std::memcpy(&s_presentation_view_backup, view, sizeof(view_class));
const f32 step = get_interpolation_step();
cXyz eye;
cXyz center;
cXyz up;
lerp_xyz(&eye, s_cam_prev.eye, s_cam_curr.eye, step);
lerp_xyz(&center, s_cam_prev.center, s_cam_curr.center, step);
lerp_xyz(&up, s_cam_prev.up, s_cam_curr.up, step);
if (!up.normalizeRS()) {
up = s_cam_curr.up;
up.normalizeRS();
}
view->lookat.eye = eye;
view->lookat.center = center;
view->lookat.up = up;
view->bank = lerp_bank(s_cam_prev.bank, s_cam_curr.bank, step);
view->fovy = s_cam_prev.fovy + (s_cam_curr.fovy - s_cam_prev.fovy) * step;
view->aspect = s_cam_prev.aspect + (s_cam_curr.aspect - s_cam_prev.aspect) * step;
view->near_ = s_cam_prev.near_ + (s_cam_curr.near_ - s_cam_prev.near_) * step;
view->far_ = s_cam_prev.far_ + (s_cam_curr.far_ - s_cam_prev.far_) * step;
// FRAME INTERP TODO: It might be better if I rewired the game to not clear this flag until the next sim frame, but I don't care enough to right now
#if WIDESCREEN_SUPPORT
if (mDoGph_gInf_c::isWide() && !mDoGph_gInf_c::isWideZoom() && step >= 0.5f ? s_cam_curr.wideZoom : s_cam_prev.wideZoom) {
mDoGph_gInf_c::onWideZoom();
}
#endif
interp_view(view);
// FRAME INTERP TODO: Largely copied from d_camera's camera_draw function from this point, got any better ideas?
C_MTXPerspective(view->projMtx, view->fovy, view->aspect, view->near_, view->far_);
@@ -590,11 +429,11 @@ void begin_presentation_camera() {
mDoLib_clipper::setup(view->fovy, view->aspect, view->near_, far_);
#if WIDESCREEN_SUPPORT
mDoGph_gInf_c::offWideZoom();
#endif
// FRAME INTERP NOTE: Removed the call to offWideZoom that was here, it causes problems with presentation during cutscenes.
s_presentation_depth = 1;
run_interpolation_callbacks();
}
void end_presentation_camera() {
@@ -611,20 +450,4 @@ void end_presentation_camera() {
std::memcpy(view, &s_presentation_view_backup, sizeof(view_class));
}
}
uint64_t alloc_simple_shadow_pair_base() {
if (!s_initialized || !g_recording || g_current_path.size() <= 1) {
return 0;
}
Path* const scope = g_current_path.back();
const uint64_t h = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(scope->draw_scope.key));
const uint32_t lo = scope->simple_shadow_pair_seq;
scope->simple_shadow_pair_seq += 2;
uint64_t tag0 = (h << 17) ^ (static_cast<uint64_t>(lo) << 1u);
if (tag0 == 0) {
tag0 = 2;
}
return tag0;
}
} // namespace dusk::frame_interp
+47 -20
View File
@@ -2,59 +2,87 @@
#include <algorithm>
#include <chrono>
#include <cmath>
#include <unordered_map>
namespace dusk {
namespace game_clock {
namespace dusk::game_clock {
using clock = std::chrono::steady_clock;
bool s_initialized = false;
clock::time_point s_previous_sample{};
float s_sim_accumulator = 0.0f;
clock::time_point s_current_snapshot_time{};
std::unordered_map<uintptr_t, clock::time_point> s_interval_last_sample;
constexpr clock::duration kSimPeriodDuration =
std::chrono::duration_cast<clock::duration>(std::chrono::duration<float>(sim_pace()));
constexpr clock::duration kAbnormalGapResetThreshold = std::chrono::milliseconds(250);
constexpr int kMaxSimTicksPerFrame = 2;
void ensure_initialized() {
if (s_initialized) {
return;
}
s_previous_sample = clock::now();
s_sim_accumulator = sim_pace();
s_current_snapshot_time = s_previous_sample;
s_initialized = true;
}
void reset_accumulator() {
ensure_initialized();
s_sim_accumulator = 0.0f;
void reset_frame_timer() {
s_previous_sample = clock::now();
s_current_snapshot_time = s_previous_sample - kSimPeriodDuration;
}
MainLoopPacer advance_main_loop() {
ensure_initialized();
const clock::time_point now = clock::now();
const float presentation_dt = std::chrono::duration<float>(now - s_previous_sample).count();
const clock::duration frame_gap = now - s_previous_sample;
const float presentation_dt = std::chrono::duration<float>(frame_gap).count();
s_previous_sample = now;
s_sim_accumulator += presentation_dt;
MainLoopPacer out{};
out.presentation_dt_seconds = presentation_dt;
const bool should_interpolate = dusk::getSettings().game.enableFrameInterpolation && !dusk::getTransientSettings().skipFrameRateLimit;
const bool should_interpolate = dusk::getSettings().game.enableFrameInterpolation &&
!dusk::getTransientSettings().skipFrameRateLimit;
out.is_interpolating = should_interpolate;
out.sim_pace = sim_pace();
if (!should_interpolate) {
s_sim_accumulator = 0.0f;
out.do_sim_tick = true;
out.interpolation_step = 0.0f;
return out;
} else {
out.do_sim_tick = s_sim_accumulator >= sim_pace();
out.interpolation_step = out.do_sim_tick ? 0.0f : s_sim_accumulator / sim_pace();
s_current_snapshot_time = now;
out.sim_ticks_to_run = 1;
return out;
}
if (frame_gap > kAbnormalGapResetThreshold) {
s_current_snapshot_time = now - kSimPeriodDuration;
out.sim_ticks_to_run = 0;
return out;
}
int sim_ticks_to_run = 0;
clock::time_point projected_snapshot_time = s_current_snapshot_time;
const clock::time_point render_time = now - kSimPeriodDuration;
while (sim_ticks_to_run < kMaxSimTicksPerFrame && projected_snapshot_time < render_time) {
projected_snapshot_time += kSimPeriodDuration;
sim_ticks_to_run++;
}
out.sim_ticks_to_run = sim_ticks_to_run;
return out;
}
void commit_sim_tick() {
ensure_initialized();
s_current_snapshot_time += kSimPeriodDuration;
}
float sample_interpolation_step() {
ensure_initialized();
const float step =
std::chrono::duration<float>(clock::now() - s_current_snapshot_time).count() / sim_pace();
return std::clamp(step, 0.0f, 1.0f);
}
float consume_interval(const void* consumer) {
@@ -72,5 +100,4 @@ float consume_interval(const void* consumer) {
return dt;
}
} // namespace game_clock
} // namespace dusk
} // namespace dusk::game_clock
+106
View File
@@ -0,0 +1,106 @@
#include <cmath>
#include <SSystem/SComponent/c_xyz.h>
#include <d/d_com_inf_game.h>
#include <d/actor/d_a_player.h>
#include <d/actor/d_a_alink.h>
#include <dusk/gamepad_color.h>
cXyz currentGamepadColor = {0, 0, 0};
cXyz finalGamepadColor = {0, 0, 0};
cXyz additionalGamepadColor = {0, 0, 0};
float lerpSpeed = 0.0f;
const cXyz duskColor = {50, 50, -50};
const cXyz noColor = {0, 0, 0};
cXyz LerpColor(cXyz a, cXyz b, float t) {
return {std::lerp(a.x, b.x, t), std::lerp(a.y, b.y, t), std::lerp(a.z, b.z, t)};
}
void FadeLED(cXyz newColor, float speed) {
finalGamepadColor = newColor;
lerpSpeed = speed / 30.0f;
}
void SetLED(cXyz newColor) {
currentGamepadColor = newColor;
finalGamepadColor = newColor;
}
void SetGamepadAdditionalColor(cXyz addColor) {
additionalGamepadColor.x = addColor.x;
additionalGamepadColor.y = addColor.y;
additionalGamepadColor.z = addColor.z;
}
void handleGamepadColor() {
bool setColor = false;
fopAc_ac_c* zhint = dComIfGp_att_getZHint();
if (zhint != NULL) {
FadeLED({50, 50, 175}, 2.0f);
setColor = true;
}
daPy_py_c* player = daPy_getPlayerActorClass();
daAlink_c* link = daAlink_getAlinkActorClass();
if (link != nullptr && !setColor) {
if (link->checkWolf()) {
FadeLED({115, 115, 75}, 5.0f);
setColor = true;
} else {
switch (dComIfGs_getSelectEquipClothes()) {
case dItemNo_WEAR_KOKIRI_e:
FadeLED({0, 100, 0}, 5.0f);
setColor = true;
break;
case dItemNo_WEAR_ZORA_e:
FadeLED({0, 0, 100}, 5.0f);
setColor = true;
break;
case dItemNo_ARMOR_e:
if (link->checkMagicArmorHeavy()) {
FadeLED({5, 100, 100}, 5.0f);
} else {
FadeLED({100, 0, 5}, 5.0f);
}
setColor = true;
break;
case dItemNo_WEAR_CASUAL_e:
FadeLED({235, 230, 115}, 5.0f);
setColor = true;
break;
}
}
}
if (dKy_darkworld_check()) {
SetGamepadAdditionalColor(duskColor);
} else {
SetGamepadAdditionalColor(noColor);
}
f32 finalRed = finalGamepadColor.x + additionalGamepadColor.x;
f32 finalGreen = finalGamepadColor.y + additionalGamepadColor.y;
f32 finalBlue = finalGamepadColor.z + additionalGamepadColor.z;
if (finalRed > 255)
finalRed = 255;
if (finalRed < 0)
finalRed = 0;
if (finalGreen > 255)
finalGreen = 255;
if (finalGreen < 0)
finalGreen = 0;
if (finalBlue > 255)
finalBlue = 255;
if (finalBlue < 0)
finalBlue = 0;
currentGamepadColor = LerpColor(currentGamepadColor, cXyz{finalRed, finalGreen, finalBlue}, lerpSpeed);
PADSetColor(PAD_CHAN0, (u8)currentGamepadColor.x, (u8)currentGamepadColor.y, (u8)currentGamepadColor.z);
}
+85 -5
View File
@@ -1,16 +1,29 @@
#include "dusk/gyro.h"
#include "d/actor/d_a_alink.h"
#include <cmath>
namespace dusk::gyro {
namespace {
constexpr s32 kRollgoalTableMaxOffset = 12000;
constexpr s32 kRollgoalTableMaxOffset = 6500;
constexpr float kGyroEmaAlphaMin = 0.05f;
constexpr float kGyroEmaAlphaMax = 1.0f;
// Smooth gravity separately so the yaw/roll blend doesn't twitch with raw accel noise.
constexpr float kGravityEmaAlpha = 0.1f;
constexpr float kMinGravityProjection = 0.2f;
// Let roll contribute more strongly as the pad approaches an upright posture.
constexpr float kRollAimBoostMax = 2.0f;
bool s_sensor_enabled = false;
bool s_accel_enabled = false;
bool s_was_aiming = false;
bool s_have_gravity_baseline = false;
float s_smooth_gx = 0.0f;
float s_smooth_gy = 0.0f;
float s_smooth_gz = 0.0f;
float s_gravity_y = 0.0f;
float s_gravity_z = 0.0f;
float s_baseline_gravity_y = 0.0f;
float s_baseline_gravity_z = 0.0f;
float s_yaw_rad = 0.0f;
float s_pitch_rad = 0.0f;
float s_roll_rad = 0.0f;
@@ -19,6 +32,10 @@ s32 s_rollgoal_az = 0;
void reset_filter_state() {
s_smooth_gx = s_smooth_gy = s_smooth_gz = 0.0f;
s_gravity_y = s_gravity_z = 0.0f;
s_baseline_gravity_y = s_baseline_gravity_z = 0.0f;
s_was_aiming = false;
s_have_gravity_baseline = false;
s_yaw_rad = s_pitch_rad = s_roll_rad = 0.0f;
s_rollgoal_ax = s_rollgoal_az = 0;
}
@@ -49,15 +66,30 @@ bool queryGyroAimContext() {
}
void read(float dt) {
if (!s_sensor_keep_alive && !queryGyroAimContext()) {
const bool aim_active = queryGyroAimContext();
const bool aim_just_started = aim_active && !s_was_aiming;
const bool aim_just_ended = !aim_active && s_was_aiming;
s_was_aiming = aim_active;
if (!s_sensor_keep_alive && !aim_active) {
if (s_sensor_enabled) {
PADSetSensorEnabled(PAD_CHAN0, PAD_SENSOR_GYRO, FALSE);
s_sensor_enabled = false;
}
if (s_accel_enabled) {
PADSetSensorEnabled(PAD_CHAN0, PAD_SENSOR_ACCEL, FALSE);
s_accel_enabled = false;
}
reset_filter_state();
return;
}
if (aim_just_started || aim_just_ended) {
s_gravity_y = s_gravity_z = 0.0f;
s_baseline_gravity_y = s_baseline_gravity_z = 0.0f;
s_have_gravity_baseline = false;
}
if (!s_sensor_enabled) {
if (!PADHasSensor(PAD_CHAN0, PAD_SENSOR_GYRO)) {
return;
@@ -68,6 +100,13 @@ void read(float dt) {
s_sensor_enabled = true;
}
if (!s_accel_enabled && PADHasSensor(PAD_CHAN0, PAD_SENSOR_ACCEL) &&
PADSetSensorEnabled(PAD_CHAN0, PAD_SENSOR_ACCEL, TRUE))
{
// We only need accel for the gravity-aware yaw/roll mix.
s_accel_enabled = true;
}
f32 gyro[3];
if (!PADGetSensorData(PAD_CHAN0, PAD_SENSOR_GYRO, gyro, 3)) {
return;
@@ -80,9 +119,50 @@ void read(float dt) {
s_smooth_gy += smooth_alpha * (gyro[1] - s_smooth_gy);
s_smooth_gz += smooth_alpha * (gyro[2] - s_smooth_gz);
s_pitch_rad = -apply_deadband(s_smooth_gx, deadband) * dt * dusk::getSettings().game.gyroSensitivityX;
s_yaw_rad = apply_deadband(s_smooth_gy, deadband) * dt * dusk::getSettings().game.gyroSensitivityY;
s_roll_rad = apply_deadband(s_smooth_gz, deadband) * dt * dusk::getSettings().game.gyroSensitivityX; // GYRO NOTE: Exposing Z sensitivity seems unusual, so I'm just using X
const float pitch_rate = apply_deadband(s_smooth_gx, deadband);
const float yaw_rate = apply_deadband(s_smooth_gy, deadband);
const float roll_rate = apply_deadband(s_smooth_gz, deadband);
s_pitch_rad = -pitch_rate * dt * dusk::getSettings().game.gyroSensitivityX;
s_roll_rad = roll_rate * dt * dusk::getSettings().game.gyroSensitivityX; // GYRO NOTE: Exposing Z sensitivity seems unusual, so I'm just using X
float horizontal_rate = yaw_rate;
if (aim_active && s_accel_enabled) {
f32 accel[3];
if (PADGetSensorData(PAD_CHAN0, PAD_SENSOR_ACCEL, accel, 3)) {
if (!s_have_gravity_baseline) {
s_gravity_y = accel[1];
s_gravity_z = accel[2];
} else {
s_gravity_y += kGravityEmaAlpha * (accel[1] - s_gravity_y);
s_gravity_z += kGravityEmaAlpha * (accel[2] - s_gravity_z);
}
// Compare the current gravity projection against the gravity vector from
// aim start so the user's resting hold angle becomes the neutral baseline.
const float gravity_yz_len = std::sqrt((s_gravity_y * s_gravity_y) + (s_gravity_z * s_gravity_z));
if (gravity_yz_len >= kMinGravityProjection) {
const float current_gravity_y = s_gravity_y / gravity_yz_len;
const float current_gravity_z = s_gravity_z / gravity_yz_len;
if (!s_have_gravity_baseline) {
s_baseline_gravity_y = current_gravity_y;
s_baseline_gravity_z = current_gravity_z;
s_have_gravity_baseline = true;
}
const float yaw_weight =
(s_baseline_gravity_y * current_gravity_y) + (s_baseline_gravity_z * current_gravity_z);
const float roll_weight =
(s_baseline_gravity_y * current_gravity_z) - (s_baseline_gravity_z * current_gravity_y);
const float roll_mix = std::fabs(roll_weight);
const float roll_boost = 1.0f + (roll_mix * (kRollAimBoostMax - 1.0f));
horizontal_rate = (yaw_rate * yaw_weight) + (roll_rate * roll_weight * roll_boost);
}
}
}
s_yaw_rad = horizontal_rate * dt * dusk::getSettings().game.gyroSensitivityY;
s_pitch_rad = dusk::getSettings().game.gyroInvertPitch ? -s_pitch_rad : s_pitch_rad;
s_yaw_rad = dusk::getSettings().game.gyroInvertYaw ? -s_yaw_rad : s_yaw_rad;
+13 -2
View File
@@ -49,9 +49,10 @@ namespace dusk {
ImGui::SeparatorText("Free-look Data");
static float eyeYawDeg = 0.0f;
static float moveSpeed = 10000.0f;
static float moveSpeed = 5000.0f;
static float rotSpeed = 5.0f;
static cXyz freeLookPos = cXyz::Zero;
static bool freeLookActive = false;
bool changed = false;
@@ -91,7 +92,17 @@ namespace dusk {
changed = true;
}
if (changed) {
if (!freeLookActive && changed) {
freeLookPos += dCam->Center();
freeLookActive = true;
}
if (ImGui::IsKeyDown(ImGuiKey_R)) {
freeLookPos = cXyz::Zero;
freeLookActive = false;
}
if (freeLookActive) {
dCam->Reset(freeLookPos, freeLookPos + (frontDir * 100.0f));
}
+10 -2
View File
@@ -17,6 +17,7 @@
#include "dusk/audio/DuskAudioSystem.h"
#include "dusk/config.hpp"
#include "dusk/dusk.h"
#include "dusk/frame_interpolation.h"
#include "dusk/main.h"
#include "dusk/settings.h"
#include "m_Do/m_Do_controller_pad.h"
@@ -281,7 +282,7 @@ namespace dusk {
void ImGuiConsole::UpdateSettings() {
getTransientSettings().skipFrameRateLimit = getSettings().game.enableTurboKeybind && ImGui::IsKeyDown(ImGuiKey_Tab);
if (mDoMain::developmentMode == 1 && (mDoCPd_c::getHold(PAD_1) & (PAD_TRIGGER_R | PAD_TRIGGER_L)) == (PAD_TRIGGER_R | PAD_TRIGGER_L) && mDoCPd_c::getTrigY(PAD_1)) {
if (dusk::frame_interp::get_ui_tick_pending() && mDoMain::developmentMode == 1 && (mDoCPd_c::getHold(PAD_1) & (PAD_TRIGGER_R | PAD_TRIGGER_L)) == (PAD_TRIGGER_R | PAD_TRIGGER_L) && mDoCPd_c::getTrigY(PAD_1)) {
getTransientSettings().moveLinkActive = !getTransientSettings().moveLinkActive;
}
if (mDoMain::developmentMode != 1) {
@@ -304,6 +305,10 @@ namespace dusk {
ImGuiMenuGame::ToggleFullscreen();
}
if (ImGui::IsKeyPressed(ImGuiKey_Escape) && getSettings().video.enableFullscreen) {
ImGuiMenuGame::ToggleFullscreen();
}
if (!dusk::IsGameLaunched) {
m_preLaunchWindow.draw();
}
@@ -318,9 +323,11 @@ namespace dusk {
}
}
// The menu bar renders with ImGuiCol_WindowBg behind it. We just want ImGuiCol_MenuBarBg,
// so make the window bg fully transparent temporarily
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
if (showMenu && ImGui::BeginMainMenuBar()) {
m_menuGame.draw();
m_menuEnhancements.draw();
m_menuTools.draw();
const auto fpsLabel =
@@ -335,6 +342,7 @@ namespace dusk {
ImGui::EndMainMenuBar();
}
ImGui::PopStyleColor();
if (!getSettings().backend.wasPresetChosen) {
m_firstRunPreset.draw();
-2
View File
@@ -9,7 +9,6 @@
#include <SDL3/SDL_touch.h>
#include "ImGuiFirstRunPreset.hpp"
#include "ImGuiMenuEnhancements.hpp"
#include "ImGuiMenuGame.hpp"
#include "ImGuiMenuTools.hpp"
#include "ImGuiPreLaunchWindow.hpp"
@@ -52,7 +51,6 @@ private:
ImGuiFirstRunPreset m_firstRunPreset;
ImGuiMenuGame m_menuGame;
ImGuiMenuEnhancements m_menuEnhancements;
ImGuiPreLaunchWindow m_preLaunchWindow;
// Keep always last
+2 -2
View File
@@ -126,7 +126,7 @@ void ImGuiEngine_Initialize(float scale) {
auto* colors = style.Colors;
colors[ImGuiCol_Text] = ImVec4(0.95f, 0.96f, 0.98f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.36f, 0.42f, 0.47f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.11f, 0.15f, 0.17f, 0.98f);
colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
colors[ImGuiCol_Border] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
@@ -137,7 +137,7 @@ void ImGuiEngine_Initialize(float scale) {
colors[ImGuiCol_TitleBg] = ImVec4(0.09f, 0.12f, 0.14f, 0.65f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 0.80f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.18f, 0.22f, 0.25f, 1.00f);
-248
View File
@@ -1,248 +0,0 @@
#include "imgui.h"
#include "ImGuiMenuEnhancements.hpp"
#include "ImGuiConfig.hpp"
#include "dusk/settings.h"
namespace dusk {
ImGuiMenuEnhancements::ImGuiMenuEnhancements() {}
void ImGuiMenuEnhancements::draw() {
if (ImGui::BeginMenu("Enhancements")) {
if (ImGui::BeginMenu("Gameplay")) {
ImGui::SeparatorText("Preferences");
config::ImGuiCheckbox("Mirror Mode", getSettings().game.enableMirrorMode);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Mirrors the world horizontally, matching the Wii version of the game.");
}
config::ImGuiCheckbox("Disable Main HUD", getSettings().game.disableMainHUD);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Disables the main HUD of the game.\n"
"Useful for recording or a more immersive experience!");
}
ImGui::SeparatorText("Difficulty");
config::ImGuiSliderInt("Damage Multiplier", getSettings().game.damageMultiplier, 1, 8, "x%d");
config::ImGuiCheckbox("Instant Death", getSettings().game.instantDeath);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Any hit will instantly kill you.");
}
config::ImGuiCheckbox("No Heart Drops", getSettings().game.noHeartDrops);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Hearts will never drop from enemies,\n"
"pots and various other places.");
}
ImGui::SeparatorText("Quality of Life");
config::ImGuiCheckbox("Bigger Wallets", getSettings().game.biggerWallets);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Wallet sizes are like in the HD version. (500, 1000, 2000)");
}
config::ImGuiCheckbox("Disable Rupee Cutscenes", getSettings().game.disableRupeeCutscenes);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Rupees won't play cutscenes after you've collected them the first time.");
}
config::ImGuiCheckbox("Faster Climbing", getSettings().game.fastClimbing);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Quicker climbing on ladders and vines like the HD version.");
}
config::ImGuiCheckbox("Faster Tears of Light", getSettings().game.fastTears);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Tears of Light dropped by Shadow Insects pop out faster like the HD version.");
}
config::ImGuiCheckbox("Instant Saves", getSettings().game.instantSaves);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Skip the delay when writing to the Memory Card.");
}
config::ImGuiCheckbox("Hold B for Instant Text", getSettings().game.instantText);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Make text scroll immediately by holding B.");
}
config::ImGuiCheckbox("No Climbing Miss Animation", getSettings().game.noMissClimbing);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Prevents Link from playing a struggle animation\n"
"when grabbing ledges or climbing on vines.");
}
config::ImGuiCheckbox("No Rupee Returns", getSettings().game.noReturnRupees);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Always collect Rupees even if your Wallet is too full.");
}
config::ImGuiCheckbox("No Sword Recoil", getSettings().game.noSwordRecoil);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Link won't recoil when his sword hits walls.");
}
config::ImGuiCheckbox("Skip TV Settings Screen", getSettings().game.hideTvSettingsScreen);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Skip the TV calibration screen shown when loading a save.");
}
config::ImGuiCheckbox("Skip Warning Screen", getSettings().game.skipWarningScreen);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Skip the warning screen shown when starting the game.");
}
config::ImGuiCheckbox("Sun's Song (R+X)", getSettings().game.sunsSong);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Allows Wolf Link to howl and change the time of day.");
}
config::ImGuiCheckbox("Quick Transform (R+Y)", getSettings().game.enableQuickTransform);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Transform instantly by pressing R and Y simultaneously.");
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Graphics")) {
config::ImGuiSliderInt("Shadow Resolution", getSettings().game.shadowResolutionMultiplier, 1, 8, "x%d");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Improves the shadow resolution, making them higher quality.");
}
config::ImGuiCheckbox("Unlock Framerate", getSettings().game.enableFrameInterpolation);
const bool frameInterpolationHovered = ImGui::IsItemHovered();
ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.72f, 0.2f, 1.0f));
ImGui::TextUnformatted("[EXPERIMENTAL]");
ImGui::PopStyleColor();
if (frameInterpolationHovered || ImGui::IsItemHovered()) {
ImGui::SetTooltip("Uses inter-frame interpolation to enable higher frame rates.\nVisual artifacts, animation glitches, or instability may occur.");
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Audio")) {
config::ImGuiCheckbox("No Low HP Sound", getSettings().game.noLowHpSound);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Disable the beeping sound when having low health.");
}
config::ImGuiCheckbox("Non-Stop Midna's Lament", getSettings().game.midnasLamentNonStop);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Prevents enemy music while Midna's Lament is playing.");
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Input")) {
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
ImGui::SeparatorText("Gyro");
config::ImGuiCheckbox("Gyro Aim", getSettings().game.enableGyroAim);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Enables the gyroscope on supported controllers\n"
"while in look mode (C-Up) and while aiming the\n"
"Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s),\n"
"Ball and Chain, and Dominion Rod.");
}
config::ImGuiCheckbox("Gyro Rollgoal", getSettings().game.enableGyroRollgoal);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Enables the gyroscope on supported controllers to\n"
"tilt the Rollgoal table in Hena's Cabin.");
}
if (getSettings().game.enableGyroAim || getSettings().game.enableGyroRollgoal) {
config::ImGuiSliderFloat("Gyro Pitch Sensitivity", getSettings().game.gyroSensitivityY, 0.25f, 4.0f, "%.2f");
config::ImGuiSliderFloat("Gyro Yaw Sensitivity", getSettings().game.gyroSensitivityX, 0.25f, 4.0f, "%.2f");
if (getSettings().game.enableGyroRollgoal) {
config::ImGuiSliderFloat("Rollgoal Sensitivity", getSettings().game.gyroSensitivityRollgoal, 0.25f, 4.0f, "%.2f");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Additional multiplier for scaling how strongly\n"
"the gyroscope affects the Rollgoal table.");
}
}
config::ImGuiSliderFloat("Gyro Deadband", getSettings().game.gyroDeadband, 0.0f, 0.5f, "%.3f");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Angular rates below this magnitude are treated as zero,\n"
"reducing drift and jitter when the controller is still.");
}
config::ImGuiSliderFloat("Gyro Smoothing", getSettings().game.gyroSmoothing, 0.0f, 1.0f, "%.2f");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Low values track raw gyro input more closely,\n"
"while higher values smooth out input over time.");
}
config::ImGuiCheckbox("Invert Gyro Pitch", getSettings().game.gyroInvertPitch);
config::ImGuiCheckbox("Invert Gyro Yaw", getSettings().game.gyroInvertYaw);
}
ImGui::SeparatorText("Tools");
config::ImGuiCheckbox("Turbo Key", getSettings().game.enableTurboKeybind);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Hold TAB to increase game speed by up to 4x.");
}
ImGui::EndMenu();
}
ImGui::Separator();
if (ImGui::BeginMenu("Cheats")) {
config::ImGuiCheckbox("Infinite Hearts", getSettings().game.infiniteHearts);
config::ImGuiCheckbox("Infinite Arrows", getSettings().game.infiniteArrows);
config::ImGuiCheckbox("Infinite Bombs", getSettings().game.infiniteBombs);
config::ImGuiCheckbox("Infinite Oil", getSettings().game.infiniteOil);
config::ImGuiCheckbox("Infinite Oxygen", getSettings().game.infiniteOxygen);
config::ImGuiCheckbox("Infinite Rupees", getSettings().game.infiniteRupees);
config::ImGuiCheckbox("Moon Jump (R+A)", getSettings().game.moonJump);
config::ImGuiCheckbox("Super Clawshot", getSettings().game.superClawshot);
config::ImGuiCheckbox("Always Greatspin", getSettings().game.alwaysGreatspin);
config::ImGuiCheckbox("Fast Iron Boots", getSettings().game.enableFastIronBoots);
config::ImGuiCheckbox("Can Transform Anywhere", getSettings().game.canTransformAnywhere);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Allows you to transform even if NPCs are looking.");
}
config::ImGuiCheckbox("Fast Spinner", getSettings().game.fastSpinner);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Speeds up Spinner movement when holding R.");
}
config::ImGuiCheckbox("Free Magic Armor", getSettings().game.freeMagicArmor);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Makes the magic armor work without rupees.");
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Technical")) {
config::ImGuiCheckbox("Restore Wii 1.0 Glitches", getSettings().game.restoreWiiGlitches);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Restores patched glitches from Wii USA 1.0,\n"
"the first released version.");
}
ImGui::EndMenu();
}
ImGui::EndMenu();
}
}
}
-18
View File
@@ -1,18 +0,0 @@
#ifndef DUSK_IMGUI_MENUENHANCEMENTS_HPP
#define DUSK_IMGUI_MENUENHANCEMENTS_HPP
#include <aurora/aurora.h>
#include <pad.h>
#include <string>
#include "imgui.h"
namespace dusk {
class ImGuiMenuEnhancements {
public:
ImGuiMenuEnhancements();
void draw();
};
}
#endif // DUSK_IMGUI_MENUENHANCEMENTS_HPP

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