mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-04 03:12:48 -04:00
Compare commits
142 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1fea4f02ed | |||
| 35ea13c53a | |||
| 5fab665f21 | |||
| 109f0a50e5 | |||
| 746910c59f | |||
| ae4806ae4f | |||
| 1c00e2cdde | |||
| 78301a8a83 | |||
| ca798049b3 | |||
| daf4b1dfeb | |||
| 5bdd31a5af | |||
| 3cb5e5172b | |||
| d625c7ab0c | |||
| c2045391c8 | |||
| f04a0ffcf1 | |||
| dfdac1c1cd | |||
| f4b361ab02 | |||
| 5f3d3012ff | |||
| 0897ef1132 | |||
| 8b89dbcbf0 | |||
| f24e944ab0 | |||
| 23130d5a57 | |||
| 1e6e1976e3 | |||
| 4453316bb0 | |||
| 14aeefb813 | |||
| c991c7c407 | |||
| 251c6e7aec | |||
| cf2357fff2 | |||
| 06e6b0d47e | |||
| a83b4186af | |||
| dc5de83436 | |||
| 77425b4b25 | |||
| 5a109313cb | |||
| d8a7927602 | |||
| cccddee106 | |||
| 6c252c6d26 | |||
| b06c1911c6 | |||
| 7c9e99220a | |||
| bfd8b9f453 | |||
| 53e8662335 | |||
| ae54f024cd | |||
| 9aa391c5bf | |||
| ec48249934 | |||
| 6a8f3516f9 | |||
| 79d4835784 | |||
| b1a4783e38 | |||
| 0038afa392 | |||
| 5fcffa0b4f | |||
| 9e9d11ae89 | |||
| 97bd84725c | |||
| 19c86b1b73 | |||
| ca247095da | |||
| c350b7b8ed | |||
| ac3d3314c4 | |||
| f916a48db0 | |||
| 6963a4b554 | |||
| 4466bf4e12 | |||
| c4d01b82a6 | |||
| 42e8d9ab9d | |||
| 9c562ff740 | |||
| 1787de517c | |||
| 832e567620 | |||
| 319efbe662 | |||
| 6f34bb050a | |||
| a2a56122e2 | |||
| 58f2679def | |||
| 396ea02fe5 | |||
| 8100ddb990 | |||
| d78c46a628 | |||
| 1e93657ab5 | |||
| 366e47245e | |||
| 4c53ba91be | |||
| cf080523cb | |||
| a15d0af139 | |||
| d99205ecc6 | |||
| dd3a61d84c | |||
| 595a6f1c9e | |||
| 18d70df188 | |||
| 46f6dc67c1 | |||
| 6267b79da3 | |||
| 62f3d09076 | |||
| 4b3c559df3 | |||
| 30a99c22f1 | |||
| 360cb37028 | |||
| 4b6b41a6aa | |||
| faa8618124 | |||
| 89acf923e0 | |||
| c42a33154c | |||
| a074e30147 | |||
| 2ce272d586 | |||
| e1636e20bd | |||
| 9904720e5a | |||
| 9910320fb4 | |||
| b43a9e2ccc | |||
| 23d81492e6 | |||
| 65b0ec3f90 | |||
| 91248d10db | |||
| f76a4d7087 | |||
| c7b609945b | |||
| 6ca6ea8065 | |||
| 315f621176 | |||
| 10d9a818c2 | |||
| e3761784af | |||
| d85556a063 | |||
| c43f33a5bc | |||
| e63897d1f7 | |||
| 35a69e7ff1 | |||
| 8b9f09bda5 | |||
| 32cddc725b | |||
| 55eec3b0de | |||
| 1cf14f176c | |||
| 74550b031f | |||
| 2f84f0eaa4 | |||
| 3ed7ef1c88 | |||
| eace147652 | |||
| 53c005c4f1 | |||
| a4ff97564c | |||
| c6beeba14f | |||
| e470278717 | |||
| 783230b654 | |||
| 4e7711725a | |||
| e5bf7606ec | |||
| aa377cd5c1 | |||
| bb9a88d7dc | |||
| 341e97ba82 | |||
| 8d3cb51157 | |||
| 7fff3b5ae0 | |||
| 6beb73b7a6 | |||
| c239a5a226 | |||
| b3f8fecfe4 | |||
| 6dcf4942f5 | |||
| cd7e429a66 | |||
| fcfcb35929 | |||
| 82b20be436 | |||
| 33101d8050 | |||
| 05160a968c | |||
| 623f29eb24 | |||
| 0a3833818a | |||
| 4f276252a3 | |||
| d17c629ce0 | |||
| 5bcc969778 | |||
| 31c5397ae3 |
Vendored
+1
-1
@@ -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
@@ -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
@@ -358,7 +358,10 @@
|
||||
"inherits": [
|
||||
"relwithdebinfo",
|
||||
"ci"
|
||||
]
|
||||
],
|
||||
"cacheVariables": {
|
||||
"AURORA_SDL3_PROVIDER": "vendor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x-linux-ci-gcc",
|
||||
|
||||
@@ -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
|
||||

|
||||
|
||||
# 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 |
Vendored
+1
-1
Submodule extern/aurora updated: 672f1e8e5e...9ff83bcb97
+85
-6
@@ -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
|
||||
)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -25,6 +25,9 @@ public:
|
||||
/* 0x164 */ cXyz mMinVal;
|
||||
/* 0x170 */ cXyz mMaxVal;
|
||||
/* 0x17C */ cXyz mViewScale;
|
||||
#if TARGET_PC
|
||||
bool mbReset = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace dusk::audio {
|
||||
|
||||
void SetMasterVolume(f32 value);
|
||||
|
||||
void SetPaused(bool paused);
|
||||
|
||||
u32 GetResetCount(int channelIdx);
|
||||
|
||||
f32 VolumeFromU16(u16 value);
|
||||
|
||||
@@ -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
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "aurora/gfx.h"
|
||||
|
||||
extern AuroraInfo auroraInfo;
|
||||
extern const char* configPath;
|
||||
|
||||
namespace dusk {
|
||||
extern AuroraStats lastFrameAuroraStats;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef GAMEPAD_COLOR_H
|
||||
#define GAMEPAD_COLOR_H
|
||||
|
||||
void handleGamepadColor();
|
||||
|
||||
#endif
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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(¤t);
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(¤t.pos, mChkObj.GetGroundH(), shadow_size, mChkObj.m_gnd, 0,
|
||||
1.0f, pTex);
|
||||
}
|
||||
return 1;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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(¢er, 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(¢er, 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
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user