mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-04 19:25:43 -04:00
Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f0e8379fa5 | |||
| 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 | |||
| 31c5397ae3 |
+54
-25
@@ -90,6 +90,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 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)
|
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
|
||||||
set(DAWN_USE_WAYLAND ON CACHE BOOL "Enable support for Wayland surface" FORCE)
|
set(DAWN_USE_WAYLAND ON CACHE BOOL "Enable support for Wayland surface" FORCE)
|
||||||
endif ()
|
endif ()
|
||||||
@@ -281,7 +286,7 @@ set(DUSK_TP_VERSION ${DUSK_GAME_NAME}${DUSK_GAME_VERSION})
|
|||||||
|
|
||||||
message(STATUS "dusk: Game Version: ${DUSK_TP_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})
|
source_group("dusk" FILES ${DUSK_FILES})
|
||||||
|
|
||||||
set(GAME_COMPILE_DEFS TARGET_PC WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0
|
set(GAME_COMPILE_DEFS TARGET_PC WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0
|
||||||
@@ -374,41 +379,65 @@ endif ()
|
|||||||
|
|
||||||
# game_debug is for game code files that we know work when compiled with DEBUG=1
|
# 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
|
# 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/DuskAudioSystem.cpp
|
||||||
src/dusk/audio/JASCriticalSection.cpp
|
src/dusk/audio/JASCriticalSection.cpp
|
||||||
src/dusk/audio/DuskDsp.cpp
|
src/dusk/audio/DuskDsp.cpp
|
||||||
src/dusk/audio/Adpcm.cpp
|
src/dusk/audio/Adpcm.cpp
|
||||||
src/dusk/audio/DspStub.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
|
# 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>)
|
foreach(jsystem_lib IN LISTS JSYSTEM_LIBRARIES)
|
||||||
target_compile_definitions(game_base PRIVATE ${GAME_COMPILE_DEFS} NDEBUG=1 NDEBUG_DEFINED=1 DEBUG_DEFINED=0 $<$<CONFIG:Debug>:PARTIAL_DEBUG=1>)
|
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
|
set(JSYSTEM_LINK_LIBRARIES ${JSYSTEM_LIBRARIES})
|
||||||
target_precompile_headers(game_base PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_SOURCE_DIR}/include/dusk_pch.hpp>")
|
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
|
||||||
target_include_directories(game_debug PRIVATE ${GAME_INCLUDE_DIRS})
|
# JSystem libraries reference each other, so they need a RESCAN group there.
|
||||||
target_include_directories(game_base PRIVATE ${GAME_INCLUDE_DIRS})
|
set(JSYSTEM_LINK_LIBRARIES "$<LINK_GROUP:RESCAN,${JSYSTEM_LIBRARIES}>")
|
||||||
|
|
||||||
# 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})
|
|
||||||
|
|
||||||
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)
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
target_compile_definitions(dusk PRIVATE TARGET_PC AVOID_UB=1 VERSION=0)
|
set(DUSK_FILES src/dusk/main.cpp ${GAME_BASE_FILES} ${GAME_DEBUG_FILES})
|
||||||
target_include_directories(dusk PRIVATE include)
|
if(ANDROID)
|
||||||
target_link_libraries(dusk PRIVATE game_base game_debug aurora::main)
|
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)
|
if (TARGET crashpad_handler)
|
||||||
add_dependencies(dusk crashpad_handler)
|
add_dependencies(dusk crashpad_handler)
|
||||||
endif ()
|
endif ()
|
||||||
|
|||||||
@@ -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.
|
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 |
|
| Version | sha1 hash |
|
||||||
| ------------ | ---------------------------------------- |
|
|--------------| ---------------------------------------- |
|
||||||
| GameCube USA | 75edd3ddff41f125d1b4ce1a40378f1b565519e7 |
|
| GameCube USA | 75edd3ddff41f125d1b4ce1a40378f1b565519e7 |
|
||||||
|
| GameCube PAL | 2601822a488eeb86fb89db16ca8f29c2c953e1ca |
|
||||||
|
|
||||||
### 2. Download [Dusk](https://github.com/TwilitRealm/dusk/releases)
|
### 2. Download [Dusk](https://github.com/TwilitRealm/dusk/releases)
|
||||||
|
|
||||||
### 3. Setup the game
|
### 3. Setup the game
|
||||||
#### Windows
|
|
||||||
- Extract the zip folder
|
- Extract the zip folder
|
||||||
- Place your dump of the game into the same folder where you extracted to
|
- Launch Dusk
|
||||||
- Launch `dusk.exe`
|
- 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
|
# Building
|
||||||
If you'd like to build Dusk from source, please read the [build instructions](docs/building.md).
|
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: 5d420c9f73...9ff83bcb97
+84
-3
@@ -314,7 +314,7 @@ set(SSYSTEM_FILES
|
|||||||
src/SSystem/SStandard/s_basic.cpp
|
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/JPAResourceManager.cpp
|
||||||
libs/JSystem/src/JParticle/JPAResource.cpp
|
libs/JSystem/src/JParticle/JPAResource.cpp
|
||||||
libs/JSystem/src/JParticle/JPABaseShape.cpp
|
libs/JSystem/src/JParticle/JPABaseShape.cpp
|
||||||
@@ -330,10 +330,19 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/JParticle/JPAEmitter.cpp
|
libs/JSystem/src/JParticle/JPAEmitter.cpp
|
||||||
libs/JSystem/src/JParticle/JPAParticle.cpp
|
libs/JSystem/src/JParticle/JPAParticle.cpp
|
||||||
libs/JSystem/src/JParticle/JPAMath.cpp
|
libs/JSystem/src/JParticle/JPAMath.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_JFramework STATIC
|
||||||
libs/JSystem/src/JFramework/JFWSystem.cpp
|
libs/JSystem/src/JFramework/JFWSystem.cpp
|
||||||
libs/JSystem/src/JFramework/JFWDisplay.cpp
|
libs/JSystem/src/JFramework/JFWDisplay.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_J3DU STATIC
|
||||||
libs/JSystem/src/J3DU/J3DUClipper.cpp
|
libs/JSystem/src/J3DU/J3DUClipper.cpp
|
||||||
libs/JSystem/src/J3DU/J3DUDL.cpp
|
libs/JSystem/src/J3DU/J3DUDL.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_JKernel STATIC
|
||||||
libs/JSystem/src/JKernel/JKRHeap.cpp
|
libs/JSystem/src/JKernel/JKRHeap.cpp
|
||||||
libs/JSystem/src/JKernel/JKRExpHeap.cpp
|
libs/JSystem/src/JKernel/JKRExpHeap.cpp
|
||||||
libs/JSystem/src/JKernel/JKRSolidHeap.cpp
|
libs/JSystem/src/JKernel/JKRSolidHeap.cpp
|
||||||
@@ -359,14 +368,23 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/JKernel/JKRDvdRipper.cpp
|
libs/JSystem/src/JKernel/JKRDvdRipper.cpp
|
||||||
libs/JSystem/src/JKernel/JKRDvdAramRipper.cpp
|
libs/JSystem/src/JKernel/JKRDvdAramRipper.cpp
|
||||||
libs/JSystem/src/JKernel/JKRDecomp.cpp
|
libs/JSystem/src/JKernel/JKRDecomp.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_JMath STATIC
|
||||||
libs/JSystem/src/JMath/JMath.cpp
|
libs/JSystem/src/JMath/JMath.cpp
|
||||||
libs/JSystem/src/JMath/random.cpp
|
libs/JSystem/src/JMath/random.cpp
|
||||||
libs/JSystem/src/JMath/JMATrigonometric.cpp
|
libs/JSystem/src/JMath/JMATrigonometric.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_JSupport STATIC
|
||||||
libs/JSystem/src/JSupport/JSUList.cpp
|
libs/JSystem/src/JSupport/JSUList.cpp
|
||||||
libs/JSystem/src/JSupport/JSUInputStream.cpp
|
libs/JSystem/src/JSupport/JSUInputStream.cpp
|
||||||
libs/JSystem/src/JSupport/JSUOutputStream.cpp
|
libs/JSystem/src/JSupport/JSUOutputStream.cpp
|
||||||
libs/JSystem/src/JSupport/JSUMemoryStream.cpp
|
libs/JSystem/src/JSupport/JSUMemoryStream.cpp
|
||||||
libs/JSystem/src/JSupport/JSUFileStream.cpp
|
libs/JSystem/src/JSupport/JSUFileStream.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_JUtility STATIC
|
||||||
libs/JSystem/src/JUtility/JUTCacheFont.cpp
|
libs/JSystem/src/JUtility/JUTCacheFont.cpp
|
||||||
libs/JSystem/src/JUtility/JUTResource.cpp
|
libs/JSystem/src/JUtility/JUTResource.cpp
|
||||||
libs/JSystem/src/JUtility/JUTTexture.cpp
|
libs/JSystem/src/JUtility/JUTTexture.cpp
|
||||||
@@ -387,6 +405,9 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/JUtility/JUTConsole.cpp
|
libs/JSystem/src/JUtility/JUTConsole.cpp
|
||||||
libs/JSystem/src/JUtility/JUTDirectFile.cpp
|
libs/JSystem/src/JUtility/JUTDirectFile.cpp
|
||||||
libs/JSystem/src/JUtility/JUTFontData_Ascfont_fix12.cpp
|
libs/JSystem/src/JUtility/JUTFontData_Ascfont_fix12.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_JStage STATIC
|
||||||
libs/JSystem/src/JStage/JSGActor.cpp
|
libs/JSystem/src/JStage/JSGActor.cpp
|
||||||
libs/JSystem/src/JStage/JSGAmbientLight.cpp
|
libs/JSystem/src/JStage/JSGAmbientLight.cpp
|
||||||
libs/JSystem/src/JStage/JSGCamera.cpp
|
libs/JSystem/src/JStage/JSGCamera.cpp
|
||||||
@@ -394,6 +415,9 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/JStage/JSGLight.cpp
|
libs/JSystem/src/JStage/JSGLight.cpp
|
||||||
libs/JSystem/src/JStage/JSGObject.cpp
|
libs/JSystem/src/JStage/JSGObject.cpp
|
||||||
libs/JSystem/src/JStage/JSGSystem.cpp
|
libs/JSystem/src/JStage/JSGSystem.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_J2DGraph STATIC
|
||||||
libs/JSystem/src/J2DGraph/J2DGrafContext.cpp
|
libs/JSystem/src/J2DGraph/J2DGrafContext.cpp
|
||||||
libs/JSystem/src/J2DGraph/J2DOrthoGraph.cpp
|
libs/JSystem/src/J2DGraph/J2DOrthoGraph.cpp
|
||||||
libs/JSystem/src/J2DGraph/J2DTevs.cpp
|
libs/JSystem/src/J2DGraph/J2DTevs.cpp
|
||||||
@@ -412,6 +436,9 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/J2DGraph/J2DAnmLoader.cpp
|
libs/JSystem/src/J2DGraph/J2DAnmLoader.cpp
|
||||||
libs/JSystem/src/J2DGraph/J2DAnimation.cpp
|
libs/JSystem/src/J2DGraph/J2DAnimation.cpp
|
||||||
libs/JSystem/src/J2DGraph/J2DManage.cpp
|
libs/JSystem/src/J2DGraph/J2DManage.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_J3DGraphBase STATIC
|
||||||
libs/JSystem/src/J3DGraphBase/J3DGD.cpp
|
libs/JSystem/src/J3DGraphBase/J3DGD.cpp
|
||||||
libs/JSystem/src/J3DGraphBase/J3DSys.cpp
|
libs/JSystem/src/J3DGraphBase/J3DSys.cpp
|
||||||
libs/JSystem/src/J3DGraphBase/J3DVertex.cpp
|
libs/JSystem/src/J3DGraphBase/J3DVertex.cpp
|
||||||
@@ -426,6 +453,9 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/J3DGraphBase/J3DTevs.cpp
|
libs/JSystem/src/J3DGraphBase/J3DTevs.cpp
|
||||||
libs/JSystem/src/J3DGraphBase/J3DDrawBuffer.cpp
|
libs/JSystem/src/J3DGraphBase/J3DDrawBuffer.cpp
|
||||||
libs/JSystem/src/J3DGraphBase/J3DStruct.cpp
|
libs/JSystem/src/J3DGraphBase/J3DStruct.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_J3DGraphAnimator STATIC
|
||||||
libs/JSystem/src/J3DGraphAnimator/J3DShapeTable.cpp
|
libs/JSystem/src/J3DGraphAnimator/J3DShapeTable.cpp
|
||||||
libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp
|
libs/JSystem/src/J3DGraphAnimator/J3DJointTree.cpp
|
||||||
libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp
|
libs/JSystem/src/J3DGraphAnimator/J3DModelData.cpp
|
||||||
@@ -437,6 +467,9 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/J3DGraphAnimator/J3DCluster.cpp
|
libs/JSystem/src/J3DGraphAnimator/J3DCluster.cpp
|
||||||
libs/JSystem/src/J3DGraphAnimator/J3DJoint.cpp
|
libs/JSystem/src/J3DGraphAnimator/J3DJoint.cpp
|
||||||
libs/JSystem/src/J3DGraphAnimator/J3DMaterialAttach.cpp
|
libs/JSystem/src/J3DGraphAnimator/J3DMaterialAttach.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_J3DGraphLoader STATIC
|
||||||
libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory.cpp
|
libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory.cpp
|
||||||
libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory_v21.cpp
|
libs/JSystem/src/J3DGraphLoader/J3DMaterialFactory_v21.cpp
|
||||||
libs/JSystem/src/J3DGraphLoader/J3DClusterLoader.cpp
|
libs/JSystem/src/J3DGraphLoader/J3DClusterLoader.cpp
|
||||||
@@ -445,6 +478,9 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/J3DGraphLoader/J3DJointFactory.cpp
|
libs/JSystem/src/J3DGraphLoader/J3DJointFactory.cpp
|
||||||
libs/JSystem/src/J3DGraphLoader/J3DShapeFactory.cpp
|
libs/JSystem/src/J3DGraphLoader/J3DShapeFactory.cpp
|
||||||
libs/JSystem/src/J3DGraphLoader/J3DAnmLoader.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.cpp
|
||||||
libs/JSystem/src/JStudio/JStudio/ctb-data.cpp
|
libs/JSystem/src/JStudio/JStudio/ctb-data.cpp
|
||||||
libs/JSystem/src/JStudio/JStudio/functionvalue.cpp
|
libs/JSystem/src/JStudio/JStudio/functionvalue.cpp
|
||||||
@@ -459,6 +495,9 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/JStudio/JStudio/stb.cpp
|
libs/JSystem/src/JStudio/JStudio/stb.cpp
|
||||||
libs/JSystem/src/JStudio/JStudio/stb-data-parse.cpp
|
libs/JSystem/src/JStudio/JStudio/stb-data-parse.cpp
|
||||||
libs/JSystem/src/JStudio/JStudio/stb-data.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/control.cpp
|
||||||
libs/JSystem/src/JStudio/JStudio_JStage/object.cpp
|
libs/JSystem/src/JStudio/JStudio_JStage/object.cpp
|
||||||
libs/JSystem/src/JStudio/JStudio_JStage/object-actor.cpp
|
libs/JSystem/src/JStudio/JStudio_JStage/object-actor.cpp
|
||||||
@@ -466,10 +505,19 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/JStudio/JStudio_JStage/object-camera.cpp
|
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-fog.cpp
|
||||||
libs/JSystem/src/JStudio/JStudio_JStage/object-light.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/control.cpp
|
||||||
libs/JSystem/src/JStudio/JStudio_JAudio2/object-sound.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/control.cpp
|
||||||
libs/JSystem/src/JStudio/JStudio_JParticle/object-particle.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/JASCalc.cpp
|
||||||
libs/JSystem/src/JAudio2/JASTaskThread.cpp
|
libs/JSystem/src/JAudio2/JASTaskThread.cpp
|
||||||
libs/JSystem/src/JAudio2/JASDvdThread.cpp
|
libs/JSystem/src/JAudio2/JASDvdThread.cpp
|
||||||
@@ -534,22 +582,34 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/JAudio2/JAUSoundAnimator.cpp
|
libs/JSystem/src/JAudio2/JAUSoundAnimator.cpp
|
||||||
libs/JSystem/src/JAudio2/JAUSoundTable.cpp
|
libs/JSystem/src/JAudio2/JAUSoundTable.cpp
|
||||||
libs/JSystem/src/JAudio2/JAUStreamFileTable.cpp
|
libs/JSystem/src/JAudio2/JAUStreamFileTable.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_JMessage STATIC
|
||||||
libs/JSystem/src/JMessage/control.cpp
|
libs/JSystem/src/JMessage/control.cpp
|
||||||
libs/JSystem/src/JMessage/data.cpp
|
libs/JSystem/src/JMessage/data.cpp
|
||||||
libs/JSystem/src/JMessage/processor.cpp
|
libs/JSystem/src/JMessage/processor.cpp
|
||||||
libs/JSystem/src/JMessage/resource.cpp
|
libs/JSystem/src/JMessage/resource.cpp
|
||||||
libs/JSystem/src/JMessage/locale.cpp
|
libs/JSystem/src/JMessage/locale.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_JGadget STATIC
|
||||||
libs/JSystem/src/JGadget/binary.cpp
|
libs/JSystem/src/JGadget/binary.cpp
|
||||||
libs/JSystem/src/JGadget/define.cpp
|
libs/JSystem/src/JGadget/define.cpp
|
||||||
libs/JSystem/src/JGadget/linklist.cpp
|
libs/JSystem/src/JGadget/linklist.cpp
|
||||||
libs/JSystem/src/JGadget/search.cpp
|
libs/JSystem/src/JGadget/search.cpp
|
||||||
libs/JSystem/src/JGadget/std-vector.cpp
|
libs/JSystem/src/JGadget/std-vector.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_JAHostIO STATIC
|
||||||
libs/JSystem/src/JAHostIO/JAHFrameNode.cpp
|
libs/JSystem/src/JAHostIO/JAHFrameNode.cpp
|
||||||
libs/JSystem/src/JAHostIO/JAHioMessage.cpp
|
libs/JSystem/src/JAHostIO/JAHioMessage.cpp
|
||||||
libs/JSystem/src/JAHostIO/JAHioMgr.cpp
|
libs/JSystem/src/JAHostIO/JAHioMgr.cpp
|
||||||
libs/JSystem/src/JAHostIO/JAHioNode.cpp
|
libs/JSystem/src/JAHostIO/JAHioNode.cpp
|
||||||
libs/JSystem/src/JAHostIO/JAHioUtil.cpp
|
libs/JSystem/src/JAHostIO/JAHioUtil.cpp
|
||||||
libs/JSystem/src/JAHostIO/JAHVirtualNode.cpp
|
libs/JSystem/src/JAHostIO/JAHVirtualNode.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(JSystem_JHostIO STATIC
|
||||||
libs/JSystem/src/JHostIO/JORFile.cpp
|
libs/JSystem/src/JHostIO/JORFile.cpp
|
||||||
libs/JSystem/src/JHostIO/JORHostInfo.cpp
|
libs/JSystem/src/JHostIO/JORHostInfo.cpp
|
||||||
libs/JSystem/src/JHostIO/JORMessageBox.cpp
|
libs/JSystem/src/JHostIO/JORMessageBox.cpp
|
||||||
@@ -559,7 +619,28 @@ set(JSYSTEM_DEBUG_FILES
|
|||||||
libs/JSystem/src/JHostIO/JHIMccBuf.cpp
|
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
|
set(REL_FILES
|
||||||
@@ -1341,13 +1422,13 @@ set(DUSK_FILES
|
|||||||
src/dusk/crash_reporting.cpp
|
src/dusk/crash_reporting.cpp
|
||||||
src/dusk/endian.cpp
|
src/dusk/endian.cpp
|
||||||
src/dusk/extras.c
|
src/dusk/extras.c
|
||||||
src/dusk/extras.cpp
|
|
||||||
src/dusk/file_select.cpp
|
src/dusk/file_select.cpp
|
||||||
src/dusk/file_select.hpp
|
src/dusk/file_select.hpp
|
||||||
src/dusk/frame_interpolation.cpp
|
src/dusk/frame_interpolation.cpp
|
||||||
src/dusk/game_clock.cpp
|
src/dusk/game_clock.cpp
|
||||||
src/dusk/globals.cpp
|
src/dusk/globals.cpp
|
||||||
src/dusk/gyro.cpp
|
src/dusk/gyro.cpp
|
||||||
|
src/dusk/gamepad_color.cpp
|
||||||
src/dusk/io.cpp
|
src/dusk/io.cpp
|
||||||
src/dusk/layout.cpp
|
src/dusk/layout.cpp
|
||||||
src/dusk/logging.cpp
|
src/dusk/logging.cpp
|
||||||
|
|||||||
@@ -103,6 +103,10 @@ public:
|
|||||||
field_0xd98 = param_1;
|
field_0xd98 = param_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
void resetScrollArrowMask() { field_0xdda = 0; }
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 0xC98 */ JKRExpHeap* mpHeap;
|
/* 0xC98 */ JKRExpHeap* mpHeap;
|
||||||
/* 0xC9C */ JKRExpHeap* mpTalkHeap;
|
/* 0xC9C */ JKRExpHeap* mpTalkHeap;
|
||||||
/* 0xCA0 */ STControl* mpStick;
|
/* 0xCA0 */ STControl* mpStick;
|
||||||
|
|||||||
@@ -75,7 +75,9 @@ public:
|
|||||||
/* 0x8 */ BE(u16) mAreaName;
|
/* 0x8 */ BE(u16) mAreaName;
|
||||||
/* 0xA */ u8 mCount;
|
/* 0xA */ u8 mCount;
|
||||||
#ifdef _MSVC_LANG
|
#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;
|
__declspec(property(get = __get_mRoomNos)) u8* mRoomNos;
|
||||||
#else
|
#else
|
||||||
/* 0xB */ u8 mRoomNos[0];
|
/* 0xB */ u8 mRoomNos[0];
|
||||||
|
|||||||
@@ -206,6 +206,15 @@ private:
|
|||||||
/* 0x6D3 */ u8 field_0x6d3;
|
/* 0x6D3 */ u8 field_0x6d3;
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
f32 mSelectItemSlideElapsed[4];
|
f32 mSelectItemSlideElapsed[4];
|
||||||
|
f32 mCursorInterpPrevX;
|
||||||
|
f32 mCursorInterpPrevY;
|
||||||
|
f32 mCursorInterpCurrX;
|
||||||
|
f32 mCursorInterpCurrY;
|
||||||
|
s16 mCursorInterpPrevAngle;
|
||||||
|
s16 mCursorInterpCurrAngle;
|
||||||
|
bool mCursorInterpPrevAngular;
|
||||||
|
bool mCursorInterpCurrAngular;
|
||||||
|
bool mCursorInterpInit;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
|
f32 getPositionX() const { return mPositionX; }
|
||||||
|
f32 getPositionY() const { return mPositionY; }
|
||||||
|
|
||||||
void refreshAspectScale();
|
void refreshAspectScale();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ void ensure_initialized();
|
|||||||
|
|
||||||
void begin_record();
|
void begin_record();
|
||||||
void end_record();
|
void end_record();
|
||||||
|
void begin_sim_tick();
|
||||||
void begin_frame(bool enabled, bool is_sim_frame, float step);
|
void begin_frame(bool enabled, bool is_sim_frame, float step);
|
||||||
void interpolate();
|
void interpolate();
|
||||||
float get_interpolation_step();
|
float get_interpolation_step();
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
#ifndef DUSK_GAME_CLOCK_H
|
#pragma once
|
||||||
#define DUSK_GAME_CLOCK_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
namespace dusk::game_clock {
|
||||||
|
|
||||||
namespace dusk {
|
|
||||||
namespace game_clock {
|
|
||||||
|
|
||||||
void ensure_initialized();
|
void ensure_initialized();
|
||||||
void reset_accumulator();
|
|
||||||
void reset_frame_timer();
|
void reset_frame_timer();
|
||||||
|
|
||||||
constexpr float sim_pace() { return 1.0f / 30.0f; }
|
constexpr float sim_pace() { return 1.0f / 30.0f; }
|
||||||
@@ -18,16 +13,14 @@ constexpr float ui_initial_dt() { return 1.0f / 60.0f; }
|
|||||||
struct MainLoopPacer {
|
struct MainLoopPacer {
|
||||||
float presentation_dt_seconds;
|
float presentation_dt_seconds;
|
||||||
bool is_interpolating;
|
bool is_interpolating;
|
||||||
bool do_sim_tick;
|
int sim_ticks_to_run;
|
||||||
float interpolation_step;
|
|
||||||
float sim_pace;
|
float sim_pace;
|
||||||
};
|
};
|
||||||
|
|
||||||
MainLoopPacer advance_main_loop();
|
MainLoopPacer advance_main_loop();
|
||||||
|
void commit_sim_tick();
|
||||||
|
float sample_interpolation_step();
|
||||||
|
|
||||||
float consume_interval(const void* consumer);
|
float consume_interval(const void* consumer);
|
||||||
|
|
||||||
} // namespace game_clock
|
} // namespace dusk::game_clock
|
||||||
} // namespace dusk
|
|
||||||
|
|
||||||
#endif // DUSK_GAME_CLOCK_H
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef GAMEPAD_COLOR_H
|
||||||
|
#define GAMEPAD_COLOR_H
|
||||||
|
|
||||||
|
void handleGamepadColor();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -69,6 +69,8 @@ struct UserSettings {
|
|||||||
ConfigVar<bool> invertCameraXAxis;
|
ConfigVar<bool> invertCameraXAxis;
|
||||||
ConfigVar<bool> disableMainHUD;
|
ConfigVar<bool> disableMainHUD;
|
||||||
ConfigVar<bool> pauseOnFocusLost;
|
ConfigVar<bool> pauseOnFocusLost;
|
||||||
|
ConfigVar<bool> enableLinkDollRotation;
|
||||||
|
|
||||||
|
|
||||||
// Graphics
|
// Graphics
|
||||||
ConfigVar<BloomMode> bloomMode;
|
ConfigVar<BloomMode> bloomMode;
|
||||||
@@ -77,6 +79,7 @@ struct UserSettings {
|
|||||||
ConfigVar<bool> enableFrameInterpolation;
|
ConfigVar<bool> enableFrameInterpolation;
|
||||||
ConfigVar<int> internalResolutionScale;
|
ConfigVar<int> internalResolutionScale;
|
||||||
ConfigVar<int> shadowResolutionMultiplier;
|
ConfigVar<int> shadowResolutionMultiplier;
|
||||||
|
ConfigVar<bool> enableDepthOfField;
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
ConfigVar<bool> noLowHpSound;
|
ConfigVar<bool> noLowHpSound;
|
||||||
@@ -100,6 +103,7 @@ struct UserSettings {
|
|||||||
ConfigVar<bool> infiniteOil;
|
ConfigVar<bool> infiniteOil;
|
||||||
ConfigVar<bool> infiniteOxygen;
|
ConfigVar<bool> infiniteOxygen;
|
||||||
ConfigVar<bool> infiniteRupees;
|
ConfigVar<bool> infiniteRupees;
|
||||||
|
ConfigVar<bool> enableIndefiniteItemDrops;
|
||||||
ConfigVar<bool> moonJump;
|
ConfigVar<bool> moonJump;
|
||||||
ConfigVar<bool> superClawshot;
|
ConfigVar<bool> superClawshot;
|
||||||
ConfigVar<bool> alwaysGreatspin;
|
ConfigVar<bool> alwaysGreatspin;
|
||||||
@@ -123,6 +127,7 @@ struct UserSettings {
|
|||||||
ConfigVar<bool> wasPresetChosen;
|
ConfigVar<bool> wasPresetChosen;
|
||||||
ConfigVar<bool> enableCrashReporting;
|
ConfigVar<bool> enableCrashReporting;
|
||||||
ConfigVar<bool> duskMenuOpen;
|
ConfigVar<bool> duskMenuOpen;
|
||||||
|
ConfigVar<int> cardFileType;
|
||||||
} backend;
|
} backend;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -147,6 +152,7 @@ struct TransientSettings {
|
|||||||
CollisionViewSettings collisionView;
|
CollisionViewSettings collisionView;
|
||||||
bool skipFrameRateLimit;
|
bool skipFrameRateLimit;
|
||||||
bool moveLinkActive;
|
bool moveLinkActive;
|
||||||
|
bool stateShareLoadActive;
|
||||||
};
|
};
|
||||||
|
|
||||||
TransientSettings& getTransientSettings();
|
TransientSettings& getTransientSettings();
|
||||||
|
|||||||
+25
-25
@@ -1,9 +1,10 @@
|
|||||||
#ifndef DUSK_TIME_H
|
#ifndef DUSK_TIME_H
|
||||||
#define DUSK_TIME_H
|
#define DUSK_TIME_H
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <numeric>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
|
#include "SDL3/SDL_timer.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
@@ -15,28 +16,26 @@
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#else
|
|
||||||
#include "SDL3/SDL_timer.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class Limiter {
|
class Limiter {
|
||||||
using delta_clock = std::chrono::high_resolution_clock;
|
|
||||||
using duration_t = std::chrono::nanoseconds;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Reset() { m_oldTime = delta_clock::now(); }
|
using duration_t = Uint64;
|
||||||
|
|
||||||
|
void Reset() { m_oldTime = SDL_GetTicksNS(); }
|
||||||
|
|
||||||
void Sleep(duration_t targetFrameTime) {
|
void Sleep(duration_t targetFrameTime) {
|
||||||
if (targetFrameTime.count() == 0) {
|
if (targetFrameTime == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto start = delta_clock::now();
|
const Uint64 start = SDL_GetTicksNS();
|
||||||
duration_t adjustedSleepTime = SleepTime(targetFrameTime);
|
duration_t adjustedSleepTime = SleepTime(targetFrameTime);
|
||||||
if (adjustedSleepTime.count() > 0) {
|
if (adjustedSleepTime > 0) {
|
||||||
NanoSleep(adjustedSleepTime);
|
NanoSleep(adjustedSleepTime);
|
||||||
duration_t overslept = TimeSince(start) - adjustedSleepTime;
|
const duration_t elapsed = TimeSince(start);
|
||||||
if (overslept < duration_t{targetFrameTime}) {
|
const duration_t overslept = elapsed > adjustedSleepTime ? elapsed - adjustedSleepTime : 0;
|
||||||
|
if (overslept < targetFrameTime) {
|
||||||
m_overheadTimes[m_overheadTimeIdx] = overslept;
|
m_overheadTimes[m_overheadTimeIdx] = overslept;
|
||||||
m_overheadTimeIdx = (m_overheadTimeIdx + 1) % m_overheadTimes.size();
|
m_overheadTimeIdx = (m_overheadTimeIdx + 1) % m_overheadTimes.size();
|
||||||
}
|
}
|
||||||
@@ -45,23 +44,23 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
duration_t SleepTime(duration_t targetFrameTime) {
|
duration_t SleepTime(duration_t targetFrameTime) {
|
||||||
const auto sleepTime = duration_t{targetFrameTime} - TimeSince(m_oldTime);
|
const duration_t elapsed = TimeSince(m_oldTime);
|
||||||
m_overhead = std::accumulate(m_overheadTimes.begin(), m_overheadTimes.end(), duration_t{}) / m_overheadTimes.size();
|
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) {
|
if (sleepTime > m_overhead) {
|
||||||
return sleepTime - m_overhead;
|
return sleepTime - m_overhead;
|
||||||
}
|
}
|
||||||
return duration_t{0};
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
delta_clock::time_point m_oldTime;
|
Uint64 m_oldTime = 0;
|
||||||
std::array<duration_t, 4> m_overheadTimes{};
|
std::array<duration_t, 4> m_overheadTimes{};
|
||||||
size_t m_overheadTimeIdx = 0;
|
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) {
|
duration_t TimeSince(Uint64 start) const { return SDL_GetTicksNS() - start; }
|
||||||
return std::chrono::duration_cast<duration_t>(delta_clock::now() - start);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
void NanoSleep(const duration_t duration) {
|
void NanoSleep(const duration_t duration) {
|
||||||
@@ -85,9 +84,10 @@ private:
|
|||||||
|
|
||||||
LARGE_INTEGER start, current;
|
LARGE_INTEGER start, current;
|
||||||
QueryPerformanceCounter(&start);
|
QueryPerformanceCounter(&start);
|
||||||
LONGLONG ticksToWait = static_cast<LONGLONG>(duration.count() * countPerNs);
|
const LONGLONG ticksToWait = static_cast<LONGLONG>(duration * countPerNs);
|
||||||
if (DWORD ms = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); ms > 1) {
|
const Uint64 ms = duration / 1'000'000ULL;
|
||||||
::Sleep(ms - 1);
|
if (ms > 1) {
|
||||||
|
::Sleep(static_cast<DWORD>(ms - 1));
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
QueryPerformanceCounter(¤t);
|
QueryPerformanceCounter(¤t);
|
||||||
@@ -99,7 +99,7 @@ private:
|
|||||||
} while (current.QuadPart - start.QuadPart < ticksToWait);
|
} while (current.QuadPart - start.QuadPart < ticksToWait);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void NanoSleep(const duration_t duration) { SDL_DelayPrecise(duration.count()); }
|
void NanoSleep(const duration_t duration) { SDL_DelayPrecise(duration); }
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -73,6 +73,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __MWERKS__
|
#ifndef __MWERKS__
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
// Silence clangd errors about MWCC PPC intrinsics by declaring them here.
|
// Silence clangd errors about MWCC PPC intrinsics by declaring them here.
|
||||||
extern int __cntlzw(unsigned int);
|
extern int __cntlzw(unsigned int);
|
||||||
extern int __rlwimi(int, int, int, int, 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 __dcbz(void*, int);
|
||||||
extern void __sync();
|
extern void __sync();
|
||||||
extern int __abs(int);
|
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
|
#endif
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
|
|||||||
@@ -263,6 +263,9 @@ public:
|
|||||||
/* 0x9C */ u8 field_0x9c[4];
|
/* 0x9C */ u8 field_0x9c[4];
|
||||||
/* 0xA0 */ OSTime mResetHoldStartTime;
|
/* 0xA0 */ OSTime mResetHoldStartTime;
|
||||||
/* 0xA8 */ u8 field_0xa8;
|
/* 0xA8 */ u8 field_0xa8;
|
||||||
|
#if TARGET_PC
|
||||||
|
u32 mResetHoldFrameCount;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "dusk/logging.h"
|
#include "dusk/logging.h"
|
||||||
#include "dusk/settings.h"
|
#include "dusk/settings.h"
|
||||||
#include "dusk/time.h"
|
#include "dusk/time.h"
|
||||||
|
#include "f_op/f_op_overlap_mng.h"
|
||||||
|
|
||||||
#include "SDL3/SDL_timer.h"
|
#include "SDL3/SDL_timer.h"
|
||||||
#include "tracy/Tracy.hpp"
|
#include "tracy/Tracy.hpp"
|
||||||
@@ -368,11 +369,11 @@ constexpr auto FRAME_PERIOD = std::chrono::duration_cast<std::chrono::nanosecond
|
|||||||
std::chrono::duration<double>(1001.0 / 30000.0));
|
std::chrono::duration<double>(1001.0 / 30000.0));
|
||||||
constexpr auto RETRACE_PERIOD = FRAME_PERIOD / 2;
|
constexpr auto RETRACE_PERIOD = FRAME_PERIOD / 2;
|
||||||
|
|
||||||
static void waitPrecise(Limiter& limiter, Uint64 targetNs) {
|
static void waitPrecise(Limiter& limiter, Limiter::duration_t targetNs) {
|
||||||
const auto sleepTime = limiter.SleepTime(std::chrono::nanoseconds(targetNs));
|
const auto sleepTime = limiter.SleepTime(targetNs);
|
||||||
dusk::frameUsagePct =
|
dusk::frameUsagePct =
|
||||||
100.0f * (1.0f - static_cast<float>(sleepTime.count()) / static_cast<float>(targetNs));
|
100.0f * (1.0f - static_cast<float>(sleepTime) / static_cast<float>(targetNs));
|
||||||
limiter.Sleep(std::chrono::nanoseconds(targetNs));
|
limiter.Sleep(targetNs);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -385,6 +386,13 @@ static void waitForTick(u32 p1, u16 p2) {
|
|||||||
if (dusk::getTransientSettings().skipFrameRateLimit) {
|
if (dusk::getTransientSettings().skipFrameRateLimit) {
|
||||||
p1 = OS_TIMER_CLOCK / 120;
|
p1 = OS_TIMER_CLOCK / 120;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (fopOvlpM_IsPeek() && dusk::getTransientSettings().stateShareLoadActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ZoneScopedC(tracy::Color::DimGray);
|
ZoneScopedC(tracy::Color::DimGray);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ BOOL JUTGamePad::init() {
|
|||||||
void JUTGamePad::clear() {
|
void JUTGamePad::clear() {
|
||||||
mButtonReset.mReset = false;
|
mButtonReset.mReset = false;
|
||||||
field_0xa8 = 1;
|
field_0xa8 = 1;
|
||||||
|
#if TARGET_PC
|
||||||
|
mResetHoldFrameCount = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
PADStatus JUTGamePad::mPadStatus[4];
|
PADStatus JUTGamePad::mPadStatus[4];
|
||||||
@@ -219,11 +222,19 @@ void JUTGamePad::update() {
|
|||||||
mButtonReset.mReset = false;
|
mButtonReset.mReset = false;
|
||||||
} else if (!JUTGamePad::C3ButtonReset::sResetOccurred) {
|
} else if (!JUTGamePad::C3ButtonReset::sResetOccurred) {
|
||||||
if (mButtonReset.mReset == true) {
|
if (mButtonReset.mReset == true) {
|
||||||
|
#if TARGET_PC
|
||||||
|
checkResetCallback(++mResetHoldFrameCount * (OS_TIMER_CLOCK / 30));
|
||||||
|
#else
|
||||||
OSTime hold_time = OSGetTime() - mResetHoldStartTime;
|
OSTime hold_time = OSGetTime() - mResetHoldStartTime;
|
||||||
checkResetCallback(hold_time);
|
checkResetCallback(hold_time);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
mButtonReset.mReset = true;
|
mButtonReset.mReset = true;
|
||||||
|
#if TARGET_PC
|
||||||
|
mResetHoldFrameCount = 0;
|
||||||
|
#else
|
||||||
mResetHoldStartTime = OSGetTime();
|
mResetHoldStartTime = OSGetTime();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,8 +117,8 @@ static Z2WolfHowlLine sNewSong3[9] = {
|
|||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
static Z2WolfHowlLine sHowlTimeSong[6] = {
|
static Z2WolfHowlLine sHowlTimeSong[6] = {
|
||||||
{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, 20}, {HOWL_LINE_LOW, 20}, {HOWL_LINE_HIGH, 40},
|
{HOWL_LINE_MID, 15}, {HOWL_LINE_LOW, 15}, {HOWL_LINE_HIGH, 30},
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -368,9 +368,9 @@ void Z2WolfHowlMgr::setCorrectData(s8 curveID, Z2WolfHowlData* data) {
|
|||||||
break;
|
break;
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
case Z2WOLFHOWL_TIMESONG:
|
case Z2WOLFHOWL_TIMESONG:
|
||||||
cPitchUp = 1.259906f;
|
cPitchUp = 1.3348f;
|
||||||
cPitchCenter = 0.94387f;
|
cPitchCenter = 0.8909f;
|
||||||
cPitchDown = 0.840885f;
|
cPitchDown = 0.7937f;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ void daAlink_c::handleWolfHowl() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canTransform = false;
|
bool canHowl = false;
|
||||||
|
|
||||||
if (mLinkAcch.ChkGroundHit() && !checkModeFlg(MODE_PLAYER_FLY) && !checkMagneBootsOn()) {
|
if (mLinkAcch.ChkGroundHit() && !checkModeFlg(MODE_PLAYER_FLY) && !checkMagneBootsOn()) {
|
||||||
if (!checkForestOldCentury()) {
|
if (!checkForestOldCentury()) {
|
||||||
@@ -52,12 +52,17 @@ void daAlink_c::handleWolfHowl() {
|
|||||||
(checkEventRun() || getMidnaActor()->checkMetamorphoseEnable()) &&
|
(checkEventRun() || getMidnaActor()->checkMetamorphoseEnable()) &&
|
||||||
(checkModeFlg(4) || dComIfGp_checkPlayerStatus0(0, 0x10))))
|
(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);
|
getWolfHowlMgrP()->setCorrectCurve(9);
|
||||||
procWolfHowlDemoInit();
|
procWolfHowlDemoInit();
|
||||||
}
|
}
|
||||||
@@ -154,6 +159,7 @@ bool daAlink_c::checkGyroAimContext() {
|
|||||||
case PROC_BOW_SUBJECT:
|
case PROC_BOW_SUBJECT:
|
||||||
case PROC_BOOMERANG_SUBJECT:
|
case PROC_BOOMERANG_SUBJECT:
|
||||||
case PROC_COPY_ROD_SUBJECT:
|
case PROC_COPY_ROD_SUBJECT:
|
||||||
|
case PROC_HAWK_SUBJECT:
|
||||||
case PROC_HOOKSHOT_SUBJECT:
|
case PROC_HOOKSHOT_SUBJECT:
|
||||||
case PROC_SWIM_HOOKSHOT_SUBJECT:
|
case PROC_SWIM_HOOKSHOT_SUBJECT:
|
||||||
case PROC_HORSE_BOW_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);
|
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));
|
J3DModelData* chainModelData = static_cast<J3DModelData*>(dComIfG_getObjectRes(l_wArcName, 15));
|
||||||
for (u16 i = 0; i < 4; i++) {
|
for (u16 i = 0; i < 4; i++) {
|
||||||
mpWlChainModels[i] = initModel(chainModelData, 0);
|
mpWlChainModels[i] = initModel(chainModelData, 0);
|
||||||
@@ -162,6 +179,23 @@ void daAlink_c::changeWolf() {
|
|||||||
mpWlMidnaHairModel =
|
mpWlMidnaHairModel =
|
||||||
initModelEnv(static_cast<J3DModelData*>(dComIfG_getObjectRes(l_wArcName, 11)), 0x1000000);
|
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 = static_cast<J3DAnmTevRegKey*>(dComIfG_getObjectRes(l_wArcName, 18));
|
||||||
mpDMidnaBrk->searchUpdateMaterialID(mpWlMidnaModel->getModelData());
|
mpDMidnaBrk->searchUpdateMaterialID(mpWlMidnaModel->getModelData());
|
||||||
mpWlMidnaModel->getModelData()->entryTevRegAnimator(mpDMidnaBrk);
|
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);
|
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"));
|
modelData = static_cast<J3DModelData*>(dComIfG_getObjectRes(mArcName, "al_bootsH.bmd"));
|
||||||
u16 i;
|
u16 i;
|
||||||
for (i = 0; i < 2; 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++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
static u16 g_e_i[] = {0x83EB, 0x83EC, 0x83ED, 0x83EE, 0x83EF};
|
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);
|
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++) {
|
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)};
|
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);
|
i_this->mDemoCamEye.set(-4820.0f, -18600.0f, -510.0f);
|
||||||
|
|||||||
@@ -1677,7 +1677,16 @@ static void demo_camera(e_fm_class* i_this) {
|
|||||||
cXyz spBC(0.0f, 0.0f, 0.0f);
|
cXyz spBC(0.0f, 0.0f, 0.0f);
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
static u16 g_e_i[] = {0x847B, 0x847C, 0x847D, 0x847E};
|
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);
|
i_this->mDemoCamFovy = 55.0f + NREG_F(10);
|
||||||
|
|||||||
@@ -761,6 +761,11 @@ static void koro2_game(fshop_class* i_this) {
|
|||||||
sp5C.x = mDoCPd_c::getStickX3D(PAD_1);
|
sp5C.x = mDoCPd_c::getStickX3D(PAD_1);
|
||||||
sp5C.y = 0.0f;
|
sp5C.y = 0.0f;
|
||||||
sp5C.z = mDoCPd_c::getStickY(PAD_1);
|
sp5C.z = mDoCPd_c::getStickY(PAD_1);
|
||||||
|
#if TARGET_PC
|
||||||
|
if (dusk::getSettings().game.enableMirrorMode) {
|
||||||
|
sp5C.x = -sp5C.x;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
MtxPosition(&sp5C, &sp68);
|
MtxPosition(&sp5C, &sp68);
|
||||||
|
|
||||||
f32 reg_f31 = sp68.x;
|
f32 reg_f31 = sp68.x;
|
||||||
@@ -782,20 +787,15 @@ static void koro2_game(fshop_class* i_this) {
|
|||||||
reg_f30 = 0.0f;
|
reg_f30 = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s16 gyro_ax = 0;
|
||||||
|
s16 gyro_az = 0;
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
if (dusk::getSettings().game.enableGyroRollgoal) {
|
if (dusk::getSettings().game.enableGyroRollgoal) {
|
||||||
s16 rg_add_x;
|
dusk::gyro::rollgoalTableOffset(gyro_ax, gyro_az);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
#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
|
#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 TARGET_PC
|
||||||
if (i_this->field_0x4010 != 2) {
|
if (i_this->field_0x4010 != 2) {
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ static char* l_arcName = "Mirror";
|
|||||||
static char* l_arcName2 = "MR-Table";
|
static char* l_arcName2 = "MR-Table";
|
||||||
|
|
||||||
dMirror_packet_c::dMirror_packet_c() {
|
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();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,6 +599,13 @@ int daMirror_c::execute() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (mPacket.mbReset) {
|
||||||
|
mPacket.mModelCount = 0;
|
||||||
|
mPacket.mbReset = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
daPy_py_c* player = daPy_getLinkPlayerActorClass();
|
daPy_py_c* player = daPy_getLinkPlayerActorClass();
|
||||||
JUT_ASSERT(0, player != NULL);
|
JUT_ASSERT(0, player != NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -2855,7 +2855,7 @@ void* daMP_Reader(void*) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 daMP_ReadThreadStack[0x2000];
|
static u8 daMP_ReadThreadStack[DUSK_IF_ELSE(8, 0x2000)];
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
static BOOL VideoThreadCancelled;
|
static BOOL VideoThreadCancelled;
|
||||||
@@ -2880,7 +2880,7 @@ static BOOL daMP_CreateReadThread(s32 param_0) {
|
|||||||
|
|
||||||
static OSThread daMP_VideoDecodeThread;
|
static OSThread daMP_VideoDecodeThread;
|
||||||
|
|
||||||
static u8 daMP_VideoDecodeThreadStack[0x64000];
|
static u8 daMP_VideoDecodeThreadStack[DUSK_IF_ELSE(8, 0x64000)];
|
||||||
|
|
||||||
static OSMessageQueue daMP_FreeTextureSetQueue;
|
static OSMessageQueue daMP_FreeTextureSetQueue;
|
||||||
|
|
||||||
@@ -3132,7 +3132,7 @@ static BOOL AudioThreadCancelled;
|
|||||||
|
|
||||||
static OSThread daMP_AudioDecodeThread;
|
static OSThread daMP_AudioDecodeThread;
|
||||||
|
|
||||||
static u8 daMP_AudioDecodeThreadStack[0x64000];
|
static u8 daMP_AudioDecodeThreadStack[DUSK_IF_ELSE(8, 0x64000)];
|
||||||
|
|
||||||
static OSMessageQueue daMP_FreeAudioBufferQueue;
|
static OSMessageQueue daMP_FreeAudioBufferQueue;
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,10 @@
|
|||||||
#include "f_op/f_op_camera_mng.h"
|
#include "f_op/f_op_camera_mng.h"
|
||||||
#include "m_Do/m_Do_mtx.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) {
|
static f32 Reflect(cXyz* i_vec, cBgS_PolyInfo const& i_polyinfo, f32 i_scale) {
|
||||||
cM3dGPla plane;
|
cM3dGPla plane;
|
||||||
|
|
||||||
@@ -31,6 +35,27 @@ static f32 Reflect(cXyz* i_vec, cBgS_PolyInfo const& i_polyinfo, f32 i_scale) {
|
|||||||
return 0.0f;
|
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() {
|
const daItemBase_data& daItemBase_c::getData() {
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
@@ -353,6 +378,10 @@ int daItem_c::_daItem_draw() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
dusk::frame_interp::add_interpolation_callback(&d_a_obj_item_interp_callback, this);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (chkDraw()) {
|
if (chkDraw()) {
|
||||||
return DrawBase();
|
return DrawBase();
|
||||||
}
|
}
|
||||||
@@ -390,6 +419,9 @@ void daItem_c::procMainNormal() {
|
|||||||
cLib_chaseF(&scale.z, mItemScale.z, step_z);
|
cLib_chaseF(&scale.z, mItemScale.z, step_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (!dusk::getSettings().game.enableIndefiniteItemDrops) {
|
||||||
|
#endif
|
||||||
if (mWaitTimer == 0) {
|
if (mWaitTimer == 0) {
|
||||||
if (mDisappearTimer == 0) {
|
if (mDisappearTimer == 0) {
|
||||||
deleteItem();
|
deleteItem();
|
||||||
@@ -399,6 +431,9 @@ void daItem_c::procMainNormal() {
|
|||||||
changeDraw();
|
changeDraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if TARGET_PC
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
mCcCyl.SetC(current.pos);
|
mCcCyl.SetC(current.pos);
|
||||||
dComIfG_Ccsp()->Set(&mCcCyl);
|
dComIfG_Ccsp()->Set(&mCcCyl);
|
||||||
@@ -1058,9 +1093,16 @@ int daItem_c::CountTimer() {
|
|||||||
if (checkCountTimer()) {
|
if (checkCountTimer()) {
|
||||||
if (mWaitTimer > 0) {
|
if (mWaitTimer > 0) {
|
||||||
mWaitTimer--;
|
mWaitTimer--;
|
||||||
} else if (mDisappearTimer > 0) {
|
}
|
||||||
|
#if TARGET_PC
|
||||||
|
else if (!dusk::getSettings().game.enableIndefiniteItemDrops && mDisappearTimer > 0) {
|
||||||
mDisappearTimer--;
|
mDisappearTimer--;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
else if (mDisappearTimer > 0) {
|
||||||
|
mDisappearTimer--;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
cLib_calcTimer<u8>(&mBoomWindTgTimer);
|
cLib_calcTimer<u8>(&mBoomWindTgTimer);
|
||||||
|
|||||||
@@ -699,8 +699,8 @@ void dFlower_packet_c::draw() {
|
|||||||
if (!cLib_checkBit<u8>(sp44->m_state, 4) && !cLib_checkBit<u8>(sp44->m_state, 0x40)) {
|
if (!cLib_checkBit<u8>(sp44->m_state, 4) && !cLib_checkBit<u8>(sp44->m_state, 0x40)) {
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
Mtx flower_mtx;
|
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);
|
GXLoadPosMtxImm(flower_mtx, 0);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
@@ -854,21 +854,18 @@ void dFlower_packet_c::draw() {
|
|||||||
if (!cLib_checkBit<u8>(sp34->m_state, 4) && cLib_checkBit<u8>(sp34->m_state, 0x40)) {
|
if (!cLib_checkBit<u8>(sp34->m_state, 4) && cLib_checkBit<u8>(sp34->m_state, 0x40)) {
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
Mtx flower_mtx;
|
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);
|
cMtx_concat(j3dSys.getViewMtx(), flower_mtx, flower_mtx);
|
||||||
GXLoadPosMtxImm(flower_mtx, 0);
|
GXLoadPosMtxImm(flower_mtx, 0);
|
||||||
} else {
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
GXLoadPosMtxImm(sp34->m_modelMtx, 0);
|
GXLoadPosMtxImm(sp34->m_modelMtx, 0);
|
||||||
#ifdef TARGET_PC
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
|
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
GXLoadTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, GX_TEXMAP0);
|
GXLoadTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, GX_TEXMAP0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!cLib_checkBit<u8>(sp34->m_state, 8)) {
|
if (!cLib_checkBit<u8>(sp34->m_state, 8)) {
|
||||||
if (!cLib_checkBit<u8>(sp34->m_state, 0x10)) {
|
if (!cLib_checkBit<u8>(sp34->m_state, 0x10)) {
|
||||||
GXCallDisplayList(mp_Jhana01DL, m_Jhana01DL_size);
|
GXCallDisplayList(mp_Jhana01DL, m_Jhana01DL_size);
|
||||||
@@ -995,7 +992,7 @@ void dFlower_packet_c::update() {
|
|||||||
mDoMtx_stack_c::scaleM(temp_f31, temp_f31, temp_f31);
|
mDoMtx_stack_c::scaleM(temp_f31, temp_f31, temp_f31);
|
||||||
cMtx_concat(j3dSys.getViewMtx(), temp_r28, data_p->m_modelMtx);
|
cMtx_concat(j3dSys.getViewMtx(), temp_r28, data_p->m_modelMtx);
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), data_p->m_modelMtx);
|
dusk::frame_interp::record_final_mtx(temp_r28, data_p->m_modelMtx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,11 +70,7 @@ dFs_HIO_c::dFs_HIO_c() {
|
|||||||
select_icon_appear_frames = 5;
|
select_icon_appear_frames = 5;
|
||||||
appear_display_wait_frames = 15;
|
appear_display_wait_frames = 15;
|
||||||
field_0x000d = 15;
|
field_0x000d = 15;
|
||||||
#if TARGET_PC
|
|
||||||
card_wait_frames = 0;
|
|
||||||
#else
|
|
||||||
card_wait_frames = 90;
|
card_wait_frames = 90;
|
||||||
#endif
|
|
||||||
test_frame_counts[0] = 1.11f;
|
test_frame_counts[0] = 1.11f;
|
||||||
test_frame_counts[1] = 1.11f;
|
test_frame_counts[1] = 1.11f;
|
||||||
test_frame_counts[2] = 1.11f;
|
test_frame_counts[2] = 1.11f;
|
||||||
@@ -2367,7 +2363,7 @@ void dFile_select_c::CommandExec() {
|
|||||||
break;
|
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() {
|
void dFile_select_c::DataEraseWait() {
|
||||||
@@ -4759,7 +4755,7 @@ void dFile_select_c::MemCardFormatYesSel2Disp() {
|
|||||||
bool isErrorTxtChange = errorTxtChangeAnm();
|
bool isErrorTxtChange = errorTxtChangeAnm();
|
||||||
bool isYnMenuMove = yesnoMenuMoveAnm();
|
bool isYnMenuMove = yesnoMenuMoveAnm();
|
||||||
if (isErrorTxtChange == true && isYnMenuMove == true) {
|
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();
|
mDoMemCd_Format();
|
||||||
mCardCheckProc = MEMCARDCHECKPROC_FORMAT;
|
mCardCheckProc = MEMCARDCHECKPROC_FORMAT;
|
||||||
}
|
}
|
||||||
@@ -4830,7 +4826,7 @@ void dFile_select_c::MemCardMakeGameFileSelDisp() {
|
|||||||
|
|
||||||
if (isErrorTxtChange == true && isYnMenuMove == true && isKetteiTxtDisp == true) {
|
if (isErrorTxtChange == true && isYnMenuMove == true && isKetteiTxtDisp == true) {
|
||||||
if (field_0x0268 != 0) {
|
if (field_0x0268 != 0) {
|
||||||
mWaitTimer = g_fsHIO.card_wait_frames;
|
mWaitTimer = IF_DUSK(dusk::getSettings().game.instantSaves ? 0 :) g_fsHIO.card_wait_frames;
|
||||||
setInitSaveData();
|
setInitSaveData();
|
||||||
dataSave();
|
dataSave();
|
||||||
mCardCheckProc = MEMCARDCHECKPROC_MAKE_GAMEFILE;
|
mCardCheckProc = MEMCARDCHECKPROC_MAKE_GAMEFILE;
|
||||||
|
|||||||
@@ -237,6 +237,13 @@ void dDrawPath_c::rendering(dDrawPath_c::line_class const* p_line) {
|
|||||||
if (isDrawType(p_line->field_0x0)) {
|
if (isDrawType(p_line->field_0x0)) {
|
||||||
int width = getLineWidth(p_line->field_0x1);
|
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) {
|
if (width > 0 && p_line->mDataNum >= 2) {
|
||||||
GXSetLineWidth(width, GX_TO_ZERO);
|
GXSetLineWidth(width, GX_TO_ZERO);
|
||||||
GXSetTevColor(GX_TEVREG0, *getLineColor(p_line->field_0x0 & 0x3F, p_line->field_0x1));
|
GXSetTevColor(GX_TEVREG0, *getLineColor(p_line->field_0x0 & 0x3F, p_line->field_0x1));
|
||||||
|
|||||||
@@ -2399,6 +2399,13 @@ void dMenu_Collect3D_c::_move(u8 param_0, u8 param_1) {
|
|||||||
posZ = 550.0f;
|
posZ = 550.0f;
|
||||||
}
|
}
|
||||||
toItem3Dpos(linkPos.x, posY, posZ, &itemPos);
|
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) {
|
if (param_0 == 0 && param_1 == 0) {
|
||||||
f32 temp = 450.0f;
|
f32 temp = 450.0f;
|
||||||
ANGLE_ADD(mLinkAngle, temp);
|
ANGLE_ADD(mLinkAngle, temp);
|
||||||
|
|||||||
+42
-1
@@ -21,6 +21,7 @@
|
|||||||
#include "d/d_msg_string.h"
|
#include "d/d_msg_string.h"
|
||||||
#include "d/d_meter_haihai.h"
|
#include "d/d_meter_haihai.h"
|
||||||
#include "d/d_menu_window.h"
|
#include "d/d_menu_window.h"
|
||||||
|
#include "dusk/settings.h"
|
||||||
#include "f_op/f_op_msg_mng.h"
|
#include "f_op/f_op_msg_mng.h"
|
||||||
#include "m_Do/m_Do_graphic.h"
|
#include "m_Do/m_Do_graphic.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -945,9 +946,15 @@ void dMenu_DmapBg_c::draw() {
|
|||||||
mpMeterHaihai->drawHaihai(field_0xdda,
|
mpMeterHaihai->drawHaihai(field_0xdda,
|
||||||
x1 + (local_224.x + local_218.x) / 2,
|
x1 + (local_224.x + local_218.x) / 2,
|
||||||
y1 + (local_224.y + local_218.y) / 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));
|
-35.0f + (local_224.y - local_218.y));
|
||||||
|
#if TARGET_PC
|
||||||
|
if (!dusk::getSettings().game.enableFrameInterpolation) {
|
||||||
|
field_0xdda = 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
field_0xdda = 0;
|
field_0xdda = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
dMenu_Dmap_c::myclass->drawFloorScreenTop(mFloorScreen, field_0xd94, field_0xd98, grafContext);
|
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);
|
JUT_ASSERT(2323, mpBackTexture != NULL);
|
||||||
|
|
||||||
void* spec = mpArchive->getResource("spec/spec.dat");
|
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);
|
memcpy(&field_0xd80, spec, 20);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2545,6 +2581,11 @@ void dMenu_Dmap_c::zoomIn_proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dMenu_Dmap_c::zoomOut_init_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);
|
Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_ZOOMOUT, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
|
||||||
mMapCtrl->initZoomOut(10);
|
mMapCtrl->initZoomOut(10);
|
||||||
mpDrawBg->iconScaleAnmInit(1.0f, 0.0f, 10);
|
mpDrawBg->iconScaleAnmInit(1.0f, 0.0f, 10);
|
||||||
|
|||||||
@@ -185,6 +185,17 @@ dMenu_Ring_c::dMenu_Ring_c(JKRExpHeap* i_heap, STControl* i_stick, CSTControl* i
|
|||||||
field_0x682 = 0xc000;
|
field_0x682 = 0xc000;
|
||||||
break;
|
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++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
field_0x674[i] = 0;
|
field_0x674[i] = 0;
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
@@ -631,7 +642,71 @@ void dMenu_Ring_c::_draw() {
|
|||||||
} else {
|
} else {
|
||||||
drawSelectItem();
|
drawSelectItem();
|
||||||
drawItem2();
|
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();
|
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->trans(mCenterPosX, mCenterPosY);
|
||||||
mpItemExplain->draw((J2DOrthoGraph*)grafPort);
|
mpItemExplain->draw((J2DOrthoGraph*)grafPort);
|
||||||
drawFlag0();
|
drawFlag0();
|
||||||
|
|||||||
@@ -1987,6 +1987,13 @@ bool jmessage_tSequenceProcessor::do_isReady() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (dusk::getSettings().game.instantText && mDoCPd_c::getHoldB(0)) {
|
||||||
|
field_0xb2 = 1;
|
||||||
|
pReference->setSendTimer(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (dComIfGp_checkMesgBgm()) {
|
if (dComIfGp_checkMesgBgm()) {
|
||||||
bool isItemMusicPlaying = true;
|
bool isItemMusicPlaying = true;
|
||||||
if (mDoAud_checkPlayingSubBgmFlag() != Z2BGM_ITEM_GET &&
|
if (mDoAud_checkPlayingSubBgmFlag() != Z2BGM_ITEM_GET &&
|
||||||
|
|||||||
+132
-10
@@ -5,14 +5,15 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <span>
|
#include <span>
|
||||||
|
|
||||||
#include "Adpcm.hpp"
|
#include "Adpcm.hpp"
|
||||||
#include "freeverb/revmodel.hpp"
|
#include "freeverb/revmodel.hpp"
|
||||||
#include "JSystem/JAudio2/JASDriverIF.h"
|
|
||||||
#include "dusk/audio/DuskAudioSystem.h"
|
#include "dusk/audio/DuskAudioSystem.h"
|
||||||
#include "dusk/endian.h"
|
#include "dusk/endian.h"
|
||||||
|
#include "dusk/logging.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "tracy/Tracy.hpp"
|
#include "tracy/Tracy.hpp"
|
||||||
|
|
||||||
@@ -95,6 +96,13 @@ static void RenderChannel(
|
|||||||
ChannelAuxData& channelAux,
|
ChannelAuxData& channelAux,
|
||||||
OutputSubframe& subframe);
|
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.
|
* 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.resamplePos = 0.0;
|
||||||
aux.resamplePrev = 0;
|
aux.resamplePrev = 0;
|
||||||
|
|
||||||
|
aux.oscPhase = 0;
|
||||||
|
|
||||||
aux.prev_lp_out = 0.0f;
|
aux.prev_lp_out = 0.0f;
|
||||||
aux.prev_lp_in = 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) {
|
void dusk::audio::DspRender(OutputSubframe& subframe) {
|
||||||
ZoneScoped;
|
ZoneScoped;
|
||||||
if (DumpAudio != sDumpWasActive) {
|
if (DumpAudio != sDumpWasActive) {
|
||||||
@@ -152,6 +275,8 @@ void dusk::audio::DspRender(OutputSubframe& subframe) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GenerateEvolvingHarmonic();
|
||||||
|
|
||||||
std::span channels(JASDsp::CH_BUF, DSP_CHANNELS);
|
std::span channels(JASDsp::CH_BUF, DSP_CHANNELS);
|
||||||
|
|
||||||
DspSubframe reverbInputL = {};
|
DspSubframe reverbInputL = {};
|
||||||
@@ -174,17 +299,14 @@ void dusk::audio::DspRender(OutputSubframe& subframe) {
|
|||||||
channel.mIsFinished = true;
|
channel.mIsFinished = true;
|
||||||
continue;
|
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 = {};
|
OutputSubframe channelSubframe = {};
|
||||||
RenderChannel(channel, channelAux, channelSubframe);
|
if (channel.mWaveAramAddress == 0) {
|
||||||
|
RenderOscChannel(channel, channelAux, channelSubframe);
|
||||||
|
} else {
|
||||||
|
ValidateChannel(channel);
|
||||||
|
RenderChannel(channel, channelAux, channelSubframe);
|
||||||
|
}
|
||||||
|
|
||||||
if (EnableReverb) {
|
if (EnableReverb) {
|
||||||
// scale the input to the reverb rather than using wet/dry on the output.
|
// 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
|
// last consumed sample from decodeBuf
|
||||||
s16 resamplePrev;
|
s16 resamplePrev;
|
||||||
|
|
||||||
|
// phase of oscillator channels
|
||||||
|
u16 oscPhase;
|
||||||
|
|
||||||
// low pass previous state
|
// low pass previous state
|
||||||
f32 prev_lp_out; // out[n-1]
|
f32 prev_lp_out; // out[n-1]
|
||||||
f32 prev_lp_in; // in[n-1]
|
f32 prev_lp_in; // in[n-1]
|
||||||
|
|||||||
+21
-5
@@ -3,6 +3,27 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.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
|
#ifndef _MSC_VER
|
||||||
int stricmp(const char* str1, const char* str2) {
|
int stricmp(const char* str1, const char* str2) {
|
||||||
char a_var;
|
char a_var;
|
||||||
@@ -48,11 +69,6 @@ int strnicmp(const char* str1, const char* str2, int n) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void *_memcpy(void* dest, void const* src, int n) {
|
|
||||||
return memcpy(dest, src, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DCZeroRange(void* addr, uint32_t nBytes) {
|
void DCZeroRange(void* addr, uint32_t nBytes) {
|
||||||
#if defined(_MSC_VER) || TARGET_ANDROID
|
#if defined(_MSC_VER) || TARGET_ANDROID
|
||||||
memset(addr, 0, nBytes);
|
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
|
|
||||||
}
|
|
||||||
@@ -127,14 +127,20 @@ void ensure_initialized() {
|
|||||||
s_initialized = true;
|
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) {
|
void begin_frame(bool enabled, bool is_sim_frame, float step) {
|
||||||
g_enabled = enabled;
|
g_enabled = enabled;
|
||||||
g_is_sim_frame = is_sim_frame;
|
g_is_sim_frame = is_sim_frame;
|
||||||
g_step = std::clamp(step, 0.0f, 1.0f);
|
g_step = std::clamp(step, 0.0f, 1.0f);
|
||||||
if (is_sim_frame) {
|
|
||||||
s_interpolationCallBackWork.clear();
|
|
||||||
s_cam_prev = std::move(s_cam_curr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_enabled() {
|
bool is_enabled() {
|
||||||
@@ -286,12 +292,20 @@ void interp_view(::view_class* view) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const f32 step = get_interpolation_step();
|
const f32 step = get_interpolation_step();
|
||||||
|
const bool is_cam_curr_authoritative = g_is_sim_frame && step <= 0.0f;
|
||||||
|
|
||||||
cXyz eye;
|
cXyz eye;
|
||||||
cXyz center;
|
cXyz center;
|
||||||
cXyz up;
|
cXyz up;
|
||||||
lerp_xyz(&eye, s_cam_prev.eye, s_cam_curr.eye, step);
|
if (is_cam_curr_authoritative) {
|
||||||
lerp_xyz(¢er, s_cam_prev.center, s_cam_curr.center, step);
|
eye = s_cam_curr.eye;
|
||||||
lerp_xyz(&up, s_cam_prev.up, s_cam_curr.up, step);
|
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()) {
|
if (!up.normalizeRS()) {
|
||||||
up = s_cam_curr.up;
|
up = s_cam_curr.up;
|
||||||
up.normalizeRS();
|
up.normalizeRS();
|
||||||
@@ -300,19 +314,25 @@ void interp_view(::view_class* view) {
|
|||||||
view->lookat.eye = eye;
|
view->lookat.eye = eye;
|
||||||
view->lookat.center = center;
|
view->lookat.center = center;
|
||||||
view->lookat.up = up;
|
view->lookat.up = up;
|
||||||
view->bank = lerp_bank(s_cam_prev.bank, s_cam_curr.bank, step);
|
if (is_cam_curr_authoritative) {
|
||||||
view->fovy = s_cam_prev.fovy + (s_cam_curr.fovy - s_cam_prev.fovy) * step;
|
view->bank = s_cam_curr.bank;
|
||||||
view->aspect = s_cam_prev.aspect + (s_cam_curr.aspect - s_cam_prev.aspect) * step;
|
view->fovy = s_cam_curr.fovy;
|
||||||
view->near_ = s_cam_prev.near_ + (s_cam_curr.near_ - s_cam_prev.near_) * step;
|
view->aspect = s_cam_curr.aspect;
|
||||||
view->far_ = s_cam_prev.far_ + (s_cam_curr.far_ - s_cam_prev.far_) * step;
|
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
|
// 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
|
// next sim frame, but I don't care enough to right now
|
||||||
#if WIDESCREEN_SUPPORT
|
#if WIDESCREEN_SUPPORT
|
||||||
if (mDoGph_gInf_c::isWide() && !mDoGph_gInf_c::isWideZoom() && step >= 0.5f ?
|
const f32 wide_step = is_cam_curr_authoritative ? 1.0f : step;
|
||||||
s_cam_curr.wideZoom :
|
if (mDoGph_gInf_c::isWide() && !mDoGph_gInf_c::isWideZoom() && wide_step >= 0.5f ? s_cam_curr.wideZoom : s_cam_prev.wideZoom) {
|
||||||
s_cam_prev.wideZoom)
|
|
||||||
{
|
|
||||||
mDoGph_gInf_c::onWideZoom();
|
mDoGph_gInf_c::onWideZoom();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+44
-23
@@ -5,62 +5,84 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace dusk {
|
namespace dusk::game_clock {
|
||||||
namespace game_clock {
|
|
||||||
|
|
||||||
using clock = std::chrono::steady_clock;
|
using clock = std::chrono::steady_clock;
|
||||||
|
|
||||||
bool s_initialized = false;
|
bool s_initialized = false;
|
||||||
clock::time_point s_previous_sample{};
|
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;
|
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() {
|
void ensure_initialized() {
|
||||||
if (s_initialized) {
|
if (s_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s_previous_sample = clock::now();
|
s_previous_sample = clock::now();
|
||||||
s_sim_accumulator = sim_pace();
|
s_current_snapshot_time = s_previous_sample;
|
||||||
s_initialized = true;
|
s_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_accumulator() {
|
|
||||||
ensure_initialized();
|
|
||||||
s_sim_accumulator = fmodf(s_sim_accumulator, sim_pace());
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset_frame_timer() {
|
void reset_frame_timer() {
|
||||||
s_previous_sample = clock::now();
|
s_previous_sample = clock::now();
|
||||||
s_sim_accumulator = 0.0f;
|
s_current_snapshot_time = s_previous_sample - kSimPeriodDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
MainLoopPacer advance_main_loop() {
|
MainLoopPacer advance_main_loop() {
|
||||||
ensure_initialized();
|
ensure_initialized();
|
||||||
|
|
||||||
const clock::time_point now = clock::now();
|
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_previous_sample = now;
|
||||||
|
|
||||||
s_sim_accumulator += presentation_dt;
|
|
||||||
|
|
||||||
MainLoopPacer out{};
|
MainLoopPacer out{};
|
||||||
out.presentation_dt_seconds = presentation_dt;
|
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.is_interpolating = should_interpolate;
|
||||||
out.sim_pace = sim_pace();
|
out.sim_pace = sim_pace();
|
||||||
|
|
||||||
if (!should_interpolate) {
|
if (!should_interpolate) {
|
||||||
s_sim_accumulator = 0.0f;
|
s_current_snapshot_time = now;
|
||||||
out.do_sim_tick = true;
|
out.sim_ticks_to_run = 1;
|
||||||
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();
|
|
||||||
return out;
|
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) {
|
float consume_interval(const void* consumer) {
|
||||||
@@ -78,5 +100,4 @@ float consume_interval(const void* consumer) {
|
|||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace game_clock
|
} // namespace dusk::game_clock
|
||||||
} // namespace dusk
|
|
||||||
|
|||||||
@@ -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 "dusk/gyro.h"
|
||||||
#include "d/actor/d_a_alink.h"
|
#include "d/actor/d_a_alink.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
namespace dusk::gyro {
|
namespace dusk::gyro {
|
||||||
namespace {
|
namespace {
|
||||||
constexpr s32 kRollgoalTableMaxOffset = 12000;
|
constexpr s32 kRollgoalTableMaxOffset = 6500;
|
||||||
constexpr float kGyroEmaAlphaMin = 0.05f;
|
constexpr float kGyroEmaAlphaMin = 0.05f;
|
||||||
constexpr float kGyroEmaAlphaMax = 1.0f;
|
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_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_gx = 0.0f;
|
||||||
float s_smooth_gy = 0.0f;
|
float s_smooth_gy = 0.0f;
|
||||||
float s_smooth_gz = 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_yaw_rad = 0.0f;
|
||||||
float s_pitch_rad = 0.0f;
|
float s_pitch_rad = 0.0f;
|
||||||
float s_roll_rad = 0.0f;
|
float s_roll_rad = 0.0f;
|
||||||
@@ -19,6 +32,10 @@ s32 s_rollgoal_az = 0;
|
|||||||
|
|
||||||
void reset_filter_state() {
|
void reset_filter_state() {
|
||||||
s_smooth_gx = s_smooth_gy = s_smooth_gz = 0.0f;
|
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_yaw_rad = s_pitch_rad = s_roll_rad = 0.0f;
|
||||||
s_rollgoal_ax = s_rollgoal_az = 0;
|
s_rollgoal_ax = s_rollgoal_az = 0;
|
||||||
}
|
}
|
||||||
@@ -49,15 +66,30 @@ bool queryGyroAimContext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void read(float dt) {
|
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) {
|
if (s_sensor_enabled) {
|
||||||
PADSetSensorEnabled(PAD_CHAN0, PAD_SENSOR_GYRO, FALSE);
|
PADSetSensorEnabled(PAD_CHAN0, PAD_SENSOR_GYRO, FALSE);
|
||||||
s_sensor_enabled = false;
|
s_sensor_enabled = false;
|
||||||
}
|
}
|
||||||
|
if (s_accel_enabled) {
|
||||||
|
PADSetSensorEnabled(PAD_CHAN0, PAD_SENSOR_ACCEL, FALSE);
|
||||||
|
s_accel_enabled = false;
|
||||||
|
}
|
||||||
reset_filter_state();
|
reset_filter_state();
|
||||||
return;
|
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 (!s_sensor_enabled) {
|
||||||
if (!PADHasSensor(PAD_CHAN0, PAD_SENSOR_GYRO)) {
|
if (!PADHasSensor(PAD_CHAN0, PAD_SENSOR_GYRO)) {
|
||||||
return;
|
return;
|
||||||
@@ -68,6 +100,13 @@ void read(float dt) {
|
|||||||
s_sensor_enabled = true;
|
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];
|
f32 gyro[3];
|
||||||
if (!PADGetSensorData(PAD_CHAN0, PAD_SENSOR_GYRO, gyro, 3)) {
|
if (!PADGetSensorData(PAD_CHAN0, PAD_SENSOR_GYRO, gyro, 3)) {
|
||||||
return;
|
return;
|
||||||
@@ -80,9 +119,50 @@ void read(float dt) {
|
|||||||
s_smooth_gy += smooth_alpha * (gyro[1] - s_smooth_gy);
|
s_smooth_gy += smooth_alpha * (gyro[1] - s_smooth_gy);
|
||||||
s_smooth_gz += smooth_alpha * (gyro[2] - s_smooth_gz);
|
s_smooth_gz += smooth_alpha * (gyro[2] - s_smooth_gz);
|
||||||
|
|
||||||
s_pitch_rad = -apply_deadband(s_smooth_gx, deadband) * dt * dusk::getSettings().game.gyroSensitivityX;
|
const float pitch_rate = apply_deadband(s_smooth_gx, deadband);
|
||||||
s_yaw_rad = apply_deadband(s_smooth_gy, deadband) * dt * dusk::getSettings().game.gyroSensitivityY;
|
const float yaw_rate = apply_deadband(s_smooth_gy, deadband);
|
||||||
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 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_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;
|
s_yaw_rad = dusk::getSettings().game.gyroInvertYaw ? -s_yaw_rad : s_yaw_rad;
|
||||||
|
|||||||
@@ -305,6 +305,10 @@ namespace dusk {
|
|||||||
ImGuiMenuGame::ToggleFullscreen();
|
ImGuiMenuGame::ToggleFullscreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_Escape) && getSettings().video.enableFullscreen) {
|
||||||
|
ImGuiMenuGame::ToggleFullscreen();
|
||||||
|
}
|
||||||
|
|
||||||
if (!dusk::IsGameLaunched) {
|
if (!dusk::IsGameLaunched) {
|
||||||
m_preLaunchWindow.draw();
|
m_preLaunchWindow.draw();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ namespace dusk {
|
|||||||
ToggleFullscreen();
|
ToggleFullscreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem("Restore Default Window Size")) {
|
if (ImGui::Button("Restore Default Window Size")) {
|
||||||
getSettings().video.enableFullscreen.setValue(false);
|
getSettings().video.enableFullscreen.setValue(false);
|
||||||
VISetWindowFullscreen(false);
|
VISetWindowFullscreen(false);
|
||||||
VISetWindowSize(FB_WIDTH * 2, FB_HEIGHT * 2);
|
VISetWindowSize(FB_WIDTH * 2, FB_HEIGHT * 2);
|
||||||
@@ -75,6 +75,8 @@ namespace dusk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
bool vsync = getSettings().video.enableVsync;
|
bool vsync = getSettings().video.enableVsync;
|
||||||
if (ImGui::Checkbox("Enable VSync", &vsync)) {
|
if (ImGui::Checkbox("Enable VSync", &vsync)) {
|
||||||
getSettings().video.enableVsync.setValue(vsync);
|
getSettings().video.enableVsync.setValue(vsync);
|
||||||
@@ -163,6 +165,8 @@ namespace dusk {
|
|||||||
|
|
||||||
ImGui::Checkbox("Enable LOD Bias", &aurora::gx::enableLodBias);
|
ImGui::Checkbox("Enable LOD Bias", &aurora::gx::enableLodBias);
|
||||||
|
|
||||||
|
config::ImGuiCheckbox("Enable Depth of Field", getSettings().game.enableDepthOfField);
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,6 +191,11 @@ namespace dusk {
|
|||||||
ImGui::SetTooltip("Restores patched glitches from Wii USA 1.0,\n"
|
ImGui::SetTooltip("Restores patched glitches from Wii USA 1.0,\n"
|
||||||
"the first released version.");
|
"the first released version.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config::ImGuiCheckbox("Enable Rotating Link Doll", getSettings().game.enableLinkDollRotation);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("Enables rotating Link in the collection menu with the C-Stick");
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::SeparatorText("Difficulty");
|
ImGui::SeparatorText("Difficulty");
|
||||||
|
|
||||||
@@ -284,6 +293,8 @@ namespace dusk {
|
|||||||
config::ImGuiCheckbox("Infinite Oil", getSettings().game.infiniteOil);
|
config::ImGuiCheckbox("Infinite Oil", getSettings().game.infiniteOil);
|
||||||
config::ImGuiCheckbox("Infinite Oxygen", getSettings().game.infiniteOxygen);
|
config::ImGuiCheckbox("Infinite Oxygen", getSettings().game.infiniteOxygen);
|
||||||
config::ImGuiCheckbox("Infinite Rupees", getSettings().game.infiniteRupees);
|
config::ImGuiCheckbox("Infinite Rupees", getSettings().game.infiniteRupees);
|
||||||
|
config::ImGuiCheckbox("Items Don't Despawn", getSettings().game.enableIndefiniteItemDrops);
|
||||||
|
ImGui::SetItemTooltip("Items Don't Despawn Unless You Load A Different Room In Which Case They Do But Even Under Some Circumstances They Don't, It Is Quite Rare Though");
|
||||||
|
|
||||||
ImGui::SeparatorText("Abilities");
|
ImGui::SeparatorText("Abilities");
|
||||||
config::ImGuiCheckbox("Moon Jump (R+A)", getSettings().game.moonJump);
|
config::ImGuiCheckbox("Moon Jump (R+A)", getSettings().game.moonJump);
|
||||||
@@ -312,14 +323,14 @@ namespace dusk {
|
|||||||
|
|
||||||
void ImGuiMenuGame::drawAudioMenu() {
|
void ImGuiMenuGame::drawAudioMenu() {
|
||||||
if (ImGui::BeginMenu("Audio")) {
|
if (ImGui::BeginMenu("Audio")) {
|
||||||
|
|
||||||
|
ImGui::SeparatorText("Volume");
|
||||||
|
|
||||||
ImGui::Text("Master Volume");
|
ImGui::Text("Master Volume");
|
||||||
if (config::ImGuiSliderInt("##masterVolume", getSettings().audio.masterVolume, 0, 100)) {
|
if (config::ImGuiSliderInt("##masterVolume", getSettings().audio.masterVolume, 0, 100)) {
|
||||||
dusk::audio::SetMasterVolume(getSettings().audio.masterVolume / 100.0f);
|
dusk::audio::SetMasterVolume(getSettings().audio.masterVolume / 100.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config::ImGuiCheckbox("Enable Reverb", getSettings().audio.enableReverb)) {
|
|
||||||
dusk::audio::SetEnableReverb(getSettings().audio.enableReverb);
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
// TODO: Implement additional settings
|
// TODO: Implement additional settings
|
||||||
ImGui::Text("Main Music Volume");
|
ImGui::Text("Main Music Volume");
|
||||||
@@ -339,6 +350,13 @@ namespace dusk {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
ImGui::SeparatorText("Effects");
|
||||||
|
|
||||||
|
if (config::ImGuiCheckbox("Enable Reverb", getSettings().audio.enableReverb)) {
|
||||||
|
dusk::audio::SetEnableReverb(getSettings().audio.enableReverb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ImGui::SeparatorText("Tweaks");
|
ImGui::SeparatorText("Tweaks");
|
||||||
|
|
||||||
config::ImGuiCheckbox("No Low HP Sound", getSettings().game.noLowHpSound);
|
config::ImGuiCheckbox("No Low HP Sound", getSettings().game.noLowHpSound);
|
||||||
@@ -359,7 +377,11 @@ namespace dusk {
|
|||||||
if (ImGui::BeginMenu("Input")) {
|
if (ImGui::BeginMenu("Input")) {
|
||||||
ImGui::SeparatorText("Controller");
|
ImGui::SeparatorText("Controller");
|
||||||
|
|
||||||
ImGui::MenuItem("Configure Controller", nullptr, &m_showControllerConfig);
|
if (ImGui::Button("Configure Controller")){
|
||||||
|
m_showControllerConfig = !m_showControllerConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SeparatorText("Camera");
|
||||||
|
|
||||||
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
|
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
|
||||||
|
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ namespace dusk {
|
|||||||
ImGui::Text("Link");
|
ImGui::Text("Link");
|
||||||
ImGuiStringViewText(
|
ImGuiStringViewText(
|
||||||
player != nullptr
|
player != nullptr
|
||||||
? fmt::format("Position: {: .2f}, {: .2f}, {: .2f}\n", player->current.pos.x, player->current.pos.y, player->current.pos.z)
|
? fmt::format("Position: {: .4f}, {: .4f}, {: .4f}\n", player->current.pos.x, player->current.pos.y, player->current.pos.z)
|
||||||
: "Position: ?, ?, ?\n"
|
: "Position: ?, ?, ?\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ namespace dusk {
|
|||||||
|
|
||||||
ImGuiStringViewText(
|
ImGuiStringViewText(
|
||||||
player != nullptr
|
player != nullptr
|
||||||
? fmt::format("Speed: {0}\n", player->speedF)
|
? fmt::format("Speed: {: .4f}\n", player->speedF)
|
||||||
: "Speed: ?\n"
|
: "Speed: ?\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@ namespace dusk {
|
|||||||
ImGui::Text("Epona");
|
ImGui::Text("Epona");
|
||||||
ImGuiStringViewText(
|
ImGuiStringViewText(
|
||||||
horse != nullptr
|
horse != nullptr
|
||||||
? fmt::format("Position: {: .2f}, {: .2f}, {: .2f}\n", horse->current.pos.x, horse->current.pos.y, horse->current.pos.z)
|
? fmt::format("Position: {: .4f}, {: .4f}, {: .4f}\n", horse->current.pos.x, horse->current.pos.y, horse->current.pos.z)
|
||||||
: "Position: ?, ?, ?\n"
|
: "Position: ?, ?, ?\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -242,7 +242,7 @@ namespace dusk {
|
|||||||
|
|
||||||
ImGuiStringViewText(
|
ImGuiStringViewText(
|
||||||
horse != nullptr
|
horse != nullptr
|
||||||
? fmt::format("Speed: {0}\n", horse->speedF)
|
? fmt::format("Speed: {: .4f}\n", horse->speedF)
|
||||||
: "Speed: ?\n"
|
: "Speed: ?\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,17 @@ static std::string ShowIsoInvalidError(const iso::ValidationError code) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string_view card_type_name(CARDFileType type) {
|
||||||
|
switch (type) {
|
||||||
|
case CARD_GCIFOLDER:
|
||||||
|
return "GCI Folder"sv;
|
||||||
|
case CARD_RAWIMAGE:
|
||||||
|
return "Card Image"sv;
|
||||||
|
default:
|
||||||
|
return ""sv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void fileDialogCallback(void* userdata, const char* path, const char* error) {
|
void fileDialogCallback(void* userdata, const char* path, const char* error) {
|
||||||
auto* self = static_cast<ImGuiPreLaunchWindow*>(userdata);
|
auto* self = static_cast<ImGuiPreLaunchWindow*>(userdata);
|
||||||
if (error != nullptr) {
|
if (error != nullptr) {
|
||||||
@@ -216,6 +227,23 @@ void ImGuiPreLaunchWindow::drawOptions() {
|
|||||||
if (configuredBackendId != m_initialGraphicsBackend) {
|
if (configuredBackendId != m_initialGraphicsBackend) {
|
||||||
ImGui::TextDisabled("Restart Required");
|
ImGui::TextDisabled("Restart Required");
|
||||||
}
|
}
|
||||||
|
auto curFileType = (CARDFileType)getSettings().backend.cardFileType.getValue();
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("Save File Type", card_type_name(curFileType).data())) {
|
||||||
|
|
||||||
|
if (ImGui::Selectable("GCI Folder", curFileType == CARD_GCIFOLDER)) {
|
||||||
|
getSettings().backend.cardFileType.setValue(CARD_GCIFOLDER);
|
||||||
|
config::Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::Selectable("Card Image", curFileType == CARD_RAWIMAGE)) {
|
||||||
|
getSettings().backend.cardFileType.setValue(CARD_RAWIMAGE);
|
||||||
|
config::Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "d/d_item_data.h"
|
#include "d/d_item_data.h"
|
||||||
#include "d/d_meter2_info.h"
|
#include "d/d_meter2_info.h"
|
||||||
#include "d/d_save.h"
|
#include "d/d_save.h"
|
||||||
|
#include "d/actor/d_a_player.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -579,20 +580,21 @@ namespace dusk {
|
|||||||
|
|
||||||
|
|
||||||
if (ImGui::BeginCombo("Clothes", itemMap.find(statusA.mSelectEquip[0])->second.m_name.c_str())) {
|
if (ImGui::BeginCombo("Clothes", itemMap.find(statusA.mSelectEquip[0])->second.m_name.c_str())) {
|
||||||
if (ImGui::Selectable("None")) {
|
|
||||||
statusA.mSelectEquip[0] = dItemNo_NONE_e;
|
|
||||||
}
|
|
||||||
if (ImGui::Selectable("Ordon Clothes")) {
|
if (ImGui::Selectable("Ordon Clothes")) {
|
||||||
statusA.mSelectEquip[0] = dItemNo_WEAR_CASUAL_e;
|
dMeter2Info_setCloth(dItemNo_WEAR_CASUAL_e, false);
|
||||||
|
daPy_getPlayerActorClass()->setClothesChange(0);
|
||||||
}
|
}
|
||||||
if (ImGui::Selectable("Hero's Clothes")) {
|
if (ImGui::Selectable("Hero's Clothes")) {
|
||||||
statusA.mSelectEquip[0] = dItemNo_WEAR_KOKIRI_e;
|
dMeter2Info_setCloth(dItemNo_WEAR_KOKIRI_e, false);
|
||||||
|
daPy_getPlayerActorClass()->setClothesChange(0);
|
||||||
}
|
}
|
||||||
if (ImGui::Selectable("Zora Armor")) {
|
if (ImGui::Selectable("Zora Armor")) {
|
||||||
statusA.mSelectEquip[0] = dItemNo_WEAR_ZORA_e;
|
dMeter2Info_setCloth(dItemNo_WEAR_ZORA_e, false);
|
||||||
|
daPy_getPlayerActorClass()->setClothesChange(0);
|
||||||
}
|
}
|
||||||
if (ImGui::Selectable("Magic Armor")) {
|
if (ImGui::Selectable("Magic Armor")) {
|
||||||
statusA.mSelectEquip[0] = dItemNo_ARMOR_e;
|
dMeter2Info_setCloth(dItemNo_ARMOR_e, false);
|
||||||
|
daPy_getPlayerActorClass()->setClothesChange(0);
|
||||||
}
|
}
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
@@ -1489,11 +1491,11 @@ namespace dusk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text(e.flagName.c_str());
|
ImGuiStringViewText(e.flagName);
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text(e.location.c_str());
|
ImGuiStringViewText(e.location);
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text(e.description.c_str());
|
ImGuiStringViewText(e.description);
|
||||||
}
|
}
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,24 @@
|
|||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
#include "absl/strings/escaping.h"
|
#include "absl/strings/escaping.h"
|
||||||
|
#include "nlohmann/json.hpp"
|
||||||
|
|
||||||
#include "d/d_com_inf_game.h"
|
#include "d/d_com_inf_game.h"
|
||||||
#include "dusk/main.h"
|
#include "dusk/main.h"
|
||||||
|
#include "dusk/io.hpp"
|
||||||
|
#include "dusk/logging.h"
|
||||||
|
#include "dusk/settings.h"
|
||||||
|
#include "f_op/f_op_overlap_mng.h"
|
||||||
|
#include "../file_select.hpp"
|
||||||
|
#include "aurora/lib/window.hpp"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
#include <zstd.h>
|
#include <zstd.h>
|
||||||
|
|
||||||
namespace dusk {
|
namespace dusk {
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct StateSharePacket {
|
struct StateSharePacket {
|
||||||
char stageName[8];
|
char stageName[8];
|
||||||
@@ -23,9 +33,65 @@ struct StateSharePacket {
|
|||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
static constexpr size_t PACKET_TOTAL = sizeof(StateSharePacket) + sizeof(dSv_info_c);
|
static constexpr size_t PACKET_TOTAL = sizeof(StateSharePacket) + sizeof(dSv_info_c);
|
||||||
|
static constexpr size_t PACKET_SAVE_ONLY = sizeof(StateSharePacket) + sizeof(dSv_save_c);
|
||||||
|
static constexpr auto STATES_FILENAME = "states.json";
|
||||||
|
|
||||||
void ImGuiStateShare::copyState() {
|
static bool ValidateEncodedState(const std::string&);
|
||||||
|
|
||||||
|
void ImGuiStateShare::onMergeFileSelected(void* userdata, const char* path, const char* /*error*/) {
|
||||||
|
auto* self = static_cast<ImGuiStateShare*>(userdata);
|
||||||
|
if (path != nullptr) {
|
||||||
|
self->m_pendingMergePath = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static std::string GetStatesFilePath() {
|
||||||
|
return (dusk::ConfigPath / STATES_FILENAME).string();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiStateShare::loadStatesFile() {
|
||||||
|
m_loaded = true;
|
||||||
|
const std::filesystem::path filePath = dusk::ConfigPath / STATES_FILENAME;
|
||||||
|
if (!std::filesystem::exists(filePath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const std::string pathStr = filePath.string();
|
||||||
|
auto data = io::FileStream::ReadAllBytes(pathStr.c_str());
|
||||||
|
auto j = json::parse(data);
|
||||||
|
if (!j.is_array()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const auto& entry : j) {
|
||||||
|
if (!entry.contains("name") || !entry.contains("data")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SavedStateEntry s;
|
||||||
|
s.name = entry["name"].get<std::string>();
|
||||||
|
s.encoded = entry["data"].get<std::string>();
|
||||||
|
m_states.push_back(std::move(s));
|
||||||
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
m_statusMsg = fmt::format("Failed to load states: {}", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiStateShare::saveStatesFile() {
|
||||||
|
json j = json::array();
|
||||||
|
for (const auto& s : m_states) {
|
||||||
|
j.push_back(json{{"name", s.name}, {"data", s.encoded}});
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
io::FileStream::WriteAllText(GetStatesFilePath().c_str(), j.dump(2));
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
m_statusMsg = fmt::format("Failed to save states: {}", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ImGuiStateShare::encodeCurrentState() {
|
||||||
StateSharePacket pkt = {};
|
StateSharePacket pkt = {};
|
||||||
strncpy(pkt.stageName, dComIfGp_getStartStageName(), 7);
|
strncpy(pkt.stageName, dComIfGp_getStartStageName(), 7);
|
||||||
pkt.roomNo = dComIfGp_getStartStageRoomNo();
|
pkt.roomNo = dComIfGp_getStartStageRoomNo();
|
||||||
@@ -40,26 +106,25 @@ void ImGuiStateShare::copyState() {
|
|||||||
std::string compressed(bound, '\0');
|
std::string compressed(bound, '\0');
|
||||||
compressed.resize(ZSTD_compress(compressed.data(), bound, raw.data(), raw.size(), 1));
|
compressed.resize(ZSTD_compress(compressed.data(), bound, raw.data(), raw.size(), 1));
|
||||||
|
|
||||||
std::string encoded = absl::Base64Escape(compressed);
|
return absl::Base64Escape(compressed);
|
||||||
ImGui::SetClipboardText(encoded.c_str());
|
|
||||||
m_statusMsg = "Copied to clipboard.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGuiStateShare::pasteState() {
|
bool ImGuiStateShare::applyEncodedState(const std::string& encoded, const std::string& name) {
|
||||||
const char* clip = ImGui::GetClipboardText();
|
|
||||||
if (!clip || clip[0] == '\0') {
|
|
||||||
m_statusMsg = "Clipboard is empty.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string decoded;
|
std::string decoded;
|
||||||
if (!absl::Base64Unescape(clip, &decoded)) {
|
if (!absl::Base64Unescape(encoded, &decoded)) {
|
||||||
m_statusMsg = "Invalid base64.";
|
m_statusMsg = "Invalid base64.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long dSize = ZSTD_getFrameContentSize(decoded.data(), decoded.size());
|
unsigned long long dSize = ZSTD_getFrameContentSize(decoded.data(), decoded.size());
|
||||||
if (dSize == ZSTD_CONTENTSIZE_ERROR || dSize == ZSTD_CONTENTSIZE_UNKNOWN || dSize < PACKET_TOTAL) {
|
if (dSize == ZSTD_CONTENTSIZE_ERROR || dSize == ZSTD_CONTENTSIZE_UNKNOWN) {
|
||||||
|
m_statusMsg = "Not a valid state string.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool isFull = (dSize == PACKET_TOTAL);
|
||||||
|
const bool isPartial = (dSize == PACKET_SAVE_ONLY);
|
||||||
|
if (!isFull && !isPartial) {
|
||||||
m_statusMsg = "Not a valid state string.";
|
m_statusMsg = "Not a valid state string.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -75,45 +140,272 @@ bool ImGuiStateShare::pasteState() {
|
|||||||
memcpy(&pkt, raw.data(), sizeof(pkt));
|
memcpy(&pkt, raw.data(), sizeof(pkt));
|
||||||
pkt.stageName[7] = '\0';
|
pkt.stageName[7] = '\0';
|
||||||
|
|
||||||
memcpy(&g_dComIfG_gameInfo.info, raw.data() + sizeof(pkt), sizeof(dSv_info_c));
|
if (isFull) {
|
||||||
|
memcpy(&g_dComIfG_gameInfo.info, raw.data() + sizeof(pkt), sizeof(dSv_info_c));
|
||||||
|
m_pendingInfo = g_dComIfG_gameInfo.info;
|
||||||
|
m_pendingSavedata.reset();
|
||||||
|
} else {
|
||||||
|
memcpy(&g_dComIfG_gameInfo.info.mSavedata, raw.data() + sizeof(pkt), sizeof(dSv_save_c));
|
||||||
|
m_pendingSavedata = g_dComIfG_gameInfo.info.mSavedata;
|
||||||
|
m_pendingInfo.reset();
|
||||||
|
}
|
||||||
|
|
||||||
s16 spawnPoint = pkt.startPoint == -4 ? -1 : pkt.startPoint;
|
s16 spawnPoint = pkt.startPoint == -4 ? -1 : pkt.startPoint;
|
||||||
|
|
||||||
if (spawnPoint == -1) {
|
if (spawnPoint == -1) {
|
||||||
dComIfGs_setRestartRoomParam(pkt.roomNo & 0x3F);
|
dComIfGs_setRestartRoomParam(pkt.roomNo & 0x3F);
|
||||||
}
|
}
|
||||||
|
|
||||||
dComIfGp_setNextStage(pkt.stageName, spawnPoint, pkt.roomNo, pkt.layer);
|
dusk::getTransientSettings().stateShareLoadActive = true;
|
||||||
m_pendingInfo = g_dComIfG_gameInfo.info;
|
m_stateSharePeekSeen = false;
|
||||||
|
dComIfGp_setNextStage(pkt.stageName, spawnPoint, pkt.roomNo, pkt.layer, 0.0f, 0, 1, 0, 0, 1, 3);
|
||||||
|
|
||||||
m_statusMsg = fmt::format("Warping to {} room {} layer {}.", pkt.stageName, (int)pkt.roomNo, (int)pkt.layer);
|
if (name.empty()) {
|
||||||
|
m_statusMsg = fmt::format("{} room {} layer {}.", pkt.stageName, (int)pkt.roomNo, (int)pkt.layer);
|
||||||
|
} else {
|
||||||
|
m_statusMsg = fmt::format("{}: {} room {} layer {}.", name, pkt.stageName, (int)pkt.roomNo, (int)pkt.layer);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiStateShare::tickPendingApply() {
|
void ImGuiStateShare::tickPendingApply() {
|
||||||
if (!m_pendingInfo.has_value() || dComIfGp_isEnableNextStage())
|
if (!m_pendingInfo.has_value() && !m_pendingSavedata.has_value()) {
|
||||||
return;
|
return;
|
||||||
g_dComIfG_gameInfo.info = *m_pendingInfo;
|
}
|
||||||
m_pendingInfo.reset();
|
if (dComIfGp_isEnableNextStage()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_pendingInfo.has_value()) {
|
||||||
|
g_dComIfG_gameInfo.info = *m_pendingInfo;
|
||||||
|
m_pendingInfo.reset();
|
||||||
|
} else {
|
||||||
|
g_dComIfG_gameInfo.info.mSavedata = *m_pendingSavedata;
|
||||||
|
m_pendingSavedata.reset();
|
||||||
|
}
|
||||||
|
dComIfGp_offOxygenShowFlag();
|
||||||
|
dComIfGp_setMaxOxygen(600);
|
||||||
|
dComIfGp_setOxygen(600);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ValidateEncodedState(const std::string& encoded) {
|
||||||
|
std::string decoded;
|
||||||
|
if (!absl::Base64Unescape(encoded, &decoded)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsigned long long dSize = ZSTD_getFrameContentSize(decoded.data(), decoded.size());
|
||||||
|
return dSize == PACKET_TOTAL || dSize == PACKET_SAVE_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiStateShare::mergeFromFile(const std::string& path) {
|
||||||
|
try {
|
||||||
|
auto data = io::FileStream::ReadAllBytes(path.c_str());
|
||||||
|
auto j = json::parse(data);
|
||||||
|
if (!j.is_array()) {
|
||||||
|
m_statusMsg = "File does not contain a JSON array.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<std::string> existingNames;
|
||||||
|
for (const auto& s : m_states) {
|
||||||
|
existingNames.insert(s.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int added = 0;
|
||||||
|
int skipped = 0;
|
||||||
|
for (const auto& entry : j) {
|
||||||
|
if (!entry.contains("name") || !entry.contains("data")) {
|
||||||
|
++skipped;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const std::string name = entry["name"].get<std::string>();
|
||||||
|
const std::string encoded = entry["data"].get<std::string>();
|
||||||
|
if (!ValidateEncodedState(encoded)) {
|
||||||
|
++skipped;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (existingNames.count(name)) {
|
||||||
|
++skipped;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SavedStateEntry s;
|
||||||
|
s.name = name;
|
||||||
|
s.encoded = encoded;
|
||||||
|
existingNames.insert(s.name);
|
||||||
|
m_states.push_back(std::move(s));
|
||||||
|
++added;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (added > 0) {
|
||||||
|
saveStatesFile();
|
||||||
|
}
|
||||||
|
m_statusMsg = fmt::format("Merged: {} added, {} skipped.", added, skipped);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
m_statusMsg = fmt::format("Failed to load file: {}", e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiStateShare::draw(bool& open) {
|
void ImGuiStateShare::draw(bool& open) {
|
||||||
if (dusk::IsGameLaunched)
|
if (dusk::IsGameLaunched) {
|
||||||
tickPendingApply();
|
tickPendingApply();
|
||||||
|
if (dusk::getTransientSettings().stateShareLoadActive) {
|
||||||
|
if (fopOvlpM_IsPeek()) {
|
||||||
|
m_stateSharePeekSeen = true;
|
||||||
|
} else if (m_stateSharePeekSeen) {
|
||||||
|
dusk::getTransientSettings().stateShareLoadActive = false;
|
||||||
|
m_stateSharePeekSeen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!open)
|
if (!m_loaded) {
|
||||||
|
loadStatesFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_pendingMergePath.empty()) {
|
||||||
|
mergeFromFile(m_pendingMergePath);
|
||||||
|
m_pendingMergePath.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!open) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ImGui::Begin("State Share", &open, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) {
|
ImGui::SetNextWindowSizeConstraints(ImVec2(400, 0), ImVec2(FLT_MAX, FLT_MAX));
|
||||||
|
if (!ImGui::Begin("State Manager", &open, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) {
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dusk::IsGameLaunched) ImGui::BeginDisabled();
|
const bool gameRunning = dusk::IsGameLaunched;
|
||||||
if (ImGui::Button("Copy State")) copyState();
|
const bool loadInProgress = dusk::getTransientSettings().stateShareLoadActive;
|
||||||
|
|
||||||
|
const float rowH = ImGui::GetTextLineHeightWithSpacing();
|
||||||
|
const float listH = rowH * 8 + ImGui::GetStyle().FramePadding.y * 2;
|
||||||
|
ImGui::BeginChild("##states", ImVec2(0, listH), true);
|
||||||
|
|
||||||
|
if (m_states.empty()) {
|
||||||
|
ImGui::TextDisabled("No saved states. Save or import one below.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int toDelete = -1;
|
||||||
|
for (int i = 0; i < (int)m_states.size(); ++i) {
|
||||||
|
ImGui::PushID(i);
|
||||||
|
|
||||||
|
if (m_renamingIndex == i) {
|
||||||
|
ImGui::SetNextItemWidth(150);
|
||||||
|
bool done = ImGui::InputText("##rename", m_renameBuffer, sizeof(m_renameBuffer),
|
||||||
|
ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll);
|
||||||
|
if (done) {
|
||||||
|
if (m_renameBuffer[0] != '\0') {
|
||||||
|
m_states[i].name = m_renameBuffer;
|
||||||
|
}
|
||||||
|
m_renamingIndex = -1;
|
||||||
|
saveStatesFile();
|
||||||
|
} else if (ImGui::IsItemDeactivated()) {
|
||||||
|
m_renamingIndex = -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::Selectable(m_states[i].name.c_str(), false, ImGuiSelectableFlags_None, ImVec2(150, 0));
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("Double-click to rename");
|
||||||
|
if (ImGui::IsMouseDoubleClicked(0)) {
|
||||||
|
m_renamingIndex = i;
|
||||||
|
strncpy(m_renameBuffer, m_states[i].name.c_str(), sizeof(m_renameBuffer) - 1);
|
||||||
|
m_renameBuffer[sizeof(m_renameBuffer) - 1] = '\0';
|
||||||
|
ImGui::SetKeyboardFocusHere(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (!gameRunning || loadInProgress) { ImGui::BeginDisabled(); }
|
||||||
|
if (ImGui::Button("Load")) {
|
||||||
|
applyEncodedState(m_states[i].encoded, m_states[i].name);
|
||||||
|
}
|
||||||
|
if (!gameRunning || loadInProgress) { ImGui::EndDisabled(); }
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Copy")) {
|
||||||
|
ImGui::SetClipboardText(m_states[i].encoded.c_str());
|
||||||
|
m_statusMsg = fmt::format("'{}' copied to clipboard.", m_states[i].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Del")) {
|
||||||
|
toDelete = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toDelete >= 0) {
|
||||||
|
if (m_renamingIndex == toDelete) { m_renamingIndex = -1; }
|
||||||
|
m_states.erase(m_states.begin() + toDelete);
|
||||||
|
saveStatesFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
// Toolbar
|
||||||
|
if (!gameRunning) { ImGui::BeginDisabled(); }
|
||||||
|
if (ImGui::Button("Save")) {
|
||||||
|
SavedStateEntry entry;
|
||||||
|
entry.name = fmt::format("State {}", m_states.size() + 1);
|
||||||
|
entry.encoded = encodeCurrentState();
|
||||||
|
m_states.push_back(std::move(entry));
|
||||||
|
saveStatesFile();
|
||||||
|
m_statusMsg = fmt::format("Saved as '{}'.", m_states.back().name);
|
||||||
|
}
|
||||||
|
if (!gameRunning) { ImGui::EndDisabled(); }
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Import State")) pasteState();
|
if (ImGui::Button("Import Clipboard")) {
|
||||||
if (!dusk::IsGameLaunched) ImGui::EndDisabled();
|
const char* clip = ImGui::GetClipboardText();
|
||||||
|
if (!clip || clip[0] == '\0') {
|
||||||
|
m_statusMsg = "Clipboard is empty.";
|
||||||
|
} else {
|
||||||
|
std::string clipStr = clip;
|
||||||
|
if (!ValidateEncodedState(clipStr)) {
|
||||||
|
m_statusMsg = "Clipboard does not contain a valid state.";
|
||||||
|
} else {
|
||||||
|
SavedStateEntry entry;
|
||||||
|
entry.name = fmt::format("Imported {}", m_states.size() + 1);
|
||||||
|
entry.encoded = std::move(clipStr);
|
||||||
|
m_states.push_back(std::move(entry));
|
||||||
|
saveStatesFile();
|
||||||
|
m_statusMsg = fmt::format("Imported as '{}'.", m_states.back().name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Load Pack")) {
|
||||||
|
static constexpr SDL_DialogFileFilter filter = {"State pack", "json"};
|
||||||
|
ShowFileSelect(&onMergeFileSelected, this, aurora::window::get_sdl_window(), &filter, 1, nullptr, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_states.empty()) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Clear All")) {
|
||||||
|
ImGui::OpenPopup("##clearall");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginPopup("##clearall")) {
|
||||||
|
ImGui::Text("Delete all saved states?");
|
||||||
|
ImGui::Spacing();
|
||||||
|
if (ImGui::Button("Yes, clear all")) {
|
||||||
|
m_states.clear();
|
||||||
|
m_renamingIndex = -1;
|
||||||
|
saveStatesFile();
|
||||||
|
m_statusMsg = "All states cleared.";
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Cancel")) {
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_statusMsg.empty()) {
|
if (!m_statusMsg.empty()) {
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
@@ -125,8 +417,9 @@ void ImGuiStateShare::draw(bool& open) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiMenuTools::ShowStateShare() {
|
void ImGuiMenuTools::ShowStateShare() {
|
||||||
if (!ImGuiConsole::CheckMenuViewToggle(ImGuiKey_F8, m_showStateShare))
|
if (!ImGuiConsole::CheckMenuViewToggle(ImGuiKey_F8, m_showStateShare)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
m_stateShare.draw(m_showStateShare);
|
m_stateShare.draw(m_showStateShare);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,21 +4,39 @@
|
|||||||
#include "d/d_save.h"
|
#include "d/d_save.h"
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace dusk {
|
namespace dusk {
|
||||||
class ImGuiStateShare {
|
|
||||||
public:
|
|
||||||
void draw(bool& open);
|
|
||||||
|
|
||||||
private:
|
struct SavedStateEntry {
|
||||||
void copyState();
|
std::string name;
|
||||||
bool pasteState();
|
std::string encoded;
|
||||||
void tickPendingApply();
|
};
|
||||||
|
|
||||||
|
class ImGuiStateShare {
|
||||||
|
public:
|
||||||
|
void draw(bool& open);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string encodeCurrentState();
|
||||||
|
bool applyEncodedState(const std::string& encoded, const std::string& name = {});
|
||||||
|
void tickPendingApply();
|
||||||
|
void loadStatesFile();
|
||||||
|
void saveStatesFile();
|
||||||
|
void mergeFromFile(const std::string& path);
|
||||||
|
static void onMergeFileSelected(void* userdata, const char* path, const char* error);
|
||||||
|
|
||||||
|
std::vector<SavedStateEntry> m_states;
|
||||||
|
std::string m_statusMsg;
|
||||||
|
std::optional<dSv_info_c> m_pendingInfo;
|
||||||
|
std::optional<dSv_save_c> m_pendingSavedata;
|
||||||
|
int m_renamingIndex = -1;
|
||||||
|
char m_renameBuffer[128] = {};
|
||||||
|
bool m_loaded = false;
|
||||||
|
bool m_stateSharePeekSeen = false;
|
||||||
|
std::string m_pendingMergePath;
|
||||||
|
};
|
||||||
|
|
||||||
std::string m_statusMsg;
|
|
||||||
std::optional<dSv_info_c> m_pendingInfo;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -43,6 +43,7 @@ UserSettings g_userSettings = {
|
|||||||
.invertCameraXAxis {"game.invertCameraXAxis", false},
|
.invertCameraXAxis {"game.invertCameraXAxis", false},
|
||||||
.disableMainHUD {"game.disableMainHUD", false},
|
.disableMainHUD {"game.disableMainHUD", false},
|
||||||
.pauseOnFocusLost {"game.pauseOnFocusLost", false},
|
.pauseOnFocusLost {"game.pauseOnFocusLost", false},
|
||||||
|
.enableLinkDollRotation = {"game.enableLinkDollRotation", false },
|
||||||
|
|
||||||
// Graphics
|
// Graphics
|
||||||
.bloomMode {"game.bloomMode", BloomMode::Classic},
|
.bloomMode {"game.bloomMode", BloomMode::Classic},
|
||||||
@@ -51,6 +52,7 @@ UserSettings g_userSettings = {
|
|||||||
.enableFrameInterpolation = {"game.enableFrameInterpolation", false},
|
.enableFrameInterpolation = {"game.enableFrameInterpolation", false},
|
||||||
.internalResolutionScale {"game.internalResolutionScale", 0},
|
.internalResolutionScale {"game.internalResolutionScale", 0},
|
||||||
.shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1},
|
.shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1},
|
||||||
|
.enableDepthOfField {"game.enableDepthOfField", true},
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
.noLowHpSound {"game.noLowHpSound", false},
|
.noLowHpSound {"game.noLowHpSound", false},
|
||||||
@@ -74,6 +76,7 @@ UserSettings g_userSettings = {
|
|||||||
.infiniteOil{"game.infiniteOil", false},
|
.infiniteOil{"game.infiniteOil", false},
|
||||||
.infiniteOxygen{"game.infiniteOxygen", false},
|
.infiniteOxygen{"game.infiniteOxygen", false},
|
||||||
.infiniteRupees{"game.infiniteRupees", false},
|
.infiniteRupees{"game.infiniteRupees", false},
|
||||||
|
.enableIndefiniteItemDrops {"game.enableIndefiniteItemDrops", false},
|
||||||
.moonJump{"game.moonJump", false},
|
.moonJump{"game.moonJump", false},
|
||||||
.superClawshot{"game.superClawshot", false},
|
.superClawshot{"game.superClawshot", false},
|
||||||
.alwaysGreatspin{"game.alwaysGreatspin", false},
|
.alwaysGreatspin{"game.alwaysGreatspin", false},
|
||||||
@@ -96,7 +99,8 @@ UserSettings g_userSettings = {
|
|||||||
.showPipelineCompilation {"backend.showPipelineCompilation", false},
|
.showPipelineCompilation {"backend.showPipelineCompilation", false},
|
||||||
.wasPresetChosen {"backend.wasPresetChosen", false},
|
.wasPresetChosen {"backend.wasPresetChosen", false},
|
||||||
.enableCrashReporting {"backend.enableCrashReporting", true},
|
.enableCrashReporting {"backend.enableCrashReporting", true},
|
||||||
.duskMenuOpen {"backend.duskMenuOpen", false}
|
.duskMenuOpen {"backend.duskMenuOpen", false},
|
||||||
|
.cardFileType {"backend.cardFileType", static_cast<int>(CARD_GCIFOLDER)}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -143,10 +147,12 @@ void registerSettings() {
|
|||||||
Register(g_userSettings.game.disableWaterRefraction);
|
Register(g_userSettings.game.disableWaterRefraction);
|
||||||
Register(g_userSettings.game.internalResolutionScale);
|
Register(g_userSettings.game.internalResolutionScale);
|
||||||
Register(g_userSettings.game.shadowResolutionMultiplier);
|
Register(g_userSettings.game.shadowResolutionMultiplier);
|
||||||
|
Register(g_userSettings.game.enableDepthOfField);
|
||||||
Register(g_userSettings.game.enableFastIronBoots);
|
Register(g_userSettings.game.enableFastIronBoots);
|
||||||
Register(g_userSettings.game.canTransformAnywhere);
|
Register(g_userSettings.game.canTransformAnywhere);
|
||||||
Register(g_userSettings.game.freeMagicArmor);
|
Register(g_userSettings.game.freeMagicArmor);
|
||||||
Register(g_userSettings.game.restoreWiiGlitches);
|
Register(g_userSettings.game.restoreWiiGlitches);
|
||||||
|
Register(g_userSettings.game.enableLinkDollRotation);
|
||||||
Register(g_userSettings.game.noMissClimbing);
|
Register(g_userSettings.game.noMissClimbing);
|
||||||
Register(g_userSettings.game.noLowHpSound);
|
Register(g_userSettings.game.noLowHpSound);
|
||||||
Register(g_userSettings.game.midnasLamentNonStop);
|
Register(g_userSettings.game.midnasLamentNonStop);
|
||||||
@@ -158,6 +164,7 @@ void registerSettings() {
|
|||||||
Register(g_userSettings.game.infiniteOil);
|
Register(g_userSettings.game.infiniteOil);
|
||||||
Register(g_userSettings.game.infiniteOxygen);
|
Register(g_userSettings.game.infiniteOxygen);
|
||||||
Register(g_userSettings.game.infiniteRupees);
|
Register(g_userSettings.game.infiniteRupees);
|
||||||
|
Register(g_userSettings.game.enableIndefiniteItemDrops);
|
||||||
Register(g_userSettings.game.moonJump);
|
Register(g_userSettings.game.moonJump);
|
||||||
Register(g_userSettings.game.superClawshot);
|
Register(g_userSettings.game.superClawshot);
|
||||||
Register(g_userSettings.game.alwaysGreatspin);
|
Register(g_userSettings.game.alwaysGreatspin);
|
||||||
@@ -179,6 +186,7 @@ void registerSettings() {
|
|||||||
Register(g_userSettings.backend.wasPresetChosen);
|
Register(g_userSettings.backend.wasPresetChosen);
|
||||||
Register(g_userSettings.backend.enableCrashReporting);
|
Register(g_userSettings.backend.enableCrashReporting);
|
||||||
Register(g_userSettings.backend.duskMenuOpen);
|
Register(g_userSettings.backend.duskMenuOpen);
|
||||||
|
Register(g_userSettings.backend.cardFileType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transient settings
|
// Transient settings
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "m_Do/m_Do_graphic.h"
|
#include "m_Do/m_Do_graphic.h"
|
||||||
#include "m_Do/m_Do_main.h"
|
#include "m_Do/m_Do_main.h"
|
||||||
#include "tracy/Tracy.hpp"
|
#include "tracy/Tracy.hpp"
|
||||||
|
#include <dusk/gamepad_color.h>
|
||||||
|
|
||||||
fapGm_HIO_c::fapGm_HIO_c() {
|
fapGm_HIO_c::fapGm_HIO_c() {
|
||||||
mUsingHostIO = true;
|
mUsingHostIO = true;
|
||||||
@@ -734,6 +735,8 @@ static void fapGm_AfterRecord() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void duskExecute() {
|
static void duskExecute() {
|
||||||
|
handleGamepadColor();
|
||||||
|
|
||||||
if (mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getTrigX(PAD_1)) {
|
if (mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getTrigX(PAD_1)) {
|
||||||
if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) {
|
if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) {
|
||||||
dynamic_cast<daAlink_c*>(link)->handleWolfHowl();
|
dynamic_cast<daAlink_c*>(link)->handleWolfHowl();
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ static OSThread MemCardThread;
|
|||||||
|
|
||||||
void mDoMemCd_Ctrl_c::ThdInit() {
|
void mDoMemCd_Ctrl_c::ThdInit() {
|
||||||
#if !PLATFORM_SHIELD
|
#if !PLATFORM_SHIELD
|
||||||
|
CARDSetLoadType((CARDFileType)dusk::getSettings().backend.cardFileType.getValue());
|
||||||
|
|
||||||
CARDInit(DUSK_GAME_NAME, DUSK_GAME_VERSION);
|
CARDInit(DUSK_GAME_NAME, DUSK_GAME_VERSION);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -351,8 +351,13 @@ void mDoExt_modelUpdateDL(J3DModel* i_model) {
|
|||||||
|
|
||||||
void mDoExt_modelEntryDL(J3DModel* i_model) {
|
void mDoExt_modelEntryDL(J3DModel* i_model) {
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
if (!dusk::frame_interp::is_sim_frame())
|
if (!dusk::frame_interp::is_sim_frame()) {
|
||||||
|
// FRAME INTERP NOTE: This fixes issue #355 where some lights would flicker.
|
||||||
|
// This is likely better solved by updating J3DMaterial::needsInterpCallBack,
|
||||||
|
// but it's unclear what exactly needs to be added.
|
||||||
|
i_model->diff();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
modelMtxErrorCheck(i_model);
|
modelMtxErrorCheck(i_model);
|
||||||
|
|||||||
@@ -1029,15 +1029,8 @@ static void drawDepth2(view_class* param_0, view_port_class* param_1, int param_
|
|||||||
GX_FALSE, 0);
|
GX_FALSE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
// use full size for pc for higher quality background elements
|
|
||||||
u16 halfWidth = width;
|
|
||||||
u16 halfHeight = height;
|
|
||||||
#else
|
|
||||||
u16 halfWidth = width >> 1;
|
u16 halfWidth = width >> 1;
|
||||||
u16 halfHeight = height >> 1;
|
u16 halfHeight = height >> 1;
|
||||||
#endif
|
|
||||||
|
|
||||||
GXRenderModeObj* sp24 = JUTGetVideoManager()->getRenderMode();
|
GXRenderModeObj* sp24 = JUTGetVideoManager()->getRenderMode();
|
||||||
GXSetCopyFilter(GX_FALSE, NULL, GX_TRUE, sp24->vfilter);
|
GXSetCopyFilter(GX_FALSE, NULL, GX_TRUE, sp24->vfilter);
|
||||||
GXSetTexCopySrc(x_orig, y_orig_pos, width, height);
|
GXSetTexCopySrc(x_orig, y_orig_pos, width, height);
|
||||||
@@ -1155,6 +1148,9 @@ static void drawDepth2(view_class* param_0, view_port_class* param_1, int param_
|
|||||||
GXSetProjection(ortho, GX_ORTHOGRAPHIC);
|
GXSetProjection(ortho, GX_ORTHOGRAPHIC);
|
||||||
GXSetCurrentMtx(0);
|
GXSetCurrentMtx(0);
|
||||||
|
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
if (dusk::getSettings().game.enableDepthOfField)
|
||||||
|
#endif
|
||||||
if (l_tevColor0.a > -255 && sp8 == 1) {
|
if (l_tevColor0.a > -255 && sp8 == 1) {
|
||||||
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
|
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
|
||||||
GXPosition3s16(x_orig, y_orig_pos, -5);
|
GXPosition3s16(x_orig, y_orig_pos, -5);
|
||||||
|
|||||||
+18
-15
@@ -242,8 +242,6 @@ void main01(void) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dusk::game_clock::MainLoopPacer pacing = dusk::game_clock::advance_main_loop();
|
|
||||||
|
|
||||||
VIWaitForRetrace();
|
VIWaitForRetrace();
|
||||||
|
|
||||||
dusk::lastFrameAuroraStats = *aurora_get_stats();
|
dusk::lastFrameAuroraStats = *aurora_get_stats();
|
||||||
@@ -254,28 +252,33 @@ void main01(void) {
|
|||||||
|
|
||||||
mDoGph_gInf_c::updateRenderSize();
|
mDoGph_gInf_c::updateRenderSize();
|
||||||
|
|
||||||
dusk::frame_interp::begin_frame(pacing.is_interpolating, pacing.do_sim_tick, pacing.interpolation_step);
|
const auto pacing = dusk::game_clock::advance_main_loop();
|
||||||
if (pacing.is_interpolating) {
|
if (pacing.is_interpolating) {
|
||||||
if (pacing.do_sim_tick) {
|
if (pacing.sim_ticks_to_run > 0) {
|
||||||
|
dusk::frame_interp::begin_frame(true, true, 0.0f);
|
||||||
dusk::frame_interp::set_ui_tick_pending(true);
|
dusk::frame_interp::set_ui_tick_pending(true);
|
||||||
mDoCPd_c::read();
|
for (int sim_tick = 0; sim_tick < pacing.sim_ticks_to_run; ++sim_tick) {
|
||||||
DuskDebugPad();
|
dusk::frame_interp::begin_sim_tick();
|
||||||
dusk::gyro::read(pacing.sim_pace);
|
mDoCPd_c::read();
|
||||||
fapGm_Execute();
|
DuskDebugPad();
|
||||||
mDoAud_Execute();
|
dusk::gyro::read(pacing.sim_pace);
|
||||||
dusk::game_clock::reset_accumulator();
|
fapGm_Execute();
|
||||||
|
mDoAud_Execute();
|
||||||
|
dusk::game_clock::commit_sim_tick();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dusk::frame_interp::begin_frame(true, false,
|
||||||
|
dusk::game_clock::sample_interpolation_step());
|
||||||
dusk::frame_interp::interpolate();
|
dusk::frame_interp::interpolate();
|
||||||
dusk::frame_interp::begin_presentation_camera();
|
dusk::frame_interp::begin_presentation_camera();
|
||||||
if (!pacing.do_sim_tick) {
|
// run draw functions for anything specially marked to handle interp
|
||||||
// run draw functions for anything specially marked to handle interp on non-sim
|
fpcM_DrawIterater((fpcM_DrawIteraterFunc)fpcM_Draw);
|
||||||
// ticks
|
|
||||||
fpcM_DrawIterater((fpcM_DrawIteraterFunc)fpcM_Draw);
|
|
||||||
}
|
|
||||||
cAPIGph_Painter();
|
cAPIGph_Painter();
|
||||||
dusk::frame_interp::end_presentation_camera();
|
dusk::frame_interp::end_presentation_camera();
|
||||||
dusk::frame_interp::set_ui_tick_pending(false);
|
dusk::frame_interp::set_ui_tick_pending(false);
|
||||||
} else {
|
} else {
|
||||||
|
dusk::frame_interp::begin_frame(false, true, 0.0f);
|
||||||
dusk::frame_interp::set_ui_tick_pending(true);
|
dusk::frame_interp::set_ui_tick_pending(true);
|
||||||
|
|
||||||
// Game Inputs
|
// Game Inputs
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
"""
|
||||||
|
Convert a folder of TPGZ saves to a states.json
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python saves_to_states_json.py path/to/saves [prefix]
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
pip install zstandard
|
||||||
|
"""
|
||||||
|
|
||||||
|
import base64
|
||||||
|
import json
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
import zstandard
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
SAVE_C_SIZE = 0x958
|
||||||
|
|
||||||
|
PACKET_FORMAT = "<8sbbh"
|
||||||
|
|
||||||
|
RETURN_PLACE_OFF = 0x058
|
||||||
|
NAME_OFF = RETURN_PLACE_OFF + 0x00
|
||||||
|
ROOM_OFF = RETURN_PLACE_OFF + 0x09
|
||||||
|
SPAWN_POINT_OFF = RETURN_PLACE_OFF + 0x08
|
||||||
|
|
||||||
|
folder = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(__file__).parent
|
||||||
|
out_path = folder / "states.json"
|
||||||
|
|
||||||
|
if len(sys.argv) > 2:
|
||||||
|
prefix = sys.argv[2]
|
||||||
|
else:
|
||||||
|
prefix = None
|
||||||
|
|
||||||
|
cctx = zstandard.ZstdCompressor(level=1)
|
||||||
|
states = []
|
||||||
|
|
||||||
|
for bin_path in sorted(folder.glob("*.bin")):
|
||||||
|
raw = bin_path.read_bytes()
|
||||||
|
save_c = raw[:SAVE_C_SIZE]
|
||||||
|
if len(save_c) < SAVE_C_SIZE:
|
||||||
|
print(f" skip {bin_path.name}: too small ({len(save_c)} bytes)")
|
||||||
|
continue
|
||||||
|
|
||||||
|
stage_name = save_c[NAME_OFF:NAME_OFF + 8]
|
||||||
|
room_no = struct.unpack_from("b", save_c, ROOM_OFF)[0]
|
||||||
|
spawn_point = struct.unpack_from("B", save_c, SPAWN_POINT_OFF)[0]
|
||||||
|
|
||||||
|
pkt = struct.pack(PACKET_FORMAT, stage_name, room_no, -1, spawn_point)
|
||||||
|
payload = pkt + save_c
|
||||||
|
encoded = base64.b64encode(cctx.compress(payload)).decode("ascii")
|
||||||
|
|
||||||
|
stage_str = stage_name.rstrip(b"\x00").decode("ascii", errors="replace")
|
||||||
|
print(f" {bin_path.stem:30s} stage={stage_str!r} room={room_no} point={spawn_point}")
|
||||||
|
states.append({"name": f"({prefix}) {bin_path.stem}" if prefix else bin_path.stem, "data": encoded})
|
||||||
|
|
||||||
|
out_path.write_text(json.dumps(states, indent=2))
|
||||||
|
print(f"\nWrote {len(states)} states to {out_path}")
|
||||||
Reference in New Issue
Block a user