Compare commits

..

1 Commits

Author SHA1 Message Date
SuperDude88 92d11863f6 Crash Reporting Option Portability
- Makes the crash reporting preference get saved with the other config files
2026-05-31 19:00:58 -04:00
209 changed files with 3603 additions and 14290 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install ninja-build clang lld mold openssl libcurl4-openssl-dev \
sudo apt-get -y install ninja-build clang lld openssl libcurl4-openssl-dev \
zlib1g-dev libglu1-mesa-dev libdbus-1-dev libvulkan-dev libxi-dev libxrandr-dev libasound2-dev \
libpulse-dev libudev-dev libpng-dev libncurses5-dev libx11-xcb-dev libfreetype-dev \
libxinerama-dev libxcursor-dev python3-markupsafe libgtk-3-dev libssl-dev \
-2
View File
@@ -53,5 +53,3 @@ compile_commands.json
pipeline_cache.bin
extract
*.dusk
+2 -2
View File
@@ -6,12 +6,12 @@
"type": "cppvsdbg",
"request": "launch",
"program": "${command:cmake.launchTargetPath}",
"args": ["-l", "1", "--dvd", "${workspaceRoot}/orig/GZ2E01/GZ2E01.iso", "--console", "--mods", "${workspaceRoot}/mods"],
"args": ["-l", "1", "--dvd", "${workspaceRoot}/orig/GZ2E01/GZ2E01.iso", "--console"],
"MIMode": "gdb",
"miDebuggerPath": "gdb",
"symbolSearchPath": "${command:cmake.launchTargetPath}",
"console": "integratedTerminal",
"cwd":"${workspaceRoot}",
"cwd":"${workspaceRoot}"
}
]
}
+33 -200
View File
@@ -21,26 +21,26 @@ else ()
find_package(Git)
if (GIT_FOUND)
# make sure version information gets re-run when the current Git HEAD changes
execute_process(WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --git-path HEAD
execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --git-path HEAD
OUTPUT_VARIABLE dusk_git_head_filename
OUTPUT_STRIP_TRAILING_WHITESPACE)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${dusk_git_head_filename}")
execute_process(WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --symbolic-full-name HEAD
execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --symbolic-full-name HEAD
OUTPUT_VARIABLE dusk_git_head_symbolic
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND ${GIT_EXECUTABLE} rev-parse --git-path ${dusk_git_head_symbolic}
OUTPUT_VARIABLE dusk_git_head_symbolic_filename
OUTPUT_STRIP_TRAILING_WHITESPACE)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${dusk_git_head_symbolic_filename}")
# defines DUSK_WC_REVISION
execute_process(WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
OUTPUT_VARIABLE DUSK_WC_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE)
# defines DUSK_WC_DESCRIBE
execute_process(WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags --long --dirty --match "v*"
execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags --long --dirty --match "v*"
OUTPUT_VARIABLE DUSK_WC_DESCRIBE
OUTPUT_STRIP_TRAILING_WHITESPACE)
@@ -49,11 +49,11 @@ if (GIT_FOUND)
string(REGEX REPLACE "-0$" "" DUSK_WC_DESCRIBE "${DUSK_WC_DESCRIBE}")
# defines DUSK_WC_BRANCH
execute_process(WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
OUTPUT_VARIABLE DUSK_WC_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE)
# defines DUSK_WC_DATE
execute_process(WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} log -1 --format=%ad
execute_process(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} log -1 --format=%ad
OUTPUT_VARIABLE DUSK_WC_DATE
OUTPUT_STRIP_TRAILING_WHITESPACE)
else ()
@@ -126,33 +126,6 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "_cmake")
option(ENABLE_ASAN "Enable AddressSanitizer" OFF)
if (ENABLE_ASAN)
if (CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" AND
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/fsanitize=address>)
add_link_options(/fsanitize=address /INCREMENTAL:NO)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "ProgramDatabase")
foreach (_lang C CXX)
foreach (_rtc_flag /RTC1 /RTCc /RTCs /RTCu)
string(REPLACE "${_rtc_flag}" "" CMAKE_${_lang}_FLAGS_DEBUG "${CMAKE_${_lang}_FLAGS_DEBUG}")
endforeach ()
endforeach ()
elseif (CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "GNU" AND
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
add_compile_options(
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fsanitize=address>
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fno-omit-frame-pointer>
)
add_link_options(-fsanitize=address)
else ()
message(FATAL_ERROR "ENABLE_ASAN requires GNU-like or MSVC-like C/C++ compiler frontends")
endif ()
add_compile_definitions(NDEBUG_SANITIZER) # Avoids absl issue with SwissTable debug code
message(STATUS "dusklight: Enabled AddressSanitizer")
endif ()
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
set(DAWN_USE_WAYLAND ON CACHE BOOL "Enable support for Wayland surface" FORCE)
endif ()
@@ -164,19 +137,11 @@ target_compile_definitions(aurora_mtx PRIVATE MTX_USE_PS=1)
add_subdirectory(libs/freeverb)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DUSK_GFX_DEBUG_GROUPS_DEFAULT ON)
else ()
set(DUSK_GFX_DEBUG_GROUPS_DEFAULT OFF)
endif ()
option(DUSK_BUILD_WARNINGS "Enable compiler warnings (off by default)")
option(DUSK_SELECTED_OPT "If on, selected parts of the project will be compiled with optimizations on Debug, intending to make the game run at 30 FPS. Note for MSVC: you will need to remove '/RTC1' from your debug flags in CMake.")
option(DUSK_MOVIE_SUPPORT "If on, compile against libjpeg-turbo to enable THP file decoding" ON)
option(DUSK_ENABLE_UPDATE_CHECKER "Enable update checking support" ON)
option(DUSK_ENABLE_SENTRY_NATIVE "Enable sentry-native crash reporting support" OFF)
option(DUSK_PACKAGE_INSTALL "Install Dusklight with a Linux-native file structure" OFF)
option(DUSK_GFX_DEBUG_GROUPS "Report debug groups to the native graphics API" ${DUSK_GFX_DEBUG_GROUPS_DEFAULT})
set(DUSK_SENTRY_DSN "" CACHE STRING "Sentry DSN")
set(DUSK_SENTRY_ENVIRONMENT "development" CACHE STRING "Sentry environment")
@@ -211,7 +176,7 @@ if (DUSK_MOVIE_SUPPORT)
-DWITH_JAVA=OFF
)
if (CMAKE_TOOLCHAIN_FILE)
get_filename_component(_jpeg_toolchain_file "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
get_filename_component(_jpeg_toolchain_file "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE BASE_DIR "${CMAKE_SOURCE_DIR}")
list(APPEND _jpeg_cmake_args -DCMAKE_TOOLCHAIN_FILE=${_jpeg_toolchain_file})
endif ()
set(_jpeg_passthrough_vars
@@ -224,8 +189,6 @@ if (DUSK_MOVIE_SUPPORT)
CMAKE_MSVC_RUNTIME_LIBRARY
CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
CMAKE_OSX_ARCHITECTURES
CMAKE_OSX_DEPLOYMENT_TARGET
CMAKE_OSX_SYSROOT
DEPLOYMENT_TARGET
ENABLE_ARC
ENABLE_BITCODE
@@ -284,6 +247,7 @@ elseif (MSVC)
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/utf-8>)
endif ()
include(FetchContent)
# Declare all dependencies first so CMake can download them in parallel
@@ -291,43 +255,15 @@ message(STATUS "dusklight: Fetching cxxopts")
FetchContent_Declare(cxxopts
URL https://github.com/jarro2783/cxxopts/archive/refs/tags/v3.3.1.tar.gz
URL_HASH SHA256=3bfc70542c521d4b55a46429d808178916a579b28d048bd8c727ee76c39e2072
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
EXCLUDE_FROM_ALL
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)
message(STATUS "dusklight: Fetching nlohmann/json")
FetchContent_Declare(json
URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz
URL_HASH SHA256=42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
EXCLUDE_FROM_ALL
)
message(STATUS "dusk: Fetching miniz")
FetchContent_Declare(miniz
URL https://github.com/richgel999/miniz/releases/download/3.0.2/miniz-3.0.2.zip
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
EXCLUDE_FROM_ALL
)
message(STATUS "dusk: Fetching funchook")
# cmake/patch_funchook.cmake patches funchook's cmake/capstone.cmake.in to inject a
# PATCH_COMMAND into capstone's inner ExternalProject. That PATCH_COMMAND runs
# cmake/fix_capstone_policy.cmake after capstone is cloned, which removes the
# cmake_policy(SET CMP0048 OLD) line that CMake >= 3.27 rejects.
# This is incredibly scuffed and we should probably think of a better way to do this
set(CAPSTONE_FIX_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/fix_capstone_policy.cmake")
FetchContent_Declare(funchook
GIT_REPOSITORY https://github.com/kubo/funchook.git
GIT_TAG v1.1.3
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
PATCH_COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=<SOURCE_DIR> -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/patch_funchook.cmake
EXCLUDE_FROM_ALL
)
set(FUNCHOOK_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(FUNCHOOK_BUILD_SHARED OFF CACHE BOOL "" FORCE)
set(FUNCHOOK_INSTALL OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(cxxopts json miniz funchook)
FetchContent_MakeAvailable(cxxopts json)
if (DUSK_ENABLE_SENTRY_NATIVE)
message(STATUS "dusklight: Fetching sentry-native")
@@ -375,7 +311,7 @@ else ()
string(TOLOWER CMAKE_SYSTEM_NAME PLATFORM_NAME)
endif ()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
configure_file(${CMAKE_SOURCE_DIR}/version.h.in ${CMAKE_BINARY_DIR}/version.h)
include(files.cmake)
@@ -400,21 +336,15 @@ set(GAME_INCLUDE_DIRS
libs/JSystem/include
libs
extern/aurora/include/dolphin
extern/aurora/include
extern
${CMAKE_CURRENT_BINARY_DIR}
${miniz_SOURCE_DIR})
# Interface target for mods and sub-projects to inherit game headers/defines
add_library(dusklight_game_headers INTERFACE)
target_include_directories(dusklight_game_headers INTERFACE ${GAME_INCLUDE_DIRS})
target_compile_definitions(dusklight_game_headers INTERFACE TARGET_PC=1)
target_link_libraries(dusklight_game_headers INTERFACE TracyClient)
${CMAKE_BINARY_DIR})
find_package(Threads REQUIRED)
set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd
aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt funchook-static
Threads::Threads zstd::libzstd)
aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt
Threads::Threads)
list(APPEND GAME_LIBS libzstd_static)
if (DUSK_ENABLE_SENTRY_NATIVE)
list(APPEND GAME_LIBS sentry)
@@ -486,26 +416,6 @@ if(ANDROID)
list(APPEND GAME_COMPILE_DEFS TARGET_ANDROID=1)
endif ()
set(DUSK_ENABLE_CODE_MODS_DEFAULT OFF)
option(DUSK_ENABLE_CODE_MODS "Enable code mods" ${DUSK_ENABLE_CODE_MODS_DEFAULT})
if (DUSK_ENABLE_CODE_MODS)
if (NOT ANDROID AND NOT IOS AND NOT TVOS)
list(APPEND GAME_COMPILE_DEFS DUSK_CODE_MODS=1)
else ()
message(FATAL_ERROR "Code mods not supported on the target platform!")
endif ()
endif ()
if (DUSK_PACKAGE_INSTALL)
include(GNUInstallDirs)
list(APPEND GAME_COMPILE_DEFS DUSK_ASSET_DIR="${CMAKE_INSTALL_FULL_DATADIR}/dusklight/")
endif ()
if (DUSK_GFX_DEBUG_GROUPS)
list(APPEND GAME_COMPILE_DEFS DUSK_GFX_DEBUG_GROUPS=1)
target_compile_definitions(aurora_gx PRIVATE AURORA_GFX_DEBUG_GROUPS)
endif ()
# game_debug is for game code files that we know work when compiled with DEBUG=1
# Of course, if building a release build, this distinction is irrelevant
set(GAME_DEBUG_FILES
@@ -523,6 +433,7 @@ set_source_files_properties(
COMPILE_DEFINITIONS "$<$<CONFIG:Debug>:DEBUG=1>;$<$<CONFIG:Debug>:PARTIAL_DEBUG=1>"
)
# game_base is for all other game code files
set(GAME_BASE_FILES
${DOLZEL_FILES}
${Z2AUDIOLIB_FILES}
@@ -539,7 +450,6 @@ set_source_files_properties(
foreach(jsystem_lib IN LISTS JSYSTEM_LIBRARIES)
target_compile_definitions(${jsystem_lib} PRIVATE
${GAME_COMPILE_DEFS}
DUSK_BUILDING_GAME=1
$<$<CONFIG:Debug>:DEBUG=1>
$<$<CONFIG:Debug>:PARTIAL_DEBUG=1>
)
@@ -555,61 +465,21 @@ if (CMAKE_CXX_LINK_GROUP_USING_RESCAN_SUPPORTED OR CMAKE_LINK_GROUP_USING_RESCAN
set(JSYSTEM_LINK_LIBRARIES "$<LINK_GROUP:RESCAN,${JSYSTEM_LIBRARIES}>")
endif ()
set(DUSK_FILES src/dusk/main.cpp ${GAME_BASE_FILES} ${GAME_DEBUG_FILES} ${miniz_SOURCE_DIR}/miniz.c)
set(DUSK_FILES src/dusk/main.cpp ${GAME_BASE_FILES} ${GAME_DEBUG_FILES})
if(ANDROID)
add_library(dusklight SHARED ${DUSK_FILES})
set_target_properties(dusklight PROPERTIES OUTPUT_NAME main)
set(DUSK_MAIN_TARGET dusklight)
elseif(WIN32)
add_library(dusklight_game SHARED ${DUSK_FILES})
set_target_properties(dusklight_game PROPERTIES
WINDOWS_EXPORT_ALL_SYMBOLS ${DUSK_ENABLE_CODE_MODS}
OUTPUT_NAME dusklight
PDB_NAME dusklight_game)
# rmlui_core uses its own PCH which creates a duplicate PCH marker symbol when linked
# Disabling rmlui's PCH removes the conflicting marker and lets the link succeed
if (MSVC AND TARGET rmlui_core AND DUSK_ENABLE_CODE_MODS)
set_target_properties(rmlui_core PROPERTIES DISABLE_PRECOMPILE_HEADERS ON)
endif ()
add_executable(dusklight WIN32 src/dusk/launcher_win32.cpp)
target_link_libraries(dusklight PRIVATE dusklight_game)
target_include_directories(dusklight PRIVATE include)
set(DUSK_MAIN_TARGET dusklight_game)
else ()
add_executable(dusklight ${DUSK_FILES})
set(DUSK_MAIN_TARGET dusklight)
endif ()
if (ENABLE_ASAN)
target_sources(${DUSK_MAIN_TARGET} PRIVATE src/dusk/asan_options.c)
endif ()
if (WIN32 AND TARGET imgui)
target_compile_definitions(imgui PRIVATE "IMGUI_API=__declspec(dllexport)")
target_sources(${DUSK_MAIN_TARGET} PRIVATE $<TARGET_OBJECTS:imgui>)
endif ()
target_compile_definitions(${DUSK_MAIN_TARGET} PRIVATE ${GAME_COMPILE_DEFS} DUSK_BUILDING_GAME=1)
target_include_directories(${DUSK_MAIN_TARGET} PRIVATE ${GAME_INCLUDE_DIRS})
target_link_libraries(${DUSK_MAIN_TARGET} PRIVATE aurora::main ${GAME_LIBS} ${JSYSTEM_LINK_LIBRARIES})
target_precompile_headers(${DUSK_MAIN_TARGET} PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_LIST_DIR}/include/dusk_pch.hpp>")
if(WIN32)
target_link_libraries(${DUSK_MAIN_TARGET} PRIVATE Psapi)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL Linux)
target_link_libraries(${DUSK_MAIN_TARGET} PRIVATE dl)
endif()
if(APPLE)
target_link_options(${DUSK_MAIN_TARGET} PRIVATE -Wl,-export_dynamic)
elseif(UNIX AND NOT ANDROID)
target_link_options(${DUSK_MAIN_TARGET} PRIVATE -rdynamic)
endif()
target_compile_definitions(dusklight PRIVATE ${GAME_COMPILE_DEFS})
target_include_directories(dusklight PRIVATE ${GAME_INCLUDE_DIRS})
target_link_libraries(dusklight PRIVATE aurora::main ${GAME_LIBS} ${JSYSTEM_LINK_LIBRARIES})
target_precompile_headers(dusklight PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_SOURCE_DIR}/include/dusk_pch.hpp>")
if (TARGET crashpad_handler)
add_dependencies(${DUSK_MAIN_TARGET} crashpad_handler)
add_custom_command(TARGET ${DUSK_MAIN_TARGET} POST_BUILD
add_dependencies(dusklight crashpad_handler)
add_custom_command(TARGET dusklight POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:crashpad_handler>"
"$<TARGET_FILE_DIR:dusklight>"
@@ -620,7 +490,7 @@ endif ()
if (ANDROID)
# SDLActivity loads SDL_main via dlsym on Android. Since aurora::main is a static
# archive, force an undefined reference so the linker keeps the SDL_main object.
target_link_options(${DUSK_MAIN_TARGET} PRIVATE "-Wl,-u,SDL_main")
target_link_options(dusklight PRIVATE "-Wl,-u,SDL_main")
endif ()
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
@@ -630,7 +500,7 @@ endif ()
if (NOT APPLE)
add_custom_command(TARGET dusklight POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/res"
"${CMAKE_SOURCE_DIR}/res"
"$<TARGET_FILE_DIR:dusklight>/res"
COMMENT "Copying resources"
)
@@ -658,13 +528,13 @@ if (WIN32)
configure_file(${DUSK_WINDOWS_RESOURCE_DIR}/dusklight.rc.in ${DUSK_WINDOWS_RC} @ONLY)
target_sources(dusklight PRIVATE ${DUSK_WINDOWS_ICON_ICO} ${DUSK_WINDOWS_RC})
set_target_properties(dusklight PROPERTIES WIN32_EXECUTABLE TRUE)
if (MSVC)
target_link_options(dusklight PRIVATE /MANIFEST:NO)
endif ()
endif ()
include(cmake/DuskModSDK.cmake)
if (APPLE)
if (IOS)
set(DUSK_RESOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios)
@@ -672,7 +542,6 @@ if (APPLE)
set(DUSK_RESOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/platforms/tvos)
else ()
set(DUSK_RESOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/platforms/macos)
set(DUSK_ENTITLEMENTS ${DUSK_RESOURCE_DIR}/Dusk.entitlements)
endif ()
set(DUSK_INFO_PLIST ${DUSK_RESOURCE_DIR}/Info.plist.in)
file(GLOB_RECURSE DUSK_RESOURCE_FILES
@@ -703,8 +572,6 @@ if (APPLE)
OUTPUT_NAME Dusklight
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "YES"
XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "YES"
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS ${DUSK_ENTITLEMENTS}
XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "YES"
)
endif ()
@@ -724,11 +591,7 @@ if (IOS)
endif ()
include(extern/aurora/cmake/AuroraCopyRuntimeDLLs.cmake)
if(WIN32)
aurora_copy_runtime_dlls(dusklight dusklight_game)
else()
aurora_copy_runtime_dlls(dusklight)
endif()
aurora_copy_runtime_dlls(dusklight)
if (DUSK_SELECTED_OPT)
if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
@@ -767,42 +630,16 @@ function(get_target_prefix target result_var)
endif ()
endfunction()
list(APPEND BINARY_TARGETS dusklight)
if(WIN32)
list(APPEND BINARY_TARGETS dusklight_game)
endif()
set(EXTRA_TARGETS "")
if (TARGET crashpad_handler)
list(APPEND EXTRA_TARGETS crashpad_handler)
endif ()
if (WIN32)
# Install the launcher and game DLL, but skip the DLL import library.
if (DUSK_PACKAGE_INSTALL)
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_BINDIR}
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
)
else ()
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS}
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}
BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX}
)
endif ()
elseif (DUSK_PACKAGE_INSTALL)
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_BINDIR})
else ()
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX})
endif ()
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX})
aurora_install_runtime_dlls(dusklight ${CMAKE_INSTALL_PREFIX})
if (NOT APPLE)
if (DUSK_PACKAGE_INSTALL)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/dusklight)
else()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_PREFIX})
endif()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_PREFIX})
endif ()
if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo AND NOT DUSK_PACKAGE_INSTALL)
if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
set(DEBUG_FILES_LIST "")
foreach (target IN LISTS BINARY_TARGETS EXTRA_TARGETS)
get_target_output_name(${target} output_name)
@@ -851,7 +688,3 @@ foreach (target IN LISTS BINARY_TARGETS)
endif ()
endforeach ()
endforeach ()
if (DUSK_ENABLE_CODE_MODS)
add_subdirectory(tools/mod_test)
endif ()
+21 -116
View File
@@ -19,19 +19,7 @@
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDLL"
}
},
{
"name": "release",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDLL",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": {
"type": "BOOL",
"value": true
}
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded"
}
},
{
@@ -52,26 +40,12 @@
}
}
},
{
"name": "asan",
"hidden": true,
"cacheVariables": {
"ENABLE_ASAN": {
"type": "BOOL",
"value": true
}
}
},
{
"name": "linux-default",
"displayName": "Linux (default)",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
},
"vendor": {
@@ -93,15 +67,6 @@
"linux-default"
]
},
{
"name": "linux-default-debug-asan",
"displayName": "Linux (default) Debug ASan",
"inherits": [
"debug",
"linux-default",
"asan"
]
},
{
"name": "linux-default-relwithdebinfo",
"displayName": "Linux (default) RelWithDebInfo",
@@ -129,15 +94,6 @@
"linux-clang"
]
},
{
"name": "linux-clang-debug-asan",
"displayName": "Linux (Clang) Debug ASan",
"inherits": [
"debug",
"linux-clang",
"asan"
]
},
{
"name": "linux-clang-relwithdebinfo",
"displayName": "Linux (Clang) RelWithDebInfo",
@@ -158,11 +114,7 @@
"cacheVariables": {
"CMAKE_C_COMPILER": "cl",
"CMAKE_CXX_COMPILER": "cl",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install",
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
}
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
},
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": {
@@ -180,15 +132,6 @@
"windows-msvc"
]
},
{
"name": "windows-msvc-debug-asan",
"displayName": "Windows (MSVC) Debug ASan",
"inherits": [
"debug",
"windows-msvc",
"asan"
]
},
{
"name": "windows-msvc-relwithdebinfo",
"displayName": "Windows (MSVC) RelWithDebInfo",
@@ -258,10 +201,6 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
},
"vendor": {
@@ -280,15 +219,6 @@
"macos-default"
]
},
{
"name": "macos-default-debug-asan",
"displayName": "macOS (default) Debug ASan",
"inherits": [
"debug",
"macos-default",
"asan"
]
},
{
"name": "macos-default-relwithdebinfo",
"displayName": "macOS (default) RelWithDebInfo",
@@ -354,21 +284,24 @@
"type": "BOOL",
"value": false
},
"ENABLE_ARC": {
"type": "BOOL",
"value": false
},
"Rust_CARGO_TARGET": "aarch64-apple-tvos",
"Rust_TOOLCHAIN": "nightly",
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"CMAKE_DISABLE_FIND_PACKAGE_BZip2": {
"type": "BOOL",
"value": true
},
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew"
"CMAKE_DISABLE_FIND_PACKAGE_LibLZMA": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_zstd": {
"type": "BOOL",
"value": true
}
},
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": {
@@ -394,14 +327,8 @@
"type": "BOOL",
"value": false
},
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_zstd": {
"type": "BOOL",
"value": true
}
"AURORA_SDL3_VERSION": "3.4.8",
"AURORA_SDL3_REF": "refs/tags/release-3.4.8"
}
},
{
@@ -429,8 +356,7 @@
"hidden": true,
"inherits": [
"android-base",
"ci",
"release"
"ci"
],
"cacheVariables": {
"DUSK_ENABLE_SENTRY_NATIVE": {
@@ -458,8 +384,7 @@
"ci"
],
"cacheVariables": {
"AURORA_SDL3_PROVIDER": "vendor",
"CMAKE_LINKER_TYPE": "MOLD"
"AURORA_SDL3_PROVIDER": "vendor"
}
},
{
@@ -488,8 +413,12 @@
"type": "BOOL",
"value": true
},
"CMAKE_OSX_DEPLOYMENT_TARGET": "12.0",
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew"
"CMAKE_OSX_DEPLOYMENT_TARGET": "11.0",
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew",
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
}
}
},
{
@@ -579,12 +508,6 @@
"description": "Linux (default) debug build",
"displayName": "Linux (default) Debug"
},
{
"name": "linux-default-debug-asan",
"configurePreset": "linux-default-debug-asan",
"description": "Linux (default) debug build with AddressSanitizer",
"displayName": "Linux (default) Debug ASan"
},
{
"name": "linux-default-relwithdebinfo",
"configurePreset": "linux-default-relwithdebinfo",
@@ -597,12 +520,6 @@
"description": "Linux (Clang) debug build",
"displayName": "Linux (Clang) Debug"
},
{
"name": "linux-clang-debug-asan",
"configurePreset": "linux-clang-debug-asan",
"description": "Linux (Clang) debug build with AddressSanitizer",
"displayName": "Linux (Clang) Debug ASan"
},
{
"name": "linux-clang-relwithdebinfo",
"configurePreset": "linux-clang-relwithdebinfo",
@@ -615,12 +532,6 @@
"description": "macOS debug build",
"displayName": "macOS Debug"
},
{
"name": "macos-default-debug-asan",
"configurePreset": "macos-default-debug-asan",
"description": "macOS debug build with AddressSanitizer",
"displayName": "macOS Debug ASan"
},
{
"name": "macos-default-relwithdebinfo",
"configurePreset": "macos-default-relwithdebinfo",
@@ -678,12 +589,6 @@
"description": "Windows (MSVC) debug build",
"displayName": "Windows (MSVC) Debug"
},
{
"name": "windows-msvc-debug-asan",
"configurePreset": "windows-msvc-debug-asan",
"description": "Windows (MSVC) debug build with AddressSanitizer",
"displayName": "Windows (MSVC) Debug ASan"
},
{
"name": "windows-msvc-relwithdebinfo",
"configurePreset": "windows-msvc-relwithdebinfo",
-49
View File
@@ -1,49 +0,0 @@
# add_dusk_mod(<target> SOURCES <file>... MOD_JSON <mod.json> [RES_DIR <res>])
set(DUSK_MODS_OUTPUT_DIR "${CMAKE_SOURCE_DIR}/mods" CACHE PATH "Directory to write .dusk packages into")
function(add_dusk_mod target_name)
cmake_parse_arguments(ARG "" "MOD_JSON;RES_DIR" "SOURCES" ${ARGN})
if(NOT ARG_MOD_JSON)
message(FATAL_ERROR "add_dusk_mod: MOD_JSON is required")
endif()
add_library(${target_name} SHARED ${ARG_SOURCES})
set_target_properties(${target_name} PROPERTIES PREFIX "" WINDOWS_EXPORT_ALL_SYMBOLS ON)
target_compile_features(${target_name} PRIVATE cxx_std_20)
target_link_libraries(${target_name} PRIVATE dusklight_game_headers)
if(APPLE)
target_link_options(${target_name} PRIVATE -undefined dynamic_lookup)
elseif(UNIX)
target_link_options(${target_name} PRIVATE -Wl,--allow-shlib-undefined)
elseif(WIN32)
target_link_libraries(${target_name} PRIVATE dusklight_game)
if(MSVC)
target_link_options(${target_name} PRIVATE /INCREMENTAL:NO)
set_target_properties(${target_name} PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
endif()
endif()
set(_stage "${CMAKE_CURRENT_BINARY_DIR}/${target_name}_stage")
set(_out "${DUSK_MODS_OUTPUT_DIR}/${target_name}.dusk")
file(MAKE_DIRECTORY "${_stage}") # must exist before POST_BUILD on Windows
set(_zip_args "$<TARGET_FILE_NAME:${target_name}>" mod.json)
set(_extra_cmds "")
if(ARG_RES_DIR)
list(APPEND _zip_args res)
set(_extra_cmds COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/${ARG_RES_DIR}" "${_stage}/res")
endif()
add_custom_command(TARGET ${target_name} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${_stage}" "${DUSK_MODS_OUTPUT_DIR}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:${target_name}>" "${_stage}/$<TARGET_FILE_NAME:${target_name}>"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/${ARG_MOD_JSON}" "${_stage}/mod.json"
${_extra_cmds}
COMMAND ${CMAKE_COMMAND} -E tar cvf "${_out}" --format=zip ${_zip_args}
WORKING_DIRECTORY "${_stage}"
COMMENT "Packaging ${target_name} -> ${_out}"
)
endfunction()
-13
View File
@@ -1,13 +0,0 @@
# Patches capstone's CMakeLists.txt for compatibility with CMake >= 4.0:
# - Bumps cmake_minimum_required to 3.10 (CMake >= 4.0 dropped < 3.5 support; < 3.10 warns)
# - Removes cmake_policy(SET CMP0048 OLD) (rejected by CMake >= 3.27)
file(READ "${DIR}/CMakeLists.txt" _content)
string(REGEX REPLACE
"cmake_minimum_required[ \t]*\\([ \t]*VERSION[ \t]+[0-9]+\\.[0-9]+(\\.[0-9]+)?[ \t]*\\)"
"cmake_minimum_required(VERSION 3.10)"
_content "${_content}")
string(REGEX REPLACE
"cmake_policy[ \t]*\\([ \t]*SET[ \t]+CMP0048[ \t]+OLD[ \t]*\\)"
"# cmake_policy(SET CMP0048 OLD)"
_content "${_content}")
file(WRITE "${DIR}/CMakeLists.txt" "${_content}")
-11
View File
@@ -1,11 +0,0 @@
file(READ "${SOURCE_DIR}/cmake/capstone.cmake.in" _content)
# Insert PATCH_COMMAND before CONFIGURE_COMMAND in the ExternalProject_Add.
# Bracket args prevent cmake from substituting ${...} while writing this file.
string(REPLACE
" CONFIGURE_COMMAND \"\""
[=[ PATCH_COMMAND "${CMAKE_COMMAND}" -DDIR=${CMAKE_CURRENT_BINARY_DIR}/capstone-src -P "${CAPSTONE_FIX_SCRIPT}"
CONFIGURE_COMMAND ""]=]
_content "${_content}")
file(WRITE "${SOURCE_DIR}/cmake/capstone.cmake.in" "${_content}")
-4
View File
@@ -180,7 +180,6 @@ cmake --build --preset macos-default-relwithdebinfo
Alternate presets available:
* `macos-default-debug`: Clang, Debug
* `macos-default-debug-asan`: Clang, Debug, AddressSanitizer
**ninja (Linux)**
@@ -192,10 +191,8 @@ cmake --build --preset linux-default-relwithdebinfo
Alternate presets available:
* `linux-default-debug`: GCC, Debug
* `linux-default-debug-asan`: GCC, Debug, AddressSanitizer
* `linux-clang-relwithdebinfo`: Clang, RelWithDebInfo
* `linux-clang-debug`: Clang, Debug
* `linux-clang-debug-asan`: Clang, Debug, AddressSanitizer
**ninja (Windows)**
@@ -207,7 +204,6 @@ cmake --build --preset windows-msvc-relwithdebinfo
Alternate presets available:
* `windows-msvc-debug`: MSVC, Debug
* `windows-msvc-debug-asan`: MSVC, Debug, AddressSanitizer
* `windows-clang-relwithdebinfo`: Clang-cl, RelWithDebInfo
* `windows-clang-debug`: Clang-cl, Debug
-351
View File
@@ -1,351 +0,0 @@
# Dusk Mod API
Mods are shared libraries packaged into a `.dusk` zip archive. The loader scans the `mods/` directory at startup, extracts each library, and calls your exports each frame.
## Table of Contents
1. [Getting Started](#getting-started)
2. [mod.json](#modjson)
3. [Required Exports](#required-exports)
4. [DuskModAPI Reference](#duskmodapi-reference)
5. [Logging](#logging)
6. [Loading Resources](#loading-resources)
7. [ImGui Integration](#imgui-integration)
8. [Hooking Game Functions](#hooking-game-functions)
- [Pre-hooks](#pre-hooks)
- [Post-hooks](#post-hooks)
- [Replace hooks](#replace-hooks)
- [Reading and writing arguments](#reading-and-writing-arguments)
9. [Inter-Mod Communication](#inter-mod-communication)
10. [Full Example](#full-example)
---
## Getting Started
Fork the [mod template](../tools/mod_template/), it is a self-contained CMake project that references dusk as a subdirectory.
```
my_mod/
├── CMakeLists.txt
├── mod.json
├── src/mod.cpp
└── res/ (optional bundled resources)
```
**CMakeLists.txt:**
```cmake
cmake_minimum_required(VERSION 3.25)
project(my_mod CXX)
set(DUSK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dusk" CACHE PATH "Path to dusk source root")
add_subdirectory("${DUSK_DIR}" dusk EXCLUDE_FROM_ALL)
add_dusk_mod(my_mod
SOURCES src/mod.cpp
MOD_JSON mod.json
RES_DIR res # optional
)
```
After building, `my_mod.dusk` is placed in `mods/` next to the project root (`DUSK_MODS_OUTPUT_DIR` cache variable). Copy it to the game's `mods/` folder and launch.
- Windows: `%APPDATA%\TwilitRealm\Dusk\mods`
- Linux: `~/.local/share/TwilitRealm/Dusk/mods`
- macOS: `~/Library/Application Support/TwilitRealm/Dusk/mods`
The `.dusk` archive is a standard zip containing `mod.json`, the compiled library, and an optional `res/` tree. `add_dusk_mod()` creates it automatically.
---
## mod.json
```json
{
"name": "My Mod",
"version": "1.0.0",
"author": "Your Name",
"description": "A short description shown in the mod manager."
}
```
All fields are optional but recommended. `name` falls back to the filename, `version` to `"?"`.
---
## Required Exports
```cpp
#include "dusk/mod_api.h"
DUSK_REQUIRE_API_VERSION // declares mod_api_version; loader rejects the mod if the engine is older
extern "C" {
void mod_init (DuskModAPI* api); // required, called once at startup
void mod_tick (DuskModAPI* api); // required, called every frame
void mod_cleanup(DuskModAPI* api); // optional, called on shutdown
}
```
`DUSK_REQUIRE_API_VERSION` is optional but recommended. When present, the loader will refuse to initialize the mod if its API version doesn't exactly match the engine's.
---
## DuskModAPI Reference
The `api` pointer is valid for the lifetime of the mod. When using `hook.hpp`, call `dusk::init(api)` once and `dusk::g_api` is set for you.
| Field | Description |
|-------|-------------|
| `api_version` | ABI version, check against `DUSK_MOD_API_VERSION` if needed |
| `mod_dir` | Absolute path to the extracted mod cache directory |
| `log_info` / `log_warn` / `log_error` | `printf`-style logging, prefixed with the mod name |
| `load_resource` / `free_resource` | Load files from the `res/` tree in the `.dusk` archive |
| `register_tab_content` | Add a panel to the mod manager's per-mod tab |
| `register_menu_item` | Add an item to the quick-access menu |
| `hook_dispatch_pre` / `hook_dispatch_post` | Called by the trampoline, do not call directly |
| `service_publish` | Register a named pointer in the global service registry |
| `service_get` | Look up a named pointer registered by another mod |
---
## Logging
```cpp
api->log_info("Player health: %d", hp);
api->log_warn("Something looks wrong");
api->log_error("Fatal: %s", msg);
```
Output appears in the dusk console as `[My Mod] ...`
The format string is `printf`-compatible.
---
## Loading Resources
```cpp
size_t size = 0;
void* data = api->load_resource("config.txt", &size);
if (data) {
std::string text(static_cast<char*>(data), size);
api->free_resource(data);
}
```
- Path is relative to `res/`, pass `"config.txt"` not `"res/config.txt"`
- Always call `free_resource`, the buffer is owned by miniz
- For writable storage, write files under `api->mod_dir`
---
## ImGui Integration
**Tab content:** shown in the mod's panel in the Mods window, called every frame while visible:
```cpp
static void DrawPanel(void* userdata) {
ImGui::Text("Hello!");
}
api->register_tab_content(DrawPanel, nullptr);
```
Pass a pointer through `userdata` if your callback needs state:
```cpp
api->register_tab_content(DrawPanel, &g_state);
```
**Menu items:** added to the quick-access menu. Use `ImGui::MenuItem`, `ImGui::Separator`, etc.:
```cpp
static void DrawMenuEntry(void*) {
if (ImGui::MenuItem("Reset rotation")) { ... }
}
api->register_menu_item(DrawMenuEntry, nullptr);
```
---
## Hooking Game Functions
Call `dusk::init(api)` first.
```cpp
#include "dusk/hook.hpp"
extern "C" void mod_init(DuskModAPI* api) {
dusk::init(api);
dusk::hookAddPre<&ClassName::Method>(callback);
}
```
The trampoline is installed once per address. Multiple mods can register pre/post callbacks for the same function independently.
### Pre-hooks
Run before the original. Return `0` to let it proceed, non-zero to cancel it. Post-hooks still run either way.
```cpp
static int32_t on_posMove_pre(void* args) {
daAlink_c* link = dusk::arg<daAlink_c*>(args, 0); // this
if (link->shape_angle.y > 10000)
return 1; // cancel
return 0;
}
dusk::hookAddPre<&daAlink_c::posMove>(on_posMove_pre);
```
### Post-hooks
Run after the original (or replace-hook).
```cpp
static void on_posMove_post(void* args) {
daAlink_c* link = dusk::arg<daAlink_c*>(args, 0);
dusk::g_api->log_info("New Y angle: %d", (int)link->shape_angle.y);
}
dusk::hookAddPost<&daAlink_c::posMove>(on_posMove_post);
```
### Replace hooks
Completely substitutes the original. Only one replace-hook per function, a second install overwrites with a warning.
```cpp
static void on_posMove_replace(void* args) {
daAlink_c* link = dusk::arg<daAlink_c*>(args, 0);
link->shape_angle.y += 100;
}
dusk::hookSetReplace<&daAlink_c::posMove>(on_posMove_replace);
```
To call the original from inside a replace-hook:
```cpp
using Entry = dusk::HookEntry<&daAlink_c::posMove>;
static void on_posMove_replace(void* args) {
daAlink_c* link = dusk::arg<daAlink_c*>(args, 0);
link->shape_angle.y = 0;
Entry::g_orig(link);
}
```
### Reading and writing arguments
`args` is a `void*[N]` array. Index `0` is `this`, subsequent indices are parameters in declaration order.
```cpp
T value = dusk::arg <T>(args, n); // copy
T& ref = dusk::argRef<T>(args, n); // reference (read/write)
```
**Example:** halve incoming damage
```cpp
// void daEnemy_c::takeDamage(int amount, daActor_c* source)
static int32_t on_takeDamage_pre(void* args) {
dusk::argRef<int>(args, 1) /= 2;
return 0;
}
dusk::hookAddPre<&daEnemy_c::takeDamage>(on_takeDamage_pre);
```
For reference parameters (e.g. `const cXyz& pos`), use `argRef<cXyz>` to get a direct reference.
---
## Inter-Mod Communication
Mods can expose a public API to each other through a global service registry. The convention for names is `"mod_name/service_name"`.
**Mod A — publishing:**
```cpp
struct MyModAPI {
void (*do_thing)(int value);
};
static void my_do_thing(int value) { ... }
static MyModAPI g_api = { my_do_thing };
extern "C" void mod_init(DuskModAPI* api) {
api->service_publish("my_mod/api", &g_api);
}
```
**Mod B — consuming:**
```cpp
#include "my_mod_api.h"
static MyModAPI* g_my_mod = nullptr;
extern "C" void mod_init(DuskModAPI* api) {
g_my_mod = static_cast<MyModAPI*>(api->service_get("my_mod/api"));
}
```
---
## Full Example
```cpp
#include "d/actor/d_a_alink.h"
#include "dusk/hook.hpp"
#include "dusk/mod_api.h"
#include "imgui.h"
#include "m_Do/m_Do_controller_pad.h"
static int g_ticks = 0;
static int32_t on_posMove_pre(void* args) {
daAlink_c* link = dusk::arg<daAlink_c*>(args, 0);
if (mDoCPd_c::getHoldR(PAD_1)) {
link->shape_angle.y -= 2048;
}
return 0;
}
static void DrawPanel(void*) {
daAlink_c* link = daAlink_getAlinkActorClass();
ImGui::Text("Ticks: %d", g_ticks);
if (link) {
ImGui::Text("Y angle: %d", (int)link->shape_angle.y);
if (ImGui::Button("Reset rotation")) {
link->shape_angle.y = 0;
}
}
}
static void DrawMenuEntry(void*) {
daAlink_c* link = daAlink_getAlinkActorClass();
if (ImGui::MenuItem("Reset rotation", nullptr, false, link != nullptr)) {
link->shape_angle.y = 0;
}
}
extern "C" {
void mod_init(DuskModAPI* api) {
dusk::init(api);
dusk::hookAddPre<&daAlink_c::posMove>(on_posMove_pre);
api->register_tab_content(DrawPanel, nullptr);
api->register_menu_item(DrawMenuEntry, nullptr);
}
void mod_tick(DuskModAPI* api) {
++g_ticks;
}
void mod_cleanup(DuskModAPI* api) {
api->log_info("Unloaded after %d ticks.", g_ticks);
}
}
```
+1 -1
-28
View File
@@ -1418,11 +1418,7 @@ set(DUSK_FILES
include/dusk/scope_guard.hpp
src/dusk/dvd_asset.cpp
src/d/actor/d_a_alink_dusk.cpp
src/dusk/android_frame_rate.hpp
src/dusk/android_frame_rate.cpp
src/dusk/asserts.cpp
src/dusk/batch.cpp
src/dusk/batch.hpp
src/dusk/config.cpp
src/dusk/crash_handler.cpp
src/dusk/crash_reporting.cpp
@@ -1436,9 +1432,6 @@ set(DUSK_FILES
src/dusk/game_clock.cpp
src/dusk/globals.cpp
src/dusk/gyro.cpp
include/dusk/menu_pointer.h
src/dusk/menu_pointer.cpp
src/dusk/mouse.cpp
src/dusk/gamepad_color.cpp
src/dusk/autosave.cpp
src/dusk/http/http.hpp
@@ -1451,7 +1444,6 @@ set(DUSK_FILES
src/dusk/stubs.cpp
include/dusk/texture_replacements.hpp
src/dusk/texture_replacements.cpp
src/dusk/touch_camera.cpp
src/dusk/update_check.cpp
src/dusk/update_check.hpp
#src/dusk/m_Do_ext_dusk.cpp
@@ -1481,7 +1473,6 @@ set(DUSK_FILES
src/dusk/ui/button.hpp
src/dusk/ui/component.cpp
src/dusk/ui/component.hpp
src/dusk/ui/controls.hpp
src/dusk/ui/controller_config.cpp
src/dusk/ui/controller_config.hpp
src/dusk/ui/document.cpp
@@ -1494,8 +1485,6 @@ set(DUSK_FILES
src/dusk/ui/graphics_tuner.hpp
src/dusk/ui/input.cpp
src/dusk/ui/input.hpp
src/dusk/ui/icon_provider.cpp
src/dusk/ui/icon_provider.hpp
src/dusk/ui/modal.cpp
src/dusk/ui/modal.hpp
src/dusk/ui/nav_types.hpp
@@ -1507,8 +1496,6 @@ set(DUSK_FILES
src/dusk/ui/pane.hpp
src/dusk/ui/menu_bar.cpp
src/dusk/ui/menu_bar.hpp
src/dusk/ui/mods_window.cpp
src/dusk/ui/mods_window.hpp
src/dusk/ui/prelaunch.cpp
src/dusk/ui/prelaunch.hpp
src/dusk/ui/preset.cpp
@@ -1523,12 +1510,6 @@ set(DUSK_FILES
src/dusk/ui/string_button.hpp
src/dusk/ui/tab_bar.cpp
src/dusk/ui/tab_bar.hpp
src/dusk/ui/touch_controls_common.cpp
src/dusk/ui/touch_controls_common.hpp
src/dusk/ui/touch_controls.cpp
src/dusk/ui/touch_controls.hpp
src/dusk/ui/touch_controls_editor.cpp
src/dusk/ui/touch_controls_editor.hpp
src/dusk/ui/ui.cpp
src/dusk/ui/ui.hpp
src/dusk/ui/warp.cpp
@@ -1543,15 +1524,6 @@ set(DUSK_FILES
src/dusk/OSReport.cpp
src/dusk/OSThread.cpp
src/dusk/OSMutex.cpp
src/dusk/hook_system.cpp
src/dusk/modding/mod_loader.cpp
src/dusk/modding/mod_loader_api.cpp
src/dusk/modding/mod_loader_overlay.cpp
src/dusk/modding/native_module.cpp
src/dusk/modding/native_module.hpp
src/dusk/modding/bundle_disk.cpp
src/dusk/modding/bundle_zip.cpp
src/dusk/gx_helper.cpp
src/dusk/discord.cpp
src/dusk/discord.hpp
src/dusk/discord_presence.cpp
-32
View File
@@ -1,32 +0,0 @@
From f69d29614644f9963f5cb3f828b58575d60a1c5a Mon Sep 17 00:00:00 2001
From: Joshua Trees <gh@jtrees.io>
Date: Thu, 4 Jun 2026 01:04:04 +0100
Subject: [PATCH] fix cmake paths
---
cmake/nodConfig.cmake.in | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/cmake/nodConfig.cmake.in b/cmake/nodConfig.cmake.in
index 0969382..2a24a88 100644
--- a/cmake/nodConfig.cmake.in
+++ b/cmake/nodConfig.cmake.in
@@ -1,12 +1,12 @@
@PACKAGE_INIT@
-set(_nod_libdir "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_LIBDIR@")
-set(_nod_incdir "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@")
+set(_nod_libdir "@CMAKE_INSTALL_FULL_LIBDIR@")
+set(_nod_incdir "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
if (NOT TARGET nod::nod_shared AND NOT TARGET nod::nod_static)
# Shared library
if (WIN32)
- set(_nod_dll "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_BINDIR@/${CMAKE_SHARED_LIBRARY_PREFIX}nod${CMAKE_SHARED_LIBRARY_SUFFIX}")
+ set(_nod_dll "@CMAKE_INSTALL_FULL_BINDIR@/${CMAKE_SHARED_LIBRARY_PREFIX}nod${CMAKE_SHARED_LIBRARY_SUFFIX}")
set(_nod_implib "${_nod_libdir}/${CMAKE_IMPORT_LIBRARY_PREFIX}nod${CMAKE_IMPORT_LIBRARY_SUFFIX}")
if (EXISTS "${_nod_dll}")
add_library(nod::nod_shared SHARED IMPORTED)
--
2.53.0
+130 -142
View File
@@ -16,37 +16,37 @@
];
forAllSystems = lib.genAttrs supportedSystems;
dawnVersion = "v20260618.032059";
nodVersion = "v2.0.0-alpha.10";
dawnVersion = "v20260423.175430";
nodVersion = "v2.0.0-alpha.8";
versionSuffix = "nix-" + (self.shortRev or self.dirtyShortRev or "dirty");
dawnInfo = {
"x86_64-linux" = {
triple = "linux-x86_64";
hash = "sha256-GFSd573b+VQx/VmFdNQgWDd0V9ayQlcw0Zuopke12ak=";
hash = "sha256-HXfKTLHtMPwupnFnaflCARtXVPuS/0PoCePXidjE5xs=";
};
"aarch64-linux" = {
triple = "linux-aarch64";
hash = "sha256-ZaoP7BAjBMnfAv2/AMRi3FNH2ZtyqASCSFyU/oB2Mzg=";
hash = "sha256-34yyFpfqBZUwoFXQ41F0AwAU78FaNihOSY0oriwn6B0=";
};
"aarch64-darwin" = {
triple = "darwin-arm64";
hash = "sha256-HT+qtlLaSHyoXPrUcXgcTGa877X5YfzbxRD4bJb7i1Y=";
hash = "sha256-eQnzrBp6gjiBek1VYQ9A5W13ClYWrDDKjIqv/7eNTR4=";
};
"x86_64-darwin" = {
triple = "darwin-x86_64";
hash = "sha256-cUNaCbA7rlKSukDVKGaVEVw0Zt1+mSbaHbmUCMvMVWc=";
hash = "sha256-QGWiGdxiI9kci3NPXH6QFFirxn16851zB/w3jqhIBJ4=";
};
};
nodPrebuiltInfo = {
"x86_64-linux" = {
triple = "linux-x86_64";
hash = "sha256-FVQWECVA2gWdc+n5OQ/Tvwn8z0qdgjSd1WlFt5HKOec=";
hash = "sha256-mUqvLsbsqaZ+HAjMmHYPYO+MgtanGRTw7Gzn5uXR5rE=";
};
"aarch64-darwin" = {
triple = "macos-arm64";
hash = "sha256-8ZEejxksVgShNKUVRCBYaLOp9x/qOC9pAeVrElQUGUk=";
hash = "sha256-UPy1ywCcv0K6VJOU3uUelJuUdBh3UNaPRlyP5LOBeDw=";
};
};
@@ -57,25 +57,15 @@
inherit (pkgs.stdenv.hostPlatform) isDarwin;
hasNodPrebuilt = nodPrebuiltInfo ? ${system};
aurora = builtins.pathExists "${self}/extern/aurora/CMakeLists.txt";
needSubmodules = ''
dusklight: The aurora submodule is not vendored. Add submodules=1 to build.
As a flake input:
dusklight.url = "git+https://github.com/TwilitRealm/dusklight?ref=main&submodules=1";
nix command:
nix run 'git+https://github.com/TwilitRealm/dusklight?submodules=1'
Local checkout:
nix run '.?submodules=1#dusklight'
'';
aurora = pkgs.fetchFromGitHub {
owner = "encounter";
repo = "aurora";
rev = "10006618ee493f248b8597e4dfa1d2871d76a1d9";
hash = "sha256-lY2xuVyB7aPJ9+2wwLRB3F5U/BuPSxdSpegdG+qNd9o=";
};
dawn = pkgs.fetchzip {
url = "https://github.com/encounter/dawn/releases/download/${dawnVersion}/dawn-${dawnInfo.${system}.triple}.tar.gz";
url = "https://github.com/encounter/dawn-build/releases/download/${dawnVersion}/dawn-${dawnInfo.${system}.triple}.tar.gz";
hash = dawnInfo.${system}.hash;
stripRoot = false;
};
@@ -94,9 +84,8 @@
owner = "encounter";
repo = "nod";
rev = nodVersion;
hash = "sha256-r8qDlOVxv5iKiFjJQrcBuL9HVoOM3yEjRVnQIMqaICs=";
hash = "sha256-+zrtVzjo0+X/6uMcNUn1+FaSR+jOhrcQSDNBFjw0NDs=";
};
patches = [ ./fix-cmake-paths.patch ];
cargoDeps = pkgs.rustPlatform.importCargoLock {
lockFile = "${finalAttrs.src}/Cargo.lock";
};
@@ -138,15 +127,15 @@
NOD_PREBUILT = nod;
CXXOPTS = pkgs.cxxopts.src;
JSON = pkgs.nlohmann_json.src;
XXHASH = pkgs.xxhash.src;
XXHASH = pkgs.xxHash.src;
ZSTD = pkgs.zstd.src;
FMT = pkgs.fetchzip {
url = "https://github.com/fmtlib/fmt/archive/refs/tags/12.1.0.tar.gz";
hash = "sha256-ZmI1Dv0ZabPlxa02OpERI47jp7zFfjpeWCy1WyuPYZ0=";
url = "https://github.com/fmtlib/fmt/archive/refs/tags/11.1.4.tar.gz";
hash = "sha256-sUbxlYi/Aupaox3JjWFqXIjcaQa0LFjclQAOleT+FRA=";
};
TRACY = pkgs.fetchzip {
url = "https://github.com/wolfpld/tracy/archive/6789e7d6f9a65ec98926b602097a33a9676d2606.tar.gz";
hash = "sha256-Xxyd7G/mnXEPpN+ehmwl0AkAhS3CwObpJNDgcqbdUJg=";
url = "https://github.com/wolfpld/tracy/archive/a64b9a20294d59421a2f57aeca3c6383d8c48169.tar.gz";
hash = "sha256-hbNGOsGeyGSvCJ2No8RkwOib1lX2on3vNZSzyVkZdXw=";
};
IMGUI = pkgs.fetchFromGitHub {
owner = "ocornut";
@@ -164,120 +153,119 @@
};
};
dusklight =
if !aurora then
throw needSubmodules
else
pkgs.stdenv.mkDerivation {
pname = "dusklight";
version = versionSuffix;
src = ./.;
dusklight = pkgs.stdenv.mkDerivation {
pname = "dusklight";
version = versionSuffix;
src = ./.;
postUnpack = ''
chmod -R u+w "$sourceRoot"
substituteInPlace "$sourceRoot/extern/aurora/CMakeLists.txt" \
--replace-warn "add_subdirectory(tests)" ""
postUnpack = ''
chmod -R u+w "$sourceRoot"
rm -rf "$sourceRoot/extern/aurora"
mkdir -p "$sourceRoot/extern"
cp -r ${aurora} "$sourceRoot/extern/aurora"
chmod -R u+w "$sourceRoot/extern/aurora"
substituteInPlace "$sourceRoot/extern/aurora/CMakeLists.txt" \
--replace-warn "add_subdirectory(tests)" ""
'';
nativeBuildInputs = [
pkgs.cmake
pkgs.ninja
pkgs.pkg-config
pkgs.python3
pkgs.python3Packages.markupsafe
]
++ lib.optionals (!isDarwin) [ pkgs.autoPatchelfHook ];
buildInputs = [
pkgs.sdl3
pkgs.freetype
pkgs.zstd
pkgs.cxxopts
pkgs.nlohmann_json
pkgs.xxHash
pkgs.abseil-cpp
pkgs.zlib
pkgs.libpng
pkgs.libjpeg_turbo
pkgs.curl
pkgs.openssl
]
++ lib.optionals isDarwin [
pkgs.apple-sdk_15
pkgs.libiconv
]
++ lib.optionals (!isDarwin) [
pkgs.libGL
pkgs.libGLU
pkgs.libglvnd
pkgs.vulkan-loader
pkgs.libX11
pkgs.libxcb
pkgs.libXcursor
pkgs.libxi
pkgs.libxrandr
pkgs.libxscrnsaver
pkgs.libxtst
pkgs.libxinerama
pkgs.libxkbcommon
pkgs.wayland
pkgs.libdecor
pkgs.alsa-lib
pkgs.libpulseaudio
pkgs.pipewire
pkgs.dbus
pkgs.udev
pkgs.libusb1
pkgs.libunwind
pkgs.gtk3
];
cmakeBuildType = "RelWithDebInfo";
ninjaFlags = [ "dusklight" ];
cmakeFlags = [
"-DDUSK_VERSION_OVERRIDE=${versionSuffix}"
"-DFETCHCONTENT_FULLY_DISCONNECTED=ON"
"-DAURORA_DAWN_PROVIDER=package"
"-DAURORA_DAWN_LINKAGE=static"
"-DAURORA_NOD_PROVIDER=package"
"-DAURORA_NOD_LINKAGE=static"
"-DAURORA_SDL3_PROVIDER=system"
]
++ lib.mapAttrsToList (key: src: "-DFETCHCONTENT_SOURCE_DIR_${key}=${src}") fetchContentDirs;
installPhase =
if isDarwin then
''
runHook preInstall
mkdir -p "$out/Applications"
cp -r Dusklight.app "$out/Applications/Dusklight.app"
runHook postInstall
''
else
''
runHook preInstall
install -Dm755 dusklight "$out/bin/dusklight"
cp -r "$src/res" "$out/bin/res"
install -Dm644 "$src/platforms/freedesktop/dev.twilitrealm.dusk.desktop" \
"$out/share/applications/dev.twilitrealm.dusk.desktop"
for size in 16 32 48 64 128 256 512 1024; do
install -Dm644 "$src/platforms/freedesktop/''${size}x''${size}/apps/dev.twilitrealm.dusk.png" \
"$out/share/icons/hicolor/''${size}x''${size}/apps/dev.twilitrealm.dusk.png"
done
runHook postInstall
'';
nativeBuildInputs = [
pkgs.cmake
pkgs.ninja
pkgs.pkg-config
pkgs.python3
pkgs.python3Packages.markupsafe
]
++ lib.optionals (!isDarwin) [ pkgs.autoPatchelfHook ];
dontStrip = true;
buildInputs = [
pkgs.sdl3
pkgs.freetype
pkgs.zstd
pkgs.cxxopts
pkgs.nlohmann_json
pkgs.xxhash
pkgs.abseil-cpp
pkgs.zlib
pkgs.libpng
pkgs.libjpeg_turbo
pkgs.curl
pkgs.openssl
]
++ lib.optionals isDarwin [
pkgs.apple-sdk_15
pkgs.libiconv
]
++ lib.optionals (!isDarwin) [
pkgs.libGL
pkgs.libGLU
pkgs.libglvnd
pkgs.vulkan-loader
pkgs.libX11
pkgs.libxcb
pkgs.libXcursor
pkgs.libxi
pkgs.libxrandr
pkgs.libxscrnsaver
pkgs.libxtst
pkgs.libxinerama
pkgs.libxkbcommon
pkgs.wayland
pkgs.libdecor
pkgs.alsa-lib
pkgs.libpulseaudio
pkgs.pipewire
pkgs.dbus
pkgs.udev
pkgs.libusb1
pkgs.libunwind
pkgs.gtk3
nod
];
cmakeBuildType = "RelWithDebInfo";
ninjaFlags = [ "dusklight" ];
cmakeFlags = [
"-DDUSK_VERSION_OVERRIDE=${versionSuffix}"
"-DFETCHCONTENT_FULLY_DISCONNECTED=ON"
"-DAURORA_DAWN_PROVIDER=package"
"-DAURORA_DAWN_LINKAGE=static"
"-DAURORA_NOD_PROVIDER=system"
"-DAURORA_SDL3_PROVIDER=system"
"-DBUILD_SHARED_LIBS=OFF"
]
++ lib.mapAttrsToList (key: src: "-DFETCHCONTENT_SOURCE_DIR_${key}=${src}") fetchContentDirs;
installPhase =
if isDarwin then
''
runHook preInstall
mkdir -p "$out/Applications"
cp -r Dusklight.app "$out/Applications/Dusklight.app"
runHook postInstall
''
else
''
runHook preInstall
install -Dm755 dusklight "$out/bin/dusklight"
cp -r "$src/res" "$out/bin/res"
install -Dm644 "$src/platforms/freedesktop/dev.twilitrealm.dusk.desktop" \
"$out/share/applications/dev.twilitrealm.dusk.desktop"
for size in 16 32 48 64 128 256 512 1024; do
install -Dm644 "$src/platforms/freedesktop/''${size}x''${size}/apps/dev.twilitrealm.dusk.png" \
"$out/share/icons/hicolor/''${size}x''${size}/apps/dev.twilitrealm.dusk.png"
done
runHook postInstall
'';
dontStrip = true;
meta = {
description = "Dusklight native PC port of the Twilight Princess decompilation";
homepage = "https://github.com/zeldaret/tp";
platforms = supportedSystems;
mainProgram = "dusklight";
};
};
meta = {
description = "Dusklight native PC port of the Twilight Princess decompilation";
homepage = "https://github.com/zeldaret/tp";
platforms = supportedSystems;
mainProgram = "dusklight";
};
};
# Tooling common to every supported host (Linux and macOS).
commonDevTools = [
+1 -1
View File
@@ -34,7 +34,7 @@ public:
bool isResetting() { return mResettingFlag; }
static Z2AudioMgr* getInterface() { return mAudioMgrPtr; }
static DUSK_GAME_DATA Z2AudioMgr* mAudioMgrPtr;
static Z2AudioMgr* mAudioMgrPtr;
/* 0x0514 */ virtual bool startSound(JAISoundID soundID, JAISoundHandle* handle, const JGeometry::TVec3<f32>* posPtr);
/* 0x0518 */ bool mResettingFlag;
+1 -18
View File
@@ -88,10 +88,6 @@ public:
/* 0x02C */ cXyz field_0x2c;
/* 0x038 */ cXyz field_0x38[60];
/* 0x308 */ cXyz field_0x308[60];
#if TARGET_PC
TGXTexObj mBlurTexObj;
ResTIMG* mpCachedBlurTex = nullptr;
#endif
}; // Size = 0x5D8
class dAlink_bottleWaterPcallBack_c : public JPAParticleCallBack {
@@ -4555,8 +4551,7 @@ public:
#if TARGET_PC
void handleWolfHowl();
void handleQuickTransform();
bool checkAimContext();
bool checkAimInputContext();
bool checkGyroAimContext();
void onIronBallChainInterpCallback();
@@ -4569,18 +4564,6 @@ public:
cXyz mIBChainInterpCurrHandRoot;
bool mIBChainInterpPrevValid;
bool mIBChainInterpCurrValid;
cXyz mHsChainInterpPrevTop;
cXyz mHsChainInterpCurrTop;
cXyz mHsChainInterpPrevRoot;
cXyz mHsChainInterpCurrRoot;
cXyz mHsChainInterpPrevSubRoot;
cXyz mHsChainInterpCurrSubRoot;
cXyz mHsChainInterpPrevSubTop;
cXyz mHsChainInterpCurrSubTop;
bool mHsChainInterpPrevValid;
bool mHsChainInterpCurrValid;
bool mIsRollstab = false;
#endif
}; // Size: 0x385C
+2 -7
View File
@@ -299,13 +299,8 @@ public:
/* 0x168C */ u8 field_0x168c;
/* 0x168D */ u8 field_0x168d;
/* 0x168E */ u8 HIOInit;
#if TARGET_PC
cXyz mLineInterpPrev[MG_ROD_LURE_LINE_LEN];
cXyz mLineInterpCurr[MG_ROD_LURE_LINE_LEN];
bool mLineInterpPrevValid;
bool mLineInterpCurrValid;
#endif
};
STATIC_ASSERT(sizeof(dmg_rod_class) == 0x1690);
#endif /* D_A_MG_ROD_H */
-9
View File
@@ -66,18 +66,9 @@ public:
/* 0x2CA7 */ s8 hide_lock;
/* 0x2CA8 */ cXyz field_0x2ca8;
/* 0x2CB4 */ u8 field_0x2cb4;
#if TARGET_PC
Mtx mChainInterpPrev[6][16];
Mtx mChainInterpCurr[6][16];
bool mChainInterpPrevValid;
bool mChainInterpCurrValid;
#endif
};
#if !TARGET_PC
STATIC_ASSERT(sizeof(obj_keyhole_class) == 0x2CB8);
#endif
class daObj_Keyhole_HIO_c : public JORReflexible {
public:
-4
View File
@@ -50,10 +50,6 @@ public:
/* 0x14 */ Mtx mProjMtx;
/* 0x44 */ ResTIMG* mpImg;
/* 0x48 */ u8* mpData;
#if TARGET_PC
TGXTexObj mTexObj;
ResTIMG* mpCachedImg = nullptr;
#endif
};
class daPy_boomerangMove_c {
-10
View File
@@ -4,10 +4,6 @@
#include "JSystem/J3DGraphBase/J3DPacket.h"
#include "SSystem/SComponent/c_xyz.h"
#if TARGET_PC
#include "dusk/batch.hpp"
#endif
class cCcD_Obj;
class dCcMassS_HitInf;
class fopAc_ac_c;
@@ -111,12 +107,6 @@ public:
#if TARGET_PC
TGXTexObj mTexObj_l_J_Ohana00_64TEX;
TGXTexObj mTexObj_l_J_Ohana01_64128_0419TEX;
dusk::batch::LeafTemplate mTplHana00; // l_J_hana00DL
dusk::batch::LeafTemplate mTplHana00Cut; // l_J_hana00_cDL
dusk::batch::LeafTemplate mTplHana01; // l_J_hana01DL
dusk::batch::LeafTemplate mTplHana01Cut00; // l_J_hana01_c_00DL
dusk::batch::LeafTemplate mTplHana01Cut; // l_J_hana01_c_01DL
#endif
}; // Size: 0x12A54
-8
View File
@@ -4,10 +4,6 @@
#include "JSystem/J3DGraphBase/J3DPacket.h"
#include "SSystem/SComponent/c_xyz.h"
#if TARGET_PC
#include "../../../src/dusk/batch.hpp"
#endif
class cCcD_Obj;
class csXyz;
class dCcMassS_HitInf;
@@ -114,10 +110,6 @@ public:
#if TARGET_PC
TGXTexObj mTexObj_l_M_Hijiki00TEX;
TGXTexObj mTexObj_l_M_kusa05_RGBATEX;
dusk::batch::LeafTemplate mTplKusa9q; // l_M_Kusa_9qDL
dusk::batch::LeafTemplate mTplKusa9qCut; // l_M_Kusa_9q_cDL
dusk::batch::LeafTemplate mTplTengusa; // l_M_TenGusaDL
#endif
}; // Size: 0x1D718
-1
View File
@@ -1037,7 +1037,6 @@ public:
bool test1Camera(s32);
bool test2Camera(s32);
#if TARGET_PC
static bool isAimActive();
bool freeCamera();
bool executeDebugFlyCam();
void deactivateDebugFlyCam();
+5 -5
View File
@@ -1049,11 +1049,11 @@ public:
STATIC_ASSERT(122384 == sizeof(dComIfG_inf_c));
DUSK_GAME_EXTERN dComIfG_inf_c g_dComIfG_gameInfo;
DUSK_GAME_EXTERN GXColor g_blackColor;
DUSK_GAME_EXTERN GXColor g_clearColor;
DUSK_GAME_EXTERN GXColor g_whiteColor;
DUSK_GAME_EXTERN GXColor g_saftyWhiteColor;
extern dComIfG_inf_c g_dComIfG_gameInfo;
extern GXColor g_blackColor;
extern GXColor g_clearColor;
extern GXColor g_whiteColor;
extern GXColor g_saftyWhiteColor;
int dComLbG_PhaseHandler(request_of_phase_process_class*, request_of_phase_process_fn*,
void*);
-13
View File
@@ -287,11 +287,6 @@ public:
MEMCARDCHECKPROC_ERR_YESNO_CURSOR_MOVE_ANM,
MEMCARDCHECKPROC_SAVEDATA_CLEAR,
#if TARGET_PC
MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE,
MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE_ERR_WAIT,
#endif
#if PLATFORM_WII || PLATFORM_SHIELD
MEMCARDCHECKPROC_NAND_STAT_CHECK,
MEMCARDCHECKPROC_GAMEFILE_INIT_SEL,
@@ -416,10 +411,6 @@ public:
bool yesnoWakuAlpahAnm(u8);
#if TARGET_PC
void fileSelectWide();
bool pointerDataSelect();
bool pointerMenuSelect();
bool pointerCopyDataToSelect();
bool pointerYesNoSelect(bool errorSelect);
#endif
void _draw();
void errorMoveAnmInitSet(int, int);
@@ -454,10 +445,6 @@ public:
void MemCardMakeGameFile();
void MemCardMakeGameFileWait();
void MemCardMakeGameFileCheck();
#if TARGET_PC
void MemCardAutoMakeGameFile();
void MemCardAutoMakeGameFileErrWait();
#endif
void MemCardMsgWindowInitOpen();
void MemCardMsgWindowOpen();
void MemCardMsgWindowClose();
+1 -2
View File
@@ -198,7 +198,6 @@ struct HOUSI_EFF {
/* 0x4C */ u16 field_0x4c;
}; // Size: 0x50
// Housi is the rising square particles in Twilight
class dKankyo_housi_Packet : public J3DPacket {
public:
virtual void draw();
@@ -209,7 +208,7 @@ public:
/* 0x0020 */ HOUSI_EFF mHousiEff[300];
/* 0x5DE0 */ u8 field_0x5de0[8];
/* 0x5DE8 */ f32 field_0x5de8;
/* 0x5DEC */ s16 mHousiCount;
/* 0x5DEC */ s16 field_0x5dec;
}; // Size: 0x5DF0
struct CLOUD_EFF {
-3
View File
@@ -157,9 +157,6 @@ public:
int getDispType() const;
void _move(f32, f32, int, f32);
void _draw();
#if TARGET_PC
bool refreshTextureSize();
#endif
virtual ~dMap_c() {
#if DEBUG
-2
View File
@@ -74,8 +74,6 @@ public:
#if TARGET_PC
void menuCollectWide();
bool pointerWait();
void pointerActivateCurrent();
#endif
void _create();
-4
View File
@@ -51,10 +51,6 @@ public:
void setBButtonString(u16);
void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Insect_c();
-4
View File
@@ -55,10 +55,6 @@ public:
u8 getLetterNum();
void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Letter_c();
-3
View File
@@ -80,9 +80,6 @@ public:
void setBButtonString(u16);
bool isRumbleSupported();
bool dpdMenuMove();
#if TARGET_PC
bool pointerConfirmSelect();
#endif
void paneResize(u64);
void initialize();
void yesnoMenuMoveAnmInitSet(int, int);
-4
View File
@@ -74,9 +74,6 @@ public:
void clacEllipsePlotAverage(int, f32, f32);
bool dpdMove();
u8 openExplain(u8);
#if TARGET_PC
bool pointerMove();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Ring_c();
@@ -218,7 +215,6 @@ private:
bool mCursorInterpPrevAngular;
bool mCursorInterpCurrAngular;
bool mCursorInterpInit;
bool mPointerTouchPressHoveredCurrent;
#endif
};
-2
View File
@@ -266,8 +266,6 @@ public:
#if TARGET_PC
void menuSaveWide();
bool pointerSaveSelect();
bool pointerYesNoSelect(bool errorSelect, u8 errParam = 0, u8 soundParam = 0);
#endif
void _draw2();
-4
View File
@@ -49,10 +49,6 @@ public:
u8 getSkillNum();
void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Skill_c();
+1 -4
View File
@@ -2,7 +2,6 @@
#define D_METER_D_METER2_INFO_H
#include "SSystem/SComponent/c_xyz.h"
#include "global.h"
class CPaneMgr;
class J2DTextBox;
@@ -302,7 +301,7 @@ public:
/* 0xF3 */ u8 unk_0xf3[5];
};
DUSK_GAME_EXTERN dMeter2Info_c g_meter2_info;
extern dMeter2Info_c g_meter2_info;
void dMeter2Info_setSword(u8 i_itemId, bool i_offItemBit);
void dMeter2Info_setCloth(u8 i_clothId, bool i_offItemBit);
@@ -850,8 +849,6 @@ inline void dMeter2Info_setFloatingMessage(u16 i_msgID, s16 i_msgTimer, bool i_w
g_meter2_info.setFloatingMessage(i_msgID, i_msgTimer, i_wakuVisible);
}
// Show a custom text notification using the floating-message HUD display.
inline void dMeter2Info_setMiniGameCount(s8 i_count) {
g_meter2_info.setMiniGameCount(i_count);
}
-4
View File
@@ -49,10 +49,6 @@ public:
void selectScale();
void selectTrans();
void selectAnimeTransform(int);
#if TARGET_PC
bool pointerMove();
bool consumePointerClick();
#endif
void setOffsetX(f32 i_offsetX) { mOffsetX = i_offsetX; }
bool isAnimeUpdate(int param_0) { return (field_0x114 & (u8)(1 << param_0)) ? TRUE : FALSE; }
-8
View File
@@ -9,8 +9,6 @@ namespace dusk {
enum class ActionBinds {
FIRST_PERSON_CAMERA,
CALL_MIDNA,
OPEN_MAP_SCREEN,
TOGGLE_MINIMAP,
OPEN_DUSKLIGHT_MENU,
TURBO_SPEED_BUTTON,
COUNT,
@@ -34,12 +32,6 @@ bool isActionBound(ActionBinds action, u32 port);
void updateActionBindings();
void setVirtualActionBind(ActionBinds action, u32 port, bool pressed, bool available = true);
void clearVirtualActionBind(ActionBinds action, u32 port);
void clearAllVirtualActionBinds();
bool getActionBindTrig(ActionBinds action, u32 port);
bool getActionBindHold(ActionBinds action, u32 port);
+5 -4
View File
@@ -89,16 +89,17 @@ public:
*/
void Register(ConfigVarBase& configVar);
/**
* \brief Indicate that all registrations have happened and everything should lock in.
*/
void FinishRegistration();
/**
* \brief Load config from the standard user preferences location.
*/
void LoadFromUserPreferences();
void LoadFromFileName(const char* path);
void LoadArgOverride(std::string_view name, std::string_view value);
void Shutdown();
/**
* \brief Save the config to file.
*/
+7 -21
View File
@@ -4,7 +4,6 @@
#include "dolphin/types.h"
#include <type_traits>
#include <cstdlib>
#include <limits>
#include <string>
/**
@@ -69,7 +68,7 @@ protected:
/**
* The name of this CVar, used in the configuration file.
*/
std::string name;
const char* name;
/**
* Whether this CVar has been registered with the global managing logic.
@@ -87,10 +86,8 @@ protected:
*/
const ConfigImplBase* impl;
// The configuration system stores a direct pointer to the ConfigVar instance.
// It is not legal to move or copy it.
ConfigVarBase(const ConfigVarBase&) = delete;
ConfigVarBase(std::string name, const ConfigImplBase* impl);
ConfigVarBase(const char* name, const ConfigImplBase* impl);
virtual ~ConfigVarBase() = default;
/**
* Check that the CVar is registered, aborting if this is not the case.
@@ -101,8 +98,6 @@ protected:
}
public:
virtual ~ConfigVarBase();
/**
* Get the name of this CVar, used in the configuration file.
*/
@@ -125,7 +120,6 @@ public:
* This is necessary to make it legal to access.
*/
void markRegistered();
void unmarkRegistered();
/**
* Clear a speedrun-mode override if one is active on this CVar.
@@ -145,16 +139,11 @@ concept ConfigValueInteger =
|| std::is_same_v<T, s64>
|| std::is_same_v<T, u64>;
template <typename T>
struct ConfigValueTraits {
static constexpr bool enabled = false;
};
/**
* \brief Concept that defines the legal set of types that can be used for CVar values.
*
* Valid types cannot be cv-qualified and must be basic primitive types (int, float, bool),
* strings, enums of the basic primitives, or explicitly-enabled structured settings.
* strings, or enums of the basic primitives.
*/
template <typename T>
concept ConfigValue =
@@ -165,8 +154,7 @@ concept ConfigValue =
|| std::is_same_v<T, f32>
|| std::is_same_v<T, f64>
|| std::is_same_v<T, std::string>
|| (std::is_enum_v<T> && ConfigValueInteger<std::underlying_type_t<T>>)
|| ConfigValueTraits<T>::enabled);
|| (std::is_enum_v<T> && ConfigValueInteger<std::underlying_type_t<T>>));
template <ConfigValue T>
const ConfigImplBase* GetConfigImpl();
@@ -197,12 +185,10 @@ public:
* @param arg Arguments to forward to construct the default value.
*/
template <typename... Args>
ConfigVar(std::string name, Args&&... arg)
: ConfigVarBase(std::move(name), GetConfigImpl<T>()), defaultValue(std::forward<Args>(arg)...),
ConfigVar(const char* name, Args&&... arg)
: ConfigVarBase(name, GetConfigImpl<T>()), defaultValue(std::forward<Args>(arg)...),
value(), overrideValue() {}
ConfigVar(ConfigVar const&) = delete;
/**
* \brief Get the current value of the CVar.
*
+9 -25
View File
@@ -7,23 +7,20 @@
#include <dolphin/gx/GXExtra.h>
#include "tracy/Tracy.hpp"
#if DUSK_GFX_DEBUG_GROUPS
#define GX_DEBUG_GROUP(name, ...) \
do { \
GXPushDebugGroup(#name); \
name(__VA_ARGS__); \
GXPopDebugGroup(); \
} while (0)
#else
#define GX_DEBUG_GROUP(name, ...) name(__VA_ARGS__)
#endif
#ifdef TARGET_PC
class GXTexObjRAII : public GXTexObj {
public:
GXTexObjRAII() : GXTexObj() {}
~GXTexObjRAII();
void reset();
~GXTexObjRAII() { GXDestroyTexObj(this); }
void reset() { GXDestroyTexObj(this); }
GXTexObjRAII(const GXTexObjRAII&) = delete;
GXTexObjRAII& operator=(const GXTexObjRAII&) = delete;
@@ -42,30 +39,17 @@ public:
static_assert(sizeof(GXTexObjRAII) == sizeof(GXTexObj),
"GXTexObjRAII should have the same size as GXTexObj");
typedef GXTexObjRAII TGXTexObj;
class GXTlutObjRAII : public GXTlutObj {
public:
GXTlutObjRAII() : GXTlutObj() {}
~GXTlutObjRAII() { GXDestroyTlutObj(this); }
void reset() { GXDestroyTlutObj(this); }
GXTlutObjRAII(const GXTlutObjRAII&) = delete;
GXTlutObjRAII& operator=(const GXTlutObjRAII&) = delete;
GXTlutObjRAII(GXTlutObjRAII&&) = delete;
GXTlutObjRAII& operator=(GXTlutObjRAII&&) = delete;
};
static_assert(sizeof(GXTlutObjRAII) == sizeof(GXTlutObj),
"GXTlutObjRAII should have the same size as GXTlutObj");
typedef GXTlutObjRAII TGXTlutObj;
#else
typedef GXTexObj TGXTexObj;
typedef GXTlutObj TGXTlutObj;
#endif
struct GXScopedDebugGroup {
explicit GXScopedDebugGroup(const char* text);
~GXScopedDebugGroup();
explicit GXScopedDebugGroup(const char* text) {
GXPushDebugGroup(text);
}
~GXScopedDebugGroup() {
GXPopDebugGroup();
}
};
#define GX_AND_TRACY_SCOPED(name) GXScopedDebugGroup scope(name); ZoneScopedN(name);
+4 -1
View File
@@ -1,4 +1,5 @@
#pragma once
#ifndef DUSK_GYRO_H
#define DUSK_GYRO_H
namespace dusk::gyro {
void read(float dt);
@@ -13,3 +14,5 @@ bool get_sensor_keep_alive();
void set_sensor_keep_alive(bool value);
bool rollgoal_gyro_enabled();
} // namespace dusk::gyro
#endif
-122
View File
@@ -1,122 +0,0 @@
#pragma once
#include <cstring>
#include <memory>
#include <type_traits>
#include "dusk/mod_api.h"
namespace dusk {
inline DuskModAPI* g_api = nullptr;
inline void init(DuskModAPI* api) { g_api = api; }
template <class T>
T arg(void* args_raw, int n) noexcept {
void** a = static_cast<void**>(args_raw);
return *static_cast<std::add_pointer_t<std::remove_reference_t<T>>>(a[n]);
}
template <class T>
std::remove_reference_t<T>& argRef(void* args_raw, int n) noexcept {
void** a = static_cast<void**>(args_raw);
return *static_cast<std::add_pointer_t<std::remove_reference_t<T>>>(a[n]);
}
template <class F>
void* mfpAddr(F fn) noexcept {
void* p = nullptr;
static_assert(sizeof(fn) >= sizeof(void*), "unexpected MFP size");
std::memcpy(&p, &fn, sizeof(void*));
return p;
}
template <auto MFP, class R, class Self, class Orig, class... A>
struct HookEntryBase {
static inline Orig g_orig = nullptr;
static R trampoline(Self self, A... args) {
void* ptrs[] = {static_cast<void*>(std::addressof(self)), static_cast<void*>(std::addressof(args))...};
if constexpr (std::is_void_v<R>) {
const bool cancel = g_api->hook_dispatch_pre(mfpAddr(MFP), static_cast<void*>(ptrs), nullptr);
if (!cancel) g_orig(self, args...);
g_api->hook_dispatch_post(mfpAddr(MFP), static_cast<void*>(ptrs), nullptr);
} else {
R result{};
const bool cancel = g_api->hook_dispatch_pre(mfpAddr(MFP), static_cast<void*>(ptrs), static_cast<void*>(std::addressof(result)));
if (!cancel) result = g_orig(self, args...);
g_api->hook_dispatch_post(mfpAddr(MFP), static_cast<void*>(ptrs), static_cast<void*>(std::addressof(result)));
return result;
}
}
};
template <auto FP, class R, class Orig, class... A>
struct HookEntryFreeBase {
static inline Orig g_orig = nullptr;
static R trampoline(A... args) {
if constexpr (sizeof...(A) == 0) {
if constexpr (std::is_void_v<R>) {
const bool cancel = g_api->hook_dispatch_pre(mfpAddr(FP), nullptr, nullptr);
if (!cancel) g_orig(args...);
g_api->hook_dispatch_post(mfpAddr(FP), nullptr, nullptr);
} else {
R result{};
const bool cancel = g_api->hook_dispatch_pre(mfpAddr(FP), nullptr, static_cast<void*>(std::addressof(result)));
if (!cancel) result = g_orig(args...);
g_api->hook_dispatch_post(mfpAddr(FP), nullptr, static_cast<void*>(std::addressof(result)));
return result;
}
} else {
void* ptrs[] = {static_cast<void*>(std::addressof(args))...};
if constexpr (std::is_void_v<R>) {
const bool cancel = g_api->hook_dispatch_pre(mfpAddr(FP), static_cast<void*>(ptrs), nullptr);
if (!cancel) g_orig(args...);
g_api->hook_dispatch_post(mfpAddr(FP), static_cast<void*>(ptrs), nullptr);
} else {
R result{};
const bool cancel = g_api->hook_dispatch_pre(mfpAddr(FP), static_cast<void*>(ptrs), static_cast<void*>(std::addressof(result)));
if (!cancel) result = g_orig(args...);
g_api->hook_dispatch_post(mfpAddr(FP), static_cast<void*>(ptrs), static_cast<void*>(std::addressof(result)));
return result;
}
}
}
};
template <auto MFP>
struct HookEntry;
template <class C, class R, class... A, R (C::*MFP)(A...)>
struct HookEntry<MFP> : HookEntryBase<MFP, R, C*, R(*)(C*, A...), A...> {};
template <class C, class R, class... A, R (C::*MFP)(A...) const>
struct HookEntry<MFP> : HookEntryBase<MFP, R, const C*, R(*)(const C*, A...), A...> {};
template <class R, class... A, R (*FP)(A...)>
struct HookEntry<FP> : HookEntryFreeBase<FP, R, R(*)(A...), A...> {};
template <auto MFP>
void hookAddPre(int32_t (*fn)(void* args)) {
using E = HookEntry<MFP>;
g_api->hook_install(mfpAddr(MFP), reinterpret_cast<void*>(E::trampoline),
reinterpret_cast<void**>(&E::g_orig));
g_api->hook_pre(mfpAddr(MFP), fn);
}
template <auto MFP>
void hookAddPost(void (*fn)(void* args, void* retval)) {
using E = HookEntry<MFP>;
g_api->hook_install(mfpAddr(MFP), reinterpret_cast<void*>(E::trampoline),
reinterpret_cast<void**>(&E::g_orig));
g_api->hook_post(mfpAddr(MFP), fn);
}
template <auto MFP>
void hookSetReplace(void (*fn)(void* args, void* retval)) {
using E = HookEntry<MFP>;
g_api->hook_install(mfpAddr(MFP), reinterpret_cast<void*>(E::trampoline),
reinterpret_cast<void**>(&E::g_orig));
g_api->hook_replace(mfpAddr(MFP), fn);
}
} // namespace dusk
-18
View File
@@ -1,18 +0,0 @@
#pragma once
#include <cstdint>
namespace dusk {
void hookInstallByAddr(void* fn_addr, void* tramp_fn, void** orig_store);
void hookRegisterPre (void* fn_addr, void* mod, int32_t (*fn)(void* args));
void hookRegisterPost(void* fn_addr, void* mod, const char* mod_name, void (*fn)(void* args, void* retval));
bool hookSetReplace (void* fn_addr, void* mod, const char* mod_name, void (*fn)(void* args, void* retval));
bool hookDispatchPre (void* fn_addr, void* args, void* retval);
void hookDispatchPost(void* fn_addr, void* args, void* retval);
void hookClearMod(void* mod);
} // namespace dusk
-65
View File
@@ -1,65 +0,0 @@
#pragma once
#include "dolphin/types.h"
class CPaneMgr;
namespace dusk::menu_pointer {
using TargetId = u16;
constexpr TargetId InvalidTarget = 0xffff;
enum class Context {
None,
FileSelect,
Save,
ItemWheel,
Collection,
Options,
Dialog,
};
enum class Phase {
Move,
Press,
Release,
Cancel,
};
struct State {
f32 x = 0.0f;
f32 y = 0.0f;
bool valid = false;
bool down = false;
bool pressed = false;
bool released = false;
bool clicked = false;
bool touch = false;
};
void begin_game_frame() noexcept;
void end_game_frame() noexcept;
void begin_context(Context context) noexcept;
bool handle_fallthrough_pointer(f32 x, f32 y, Phase phase, bool touch, s32 mouseButton = -1) noexcept;
bool active() noexcept;
bool enabled() noexcept;
bool mouse_capture_active() noexcept;
const State& state() noexcept;
void set_hover_target(TargetId target) noexcept;
bool consume_click() noexcept;
bool peek_click() noexcept;
void set_dialog_choice(u8 choice, bool clicked) noexcept;
bool get_dialog_choice(u8& choice) noexcept;
bool consume_dialog_click(u8& choice) noexcept;
void defer_activation(Context context, TargetId target) noexcept;
bool consume_deferred_activation(Context context, TargetId target) noexcept;
void clear_deferred_activation(Context context) noexcept;
u32 suppressed_pad_buttons(u32 port) noexcept;
void finish_pad_suppression_read(u32 port) noexcept;
bool hit_rect(f32 left, f32 top, f32 right, f32 bottom, f32 padding = 0.0f) noexcept;
bool hit_pane(CPaneMgr* pane, f32 padding = 0.0f) noexcept;
bool hit_pane(J2DPane* pane, f32 padding = 0.0f) noexcept;
} // namespace dusk::menu_pointer
-65
View File
@@ -1,65 +0,0 @@
#pragma once
#include <cstddef>
#include <cstdint>
#if defined(_WIN32)
#define DUSK_MOD_EXPORT __declspec(dllexport)
#else
#define DUSK_MOD_EXPORT __attribute__((visibility("default")))
#endif
#define DUSK_MOD_API_VERSION 1
typedef void* DuskPanelHandle;
typedef void* DuskElemHandle;
// Place this once at file scope in your mod to declare the minimum API version required.
// The loader will refuse to initialize the mod if the engine's API version is older.
#define DUSK_REQUIRE_API_VERSION \
extern "C" DUSK_MOD_EXPORT uint32_t mod_api_version = DUSK_MOD_API_VERSION;
struct DuskModAPIv1 {
uint32_t api_version;
const char* mod_dir;
void (*log_info)(const char* fmt, ...);
void (*log_warn)(const char* fmt, ...);
void (*log_error)(const char* fmt, ...);
void* (*load_resource)(const char* relative_path, size_t* out_size);
void (*free_resource)(void* data);
void (*register_tab_content)(
void (*build_fn)(DuskPanelHandle panel, void* userdata), void* userdata);
void (*register_tab_update)(void (*update_fn)(void* userdata), void* userdata);
void (*panel_add_section)(DuskPanelHandle panel, const char* text);
void (*panel_add_button)(
DuskPanelHandle panel, const char* label, void (*cb)(void* userdata), void* userdata);
DuskElemHandle (*panel_add_badge_row)(DuskPanelHandle panel, const char* label, int ok);
DuskElemHandle (*panel_add_dyn_text)(DuskPanelHandle panel, const char* text);
DuskElemHandle (*panel_add_progress)(DuskPanelHandle panel, float value);
void (*elem_set_badge)(DuskElemHandle elem, int ok);
void (*elem_set_text)(DuskElemHandle elem, const char* text);
void (*elem_set_progress)(DuskElemHandle elem, float value);
void (*hook_install)(void* fn_addr, void* tramp_fn, void** orig_store);
void (*hook_pre)(void* fn_addr, int32_t (*fn)(void* args));
void (*hook_post)(void* fn_addr, void (*fn)(void* args, void* retval));
void (*hook_replace)(void* fn_addr, void (*fn)(void* args, void* retval));
bool (*hook_dispatch_pre)(void* fn_addr, void* args, void* retval);
void (*hook_dispatch_post)(void* fn_addr, void* args, void* retval);
void (*service_publish)(const char* name, void* ptr);
void* (*service_get)(const char* name);
};
using DuskModAPI = DuskModAPIv1;
extern "C" {
void mod_init(DuskModAPI* api);
void mod_tick(DuskModAPI* api);
}
-134
View File
@@ -1,134 +0,0 @@
#pragma once
#include <filesystem>
#include <string>
#include <vector>
#include <ranges>
#include "dusk/mod_api.h"
#include "dusk/config_var.hpp"
namespace dusk::modding {
class ModBundle;
class NativeModule;
}
namespace dusk {
struct RmlTabContentCallback {
void (*build_fn)(void* panel, void* userdata);
void* userdata;
};
struct RmlTabUpdateCallback {
void (*update_fn)(void* userdata);
void* userdata;
};
struct ModMetadata {
std::string id;
std::string name;
std::string version;
std::string author;
std::string description;
bool hasCode;
};
struct NativeMod {
std::unique_ptr<modding::NativeModule> handle;
DuskModAPI api{};
using FnInit = void (*)(DuskModAPI*);
using FnTick = void (*)(DuskModAPI*);
using FnCleanup = void (*)(DuskModAPI*);
FnInit fn_init = nullptr;
FnTick fn_tick = nullptr;
FnCleanup fn_cleanup = nullptr;
};
enum class NativeModStatus : u8 {
/**
* Mod does not have native code included.
*/
None,
/**
* Native code mod loaded successfully.
*
* Note that this only indicates load status of the native library. If the native lib throws in
* its init function, it will still be disabled!
*/
Loaded,
/**
* This build was compiled without native mod support!
*/
BuildDisabled,
/**
* Mod does not have a native library suitable for this build's platform.
*/
ModMissingPlatform,
/**
* Mod is built for a different API version than this build of the game.
*/
ApiVersionMismatch,
/**
* Unknown error loading the native mod.
*/
Unknown,
};
struct LoadedMod {
ModMetadata metadata;
std::string mod_path;
std::string dir;
std::unique_ptr<ConfigVar<bool>> cvarIsEnabled;
bool active = false;
bool load_failed = false;
NativeModStatus native_status = NativeModStatus::None;
std::unique_ptr<NativeMod> native;
std::unique_ptr<modding::ModBundle> bundle;
std::vector<RmlTabContentCallback> tab_content;
std::vector<RmlTabUpdateCallback> tab_updates;
};
class ModLoader {
public:
static ModLoader& instance();
void setModsDir(std::filesystem::path dir) { m_modsDir = std::move(dir); }
void init();
void tick();
void shutdown();
[[nodiscard]] auto mods() const {
return m_mods | std::views::transform([](const auto& m) -> LoadedMod& { return *m; });
}
[[nodiscard]] auto active_mods() const {
return mods() | std::views::filter([](const auto& m) { return m.active; });
}
private:
std::vector<std::unique_ptr<LoadedMod>> m_mods;
std::filesystem::path m_modsDir;
bool m_initialized = false;
void tryLoadDusk(const std::filesystem::path& modPath, bool fromDir);
void tryLoadNativeMod(LoadedMod& mod);
void buildAPI(LoadedMod& mod);
void initOverlayFiles();
};
using ModIndex = std::ranges::range_difference_t<decltype(std::declval<ModLoader>().mods())>;
} // namespace dusk
-28
View File
@@ -1,28 +0,0 @@
#pragma once
#include "f_op/f_op_actor_mng.h"
#include "f_pc/f_pc_layer.h"
#include "f_pc/f_pc_manager.h"
#include "f_pc/f_pc_node.h"
#include "m_Do/m_Do_controller_pad.h"
// Remove a button from this frame's trigger state so the game won't see it
// Call after detecting a combo in mod_tick to prevent double-processing
inline void consumeInput(u32 pad, u32 buttonMask) {
mDoCPd_c::getCpadInfo(pad).mPressedButtonFlags &= ~buttonMask;
}
// Spawn an actor in the play scene layer
// calling fopAcM_create directly outside game simulation context creates the actor in the wrong
// layer, corrupting its first-frame rendering setup
inline fpc_ProcID fopAcM_createInPlayScene(s16 proc_name, u32 params, const cXyz* pos, int room_no,
const csXyz* angle, const cXyz* scale, s8 argument) {
layer_class* savedLayer = fpcLy_CurrentLayer();
base_process_class* playScene = fpcM_SearchByName(fpcNm_PLAY_SCENE_e);
if (playScene != nullptr) {
fpcLy_SetCurrentLayer(&((process_node_class*)playScene)->layer);
}
fpc_ProcID result = fopAcM_create(proc_name, params, pos, room_no, angle, scale, argument);
fpcLy_SetCurrentLayer(savedLayer);
return result;
}
-12
View File
@@ -1,12 +0,0 @@
#pragma once
#include <SDL3/SDL_events.h>
namespace dusk::mouse {
void read();
void getAimDeltas(float& out_yaw, float& out_pitch);
void getCameraDeltas(float& out_yaw, float& out_pitch);
void handle_event(const SDL_Event& event) noexcept;
void onFocusLost();
void onFocusGained();
} // namespace dusk::mouse
+19 -40
View File
@@ -1,9 +1,9 @@
#pragma once
#ifndef DUSK_CONFIG_H
#define DUSK_CONFIG_H
#include <array>
#include "dusk/config_var.hpp"
#include "dusk/ui/controls.hpp"
namespace dusk {
@@ -40,6 +40,11 @@ enum class DiscVerificationState : u8 {
HashMismatch,
};
enum class GyroMode : u8 {
Sensor = 0,
Mouse = 1,
};
enum class FrameInterpMode : u8 {
Off = 0,
Capped = 1,
@@ -52,14 +57,6 @@ enum class MenuScaling : u8 {
Dusklight = 2,
};
enum class MagicArmorMode : u8 {
NORMAL = 0,
ON_DAMAGE = 1,
DOUBLE_DEFENSE = 2,
INVINCIBLE = 3,
COSMETIC = 4,
};
namespace config {
template <>
struct ConfigEnumRange<BloomMode> {
@@ -91,6 +88,12 @@ struct ConfigEnumRange<DiscVerificationState> {
static constexpr auto max = DiscVerificationState::HashMismatch;
};
template <>
struct ConfigEnumRange<GyroMode> {
static constexpr auto min = GyroMode::Sensor;
static constexpr auto max = GyroMode::Mouse;
};
template <>
struct ConfigEnumRange<FrameInterpMode> {
static constexpr auto min = FrameInterpMode::Off;
@@ -102,17 +105,6 @@ struct ConfigEnumRange<MenuScaling> {
static constexpr auto min = MenuScaling::GameCube;
static constexpr auto max = MenuScaling::Dusklight;
};
template <>
struct ConfigEnumRange<MagicArmorMode> {
static constexpr auto min = MagicArmorMode::NORMAL;
static constexpr auto max = MagicArmorMode::COSMETIC;
};
template <>
struct ConfigValueTraits<ui::ControlLayout> {
static constexpr bool enabled = true;
};
} // namespace config
// Persistent user settings
@@ -128,9 +120,6 @@ struct UserSettings {
ConfigVar<bool> enableFpsOverlay;
ConfigVar<int> fpsOverlayCorner;
ConfigVar<int> maxFrameRate;
ConfigVar<bool> rememberWindowSize;
ConfigVar<int> lastWindowWidth;
ConfigVar<int> lastWindowHeight;
} video;
struct {
@@ -164,7 +153,6 @@ struct UserSettings {
ConfigVar<bool> noMissClimbing;
ConfigVar<bool> fastTears;
ConfigVar<bool> no2ndFishForCat;
ConfigVar<bool> buttonFishing;
ConfigVar<bool> instantSaves;
ConfigVar<bool> instantText;
ConfigVar<bool> sunsSong;
@@ -174,7 +162,6 @@ struct UserSettings {
// Preferences
ConfigVar<bool> enableMirrorMode;
ConfigVar<bool> minimalHUD;
ConfigVar<float> hudScale;
ConfigVar<bool> pauseOnFocusLost;
ConfigVar<bool> enableLinkDollRotation;
ConfigVar<bool> enableAchievementToasts;
@@ -200,6 +187,7 @@ struct UserSettings {
ConfigVar<bool> midnasLamentNonStop;
// Input
ConfigVar<GyroMode> gyroMode;
ConfigVar<bool> enableGyroAim;
ConfigVar<bool> enableGyroRollgoal;
ConfigVar<float> gyroSensitivityX;
@@ -209,15 +197,7 @@ struct UserSettings {
ConfigVar<float> gyroDeadband;
ConfigVar<bool> gyroInvertPitch;
ConfigVar<bool> gyroInvertYaw;
ConfigVar<bool> enableMouseCamera;
ConfigVar<bool> enableMouseAim;
ConfigVar<float> mouseAimSensitivity;
ConfigVar<float> mouseCameraSensitivity;
ConfigVar<bool> invertMouseY;
ConfigVar<bool> freeCamera;
ConfigVar<bool> enableTouchControls;
ConfigVar<bool> enableMenuPointer;
ConfigVar<ui::ControlLayout> touchControlsLayout;
ConfigVar<bool> invertCameraXAxis;
ConfigVar<bool> invertCameraYAxis;
ConfigVar<bool> invertFirstPersonXAxis;
@@ -226,8 +206,6 @@ struct UserSettings {
ConfigVar<bool> invertAirSwimY;
ConfigVar<float> freeCameraXSensitivity;
ConfigVar<float> freeCameraYSensitivity;
ConfigVar<float> touchCameraXSensitivity;
ConfigVar<float> touchCameraYSensitivity;
ConfigVar<bool> debugFlyCam;
ConfigVar<bool> debugFlyCamLockEvents;
ConfigVar<bool> allowBackgroundInput;
@@ -250,7 +228,7 @@ struct UserSettings {
ConfigVar<bool> canTransformAnywhere;
ConfigVar<bool> fastRoll;
ConfigVar<bool> fastSpinner;
ConfigVar<MagicArmorMode> armorRupeeDrain;
ConfigVar<bool> freeMagicArmor;
ConfigVar<bool> invincibleEnemies;
// Technical
@@ -275,6 +253,7 @@ struct UserSettings {
ConfigVar<DiscVerificationState> isoVerification;
ConfigVar<std::string> graphicsBackend;
ConfigVar<bool> skipPreLaunchUI;
ConfigVar<bool> showPipelineCompilation;
ConfigVar<bool> wasPresetChosen;
ConfigVar<bool> checkForUpdates;
ConfigVar<int> cardFileType;
@@ -285,8 +264,6 @@ struct UserSettings {
struct {
std::array<ActionBindConfigVar, 4> firstPersonCamera;
std::array<ActionBindConfigVar, 4> callMidna;
std::array<ActionBindConfigVar, 4> openMapScreen;
std::array<ActionBindConfigVar, 4> toggleMinimap;
std::array<ActionBindConfigVar, 4> openDusklightMenu;
std::array<ActionBindConfigVar, 4> turboSpeedButton;
} actionBindings;
@@ -318,4 +295,6 @@ struct TransientSettings {
TransientSettings& getTransientSettings();
} // namespace dusk
}
#endif // DUSK_CONFIG_H
-12
View File
@@ -1,12 +0,0 @@
#pragma once
namespace dusk::touch_camera {
constexpr float YAW_DEGREES_PER_DP = 0.34f;
constexpr float PITCH_DEGREES_PER_DP = 0.22f;
void add_delta(float yaw_dp, float pitch_dp) noexcept;
bool consume_delta(float& yaw_dp, float& pitch_dp) noexcept;
void clear() noexcept;
} // namespace dusk::touch_camera
-13
View File
@@ -114,19 +114,6 @@ inline int __builtin_clz(unsigned int v) {
#endif
// Data symbols in dusk.dll need dllimport on the mod side
// DUSK_BUILDING_GAME is defined for the game build so the same headers work in both.
#if defined(TARGET_PC) && defined(_WIN32) && !defined(DUSK_BUILDING_GAME)
# define DUSK_GAME_EXTERN extern __declspec(dllimport)
# define DUSK_GAME_DATA __declspec(dllimport)
#elif defined(TARGET_PC) && defined(_WIN32) && defined(DUSK_BUILDING_GAME)
# define DUSK_GAME_EXTERN extern __declspec(dllexport)
# define DUSK_GAME_DATA __declspec(dllexport)
#else
# define DUSK_GAME_EXTERN extern
# define DUSK_GAME_DATA
#endif
#define FAST_DIV(x, n) (x >> (n / 2))
#define SQUARE(x) ((x) * (x))
+1 -1
View File
@@ -33,7 +33,7 @@ public:
static void onBgmSet() { mBgmSet = true; }
static void offBgmSet() { mBgmSet = false; }
static DUSK_GAME_DATA u8 mInitFlag;
static u8 mInitFlag;
static u8 mResetFlag;
static u8 mBgmSet;
};
+1 -2
View File
@@ -4,7 +4,6 @@
#include "JSystem/JUtility/JUTGamePad.h"
#include "SSystem/SComponent/c_API_controller_pad.h"
#include "dusk/settings.h"
#include "global.h"
// Controller Ports 1 - 4
enum { PAD_1, PAD_2, PAD_3, PAD_4 };
@@ -95,7 +94,7 @@ public:
static void stopMotorWaveHard(u32 pad) { return m_gamePad[pad]->stopMotorWaveHard(); }
static JUTGamePad* m_gamePad[4];
static DUSK_GAME_DATA interface_of_controller_pad m_cpadInfo[4];
static interface_of_controller_pad m_cpadInfo[4];
static interface_of_controller_pad m_debugCpadInfo[4];
};
+1 -1
View File
@@ -371,7 +371,6 @@ public:
static int m_height;
static f32 m_heightF;
static f32 m_widthF;
#endif
#if TARGET_PC
static f32 m_safeMinXF;
@@ -381,6 +380,7 @@ public:
static f32 m_safeWidthF;
static f32 m_safeHeightF;
#endif
#endif
};
#endif /* M_DO_M_DO_GRAPHIC_H */
+1 -1
View File
@@ -44,7 +44,7 @@ struct mDoLib_clipper {
void mDoLib_project(Vec* src, Vec* dst);
u32 mDoLib_setResTimgObj(ResTIMG const* res, TGXTexObj* o_texObj, u32 tlut_name,
TGXTlutObj* o_tlutObj);
GXTlutObj* o_tlutObj);
void mDoLib_pos2camera(Vec* src, Vec* dst);
#if PLATFORM_WII
+16 -41
View File
@@ -952,70 +952,45 @@ if(DEFINED APPLE_TARGET_TRIPLE)
set(APPLE_TARGET_TRIPLE_FLAG "-target ${APPLE_TARGET_TRIPLE}")
endif()
function(ios_toolchain_set_cached_flags variable description)
set(clean_flags "${${variable}}")
foreach(toolchain_flag IN LISTS ARGN)
if(NOT "${toolchain_flag}" STREQUAL "")
string(REPLACE "${toolchain_flag}" "" clean_flags "${clean_flags}")
endif()
endforeach()
string(REGEX REPLACE "[ \t]+" " " clean_flags "${clean_flags}")
string(STRIP "${clean_flags}" clean_flags)
set(final_flags "")
foreach(toolchain_flag IN LISTS ARGN)
if(NOT "${toolchain_flag}" STREQUAL "")
string(APPEND final_flags " ${toolchain_flag}")
endif()
endforeach()
if(NOT "${clean_flags}" STREQUAL "")
string(APPEND final_flags " ${clean_flags}")
endif()
string(REGEX REPLACE "[ \t]+" " " final_flags "${final_flags}")
string(STRIP "${final_flags}" final_flags)
set(${variable} "${final_flags}" CACHE INTERNAL "${description}")
endfunction()
#Check if Xcode generator is used since that will handle these flags automagically
if(CMAKE_GENERATOR MATCHES "Xcode")
message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as the generator. Modifying the Xcode build-settings directly instead.")
else()
ios_toolchain_set_cached_flags(CMAKE_C_FLAGS "Flags used by the compiler during all C build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${OBJC_LEGACY_VARS}" "${BITCODE}" "${VISIBILITY}")
set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_C_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all C build types.")
set(CMAKE_C_FLAGS_DEBUG "-O0 -g ${CMAKE_C_FLAGS_DEBUG}")
set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_C_FLAGS_MINSIZEREL}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_C_FLAGS_RELEASE}")
ios_toolchain_set_cached_flags(CMAKE_CXX_FLAGS "Flags used by the compiler during all CXX build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${OBJC_LEGACY_VARS}" "${BITCODE}" "${VISIBILITY}")
set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_CXX_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all CXX build types.")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g ${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_CXX_FLAGS_MINSIZEREL}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_CXX_FLAGS_RELEASE}")
if(NAMED_LANGUAGE_SUPPORT_INT)
ios_toolchain_set_cached_flags(CMAKE_OBJC_FLAGS "Flags used by the compiler during all OBJC build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${BITCODE}" "${VISIBILITY}" "${FOBJC_ARC}" "${OBJC_VARS}")
set(CMAKE_OBJC_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJC_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all OBJC build types.")
set(CMAKE_OBJC_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJC_FLAGS_DEBUG}")
set(CMAKE_OBJC_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJC_FLAGS_MINSIZEREL}")
set(CMAKE_OBJC_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJC_FLAGS_RELWITHDEBINFO}")
set(CMAKE_OBJC_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJC_FLAGS_RELEASE}")
ios_toolchain_set_cached_flags(CMAKE_OBJCXX_FLAGS "Flags used by the compiler during all OBJCXX build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${BITCODE}" "${VISIBILITY}" "${FOBJC_ARC}" "${OBJC_VARS}")
set(CMAKE_OBJCXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJCXX_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all OBJCXX build types.")
set(CMAKE_OBJCXX_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJCXX_FLAGS_DEBUG}")
set(CMAKE_OBJCXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJCXX_FLAGS_MINSIZEREL}")
set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_OBJCXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}")
endif()
ios_toolchain_set_cached_flags(CMAKE_C_LINK_FLAGS "Flags used by the compiler for all C link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
ios_toolchain_set_cached_flags(CMAKE_CXX_LINK_FLAGS "Flags used by the compiler for all CXX link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all C link types.")
set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all CXX link types.")
if(NAMED_LANGUAGE_SUPPORT_INT)
ios_toolchain_set_cached_flags(CMAKE_OBJC_LINK_FLAGS "Flags used by the compiler for all OBJC link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
ios_toolchain_set_cached_flags(CMAKE_OBJCXX_LINK_FLAGS "Flags used by the compiler for all OBJCXX link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
set(CMAKE_OBJC_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJC_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all OBJC link types.")
set(CMAKE_OBJCXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJCXX_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all OBJCXX link types.")
endif()
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp" CACHE INTERNAL
"Flags used by the compiler for all ASM build types.")
@@ -212,9 +212,6 @@ public:
void setCornerColor(JUtility::TColor c0) {
setCornerColor(c0, c0, c0, c0);
}
#if TARGET_PC
JUtility::TColor corner(size_t index) const { return mCornerColor[index]; }
#endif
protected:
/* 0x100 */ JUTTexture* mTexture[2];
@@ -1,7 +1,6 @@
#ifndef J3DSHAPEDRAW_H
#define J3DSHAPEDRAW_H
#include <gx.h>
#include <types.h>
/**
@@ -13,9 +12,6 @@ public:
u32 countVertex(u32);
void addTexMtxIndexInDL(u32, u32, u32);
J3DShapeDraw(u8 const*, u32);
#if TARGET_PC
J3DShapeDraw(u8 const*, u32, const GXVtxDescList*);
#endif
void draw() const;
virtual ~J3DShapeDraw();
@@ -4,7 +4,6 @@
#include <types.h>
#include <cmath>
#include <utility>
#include "global.h"
#ifdef __cplusplus
extern "C" {
@@ -142,9 +141,9 @@ struct TAsinAcosTable {
}
};
DUSK_GAME_EXTERN TSinCosTable<13, f32> sincosTable_;
DUSK_GAME_EXTERN TAtanTable<1024, f32> atanTable_;
DUSK_GAME_EXTERN TAsinAcosTable<1024, f32> asinAcosTable_;
extern TSinCosTable<13, f32> sincosTable_;
extern TAtanTable<1024, f32> atanTable_;
extern TAsinAcosTable<1024, f32> asinAcosTable_;
inline f32 acosDegree(f32 x) {
return asinAcosTable_.acosDegree(x);
@@ -3,20 +3,6 @@
#include <gx.h>
#if TARGET_PC
#include <mtx.h>
struct ParticleDrawCtx {
bool batch; // off = immediate mode
bool useTexMtx; // UVs transformed by texMtx
bool useClr0; // prm color in GX_VA_CLR0
bool useClr1; // env color in GX_VA_CLR1
Mtx texMtx;
GXColor clr0;
GXColor clr1;
};
#endif
struct JPAEmitterWorkData;
class JPABaseParticle;
class JKRHeap;
@@ -89,9 +75,6 @@ public:
const GXTevColorArg* getTevColorArg() const { return st_ca[(pBsd->mFlags >> 0x0F) & 0x07]; }
const GXTevAlphaArg* getTevAlphaArg() const { return st_aa[(pBsd->mFlags >> 0x12) & 0x01]; }
#if TARGET_PC
u32 getTevColorArgSel() const { return (pBsd->mFlags >> 0x0F) & 0x07; }
#endif
u32 getType() const { return (pBsd->mFlags >> 0) & 0x0F; }
u32 getDirType() const { return (pBsd->mFlags >> 4) & 0x07; }
@@ -203,34 +186,26 @@ void JPARegistPrm(JPAEmitterWorkData*);
void JPARegistEnv(JPAEmitterWorkData*);
void JPARegistPrmEnv(JPAEmitterWorkData*);
#if TARGET_PC
#define JPA_DRAW_PARTICLE_ARGS JPAEmitterWorkData*, JPABaseParticle*, ParticleDrawCtx*
#else
#define JPA_DRAW_PARTICLE_ARGS JPAEmitterWorkData*, JPABaseParticle*
#endif
void JPADrawPoint(JPA_DRAW_PARTICLE_ARGS);
void JPADrawLine(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotDirection(JPA_DRAW_PARTICLE_ARGS);
void JPADrawDirection(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotation(JPA_DRAW_PARTICLE_ARGS);
void JPADrawDBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotYBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawYBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawParticleCallBack(JPA_DRAW_PARTICLE_ARGS);
void JPALoadTexAnm(JPA_DRAW_PARTICLE_ARGS);
void JPASetPointSize(JPA_DRAW_PARTICLE_ARGS);
void JPASetLineWidth(JPA_DRAW_PARTICLE_ARGS);
void JPALoadCalcTexCrdMtxAnm(JPA_DRAW_PARTICLE_ARGS);
void JPARegistAlpha(JPA_DRAW_PARTICLE_ARGS);
void JPARegistEnv(JPA_DRAW_PARTICLE_ARGS);
void JPARegistAlphaEnv(JPA_DRAW_PARTICLE_ARGS);
void JPARegistPrmAlpha(JPA_DRAW_PARTICLE_ARGS);
void JPARegistPrmAlphaEnv(JPA_DRAW_PARTICLE_ARGS);
#undef JPA_DRAW_PARTICLE_ARGS
void JPADrawPoint(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawLine(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotDirection(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawDirection(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotation(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawDBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotYBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawYBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawParticleCallBack(JPAEmitterWorkData*, JPABaseParticle*);
void JPALoadTexAnm(JPAEmitterWorkData*, JPABaseParticle*);
void JPASetPointSize(JPAEmitterWorkData*, JPABaseParticle*);
void JPASetLineWidth(JPAEmitterWorkData*, JPABaseParticle*);
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistAlpha(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistEnv(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistPrmAlpha(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistPrmAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
#if TARGET_PC
void JPAInterpBillboard(JPAEmitterWorkData*, JPABaseParticle*);
@@ -17,10 +17,6 @@ class JPADynamicsBlock;
class JPAFieldBlock;
class JPAKeyBlock;
#if TARGET_PC
struct ParticleDrawCtx;
#endif
/**
* @ingroup jsystem-jparticle
*
@@ -54,19 +50,13 @@ public:
public:
typedef void (*EmitterFunc)(JPAEmitterWorkData*);
typedef void (*ParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*);
#if TARGET_PC
typedef void (*DrawParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*,
ParticleDrawCtx*);
#else
typedef ParticleFunc DrawParticleFunc;
#endif
/* 0x00 */ EmitterFunc* mpCalcEmitterFuncList;
/* 0x04 */ EmitterFunc* mpDrawEmitterFuncList;
/* 0x08 */ EmitterFunc* mpDrawEmitterChildFuncList;
/* 0x0C */ ParticleFunc* mpCalcParticleFuncList;
/* 0x10 */ DrawParticleFunc* mpDrawParticleFuncList;
/* 0x10 */ ParticleFunc* mpDrawParticleFuncList;
/* 0x14 */ ParticleFunc* mpCalcParticleChildFuncList;
/* 0x18 */ DrawParticleFunc* mpDrawParticleChildFuncList;
/* 0x18 */ ParticleFunc* mpDrawParticleChildFuncList;
/* 0x1C */ JPABaseShape* pBsp;
/* 0x20 */ JPAExtraShape* pEsp;
@@ -87,20 +77,6 @@ public:
/* 0x45 */ u8 mpDrawParticleFuncListNum;
/* 0x46 */ u8 mpCalcParticleChildFuncListNum;
/* 0x47 */ u8 mpDrawParticleChildFuncListNum;
#if TARGET_PC
struct BatchInfo {
f32 vtxPos[8][3];
f32 vtxUv[8][2];
u8 vtxCount; // 4 (quad) or 8 (cross)
bool supported; // draw func list contains only batchable funcs
bool hasPtclColor; // per-particle JPARegist* func is present
bool hasPtclTexMtx; // JPALoadCalcTexCrdMtxAnm is present
};
BatchInfo mBatchInfo;
void initBatchInfo();
#endif
};
#endif /* JPARESOURCE_H */
@@ -3,8 +3,6 @@
#include "JSystem/J2DGraph/J2DGrafContext.h"
#include <gx.h>
#include <tracy/Tracy.hpp>
J2DGrafContext::J2DGrafContext(f32 x, f32 y, f32 width, f32 height)
: mBounds(x, y, x + width, y + height), mScissorBounds(x, y, x + width, y + height) {
if (x < 0.0f || y < 0.0f) {
@@ -139,7 +137,6 @@ void J2DGrafContext::setLineWidth(u8 lineWidth) {
}
void J2DGrafContext::fillBox(JGeometry::TBox2<f32> const& box) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mBoxPart.mType, (GXBlendFactor)mBoxPart.mSrcFactor,
(GXBlendFactor)mBoxPart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
@@ -158,7 +155,6 @@ void J2DGrafContext::fillBox(JGeometry::TBox2<f32> const& box) {
}
void J2DGrafContext::drawFrame(JGeometry::TBox2<f32> const& box) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mBoxPart.mType, (GXBlendFactor)mBoxPart.mSrcFactor,
(GXBlendFactor)mBoxPart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
@@ -179,7 +175,6 @@ void J2DGrafContext::drawFrame(JGeometry::TBox2<f32> const& box) {
}
void J2DGrafContext::line(JGeometry::TVec2<f32> start, JGeometry::TVec2<f32> end) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mLinePart.mType, (GXBlendFactor)mLinePart.mSrcFactor,
(GXBlendFactor)mLinePart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
@@ -542,11 +542,8 @@ void J3DModel::viewCalc() {
}
#ifdef TARGET_PC
Mtx* drawMtx = getDrawMtxPtr();
if (drawMtx != J3DMtxBuffer::sNoUseDrawMtxPtr) {
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
dusk::frame_interp::record_final_mtx(drawMtx[i]);
}
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
dusk::frame_interp::record_final_mtx(getDrawMtxPtr()[i]);
}
#endif
+2 -2
View File
@@ -136,8 +136,8 @@ void J3DLoadCPCmd(u8 addr, u32 val) {
#if TARGET_PC
static void J3DLoadArrayBasePtr(GXAttr attr, void* data, u32 size, bool le) {
u32 idx = (attr == GX_VA_NBT) ? 1 : (attr - GX_VA_POS);
GXCmd1u8(GX_AURORA);
GXCmd1u16(GX_AURORA_LOAD_ARRAYBASE | idx);
GXCmd1u8(GX_LOAD_AURORA);
GXCmd1u16(GX_LOAD_AURORA_ARRAYBASE | idx);
GXCmd1u64((u64)data);
GXCmd1u32(size);
GXCmd1u8(le ? 1 : 0);
+4 -101
View File
@@ -1,47 +1,15 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include <cstring>
#include <gx.h>
#include <stdint.h>
#include "JSystem/J3DGraphBase/J3DShapeDraw.h"
#include "JSystem/JKernel/JKRHeap.h"
#if TARGET_PC
#include <aurora/dl.hpp>
#include <tracy/Tracy.hpp>
namespace {
void set_display_list_copy(void*& displayList, u32& displayListSize, const u8* data, u32 size) {
const u32 alignedSize = ALIGN_NEXT(size, 0x20);
u8* newDL = JKR_NEW_ARRAY_ARGS(u8, alignedSize, 0x20);
if (size != 0) {
std::memcpy(newDL, data, size);
}
for (u32 i = size; i < alignedSize; i++) {
newDL[i] = 0;
}
displayList = newDL;
displayListSize = alignedSize;
DCStoreRange(newDL, displayListSize);
}
} // namespace
#endif
#include <cstring>
#include <stdint.h>
#include <gx.h>
u32 J3DShapeDraw::countVertex(u32 stride) {
u32 count = 0;
u8* dlStart = (u8*)getDisplayList();
#if TARGET_PC
aurora::gx::dl::Reader reader{dlStart, getDisplayListSize(), static_cast<u8>(stride)};
while (const auto cmd = reader.next()) {
if (cmd->kind != aurora::gx::dl::Command::Kind::Passthrough) {
count += cmd->draw.vtxCount;
}
}
#else
for (u8* dl = dlStart; (dl - dlStart) < getDisplayListSize();) {
u8 cmd = *(u8*)dl;
dl++;
@@ -52,58 +20,10 @@ u32 J3DShapeDraw::countVertex(u32 stride) {
count += vtxNum;
dl = (u8*)dl + stride * vtxNum;
}
#endif
return count;
}
#if TARGET_PC
void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
u32 byteNum = countVertex(stride);
u32 oldSize = mDisplayListSize;
u32 newSize = ALIGN_NEXT(oldSize + byteNum, 0x20);
u8* newDLStart = JKR_NEW_ARRAY_ARGS(u8, newSize, 0x20);
u8* oldDLStart = (u8*)mDisplayList;
u8* newDL = newDLStart;
aurora::gx::dl::Reader reader{oldDLStart, mDisplayListSize, static_cast<u8>(stride)};
while (const auto cmd = reader.next()) {
if (cmd->kind == aurora::gx::dl::Command::Kind::Passthrough) {
std::memcpy(newDL, cmd->data, cmd->size);
newDL += cmd->size;
continue;
}
const auto& draw = cmd->draw;
const u32 headerSize = draw.vertices - cmd->data;
std::memcpy(newDL, cmd->data, headerSize);
newDL += headerSize;
for (u32 i = 0; i < draw.vtxCount; i++) {
const u8* oldVtx = draw.vertices + stride * i;
u8 pnmtxidx = oldVtx[0];
std::memcpy(newDL, oldVtx, attrOffs);
newDL += attrOffs;
*newDL++ = valueBase + pnmtxidx;
std::memcpy(newDL, oldVtx + attrOffs, stride - attrOffs);
newDL += stride - attrOffs;
}
}
if (reader.failed()) {
// preserve the remainder untouched
std::memcpy(newDL, oldDLStart + reader.pos(), mDisplayListSize - reader.pos());
newDL += mDisplayListSize - reader.pos();
}
u32 realSize = ALIGN_NEXT((uintptr_t)newDL - (uintptr_t)newDLStart, 0x20);
for (; (newDL - newDLStart) < newSize; newDL++)
*newDL = 0;
mDisplayListSize = realSize;
mDisplayList = newDLStart;
DCStoreRange(newDLStart, mDisplayListSize);
}
#else
void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
u32 byteNum = countVertex(stride);
u32 oldSize = mDisplayListSize;
@@ -149,30 +69,13 @@ void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
mDisplayList = newDLStart;
DCStoreRange(newDLStart, mDisplayListSize);
}
#endif
J3DShapeDraw::J3DShapeDraw(const u8* displayList, u32 displayListSize) {
#if TARGET_PC
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
#else
mDisplayList = (void*)displayList;
mDisplayListSize = displayListSize;
#endif
}
#if TARGET_PC
J3DShapeDraw::J3DShapeDraw(
const u8* displayList, u32 displayListSize, const GXVtxDescList* vtxDesc) {
if (const auto optimized = aurora::gx::dl::optimize(displayList, displayListSize, vtxDesc)) {
set_display_list_copy(mDisplayList, mDisplayListSize, optimized->data(), optimized->size());
} else {
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
}
}
#endif
void J3DShapeDraw::draw() const {
ZoneScoped;
GXCallDisplayList(mDisplayList, mDisplayListSize);
}
@@ -132,12 +132,7 @@ J3DShapeDraw* J3DShapeFactory::newShapeDraw(int shapeNo, int mtxGroupNo) const {
const J3DShapeInitData& shapeInitData = mShapeInitData[mIndexTable[shapeNo]];
const J3DShapeDrawInitData& drawInitData =
(&mDrawInitData[shapeInitData.mDrawInitDataIndex])[mtxGroupNo];
#if TARGET_PC
shapeDraw = JKR_NEW J3DShapeDraw(&mDisplayListData[drawInitData.mDisplayListIndex], drawInitData.mDisplayListSize,
getVtxDescList(shapeNo));
#else
shapeDraw = JKR_NEW J3DShapeDraw(&mDisplayListData[drawInitData.mDisplayListIndex], drawInitData.mDisplayListSize);
#endif
J3D_ASSERT_ALLOCMEM(193, shapeDraw);
return shapeDraw;
}
@@ -159,7 +154,7 @@ s32 J3DShapeFactory::calcSize(int shapeNo, u32 flag) {
for (u32 i = 0; i < mtxGroupNo; i++) {
size += calcSizeShapeMtx(flag, shapeNo, i);
size += sizeof(J3DShapeDraw);
size += 0x0C;
}
return size;
+3 -3
View File
@@ -16,10 +16,10 @@ inline f64 getConst2() {
return 9.765625E-4;
}
DUSK_GAME_DATA TSinCosTable<13, f32> sincosTable_ ATTRIBUTE_ALIGN(32);
TSinCosTable<13, f32> sincosTable_ ATTRIBUTE_ALIGN(32);
DUSK_GAME_DATA TAtanTable<1024, f32> atanTable_ ATTRIBUTE_ALIGN(32);
TAtanTable<1024, f32> atanTable_ ATTRIBUTE_ALIGN(32);
DUSK_GAME_DATA TAsinAcosTable<1024, f32> asinAcosTable_ ATTRIBUTE_ALIGN(32);
TAsinAcosTable<1024, f32> asinAcosTable_ ATTRIBUTE_ALIGN(32);
} // namespace JMath
+30 -269
View File
@@ -14,33 +14,6 @@
#endif
#include "tracy/Tracy.hpp"
#if TARGET_PC
#define JPA_DRAW_CTX_PARAM , ParticleDrawCtx* ctx
namespace {
GXColor emitter_prm_color(JPAEmitterWorkData* work) {
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g);
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
return prm;
}
GXColor emitter_env_color(JPAEmitterWorkData* work) {
JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = emtr->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
return env;
}
} // namespace
#else
#define JPA_DRAW_CTX_PARAM
#endif
void JPASetPointSize(JPAEmitterWorkData* work) {
GXSetPointSize((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
}
@@ -49,16 +22,15 @@ void JPASetLineWidth(JPAEmitterWorkData* work) {
GXSetLineWidth((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
}
void JPASetPointSize(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
void JPASetPointSize(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
GXSetPointSize((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
}
void JPASetLineWidth(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
void JPASetLineWidth(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
GXSetLineWidth((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
}
void JPARegistPrm(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
@@ -69,7 +41,6 @@ void JPARegistPrm(JPAEmitterWorkData* work) {
}
void JPARegistEnv(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = emtr->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
@@ -79,7 +50,6 @@ void JPARegistEnv(JPAEmitterWorkData* work) {
}
void JPARegistPrmEnv(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
GXColor env = emtr->mEnvClr;
@@ -94,8 +64,7 @@ void JPARegistPrmEnv(JPAEmitterWorkData* work) {
GXSetTevColor(GX_TEVREG1, env);
}
void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
@@ -103,19 +72,10 @@ void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
if (ctx->useClr1) {
ctx->clr1 = emitter_env_color(work);
}
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
}
void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = ptcl->mPrmClr;
@@ -124,19 +84,10 @@ void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
if (ctx->useClr1) {
ctx->clr1 = emitter_env_color(work);
}
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
}
void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = ptcl->mPrmClr;
@@ -149,19 +100,11 @@ void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DR
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
GXSetTevColor(GX_TEVREG1, env);
}
void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
GXColor env = ptcl->mEnvClr;
@@ -173,31 +116,16 @@ void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
GXSetTevColor(GX_TEVREG1, env);
}
void JPARegistEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
void JPARegistEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = ptcl->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = emitter_prm_color(work);
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG1, env);
}
@@ -330,7 +258,7 @@ void JPAGenCalcTexCrdMtxAnm(JPAEmitterWorkData* work) {
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
}
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
ZoneScoped;
JPABaseShape* shape = work->mpRes->getBsp();
f32 dVar16 = param_1->mAge;
@@ -358,12 +286,6 @@ void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1
local_108[2][1] = 0.0f;
local_108[2][2] = 1.0f;
local_108[2][3] = 0.0f;
#if TARGET_PC
if (ctx->batch) {
MTXCopy(local_108, ctx->texMtx);
return;
}
#endif
GXLoadTexMtxImm(local_108, 0x1e, GX_MTX2x4);
}
@@ -377,7 +299,7 @@ void JPALoadTexAnm(JPAEmitterWorkData* work) {
work->mpResMgr->load(work->mpRes->getTexIdx(work->mpEmtr->mTexAnmIdx), GX_TEXMAP0);
}
void JPALoadTexAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
void JPALoadTexAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
ZoneScoped;
work->mpResMgr->load(work->mpRes->getTexIdx(ptcl->mTexAnmIdx), GX_TEXMAP0);
}
@@ -507,47 +429,6 @@ static projectionFunc p_prj[3] = {
};
#if TARGET_PC
static void emit_batch_quad(JPAEmitterWorkData* work, const ParticleDrawCtx* ctx,
const Mtx posMtx) {
const JPAResource::BatchInfo& info = work->mpRes->mBatchInfo;
for (int i = 0; i < info.vtxCount; i++) {
Vec localPos = {info.vtxPos[i][0], info.vtxPos[i][1], info.vtxPos[i][2]};
Vec drawPos;
MTXMultVec(posMtx, &localPos, &drawPos);
f32 texS = info.vtxUv[i][0];
f32 texT = info.vtxUv[i][1];
if (ctx->useTexMtx) {
f32 srcS = texS;
f32 srcT = texT;
texS = ctx->texMtx[0][0] * srcS + ctx->texMtx[0][1] * srcT + ctx->texMtx[0][3];
texT = ctx->texMtx[1][0] * srcS + ctx->texMtx[1][1] * srcT + ctx->texMtx[1][3];
}
GXPosition3f32(drawPos.x, drawPos.y, drawPos.z);
if (ctx->useClr0) {
GXColor4u8(ctx->clr0.r, ctx->clr0.g, ctx->clr0.b, ctx->clr0.a);
}
if (ctx->useClr1) {
GXColor4u8(ctx->clr1.r, ctx->clr1.g, ctx->clr1.b, ctx->clr1.a);
}
GXTexCoord2f32(texS, texT);
}
}
static void submit_particle_quad(
JPAEmitterWorkData* work, ParticleDrawCtx* ctx, const Mtx posMtx, const u8* dl, u32 dlSize) {
if (ctx->batch) {
emit_batch_quad(work, ctx, posMtx);
return;
}
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(dl, dlSize);
}
void JPAInterpBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
Mtx ptclPosMtx;
MTXTrans(ptclPosMtx, ptcl->mPosition.x, ptcl->mPosition.y, ptcl->mPosition.z);
@@ -567,7 +448,7 @@ void JPAInterpRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
}
#endif
void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -592,16 +473,12 @@ void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_C
posMtx[2][2] = 1.0f;
posMtx[2][3] = pos.z;
posMtx[0][1] = posMtx[0][2] = posMtx[1][0] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -640,16 +517,12 @@ void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRA
posMtx[2][2] = 1.0f;
posMtx[2][3] = pos.z;
posMtx[0][2] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -669,16 +542,12 @@ void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DR
local_38[2][2] = work->mYBBCamMtx[2][2];
local_38[2][3] = local_48.z;
local_38[0][1] = local_38[0][2] = local_38[1][0] = local_38[2][0] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, local_38, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(local_38, GX_PNMTX0);
p_prj[work->mPrjType](work, local_38);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -707,13 +576,9 @@ void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA
local_38[2][1] = local_94 * fVar1;
local_38[2][2] = local_90;
local_38[2][3] = local_48.z;
#if TARGET_PC
submit_particle_quad(work, ctx, local_38, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(local_38, GX_PNMTX0);
p_prj[work->mPrjType](work, local_38);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void dirTypeVel(JPAEmitterWorkData const* work, JPABaseParticle const* param_1,
@@ -876,88 +741,6 @@ static u8* p_dl[2] = {
};
#if TARGET_PC
static bool make_direction_mtx(JPAEmitterWorkData* work, JPABaseParticle* ptcl, Mtx posMtx) {
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
JGeometry::TVec3<f32> baseAxis(ptcl->mBaseAxis);
p_direction[work->mDirType](work, ptcl, &axisY);
if (axisY.isZero()) {
return false;
}
axisY.normalize();
axisZ.cross(baseAxis, axisY);
if (axisZ.isZero()) {
return false;
}
axisZ.normalize();
baseAxis.cross(axisY, axisZ);
baseAxis.normalize();
ptcl->mBaseAxis.set(baseAxis);
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
posMtx[0][0] = baseAxis.x;
posMtx[0][1] = axisY.x;
posMtx[0][2] = axisZ.x;
posMtx[0][3] = ptcl->mPosition.x;
posMtx[1][0] = baseAxis.y;
posMtx[1][1] = axisY.y;
posMtx[1][2] = axisZ.y;
posMtx[1][3] = ptcl->mPosition.y;
posMtx[2][0] = baseAxis.z;
posMtx[2][1] = axisY.z;
posMtx[2][2] = axisZ.z;
posMtx[2][3] = ptcl->mPosition.z;
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
return true;
}
static bool make_rot_direction_mtx(JPAEmitterWorkData* work, JPABaseParticle* ptcl, Mtx posMtx) {
f32 sinRot = JMASSin(ptcl->mRotateAngle);
f32 cosRot = JMASCos(ptcl->mRotateAngle);
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
JGeometry::TVec3<f32> baseAxis(ptcl->mBaseAxis);
p_direction[work->mDirType](work, ptcl, &axisY);
if (axisY.isZero()) {
return false;
}
axisY.normalize();
axisZ.cross(baseAxis, axisY);
if (axisZ.isZero()) {
return false;
}
axisZ.normalize();
baseAxis.cross(axisY, axisZ);
baseAxis.normalize();
ptcl->mBaseAxis.set(baseAxis);
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
Mtx rotMtx;
Mtx dirMtx;
p_rot[work->mRotType](sinRot, cosRot, rotMtx);
p_plane[work->mPlaneType](rotMtx, scaleX, scaleY);
dirMtx[0][0] = baseAxis.x;
dirMtx[0][1] = axisY.x;
dirMtx[0][2] = axisZ.x;
dirMtx[0][3] = ptcl->mPosition.x;
dirMtx[1][0] = baseAxis.y;
dirMtx[1][1] = axisY.y;
dirMtx[1][2] = axisZ.y;
dirMtx[1][3] = ptcl->mPosition.y;
dirMtx[2][0] = baseAxis.z;
dirMtx[2][1] = axisY.z;
dirMtx[2][2] = axisZ.z;
dirMtx[2][3] = ptcl->mPosition.z;
MTXConcat(dirMtx, rotMtx, posMtx);
return true;
}
void JPAInterpDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
@@ -1040,7 +823,7 @@ void JPAInterpRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
}
#endif
void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -1049,12 +832,8 @@ void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_C
Mtx posMtx;
#if TARGET_PC
if (!dusk::frame_interp::lookup_replacement(ptcl, posMtx) &&
!make_direction_mtx(work, ptcl, posMtx))
{
return;
}
#else
if (!dusk::frame_interp::lookup_replacement(ptcl, posMtx))
#endif
{
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
@@ -1090,19 +869,14 @@ void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_C
posMtx[2][3] = ptcl->mPosition.z;
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
}
#endif
MTXConcat(work->mPosCamMtx, posMtx, posMtx);
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, p_dl[work->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
#endif
}
void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -1112,12 +886,8 @@ void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRA
Mtx mtx1;
Mtx mtx2;
#if TARGET_PC
if (!dusk::frame_interp::lookup_replacement(ptcl, mtx1) &&
!make_rot_direction_mtx(work, ptcl, mtx1))
{
return;
}
#else
if (!dusk::frame_interp::lookup_replacement(ptcl, mtx1))
#endif
{
f32 sinRot = JMASSin(ptcl->mRotateAngle);
f32 cosRot = JMASCos(ptcl->mRotateAngle);
@@ -1157,18 +927,13 @@ void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRA
mtx2[2][3] = ptcl->mPosition.z;
MTXConcat(mtx2, mtx1, mtx1);
}
#endif
MTXConcat(work->mPosCamMtx, mtx1, mtx2);
#if TARGET_PC
submit_particle_quad(work, ctx, mtx2, p_dl[work->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(mtx2, GX_PNMTX0);
p_prj[work->mPrjType](work, mtx2);
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
#endif
}
void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -1205,7 +970,7 @@ void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
}
void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -1223,16 +988,12 @@ void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_D
auStack_88[1][3] = param_1->mPosition.y;
auStack_88[2][3] = param_1->mPosition.z;
MTXConcat(param_0->mPosCamMtx, auStack_88, auStack_88);
#if TARGET_PC
submit_particle_quad(param_0, ctx, auStack_88, p_dl[param_0->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(auStack_88, 0);
p_prj[param_0->mPrjType](param_0, auStack_88);
GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl));
#endif
}
void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -1249,7 +1010,7 @@ void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_P
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
}
void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -1325,7 +1086,7 @@ void JPADrawStripe(JPAEmitterWorkData* param_0) {
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) {
param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject();
@@ -1350,7 +1111,7 @@ void JPADrawStripe(JPAEmitterWorkData* param_0) {
}
particle->mBaseAxis.cross(local_f8, local_104);
particle->mBaseAxis.normalize();
local_c8[0][0] = local_104.x;
local_c8[0][1] = local_f8.x;
local_c8[0][2] = particle->mBaseAxis.x;
@@ -1416,7 +1177,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) {
param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject();
@@ -1441,7 +1202,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
}
particle->mBaseAxis.cross(local_c0, local_cc);
particle->mBaseAxis.normalize();
local_90[0][0] = local_cc.x;
local_90[0][1] = local_c0.x;
local_90[0][2] = particle->mBaseAxis.x;
@@ -1466,7 +1227,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
coord = start_coord;
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) {
param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject();
@@ -1491,7 +1252,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
}
particle->mBaseAxis.cross(local_c0, local_cc);
particle->mBaseAxis.normalize();
local_90[0][0] = local_cc.x;
local_90[0][1] = local_c0.x;
local_90[0][2] = particle->mBaseAxis.x;
@@ -1528,7 +1289,7 @@ void JPADrawEmitterCallBackB(JPAEmitterWorkData* work) {
emtr->mpEmtrCallBack->draw(emtr);
}
void JPADrawParticleCallBack(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
void JPADrawParticleCallBack(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
JPABaseEmitter* emtr = work->mpEmtr;
if (emtr->mpPtclCallBack == NULL) {
return;
+2 -1
View File
@@ -206,7 +206,8 @@ void JPABaseParticle::init_c(JPAEmitterWorkData* work, JPABaseParticle* parent)
#if TARGET_PC
void JPABaseParticle::interp(JPAEmitterWorkData* work, void const* drawFunc) {
if (!dusk::frame_interp::is_enabled())
static bool enable = false;
if (!enable)
return;
// don't interpolate the first frame
+6 -284
View File
@@ -18,21 +18,9 @@
#include "global.h"
#include "tracy/Tracy.hpp"
#if TARGET_PC
#define JPA_DRAW_CTX_ARG , &ctx
#else
#define JPA_DRAW_CTX_ARG
#endif
JPAResource::JPAResource() {
mpCalcEmitterFuncList = mpDrawEmitterFuncList = mpDrawEmitterChildFuncList = NULL;
#if TARGET_PC
mpCalcParticleFuncList = mpCalcParticleChildFuncList = NULL;
mpDrawParticleFuncList = mpDrawParticleChildFuncList = NULL;
mBatchInfo = {};
#else
mpCalcParticleFuncList = mpDrawParticleFuncList = mpCalcParticleChildFuncList = mpDrawParticleChildFuncList = NULL;
#endif
pBsp = NULL;
pEsp = NULL;
pCsp = NULL;
@@ -73,60 +61,6 @@ static u8 jpa_crd[32] ATTRIBUTE_ALIGN(32) = {
0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02,
};
#if TARGET_PC
void JPAResource::initBatchInfo() {
mBatchInfo = {};
bool hasDrawFunc = false;
for (int i = 0; i < mpDrawParticleFuncListNum; i++) {
DrawParticleFunc func = mpDrawParticleFuncList[i];
if (func == JPADrawBillboard || func == JPADrawRotBillboard ||
func == JPADrawYBillboard || func == JPADrawRotYBillboard ||
func == JPADrawDirection || func == JPADrawRotDirection || func == JPADrawRotation)
{
hasDrawFunc = true;
} else if (func == JPADrawParticleCallBack) {
// Batchable only for emitters without a particle callback; checked per draw
} else if (func == JPALoadCalcTexCrdMtxAnm) {
mBatchInfo.hasPtclTexMtx = true;
} else if (func == JPARegistAlpha || func == JPARegistPrmAlpha ||
func == JPARegistPrmAlphaEnv || func == JPARegistAlphaEnv ||
func == static_cast<DrawParticleFunc>(JPARegistEnv)) // overloaded
{
mBatchInfo.hasPtclColor = true;
} else {
// JPADrawPoint, JPADrawLine, JPADrawDBillboard, JPALoadTexAnm,
// JPASetPointSize, JPASetLineWidth
return;
}
}
if (!hasDrawFunc) {
return;
}
// Template array offsets, same math as setPTev
int base_plane_type = (pBsp->getType() == 3 || pBsp->getType() == 7) ?
pBsp->getBasePlaneType() : 0;
int center_offset = pEsp != nullptr ? (pEsp->getScaleCenterX() + 3 * pEsp->getScaleCenterY()) * 0xC : 0x30;
const s8* pos = reinterpret_cast<const s8*>(jpa_pos) + center_offset + base_plane_type * 0x6C;
const s8* crd = reinterpret_cast<const s8*>(jpa_crd) + (pBsp->getTilingS() + 2 * pBsp->getTilingT()) * 8;
bool cross = pBsp->getType() == 4 || pBsp->getType() == 8;
mBatchInfo.vtxCount = cross ? 8 : 4;
for (int i = 0; i < mBatchInfo.vtxCount; i++) {
int posIdx = i < 4 ? i : 72 + (i - 4);
int crdIdx = i & 3;
mBatchInfo.vtxPos[i][0] = pos[posIdx * 3 + 0];
mBatchInfo.vtxPos[i][1] = pos[posIdx * 3 + 1];
mBatchInfo.vtxPos[i][2] = pos[posIdx * 3 + 2];
mBatchInfo.vtxUv[i][0] = crd[crdIdx * 2 + 0];
mBatchInfo.vtxUv[i][1] = crd[crdIdx * 2 + 1];
}
mBatchInfo.supported = true;
}
#endif
void JPAResource::init(JKRHeap* heap) {
BOOL is_glbl_clr_anm = pBsp->isGlblClrAnm();
BOOL is_glbl_tex_anm = pBsp->isGlblTexAnm();
@@ -591,10 +525,7 @@ void JPAResource::init(JKRHeap* heap) {
if (mpDrawParticleFuncListNum != 0) {
mpDrawParticleFuncList =
(DrawParticleFunc*)JKRAllocFromHeap(
heap,
mpDrawParticleFuncListNum * sizeof(DrawParticleFunc),
alignof(DrawParticleFunc));
(ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleFuncListNum * sizeof(ParticleFunc), alignof(ParticleFunc));
}
func_no = 0;
@@ -704,10 +635,7 @@ void JPAResource::init(JKRHeap* heap) {
if (mpDrawParticleChildFuncListNum != 0) {
mpDrawParticleChildFuncList =
(DrawParticleFunc*)JKRAllocFromHeap(
heap,
mpDrawParticleChildFuncListNum * sizeof(DrawParticleFunc),
alignof(DrawParticleFunc));
(ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleChildFuncListNum * sizeof(ParticleFunc), sizeof(EmitterFunc));
}
func_no = 0;
@@ -771,10 +699,6 @@ void JPAResource::init(JKRHeap* heap) {
mpDrawParticleChildFuncList[func_no] = &JPARegistPrmAlphaEnv;
func_no++;
}
#if TARGET_PC
initBatchInfo();
#endif
}
bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
@@ -837,15 +761,6 @@ bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
}
}
#ifdef TARGET_PC
if (((pBsp && pBsp->getDirType() == 3) || (pCsp && pCsp->getDirType() == 3)) &&
dusk::frame_interp::is_enabled())
{
// ensure mGlobalEmtrDir is valid
calcWorkData_d(work);
}
#endif
JPANode<JPABaseParticle>* next = NULL;
for (JPANode<JPABaseParticle>* node = emtr->mAlivePtclBase.getFirst(); node != emtr->mAlivePtclBase.getEnd(); node = next) {
next = node->getNext();
@@ -884,183 +799,6 @@ void JPAResource::draw(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
}
}
#if TARGET_PC
static GXTevAlphaArg to_vtx_alpha_arg(GXTevAlphaArg arg) {
return arg == GX_CA_A0 ? GX_CA_RASA : arg;
}
static void batch_set_tev_op(GXTevStageID stage) {
GXSetTevColorOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
}
static void batch_setup_tev(JPAEmitterWorkData* work, bool useClr1) {
JPABaseShape* shape = work->mpRes->getBsp();
JPAExTexShape* ets = work->mpRes->getEts();
bool useIndirect = ets != nullptr && ets->isUseIndirect();
// JPAEmitterManager::draw configures both channels to pass vertex color through
GXSetNumChans(useClr1 ? 2 : 1);
const GXTevAlphaArg* alphaArg = shape->getTevAlphaArg();
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GXSetTevAlphaIn(GX_TEVSTAGE0, to_vtx_alpha_arg(alphaArg[0]), to_vtx_alpha_arg(alphaArg[1]),
to_vtx_alpha_arg(alphaArg[2]), to_vtx_alpha_arg(alphaArg[3]));
batch_set_tev_op(GX_TEVSTAGE0);
if (!useIndirect) {
GXSetTevDirect(GX_TEVSTAGE0);
}
GXTevStageID nextStage = GX_TEVSTAGE1;
switch (shape->getTevColorArgSel()) {
case 0: // TEXC
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_ONE, GX_CC_ZERO);
break;
case 1: // C0 * TEXC
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
break;
case 2: // lerp(C0, 1, TEXC)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO);
break;
case 3: // lerp(C1, C0, TEXC) = C0 * TEXC (stage 0) + C1 * (1 - TEXC) (stage 1)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
GXSetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR1A1);
GXSetTevColorIn(nextStage, GX_CC_RASC, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
break;
case 4: // TEXC * C0 + C1: C0 * TEXC (stage 0), + C1 (stage 1)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
GXSetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR1A1);
GXSetTevColorIn(nextStage, GX_CC_CPREV, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
break;
case 5: // C0
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
break;
}
if (ets != nullptr && ets->isUseSecTex()) {
// Mirrors setPTev's secondary texture stage, at the next free stage
GXTexCoordID texCoord = useIndirect ? GX_TEXCOORD2 : GX_TEXCOORD1;
GXSetTevOrder(nextStage, texCoord, GX_TEXMAP3, GX_COLOR_NULL);
GXSetTevColorIn(nextStage, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_ZERO);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
}
GXSetNumTevStages(nextStage);
}
static void batch_setup_vtx_desc(bool useClr0, bool useClr1) {
static Mtx identityMtx = {
{1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, 0.0f},
};
GXLoadPosMtxImm(identityMtx, GX_PNMTX0);
GXSetCurrentMtx(GX_PNMTX0);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
if (useClr0) {
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
}
if (useClr1) {
GXSetVtxDesc(GX_VA_CLR1, GX_DIRECT);
}
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
if (useClr0) {
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
}
if (useClr1) {
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0);
}
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
}
static void batch_restore_gx(JPAEmitterWorkData* work, bool changedTev, bool changedTexMtx) {
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSetCurrentMtx(GX_PNMTX0);
if (changedTexMtx) {
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
}
if (changedTev) {
GXSetNumChans(0);
work->mpRes->getBsp()->setGX(work);
work->mpRes->setPTev();
}
}
static bool draw_particle_batch(JPAEmitterWorkData* work) {
ZoneScoped;
JPAResource* res = work->mpRes;
const JPAResource::BatchInfo& info = res->mBatchInfo;
if (!info.supported || work->mPrjType != 0 || work->mpEmtr->mpPtclCallBack != nullptr) {
return false;
}
bool useClr0 = false;
bool useClr1 = false;
if (info.hasPtclColor) {
u32 colorSel = res->getBsp()->getTevColorArgSel();
if (colorSel >= 6) {
return false;
}
useClr0 = true;
useClr1 = colorSel == 3 || colorSel == 4;
batch_setup_tev(work, useClr1);
}
if (info.hasPtclTexMtx) {
// UVs are CPU-transformed; drop the texgen
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
}
batch_setup_vtx_desc(useClr0, useClr1);
ParticleDrawCtx ctx{};
ctx.batch = true;
ctx.useTexMtx = info.hasPtclTexMtx;
ctx.useClr0 = useClr0;
ctx.useClr1 = useClr1;
bool fwdAhead = res->getBsp()->isDrawFwdAhead();
JPANode<JPABaseParticle>* node = fwdAhead ? work->mpEmtr->mAlivePtclBase.getLast() :
work->mpEmtr->mAlivePtclBase.getFirst();
GXBegin(GX_QUADS, GX_VTXFMT1, GX_AUTO);
while (node != work->mpEmtr->mAlivePtclBase.getEnd()) {
work->mpCurNode = node;
for (int i = res->mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*res->mpDrawParticleFuncList[i])(work, node->getObject(), &ctx);
}
node = fwdAhead ? node->getPrev() : node->getNext();
}
GXEnd();
batch_restore_gx(work, useClr0, info.hasPtclTexMtx);
return true;
}
#endif
void JPAResource::drawP(JPAEmitterWorkData* work) {
ZoneScoped;
work->mpEmtr->clearStatus(0x80);
@@ -1095,25 +833,13 @@ void JPAResource::drawP(JPAEmitterWorkData* work) {
(*mpDrawEmitterFuncList[i])(work);
}
#if TARGET_PC
if (draw_particle_batch(work)) {
GXSetMisc(GX_MT_XF_FLUSH, 0);
if (work->mpEmtr->mpEmtrCallBack != nullptr) {
work->mpEmtr->mpEmtrCallBack->drawAfter(work->mpEmtr);
}
return;
}
ParticleDrawCtx ctx{}; // immediate mode
#endif
if (pBsp->isDrawFwdAhead()) {
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclBase.getLast();
for (; node != work->mpEmtr->mAlivePtclBase.getEnd(); node = node->getPrev()) {
work->mpCurNode = node;
if (mpDrawParticleFuncList != NULL) {
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
(*mpDrawParticleFuncList[i])(work, node->getObject());
}
}
}
@@ -1123,7 +849,7 @@ void JPAResource::drawP(JPAEmitterWorkData* work) {
work->mpCurNode = node;
if (mpDrawParticleFuncList != NULL) {
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
(*mpDrawParticleFuncList[i])(work, node->getObject());
}
}
}
@@ -1170,17 +896,13 @@ void JPAResource::drawC(JPAEmitterWorkData* work) {
(*mpDrawEmitterChildFuncList[i])(work);
}
#if TARGET_PC
ParticleDrawCtx ctx{}; // immediate mode
#endif
if (pBsp->isDrawFwdAhead()) {
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclChld.getLast();
for (; node != work->mpEmtr->mAlivePtclChld.getEnd(); node = node->getPrev()) {
work->mpCurNode = node;
if (mpDrawParticleChildFuncList != NULL) {
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleChildFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
(*mpDrawParticleChildFuncList[i])(work, node->getObject());
}
}
}
@@ -1190,7 +912,7 @@ void JPAResource::drawC(JPAEmitterWorkData* work) {
work->mpCurNode = node;
if (mpDrawParticleChildFuncList != NULL) {
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleChildFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
(*mpDrawParticleChildFuncList[i])(work, node->getObject());
}
}
}
-1
View File
@@ -249,7 +249,6 @@ f32 JUTResFont::drawChar_scale(f32 pos_x, f32 pos_y, f32 scale_x, f32 scale_y, i
f32 x2;
f32 y1;
ZoneScoped;
JUT_ASSERT(378, mValid);
JUTFont::TWidth width;
loadFont(str_int, GX_TEXMAP0, &width FONT_DRAW_CTX_ARG);
@@ -4,7 +4,6 @@ import android.app.ActionBar;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
@@ -15,16 +14,12 @@ import android.provider.DocumentsContract;
import android.provider.OpenableColumns;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import org.libsdl.app.SDLActivity;
import org.libsdl.app.SDLSurface;
import java.io.File;
import java.util.ArrayList;
@@ -32,7 +27,6 @@ import java.util.List;
public class DuskActivity extends SDLActivity {
private static final String TAG = "DuskActivity";
private static final float DEFAULT_SURFACE_FRAME_RATE = 60.0f;
private static final int FOLDER_DIALOG_REQUEST_CODE = 0x4455;
private static final int MANAGE_STORAGE_REQUEST_CODE = 0x4456;
private static final String EXTERNAL_STORAGE_AUTHORITY =
@@ -94,11 +88,6 @@ public class DuskActivity extends SDLActivity {
hideSystemBars();
}
@Override
protected SDLSurface createSDLSurface(Context context) {
return new DuskSurface(context);
}
@Override
protected void onResume() {
super.onResume();
@@ -150,77 +139,6 @@ public class DuskActivity extends SDLActivity {
};
}
public void setPreferredSurfaceFrameRate(float frameRate) {
runOnUiThread(() -> {
if (mSurface instanceof DuskSurface) {
((DuskSurface)mSurface).setPreferredFrameRate(frameRate);
}
});
}
private static final class DuskSurface extends SDLSurface {
private float preferredFrameRate = DEFAULT_SURFACE_FRAME_RATE;
DuskSurface(Context context) {
super(context);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.surfaceChanged(holder, format, width, height);
setTargetFrameRate(holder);
}
void setPreferredFrameRate(float frameRate) {
preferredFrameRate = frameRate;
setTargetFrameRate(getHolder());
}
private void setTargetFrameRate(SurfaceHolder holder) {
if (!mIsSurfaceReady || Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
return;
}
Surface surface = holder != null ? holder.getSurface() : getHolder().getSurface();
if (surface == null || !surface.isValid()) {
return;
}
float targetFrameRate = getMaxSupportedFrameRate();
if (preferredFrameRate > 0.0f) {
targetFrameRate = preferredFrameRate;
}
if (targetFrameRate <= 0.0f) {
return;
}
try {
surface.setFrameRate(
targetFrameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
Log.v(TAG, "Requested surface frame rate " + targetFrameRate + " fps");
} catch (RuntimeException e) {
Log.w(TAG, "Failed to request surface frame rate", e);
}
}
private float getMaxSupportedFrameRate() {
if (mDisplay == null) {
return 0.0f;
}
float maxFrameRate = mDisplay.getRefreshRate();
Display.Mode[] modes = mDisplay.getSupportedModes();
if (modes == null) {
return maxFrameRate;
}
for (Display.Mode mode : modes) {
maxFrameRate = Math.max(maxFrameRate, mode.getRefreshRate());
}
return maxFrameRate;
}
}
@Override
protected String[] getArguments() {
Intent intent = getIntent();
@@ -19,13 +19,9 @@ import android.os.*;
import java.lang.Runnable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDevice {
private static final String TAG = "hidapi";
@@ -37,19 +33,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
private boolean mIsConnected = false;
private boolean mIsChromebook = false;
private boolean mIsReconnecting = false;
private boolean mHasEnabledNotifications = false;
private boolean mHasSeenInputUpdate = false;
private boolean mFrozen = false;
private LinkedList<GattOperation> mOperations;
GattOperation mCurrentOperation = null;
private Handler mHandler;
private int mProductId = -1;
private int mReportId = 0;
private UUID mInputCharacteristic;
private static final int D0G_BLE2_PID = 0x1106;
private static final int TRITON_BLE_PID = 0x1303;
private static final int TRANSPORT_AUTO = 0;
private static final int TRANSPORT_BREDR = 1;
@@ -58,14 +45,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000;
static final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicD0G = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicTriton_0x45 = UUID.fromString("100F6C7A-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicTriton_0x47 = UUID.fromString("100F6C7C-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristic = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
static final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3");
static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 };
private HashMap<Integer, BluetoothGattCharacteristic> mOutputReportChars = new HashMap<Integer, BluetoothGattCharacteristic>();
static class GattOperation {
private enum Operation {
CHR_READ,
@@ -78,7 +61,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
byte[] mValue;
BluetoothGatt mGatt;
boolean mResult = true;
int mDelayMs = 0;
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid) {
mGatt = gatt;
@@ -86,13 +68,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mUuid = uuid;
}
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, int delayMs) {
mGatt = gatt;
mOp = operation;
mUuid = uuid;
mDelayMs = delayMs;
}
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value) {
mGatt = gatt;
mOp = operation;
@@ -100,14 +75,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mValue = value;
}
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value, int delayMs) {
mGatt = gatt;
mOp = operation;
mUuid = uuid;
mValue = value;
mDelayMs = delayMs;
}
public void run() {
// This is executed in main thread
BluetoothGattCharacteristic chr;
@@ -169,8 +136,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
return mResult;
}
public int getDelayMs() { return mDelayMs; }
private BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
BluetoothGattService valveService = mGatt.getService(steamControllerService);
if (valveService == null)
@@ -189,10 +154,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid) {
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid);
}
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid, int delayMs) {
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid, delayMs);
}
}
HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) {
@@ -205,8 +166,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mHandler = new Handler(Looper.getMainLooper());
mGatt = connectGatt();
mHasEnabledNotifications = false;
mHasSeenInputUpdate = false;
// final HIDDeviceBLESteamController finalThis = this;
// mHandler.postDelayed(new Runnable() {
// @Override
@@ -355,45 +314,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
Log.v(TAG, "Found Valve steam controller service " + service.getUuid());
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
if (chr.getUuid().equals(inputCharacteristicTriton_0x45)) {
Log.v(TAG, "Found Triton input characteristic 0x45");
mProductId = TRITON_BLE_PID;
mReportId = 0x45;
mInputCharacteristic = chr.getUuid();
} else if (chr.getUuid().equals(inputCharacteristicTriton_0x47)) {
Log.v(TAG, "Found Triton input characteristic 0x47");
mProductId = TRITON_BLE_PID;
mReportId = 0x47;
mInputCharacteristic = chr.getUuid();
} else if (chr.getUuid().equals(inputCharacteristicD0G)) {
Log.v(TAG, "Found D0G input characteristic");
mProductId = D0G_BLE2_PID;
mReportId = 0x03;
mInputCharacteristic = chr.getUuid();
} else {
Pattern reportPattern = Pattern.compile("100F6C([0-9A-Z]{2})", Pattern.CASE_INSENSITIVE);
Matcher matcher = reportPattern.matcher(chr.getUuid().toString());
if (matcher.find()) {
try {
int reportId = Integer.parseInt(matcher.group(1), 16);
reportId -= 0x35;
if (reportId >= 0x80) {
// This is a Triton output report characteristic that we need to care about.
Log.v(TAG, "Found Triton output report 0x" + Integer.toString(reportId, 16));
mOutputReportChars.put(reportId, chr);
}
}
catch (NumberFormatException nfe) {
Log.w(TAG, "Could not parse report characteristic " + chr.getUuid().toString() + ": " + nfe.toString());
}
}
}
}
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
if (chr.getUuid().equals(mInputCharacteristic)) {
if (chr.getUuid().equals(inputCharacteristic)) {
Log.v(TAG, "Found input characteristic");
// Start notifications
BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
if (cccd != null) {
@@ -450,30 +372,21 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mCurrentOperation = mOperations.removeFirst();
}
Runnable gattOperationRunnable = new Runnable() {
@Override
public void run() {
synchronized (mOperations) {
if (mCurrentOperation == null) {
Log.e(TAG, "Current operation null in executor?");
return;
}
mCurrentOperation.run();
// now wait for the GATT callback and when it comes, finish this operation
// Run in main thread
mHandler.post(new Runnable() {
@Override
public void run() {
synchronized (mOperations) {
if (mCurrentOperation == null) {
Log.e(TAG, "Current operation null in executor?");
return;
}
mCurrentOperation.run();
// now wait for the GATT callback and when it comes, finish this operation
}
};
if (mCurrentOperation.getDelayMs() == 0) {
// Run in main thread
mHandler.post(gattOperationRunnable);
}
else {
// If we have a delay on this operation, wait before we post it.
mHandler.postDelayed(gattOperationRunnable, mCurrentOperation.getDelayMs());
}
}
});
}
private void queueGattOperation(GattOperation op) {
@@ -484,39 +397,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
}
private void enableNotification(UUID chrUuid) {
// Add a 500ms delay to notification write for Amazon Fire TV devices, as otherwise if we do this too quickly after connecting
// it will return success and then silently drop the operation on the floor.
GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid, 500);
GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid);
queueGattOperation(op);
// Amazon Fire devices can also silently timeout on writeDescriptor, so
// set up a little delayed check that will attempt to write a second time.
//
// While this only seems to be needed on Amazon Fire TV devices at present, it
// doesn't hurt to have a retry on other devices as well.
//
final HIDDeviceBLESteamController finalThis = this;
final UUID finalUuid = chrUuid;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (!finalThis.mHasEnabledNotifications) {
if (finalThis.mHasSeenInputUpdate) {
// Amazon Five devices may have enabled notifications on the input characteristic and not given us a callback. If we've seen
// input reports, though, somewhat by definition notifications are enabled.
Log.w(TAG, "WriteDescriptor has never returned, but we've seen input reports. Moving on with controller initialization.");
finalThis.mHasEnabledNotifications = true;
finalThis.enableValveMode();
return;
}
// Give one more try.
GattOperation retry = HIDDeviceBLESteamController.GattOperation.enableNotification(finalThis.mGatt, finalUuid, 500);
finalThis.queueGattOperation(retry);
}
}
}, 1000);
}
void writeCharacteristic(UUID uuid, byte[] value) {
@@ -566,16 +448,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mIsConnected = false;
gatt.disconnect();
mGatt = connectGatt(false);
} else {
if (getProductId() == TRITON_BLE_PID) {
// Android will not properly play well with Data Length Extensions without manually requesting a large MTU,
// and Triton controllers require DLE support.
//
// 517 is basically a "magic number" as far as Android's bluetooth code is concerned, so do not change
// this value. It is functionally "please enable data length extensions" on some Android builds.
mGatt.requestMtu(517);
}
}
else {
probeService(this);
}
}
@@ -600,7 +474,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
// Only register controller with the native side once it has been fully configured
if (!isRegistered()) {
Log.v(TAG, "Registering Steam Controller with ID: " + getId());
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId);
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true);
setRegistered();
}
}
@@ -613,8 +487,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
// Enable this for verbose logging of controller input reports
//Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue()));
if (characteristic.getUuid().equals(mInputCharacteristic) && !mFrozen) {
mHasSeenInputUpdate = true;
if (characteristic.getUuid().equals(inputCharacteristic) && !mFrozen) {
mManager.HIDDeviceInputReport(getId(), characteristic.getValue());
}
}
@@ -624,36 +497,19 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
//Log.v(TAG, "onDescriptorRead status=" + status);
}
private void enableValveMode()
{
BluetoothGattService valveService = mGatt.getService(steamControllerService);
if (valveService == null)
return;
BluetoothGattCharacteristic reportChr = valveService.getCharacteristic(reportCharacteristic);
if (reportChr != null) {
if (getProductId() == TRITON_BLE_PID) {
// For Triton we just mark things registered.
Log.v(TAG, "Registering Triton Steam Controller with ID: " + getId());
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId);
setRegistered();
} else {
// For the original controller, we need to manually enter Valve mode.
Log.v(TAG, "Writing report characteristic to enter valve mode");
reportChr.setValue(enterValveMode);
mGatt.writeCharacteristic(reportChr);
}
}
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
BluetoothGattCharacteristic chr = descriptor.getCharacteristic();
//Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid());
if (chr.getUuid().equals(mInputCharacteristic)) {
mHasEnabledNotifications = true;
enableValveMode();
if (chr.getUuid().equals(inputCharacteristic)) {
boolean hasWrittenInputDescriptor = true;
BluetoothGattCharacteristic reportChr = chr.getService().getCharacteristic(reportCharacteristic);
if (reportChr != null) {
Log.v(TAG, "Writing report characteristic to enter valve mode");
reportChr.setValue(enterValveMode);
gatt.writeCharacteristic(reportChr);
}
}
finishCurrentGattOperation();
@@ -692,20 +548,9 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
@Override
public int getProductId() {
if (mProductId > 0) {
// We've already set a product ID.
return mProductId;
}
if (mDevice.getName().startsWith("Steam Ctrl")) {
// We're a newer Triton device
mProductId = TRITON_BLE_PID;
} else {
// We're an OG Steam Controller
mProductId = D0G_BLE2_PID;
}
return mProductId;
// We don't have an easy way to query from the Bluetooth device, but we know what it is
final int D0G_BLE2_PID = 0x1106;
return D0G_BLE2_PID;
}
@Override
@@ -756,29 +601,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
writeCharacteristic(reportCharacteristic, actual_report);
return report.length;
} else {
// If we're an original-recipe Steam Controller we just write to the characteristic directly.
if (getProductId() == D0G_BLE2_PID) {
//Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report));
writeCharacteristic(reportCharacteristic, report);
return report.length;
}
// If we're a Triton, we need to find the correct report characteristic.
if (report.length > 0) {
int reportId = report[0] & 0xFF;
BluetoothGattCharacteristic targetedReportCharacteristic = mOutputReportChars.get(reportId);
if (targetedReportCharacteristic != null) {
byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1);
//Log.v(TAG, "writeOutputReport 0x" + Integer.toString(reportId, 16) + " " + HexDump.dumpHexString(report));
writeCharacteristic(targetedReportCharacteristic.getUuid(), actual_report);
return report.length;
} else {
Log.w(TAG, "Got report write request for unknown report type 0x" + Integer.toString(reportId, 16));
}
}
//Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report));
writeCharacteristic(reportCharacteristic, report);
return report.length;
}
return -1;
}
@Override
@@ -256,7 +256,6 @@ public class HIDDeviceManager {
0x24c6, // PowerA
0x2c22, // Qanba
0x2dc8, // 8BitDo
0x3537, // GameSir
0x37d7, // Flydigi
0x9886, // ASTRO Gaming
};
@@ -361,7 +360,7 @@ public class HIDDeviceManager {
HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index);
int id = device.getId();
mDevicesById.put(id, device);
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false, 0);
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false);
}
}
}
@@ -530,13 +529,7 @@ public class HIDDeviceManager {
return false;
}
// Steam Controllers will always support Bluetooth Low Energy
if ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) == 0) {
return false;
}
// Match on the name either the original Steam Controller or the new second-generation one advertise with.
return bluetoothDevice.getName().equals("SteamController") || bluetoothDevice.getName().startsWith("Steam Ctrl");
return bluetoothDevice.getName().equals("SteamController") && ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) != 0);
}
private void close() {
@@ -688,7 +681,7 @@ public class HIDDeviceManager {
private native void HIDDeviceRegisterCallback();
private native void HIDDeviceReleaseCallback();
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth, int reportID);
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth);
native void HIDDeviceOpenPending(int deviceID);
native void HIDDeviceOpenResult(int deviceID, boolean opened);
native void HIDDeviceDisconnected(int deviceID);
@@ -21,7 +21,6 @@ class HIDDeviceUSB implements HIDDevice {
protected InputThread mInputThread;
protected boolean mRunning;
protected boolean mFrozen;
protected boolean mClaimed;
public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) {
mManager = manager;
@@ -30,7 +29,6 @@ class HIDDeviceUSB implements HIDDevice {
mInterface = mDevice.getInterface(mInterfaceIndex).getId();
mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier());
mRunning = false;
mClaimed = false;
}
String getIdentifier() {
@@ -116,7 +114,6 @@ class HIDDeviceUSB implements HIDDevice {
close();
return false;
}
mClaimed = true;
// Find the endpoints
for (int j = 0; j < iface.getEndpointCount(); j++) {
@@ -135,12 +132,9 @@ class HIDDeviceUSB implements HIDDevice {
}
}
// Make sure the required endpoints were present. The original Steam Controller and the wireless dongle for it do NOT
// actually have -- or require -- output endpoints, so we need to accept only an input one for them or else we'll fall
// back to the Android system gamepad functionality (and lose our paddles et al).
if (mInputEndpoint == null) {
// Make sure the required endpoints were present
if (mInputEndpoint == null || mOutputEndpoint == null) {
Log.w(TAG, "Missing required endpoint on USB device " + getDeviceName());
mConnection.releaseInterface(iface);
close();
return false;
}
@@ -160,11 +154,6 @@ class HIDDeviceUSB implements HIDDevice {
return -1;
}
if (!mClaimed) {
Log.w(TAG, "writeReport() called but some other process currently owns the USB device");
return -1;
}
if (feature) {
int res = -1;
int offset = 0;
@@ -196,11 +185,6 @@ class HIDDeviceUSB implements HIDDevice {
}
return length;
} else {
if (mOutputEndpoint == null)
{
Log.e(TAG, "Tried to write an output report to an interface with no output endpoint!");
return -1;
}
int res = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
if (res != report.length) {
Log.w(TAG, "writeOutputReport() returned " + res + " on device " + getDeviceName());
@@ -221,12 +205,6 @@ class HIDDeviceUSB implements HIDDevice {
Log.w(TAG, "readReport() called with no device connection");
return false;
}
if (!mClaimed) {
if (feature) {
return false;
}
return true;
}
if (report_number == 0x0) {
/* Offset the return buffer by 1, so that the report ID
@@ -280,13 +258,10 @@ class HIDDeviceUSB implements HIDDevice {
mInputThread = null;
}
if (mConnection != null) {
if (mClaimed) {
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
mConnection.releaseInterface(iface);
}
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
mConnection.releaseInterface(iface);
mConnection.close();
mConnection = null;
mClaimed = false;
}
}
@@ -299,22 +274,6 @@ class HIDDeviceUSB implements HIDDevice {
@Override
public void setFrozen(boolean frozen) {
mFrozen = frozen;
/* If we have a valid device connection and the claim state doesn't match what we want, try to correct that. */
if (mConnection != null && mClaimed == mFrozen) {
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
if (frozen) {
mClaimed = !mConnection.releaseInterface(iface);
if (mClaimed) {
Log.e(TAG, "Tried to release claim on USB device, but failed!");
}
} else {
mClaimed = mConnection.claimInterface(iface, true);
if (!mClaimed) {
Log.e(TAG, "Tried to regain claim on USB device, but failed!");
}
}
}
}
protected class InputThread extends Thread {
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 3;
private static final int SDL_MINOR_VERSION = 4;
private static final int SDL_MICRO_VERSION = 10;
private static final int SDL_MICRO_VERSION = 8;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
@@ -530,8 +530,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(true);
}
}
if (!mHasMultiWindow) {
pauseNativeThread();
}
@@ -544,8 +543,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(false);
}
}
if (!mHasMultiWindow) {
resumeNativeThread();
}
@@ -618,14 +616,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
super.onWindowFocusChanged(hasFocus);
Log.v(TAG, "onWindowFocusChanged(): " + hasFocus);
// If we are gaining focus, we can always try to restore our USB devices. If we are losing focus,
// only try to relinquish them if we don't have background events allowed (for multi-window Android setups).
if (hasFocus || !SDLActivity.nativeGetHintBoolean("SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", false)) {
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(!hasFocus);
}
}
if (SDLActivity.mBrokenLibraries) {
return;
}
@@ -1491,11 +1481,11 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
// Note that we process events with specific key codes here
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLControllerManager.onNativePadDown(deviceId, keyCode, event.getScanCode())) {
if (SDLControllerManager.onNativePadDown(deviceId, keyCode)) {
return true;
}
} else if (event.getAction() == KeyEvent.ACTION_UP) {
if (SDLControllerManager.onNativePadUp(deviceId, keyCode, event.getScanCode())) {
if (SDLControllerManager.onNativePadUp(deviceId, keyCode)) {
return true;
}
}
@@ -1973,7 +1963,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
| Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
i.addFlags(flags);
@@ -2237,4 +2227,3 @@ class SDLClipboardHandler implements
SDLActivity.onNativeClipboardChanged();
}
}
@@ -10,10 +10,6 @@ import android.hardware.lights.Light;
import android.hardware.lights.LightsRequest;
import android.hardware.lights.LightsManager;
import android.hardware.lights.LightState;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.graphics.Color;
import android.os.Build;
import android.os.VibrationEffect;
@@ -34,18 +30,16 @@ public class SDLControllerManager
static native void nativeAddJoystick(int device_id, String name, String desc,
int vendor_id, int product_id,
int button_mask,
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led,
boolean has_accelerometer, boolean has_gyroscope);
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led);
static native void nativeRemoveJoystick(int device_id);
static native void nativeAddHaptic(int device_id, String name);
static native void nativeRemoveHaptic(int device_id);
static public native boolean onNativePadDown(int device_id, int keycode, int scancode);
static public native boolean onNativePadUp(int device_id, int keycode, int scancode);
static public native boolean onNativePadDown(int device_id, int keycode);
static public native boolean onNativePadUp(int device_id, int keycode);
static native void onNativeJoy(int device_id, int axis,
float value);
static native void onNativeHat(int device_id, int hat_id,
int x, int y);
static native void onNativeJoySensor(int device_id, int sensor_type, long sensor_timestamp, float x, float y, float z);
protected static SDLJoystickHandler mJoystickHandler;
protected static SDLHapticHandler mHapticHandler;
@@ -87,13 +81,6 @@ public class SDLControllerManager
mJoystickHandler.setLED(device_id, red, green, blue);
}
/**
* This method is called by SDL using JNI.
*/
static void joystickSetSensorsEnabled(int device_id, boolean enabled) {
mJoystickHandler.setSensorsEnabled(device_id, enabled);
}
/**
* This method is called by SDL using JNI.
*/
@@ -166,10 +153,6 @@ class SDLJoystickHandler {
ArrayList<InputDevice.MotionRange> hats;
ArrayList<Light> lights;
LightsManager.LightsSession lightsSession;
SensorManager sensorManager;
SDLJoySensorListener sensorListener;
Sensor accelerometerSensor;
Sensor gyroscopeSensor;
}
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
@Override
@@ -242,13 +225,12 @@ class SDLJoystickHandler {
joystick.desc = getJoystickDescriptor(joystickDevice);
joystick.axes = new ArrayList<InputDevice.MotionRange>();
joystick.hats = new ArrayList<InputDevice.MotionRange>();
java.util.Set<Integer> axisStrsSet = new java.util.HashSet<Integer>();
joystick.lights = new ArrayList<Light>();
List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
Collections.sort(ranges, new RangeComparator());
for (InputDevice.MotionRange range : ranges) {
if (((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) && axisStrsSet.add(range.getAxis())) {
if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
joystick.hats.add(range);
} else {
@@ -259,8 +241,6 @@ class SDLJoystickHandler {
boolean can_rumble = false;
boolean has_rgb_led = false;
boolean has_accelerometer = false;
boolean has_gyroscope = false;
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
VibratorManager vibratorManager = joystickDevice.getVibratorManager();
int[] vibrators = vibratorManager.getVibratorIds();
@@ -278,26 +258,12 @@ class SDLJoystickHandler {
joystick.lightsSession = lightsManager.openSession();
has_rgb_led = true;
}
SensorManager sensorManager = joystickDevice.getSensorManager();
if (sensorManager != null) {
joystick.sensorManager = sensorManager;
joystick.sensorListener = new SDLJoySensorListener(joystick.device_id);
joystick.accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (joystick.accelerometerSensor != null) {
has_accelerometer = true;
}
joystick.gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
if (joystick.gyroscopeSensor != null) {
has_gyroscope = true;
}
}
}
mJoysticks.add(joystick);
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
getVendorId(joystickDevice), getProductId(joystickDevice),
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led,
has_accelerometer, has_gyroscope);
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led);
}
}
}
@@ -542,31 +508,6 @@ class SDLJoystickHandler {
}
joystick.lightsSession.requestLights(lightsRequest.build());
}
void setSensorsEnabled(int device_id, boolean enabled) {
if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
return;
}
SDLJoystick joystick = getJoystick(device_id);
if (joystick == null || joystick.sensorManager == null) {
return;
}
if (enabled) {
if (joystick.accelerometerSensor != null) {
SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
}
if (joystick.gyroscopeSensor != null) {
SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor, SensorManager.SENSOR_DELAY_GAME);
}
} else {
if (joystick.accelerometerSensor != null) {
SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor);
}
if (joystick.gyroscopeSensor != null) {
SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor);
}
}
}
}
class SDLHapticHandler_API31 extends SDLHapticHandler {
@@ -992,19 +933,3 @@ class SDLGenericMotionListener_API29 extends SDLGenericMotionListener_API26 {
return penDevice.isExternal() ? SDL_PEN_DEVICE_TYPE_INDIRECT : SDL_PEN_DEVICE_TYPE_DIRECT;
}
}
class SDLJoySensorListener implements SensorEventListener {
int device_id;
public SDLJoySensorListener(int device_id) {
this.device_id = device_id;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
@Override
public void onSensorChanged(SensorEvent event) {
SDLControllerManager.onNativeJoySensor(device_id, event.sensor.getType(), event.timestamp, event.values[0], event.values[1], event.values[2]);
}
}
@@ -1,32 +0,0 @@
package org.libsdl.app;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
// This class coordinates synchronized access to sensor manager registration
//
// This prevents a java.util.ConcurrentModificationException exception on
// Android 16, specifically on the Samsung Tab S9 Ultra.
class SDLSensorManager
{
static private SDLSensorManager mManager = new SDLSensorManager();
public static void registerListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
mManager.RegisterListener(manager, listener, sensor, samplingPeriodUs);
}
public static void unregisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor) {
mManager.UnregisterListener(manager, listener, sensor);
}
private synchronized void RegisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
manager.registerListener(listener, sensor, samplingPeriodUs, null);
}
private synchronized void UnregisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor) {
manager.unregisterListener(listener, sensor);
}
}
@@ -47,9 +47,6 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// Is SurfaceView ready for rendering
protected boolean mIsSurfaceReady;
// Is on-screen keyboard visible
protected boolean mKeyboardVisible;
// Pinch events
private final ScaleGestureDetector scaleGestureDetector;
@@ -216,18 +213,6 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
WindowInsets.Type.displayCutout());
SDLActivity.onNativeInsetsChanged(combined.left, combined.right, combined.top, combined.bottom);
if (insets.isVisible(WindowInsets.Type.ime())) {
if (!mKeyboardVisible) {
mKeyboardVisible = true;
SDLActivity.onNativeScreenKeyboardShown();
}
} else {
if (mKeyboardVisible) {
mKeyboardVisible = false;
SDLActivity.onNativeScreenKeyboardHidden();
}
}
}
// Pass these to any child views in case they need them
@@ -333,11 +318,11 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
protected void enableSensor(int sensortype, boolean enabled) {
// TODO: This uses getDefaultSensor - what if we have >1 accels?
if (enabled) {
SDLSensorManager.registerListener(mSensorManager, this,
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(sensortype),
SensorManager.SENSOR_DELAY_GAME);
SensorManager.SENSOR_DELAY_GAME, null);
} else {
SDLSensorManager.unregisterListener(mSensorManager, this,
mSensorManager.unregisterListener(this,
mSensorManager.getDefaultSensor(sensortype));
}
}
@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>dev.twilitrealm.dusk</id>
<launchable type="desktop-id">dev.twilitrealm.dusk.desktop</launchable>
<name>Dusklight</name>
<summary>Native port of a classic adventure game</summary>
<developer id="dev.twilitrealm">
<name>Twilit Realm</name>
</developer>
<url type="homepage">https://twilitrealm.dev</url>
<url type="bugtracker">https://github.com/TwilitRealm/dusklight/issues</url>
<metadata_license>CC0-1.0</metadata_license>
<project_license>CC0-1.0</project_license>
<content_rating type="oars-1.0"/>
<supports>
<control>console</control>
<control>gamepad</control>
</supports>
<description>
<p>
Dusklight is a reverse-engineered reimplementation of a classic adventure game.
It aims to be as accurate as possible to the original while also providing new options, enhancements, and tools to customize your experience.
</p>
</description>
<provides>
<binary>dusklight</binary>
<id>dev.twilitrealm.dusk.desktop</id>
</provides>
<releases>
<release version="UNRELEASED" date="2026-12-31">
<description>
<p>Initial Flatpak release.</p>
</description>
</release>
</releases>
</component>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
File diff suppressed because it is too large Load Diff
+3 -53
View File
@@ -16,12 +16,11 @@ body {
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
z-index: 2;
z-index: 1;
pointer-events: none;
}
fps,
pipeline-progress,
toast {
position: absolute;
border: 1dp #92875B;
@@ -99,7 +98,7 @@ toast message row.muted {
opacity: 0.5;
}
progress {
toast progress {
height: 4dp;
position: absolute;
left: 0;
@@ -107,50 +106,10 @@ progress {
width: 100%;
}
progress fill {
toast progress fill {
background-color: rgba(194, 164, 45, 80%);
}
pipeline-progress {
left: 12dp;
bottom: 12dp;
display: flex;
flex-flow: column;
z-index: 100;
min-width: 260dp;
max-width: 90%;
padding: 10dp 16dp 12dp;
border-radius: 7dp;
overflow: hidden;
filter: opacity(0);
transition: filter 0.2s linear-in-out;
pointer-events: none;
}
pipeline-progress[open] {
filter: opacity(1);
}
pipeline-status {
display: flex;
align-items: center;
gap: 8dp;
font-size: 18dp;
font-weight: normal;
white-space: nowrap;
}
icon.pipeline-spinner {
width: 1.2em;
height: 1.2em;
line-height: 1.2em;
font-size: 1.2em;
color: #C2A42D;
text-align: center;
transform-origin: center;
animation: 1s linear infinite pipeline-spinner-spin;
}
toast.achievement {
border: 1dp #C2A42D;
}
@@ -351,15 +310,6 @@ logo img.outer {
}
}
@keyframes pipeline-spinner-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (max-height: 640dp) {
toast {
top: 20dp;
-4
View File
@@ -362,10 +362,6 @@ body.animate-in .intro-item {
transition: opacity transform 0.3s 0.6s cubic-in-out;
}
.delay-6 {
transition: opacity transform 0.3s 0.7s cubic-in-out;
}
/* Mobile layout */
@media (max-height: 640dp) {
.gradient {
-339
View File
@@ -1,339 +0,0 @@
*, *:before, *:after {
box-sizing: border-box;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
font-family: "Fira Sans Condensed";
font-weight: bold;
color: rgba(248, 244, 232, 90%);
z-index: 1;
filter: opacity(0);
transition: filter 0.2s linear-in-out;
}
body[open] {
filter: opacity(1);
}
body:not([open]) {
pointer-events: none;
}
button {
display: flex;
align-items: center;
justify-content: center;
decorator: none;
padding: 0;
border: 1dp rgba(255, 255, 255, 22%);
background-color: rgba(22, 24, 28, 48%);
color: rgba(248, 244, 232, 90%);
text-align: center;
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 6dp 18dp rgba(0, 0, 0, 28%); */
transform-origin: center;
transition: background-color border-color filter transform 0.08s linear-in-out,
opacity 0.2s linear-in-out;
}
button.pressed,
button.active {
background-color: rgba(63, 78, 90, 68%);
border-color: rgba(255, 255, 255, 48%);
filter: brightness(1.18);
}
button:hidden {
opacity: 0;
pointer-events: none;
}
button span {
display: block;
line-height: 1;
}
button icon {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
button icon glyph {
display: block;
font-family: "Material Symbols Rounded";
font-weight: normal;
font-size: 24dp;
line-height: 1;
}
.midna-icon,
.item-icon,
.item-count,
.oil-meter {
display: none;
}
.midna-icon.visible,
.item-icon.visible,
.item-count.visible,
.oil-meter.visible {
display: block;
}
.control {
position: absolute;
}
.trigger-l.active {
background-color: rgba(57, 116, 133, 74%);
border-color: rgba(128, 222, 234, 72%);
}
.trigger,
.skip {
border-radius: 23dp;
}
.trigger {
font-size: 22dp;
}
.button-z {
background-color: rgba(118, 79, 158, 58%);
border-color: rgba(203, 170, 255, 36%);
}
.midna-icon {
position: absolute;
left: 9dp;
top: -1dp;
height: 48dp;
}
.button-z.has-icon span,
.face.has-item span {
position: absolute;
font-size: 13dp;
line-height: 1;
}
.button-z.has-icon span {
right: 9dp;
bottom: 7dp;
}
.button-z.pressed {
background-color: rgba(139, 91, 187, 82%);
border-color: rgba(220, 194, 255, 70%);
}
action-bar {
position: absolute;
display: flex;
align-items: center;
border: 1dp rgba(255, 255, 255, 22%);
border-radius: 23dp;
background-color: rgba(22, 24, 28, 48%);
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 -6dp 18dp rgba(0, 0, 0, 28%); */
overflow: hidden;
opacity: 1;
transform-origin: center;
transition: opacity 0.2s linear-in-out;
}
action-bar:hidden,
action-bar:hidden button,
action-bar:hidden separator {
opacity: 0;
pointer-events: none;
}
.utility {
position: relative;
flex: 1 1 auto;
width: 56dp;
height: 44dp;
margin: 0;
border-width: 0dp;
border-radius: 0;
background-color: transparent;
box-shadow: none;
}
.utility,
.skip {
opacity: 0.55;
}
.utility.pressed {
background-color: rgba(63, 78, 90, 68%);
}
.utility.pressed,
.skip.pressed {
opacity: 1;
}
.skip {
z-index: 1;
border-color: rgba(255, 255, 255, 36%);
}
separator {
display: block;
flex: 0 0 1dp;
width: 1dp;
height: 24dp;
background-color: rgba(255, 255, 255, 18%);
opacity: 1;
transition: opacity 0.2s linear-in-out;
}
.face {
position: absolute;
border-radius: 29dp;
font-size: 24dp;
overflow: visible;
}
.item-icon {
width: auto;
height: auto;
max-width: 76%;
max-height: 76%;
}
.item-count {
position: absolute;
left: 6dp;
bottom: 5dp;
min-width: 17dp;
height: 15dp;
padding: 1dp 3dp;
border-radius: 7dp;
background-color: rgba(0, 0, 0, 52%);
color: rgba(255, 255, 255, 92%);
font-size: 12dp;
line-height: 13dp;
text-align: center;
}
.oil-meter {
position: absolute;
left: 12dp;
bottom: -5dp;
width: 34dp;
height: 8dp;
padding: 2dp;
border: 1dp rgba(42, 32, 18, 82%);
border-radius: 4dp;
background-color: rgba(18, 14, 10, 70%);
/* box-shadow: 0 2dp 6dp rgba(0, 0, 0, 35%); */
}
oil-fill {
display: block;
width: 0%;
height: 100%;
border-radius: 2dp;
background-color: rgb(255, 232, 74);
}
.face.has-item span {
right: 6dp;
bottom: 6dp;
color: rgba(255, 255, 255, 88%);
}
.face.a {
border-radius: 37dp;
font-size: 31dp;
background-color: rgba(34, 112, 123, 62%);
}
.face.b {
background-color: rgba(161, 61, 66, 58%);
}
.face.x {
background-color: rgba(83, 115, 151, 56%);
}
.face.y {
background-color: rgba(113, 91, 150, 54%);
}
button.control.docked-top,
action-bar.docked-top {
border-top-width: 0dp;
border-top-left-radius: 0dp;
border-top-right-radius: 0dp;
}
button.control.docked-bottom,
action-bar.docked-bottom {
border-bottom-width: 0dp;
border-bottom-left-radius: 0dp;
border-bottom-right-radius: 0dp;
}
button.control.docked-left,
action-bar.docked-left {
border-left-width: 0dp;
border-top-left-radius: 0dp;
border-bottom-left-radius: 0dp;
}
button.control.docked-right,
action-bar.docked-right {
border-right-width: 0dp;
border-top-right-radius: 0dp;
border-bottom-right-radius: 0dp;
}
touch-stick {
display: block;
position: absolute;
width: 124dp;
height: 124dp;
border-radius: 62dp;
background-color: rgba(18, 20, 24, 35%);
border: 1dp rgba(255, 255, 255, 20%);
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 8dp 24dp rgba(0, 0, 0, 24%); */
opacity: 0;
pointer-events: none;
transition: opacity 0.18s linear-in-out;
}
touch-stick.active {
opacity: 1;
}
stick-ring {
position: absolute;
left: 18dp;
top: 18dp;
width: 88dp;
height: 88dp;
border-radius: 44dp;
border: 1dp rgba(255, 255, 255, 18%);
}
stick-knob {
position: absolute;
width: 48dp;
height: 48dp;
border-radius: 24dp;
background-color: rgba(238, 236, 226, 55%);
border: 1dp rgba(255, 255, 255, 45%);
}
-138
View File
@@ -1,138 +0,0 @@
body.touch-editor {
background-color: rgba(4, 6, 8, 34%);
z-index: 8;
}
body.touch-editor .control,
body.touch-editor action-bar {
opacity: 0.88;
cursor: move;
pointer-events: auto;
}
body.touch-editor .control:hover,
body.touch-editor action-bar:hover,
body.touch-editor .control.editor-selected,
body.touch-editor action-bar.editor-selected {
border-color: rgba(255, 232, 128, 80%);
filter: brightness(1.15);
}
body.touch-editor action-bar button,
body.touch-editor action-bar separator {
pointer-events: none;
}
selection-frame {
display: none;
position: absolute;
z-index: 20;
border: 2dp rgba(255, 232, 128, 88%);
background-color: rgba(255, 232, 128, 7%);
pointer-events: none;
}
selection-frame.visible {
display: block;
}
resize-handle {
display: block;
position: absolute;
width: 22dp;
height: 22dp;
border: 2dp rgba(255, 244, 190, 96%);
border-radius: 11dp;
background-color: rgba(34, 37, 42, 86%);
pointer-events: auto;
}
resize-handle.left {
left: -12dp;
}
resize-handle.right {
right: -12dp;
}
resize-handle.top {
top: -12dp;
}
resize-handle.bottom {
bottom: -12dp;
}
resize-handle.horizontal {
top: 50%;
margin-top: -11dp;
}
resize-handle.vertical {
left: 50%;
margin-left: -11dp;
}
resize-handle.corner.left {
left: -12dp;
}
resize-handle.corner.right {
right: -12dp;
}
resize-handle.corner.top {
top: -12dp;
}
resize-handle.corner.bottom {
bottom: -12dp;
}
editor-toolbar {
display: flex;
position: absolute;
left: 24dp;
right: 24dp;
top: 50%;
z-index: 30;
height: 48dp;
margin-top: -24dp;
gap: 8dp;
justify-content: center;
pointer-events: auto;
}
editor-toolbar button.editor-command {
flex: 0 1 150dp;
min-width: 96dp;
height: 48dp;
padding: 0 14dp;
border-radius: 8dp;
border: 1dp rgba(255, 255, 255, 26%);
background-color: rgba(17, 19, 24, 88%);
color: rgba(255, 250, 232, 94%);
font-family: "Fira Sans";
font-size: 18dp;
line-height: 48dp;
opacity: 1;
cursor: pointer;
}
editor-toolbar button.editor-command span {
display: block;
width: 100%;
line-height: 48dp;
text-align: center;
}
editor-toolbar button.editor-command.primary {
border-color: rgba(255, 232, 128, 70%);
background-color: rgba(96, 82, 38, 90%);
}
editor-toolbar button.editor-command:hover,
editor-toolbar button.editor-command:focus-visible {
border-color: rgba(255, 244, 190, 92%);
background-color: rgba(78, 85, 96, 92%);
}
-29
View File
@@ -395,11 +395,6 @@ progress.progress-ongoing fill {
border-radius: 3dp;
}
progress.progress-health fill {
background-color: #cc3322;
border-radius: 3dp;
}
button.achievement-clear {
flex: 0 0 auto;
align-self: center;
@@ -514,30 +509,6 @@ progress.verification-progress-bar {
color: rgba(224, 219, 200, 65%);
}
.mod-info-row {
display: flex;
align-items: center;
gap: 12dp;
padding: 4dp 0;
}
.mod-info-label {
font-family: "Fira Sans Condensed";
font-weight: bold;
opacity: 0.55;
flex: 0 0 80dp;
}
.mod-info-value {
flex: 1 1 0;
}
.mod-path {
font-size: 14dp;
word-break: break-all;
opacity: 0.7;
}
.modal-actions {
display: flex;
flex-direction: row;
-6
View File
@@ -142,12 +142,6 @@ DynamicModuleControl::DynamicModuleControl(char const* name) {
}
#endif
#if TARGET_PC
// dump() is declared but its definition is inside #if !TARGET_PC above; stub it out.
void DynamicModuleControlBase::dump() {}
void DynamicModuleControlBase::dump(char*) {}
#endif
u32 DynamicModuleControl::sAllocBytes;
JKRArchive* DynamicModuleControl::sArchive;
+1 -1
View File
@@ -19,7 +19,7 @@
#include "Z2AudioCS/Z2AudioCS.h"
#endif
DUSK_GAME_DATA Z2AudioMgr* Z2AudioMgr::mAudioMgrPtr;
Z2AudioMgr* Z2AudioMgr::mAudioMgrPtr;
u8 gMuffleOutOfRangeMic = false;
Z2AudioMgr::Z2AudioMgr() : mSoundStarter(true) {
+18 -46
View File
@@ -12734,19 +12734,7 @@ void daAlink_c::setMagicArmorBrk(int i_status) {
BOOL daAlink_c::checkMagicArmorHeavy() const {
#if TARGET_PC
if(!checkMagicArmorWearAbility()) {
return false;
}
switch(dusk::getSettings().game.armorRupeeDrain) {
case dusk::MagicArmorMode::NORMAL:
return dComIfGs_getRupee() == 0;
case dusk::MagicArmorMode::ON_DAMAGE:
case dusk::MagicArmorMode::DOUBLE_DEFENSE:
case dusk::MagicArmorMode::INVINCIBLE:
case dusk::MagicArmorMode::COSMETIC:
return false;
}
return checkMagicArmorWearAbility() && (dComIfGs_getRupee() == 0 && !dusk::getSettings().game.freeMagicArmor);
#else
return checkMagicArmorWearAbility() && dComIfGs_getRupee() == 0;
#endif
@@ -14808,8 +14796,6 @@ void daAlink_c::deleteEquipItem(BOOL i_isPlaySound, BOOL i_isDeleteKantera) {
#if TARGET_PC
mIBChainInterpPrevValid = false;
mIBChainInterpCurrValid = false;
mHsChainInterpPrevValid = false;
mHsChainInterpCurrValid = false;
#endif
field_0x0774 = NULL;
field_0x0778 = NULL;
@@ -18721,7 +18707,7 @@ int daAlink_c::execute() {
#if TARGET_PC
// This handles rupee drain and transitions between rupees/no rupees
// We can skip all of that if the magic armor doesn't use rupees
if (dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::NORMAL && checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
if (!dusk::getSettings().game.freeMagicArmor && checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
#else
if (checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
#endif
@@ -19782,37 +19768,23 @@ int daAlink_c::draw() {
dComIfGd_getOpaListDark()->entryImm(mpHookChain, 0);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (mEquipItem == dItemNo_IRONBALL_e &&
mIronBallChainPos != NULL && mIronBallChainAngle != NULL)
{
if (mIBChainInterpCurrValid) {
memcpy(mIBChainInterpPrevPos, mIBChainInterpCurrPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpPrevAngle, mIBChainInterpCurrAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpPrevHandRoot = mIBChainInterpCurrHandRoot;
mIBChainInterpPrevValid = true;
}
memcpy(mIBChainInterpCurrPos, mIronBallChainPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpCurrAngle, mIronBallChainAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpCurrHandRoot = mHookshotTopPos;
mIBChainInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&ironBallChainInterpCallback, this);
} else {
if (mHsChainInterpCurrValid) {
mHsChainInterpPrevTop = mHsChainInterpCurrTop;
mHsChainInterpPrevRoot = mHsChainInterpCurrRoot;
mHsChainInterpPrevSubRoot = mHsChainInterpCurrSubRoot;
mHsChainInterpPrevSubTop = mHsChainInterpCurrSubTop;
mHsChainInterpPrevValid = true;
}
mHsChainInterpCurrTop = mHookshotTopPos;
mHsChainInterpCurrRoot = mHeldItemRootPos;
mHsChainInterpCurrSubRoot = field_0x3810;
mHsChainInterpCurrSubTop = mIronBallBgChkPos;
mHsChainInterpCurrValid = true;
if (dusk::frame_interp::is_enabled() &&
mEquipItem == dItemNo_IRONBALL_e &&
mIronBallChainPos != NULL && mIronBallChainAngle != NULL)
{
if (mIBChainInterpCurrValid) {
memcpy(mIBChainInterpPrevPos, mIBChainInterpCurrPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpPrevAngle, mIBChainInterpCurrAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpPrevHandRoot = mIBChainInterpCurrHandRoot;
mIBChainInterpPrevValid = true;
}
memcpy(mIBChainInterpCurrPos, mIronBallChainPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpCurrAngle, mIronBallChainAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpCurrHandRoot = mHookshotTopPos;
mIBChainInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&ironBallChainInterpCallback, this);
}
#endif
}
+1 -25
View File
@@ -192,7 +192,7 @@ int daAlink_c::setDamagePoint(int i_dmgAmount, BOOL i_checkZoraMag, BOOL i_setDm
if (checkMagicArmorNoDamage()) {
#if TARGET_PC
if(dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::INVINCIBLE) {
if(dusk::getSettings().game.freeMagicArmor) {
i_dmgAmount = 0;
}
#endif
@@ -202,11 +202,6 @@ int daAlink_c::setDamagePoint(int i_dmgAmount, BOOL i_checkZoraMag, BOOL i_setDm
if (!mpHIO->mDamage.m.mInvincible && g_debugHpMode == 0)
#endif
{
#if TARGET_PC
if(checkMagicArmorWearAbility() && dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::DOUBLE_DEFENSE) {
i_dmgAmount /= 2;
}
#endif
dComIfGp_setItemLifeCount(-i_dmgAmount, 0);
}
@@ -286,26 +281,7 @@ BOOL daAlink_c::checkIcePolygonDamage(cBgS_PolyInfo* i_poly) {
}
BOOL daAlink_c::checkMagicArmorNoDamage() {
#ifdef TARGET_PC
if (!checkMagicArmorWearAbility()) {
return false;
}
switch(dusk::getSettings().game.armorRupeeDrain) {
case dusk::MagicArmorMode::NORMAL:
return !checkMagicArmorHeavy();
case dusk::MagicArmorMode::ON_DAMAGE:
return dComIfGs_getRupee() != 0;
case dusk::MagicArmorMode::DOUBLE_DEFENSE:
return false;
case dusk::MagicArmorMode::INVINCIBLE:
return true;
case dusk::MagicArmorMode::COSMETIC:
return false;
}
#else
return checkMagicArmorWearAbility() && !checkMagicArmorHeavy();
#endif
}
int daAlink_c::checkPolyDamage() {
+1 -11
View File
@@ -144,7 +144,7 @@ void daAlink_c::handleQuickTransform() {
procCoMetamorphoseInit();
}
bool daAlink_c::checkAimContext() {
bool daAlink_c::checkGyroAimContext() {
switch (mProcID) {
case PROC_SUBJECTIVITY:
case PROC_SWIM_SUBJECTIVITY:
@@ -175,13 +175,3 @@ bool daAlink_c::checkAimContext() {
return false;
}
}
bool daAlink_c::checkAimInputContext() {
switch (mProcID) {
case PROC_HOOKSHOT_ROOF_WAIT:
case PROC_HOOKSHOT_WALL_WAIT:
return false;
default:
return checkAimContext();
}
}
+3 -16
View File
@@ -2028,10 +2028,11 @@ void daAlink_blur_c::traceBlur(cXyz const* param_0, cXyz const* param_1, s16 par
}
void daAlink_blur_c::draw() {
ZoneScoped;
j3dSys.reinitGX();
#if !TARGET_PC
#ifdef TARGET_PC
TGXTexObj texObj;
#else
static TGXTexObj texObj;
#endif
static GXColor nColor0 = {0xFF, 0xFF, 0xFF, 0x14};
@@ -2039,25 +2040,11 @@ void daAlink_blur_c::draw() {
GXSetNumIndStages(0);
nColor0.a = field_0x20;
#if TARGET_PC
if (mpCachedBlurTex != m_blurTex) {
mBlurTexObj.reset();
GXInitTexObj(&mBlurTexObj,
reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(m_blurTex) + m_blurTex->imageOffset),
16, 4, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(
&mBlurTexObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
mpCachedBlurTex = m_blurTex;
}
GXLoadTexObj(&mBlurTexObj, GX_TEXMAP0);
#else
GXInitTexObj(&texObj, (void*)((uintptr_t)m_blurTex + m_blurTex->imageOffset), 16, 4, GX_TF_I4,
GX_CLAMP, GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(&texObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE,
GX_ANISO_1);
GXLoadTexObj(&texObj, GX_TEXMAP0);
#endif
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBA4, 8);
GXClearVtxDesc();
-23
View File
@@ -136,26 +136,8 @@ void daAlink_c::hsChainShape_c::draw() {
}
}
} else {
#if TARGET_PC
cXyz hsInterpTop, hsInterpRoot, hsInterpSubRoot, hsInterpSubTop;
if (dusk::frame_interp::is_enabled() && alink->mHsChainInterpPrevValid && alink->mHsChainInterpCurrValid) {
const f32 alpha = dusk::frame_interp::get_interpolation_step();
hsInterpTop = alink->mHsChainInterpPrevTop + (alink->mHsChainInterpCurrTop - alink->mHsChainInterpPrevTop) * alpha;
hsInterpRoot = alink->mHsChainInterpPrevRoot + (alink->mHsChainInterpCurrRoot - alink->mHsChainInterpPrevRoot) * alpha;
hsInterpSubRoot = alink->mHsChainInterpPrevSubRoot + (alink->mHsChainInterpCurrSubRoot - alink->mHsChainInterpPrevSubRoot) * alpha;
hsInterpSubTop = alink->mHsChainInterpPrevSubTop + (alink->mHsChainInterpCurrSubTop - alink->mHsChainInterpPrevSubTop) * alpha;
} else {
hsInterpTop = alink->getHsChainTopPos();
hsInterpRoot = alink->getHsChainRootPos();
hsInterpSubRoot = alink->getHsSubChainRootPos();
hsInterpSubTop = alink->getHsSubChainTopPos();
}
const cXyz& chainRootPos = hsInterpRoot;
const cXyz& chainTopPos = hsInterpTop;
#else
const cXyz& chainRootPos = alink->getHsChainRootPos();
const cXyz& chainTopPos = alink->getHsChainTopPos();
#endif
cXyz maxDistance = chainRootPos - chainTopPos;
f32 maxDistanceF = maxDistance.abs();
@@ -218,13 +200,8 @@ void daAlink_c::hsChainShape_c::draw() {
}
}
#if TARGET_PC
const cXyz& subChainRootPos = hsInterpSubRoot;
const cXyz& subChainTopPos = hsInterpSubTop;
#else
const cXyz& subChainRootPos = alink->getHsSubChainRootPos();
const cXyz& subChainTopPos = alink->getHsSubChainTopPos();
#endif
maxDistance = subChainRootPos - subChainTopPos;
maxDistanceF = maxDistance.abs();
+11 -58
View File
@@ -11,10 +11,8 @@
#include "d/actor/d_a_tag_mhint.h"
#if TARGET_PC
#include "dusk/action_bindings.h"
#include "dusk/gyro.h"
#include "dusk/mouse.h"
#include "dusk/touch_camera.h"
#include "dusk/action_bindings.h"
#endif
bool daAlink_c::checkNoSubjectModeCamera() {
@@ -122,28 +120,18 @@ BOOL daAlink_c::setBodyAngleToCamera() {
var_f31 /= dComIfGp_getCameraZoomScale(field_0x317c);
}
#if TARGET_PC
if (dusk::getSettings().game.enableMouseAim && checkAimInputContext()) {
sp8 = mBodyAngle.x;
} else
#endif
{
shape_angle.y = shape_angle.y + (var_f31 * cM_ssin(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonXAxis ? -1.0f : 1.0f)));
sp8 = mBodyAngle.x + (var_f31 * cM_scos(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonYAxis ? -1.0f : 1.0f)));
shape_angle.y = shape_angle.y + (var_f31 * cM_ssin(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonXAxis ? -1.0f : 1.0f)));
sp8 = mBodyAngle.x + (var_f31 * cM_scos(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonYAxis ? -1.0f : 1.0f)));
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
} else {
sp8 = mBodyAngle.x;
}
#if TARGET_PC
if ((dusk::getSettings().game.enableGyroAim ||
dusk::getSettings().game.enableMouseAim) &&
checkAimInputContext())
{
if (dusk::getSettings().game.enableGyroAim && checkGyroAimContext()) {
f32 gyro_scale = 1.0f;
if (checkWolfEyeUp()) {
gyro_scale *= 0.6f;
@@ -153,52 +141,17 @@ BOOL daAlink_c::setBodyAngleToCamera() {
gyro_scale /= dComIfGp_getCameraZoomScale(field_0x317c);
}
f32 final_yaw = 0.f;
f32 final_pitch = 0.f;
if (dusk::getSettings().game.enableMouseAim) {
dusk::mouse::getAimDeltas(final_yaw, final_pitch);
}
if (dusk::getSettings().game.enableGyroAim) {
f32 gyro_yaw = 0.f;
f32 gyro_pitch = 0.f;
dusk::gyro::getAimDeltas(gyro_yaw, gyro_pitch);
final_yaw += gyro_yaw;
final_pitch += gyro_pitch;
}
f32 gy_yaw = 0.f;
f32 gy_pitch = 0.f;
dusk::gyro::getAimDeltas(gy_yaw, gy_pitch);
shape_angle.y = shape_angle.y + cM_rad2s(final_yaw * gyro_scale);
sp8 = sp8 + cM_rad2s(final_pitch * gyro_scale);
shape_angle.y = shape_angle.y + cM_rad2s(gy_yaw * gyro_scale);
sp8 = sp8 + cM_rad2s(gy_pitch * gyro_scale);
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
}
if (dusk::getSettings().game.enableTouchControls && checkAimInputContext()) {
f32 touchYawDp = 0.0f;
f32 touchPitchDp = 0.0f;
if (dusk::touch_camera::consume_delta(touchYawDp, touchPitchDp)) {
f32 scale = 1.0f;
if (checkWolfEyeUp()) {
scale *= 0.6f;
}
if (dComIfGp_checkPlayerStatus0(0, 0x200000)) {
scale /= dComIfGp_getCameraZoomScale(field_0x317c);
}
const f32 yawDeg = -touchYawDp * dusk::touch_camera::YAW_DEGREES_PER_DP * scale *
dusk::getSettings().game.touchCameraXSensitivity;
const f32 pitchDeg = touchPitchDp * dusk::touch_camera::PITCH_DEGREES_PER_DP *
scale * dusk::getSettings().game.touchCameraYSensitivity;
shape_angle.y = shape_angle.y + cM_deg2s(yawDeg);
sp8 = sp8 + cM_deg2s(pitchDeg);
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
}
}
#endif
if (checkNotItemSinkLimit() && sp8 > 0) {
+2 -2
View File
@@ -348,7 +348,7 @@ void daAlink_c::changeLink(int param_0) {
initModel(static_cast<J3DModelData*>(dComIfG_getObjectRes(l_mArcName, "al_hands.bmd")), 0);
#if TARGET_PC
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.armorRupeeDrain.getValue() != dusk::MagicArmorMode::NORMAL)
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.freeMagicArmor)
#else
if (dComIfGs_getRupee() != 0)
#endif
@@ -458,7 +458,7 @@ void daAlink_c::changeLink(int param_0) {
field_0x06f0 = field_0x064C->getMaterialNodePointer(2)->getShape();
#if TARGET_PC
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.armorRupeeDrain.getValue() != dusk::MagicArmorMode::NORMAL) {
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.freeMagicArmor) {
#else
if (dComIfGs_getRupee() != 0) {
#endif
-9
View File
@@ -5472,15 +5472,6 @@ int daB_ZANT_c::create() {
fopAcM_ct(this, daB_ZANT_c);
OS_REPORT("B_ZANT PARAM %x\n", fopAcM_GetParam(this));
#if TARGET_PC
// Due to our loads being so much faster, Zant can initialize *before* the player
// This breaks respawning in the final phase of the fight when it tries
// to load the player's position
if (daPy_getPlayerActorClass() == NULL) {
return cPhs_INIT_e;
}
#endif
mSwbit = fopAcM_GetParam(this);
if (mSwbit != 0xFF) {
if (dComIfGs_isSwitch(mSwbit, fopAcM_GetRoomNo(this))) {
-8
View File
@@ -923,14 +923,6 @@ static void damage_check(e_sm2_class* i_this) {
sm_hit_actor->mode = 10;
u8 new_color_type = new_col_d[(sm_hit_actor->type * 7) + i_this->type];
#if TARGET_PC
if (dusk::getSettings().game.restoreWiiGlitches &&
((sm_hit_actor->type == TYPE_BLUE && i_this->type == TYPE_YELLOW) ||
(sm_hit_actor->type == TYPE_YELLOW && i_this->type == TYPE_BLUE)))
{
new_color_type = TYPE_GREEN;
}
#endif
i_this->type = new_color_type;
sm_hit_actor->type = new_color_type;
+231 -60
View File
@@ -16,30 +16,12 @@
using GameVersion = dusk::version::GameVersion;
// keep the original version of the cape texture const so we don't need to reload the file
static u8 const * l_Egnd_mantTEX_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x1C00}, {GameVersion::GcnPal, 0x1C00}}, 0x4000), true); return buf; }
static u8* l_Egnd_mantTEX_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x1C00}, {GameVersion::GcnPal, 0x1C00}}, 0x4000), true); return buf; }
static u8* l_Egnd_mantTEX_U_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x5C00}, {GameVersion::GcnPal, 0x5C00}}, 0x4000), true); return buf; }
static u8* l_Egnd_mantPAL_get() { alignas(32) static u8 buf[0x60]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x9C00}, {GameVersion::GcnPal, 0x9C00}}, 0x60), true); return buf; }
#define l_Egnd_mantTEX (l_Egnd_mantTEX_get())
#define l_Egnd_mantTEX_U (l_Egnd_mantTEX_U_get())
#define l_Egnd_mantPAL (l_Egnd_mantPAL_get())
// make a copy of the cape texture that can be overwritten with the tears
static u8 l_Egnd_mantTEX_copy[0x4000];
// keep our cached texture objects out here so that we can update them from multiple places
static bool textureObjsInitialized = false;
static TGXTlutObj tlutObj;
static TGXTexObj mainTexObj;
static TGXTexObj undersideTexObj;
// l_pos is unused
//static f32* l_pos_get() { alignas(32) static f32 buf[507]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0xA44C}, {GameVersion::GcnPal, 0xA44C}}, sizeof(buf)), true); return buf; }
static f32* l_normal_get() { alignas(32) static f32 buf[3]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x9C60}, {GameVersion::GcnPal, 0x9C60}}, sizeof(buf)), true); return buf; }
static f32* l_texCoord_get() { alignas(32) static f32 buf[338]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0xA458}, {GameVersion::GcnPal, 0xA458}}, sizeof(buf)), true); return buf; }
//#define l_pos (l_pos_get())
#define l_normal (l_normal_get())
#define l_texCoord (l_texCoord_get())
#else
#include "assets/l_Egnd_mantTEX.h"
@@ -49,6 +31,228 @@ static f32* l_texCoord_get() { alignas(32) static f32 buf[338]; static bool _
#endif
#include "d/d_s_play.h"
static u32 l_pos[507] = {
0x42480000, 0x3F5CFC93, 0xC365BD9C, 0x4226AAAA,
0x3F5CFC93, 0xC365BD9C, 0x42055556, 0x3F5CFC93,
0xC365BD9C, 0x41C80000, 0x3F5CFC93, 0xC365BD9C,
0x41855556, 0x3F5CFC93, 0xC365BD9C, 0x41055556,
0x3F5CFC93, 0xC365BD9C, 0x358637BD, 0x3F5CFC93,
0xC365BD9C, 0xC1055554, 0x3F5CFC93, 0xC365BD9C,
0xC1855554, 0x3F5CFC93, 0xC365BD9C, 0xC1C7FFFF,
0x3F5CFC93, 0xC365BD9C, 0xC2055554, 0x3F5CFC93,
0xC365BD9C, 0xC226AAAA, 0x3F5CFC93, 0xC365BD9C,
0xC2480000, 0x3F5CFC93, 0xC365BD9C, 0x42480000,
0x3F5CFC93, 0xC35292F0, 0x4226AAAA, 0x3F5CFC93,
0xC35292F0, 0x42055556, 0x3F5CFC93, 0xC35292F0,
0x41C80000, 0x3F5CFC93, 0xC35292F0, 0x41855556,
0x3F5CFC93, 0xC35292F0, 0x41055556, 0x3F5CFC93,
0xC35292F0, 0x358637BD, 0x3F5CFC93, 0xC35292F0,
0xC1055554, 0x3F5CFC93, 0xC35292F0, 0xC1855554,
0x3F5CFC93, 0xC35292F0, 0xC1C7FFFF, 0x3F5CFC93,
0xC35292F0, 0xC2055554, 0x3F5CFC93, 0xC35292F0,
0xC226AAAA, 0x3F5CFC93, 0xC35292F0, 0xC2480000,
0x3F5CFC93, 0xC35292F0, 0x42480000, 0x3F5CFC93,
0xC33F6846, 0x4226AAAA, 0x3F5CFC93, 0xC33F6846,
0x42055556, 0x3F5CFC93, 0xC33F6846, 0x41C80000,
0x3F5CFC93, 0xC33F6846, 0x41855556, 0x3F5CFC93,
0xC33F6846, 0x41055556, 0x3F5CFC93, 0xC33F6846,
0x358637BD, 0x3F5CFC93, 0xC33F6846, 0xC1055554,
0x3F5CFC93, 0xC33F6846, 0xC1855554, 0x3F5CFC93,
0xC33F6846, 0xC1C7FFFF, 0x3F5CFC93, 0xC33F6846,
0xC2055554, 0x3F5CFC93, 0xC33F6846, 0xC226AAAA,
0x3F5CFC93, 0xC33F6846, 0xC2480000, 0x3F5CFC93,
0xC33F6846, 0x42480000, 0x3F5CFC93, 0xC32C3D9C,
0x4226AAAA, 0x3F5CFC93, 0xC32C3D9C, 0x42055556,
0x3F5CFC93, 0xC32C3D9C, 0x41C80000, 0x3F5CFC93,
0xC32C3D9C, 0x41855556, 0x3F5CFC93, 0xC32C3D9C,
0x41055556, 0x3F5CFC93, 0xC32C3D9C, 0x358637BD,
0x3F5CFC93, 0xC32C3D9C, 0xC1055554, 0x3F5CFC93,
0xC32C3D9C, 0xC1855554, 0x3F5CFC93, 0xC32C3D9C,
0xC1C7FFFF, 0x3F5CFC93, 0xC32C3D9C, 0xC2055554,
0x3F5CFC93, 0xC32C3D9C, 0xC226AAAA, 0x3F5CFC93,
0xC32C3D9C, 0xC2480000, 0x3F5CFC93, 0xC32C3D9C,
0x42480000, 0x3F5CFC93, 0xC31912F1, 0x4226AAAA,
0x3F5CFC93, 0xC31912F1, 0x42055556, 0x3F5CFC93,
0xC31912F1, 0x41C80000, 0x3F5CFC93, 0xC31912F1,
0x41855556, 0x3F5CFC93, 0xC31912F1, 0x41055556,
0x3F5CFC93, 0xC31912F1, 0x358637BD, 0x3F5CFC93,
0xC31912F1, 0xC1055554, 0x3F5CFC93, 0xC31912F1,
0xC1855554, 0x3F5CFC93, 0xC31912F1, 0xC1C7FFFF,
0x3F5CFC93, 0xC31912F1, 0xC2055554, 0x3F5CFC93,
0xC31912F1, 0xC226AAAA, 0x3F5CFC93, 0xC31912F1,
0xC2480000, 0x3F5CFC93, 0xC31912F1, 0x42480000,
0x3F5CFC93, 0xC305E846, 0x4226AAAA, 0x3F5CFC93,
0xC305E846, 0x42055556, 0x3F5CFC93, 0xC305E846,
0x41C80000, 0x3F5CFC93, 0xC305E846, 0x41855556,
0x3F5CFC93, 0xC305E846, 0x41055556, 0x3F5CFC93,
0xC305E846, 0x358637BD, 0x3F5CFC93, 0xC305E846,
0xC1055554, 0x3F5CFC93, 0xC305E846, 0xC1855554,
0x3F5CFC93, 0xC305E846, 0xC1C7FFFF, 0x3F5CFC93,
0xC305E846, 0xC2055554, 0x3F5CFC93, 0xC305E846,
0xC226AAAA, 0x3F5CFC93, 0xC305E846, 0xC2480000,
0x3F5CFC93, 0xC305E846, 0x42480000, 0x3F5CFC93,
0xC2E57B38, 0x4226AAAA, 0x3F5CFC93, 0xC2E57B38,
0x42055556, 0x3F5CFC93, 0xC2E57B38, 0x41C80000,
0x3F5CFC93, 0xC2E57B38, 0x41855556, 0x3F5CFC93,
0xC2E57B38, 0x41055556, 0x3F5CFC93, 0xC2E57B38,
0x358637BD, 0x3F5CFC93, 0xC2E57B38, 0xC1055554,
0x3F5CFC93, 0xC2E57B38, 0xC1855554, 0x3F5CFC93,
0xC2E57B38, 0xC1C7FFFF, 0x3F5CFC93, 0xC2E57B38,
0xC2055554, 0x3F5CFC93, 0xC2E57B38, 0xC226AAAA,
0x3F5CFC93, 0xC2E57B38, 0xC2480000, 0x3F5CFC93,
0xC2E57B38, 0x42480000, 0x3F5CFC93, 0xC2BF25E2,
0x4226AAAA, 0x3F5CFC93, 0xC2BF25E2, 0x42055556,
0x3F5CFC93, 0xC2BF25E2, 0x41C80000, 0x3F5CFC93,
0xC2BF25E2, 0x41855556, 0x3F5CFC93, 0xC2BF25E2,
0x41055556, 0x3F5CFC93, 0xC2BF25E2, 0x358637BD,
0x3F5CFC93, 0xC2BF25E2, 0xC1055554, 0x3F5CFC93,
0xC2BF25E2, 0xC1855554, 0x3F5CFC93, 0xC2BF25E2,
0xC1C7FFFF, 0x3F5CFC93, 0xC2BF25E2, 0xC2055554,
0x3F5CFC93, 0xC2BF25E2, 0xC226AAAA, 0x3F5CFC93,
0xC2BF25E2, 0xC2480000, 0x3F5CFC93, 0xC2BF25E2,
0x42480000, 0x3F5CFC93, 0xC298D08D, 0x4226AAAA,
0x3F5CFC93, 0xC298D08D, 0x42055556, 0x3F5CFC93,
0xC298D08D, 0x41C80000, 0x3F5CFC93, 0xC298D08D,
0x41855556, 0x3F5CFC93, 0xC298D08D, 0x41055556,
0x3F5CFC93, 0xC298D08D, 0x358637BD, 0x3F5CFC93,
0xC298D08D, 0xC1055554, 0x3F5CFC93, 0xC298D08D,
0xC1855554, 0x3F5CFC93, 0xC298D08D, 0xC1C7FFFF,
0x3F5CFC93, 0xC298D08D, 0xC2055554, 0x3F5CFC93,
0xC298D08D, 0xC226AAAA, 0x3F5CFC93, 0xC298D08D,
0xC2480000, 0x3F5CFC93, 0xC298D08D, 0x42480000,
0x3F5CFC93, 0xC264F66F, 0x4226AAAA, 0x3F5CFC93,
0xC264F66F, 0x42055556, 0x3F5CFC93, 0xC264F66F,
0x41C80000, 0x3F5CFC93, 0xC264F66F, 0x41855556,
0x3F5CFC93, 0xC264F66F, 0x41055556, 0x3F5CFC93,
0xC264F66F, 0x358637BD, 0x3F5CFC93, 0xC264F66F,
0xC1055554, 0x3F5CFC93, 0xC264F66F, 0xC1855554,
0x3F5CFC93, 0xC264F66F, 0xC1C7FFFF, 0x3F5CFC93,
0xC264F66F, 0xC2055554, 0x3F5CFC93, 0xC264F66F,
0xC226AAAA, 0x3F5CFC93, 0xC264F66F, 0xC2480000,
0x3F5CFC93, 0xC264F66F, 0x42480000, 0x3F5CFC93,
0xC2184BC4, 0x4226AAAA, 0x3F5CFC93, 0xC2184BC4,
0x42055556, 0x3F5CFC93, 0xC2184BC4, 0x41C80000,
0x3F5CFC93, 0xC2184BC4, 0x41855556, 0x3F5CFC93,
0xC2184BC4, 0x41055556, 0x3F5CFC93, 0xC2184BC4,
0x358637BD, 0x3F5CFC93, 0xC2184BC4, 0xC1055554,
0x3F5CFC93, 0xC2184BC4, 0xC1855554, 0x3F5CFC93,
0xC2184BC4, 0xC1C7FFFF, 0x3F5CFC93, 0xC2184BC4,
0xC2055554, 0x3F5CFC93, 0xC2184BC4, 0xC226AAAA,
0x3F5CFC93, 0xC2184BC4, 0xC2480000, 0x3F5CFC93,
0xC2184BC4, 0x42480000, 0x3F5CFC93, 0xC1974231,
0x4226AAAA, 0x3F5CFC93, 0xC1974231, 0x42055556,
0x3F5CFC93, 0xC1974231, 0x41C80000, 0x3F5CFC93,
0xC1974231, 0x41855556, 0x3F5CFC93, 0xC1974231,
0x41055556, 0x3F5CFC93, 0xC1974231, 0x358637BD,
0x3F5CFC93, 0xC1974231, 0xC1055554, 0x3F5CFC93,
0xC1974231, 0xC1855554, 0x3F5CFC93, 0xC1974231,
0xC1C7FFFF, 0x3F5CFC93, 0xC1974231, 0xC2055554,
0x3F5CFC93, 0xC1974231, 0xC226AAAA, 0x3F5CFC93,
0xC1974231, 0xC2480000, 0x3F5CFC93, 0xC1974231,
0x42480000, 0x3F5CFC93, 0x3E84C964, 0x4226AAAA,
0x3F5CFC93, 0x3E84C964, 0x42055556, 0x3F5CFC93,
0x3E84C964, 0x41C80000, 0x3F5CFC93, 0x3E84C964,
0x41855556, 0x3F5CFC93, 0x3E84C964, 0x41055556,
0x3F5CFC93, 0x3E84C964, 0x358637BD, 0x3F5CFC93,
0x3E84C964, 0xC1055554, 0x3F5CFC93, 0x3E84C964,
0xC1855554, 0x3F5CFC93, 0x3E84C964, 0xC1C7FFFF,
0x3F5CFC93, 0x3E84C964, 0xC2055554, 0x3F5CFC93,
0x3E84C964, 0xC226AAAA, 0x3F5CFC93, 0x3E84C964,
0xC2480000, 0x3F5CFC93, 0x3E84C964,
};
static u32 l_normal[3] = {
0x00000000, 0x3F800000, 0x00000000,
};
static u32 l_texCoord[338] = {
0x00000000, 0x3F6AAAB0, 0x3DAAAA7E, 0x3F6AAAB0,
0x3DAAAA7E, 0x3F800000, 0x00000000, 0x3F800000,
0x3E2AAAC1, 0x3F6AAAB0, 0x3E2AAAC1, 0x3F800000,
0x3E800000, 0x3F6AAAB0, 0x3E800000, 0x3F800000,
0x3EAAAA9F, 0x3F6AAAB0, 0x3EAAAA9F, 0x3F800000,
0x3ED55561, 0x3F6AAAB0, 0x3ED55561, 0x3F800000,
0x3F000000, 0x3F6AAAB0, 0x3F000000, 0x3F800000,
0x3F155550, 0x3F6AAAB0, 0x3F155550, 0x3F800000,
0x3F2AAAB0, 0x3F6AAAB0, 0x3F2AAAB0, 0x3F800000,
0x3F400000, 0x3F6AAAB0, 0x3F400000, 0x3F800000,
0x3F555550, 0x3F6AAAB0, 0x3F555550, 0x3F800000,
0x3F6AAAB0, 0x3F6AAAB0, 0x3F6AAAB0, 0x3F800000,
0x3F800000, 0x3F6AAAB0, 0x3F800000, 0x3F800000,
0x00000000, 0x3F555550, 0x3DAAAA7E, 0x3F555550,
0x3E2AAAC1, 0x3F555550, 0x3E800000, 0x3F555550,
0x3EAAAA9F, 0x3F555550, 0x3ED55561, 0x3F555550,
0x3F000000, 0x3F555550, 0x3F155550, 0x3F555550,
0x3F2AAAB0, 0x3F555550, 0x3F400000, 0x3F555550,
0x3F555550, 0x3F555550, 0x3F6AAAB0, 0x3F555550,
0x3F800000, 0x3F555550, 0x00000000, 0x3F400000,
0x3DAAAA7E, 0x3F400000, 0x3E2AAAC1, 0x3F400000,
0x3E800000, 0x3F400000, 0x3EAAAA9F, 0x3F400000,
0x3ED55561, 0x3F400000, 0x3F000000, 0x3F400000,
0x3F155550, 0x3F400000, 0x3F2AAAB0, 0x3F400000,
0x3F400000, 0x3F400000, 0x3F555550, 0x3F400000,
0x3F6AAAB0, 0x3F400000, 0x3F800000, 0x3F400000,
0x00000000, 0x3F2AAAB0, 0x3DAAAA7E, 0x3F2AAAB0,
0x3E2AAAC1, 0x3F2AAAB0, 0x3E800000, 0x3F2AAAB0,
0x3EAAAA9F, 0x3F2AAAB0, 0x3ED55561, 0x3F2AAAB0,
0x3F000000, 0x3F2AAAB0, 0x3F155550, 0x3F2AAAB0,
0x3F2AAAB0, 0x3F2AAAB0, 0x3F400000, 0x3F2AAAB0,
0x3F555550, 0x3F2AAAB0, 0x3F6AAAB0, 0x3F2AAAB0,
0x3F800000, 0x3F2AAAB0, 0x00000000, 0x3F155550,
0x3DAAAA7E, 0x3F155550, 0x3E2AAAC1, 0x3F155550,
0x3E800000, 0x3F155550, 0x3EAAAA9F, 0x3F155550,
0x3ED55561, 0x3F155550, 0x3F000000, 0x3F155550,
0x3F155550, 0x3F155550, 0x3F2AAAB0, 0x3F155550,
0x3F400000, 0x3F155550, 0x3F555550, 0x3F155550,
0x3F6AAAB0, 0x3F155550, 0x3F800000, 0x3F155550,
0x00000000, 0x3F000000, 0x3DAAAA7E, 0x3F000000,
0x3E2AAAC1, 0x3F000000, 0x3E800000, 0x3F000000,
0x3EAAAA9F, 0x3F000000, 0x3ED55561, 0x3F000000,
0x3F000000, 0x3F000000, 0x3F155550, 0x3F000000,
0x3F2AAAB0, 0x3F000000, 0x3F400000, 0x3F000000,
0x3F555550, 0x3F000000, 0x3F6AAAB0, 0x3F000000,
0x3F800000, 0x3F000000, 0x00000000, 0x3ED55561,
0x3DAAAA7E, 0x3ED55561, 0x3E2AAAC1, 0x3ED55561,
0x3E800000, 0x3ED55561, 0x3EAAAA9F, 0x3ED55561,
0x3ED55561, 0x3ED55561, 0x3F000000, 0x3ED55561,
0x3F155550, 0x3ED55561, 0x3F2AAAB0, 0x3ED55561,
0x3F400000, 0x3ED55561, 0x3F555550, 0x3ED55561,
0x3F6AAAB0, 0x3ED55561, 0x3F800000, 0x3ED55561,
0x00000000, 0x3EAAAA9F, 0x3DAAAA7E, 0x3EAAAA9F,
0x3E2AAAC1, 0x3EAAAA9F, 0x3E800000, 0x3EAAAA9F,
0x3EAAAA9F, 0x3EAAAA9F, 0x3ED55561, 0x3EAAAA9F,
0x3F000000, 0x3EAAAA9F, 0x3F155550, 0x3EAAAA9F,
0x3F2AAAB0, 0x3EAAAA9F, 0x3F400000, 0x3EAAAA9F,
0x3F555550, 0x3EAAAA9F, 0x3F6AAAB0, 0x3EAAAA9F,
0x3F800000, 0x3EAAAA9F, 0x00000000, 0x3E800000,
0x3DAAAA7E, 0x3E800000, 0x3E2AAAC1, 0x3E800000,
0x3E800000, 0x3E800000, 0x3EAAAA9F, 0x3E800000,
0x3ED55561, 0x3E800000, 0x3F000000, 0x3E800000,
0x3F155550, 0x3E800000, 0x3F2AAAB0, 0x3E800000,
0x3F400000, 0x3E800000, 0x3F555550, 0x3E800000,
0x3F6AAAB0, 0x3E800000, 0x3F800000, 0x3E800000,
0x00000000, 0x3E2AAAC1, 0x3DAAAA7E, 0x3E2AAAC1,
0x3E2AAAC1, 0x3E2AAAC1, 0x3E800000, 0x3E2AAAC1,
0x3EAAAA9F, 0x3E2AAAC1, 0x3ED55561, 0x3E2AAAC1,
0x3F000000, 0x3E2AAAC1, 0x3F155550, 0x3E2AAAC1,
0x3F2AAAB0, 0x3E2AAAC1, 0x3F400000, 0x3E2AAAC1,
0x3F555550, 0x3E2AAAC1, 0x3F6AAAB0, 0x3E2AAAC1,
0x3F800000, 0x3E2AAAC1, 0x00000000, 0x3DAAAA7E,
0x3DAAAA7E, 0x3DAAAA7E, 0x3E2AAAC1, 0x3DAAAA7E,
0x3E800000, 0x3DAAAA7E, 0x3EAAAA9F, 0x3DAAAA7E,
0x3ED55561, 0x3DAAAA7E, 0x3F000000, 0x3DAAAA7E,
0x3F155550, 0x3DAAAA7E, 0x3F2AAAB0, 0x3DAAAA7E,
0x3F400000, 0x3DAAAA7E, 0x3F555550, 0x3DAAAA7E,
0x3F6AAAB0, 0x3DAAAA7E, 0x3F800000, 0x3DAAAA7E,
0x00000000, 0x00000000, 0x3DAAAA7E, 0x00000000,
0x3E2AAAC1, 0x00000000, 0x3E800000, 0x00000000,
0x3EAAAA9F, 0x00000000, 0x3ED55561, 0x00000000,
0x3F000000, 0x00000000, 0x3F155550, 0x00000000,
0x3F2AAAB0, 0x00000000, 0x3F400000, 0x00000000,
0x3F555550, 0x00000000, 0x3F6AAAB0, 0x00000000,
0x3F800000, 0x00000000,
};
#if TARGET_PC
using GameVersion = dusk::version::GameVersion;
@@ -101,9 +305,8 @@ static void mant_build_anchor_frame(const cXyz& anchor_a, const cXyz& anchor_b,
#endif
void daMant_packet_c::draw() {
ZoneScoped;
#if TARGET_PC
void* image = l_Egnd_mantTEX_copy;
void* image = l_Egnd_mantTEX;
void* lut = l_Egnd_mantPAL;
#else
void* image = tex_d[0];
@@ -185,12 +388,12 @@ void daMant_packet_c::draw() {
}
}
GXSETARRAY(GX_VA_POS, draw_pos, sizeof(mNrm[0]), 12, true);
GXSETARRAY(GX_VA_NRM, l_normal, sizeof(f32) * 3, 12, false);
GXSETARRAY(GX_VA_NRM, &l_normal, sizeof(l_normal), 12, false);
#else
GXSETARRAY(GX_VA_POS, this->getPos(), sizeof(mPos[0]), 12, true);
GXSETARRAY(GX_VA_NRM, this->getNrm(), sizeof(mNrm[0]), 12, true);
#endif
GXSETARRAY(GX_VA_TEX0, l_texCoord, sizeof(f32) * 338, 8, false);
GXSETARRAY(GX_VA_TEX0, &l_texCoord, sizeof(l_texCoord), 8, false); // TODO: set to true when converted to float literals
GXSetZCompLoc(0);
GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_ENABLE);
@@ -215,32 +418,15 @@ void daMant_packet_c::draw() {
GXSetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K3_A);
GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
#if TARGET_PC
if (!textureObjsInitialized) {
GXInitTlutObj(&tlutObj, lut, GX_TL_RGB5A3, 0x100);
GXInitTexObjCI(&mainTexObj, image, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&mainTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
GXInitTexObjCI(
&undersideTexObj, l_Egnd_mantTEX_U, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&undersideTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
textureObjsInitialized = true;
}
#else
GXTlutObj GStack_80;
GXInitTlutObj(&GStack_80, lut, GX_TL_RGB5A3, 0x100);
TGXTexObj GStack_74;
GXInitTexObjCI(&GStack_74, image, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&GStack_74, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
#endif
#if TARGET_PC
GXLoadTlut(&tlutObj, GX_TLUT0);
GXLoadTexObj(&mainTexObj, GX_TEXMAP0);
#else
GXLoadTlut(&GStack_80, GX_TLUT0);
GXLoadTlut(&GStack_80, 0);
GXLoadTexObj(&GStack_74, GX_TEXMAP0);
#endif
GXSetCullMode(GX_CULL_BACK);
@@ -256,13 +442,12 @@ void daMant_packet_c::draw() {
GXLoadNrmMtxImm(MStack_54, GX_PNMTX0);
GXCallDisplayList(l_Egnd_mantDL, 0x3e0);
#if TARGET_PC
GXLoadTexObj(&undersideTexObj, GX_TEXMAP0);
#else
#ifdef TARGET_PC
GStack_74.reset();
#endif
GXInitTexObjCI(&GStack_74, l_Egnd_mantTEX_U, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&GStack_74, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
GXLoadTexObj(&GStack_74, GX_TEXMAP0);
#endif
GXSetTevColor(GX_TEVREG0, COMPOUND_LITERAL(GXColor){0, 0, 0, 0});
GXSetTevKColor(GX_KCOLOR0, COMPOUND_LITERAL(GXColor){0, 0, 0, 0});
@@ -709,14 +894,8 @@ static int daMant_Execute(mant_class* i_this) {
if (0 <= uVar1 && uVar1 < 0x4000) {
int iVar5 = (uVar1 & 7) + (uVar1 & 0x78) * 4 + (uVar1 >> 4 & 0x18) + (uVar1 & 0x3e00);
DUSK_IF_ELSE(l_Egnd_mantTEX_copy[iVar5], l_Egnd_mantTEX[iVar5]) = l_Egnd_mantTEX_U[iVar5] = 0;
l_Egnd_mantTEX[iVar5] = l_Egnd_mantTEX_U[iVar5] = 0;
}
#if TARGET_PC
if(textureObjsInitialized) {
GXInitTlutObjData(&tlutObj, l_Egnd_mantPAL); // make sure the cached textures are updated
}
#endif
}
}
@@ -754,14 +933,6 @@ static int daMant_Create(fopAc_ac_c* i_this) {
l_Egnd_mantTEX_U[i] = 6;
}
#if TARGET_PC
memcpy(l_Egnd_mantTEX_copy, l_Egnd_mantTEX, sizeof(l_Egnd_mantTEX_copy));
if(textureObjsInitialized) {
GXInitTlutObjData(&tlutObj, l_Egnd_mantPAL); // make sure the cached textures are updated
}
#endif
lbl_277_bss_0 = 0;
daMant_Execute(m_this);
return 4;
-66
View File
@@ -26,7 +26,6 @@
#include <cstring>
#if TARGET_PC
#include "dusk/frame_interpolation.h"
#include "dusk/settings.h"
#include "dusk/version.hpp"
#endif
@@ -181,25 +180,6 @@ static int Worm_nodeCallBack(J3DJoint* i_joint, int param_1) {
return 1;
}
#if TARGET_PC
static void dmg_rod_interp_callback(bool isSimFrame, void* pUserWork) {
dmg_rod_class* i_this = (dmg_rod_class*)pUserWork;
if (!i_this->mLineInterpPrevValid || !i_this->mLineInterpCurrValid) {
return;
}
const f32 alpha = dusk::frame_interp::get_interpolation_step();
const int count = i_this->kind == MG_ROD_KIND_LURE ? MG_ROD_LURE_LINE_LEN : MG_ROD_UKI_LINE_LEN;
cXyz* dst = i_this->linemat.getPos(0);
for (int i = 0; i < count; i++) {
const cXyz& p0 = i_this->mLineInterpPrev[i];
const cXyz& p1 = i_this->mLineInterpCurr[i];
dst[i] = p0 + (p1 - p0) * alpha;
}
static GXColor l_color = {0xFF, 0xFF, 0x96, 0xFF};
i_this->linemat.update(count, l_color, &i_this->actor.tevStr);
}
#endif
static int dmg_rod_Draw(dmg_rod_class* i_this) {
int unused;
fopAc_ac_c* actor = &i_this->actor;
@@ -240,18 +220,6 @@ static int dmg_rod_Draw(dmg_rod_class* i_this) {
i_this->linemat.update(MG_ROD_LURE_LINE_LEN, l_color, &i_this->actor.tevStr);
dComIfGd_set3DlineMat(&i_this->linemat);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (i_this->mLineInterpCurrValid) {
memcpy(i_this->mLineInterpPrev, i_this->mLineInterpCurr, MG_ROD_LURE_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpPrevValid = true;
}
memcpy(i_this->mLineInterpCurr, i_this->linemat.getPos(0), MG_ROD_LURE_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&dmg_rod_interp_callback, i_this);
}
#endif
model = i_this->rod_modelMorf->getModel();
g_env_light.setLightTevColorType_MAJI(model, &i_this->actor.tevStr);
i_this->rod_modelMorf->entryDL();
@@ -276,18 +244,6 @@ static int dmg_rod_Draw(dmg_rod_class* i_this) {
i_this->linemat.update(MG_ROD_UKI_LINE_LEN, l_color, &i_this->actor.tevStr);
dComIfGd_set3DlineMat(&i_this->linemat);
#if TARGET_PC
if (dusk::frame_interp::is_enabled()) {
if (i_this->mLineInterpCurrValid) {
memcpy(i_this->mLineInterpPrev, i_this->mLineInterpCurr, MG_ROD_UKI_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpPrevValid = true;
}
memcpy(i_this->mLineInterpCurr, i_this->linemat.getPos(0), MG_ROD_UKI_LINE_LEN * sizeof(cXyz));
i_this->mLineInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&dmg_rod_interp_callback, i_this);
}
#endif
for (int i = 0; i < 15; i++) {
g_env_light.setLightTevColorType_MAJI(i_this->rod_uki_model[i], &actor->tevStr);
mDoExt_modelUpdateDL(i_this->rod_uki_model[i]);
@@ -5799,12 +5755,6 @@ static void play_camera_u(dmg_rod_class* i_this) {
}
}
#if TARGET_PC
BOOL item_any_fishing_rod(int itemId) {
return itemId == dItemNo_FISHING_ROD_1_e || (itemId >= dItemNo_BEE_ROD_e && itemId <= dItemNo_JEWEL_WORM_ROD_e);
}
#endif
static int dmg_rod_Execute(dmg_rod_class* i_this) {
fopAc_ac_c* actor = &i_this->actor;
@@ -5871,17 +5821,6 @@ static int dmg_rod_Execute(dmg_rod_class* i_this) {
i_this->prev_rod_substick_y = i_this->rod_substick_y;
i_this->rod_substick_y = mDoCPd_c::getSubStickY(PAD_1);
#if TARGET_PC
if (dusk::getSettings().game.buttonFishing) {
if ((item_any_fishing_rod(dComIfGp_getSelectItem(0)) && mDoCPd_c::getHoldX(PAD_1)) ||
(item_any_fishing_rod(dComIfGp_getSelectItem(1)) && mDoCPd_c::getHoldY(PAD_1)))
{
i_this->rod_stick_y = -1.0f;
i_this->rod_substick_y = -1.0f;
}
}
#endif
i_this->reel_speed = 5.0f;
i_this->reel_btn_flags = mDoCPd_c::getHoldB(PAD_1) | mDoCPd_c::getHoldDown(PAD_1);
if (mDoCPd_c::getHoldDown(PAD_1)) {
@@ -6449,11 +6388,6 @@ static int dmg_rod_Create(fopAc_ac_c* i_this) {
return cPhs_ERROR_e;
}
#if TARGET_PC
rod->mLineInterpPrevValid = false;
rod->mLineInterpCurrValid = false;
#endif
OS_REPORT("//////////////MG_ROD SET 2 !!\n");
if (!hio_set) {
rod->HIOInit = TRUE;
-2
View File
@@ -105,7 +105,6 @@ int dMirror_packet_c::entryModel(J3DModel* i_model) {
void dMirror_packet_c::mirrorZdraw(f32* param_0, f32* param_1, f32 param_2, f32 param_3,
f32 param_4, f32 param_5, f32 param_6, f32 param_7) {
ZoneScoped;
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE);
GXSetNumTexGens(0);
@@ -266,7 +265,6 @@ void dMirror_packet_c::modelDraw(J3DModel* i_model, Mtx param_1) {
}
void dMirror_packet_c::mainDraw() {
ZoneScoped;
j3dSys.reinitGX();
cXyz sp19C[5];

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