Compare commits

...

50 Commits

Author SHA1 Message Date
gymnast86 af17623e69 remove unneeded include and const qualifier 2026-08-14 23:49:56 -07:00
gymnast86 c01610dc37 fix includes 2026-08-14 23:20:46 -07:00
gymnast86 f4700c9636 manual cleanup 2026-08-14 23:05:00 -07:00
gymnast86 5d01c93839 Merge branch 'main' of https://github.com/TwilitRealm/dusk into basic-cosmetics-mod 2026-08-14 21:59:46 -07:00
gymnast86 0c546819f4 update descriptions 2026-08-14 21:59:34 -07:00
gymnast86 094f0cd78d use TextureService instead of overwriting model file data on load 2026-08-14 21:59:22 -07:00
gymnast86 c251aba39d fix default midna hair color 2026-08-14 21:58:02 -07:00
TakaRikka c722cb1be0 update aurora 2026-08-14 19:12:14 -07:00
Luke Street 0f5a248401 Time revamp (#2304)
* Don't Use OSCalendarTime for Speedrun Timing

- Shouldn't rely on OSTicksToCalendarTime since it will be changed to handle time zone conversion, and that doesn't make sense on elapsed time

* Use OSGetSystemTime Extension

- Fixes desyncing issues with save file time and a couple other odd instances, particularly on mobile platforms that suspend apps

* Time revamp

* Update aurora

* Split IGT/RTA calculations

* Shift-Turbo to slow down

---------

Co-authored-by: SuperDude88 <82904174+SuperDude88@users.noreply.github.com>
2026-08-14 00:07:54 -06:00
matthewdavidrichardanderson 045fbd9b46 request presentation sync for all captures (#2293)
Co-authored-by: matthewdavidrichardanderson <matthewdavidrichardanderson@mfb.com>
2026-08-13 23:54:29 -06:00
doop 46da33be37 Use texture replacement API for HQ minimap textures (#2303) 2026-08-13 23:44:36 -06:00
TakaRikka 008a18c142 Merge pull request #2292 from TwilitRealm/item-svc
initial item service implementation
2026-08-12 15:34:45 -07:00
TakaRikka 5b4def820a couple fixes 2026-08-12 15:02:33 -07:00
TakaRikka 635901d3bd update game service major version 2026-08-12 13:59:01 -07:00
TakaRikka 5abc956448 daTbox2 handling 2026-08-11 14:45:53 -07:00
TakaRikka 0c3bbbaba0 standardize some check names 2026-08-10 12:35:08 -07:00
baxlek 0fc05028cc Add Aiming Reticle for Bow and Slingshot (#2290)
* Change sight drawing flag to on in arrow logic

* Refactor setBowSight for PC targeting and reticle logic

* Add Aiming Reticle option to settings

Add option for Aiming Reticle in settings.

* Add aiming reticle setting to game preferences

* Add aiming reticle to user settings registration

* Add aimingReticle configuration variable

* Fix syntax error in settings.cpp

* Add aiming reticle check to bow charge condition

* Refactor bow charge sight position logic

Removed redundant sight position handling when aiming reticle is not displayed.

* Refactor setBowSight for Dusk targeting

* Clarify aiming reticle option description

* Refactor bow sight logic in setBowSight function

Removed dusk condition from bow sight check and adjusted sight drawing logic.

* Refactor sight drawing logic in d_a_alink_bow.inc

Remove redundant call to offDrawFlg() when aiming reticle is enabled.
2026-08-10 00:14:17 -04:00
TakaRikka 71b2eedc82 initial item service implementation 2026-08-09 16:40:26 -07:00
gymnast86 0da58ac91d gx.h instead of dolphin/gx/GXstruct.h 2026-08-09 10:13:51 -07:00
gymnast86 c29cafa8a2 constexpr descriptions 2026-08-09 10:13:32 -07:00
gymnast86 5e669c8f0f fix mod.json 2026-08-09 09:24:49 -07:00
gymnast86 3e625cf006 Merge branch 'main' of https://github.com/TwilitRealm/dusk into basic-cosmetics-mod 2026-08-09 09:13:18 -07:00
gymnast86 c6f497b525 move option descriptions 2026-08-09 08:52:29 -07:00
gymnast86 79d3c7c76a recolor epona's eyelids 2026-08-09 08:52:16 -07:00
gymnast86 16dd1118d1 add support for ordon sword recoloring 2026-08-09 08:18:28 -07:00
gymnast86 e9918cc8ed cleanup 2026-08-09 08:17:42 -07:00
gymnast86 058304dc26 recolor heart piece models 2026-08-08 20:10:50 -07:00
gymnast86 d55b44b5a5 override colors for items on other models 2026-08-08 20:10:21 -07:00
Giorgio Mendieta 7434a0f834 Enable color diagnostics for CMake (#2273) 2026-08-08 16:14:52 -06:00
gymnast86 469575fd65 fix pane cache again 2026-08-08 07:09:28 -07:00
gymnast86 4883c11182 Merge branch 'main' of https://github.com/TwilitRealm/dusk into basic-cosmetics-mod 2026-08-07 18:34:19 -07:00
gymnast86 7ac2340312 add UI colors 2026-08-07 18:33:40 -07:00
gymnast86 3352ea3dde fix PaneCache naming conflict 2026-08-07 18:32:41 -07:00
TakaRikka 82e2fd4bea Merge pull request #2283 from encounter/camera-operator
Add camera operator API to CameraService
2026-08-07 03:44:59 -07:00
TakaRikka fcd9dd0f70 Merge pull request #2282 from encounter/mods-data-dir
Add HostService.data_dir
2026-08-07 03:42:53 -07:00
TakaRikka 8afe479d0f Merge pull request #2281 from encounter/hook-uninstall
Add mods::hook::uninstall
2026-08-07 03:39:24 -07:00
Luke Street c5933be631 Add camera operator API to CameraService 2026-08-07 00:34:57 -06:00
Luke Street 928e9b4bc7 Add HostService.data_dir 2026-08-07 00:20:09 -06:00
Luke Street 3ac0fcb156 Add mods::hook::uninstall 2026-08-06 23:59:26 -06:00
gymnast86 6481d12a3d add lantern, midna, and heart colors 2026-08-06 09:38:00 -07:00
TakaRikka 2c7ab755a0 Merge pull request #2276 from encounter/align
Fix ATTRIBUTE_ALIGN placement
2026-08-06 08:58:15 -07:00
Luke Street cf8ab52f55 Fix ATTRIBUTE_ALIGN placement 2026-08-05 21:16:06 -06:00
gymnast86 960d016113 get most colors working 2026-08-05 08:01:57 -07:00
Luke Street 13b3b68fe5 Migrate to Borealis (#2266) 2026-08-05 07:54:31 -06:00
TakaRikka 4604304305 mods: stage service (#2268)
* initial stage service ported from encounter's original impl

* Review cleanup

* initial stage service ported from encounter's original impl

---------

Co-authored-by: Luke Street <luke@street.dev>
2026-08-04 21:51:52 -06:00
Pwootage 794bb130e2 Fix for Linux distributions that use lib64: force libturbojpeg to use 'lib' (#2269) 2026-08-04 21:49:33 -06:00
gymnast86 e02251a669 template setup 2026-08-04 15:28:11 -07:00
Pieter-Jan Briers 2c9f814ec6 Make JASCalc memory helpers just use memcpy/memset (#2258) 2026-08-03 21:37:36 -06:00
TakaRikka 76079b6294 mods: save service (#2256)
* initial save service updated from encounter's impl

* Review cleanup

---------

Co-authored-by: Luke Street <luke@street.dev>
2026-08-03 20:58:09 -06:00
Pieter-Jan Briers 519305b7d4 Linux/Apple compile warnings consistency (#2255)
This re-organizes the CMakeLists.txt a lil so that some of the warning compile flags on Linux also get applied to Apple platforms.
2026-08-03 19:31:03 -06:00
298 changed files with 7171 additions and 14882 deletions
+4 -4
View File
@@ -76,7 +76,7 @@ jobs:
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: dusklight-${{env.DUSK_VERSION}}-linux-${{matrix.preset}}-${{matrix.artifact_arch}} name: dusklight-${{env.APP_VERSION}}-linux-${{matrix.preset}}-${{matrix.artifact_arch}}
path: | path: |
build/install/Dusklight-*.AppImage build/install/Dusklight-*.AppImage
build/install/debug.tar.* build/install/debug.tar.*
@@ -145,7 +145,7 @@ jobs:
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: dusklight-${{env.DUSK_VERSION}}-${{matrix.artifact_name}} name: dusklight-${{env.APP_VERSION}}-${{matrix.artifact_name}}
path: | path: |
build/install/Dusklight.app build/install/Dusklight.app
build/install/debug.tar.* build/install/debug.tar.*
@@ -221,7 +221,7 @@ jobs:
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: dusklight-${{env.DUSK_VERSION}}-android-${{matrix.artifact_arch}} name: dusklight-${{env.APP_VERSION}}-android-${{matrix.artifact_arch}}
path: upload/ path: upload/
build-windows: build-windows:
@@ -283,7 +283,7 @@ jobs:
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: dusklight-${{env.DUSK_VERSION}}-win32-msvc-${{matrix.artifact_arch}} name: dusklight-${{env.APP_VERSION}}-win32-msvc-${{matrix.artifact_arch}}
path: | path: |
build/install/*.exe build/install/*.exe
build/install/*.dll build/install/*.dll
+3
View File
@@ -1,3 +1,6 @@
[submodule "extern/aurora"] [submodule "extern/aurora"]
path = extern/aurora path = extern/aurora
url = https://github.com/encounter/aurora.git url = https://github.com/encounter/aurora.git
[submodule "extern/borealis"]
path = extern/borealis
url = https://github.com/encounter/borealis.git
+34 -140
View File
@@ -5,10 +5,11 @@ if (NOT CMAKE_BUILD_TYPE)
"Build type options: Debug Release RelWithDebInfo MinSizeRel" FORCE) "Build type options: Debug Release RelWithDebInfo MinSizeRel" FORCE)
endif () endif ()
include(cmake/DetectVersion.cmake) include(extern/borealis/cmake/DetectVersion.cmake)
detect_version() borealis_detect_version()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
project(dusklight LANGUAGES C CXX VERSION ${DUSK_VERSION_STRING}) project(dusklight LANGUAGES C CXX VERSION ${BOREALIS_APP_VERSION})
if (APPLE) if (APPLE)
enable_language(OBJC OBJCXX) enable_language(OBJC OBJCXX)
endif () endif ()
@@ -32,6 +33,7 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_COLOR_DIAGNOSTICS ON)
# Folder-based instead of target-based organization # Folder-based instead of target-based organization
# in Visual Studio and Xcode generators # in Visual Studio and Xcode generators
@@ -74,6 +76,8 @@ set(AURORA_ENABLE_RMLUI ON CACHE BOOL "Enable RmlUi UI support" FORCE)
add_subdirectory(extern/aurora EXCLUDE_FROM_ALL) add_subdirectory(extern/aurora EXCLUDE_FROM_ALL)
target_compile_definitions(aurora_mtx PRIVATE MTX_USE_PS=1) target_compile_definitions(aurora_mtx PRIVATE MTX_USE_PS=1)
add_subdirectory(extern/borealis EXCLUDE_FROM_ALL)
add_subdirectory(libs/freeverb) add_subdirectory(libs/freeverb)
if (CMAKE_BUILD_TYPE STREQUAL "Debug") if (CMAKE_BUILD_TYPE STREQUAL "Debug")
@@ -85,8 +89,6 @@ endif ()
option(DUSK_BUILD_WARNINGS "Enable compiler warnings (off by default)") 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_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_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_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}) option(DUSK_GFX_DEBUG_GROUPS "Report debug groups to the native graphics API" ${DUSK_GFX_DEBUG_GROUPS_DEFAULT})
option(DUSK_ENABLE_CODE_MODS "Enable code mods" OFF) option(DUSK_ENABLE_CODE_MODS "Enable code mods" OFF)
@@ -150,6 +152,7 @@ if (DUSK_MOVIE_SUPPORT)
-DENABLE_SHARED=OFF -DENABLE_SHARED=OFF
-DWITH_TURBOJPEG=ON -DWITH_TURBOJPEG=ON
-DWITH_JAVA=OFF -DWITH_JAVA=OFF
-DCMAKE_INSTALL_LIBDIR=lib
) )
if (CMAKE_TOOLCHAIN_FILE) if (CMAKE_TOOLCHAIN_FILE)
get_filename_component(_jpeg_toolchain_file "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE BASE_DIR "${CMAKE_SOURCE_DIR}") get_filename_component(_jpeg_toolchain_file "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE BASE_DIR "${CMAKE_SOURCE_DIR}")
@@ -193,24 +196,21 @@ if (DUSK_MOVIE_SUPPORT)
endif () endif ()
endif () endif ()
if (CMAKE_SYSTEM_NAME STREQUAL Linux) if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
# -Wno-multichar: Multi-character constants ('ABCD') are implementation-defined but all compilers # -Wno-multichar: Multi-character constants ('ABCD') are implementation-defined but all compilers
# (CW, GCC, Clang, MSVC) encode them identically in big-endian order. # (CW, GCC, Clang, MSVC) encode them identically in big-endian order.
# For >4-char literals (which GCC/Clang truncate to int), use the MULTI_CHAR() macro. # For >4-char literals (which GCC/Clang truncate to int), use the MULTI_CHAR() macro.
# -Wdeprecated-declarations: JSystem uses std::iterator, deprecated in C++17 # -Wdeprecated-declarations: JSystem uses std::iterator, deprecated in C++17
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-multichar")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-multichar -Wno-trigraphs -Wno-deprecated-declarations")
set(CMAKE_INSTALL_RPATH "$ORIGIN")
set(CMAKE_BUILD_RPATH "$ORIGIN")
elseif (APPLE)
add_compile_options(-Wno-declaration-after-statement -Wno-non-pod-varargs)
set(CMAKE_INSTALL_RPATH "@loader_path")
set(CMAKE_BUILD_RPATH "@loader_path")
elseif (MSVC)
add_compile_options( add_compile_options(
$<$<COMPILE_LANGUAGE:C,CXX>:/bigobj> $<$<COMPILE_LANGUAGE:C,CXX>:-Wno-multichar>
$<$<COMPILE_LANGUAGE:C,CXX>:/MP> $<$<COMPILE_LANGUAGE:CXX>:-Wno-trigraphs>
$<$<COMPILE_LANGUAGE:C,CXX>:/FS> $<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-declarations>
)
elseif (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
add_compile_options(
$<$<COMPILE_LANGUAGE:C,CXX>:/bigobj>
$<$<COMPILE_LANGUAGE:C,CXX>:/MP>
$<$<COMPILE_LANGUAGE:C,CXX>:/FS>
) )
if (NOT DUSK_BUILD_WARNINGS) if (NOT DUSK_BUILD_WARNINGS)
@@ -225,21 +225,18 @@ elseif (MSVC)
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/utf-8>) add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/utf-8>)
endif () endif ()
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
set(CMAKE_INSTALL_RPATH "$ORIGIN")
set(CMAKE_BUILD_RPATH "$ORIGIN")
elseif (APPLE)
add_compile_options(-Wno-declaration-after-statement -Wno-non-pod-varargs)
set(CMAKE_INSTALL_RPATH "@loader_path")
set(CMAKE_BUILD_RPATH "@loader_path")
endif ()
include(FetchContent) include(FetchContent)
# Declare all dependencies first so CMake can download them in parallel # Declare all dependencies first so CMake can download them in parallel
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
)
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
)
message(STATUS "dusklight: Fetching miniz") message(STATUS "dusklight: Fetching miniz")
FetchContent_Declare(miniz FetchContent_Declare(miniz
URL https://github.com/richgel999/miniz/releases/download/3.0.2/miniz-3.0.2.zip URL https://github.com/richgel999/miniz/releases/download/3.0.2/miniz-3.0.2.zip
@@ -247,7 +244,7 @@ FetchContent_Declare(miniz
EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL
) )
set(_fetch_content_deps cxxopts json miniz) set(_fetch_content_deps miniz)
if (DUSK_HAS_FUNCHOOK) if (DUSK_HAS_FUNCHOOK)
message(STATUS "dusklight: Fetching funchook") message(STATUS "dusklight: Fetching funchook")
# cmake/PatchFunchook.cmake patches funchook's cmake/capstone.cmake.in to inject a # cmake/PatchFunchook.cmake patches funchook's cmake/capstone.cmake.in to inject a
@@ -282,40 +279,12 @@ if (DUSK_HAS_FUNCHOOK)
endif () endif ()
FetchContent_MakeAvailable(${_fetch_content_deps}) FetchContent_MakeAvailable(${_fetch_content_deps})
if (DUSK_ENABLE_SENTRY_NATIVE)
message(STATUS "dusklight: Fetching sentry-native")
set(SENTRY_BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set(SENTRY_BACKEND crashpad CACHE STRING "" FORCE)
if (WIN32)
set(SENTRY_TRANSPORT winhttp CACHE STRING "" FORCE)
endif ()
set(SENTRY_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(SENTRY_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(SENTRY_BUILD_BENCHMARKS OFF CACHE BOOL "" FORCE)
FetchContent_Declare(sentry_native
GIT_REPOSITORY https://github.com/getsentry/sentry-native.git
GIT_TAG 0.13.6
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
GIT_SUBMODULES_RECURSE TRUE
)
if (NOT sentry_native_POPULATED)
FetchContent_Populate(sentry_native)
set(_skip_install_rules ${CMAKE_SKIP_INSTALL_RULES})
set(CMAKE_SKIP_INSTALL_RULES ON)
add_subdirectory(${sentry_native_SOURCE_DIR} ${sentry_native_BINARY_DIR} EXCLUDE_FROM_ALL)
set(CMAKE_SKIP_INSTALL_RULES ${_skip_install_rules})
endif ()
endif ()
# Use signed char on ARM to match the original game (and x86) # Use signed char on ARM to match the original game (and x86)
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" _arch) string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" _arch)
if(_arch MATCHES "^(arm|aarch64)" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") if(_arch MATCHES "^(arm|aarch64)" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
add_compile_options(-fsigned-char) add_compile_options(-fsigned-char)
endif() endif()
configure_version_header()
include(files.cmake) include(files.cmake)
# TODO: version handling for res includes # TODO: version handling for res includes
@@ -328,67 +297,23 @@ set(DUSK_PRODUCT_NAME "Dusklight")
set(DUSK_COPYRIGHT "Copyright (C) Twilit Realm contributors") set(DUSK_COPYRIGHT "Copyright (C) Twilit Realm contributors")
source_group("dolzel" FILES ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${REL_FILES}) source_group("dolzel" FILES ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${REL_FILES})
source_group("dusklight" FILES ${DUSK_FILES} ${DUSK_HTTP_BACKEND_FILES}) source_group("dusklight" FILES ${DUSK_FILES})
include(cmake/GameABIConfig.cmake) include(cmake/GameABIConfig.cmake)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
set(GAME_COMPILE_DEFS DUSK_BUILDING_GAME=1) set(GAME_COMPILE_DEFS DUSK_BUILDING_GAME=1)
set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd 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 aurora::card borealis::cli borealis::crash borealis::data borealis::disc borealis::discord borealis::file_select borealis::log borealis::presentation borealis::sentry borealis::update freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt
Threads::Threads zstd::libzstd dusklight_game_headers) Threads::Threads zstd::libzstd dusklight_game_headers)
if (DUSK_HAS_FUNCHOOK) if (DUSK_HAS_FUNCHOOK)
list(APPEND GAME_LIBS funchook-static) list(APPEND GAME_LIBS funchook-static)
endif () endif ()
if (DUSK_ENABLE_SENTRY_NATIVE)
list(APPEND GAME_LIBS sentry)
list(APPEND GAME_COMPILE_DEFS DUSK_ENABLE_SENTRY_NATIVE=1 SENTRY_BUILD_STATIC=1)
endif ()
if (WIN32) if (WIN32)
list(APPEND GAME_LIBS Ws2_32) list(APPEND GAME_LIBS Ws2_32)
if (CMAKE_BUILD_TYPE STREQUAL Debug)
list(APPEND GAME_LIBS dbghelp)
list(APPEND GAME_COMPILE_DEFS DUSK_CRASH_DBGHELP=1)
endif ()
endif () endif ()
set(DUSK_HTTP_BACKEND_SOURCE src/dusk/http/no_backend.cpp)
if (DUSK_ENABLE_UPDATE_CHECKER)
list(APPEND GAME_COMPILE_DEFS DUSK_ENABLE_UPDATE_CHECKER=1)
if (WIN32)
set(DUSK_HTTP_BACKEND_SOURCE src/dusk/http/winhttp.cpp)
list(APPEND GAME_LIBS winhttp)
list(APPEND GAME_COMPILE_DEFS DUSK_HTTP_BACKEND_WINHTTP=1)
message(STATUS "dusklight: Enabled update checker (WinHTTP)")
elseif (ANDROID)
set(DUSK_HTTP_BACKEND_SOURCE src/dusk/http/android.cpp)
list(APPEND GAME_COMPILE_DEFS DUSK_HTTP_BACKEND_ANDROID=1)
message(STATUS "dusklight: Enabled update checker (Android)")
elseif (APPLE)
find_library(FOUNDATION_FRAMEWORK Foundation REQUIRED)
set(DUSK_HTTP_BACKEND_SOURCE src/dusk/http/url_session.mm)
set_source_files_properties(src/dusk/http/url_session.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
list(APPEND GAME_LIBS ${FOUNDATION_FRAMEWORK})
list(APPEND GAME_COMPILE_DEFS DUSK_HTTP_BACKEND_URLSESSION=1)
message(STATUS "dusklight: Enabled update checker (NSURLSession)")
elseif (CMAKE_SYSTEM_NAME STREQUAL Linux)
find_package(CURL QUIET OPTIONAL_COMPONENTS HTTPS SSL)
if (CURL_FOUND AND CURL_HTTPS_FOUND AND CURL_SSL_FOUND)
set(DUSK_HTTP_BACKEND_SOURCE src/dusk/http/curl.cpp)
list(APPEND GAME_LIBS CURL::libcurl)
list(APPEND GAME_COMPILE_DEFS DUSK_HTTP_BACKEND_LIBCURL=1)
message(STATUS "dusklight: Enabled update checker (libcurl)")
else ()
message(STATUS "dusklight: Disabled update checker (libcurl + HTTPS/SSL not found)")
endif ()
else ()
message(STATUS "dusklight: Disabled update checker (unsupported platform)")
endif ()
endif ()
list(APPEND DUSK_FILES ${DUSK_HTTP_BACKEND_SOURCE})
if (DUSK_MOVIE_SUPPORT) if (DUSK_MOVIE_SUPPORT)
if (TARGET libjpeg-turbo::turbojpeg-static) if (TARGET libjpeg-turbo::turbojpeg-static)
list(APPEND GAME_LIBS libjpeg-turbo::turbojpeg-static) list(APPEND GAME_LIBS libjpeg-turbo::turbojpeg-static)
@@ -398,15 +323,6 @@ if (DUSK_MOVIE_SUPPORT)
list(APPEND GAME_COMPILE_DEFS MOVIE_SUPPORT=1) list(APPEND GAME_COMPILE_DEFS MOVIE_SUPPORT=1)
endif () endif ()
set(DUSK_ENABLE_DISCORD_DEFAULT ON)
if (DEFINED DUSK_ENABLE_DISCORD_RPC AND NOT DEFINED DUSK_ENABLE_DISCORD)
set(DUSK_ENABLE_DISCORD_DEFAULT ${DUSK_ENABLE_DISCORD_RPC})
endif ()
option(DUSK_ENABLE_DISCORD "Enable Discord Rich Presence support" ${DUSK_ENABLE_DISCORD_DEFAULT})
if (DUSK_ENABLE_DISCORD AND NOT ANDROID AND NOT IOS AND NOT TVOS)
list(APPEND GAME_COMPILE_DEFS DUSK_DISCORD=1)
endif ()
if (DUSK_ENABLE_CODE_MODS) if (DUSK_ENABLE_CODE_MODS)
list(APPEND GAME_COMPILE_DEFS DUSK_CODE_MODS=1) list(APPEND GAME_COMPILE_DEFS DUSK_CODE_MODS=1)
endif () endif ()
@@ -471,10 +387,10 @@ 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} ${miniz_SOURCE_DIR}/miniz.c)
if(ANDROID) if(ANDROID)
add_library(dusklight SHARED ${DUSK_FILES}) add_library(dusklight SHARED ${DUSK_FILES})
set_target_properties(dusklight PROPERTIES OUTPUT_NAME main)
else () else ()
add_executable(dusklight ${DUSK_FILES}) add_executable(dusklight ${DUSK_FILES})
endif () endif ()
borealis_configure_android_application(dusklight)
if (ENABLE_ASAN) if (ENABLE_ASAN)
target_sources(dusklight PRIVATE src/dusk/asan_options.c) target_sources(dusklight PRIVATE src/dusk/asan_options.c)
endif () endif ()
@@ -552,17 +468,9 @@ if (TARGET crashpad_handler)
) )
endif () 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(dusklight PRIVATE "-Wl,-u,SDL_main")
endif ()
if (CMAKE_SYSTEM_NAME STREQUAL Linux) if (CMAKE_SYSTEM_NAME STREQUAL Linux)
target_link_options(dusklight PRIVATE "-Wl,--build-id=sha1") target_link_options(dusklight PRIVATE "-Wl,--build-id=sha1")
target_link_libraries(dusklight PRIVATE dl) target_link_libraries(dusklight PRIVATE dl)
elseif (ANDROID)
target_link_options(dusklight PRIVATE "-Wl,--build-id=sha1")
endif () endif ()
if (NOT APPLE) if (NOT APPLE)
@@ -611,6 +519,7 @@ if (DUSK_ENABLE_CODE_MODS AND CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR
add_subdirectory(mods/ao_mod) add_subdirectory(mods/ao_mod)
add_subdirectory(mods/shadow_mod) add_subdirectory(mods/shadow_mod)
add_subdirectory(mods/window_demo) add_subdirectory(mods/window_demo)
add_subdirectory(mods/basic_cosmetics_mod)
endif () endif ()
if (APPLE) if (APPLE)
@@ -644,8 +553,8 @@ if (APPLE)
MACOSX_BUNDLE TRUE MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_BUNDLE_NAME ${DUSK_BUNDLE_NAME} MACOSX_BUNDLE_BUNDLE_NAME ${DUSK_BUNDLE_NAME}
MACOSX_BUNDLE_GUI_IDENTIFIER ${DUSK_BUNDLE_IDENTIFIER} MACOSX_BUNDLE_GUI_IDENTIFIER ${DUSK_BUNDLE_IDENTIFIER}
MACOSX_BUNDLE_BUNDLE_VERSION ${DUSK_VERSION_STRING} MACOSX_BUNDLE_BUNDLE_VERSION ${BOREALIS_APP_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${DUSK_SHORT_VERSION_STRING} MACOSX_BUNDLE_SHORT_VERSION_STRING ${BOREALIS_APP_SHORT_VERSION}
MACOSX_BUNDLE_INFO_PLIST ${DUSK_INFO_PLIST} MACOSX_BUNDLE_INFO_PLIST ${DUSK_INFO_PLIST}
OUTPUT_NAME Dusklight OUTPUT_NAME Dusklight
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "YES" XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "YES"
@@ -678,21 +587,6 @@ if (APPLE)
endif () endif ()
endif () endif ()
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
find_library(APPKIT_FRAMEWORK AppKit REQUIRED)
target_sources(dusklight PRIVATE src/dusk/file_select_macos.mm)
set_source_files_properties(src/dusk/file_select_macos.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
target_link_libraries(dusklight PRIVATE ${APPKIT_FRAMEWORK})
endif ()
if (IOS)
find_library(UIKIT_FRAMEWORK UIKit REQUIRED)
find_library(UNIFORM_TYPE_IDENTIFIERS_FRAMEWORK UniformTypeIdentifiers REQUIRED)
target_sources(dusklight PRIVATE src/dusk/ios/FileSelectDialog.m)
set_source_files_properties(src/dusk/ios/FileSelectDialog.m PROPERTIES COMPILE_FLAGS -fobjc-arc)
target_link_libraries(dusklight PRIVATE ${UIKIT_FRAMEWORK} ${UNIFORM_TYPE_IDENTIFIERS_FRAMEWORK})
endif ()
include(extern/aurora/cmake/AuroraCopyRuntimeDLLs.cmake) include(extern/aurora/cmake/AuroraCopyRuntimeDLLs.cmake)
aurora_copy_runtime_dlls(dusklight) aurora_copy_runtime_dlls(dusklight)
+4 -4
View File
@@ -28,12 +28,12 @@
"cacheVariables": { "cacheVariables": {
"CMAKE_C_COMPILER_LAUNCHER": "sccache", "CMAKE_C_COMPILER_LAUNCHER": "sccache",
"CMAKE_CXX_COMPILER_LAUNCHER": "sccache", "CMAKE_CXX_COMPILER_LAUNCHER": "sccache",
"DUSK_ENABLE_SENTRY_NATIVE": { "BOREALIS_ENABLE_SENTRY": {
"type": "BOOL", "type": "BOOL",
"value": true "value": true
}, },
"DUSK_SENTRY_DSN": "$env{SENTRY_DSN}", "BOREALIS_SENTRY_DSN": "$env{SENTRY_DSN}",
"DUSK_SENTRY_ENVIRONMENT": "production", "BOREALIS_SENTRY_ENVIRONMENT": "production",
"Rust_RUSTUP_INSTALL_MISSING_TARGET": { "Rust_RUSTUP_INSTALL_MISSING_TARGET": {
"type": "BOOL", "type": "BOOL",
"value": true "value": true
@@ -448,7 +448,7 @@
"ci" "ci"
], ],
"cacheVariables": { "cacheVariables": {
"DUSK_ENABLE_SENTRY_NATIVE": { "BOREALIS_ENABLE_SENTRY": {
"type": "BOOL", "type": "BOOL",
"value": false "value": false
} }
+1 -1
View File
@@ -23,5 +23,5 @@ cp -r platforms/freedesktop/{16x16,32x32,48x48,64x64,128x128,256x256,512x512,102
cp platforms/freedesktop/dev.twilitrealm.dusk.desktop build/appdir/usr/share/applications cp platforms/freedesktop/dev.twilitrealm.dusk.desktop build/appdir/usr/share/applications
cd build/install cd build/install
VERSION="$DUSK_VERSION" NO_STRIP=1 "$linuxdeploy" \ VERSION="$APP_VERSION" NO_STRIP=1 "$linuxdeploy" \
-l "$lib_dir/libusb-1.0.so" --appdir "$build_dir/appdir" --output appimage -l "$lib_dir/libusb-1.0.so" --appdir "$build_dir/appdir" --output appimage
-121
View File
@@ -1,121 +0,0 @@
# Version detection shared by the main build and the mod SDK (sdk/CMakeLists.txt)
include_guard(GLOBAL)
get_filename_component(_DUSK_VERSION_ROOT "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
set(DUSK_SENTRY_DSN "" CACHE STRING "Sentry DSN")
set(DUSK_SENTRY_ENVIRONMENT "development" CACHE STRING "Sentry environment")
set(DUSK_VERSION_OVERRIDE "" CACHE STRING "Override version string (skips git detection and format validation)")
macro(detect_version)
if (DUSK_VERSION_OVERRIDE)
set(DUSK_WC_DESCRIBE "${DUSK_VERSION_OVERRIDE}")
set(DUSK_VERSION_STRING "0.0.0.0")
set(DUSK_SHORT_VERSION_STRING "0.0.0")
set(DUSK_VERSION_CODE "1")
set(DUSK_WC_REVISION "")
set(DUSK_WC_BRANCH "")
set(DUSK_WC_DATE "")
message(STATUS "Dusklight version overridden to ${DUSK_WC_DESCRIBE}")
else ()
# obtain revision info from git
find_package(Git)
if (GIT_FOUND)
# make sure version information gets re-run when the current Git HEAD changes
execute_process(WORKING_DIRECTORY ${_DUSK_VERSION_ROOT} COMMAND ${GIT_EXECUTABLE} rev-parse --git-path HEAD
OUTPUT_VARIABLE dusk_git_head_filename
OUTPUT_STRIP_TRAILING_WHITESPACE)
get_filename_component(dusk_git_head_filename "${dusk_git_head_filename}" ABSOLUTE BASE_DIR "${_DUSK_VERSION_ROOT}")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${dusk_git_head_filename}")
execute_process(WORKING_DIRECTORY ${_DUSK_VERSION_ROOT} COMMAND ${GIT_EXECUTABLE} rev-parse --symbolic-full-name HEAD
OUTPUT_VARIABLE dusk_git_head_symbolic
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(WORKING_DIRECTORY ${_DUSK_VERSION_ROOT}
COMMAND ${GIT_EXECUTABLE} rev-parse --git-path ${dusk_git_head_symbolic}
OUTPUT_VARIABLE dusk_git_head_symbolic_filename
OUTPUT_STRIP_TRAILING_WHITESPACE)
get_filename_component(dusk_git_head_symbolic_filename "${dusk_git_head_symbolic_filename}" ABSOLUTE BASE_DIR "${_DUSK_VERSION_ROOT}")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${dusk_git_head_symbolic_filename}")
# defines DUSK_WC_REVISION
execute_process(WORKING_DIRECTORY ${_DUSK_VERSION_ROOT} COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
OUTPUT_VARIABLE DUSK_WC_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE)
# defines DUSK_WC_DESCRIBE
execute_process(WORKING_DIRECTORY ${_DUSK_VERSION_ROOT} COMMAND ${GIT_EXECUTABLE} describe --tags --long --dirty --match "v*"
OUTPUT_VARIABLE DUSK_WC_DESCRIBE
OUTPUT_STRIP_TRAILING_WHITESPACE)
# remove the git hash, then collapse a clean "-0" suffix only
string(REGEX REPLACE "-[^-]+(-dirty|)$" "\\1" DUSK_WC_DESCRIBE "${DUSK_WC_DESCRIBE}")
string(REGEX REPLACE "-0$" "" DUSK_WC_DESCRIBE "${DUSK_WC_DESCRIBE}")
# defines DUSK_WC_BRANCH
execute_process(WORKING_DIRECTORY ${_DUSK_VERSION_ROOT} 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 ${_DUSK_VERSION_ROOT} COMMAND ${GIT_EXECUTABLE} log -1 --format=%ad
OUTPUT_VARIABLE DUSK_WC_DATE
OUTPUT_STRIP_TRAILING_WHITESPACE)
else ()
message(STATUS "Unable to find git, commit information will not be available")
endif ()
if (DUSK_WC_DESCRIBE MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)([-+].*)?$")
set(DUSK_SHORT_VERSION_STRING "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
set(_ver_major ${CMAKE_MATCH_1})
set(_ver_minor ${CMAKE_MATCH_2})
set(_ver_patch ${CMAKE_MATCH_3})
set(DUSK_VERSION_TWEAK "0")
if (DUSK_WC_DESCRIBE MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+-([0-9]+)(-dirty)?$")
set(DUSK_VERSION_TWEAK "${CMAKE_MATCH_1}")
elseif (DUSK_WC_DESCRIBE MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+-[0-9A-Za-z.-]+-([0-9]+)(-dirty)?$")
set(DUSK_VERSION_TWEAK "${CMAKE_MATCH_1}")
endif ()
set(DUSK_VERSION_STRING "${DUSK_SHORT_VERSION_STRING}.${DUSK_VERSION_TWEAK}")
if (DUSK_VERSION_TWEAK GREATER 999)
set(_tweak 999)
else ()
set(_tweak ${DUSK_VERSION_TWEAK})
endif ()
# encoding: major*1e7 + minor*1e5 + patch*1e3 + tweak; collision-free for major<210, minor<100, patch<100, tweak<=999
math(EXPR DUSK_VERSION_CODE
"${_ver_major} * 10000000 + ${_ver_minor} * 100000 + ${_ver_patch} * 1000 + ${_tweak}")
else ()
set(DUSK_WC_DESCRIBE "UNKNOWN-VERSION")
set(DUSK_VERSION_STRING "0.0.0.0")
set(DUSK_SHORT_VERSION_STRING "0.0.0")
set(DUSK_VERSION_CODE "1")
endif ()
endif ()
# Add version information to CI environment variables
if (DEFINED ENV{GITHUB_ENV})
file(APPEND "$ENV{GITHUB_ENV}" "DUSK_VERSION=${DUSK_WC_DESCRIBE}\n")
file(APPEND "$ENV{GITHUB_ENV}" "DUSK_VERSION_CODE=${DUSK_VERSION_CODE}\n")
endif ()
message(STATUS "Dusklight version set to ${DUSK_WC_DESCRIBE}")
endmacro()
# Sets PLATFORM_NAME and configures version.h into the caller's binary dir.
macro(configure_version_header)
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
set(PLATFORM_NAME win32)
elseif (CMAKE_SYSTEM_NAME STREQUAL Darwin)
if (IOS)
set(PLATFORM_NAME ios)
elseif (TVOS)
set(PLATFORM_NAME tvos)
else ()
set(PLATFORM_NAME macos)
endif ()
else ()
string(TOLOWER CMAKE_SYSTEM_NAME PLATFORM_NAME)
endif ()
configure_file(${_DUSK_VERSION_ROOT}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
endmacro()
+101 -8
View File
@@ -209,8 +209,8 @@ if (svc_resource->load(mod_ctx, "config.txt", &buf) == MOD_OK) {
} }
``` ```
Missing files return `MOD_UNAVAILABLE`. Always `free` what you `load`. Note that the bundle is read-only; for writable Missing files return `MOD_UNAVAILABLE`. Always `free` what you `load`. The bundle is read-only; use
storage, use the directory from `svc_host->mod_dir(mod_ctx)`. `HostService::data_dir` for persistent storage.
### HostService (`mods/svc/host.h`) ### HostService (`mods/svc/host.h`)
@@ -219,9 +219,17 @@ Mod metadata and runtime interaction with the loader:
```cpp ```cpp
IMPORT_SERVICE(HostService, svc_host); IMPORT_SERVICE(HostService, svc_host);
const char* id = svc_host->mod_id(mod_ctx); // Temporary mod data directory, wiped on startup
const char* dir = svc_host->mod_dir(mod_ctx); // writable per-mod directory const char* cacheDir = svc_host->mod_dir(mod_ctx);
svc_host->fail(mod_ctx, MOD_ERROR, "something unrecoverable happened"); // disables the mod
// Persistent mod data directory
const char* dataDir = nullptr;
if (svc_host->data_dir(mod_ctx, &dataDir) == MOD_OK) {
// ...
}
// Report an error and disable the mod
svc_host->fail(mod_ctx, MOD_ERROR, "something unrecoverable happened");
``` ```
`get_service`/`publish_service` provide dynamic service lookup; see [Exporting Services](#exporting-services). `get_service`/`publish_service` provide dynamic service lookup; see [Exporting Services](#exporting-services).
@@ -340,6 +348,88 @@ Change callbacks fire on the game thread whenever the value changes at runtime (
Writes that store the same value are silent. Values applied from `config.json` or `--cvar` at registration do Writes that store the same value are silent. Values applied from `config.json` or `--cvar` at registration do
**not** fire callbacks; read the value after `register_var` for the starting state. **not** fire callbacks; read the value after `register_var` for the starting state.
### SaveService (`mods/svc/save.h`)
Stores named binary blobs for each save slot. Blob names are scoped to the calling mod, and each mod may store up to
`SAVE_BLOB_BUDGET_BYTES` per slot. The service copies data passed to `set_blob`.
```cpp
IMPORT_SERVICE(SaveService, svc_save);
struct MySaveData {
uint32_t version;
uint32_t counter;
};
MySaveData state{1, 42};
svc_save->set_blob(mod_ctx, "state", &state, sizeof(state));
MySaveData loaded{};
size_t loadedSize = sizeof(loaded);
if (svc_save->get_blob(mod_ctx, "state", &loaded, &loadedSize) == MOD_OK &&
loadedSize == sizeof(loaded)) {
apply_state(loaded);
}
```
`set_blob`, `get_blob`, and `delete_blob` operate on the current slot, which is available after creating or loading a
save and unavailable at file select. Blob changes are written with the next game save. File-select copy and erase
operations update the blob data as well. Use `peek_blob` to read the calling mod's data from any slot; it uses the same
buffer contract as `get_blob`. Pass a `NULL` buffer to either read function to query the blob size.
`observe_saves` registers callbacks for new, loaded, and written saves. New-save callbacks run after the slot's blobs
are cleared. Observers are removed automatically when the mod is detached, so the output handle is only needed for
manual unregistration. Save callbacks run on the game thread.
### StageService (`mods/svc/stage.h`)
Allows making changes to a stage's "stage info" (contents of .dzs/.dzr files).
(Currently only supports editing actor nodes.)
```cpp
IMPORT_SERVICE(StageService, svc_stage);
stage_actor_data_class record = {
"carry00",
0xFF000000,
cXyz(0.0f, 0.0f, 0.0f),
csXyz(0, 0, 0),
0,
};
StageActorHandle handle{};
svc_stage->patch_actor(mod_ctx, "F_SP102", 0, -1, record_crc, &record, sizeof(record), &handle);
```
```
StageActorHandle handle{};
svc_stage->delete_actor(mod_ctx, "F_SP102", 0, -1, record_crc, &handle);
```
Patch or remove actors from the original actor list as the room loads.
Given records must be of either `stage_actor_data_class` or `stage_tgsc_data_class` types.
`record_crc` is the CRC-32 of the unmodified original record used to identify the record to replace or remove.
```
stage_actor_data_class record = {
"carry00",
0xFF000000,
cXyz(0.0f, 0.0f, 0.0f),
csXyz(0, 0, 0),
0,
};
StageActorHandle handle{};
svc_stage->add_actor(mod_ctx, "F_SP102", 0, -1, &record, sizeof(record), &handle);
```
Add a new actor to the actor list as the room loads.
Given records must be of either `stage_actor_data_class` or `stage_tgsc_data_class` types.
Stage names may contain up to 8 characters. For patches and deletions, room `0xff` and layer `-1` match any room or
layer; additions require a specific room. Edits are removed when the mod is detached. If multiple mods edit the same
record, the later-loaded mod wins.
### UiService (`mods/svc/ui.h`) ### UiService (`mods/svc/ui.h`)
Integrate seamlessly with Dusklight's UI system: add controls and buttons to your mod's detail pane in the Mods window, Integrate seamlessly with Dusklight's UI system: add controls and buttons to your mod's detail pane in the Mods window,
@@ -543,6 +633,9 @@ if (svc_camera->get_camera(mod_ctx, game_view, &camera) == MOD_OK) {
first in-game frame. Projection matrices match the renderer's WebGPU clip convention and renderer depth convention first in-game frame. Projection matrices match the renderer's WebGPU clip convention and renderer depth convention
(reversed-Z by default). (reversed-Z by default).
Camera operators allow overriding the main camera. When an operator callback returns true, its values replace the camera
state for the current frame. Register and unregister using `register_camera_operator` / `unregister_camera_operator`.
--- ---
## Hooking Game Functions ## Hooking Game Functions
@@ -845,6 +938,6 @@ const char* nativeDir = svc_host->native_dir(mod_ctx); // read-only
``` ```
Libraries loaded explicitly by the mod remain its responsibility: stop their threads and unload them during Libraries loaded explicitly by the mod remain its responsibility: stop their threads and unload them during
`mod_shutdown`. Do not write into `native_dir`; use `mod_dir` for writable state. Native library namespaces are `mod_shutdown`. Do not write into `native_dir`; use `data_dir` for persistent storage or `mod_dir` for temporary
process-wide on some platforms, so two mods cannot safely assume that incompatible libraries with the same filename (session) storage. Native library namespaces are process-wide on some platforms, so two mods cannot safely assume that
will remain isolated. incompatible libraries with the same filename will remain isolated.
+1 -1
Vendored Submodule
+1
Submodule extern/borealis added at 6fd955e7e6
+13 -18
View File
@@ -1421,30 +1421,22 @@ set(DUSK_FILES
src/dusk/achievements.cpp src/dusk/achievements.cpp
src/dusk/action_bindings.cpp src/dusk/action_bindings.cpp
src/dusk/action_bindings.h src/dusk/action_bindings.h
src/dusk/android_frame_rate.cpp
src/dusk/android_frame_rate.hpp
src/dusk/asserts.cpp src/dusk/asserts.cpp
src/dusk/autosave.cpp src/dusk/autosave.cpp
src/dusk/config.cpp src/dusk/config.cpp
src/dusk/config.hpp src/dusk/config.hpp
src/dusk/crash_handler.cpp
src/dusk/crash_reporting.cpp
src/dusk/data.cpp src/dusk/data.cpp
src/dusk/data.hpp src/dusk/data.hpp
src/dusk/discord.cpp
src/dusk/discord.hpp
src/dusk/discord_presence.cpp src/dusk/discord_presence.cpp
src/dusk/dvd_asset.cpp src/dusk/dvd_asset.cpp
src/dusk/dvd_asset.hpp src/dusk/dvd_asset.hpp
src/dusk/extras.c src/dusk/extras.c
src/dusk/file_select.cpp
src/dusk/file_select.hpp
src/dusk/frame_interpolation.cpp src/dusk/frame_interpolation.cpp
src/dusk/game_clock.cpp src/dusk/game_clock.cpp
src/dusk/gamepad_color.cpp src/dusk/gamepad_color.cpp
src/dusk/globals.cpp src/dusk/globals.cpp
src/dusk/gyro.cpp src/dusk/gyro.cpp
src/dusk/http/http.hpp src/dusk/hq_minimap.cpp
src/dusk/imgui/ImGuiActorSpawner.cpp src/dusk/imgui/ImGuiActorSpawner.cpp
src/dusk/imgui/ImGuiBloomWindow.cpp src/dusk/imgui/ImGuiBloomWindow.cpp
src/dusk/imgui/ImGuiBloomWindow.hpp src/dusk/imgui/ImGuiBloomWindow.hpp
@@ -1481,6 +1473,9 @@ set(DUSK_FILES
src/dusk/mods/loader/native_module.hpp src/dusk/mods/loader/native_module.hpp
src/dusk/mods/loader/prepatch.cpp src/dusk/mods/loader/prepatch.cpp
src/dusk/mods/loader/prepatch.hpp src/dusk/mods/loader/prepatch.hpp
src/dusk/mods/item.hpp
src/dusk/mods/item_checks.cpp
src/dusk/mods/item_gives.cpp
src/dusk/mods/log_buffer.cpp src/dusk/mods/log_buffer.cpp
src/dusk/mods/log_buffer.hpp src/dusk/mods/log_buffer.hpp
src/dusk/mods/manifest.cpp src/dusk/mods/manifest.cpp
@@ -1492,6 +1487,8 @@ set(DUSK_FILES
src/dusk/mods/svc/gfx.cpp src/dusk/mods/svc/gfx.cpp
src/dusk/mods/svc/hook.cpp src/dusk/mods/svc/hook.cpp
src/dusk/mods/svc/host.cpp src/dusk/mods/svc/host.cpp
src/dusk/mods/svc/item.cpp
src/dusk/mods/svc/item.hpp
src/dusk/mods/svc/log.cpp src/dusk/mods/svc/log.cpp
src/dusk/mods/svc/overlay.cpp src/dusk/mods/svc/overlay.cpp
src/dusk/mods/svc/registry.cpp src/dusk/mods/svc/registry.cpp
@@ -1502,7 +1499,13 @@ set(DUSK_FILES
src/dusk/mods/svc/ui.hpp src/dusk/mods/svc/ui.hpp
src/dusk/mods/svc/window.cpp src/dusk/mods/svc/window.cpp
src/dusk/mods/svc/window.hpp src/dusk/mods/svc/window.hpp
src/dusk/mods/svc/save.cpp
src/dusk/mods/svc/save.hpp
src/dusk/mods/svc/stage.cpp
src/dusk/mods/svc/stage.hpp
src/dusk/mouse.cpp src/dusk/mouse.cpp
src/dusk/presentation.cpp
src/dusk/presentation.hpp
src/dusk/scope_guard.hpp src/dusk/scope_guard.hpp
src/dusk/settings.cpp src/dusk/settings.cpp
src/dusk/speedrun.cpp src/dusk/speedrun.cpp
@@ -1578,18 +1581,10 @@ set(DUSK_FILES
src/dusk/ui/warp.hpp src/dusk/ui/warp.hpp
src/dusk/ui/window.cpp src/dusk/ui/window.cpp
src/dusk/ui/window.hpp src/dusk/ui/window.hpp
src/dusk/update_check.cpp
src/dusk/update_check.hpp
src/dusk/version.cpp src/dusk/version.cpp
src/dusk/utilities.cpp
src/helpers/batch.cpp src/helpers/batch.cpp
src/helpers/endian.cpp src/helpers/endian.cpp
src/helpers/offset_ptr.cpp src/helpers/offset_ptr.cpp
src/helpers/string.cpp src/helpers/string.cpp
) )
set(DUSK_HTTP_BACKEND_FILES
src/dusk/http/no_backend.cpp
src/dusk/http/curl.cpp
src/dusk/http/winhttp.cpp
src/dusk/http/url_session.mm
)
+1 -1
View File
@@ -228,7 +228,7 @@
ninjaFlags = [ "dusklight" ]; ninjaFlags = [ "dusklight" ];
cmakeFlags = [ cmakeFlags = [
"-DDUSK_VERSION_OVERRIDE=${versionSuffix}" "-DBOREALIS_APP_VERSION_OVERRIDE=${versionSuffix}"
"-DFETCHCONTENT_FULLY_DISCONNECTED=ON" "-DFETCHCONTENT_FULLY_DISCONNECTED=ON"
"-DAURORA_DAWN_PROVIDER=package" "-DAURORA_DAWN_PROVIDER=package"
"-DAURORA_DAWN_LINKAGE=static" "-DAURORA_DAWN_LINKAGE=static"
+3
View File
@@ -96,6 +96,9 @@ public:
/* 0xDE0 */ cXyz field_0xde0; /* 0xDE0 */ cXyz field_0xde0;
/* 0xDEC */ u8 field_0xdec[0xdf9 - 0xdec]; /* 0xDEC */ u8 field_0xdec[0xdf9 - 0xdec];
/* 0xDF9 */ u8 field_0xdf9; /* 0xDF9 */ u8 field_0xdf9;
#if TARGET_PC
bool mItemCheckOverridden;
#endif
}; };
STATIC_ASSERT(sizeof(daE_HP_c) == 0xdfc); STATIC_ASSERT(sizeof(daE_HP_c) == 0xdfc);
+1 -1
View File
@@ -423,7 +423,7 @@ public:
static DUSK_GAME_DATA daMidna_texData_s const m_texDataTable[21]; static DUSK_GAME_DATA daMidna_texData_s const m_texDataTable[21];
static DUSK_GAME_DATA daMidna_anmData_s const m_anmDataTable[53]; static DUSK_GAME_DATA daMidna_anmData_s const m_anmDataTable[53];
private: // private:
/* 0x568 */ request_of_phase_process_class mPhase; /* 0x568 */ request_of_phase_process_class mPhase;
/* 0x570 */ J3DModel* mpModel; /* 0x570 */ J3DModel* mpModel;
/* 0x574 */ J3DModel* mpShadowModel; /* 0x574 */ J3DModel* mpShadowModel;
+5
View File
@@ -88,6 +88,11 @@ private:
/* 0x99C */ dPa_followEcallBack mEffect2; /* 0x99C */ dPa_followEcallBack mEffect2;
/* 0x9B0 */ Z2SoundObjSimple mSound; /* 0x9B0 */ Z2SoundObjSimple mSound;
/* 0x9D0 */ u8 mIsHookCarry; /* 0x9D0 */ u8 mIsHookCarry;
#if TARGET_PC
u8 mOriginalItemNo;
bool mItemOverridden;
bool mOverrideHover;
#endif
}; };
STATIC_ASSERT(sizeof(daObjLife_c) == 0x9d4); STATIC_ASSERT(sizeof(daObjLife_c) == 0x9d4);
+3
View File
@@ -194,6 +194,9 @@ private:
/* 0x9FC */ u8 field_0x9fc; /* 0x9FC */ u8 field_0x9fc;
/* 0x9FD */ u8 field_0x9fd; /* 0x9FD */ u8 field_0x9fd;
/* 0xA00 */ Mtx mDrawMtx; /* 0xA00 */ Mtx mDrawMtx;
#if TARGET_PC
u8 mOriginalItemNo;
#endif
}; };
STATIC_ASSERT(sizeof(daTbox_c) == 0xA30); STATIC_ASSERT(sizeof(daTbox_c) == 0xA30);
+4
View File
@@ -83,6 +83,10 @@ private:
/* 0xAC0 */ u8 field_0xAC0[0xAC4 - 0xAC0]; /* 0xAC0 */ u8 field_0xAC0[0xAC4 - 0xAC0];
/* 0xAC4 */ int mStaffIdx; /* 0xAC4 */ int mStaffIdx;
/* 0xAC8 */ dBgW* mBoxBgW; /* 0xAC8 */ dBgW* mBoxBgW;
#if TARGET_PC
bool mParamsInit;
u8 mOriginalItemNo;
#endif
}; };
STATIC_ASSERT(sizeof(daTbox2_c) == 0xACC); STATIC_ASSERT(sizeof(daTbox2_c) == 0xACC);
+4
View File
@@ -145,6 +145,10 @@ public:
/* 0x9BC */ u8 field_0x9bc[4]; /* 0x9BC */ u8 field_0x9bc[4];
/* 0x9C0 */ u8 field_0x9c0; /* 0x9C0 */ u8 field_0x9c0;
/* 0x9C1 */ u8 field_0x9c1; /* 0x9C1 */ u8 field_0x9c1;
#if TARGET_PC
u8 mOriginalItemNo;
bool mItemOverridden;
#endif
}; // Size: 0x9C4 }; // Size: 0x9C4
#endif /* D_A_D_A_ITEM_STATIC_H */ #endif /* D_A_D_A_ITEM_STATIC_H */
+7
View File
@@ -50,6 +50,9 @@ public:
csXyz* getRotateP(); csXyz* getRotateP();
cXyz* getPosP(); cXyz* getPosP();
const char* getShopArcname(); const char* getShopArcname();
#if TARGET_PC
const ResourceData& getResourceData() const;
#endif
u16 getHeapSize(); u16 getHeapSize();
void CreateInit(); void CreateInit();
void set_mtx(); void set_mtx();
@@ -110,6 +113,10 @@ private:
/* 0x960 */ s16 mAngleX; /* 0x960 */ s16 mAngleX;
/* 0x962 */ s16 mAngleY; /* 0x962 */ s16 mAngleY;
/* 0x964 */ u8 mShopItemID; /* 0x964 */ u8 mShopItemID;
#if TARGET_PC
ResourceData mOverrideData;
bool mItemOverridden;
#endif
}; };
int CheckShopItemCreateHeap(fopAc_ac_c* i_this); int CheckShopItemCreateHeap(fopAc_ac_c* i_this);
+1 -1
View File
@@ -37,7 +37,7 @@ public:
CPaneMgrAlpha* getNoDatBase() { return mNoDatBase; } CPaneMgrAlpha* getNoDatBase() { return mNoDatBase; }
void draw() { _draw(); } void draw() { _draw(); }
private: // private:
/* 0x04 */ JKRArchive* mArchive; /* 0x04 */ JKRArchive* mArchive;
/* 0x08 */ dDlst_FileInfo_c mFileInfo; /* 0x08 */ dDlst_FileInfo_c mFileInfo;
/* 0x1C */ u8 field_0x1c[4]; /* 0x1C */ u8 field_0x1c[4];
+1 -29
View File
@@ -13,36 +13,8 @@ class dFile_info_c;
class J2DPicture; class J2DPicture;
#if TARGET_PC #if TARGET_PC
static PaneCache mSelDtPanes[] = {
{MULTI_CHAR('tate_n0'), 0.0f, 0.0f, false},
{MULTI_CHAR('tate_n1'), 0.0f, 0.0f, false},
{MULTI_CHAR('ken_n0'), 0.0f, 0.0f, false},
{MULTI_CHAR('ken_n1'), 0.0f, 0.0f, false},
{MULTI_CHAR('fuku_n0'), 0.0f, 0.0f, false},
{MULTI_CHAR('fuku_n1'), 0.0f, 0.0f, false},
{MULTI_CHAR('fuku_n2'), 0.0f, 0.0f, false},
{MULTI_CHAR('gray_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('b_base'), 0.0f, 0.0f, false},
{MULTI_CHAR('b_base1'), 0.0f, 0.0f, false},
};
static PaneCache fileSelPanes[] = {
{MULTI_CHAR('w_uzu00'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_uzu01'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_uzu02'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_uzu03'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_uzu04'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_uzu05'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_uzu06'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_uzu07'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_uzu08'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_uzu09'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_er_msg'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_er_msE'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_er_msR'), 0.0f, 0.0f, false},
{MULTI_CHAR('er_for0'), 0.0f, 0.0f, false},
{MULTI_CHAR('er_for1'), 0.0f, 0.0f, false},
};
#endif #endif
class dDlst_FileSel_c : public dDlst_base_c { class dDlst_FileSel_c : public dDlst_base_c {
+3 -1
View File
@@ -11,7 +11,9 @@ public:
static DUSK_GAME_DATA u8* mData; static DUSK_GAME_DATA u8* mData;
}; };
void execItemGet(u8 item_id); class fopAc_ac_c;
void execItemGet(
u8 item_id IF_DUSK_ARG(u32 item_give_tag = 0) IF_DUSK_ARG(fopAc_ac_c* giver = NULL));
void item_func_HEART(); void item_func_HEART();
void item_func_GREEN_RUPEE(); void item_func_GREEN_RUPEE();
+1 -1
View File
@@ -30,7 +30,7 @@ public:
void drawSelf() { mpKanteraIcon->draw(); } void drawSelf() { mpKanteraIcon->draw(); }
private: // private:
/* 0x04 */ dDlst_KanteraIcon_c* mpKanteraIcon; /* 0x04 */ dDlst_KanteraIcon_c* mpKanteraIcon;
/* 0x08 */ CPaneMgr* mpParent; /* 0x08 */ CPaneMgr* mpParent;
/* 0x0C */ CPaneMgr* mpGauge; /* 0x0C */ CPaneMgr* mpGauge;
+1 -44
View File
@@ -15,49 +15,6 @@ class dMenu_Fishing_c;
class dMenu_Skill_c; class dMenu_Skill_c;
class dMenu_Insect_c; class dMenu_Insect_c;
class dSelect_cursor_c; class dSelect_cursor_c;
#if TARGET_PC
struct PaneCache {
u64 tag;
f32 origTransX;
f32 origTransY;
bool cached;
};
static PaneCache mpScreenPanes[] = {
{MULTI_CHAR('sa_tex_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('op_tex_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('heart_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('wolf_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('item_0_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('item_1_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('item_2_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('fish_3_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('lett_4_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('maki_5_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('fuku_n0'), 0.0f, 0.0f, false},
{MULTI_CHAR('fuku_n1'), 0.0f, 0.0f, false},
{MULTI_CHAR('fuku_n2'), 0.0f, 0.0f, false},
{MULTI_CHAR('tate_n0'), 0.0f, 0.0f, false},
{MULTI_CHAR('tate_n1'), 0.0f, 0.0f, false},
{MULTI_CHAR('ken_n0'), 0.0f, 0.0f, false},
{MULTI_CHAR('ken_n1'), 0.0f, 0.0f, false},
{MULTI_CHAR('kabu_6n'), 0.0f, 0.0f, false},
{MULTI_CHAR('t_t00'), 0.0f, 0.0f, false},
{MULTI_CHAR('f_t00'), 0.0f, 0.0f, false},
{MULTI_CHAR('itemn_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('infotxtn'), 0.0f, 0.0f, false},
{MULTI_CHAR('sa_op_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('title_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('menu_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('w_er_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('center_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('info_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('lavel_n'), 0.0f, 0.0f, false},
{MULTI_CHAR('modelbgn'), 0.0f, 0.0f, false},
};
#endif
class dMenu_Collect2D_c; class dMenu_Collect2D_c;
class dMenu_Collect2DTop_c : public dDlst_base_c { class dMenu_Collect2DTop_c : public dDlst_base_c {
public: public:
@@ -172,7 +129,7 @@ public:
J2DPicture* getBlackTex() { return mpBlackTex; } J2DPicture* getBlackTex() { return mpBlackTex; }
u8 getSubWindowOpenCheck() { return mSubWindowOpenCheck; } u8 getSubWindowOpenCheck() { return mSubWindowOpenCheck; }
private: // private:
/* 0x004 */ JKRExpHeap* mpHeap; /* 0x004 */ JKRExpHeap* mpHeap;
/* 0x008 */ JKRExpHeap* mpSubHeap; /* 0x008 */ JKRExpHeap* mpSubHeap;
/* 0x00C */ void* field_0xc; /* 0x00C */ void* field_0xc;
+1 -1
View File
@@ -43,7 +43,7 @@ public:
u8 getStatus() { return mStatus; } u8 getStatus() { return mStatus; }
private: // private:
/* 0x004 */ JKRExpHeap* mpHeap; /* 0x004 */ JKRExpHeap* mpHeap;
/* 0x008 */ JKRArchive* mpArchive; /* 0x008 */ JKRArchive* mpArchive;
/* 0x00C */ STControl* mpStick; /* 0x00C */ STControl* mpStick;
+1 -1
View File
@@ -270,7 +270,7 @@ public:
static DUSK_GAME_DATA dMenu_Fmap_c* MyClass; static DUSK_GAME_DATA dMenu_Fmap_c* MyClass;
private: // private:
/* 0x004 */ JKRExpHeap* mpHeap; /* 0x004 */ JKRExpHeap* mpHeap;
/* 0x008 */ JKRExpHeap* mpTalkHeap; /* 0x008 */ JKRExpHeap* mpTalkHeap;
/* 0x00C */ STControl* mpStick; /* 0x00C */ STControl* mpStick;
+1 -1
View File
@@ -60,7 +60,7 @@ public:
u8 getStatus() { return mStatus; } u8 getStatus() { return mStatus; }
private: // private:
/* 0x04 */ JKRExpHeap* mpHeap; /* 0x04 */ JKRExpHeap* mpHeap;
/* 0x08 */ JKRArchive* mpArchive; /* 0x08 */ JKRArchive* mpArchive;
/* 0x0C */ STControl* mpStick; /* 0x0C */ STControl* mpStick;
+1 -1
View File
@@ -64,7 +64,7 @@ public:
u8 getStatus() { return mStatus; } u8 getStatus() { return mStatus; }
private: // private:
/* 0x004 */ JKRExpHeap* mpHeap; /* 0x004 */ JKRExpHeap* mpHeap;
/* 0x008 */ JKRArchive* mpArchive; /* 0x008 */ JKRArchive* mpArchive;
/* 0x00C */ STControl* mpStick; /* 0x00C */ STControl* mpStick;
+1 -1
View File
@@ -117,7 +117,7 @@ public:
return ((u8)mUseFlag & (u8)i_flag) != 0 ? true : false; return ((u8)mUseFlag & (u8)i_flag) != 0 ? true : false;
} }
private: // private:
/* 0x004 */ J2DScreen* mpBackScreen; /* 0x004 */ J2DScreen* mpBackScreen;
/* 0x008 */ J2DScreen* mpScreen; /* 0x008 */ J2DScreen* mpScreen;
/* 0x00C */ J2DScreen* mpClipScreen; /* 0x00C */ J2DScreen* mpClipScreen;
+1 -1
View File
@@ -84,7 +84,7 @@ public:
void drawFlag0() { mDrawFlag = 0; } void drawFlag0() { mDrawFlag = 0; }
void setStatus(u8 i_status) { mStatus = i_status; } void setStatus(u8 i_status) { mStatus = i_status; }
private: // private:
/* 0x004 */ JKRExpHeap* mpHeap; /* 0x004 */ JKRExpHeap* mpHeap;
/* 0x008 */ STControl* mpStick; /* 0x008 */ STControl* mpStick;
/* 0x00C */ CSTControl* mpCStick; /* 0x00C */ CSTControl* mpCStick;
+1 -1
View File
@@ -278,7 +278,7 @@ public:
u8 getEndStatus() { return mEndStatus; } u8 getEndStatus() { return mEndStatus; }
void setUseType(u8 type) { mUseType = type; } void setUseType(u8 type) { mUseType = type; }
private: // private:
/* 0x0004 */ JKRArchive* mpArchive; /* 0x0004 */ JKRArchive* mpArchive;
/* 0x0008 */ mDoDvdThd_mountArchive_c* mpMount; /* 0x0008 */ mDoDvdThd_mountArchive_c* mpMount;
/* 0x000C */ STControl* stick; /* 0x000C */ STControl* stick;
+1 -1
View File
@@ -58,7 +58,7 @@ public:
u8 getStatus() { return mStatus; } u8 getStatus() { return mStatus; }
private: // private:
/* 0x004 */ JKRExpHeap* mpHeap; /* 0x004 */ JKRExpHeap* mpHeap;
/* 0x008 */ JKRArchive* mpArchive; /* 0x008 */ JKRArchive* mpArchive;
/* 0x00C */ STControl* mpStick; /* 0x00C */ STControl* mpStick;
+1 -1
View File
@@ -154,7 +154,7 @@ public:
} }
#endif #endif
private: // private:
/* 0x004 */ item_params mItemParams[4]; /* 0x004 */ item_params mItemParams[4];
/* 0x074 */ JKRExpHeap* heap; /* 0x074 */ JKRExpHeap* heap;
/* 0x078 */ J2DScreen* mpScreen; /* 0x078 */ J2DScreen* mpScreen;
+2 -2
View File
@@ -25,7 +25,7 @@ public:
void setTextBoxPtr(J2DTextBox* p_textBox) { mpTextBoxPtr = p_textBox; } void setTextBoxPtr(J2DTextBox* p_textBox) { mpTextBoxPtr = p_textBox; }
void resetType() { mType = 0x47; } void resetType() { mType = 0x47; }
private: // private:
/* 0x04 */ J2DTextBox* mpTextBoxPtr; /* 0x04 */ J2DTextBox* mpTextBoxPtr;
/* 0x08 */ f32 mPosX; /* 0x08 */ f32 mPosX;
/* 0x0C */ f32 mPosY; /* 0x0C */ f32 mPosY;
@@ -53,7 +53,7 @@ public:
void setRupeeColor(u8 color) { mRupeeColor = color; } void setRupeeColor(u8 color) { mRupeeColor = color; }
private: // private:
/* 0x004 */ COutFontSet_c* mpOfs[35]; /* 0x004 */ COutFontSet_c* mpOfs[35];
/* 0x090 */ J2DPicture* mpPane[70]; /* 0x090 */ J2DPicture* mpPane[70];
/* 0x1A8 */ f32 mAlphaRatio; /* 0x1A8 */ f32 mAlphaRatio;
-28
View File
@@ -12,34 +12,6 @@ class J2DTextBox;
class JUTFont; class JUTFont;
class STControl; class STControl;
#if TARGET_PC
struct PaneCache {
u64 tag;
f32 origTransX;
f32 origTransY;
bool cached;
};
static PaneCache l_tagName[] = {
{MULTI_CHAR('m_00_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_3'), 0.0f, 0.0f, false},
{MULTI_CHAR('m_01_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_2'), 0.0f, 0.0f, false},
{MULTI_CHAR('m03_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_1'), 0.0f, 0.0f, false},
{MULTI_CHAR('m_05_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_0'), 0.0f, 0.0f, false},
{MULTI_CHAR('m_07_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_4'), 0.0f, 0.0f, false},
{MULTI_CHAR('m_09_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_3'), 0.0f, 0.0f, false},
{MULTI_CHAR('m_10_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_2'), 0.0f, 0.0f, false},
{MULTI_CHAR('m12_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_0'), 0.0f, 0.0f, false},
};
static PaneCache l_nameTagName[] = {
{MULTI_CHAR('name_00'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_01'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_02'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_03'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_04'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_05'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_06'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_07'), 0.0f, 0.0f, false},
};
static PaneCache l_nameCurTagName[] = {
{MULTI_CHAR('s__n_00'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_01'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_02'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_03'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_04'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_05'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_06'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_07'), 0.0f, 0.0f, false},
};
#endif
class dNm_HIO_c { class dNm_HIO_c {
public: public:
dNm_HIO_c(); dNm_HIO_c();
+5
View File
@@ -318,6 +318,11 @@ public:
/* 0x566 */ s8 field_0x566; /* 0x566 */ s8 field_0x566;
/* 0x567 */ s8 field_0x567; /* 0x567 */ s8 field_0x567;
#if TARGET_PC
u32 mItemGiveTag;
u8 mItemGiveOriginalNo;
#endif
#if !__MWERKS__ #if !__MWERKS__
s8 actor_last_base_field; s8 actor_last_base_field;
#endif #endif
+20 -13
View File
@@ -79,6 +79,10 @@ struct fopAcM_prm_class {
/* 0x1C */ fpc_ProcID parent_id; /* 0x1C */ fpc_ProcID parent_id;
/* 0x20 */ s8 argument; /* 0x20 */ s8 argument;
/* 0x21 */ s8 room_no; /* 0x21 */ s8 room_no;
#if TARGET_PC
u32 mItemGiveTag;
u8 mItemGiveOriginalNo;
#endif
}; };
struct fopAcM_search4ev_prm { struct fopAcM_search4ev_prm {
@@ -516,8 +520,9 @@ s32 fopAcM_SearchByName(s16 i_procName, fopAc_ac_c** i_outActor);
fopAcM_prm_class* fopAcM_CreateAppend(); fopAcM_prm_class* fopAcM_CreateAppend();
fopAcM_prm_class* createAppend(u16 i_setId, u32 i_parameters, const cXyz* i_pos, int i_roomNo, fopAcM_prm_class* createAppend(u16 i_setId, u32 i_parameters, const cXyz* i_pos, int i_roomNo,
const csXyz* i_angle, const cXyz* i_scale, s8 i_argument, const csXyz* i_angle, const cXyz* i_scale, s8 i_argument,
fpc_ProcID i_parentId); fpc_ProcID i_parentId IF_DUSK_ARG(u32 i_itemGiveTag = 0)
IF_DUSK_ARG(u8 i_itemOriginalNo = 0xFF));
void fopAcM_Log(fopAc_ac_c const* i_actor, char const* i_message); void fopAcM_Log(fopAc_ac_c const* i_actor, char const* i_message);
@@ -526,19 +531,20 @@ s32 fopAcM_delete(fopAc_ac_c* i_actor);
s32 fopAcM_delete(fpc_ProcID i_actorID); s32 fopAcM_delete(fpc_ProcID i_actorID);
fpc_ProcID fopAcM_create(s16 i_procName, u16 i_setId, u32 i_parameters, const cXyz* i_pos, fpc_ProcID fopAcM_create(s16 i_procName, u16 i_setId, u32 i_parameters, const cXyz* i_pos,
int i_roomNo, const csXyz* i_angle, const cXyz* i_scale, s8 i_argument, int i_roomNo, const csXyz* i_angle, const cXyz* i_scale, s8 i_argument,
createFunc i_createFunc); createFunc i_createFunc IF_DUSK_ARG(u32 i_itemGiveTag = 0));
fpc_ProcID fopAcM_create(s16 i_procName, u32 i_parameters, const cXyz* i_pos, int i_roomNo, fpc_ProcID fopAcM_create(s16 i_procName, u32 i_parameters, const cXyz* i_pos, int i_roomNo,
const csXyz* i_angle, const cXyz* i_scale, s8 i_argument); const csXyz* i_angle, const cXyz* i_scale, s8 i_argument IF_DUSK_ARG(u32 i_itemGiveTag = 0));
inline fpc_ProcID fopAcM_Create(s16 i_procName, createFunc i_createFunc, void* params) { inline fpc_ProcID fopAcM_Create(s16 i_procName, createFunc i_createFunc, void* params) {
return fpcM_Create(i_procName, i_createFunc,params); return fpcM_Create(i_procName, i_createFunc,params);
} }
fopAc_ac_c* fopAcM_fastCreate(s16 i_procName, u32 i_parameters, const cXyz* i_pos, int i_roomNo, fopAc_ac_c* fopAcM_fastCreate(s16 i_procName, u32 i_parameters, const cXyz* i_pos, int i_roomNo,
const csXyz* i_angle, const cXyz* i_scale, s8 i_argument, const csXyz* i_angle, const cXyz* i_scale, s8 i_argument, createFunc i_createFunc,
createFunc i_createFunc, void* i_createFuncData); void* i_createFuncData IF_DUSK_ARG(u32 i_itemGiveTag = 0)
IF_DUSK_ARG(u8 i_itemOriginalNo = 0xFF));
fopAc_ac_c* fopAcM_fastCreate(const char* i_actorname, u32 i_parameters, const cXyz* i_pos, fopAc_ac_c* fopAcM_fastCreate(const char* i_actorname, u32 i_parameters, const cXyz* i_pos,
int i_roomNo, const csXyz* i_angle, const cXyz* i_scale, int i_roomNo, const csXyz* i_angle, const cXyz* i_scale,
@@ -623,11 +629,11 @@ fopAc_ac_c* fopAcM_getItemEventPartner(const fopAc_ac_c*);
fopAc_ac_c* fopAcM_getEventPartner(const fopAc_ac_c*); fopAc_ac_c* fopAcM_getEventPartner(const fopAc_ac_c*);
fpc_ProcID fopAcM_createItemForPresentDemo(cXyz const* i_pos, int i_itemNo, u8 param_2, fpc_ProcID fopAcM_createItemForPresentDemo(cXyz const* i_pos, int i_itemNo, u8 param_2,
int i_itemBitNo, int i_roomNo, csXyz const* i_angle, int i_itemBitNo, int i_roomNo, csXyz const* i_angle,
cXyz const* i_scale); cXyz const* i_scale IF_DUSK_ARG(u32 i_itemGiveTag = 0));
fpc_ProcID fopAcM_createItemForTrBoxDemo(cXyz const* i_pos, int i_itemNo, int i_itemBitNo, fpc_ProcID fopAcM_createItemForTrBoxDemo(cXyz const* i_pos, int i_itemNo, int i_itemBitNo,
int i_roomNo, csXyz const* i_angle, cXyz const* i_scale); int i_roomNo, csXyz const* i_angle, cXyz const* i_scale IF_DUSK_ARG(u32 i_itemGiveTag = 0));
u8 fopAcM_getItemNoFromTableNo(u8 i_tableNo); u8 fopAcM_getItemNoFromTableNo(u8 i_tableNo);
@@ -641,11 +647,12 @@ fpc_ProcID fopAcM_createItemFromTable(cXyz const* i_pos, int i_tableNo, int i_it
bool i_createDirect); bool i_createDirect);
fpc_ProcID fopAcM_createDemoItem(const cXyz* i_pos, int i_itemNo, int i_itemBitNo, fpc_ProcID fopAcM_createDemoItem(const cXyz* i_pos, int i_itemNo, int i_itemBitNo,
const csXyz* i_angle, int i_roomNo, const cXyz* scale, u8 param_7); const csXyz* i_angle, int i_roomNo, const cXyz* scale,
u8 param_7 IF_DUSK_ARG(u32 i_itemGiveTag = 0));
fpc_ProcID fopAcM_createItemForBoss(const cXyz* i_pos, int i_itemNo, int i_roomNo, fpc_ProcID fopAcM_createItemForBoss(const cXyz* i_pos, int i_itemNo, int i_roomNo,
const csXyz* i_angle, const cXyz* i_scale, f32 i_speedF, const csXyz* i_angle, const cXyz* i_scale, f32 i_speedF, f32 i_speedY,
f32 i_speedY, int param_8); int param_8 IF_DUSK_ARG(const char* i_itemCheckName = NULL));
fpc_ProcID fopAcM_createItemForMidBoss(const cXyz* i_pos, int i_itemNo, int i_roomNo, fpc_ProcID fopAcM_createItemForMidBoss(const cXyz* i_pos, int i_itemNo, int i_roomNo,
const csXyz* i_angle, const cXyz* i_scale, int param_6, const csXyz* i_angle, const cXyz* i_scale, int param_6,
+13
View File
@@ -256,4 +256,17 @@ using std::isnan;
#define DUSK_CONST IF_DUSK(const) #define DUSK_CONST IF_DUSK(const)
#define DUSK_CONSTEXPR IF_DUSK(constexpr) #define DUSK_CONSTEXPR IF_DUSK(constexpr)
#if TARGET_PC && defined(DUSK_BUILDING_GAME)
#include "dusk/mods/item.hpp"
#define DUSK_ITEM_CHECK(name, item_no, giver) \
(item_no) = ::dusk::mods::item_check(name, (item_no), giver)
#define DUSK_ITEM_CHECK_EXPR(name, item_no, giver) \
(::dusk::mods::item_check(name, (item_no), giver))
#define DUSK_GIVE_TAG(name) IF_DUSK_ARG(::dusk::mods::item_give_tag(name))
#else
#define DUSK_ITEM_CHECK(name, item_no, giver)
#define DUSK_ITEM_CHECK_EXPR(name, item_no, giver) (item_no)
#define DUSK_GIVE_TAG(name)
#endif
#endif #endif
+3 -3
View File
@@ -68,7 +68,7 @@ public:
JKRMemArchive* getArchive() const { return mArchive; } JKRMemArchive* getArchive() const { return mArchive; }
JKRHeap* getHeap() const { return mHeap; } JKRHeap* getHeap() const { return mHeap; }
private: // private:
/* 0x14 */ u8 mMountDirection; /* 0x14 */ u8 mMountDirection;
/* 0x18 */ s32 mEntryNumber; /* 0x18 */ s32 mEntryNumber;
/* 0x1C */ JKRMemArchive* mArchive; /* 0x1C */ JKRMemArchive* mArchive;
@@ -130,8 +130,8 @@ private:
}; // Size = 0x28 }; // Size = 0x28
struct mDoDvdThdStack { struct mDoDvdThdStack {
u8 stack[4096]; ATTRIBUTE_ALIGN(16) u8 stack[4096];
} ATTRIBUTE_ALIGN(16); };
struct mDoDvdThd { struct mDoDvdThd {
static s32 main(void*); static s32 main(void*);
+21 -5
View File
@@ -2,6 +2,7 @@
#define JASCALC_H #define JASCALC_H
#include <types.h> #include <types.h>
#include <cstring>
#include <limits> #include <limits>
/** /**
@@ -10,16 +11,31 @@
*/ */
struct JASCalc { struct JASCalc {
static void imixcopy(const s16*, const s16*, s16*, u32); static void imixcopy(const s16*, const s16*, s16*, u32);
static void bcopyfast(const void* src, void* dest, u32 size); #if TARGET_PC
static void bcopyfast(const void* src, void* dest, u32 size) {
std::memcpy(dest, src, size);
}
#if TARGET_ANDROID #if TARGET_ANDROID
static void _bcopy(const void* src, void* dest, u32 size); static void _bcopy(const void* src, void* dest, u32 size) {
#else #else
static void bcopy(const void* src, void* dest, u32 size); static void bcopy(const void* src, void* dest, u32 size) {
#endif #endif
static void bzerofast(void* dest, u32 size); std::memcpy(dest, src, size);
}
static void bzerofast(void* dest, u32 size) {
std::memset(dest, 0, size);
}
#if TARGET_ANDROID #if TARGET_ANDROID
static void _bzero(void* dest, u32 size); static void _bzero(void* dest, u32 size) {
#else #else
static void bzero(void* dest, u32 size) {
#endif
std::memset(dest, 0, size);
}
#else
static void bcopyfast(const void* src, void* dest, u32 size);
static void bcopy(const void* src, void* dest, u32 size);
static void bzerofast(void* dest, u32 size);
static void bzero(void* dest, u32 size); static void bzero(void* dest, u32 size);
#endif #endif
static f32 pow2(f32); static f32 pow2(f32);
+2 -2
View File
@@ -23,9 +23,9 @@ DUSK_GAME_DATA Vec J3DSys::mParentS;
DUSK_GAME_DATA J3DTexCoordScaleInfo J3DSys::sTexCoordScaleTable[8]; DUSK_GAME_DATA J3DTexCoordScaleInfo J3DSys::sTexCoordScaleTable[8];
#if TARGET_PC // Original game bug, array is too small. #if TARGET_PC // Original game bug, array is too small.
static u8 NullTexData[0x20] ATTRIBUTE_ALIGN(32) = {0}; ATTRIBUTE_ALIGN(32) static u8 NullTexData[0x20] = {0};
#else #else
static u8 NullTexData[0x10] ATTRIBUTE_ALIGN(32) = {0}; ATTRIBUTE_ALIGN(32) static u8 NullTexData[0x10] = {0};
#endif #endif
static Mtx j3dIdentityMtx = { static Mtx j3dIdentityMtx = {
+2 -8
View File
@@ -11,6 +11,7 @@ void JASCalc::imixcopy(const s16* s1, const s16* s2, s16* dst, u32 n) {
} }
} }
#if !TARGET_PC
void JASCalc::bcopyfast(const void* src, void* dest, u32 size) { void JASCalc::bcopyfast(const void* src, void* dest, u32 size) {
JUT_ASSERT(226, (reinterpret_cast<uintptr_t>(src) & 0x03) == 0); JUT_ASSERT(226, (reinterpret_cast<uintptr_t>(src) & 0x03) == 0);
JUT_ASSERT(227, (reinterpret_cast<uintptr_t>(dest) & 0x03) == 0); JUT_ASSERT(227, (reinterpret_cast<uintptr_t>(dest) & 0x03) == 0);
@@ -33,11 +34,7 @@ void JASCalc::bcopyfast(const void* src, void* dest, u32 size) {
} }
} }
#if TARGET_ANDROID
void JASCalc::_bcopy(const void* src, void* dest, u32 size) {
#else
void JASCalc::bcopy(const void* src, void* dest, u32 size) { void JASCalc::bcopy(const void* src, void* dest, u32 size) {
#endif
u32* usrc; u32* usrc;
u32* udest; u32* udest;
@@ -94,11 +91,7 @@ void JASCalc::bzerofast(void* dest, u32 size) {
} }
} }
#if TARGET_ANDROID
void JASCalc::_bzero(void* dest, u32 size) {
#else
void JASCalc::bzero(void* dest, u32 size) { void JASCalc::bzero(void* dest, u32 size) {
#endif
u32* udest; u32* udest;
u8* bdest = (u8*)dest; u8* bdest = (u8*)dest;
if ((size & 0x1f) == 0 && (reinterpret_cast<uintptr_t>(dest) & 0x1f) == 0) { if ((size & 0x1f) == 0 && (reinterpret_cast<uintptr_t>(dest) & 0x1f) == 0) {
@@ -139,6 +132,7 @@ void JASCalc::bzero(void* dest, u32 size) {
} }
} }
} }
#endif
#if AVOID_UB #if AVOID_UB
DUSK_GAME_DATA s16 const JASCalc::CUTOFF_TO_IIR_TABLE[129][4] = { DUSK_GAME_DATA s16 const JASCalc::CUTOFF_TO_IIR_TABLE[129][4] = {
+2 -2
View File
@@ -99,14 +99,14 @@ void JASDsp::invalChannelAll() {
DCInvalidateRange(CH_BUF, sizeof(TChannel) * DSP_CHANNELS); DCInvalidateRange(CH_BUF, sizeof(TChannel) * DSP_CHANNELS);
} }
DUSK_GAME_DATA u8 const ATTRIBUTE_ALIGN(32) JASDsp::DSPADPCM_FILTER[64] = { ATTRIBUTE_ALIGN(32) DUSK_GAME_DATA u8 const JASDsp::DSPADPCM_FILTER[64] = {
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00,
0x10, 0x00, 0xF8, 0x00, 0x0E, 0x00, 0xFA, 0x00, 0x0C, 0x00, 0xFC, 0x00, 0x12, 0x00, 0xF6, 0x00, 0x10, 0x00, 0xF8, 0x00, 0x0E, 0x00, 0xFA, 0x00, 0x0C, 0x00, 0xFC, 0x00, 0x12, 0x00, 0xF6, 0x00,
0x10, 0x68, 0xF7, 0x38, 0x12, 0xC0, 0xF7, 0x04, 0x14, 0x00, 0xF4, 0x00, 0x08, 0x00, 0xF8, 0x00, 0x10, 0x68, 0xF7, 0x38, 0x12, 0xC0, 0xF7, 0x04, 0x14, 0x00, 0xF4, 0x00, 0x08, 0x00, 0xF8, 0x00,
0x04, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0x04, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x04, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0x04, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00,
}; };
DUSK_GAME_DATA u32 const ATTRIBUTE_ALIGN(32) JASDsp::DSPRES_FILTER[320] = { ATTRIBUTE_ALIGN(32) DUSK_GAME_DATA u32 const JASDsp::DSPRES_FILTER[320] = {
0x0C3966AD, 0x0C3966AD,
0x0D46FFDF, 0x0D46FFDF,
0x0B396696, 0x0B396696,
+3 -3
View File
@@ -25,7 +25,7 @@ void DspHandShake(void*) {
Dsp_Running_Start(); Dsp_Running_Start();
} }
static u8 jdsp[7936] ATTRIBUTE_ALIGN(32) = { ATTRIBUTE_ALIGN(32) static u8 jdsp[7936] = {
0x02, 0x9F, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02, 0x9F, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02, 0xFF, 0x00, 0x00,
0x02, 0xFF, 0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02, 0x9F, 0x06, 0xA5, 0x02, 0xFF, 0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02, 0x9F, 0x06, 0xA5,
0x02, 0x9F, 0x00, 0x4E, 0x12, 0x05, 0x02, 0xBF, 0x00, 0x57, 0x81, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x02, 0x9F, 0x00, 0x4E, 0x12, 0x05, 0x02, 0xBF, 0x00, 0x57, 0x81, 0x00, 0x00, 0x9F, 0x10, 0x00,
@@ -524,9 +524,9 @@ static u8 jdsp[7936] ATTRIBUTE_ALIGN(32) = {
0x80, 0x01, 0x02, 0xBF, 0x00, 0xF4, 0x02, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x02, 0xBF, 0x00, 0xF4, 0x02, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; };
static DSPTaskInfo audio_task ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static DSPTaskInfo audio_task;
static u8 AUDIO_YIELD_BUFFER[8192] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u8 AUDIO_YIELD_BUFFER[8192];
void DspBoot(void (*requestCallback)(void*)) { void DspBoot(void (*requestCallback)(void*)) {
DspInitWork(); DspInitWork();
+7 -12
View File
@@ -38,7 +38,7 @@ void JFWDisplay::ctor_subroutine(bool enableAlpha) {
mTickRate = 0; mTickRate = 0;
mCombinationRatio = 0.0f; mCombinationRatio = 0.0f;
field_0x30 = 0; field_0x30 = 0;
field_0x2c = OSGetTick(); field_0x2c = DUSK_IF_ELSE(static_cast<OSTick>(OSGetNativeTime()), OSGetTick());
field_0x34 = 0; field_0x34 = 0;
field_0x48 = 0; field_0x48 = 0;
field_0x4a = 0; field_0x4a = 0;
@@ -258,7 +258,7 @@ void JFWDisplay::beginRender() {
waitForTick(mTickRate, mFrameRate); waitForTick(mTickRate, mFrameRate);
JUTVideo::getManager()->waitRetraceIfNeed(); JUTVideo::getManager()->waitRetraceIfNeed();
OSTick tick = OSGetTick(); OSTick tick = DUSK_IF_ELSE(static_cast<OSTick>(OSGetNativeTime()), OSGetTick());
field_0x30 = tick - field_0x2c; field_0x30 = tick - field_0x2c;
field_0x2c = tick; field_0x2c = tick;
field_0x34 = field_0x2c - JUTVideo::getVideoLastTick(); field_0x34 = field_0x2c - JUTVideo::getVideoLastTick();
@@ -371,7 +371,7 @@ constexpr auto FRAME_PERIOD = std::chrono::duration_cast<std::chrono::nanosecond
constexpr auto RETRACE_PERIOD = FRAME_PERIOD / 2; constexpr auto RETRACE_PERIOD = FRAME_PERIOD / 2;
static void waitPrecise(Limiter& limiter, Limiter::duration_t targetNs) { static void waitPrecise(Limiter& limiter, Limiter::duration_t targetNs) {
const auto sleepTime = limiter.Sleep(targetNs); const auto sleepTime = limiter.Sleep(targetNs);
dusk::frameUsagePct = dusk::frameUsagePct =
100.0f * (1.0f - static_cast<float>(sleepTime) / static_cast<float>(targetNs)); 100.0f * (1.0f - static_cast<float>(sleepTime) / static_cast<float>(targetNs));
} }
@@ -381,15 +381,12 @@ static void waitForTick(u32 p1, u16 p2) {
#if TARGET_PC #if TARGET_PC
static Limiter limiter; static Limiter limiter;
if (dusk::frame_interp::is_enabled() && !dusk::getTransientSettings().skipFrameRateLimit) { if (dusk::frame_interp::is_enabled() || dusk::getTransientSettings().turboMode) {
limiter.Reset();
dusk::frameUsagePct = 0.f; dusk::frameUsagePct = 0.f;
return; return;
} }
if (dusk::getTransientSettings().skipFrameRateLimit) {
p1 = OS_TIMER_CLOCK / 120;
}
if (fopOvlpM_IsPeek() && dusk::getTransientSettings().stateShareLoadActive) { if (fopOvlpM_IsPeek() && dusk::getTransientSettings().stateShareLoadActive) {
return; return;
} }
@@ -399,7 +396,6 @@ static void waitForTick(u32 p1, u16 p2) {
if (p1 != 0) { if (p1 != 0) {
#if TARGET_PC #if TARGET_PC
static Limiter limiter;
waitPrecise(limiter, static_cast<Uint64>(OSTicksToMicroseconds(p1)) * 1000ULL); waitPrecise(limiter, static_cast<Uint64>(OSTicksToMicroseconds(p1)) * 1000ULL);
#else #else
static OSTime nextTick = OSGetTime(); static OSTime nextTick = OSGetTime();
@@ -413,7 +409,6 @@ static void waitForTick(u32 p1, u16 p2) {
} else { } else {
u32 uVar1 = (p2 == 0) ? 1 : p2; u32 uVar1 = (p2 == 0) ? 1 : p2;
#if TARGET_PC #if TARGET_PC
static Limiter limiter;
waitPrecise(limiter, static_cast<Uint64>((RETRACE_PERIOD * uVar1).count())); waitPrecise(limiter, static_cast<Uint64>((RETRACE_PERIOD * uVar1).count()));
#else #else
static u32 nextCount = VIGetRetraceCount(); static u32 nextCount = VIGetRetraceCount();
@@ -452,13 +447,13 @@ static void dummy() {
JUTXfb::getManager()->setDisplayingXfbIndex(0); JUTXfb::getManager()->setDisplayingXfbIndex(0);
} }
static Mtx e_mtx ATTRIBUTE_ALIGN(32) = { ATTRIBUTE_ALIGN(32) static Mtx e_mtx = {
{1.0f, 0.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f},
}; };
static u8 clear_z_TX[64] ATTRIBUTE_ALIGN(32) = { ATTRIBUTE_ALIGN(32) static u8 clear_z_TX[64] = {
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+3 -3
View File
@@ -16,10 +16,10 @@ inline f64 getConst2() {
return 9.765625E-4; return 9.765625E-4;
} }
DUSK_GAME_DATA TSinCosTable<13, f32> sincosTable_ ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) DUSK_GAME_DATA TSinCosTable<13, f32> sincosTable_;
DUSK_GAME_DATA TAtanTable<1024, f32> atanTable_ ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) DUSK_GAME_DATA TAtanTable<1024, f32> atanTable_;
DUSK_GAME_DATA TAsinAcosTable<1024, f32> asinAcosTable_ ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) DUSK_GAME_DATA TAsinAcosTable<1024, f32> asinAcosTable_;
} // namespace JMath } // namespace JMath
+2 -2
View File
@@ -46,7 +46,7 @@ JPAResource::JPAResource() {
mUsrIdx = fldNum = keyNum = texNum = mpCalcEmitterFuncListNum = mpDrawEmitterFuncListNum = mpDrawEmitterChildFuncListNum = mpCalcParticleFuncListNum = mpDrawParticleFuncListNum = mpCalcParticleChildFuncListNum = mpDrawParticleChildFuncListNum = 0; mUsrIdx = fldNum = keyNum = texNum = mpCalcEmitterFuncListNum = mpDrawEmitterFuncListNum = mpDrawEmitterChildFuncListNum = mpCalcParticleFuncListNum = mpDrawParticleFuncListNum = mpCalcParticleChildFuncListNum = mpDrawParticleChildFuncListNum = 0;
} }
static u8 jpa_pos[324] ATTRIBUTE_ALIGN(32) = { ATTRIBUTE_ALIGN(32) static u8 jpa_pos[324] = {
0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0xCE, 0x00, 0x00, 0xCE, 0x00, 0xE7, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0xCE, 0x00, 0x00, 0xCE, 0x00, 0xE7, 0x00, 0x00, 0x19,
0x00, 0x00, 0x19, 0xCE, 0x00, 0xE7, 0xCE, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x19, 0xCE, 0x00, 0xE7, 0xCE, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE,
0x00, 0xCE, 0xCE, 0x00, 0x00, 0x19, 0x00, 0x32, 0x19, 0x00, 0x32, 0xE7, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xCE, 0xCE, 0x00, 0x00, 0x19, 0x00, 0x32, 0x19, 0x00, 0x32, 0xE7, 0x00, 0x00, 0xE7, 0x00,
@@ -70,7 +70,7 @@ static u8 jpa_pos[324] ATTRIBUTE_ALIGN(32) = {
0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xCE,
}; };
static u8 jpa_crd[32] ATTRIBUTE_ALIGN(32) = { ATTRIBUTE_ALIGN(32) static u8 jpa_crd[32] = {
0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00, 0x01,
0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02,
}; };
@@ -8,7 +8,7 @@
#endif #endif
#include "global.h" #include "global.h"
DUSK_GAME_DATA u8 const JUTResFONT_Ascfont_fix12[] ATTRIBUTE_ALIGN(32) = { ATTRIBUTE_ALIGN(32) DUSK_GAME_DATA u8 const JUTResFONT_Ascfont_fix12[] = {
0x46, 0x4F, 0x4E, 0x54, 0x62, 0x66, 0x6E, 0x31, 0x00, 0x00, 0x41, 0x60, 0x00, 0x00, 0x00, 0x04, 0x46, 0x4F, 0x4E, 0x54, 0x62, 0x66, 0x6E, 0x31, 0x00, 0x00, 0x41, 0x60, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0x4E, 0x46, 0x31, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x49, 0x4E, 0x46, 0x31, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C,
+2 -2
View File
@@ -42,7 +42,7 @@ JUTVideo::JUTVideo(GXRenderModeObj const* param_0) {
mRetraceCount = VIGetRetraceCount(); mRetraceCount = VIGetRetraceCount();
field_0x10 = 1; field_0x10 = 1;
field_0x18 = 0; field_0x18 = 0;
sVideoLastTick = OSGetTick(); sVideoLastTick = DUSK_IF_ELSE(static_cast<OSTick>(OSGetNativeTime()), OSGetTick());
sVideoInterval = 670000; sVideoInterval = 670000;
mPreRetraceCallback = VISetPreRetraceCallback(preRetraceProc); mPreRetraceCallback = VISetPreRetraceCallback(preRetraceProc);
mPostRetraceCallback = VISetPostRetraceCallback(postRetraceProc); mPostRetraceCallback = VISetPostRetraceCallback(postRetraceProc);
@@ -68,7 +68,7 @@ void JUTVideo::preRetraceProc(u32 retrace_count) {
(*sManager->mPreCallback)(retrace_count); (*sManager->mPreCallback)(retrace_count);
} }
OSTick tick = OSGetTick(); OSTick tick = DUSK_IF_ELSE(static_cast<OSTick>(OSGetNativeTime()), OSGetTick());
sVideoInterval = tick - sVideoLastTick; sVideoInterval = tick - sVideoLastTick;
sVideoLastTick = tick; sVideoLastTick = tick;
@@ -136,7 +136,7 @@ void TRK__read_aram(__REGISTER int c, __REGISTER u32 p2, void* p3) {
} }
void TRK__write_aram(__REGISTER int c, __REGISTER u32 p2, void* p3) { void TRK__write_aram(__REGISTER int c, __REGISTER u32 p2, void* p3) {
u8 buff[32] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 buff[32];
u32 err; u32 err;
__REGISTER int count = c; __REGISTER int count = c;
__REGISTER u32 bf; __REGISTER u32 bf;
@@ -85,7 +85,7 @@ DSError TRKDoSupportMask(TRKBuffer*) {
} }
DSError TRKDoReadMemory(TRKBuffer* buffer) { DSError TRKDoReadMemory(TRKBuffer* buffer) {
u8 buf[0x820] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 buf[0x820];
size_t tempLength; size_t tempLength;
int result; int result;
int replyErr; int replyErr;
@@ -158,7 +158,7 @@ DSError TRKDoReadMemory(TRKBuffer* buffer) {
} }
DSError TRKDoWriteMemory(TRKBuffer* b) { DSError TRKDoWriteMemory(TRKBuffer* b) {
u8 buf[0x820] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 buf[0x820];
size_t tempLength; size_t tempLength;
int options; int options;
int result; int result;
+2 -2
View File
@@ -3,8 +3,8 @@
#include "__ax.h" #include "__ax.h"
static s32 __AXBufferAuxA[3][480] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static s32 __AXBufferAuxA[3][480];
static s32 __AXBufferAuxB[3][480] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static s32 __AXBufferAuxB[3][480];
static void (* __AXCallbackAuxA)(void*, void*); static void (* __AXCallbackAuxA)(void*, void*);
static void (* __AXCallbackAuxB)(void*, void*); static void (* __AXCallbackAuxB)(void*, void*);
+1 -1
View File
@@ -3,7 +3,7 @@
#include "__ax.h" #include "__ax.h"
static AXSPB __AXStudio ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static AXSPB __AXStudio;
static s32 __AXSpbAL; static s32 __AXSpbAL;
static s32 __AXSpbAR; static s32 __AXSpbAR;
+3 -3
View File
@@ -35,9 +35,9 @@ static u32 __AXAuxMixCycles[32] = {
0x000009E2, 0x00000E97 0x000009E2, 0x00000E97
}; };
static AXPB __AXPB[AX_MAX_VOICES] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static AXPB __AXPB[AX_MAX_VOICES];
static AXPBITDBUFFER __AXITD[AX_MAX_VOICES] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static AXPBITDBUFFER __AXITD[AX_MAX_VOICES];
static AXPBU __AXUpdates[AX_MAX_VOICES] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static AXPBU __AXUpdates[AX_MAX_VOICES];
static AXVPB __AXVPB[AX_MAX_VOICES]; static AXVPB __AXVPB[AX_MAX_VOICES];
static u32 __AXMaxDspCycles; static u32 __AXMaxDspCycles;
+1 -1
View File
@@ -3,7 +3,7 @@
u16 axDspSlaveLength = (AX_DSP_SLAVE_LENGTH * 2); u16 axDspSlaveLength = (AX_DSP_SLAVE_LENGTH * 2);
u16 axDspSlave[AX_DSP_SLAVE_LENGTH] ATTRIBUTE_ALIGN(32) = { ATTRIBUTE_ALIGN(32) u16 axDspSlave[AX_DSP_SLAVE_LENGTH] = {
0x0000, 0x0000, 0x029F, 0x0E88, 0x029F, 0x0E97, 0x0000, 0x0000, 0x029F, 0x0E88, 0x029F, 0x0E97,
0x029F, 0x0EB3, 0x029F, 0x0ED3, 0x029F, 0x0ED9, 0x029F, 0x0EB3, 0x029F, 0x0ED3, 0x029F, 0x0ED9,
0x029F, 0x0F0B, 0x029F, 0x0F11, 0x1302, 0x1303, 0x029F, 0x0F0B, 0x029F, 0x0F11, 0x1302, 0x1303,
+1 -1
View File
@@ -4,7 +4,7 @@
#include "__card.h" #include "__card.h"
static u8 CardData[352] ATTRIBUTE_ALIGN(DOLPHIN_ALIGNMENT) = { ATTRIBUTE_ALIGN(DOLPHIN_ALIGNMENT) static u8 CardData[352] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0xFF, 0x00, 0x21, 0x13, 0x06, 0x12, 0x03, 0x12, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0xFF, 0x00, 0x21, 0x13, 0x06, 0x12, 0x03, 0x12, 0x04,
0x13, 0x05, 0x00, 0x92, 0x00, 0xFF, 0x00, 0x88, 0xFF, 0xFF, 0x00, 0x89, 0xFF, 0xFF, 0x00, 0x8A, 0xFF, 0xFF, 0x00, 0x13, 0x05, 0x00, 0x92, 0x00, 0xFF, 0x00, 0x88, 0xFF, 0xFF, 0x00, 0x89, 0xFF, 0xFF, 0x00, 0x8A, 0xFF, 0xFF, 0x00,
+1 -1
View File
@@ -3,7 +3,7 @@
#include <dolphin/demo.h> #include <dolphin/demo.h>
#include "sdk_math.h" #include "sdk_math.h"
static s16 __AVX_internal_buffer[3200] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static s16 __AVX_internal_buffer[3200];
static void (*__AVX_save_isr)(void); static void (*__AVX_save_isr)(void);
+1 -1
View File
@@ -1,7 +1,7 @@
#include <dolphin/dolphin.h> #include <dolphin/dolphin.h>
#include <dolphin/demo.h> #include <dolphin/demo.h>
u32 DEMOFontBitmap[768] ATTRIBUTE_ALIGN(32) = { ATTRIBUTE_ALIGN(32) u32 DEMOFontBitmap[768] = {
0x00000000, 0x00000000,
0x00000000, 0x00000000,
0x00000000, 0x00000000,
+1 -1
View File
@@ -43,7 +43,7 @@ void* __piReg;
GXBool __GXinBegin; GXBool __GXinBegin;
#endif #endif
static u16 DefaultTexData[] ATTRIBUTE_ALIGN(32) = { ATTRIBUTE_ALIGN(32) static u16 DefaultTexData[] = {
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
}; };
+5 -5
View File
@@ -7,11 +7,11 @@ const char* __MCCVersion = "<< Dolphin SDK - MCC\tdebug build: Apr 5 2004 03:57
const char* __MCCVersion = "<< Dolphin SDK - MCC\trelease build: Apr 5 2004 04:15:49 (0x2301) >>"; const char* __MCCVersion = "<< Dolphin SDK - MCC\trelease build: Apr 5 2004 04:15:49 (0x2301) >>";
#endif #endif
static MCC_ChannelInfo gChannelInfo[16] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static MCC_ChannelInfo gChannelInfo[16];
static char gStreamWork[32] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static char gStreamWork[32];
static char m_szAdapterMode[32] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static char m_szAdapterMode[32];
static char m_szInitCode[32] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static char m_szInitCode[32];
static MCC_Info channelInfo[16] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static MCC_Info channelInfo[16];
volatile static BOOL gIsChannelinfoDirty = TRUE; volatile static BOOL gIsChannelinfoDirty = TRUE;
+1 -1
View File
@@ -3,7 +3,7 @@
#include "__os.h" #include "__os.h"
static SramControl Scb ATTRIBUTE_ALIGN(DOLPHIN_ALIGNMENT); ATTRIBUTE_ALIGN(DOLPHIN_ALIGNMENT) static SramControl Scb;
// prototypes // prototypes
static int GetRTC(u32* rtc); static int GetRTC(u32* rtc);
+1 -1
View File
@@ -3,7 +3,7 @@
#include "__card.h" #include "__card.h"
static u8 CardData[352] ATTRIBUTE_ALIGN(DOLPHIN_ALIGNMENT) = { ATTRIBUTE_ALIGN(DOLPHIN_ALIGNMENT) static u8 CardData[352] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0xFF, 0x00, 0x21, 0x13, 0x06, 0x12, 0x03, 0x12, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0xFF, 0x00, 0x21, 0x13, 0x06, 0x12, 0x03, 0x12, 0x04,
0x13, 0x05, 0x00, 0x92, 0x00, 0xFF, 0x00, 0x88, 0xFF, 0xFF, 0x00, 0x89, 0xFF, 0xFF, 0x00, 0x8A, 0xFF, 0xFF, 0x00, 0x13, 0x05, 0x00, 0x92, 0x00, 0xFF, 0x00, 0x88, 0xFF, 0xFF, 0x00, 0x89, 0xFF, 0xFF, 0x00, 0x8A, 0xFF, 0xFF, 0x00,
+5 -5
View File
@@ -44,7 +44,7 @@ static u32 LastError;
static BOOL ResetRequired; static BOOL ResetRequired;
static u32 MotorState; static u32 MotorState;
static volatile OSTime LastResetEnd; static volatile OSTime LastResetEnd;
static u32 __DVDNumTmdBytes ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u32 __DVDNumTmdBytes;
static DVDGameTOC* GameToc; static DVDGameTOC* GameToc;
static DVDPartitionInfo* PartInfo; static DVDPartitionInfo* PartInfo;
static DVDPartitionInfo* BootGameInfo; static DVDPartitionInfo* BootGameInfo;
@@ -80,10 +80,10 @@ static DVDCommandBlock DummyCommandBlock;
static OSAlarm ResetAlarm; static OSAlarm ResetAlarm;
static OSAlarm CoverAlarm; static OSAlarm CoverAlarm;
static u8 __DVDGameTocBuffer[OSRoundUp32B(sizeof(DVDGameTOC) * 4)] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u8 __DVDGameTocBuffer[OSRoundUp32B(sizeof(DVDGameTOC) * 4)];
static u8 __DVDPartInfoBuffer[OSRoundUp32B(sizeof(DVDPartitionInfo) * 4)] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u8 __DVDPartInfoBuffer[OSRoundUp32B(sizeof(DVDPartitionInfo) * 4)];
static u8 __DVDTmdBuffer[OSRoundUp32B(sizeof(ESTitleMeta))] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u8 __DVDTmdBuffer[OSRoundUp32B(sizeof(ESTitleMeta))];
static u8 __DVDTicketViewBuffer[OSRoundUp32B(sizeof(ESTicketView))] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u8 __DVDTicketViewBuffer[OSRoundUp32B(sizeof(ESTicketView))];
static OSAlarm FatalAlarm; static OSAlarm FatalAlarm;
DVDCommandBlock __DVDStopMotorCommandBlock; DVDCommandBlock __DVDStopMotorCommandBlock;
+1 -1
View File
@@ -5,7 +5,7 @@
#include "__os.h" #include "__os.h"
#include "__dvd.h" #include "__dvd.h"
static u8 CheckBuffer[32] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u8 CheckBuffer[32];
static volatile BOOL lowDone = TRUE; static volatile BOOL lowDone = TRUE;
static volatile u32 lowIntType = 0; static volatile u32 lowIntType = 0;
+7 -7
View File
@@ -8,15 +8,15 @@ static volatile u8 requestInProgress = FALSE;
static u8 breakRequested; static u8 breakRequested;
static u8 callbackInProgress; static u8 callbackInProgress;
static u32 registerBuf[8] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u32 registerBuf[8];
static u32 statusRegister[8] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u32 statusRegister[8];
static u32 controlRegister[8] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u32 controlRegister[8];
static s32 lastTicketError[8] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static s32 lastTicketError[8];
static u32 readLength; static u32 readLength;
static u32 spinUpValue; static u32 spinUpValue;
static diRegVals_t diRegValCache ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static diRegVals_t diRegValCache;
static u8 DVDLowInitCalled = FALSE; static u8 DVDLowInitCalled = FALSE;
@@ -42,8 +42,8 @@ typedef struct dvdContext {
static int freeDvdContext = 0; static int freeDvdContext = 0;
static u8 dvdContextsInited = FALSE; static u8 dvdContextsInited = FALSE;
static dvdContext_t dvdContexts[4] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static dvdContext_t dvdContexts[4];
static IOSIoVector ioVec[10] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static IOSIoVector ioVec[10];
static void* ddrAllocAligned32(const int size) { static void* ddrAllocAligned32(const int size) {
void* low, *high; void* low, *high;
+2 -2
View File
@@ -11,8 +11,8 @@ static NANDCommandBlock NandCb;
static NANDFileInfo NandInfo; static NANDFileInfo NandInfo;
static DVDCBCallback Callback; static DVDCBCallback Callback;
static u32 NextOffset; static u32 NextOffset;
DVDErrorInfo __ErrorInfo ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) DVDErrorInfo __ErrorInfo;
DVDErrorInfo __FirstErrorInfo ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) DVDErrorInfo __FirstErrorInfo;
void cbForNandClose(s32 result, NANDCommandBlock* block) { void cbForNandClose(s32 result, NANDCommandBlock* block) {
if (Callback) { if (Callback) {
+8 -8
View File
@@ -33,7 +33,7 @@ s32 ESP_CloseLib(void) {
s32 ESP_LaunchTitle(u64 titleID, ESTicketView* pTicketView) { s32 ESP_LaunchTitle(u64 titleID, ESTicketView* pTicketView) {
s32 ret = 0; s32 ret = 0;
u8 buf[256] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 buf[256];
IOSIoVector* vec = (IOSIoVector*)(buf + 208); IOSIoVector* vec = (IOSIoVector*)(buf + 208);
u64* id = (u64*)buf; u64* id = (u64*)buf;
@@ -63,7 +63,7 @@ out:
s32 ESP_GetTicketViews(ESTitleId titleId, ESTicketView* ticketViewList, u32* ticketViewCnt) { s32 ESP_GetTicketViews(ESTitleId titleId, ESTicketView* ticketViewList, u32* ticketViewCnt) {
s32 rv = 0; s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 __esBuf[256];
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector)); IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
ESTitleId* p1 = (ESTitleId*)__esBuf; ESTitleId* p1 = (ESTitleId*)__esBuf;
u32* p2 = (u32*)(__esBuf + 32); u32* p2 = (u32*)(__esBuf + 32);
@@ -111,7 +111,7 @@ out:
s32 ESP_DiGetTicketView(const void* ticket, ESTicketView* ticketView) { s32 ESP_DiGetTicketView(const void* ticket, ESTicketView* ticketView) {
s32 rv = 0; s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 __esBuf[256];
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector)); IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
if (__esFd < 0 || ticketView == NULL) { if (__esFd < 0 || ticketView == NULL) {
@@ -142,7 +142,7 @@ out:
s32 ESP_DiGetTmd(ESTitleMeta* tmd, u32* tmdSize) { s32 ESP_DiGetTmd(ESTitleMeta* tmd, u32* tmdSize) {
s32 rv = 0; s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 __esBuf[256];
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector)); IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
u32* p1 = (u32*)__esBuf; u32* p1 = (u32*)__esBuf;
@@ -184,7 +184,7 @@ out:
s32 ESP_GetTmdView(ESTitleId titleId, ESTmdView* tmdView, u32* size) { s32 ESP_GetTmdView(ESTitleId titleId, ESTmdView* tmdView, u32* size) {
s32 rv = 0; s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 __esBuf[256];
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector)); IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
ESTitleId* p1 = (ESTitleId*)__esBuf; ESTitleId* p1 = (ESTitleId*)__esBuf;
u32* p2 = (u32*)(__esBuf + 32); u32* p2 = (u32*)(__esBuf + 32);
@@ -233,7 +233,7 @@ out:
s32 ESP_GetDataDir(ESTitleId titleId, char* dataDir) { s32 ESP_GetDataDir(ESTitleId titleId, char* dataDir) {
s32 rv = 0; s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 __esBuf[256];
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector)); IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
ESTitleId* p1 = (ESTitleId*)__esBuf; ESTitleId* p1 = (ESTitleId*)__esBuf;
@@ -260,7 +260,7 @@ out:
s32 ESP_GetTitleId(ESTitleId* titleId) { s32 ESP_GetTitleId(ESTitleId* titleId) {
s32 rv = 0; s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 __esBuf[256];
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector)); IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
if (__esFd < 0 || titleId == NULL) { if (__esFd < 0 || titleId == NULL) {
@@ -283,7 +283,7 @@ out:
s32 ESP_GetConsumption(ESTicketId ticketId, ESLpEntry* entries, u32* nEntries) { s32 ESP_GetConsumption(ESTicketId ticketId, ESLpEntry* entries, u32* nEntries) {
s32 rv = 0; s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 __esBuf[256];
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector)); IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
ESTicketId* p1 = (ESTicketId*)__esBuf; ESTicketId* p1 = (ESTicketId*)__esBuf;
u32* p2 = (u32*)(__esBuf + 32); u32* p2 = (u32*)(__esBuf + 32);
+1 -1
View File
@@ -25,7 +25,7 @@ typedef struct isfs_GetUsage {
} isfs_GetUsage; } isfs_GetUsage;
typedef struct __isfsCtxt { typedef struct __isfsCtxt {
u8 ioBuf[ROUNDUP(256)] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 ioBuf[ROUNDUP(256)];
ISFSCallback cb; ISFSCallback cb;
void* ctxt; void* ctxt;
u32 func; u32 func;
+1 -1
View File
@@ -49,7 +49,7 @@ volatile void* __piReg;
GXBool __GXinBegin; GXBool __GXinBegin;
#endif #endif
static u16 DefaultTexData[] ATTRIBUTE_ALIGN(32) = { ATTRIBUTE_ALIGN(32) static u16 DefaultTexData[] = {
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
}; };
@@ -34,7 +34,7 @@ namespace nw4hbm {
private: private:
/* 0x00 (base) */ /* 0x00 (base) */
/* 0xD4 */ ut::Color mVtxColors[VERTEXCOLOR_MAX] ATTRIBUTE_ALIGN(4); /* 0xD4 */ ATTRIBUTE_ALIGN(4) ut::Color mVtxColors[VERTEXCOLOR_MAX];
/* 0xE4 */ detail::TexCoordAry mTexCoordAry; /* 0xE4 */ detail::TexCoordAry mTexCoordAry;
}; };
@@ -58,7 +58,7 @@ namespace nw4hbm {
public: public:
/* 0x14 */ ut::LinkListNode mLinkNode; /* 0x14 */ ut::LinkListNode mLinkNode;
static u8 mMramBuf[LOAD_BUFFER_SIZE] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u8 mMramBuf[LOAD_BUFFER_SIZE];
}; };
typedef ut::LinkList<LoadCommand, offsetof(LoadCommand, mLinkNode)> LoadCommandList; typedef ut::LinkList<LoadCommand, offsetof(LoadCommand, mLinkNode)> LoadCommandList;
+2 -2
View File
@@ -24,7 +24,7 @@ static u32 __relnchFl = 0;
typedef struct IOSRpcRequest { typedef struct IOSRpcRequest {
IOSResourceRequest request; IOSResourceRequest request;
IOSIpcCb cb ATTRIBUTE_ALIGN(32); // I am assuming this is aligned due to where cbArg is stored, and I see nothing between cb and callback_arg? ATTRIBUTE_ALIGN(32) IOSIpcCb cb; // I am assuming this is aligned due to where cbArg is stored, and I see nothing between cb and callback_arg?
void* callback_arg; void* callback_arg;
u32 relaunch_flag; u32 relaunch_flag;
OSThreadQueue thread_queue; OSThreadQueue thread_queue;
@@ -37,7 +37,7 @@ static IOSRpcRequest* __relnchRpcSave = 0;
#define ROUNDUP(sz) (((u32)(sz) + (IPC_BUF_CNT / 2 - 1)) & ~(u32)(IPC_BUF_CNT / 2 - 1)) #define ROUNDUP(sz) (((u32)(sz) + (IPC_BUF_CNT / 2 - 1)) & ~(u32)(IPC_BUF_CNT / 2 - 1))
static u8 __rpcBuf[ROUNDUP(sizeof(IOSRpcRequest))] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u8 __rpcBuf[ROUNDUP(sizeof(IOSRpcRequest))];
static struct { static struct {
u32 rcount; u32 rcount;
+4 -4
View File
@@ -33,8 +33,8 @@ enum LibState {
}; };
static enum LibState s_libState = STATE_NOT_INITIALIZED; static enum LibState s_libState = STATE_NOT_INITIALIZED;
static char s_currentDir[64] ATTRIBUTE_ALIGN(32) = "/"; ATTRIBUTE_ALIGN(32) static char s_currentDir[64] = "/";
static char s_homeDir[64] ATTRIBUTE_ALIGN(32) = ""; ATTRIBUTE_ALIGN(32) static char s_homeDir[64] = "";
static BOOL nandOnShutdown(BOOL final, u32 event); static BOOL nandOnShutdown(BOOL final, u32 event);
void nandConvertPath(char* abspath, const char* wd, const char* relpath); void nandConvertPath(char* abspath, const char* wd, const char* relpath);
@@ -262,7 +262,7 @@ s32 nandConvertErrorCode(const ISFSError err) {
for (; i < sizeof(ERRMAP) / 4; i = i + 2) { for (; i < sizeof(ERRMAP) / 4; i = i + 2) {
if (ERRMAP[i] == err) { if (ERRMAP[i] == err) {
if (err == ISFS_ERROR_ECC_CRIT || err == ISFS_ERROR_HMAC || err == ISFS_ERROR_UNKNOWN || err == IOS_ERROR_UNKNOWN || err == IOS_ERROR_ECC_CRIT) { if (err == ISFS_ERROR_ECC_CRIT || err == ISFS_ERROR_HMAC || err == ISFS_ERROR_UNKNOWN || err == IOS_ERROR_UNKNOWN || err == IOS_ERROR_ECC_CRIT) {
char buf[128] ATTRIBUTE_ALIGN(64); ATTRIBUTE_ALIGN(64) char buf[128];
sprintf(buf, "ISFS error code: %d", err); sprintf(buf, "ISFS error code: %d", err);
NANDLoggingAddMessageAsync(nandLoggingCallback, err, buf); NANDLoggingAddMessageAsync(nandLoggingCallback, err, buf);
} }
@@ -279,7 +279,7 @@ s32 nandConvertErrorCode(const ISFSError err) {
OSReport("CAUTION! Unexpected error code [%d] was found.\n", err); OSReport("CAUTION! Unexpected error code [%d] was found.\n", err);
{ {
char buf[128] ATTRIBUTE_ALIGN(64); ATTRIBUTE_ALIGN(64) char buf[128];
sprintf(buf, "ISFS unexpected error code: %d", err); sprintf(buf, "ISFS unexpected error code: %d", err);
NANDLoggingAddMessageAsync(nandLoggingCallback, err, buf); NANDLoggingAddMessageAsync(nandLoggingCallback, err, buf);
} }
+3 -3
View File
@@ -7,7 +7,7 @@
static IOSFd s_fd = -255; static IOSFd s_fd = -255;
static IOSError s_err = ISFS_ERROR_UNKNOWN; static IOSError s_err = ISFS_ERROR_UNKNOWN;
static int s_stage; static int s_stage;
static char s_message[256] ATTRIBUTE_ALIGN(64); ATTRIBUTE_ALIGN(64) static char s_message[256];
static NANDLoggingCallback s_callback = 0; static NANDLoggingCallback s_callback = 0;
static void asyncRoutine(ISFSError, void*); static void asyncRoutine(ISFSError, void*);
@@ -70,8 +70,8 @@ static void callbackRoutine(BOOL result) {
static void asyncRoutine(ISFSError result, void *ctxt) { static void asyncRoutine(ISFSError result, void *ctxt) {
ISFSError ret = ISFS_ERROR_UNKNOWN; ISFSError ret = ISFS_ERROR_UNKNOWN;
static char s_rBuf[256] ATTRIBUTE_ALIGN(64); ATTRIBUTE_ALIGN(64) static char s_rBuf[256];
static char s_wBuf[256] ATTRIBUTE_ALIGN(64); ATTRIBUTE_ALIGN(64) static char s_wBuf[256];
++s_stage; ++s_stage;
if (s_stage == 2) { if (s_stage == 2) {
+1 -1
View File
@@ -293,7 +293,7 @@ s32 NANDMove(const char* path, const char* destDir) {
} }
static ISFSError nandGetFileStatus(IOSFd fd, u32* length, u32* pos) { static ISFSError nandGetFileStatus(IOSFd fd, u32* length, u32* pos) {
ISFSFileStats fstat ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) ISFSFileStats fstat;
ISFSError result = ISFS_GetFileStats(fd, &fstat); ISFSError result = ISFS_GetFileStats(fd, &fstat);
if (result == ISFS_ERROR_OK) { if (result == ISFS_ERROR_OK) {
if (length) { if (length) {
+1 -1
View File
@@ -8,7 +8,7 @@ void __OSRelaunchTitle(u32 resetCode) {
s32 rc = 0; s32 rc = 0;
u32 ticketCnt = 1; u32 ticketCnt = 1;
ESTicketView* tik = NULL; ESTicketView* tik = NULL;
ESTitleId titleId ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) ESTitleId titleId;
__OSPlayTimeType type = OSPLAYTIME_PERMANENT; __OSPlayTimeType type = OSPLAYTIME_PERMANENT;
u32 remain = 0; u32 remain = 0;
u8* bi2 = NULL; u8* bi2 = NULL;
+1 -1
View File
@@ -85,7 +85,7 @@ NWC24Err NWC24iSynchronizeRtcCounter(BOOL param_0) {
} }
NWC24Err NWC24SuspendScheduler(void) { NWC24Err NWC24SuspendScheduler(void) {
static u8 susResult[0x20] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u8 susResult[0x20];
NWC24Err rt = NWC24_OK; NWC24Err rt = NWC24_OK;
NWC24Err closeRt = NWC24_OK; NWC24Err closeRt = NWC24_OK;
IOSFd fd; IOSFd fd;
+1 -1
View File
@@ -2,7 +2,7 @@
#include <revolution/nand.h> #include <revolution/nand.h>
static BOOL PlayRecordGet = FALSE; static BOOL PlayRecordGet = FALSE;
static OSPlayRecord PlayRecord ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static OSPlayRecord PlayRecord;
static NANDFileInfo FileInfo; static NANDFileInfo FileInfo;
static NANDCommandBlock Block; static NANDCommandBlock Block;
static s32 PlayRecordState = 9; static s32 PlayRecordState = 9;
+6 -6
View File
@@ -7,7 +7,7 @@
#include "__os.h" #include "__os.h"
OSAlarm __OSExpireAlarm ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) OSAlarm __OSExpireAlarm;
OSTime __OSExpireTime; OSTime __OSExpireTime;
OSPlayTimeCallbackFunc __OSExpireCallback; OSPlayTimeCallbackFunc __OSExpireCallback;
BOOL __OSExpireSetExpiredFlag; BOOL __OSExpireSetExpiredFlag;
@@ -103,7 +103,7 @@ BOOL __OSWriteExpiredFlag(void) {
s32 rv = 0; s32 rv = 0;
NANDFileInfo nInfo; NANDFileInfo nInfo;
BOOL openNInfo = FALSE; BOOL openNInfo = FALSE;
u8 titleId[32] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 titleId[32];
rv = NANDPrivateCreate("/shared2/expired", 63, 0); rv = NANDPrivateCreate("/shared2/expired", 63, 0);
@@ -162,7 +162,7 @@ BOOL __OSWriteExpiredFlagIfSet(void) {
void* __OSPlayTimeRebootThread(void* args) { void* __OSPlayTimeRebootThread(void* args) {
BOOL enabled; BOOL enabled;
u32 frames, fadeShift = 1; u32 frames, fadeShift = 1;
__OSExpireAIFadeStruct aiFade ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) __OSExpireAIFadeStruct aiFade;
__OSExpireAIFade = &aiFade; __OSExpireAIFade = &aiFade;
memset(__OSExpireAIFade, 0, sizeof(__OSExpireAIFadeStruct)); memset(__OSExpireAIFade, 0, sizeof(__OSExpireAIFadeStruct));
@@ -227,9 +227,9 @@ out:
s32 __OSGetPlayTime(ESTicketView* ticket, __OSPlayTimeType* type, u32* playTime) { s32 __OSGetPlayTime(ESTicketView* ticket, __OSPlayTimeType* type, u32* playTime) {
s32 rv; s32 rv;
u32 i; u32 i;
ESLpEntry lpEntry[8] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) ESLpEntry lpEntry[8];
u32 numCc = 0, seenOther = 0; u32 numCc = 0, seenOther = 0;
ESTicketView ticketAligned ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) ESTicketView ticketAligned;
ASSERTLINE(601, ticket && type && playTime); ASSERTLINE(601, ticket && type && playTime);
@@ -288,7 +288,7 @@ out:
s32 __OSGetPlayTimeCurrent(__OSPlayTimeType* type, u32* playTime) { s32 __OSGetPlayTimeCurrent(__OSPlayTimeType* type, u32* playTime) {
s32 rv; s32 rv;
ESTicketView ticket ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) ESTicketView ticket;
ASSERTLINE(676, type && playTime); ASSERTLINE(676, type && playTime);
+1 -1
View File
@@ -3,7 +3,7 @@
#include "__os.h" #include "__os.h"
static SramControl Scb ATTRIBUTE_ALIGN(DOLPHIN_ALIGNMENT); ATTRIBUTE_ALIGN(DOLPHIN_ALIGNMENT) static SramControl Scb;
// prototypes // prototypes
static int GetRTC(u32* rtc); static int GetRTC(u32* rtc);
+1 -1
View File
@@ -2,7 +2,7 @@
#include <revolution/nand.h> #include <revolution/nand.h>
#include <cstring> #include <cstring>
static OSStateFlags StateFlags ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static OSStateFlags StateFlags;
static u32 CheckSum(OSStateFlags* flags) { static u32 CheckSum(OSStateFlags* flags) {
u32* ptr, i, sum; u32* ptr, i, sum;
+6 -6
View File
@@ -5,14 +5,14 @@
#include <revolution/private/iosrestypes.h> #include <revolution/private/iosrestypes.h>
static u32 StmImInBuf[8] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u32 StmImInBuf[8];
static u32 StmImOutBuf[8] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u32 StmImOutBuf[8];
static u32 StmVdInBuf[8] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u32 StmVdInBuf[8];
static u32 StmVdOutBuf[8] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u32 StmVdOutBuf[8];
static u32 StmEhInBuf[8] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u32 StmEhInBuf[8];
static u32 StmEhOutBuf[8] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u32 StmEhOutBuf[8];
static OSResetCallback ResetCallback; static OSResetCallback ResetCallback;
static OSPowerCallback PowerCallback; static OSPowerCallback PowerCallback;
+1 -1
View File
@@ -873,4 +873,4 @@ void* OSGetThreadSpecific(s32 index) {
#include "global.h" #include "global.h"
extern u8 Debug_BBA_804516D0; extern u8 Debug_BBA_804516D0;
u8 Debug_BBA_804516D0 ATTRIBUTE_ALIGN(8); ATTRIBUTE_ALIGN(8) u8 Debug_BBA_804516D0;
+2 -2
View File
@@ -75,8 +75,8 @@ static const char ConfDirName[] = "/shared2/sys";
static const char ConfFileName[] = "/shared2/sys/SYSCONF"; static const char ConfFileName[] = "/shared2/sys/SYSCONF";
static const char ProductInfoFileName[] = "/title/00000001/00000002/data/setting.txt"; static const char ProductInfoFileName[] = "/title/00000001/00000002/data/setting.txt";
static u8 ConfBuf[0x4000] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u8 ConfBuf[0x4000];
static u8 ConfBufForFlush[0x4000] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) static u8 ConfBufForFlush[0x4000];
static u8 Initialized; static u8 Initialized;
static u8 DirtyFlag; static u8 DirtyFlag;
+1 -1
View File
@@ -262,7 +262,7 @@ void WPADiManageHandler(OSAlarm*, OSContext*) {
BTA_HhGetAclQueueInfo(); BTA_HhGetAclQueueInfo();
} }
u8 __WPADiManageHandlerStack[4096] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 __WPADiManageHandlerStack[4096];
void WPADiManageHandler0(OSAlarm* alarm, OSContext* context) { void WPADiManageHandler0(OSAlarm* alarm, OSContext* context) {
OSSwitchFiberEx((u32)alarm, (u32)context, 0, 0, (u32)WPADiManageHandler, (u32)(__WPADiManageHandlerStack + sizeof(__WPADiManageHandlerStack))); OSSwitchFiberEx((u32)alarm, (u32)context, 0, 0, (u32)WPADiManageHandler, (u32)(__WPADiManageHandlerStack + sizeof(__WPADiManageHandlerStack)));
+1 -1
View File
@@ -41,7 +41,7 @@ WUDControlBlock _wcb;
WUDDevInfo _work; WUDDevInfo _work;
static WUDDiscResp _discResp; static WUDDiscResp _discResp;
SCBtDeviceInfoArray _scArray; SCBtDeviceInfoArray _scArray;
u8 __WUDHandlerStack[0x1000] ATTRIBUTE_ALIGN(32); ATTRIBUTE_ALIGN(32) u8 __WUDHandlerStack[0x1000];
extern u8 _scFlush; extern u8 _scFlush;
+34
View File
@@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.25)
project(basic_cosmetics_mod CXX)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(DUSK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../.." CACHE PATH "Path to dusk source root")
option(DUSK_MOD_USE_FULL_TREE "Use full build instead of the minimal mod SDK" OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if (DUSK_MOD_USE_FULL_TREE)
add_subdirectory("${DUSK_DIR}" dusk EXCLUDE_FROM_ALL)
else ()
add_subdirectory("${DUSK_DIR}/sdk" dusk-sdk EXCLUDE_FROM_ALL)
endif ()
endif ()
include(FetchContent)
message(STATUS "basic_cosmetics_mod: Fetching xxhash")
FetchContent_Declare(
xxhash
GIT_REPOSITORY https://github.com/Cyan4973/xxHash.git
GIT_TAG v0.8.3
)
FetchContent_MakeAvailable(xxhash)
set(COSMETIC_SOURCES src/color_utils.cpp src/midna_hair_color.cpp src/texture_utils.cpp src/hooks.cpp)
add_mod(basic_cosmetics_mod
FEATURES game fmt
SOURCES src/mod.cpp ${COSMETIC_SOURCES}
MOD_JSON mod.json
RES_DIR res
)
target_link_libraries(basic_cosmetics_mod PRIVATE xxHash::xxhash)
+7
View File
@@ -0,0 +1,7 @@
{
"id": "dev.twilitrealm.basic_cosmetics",
"name": "Basic Cosmetics",
"version": "1.0.0",
"author": "Twilit Realm",
"description": "Change Basic Cosmetic Colors"
}
@@ -0,0 +1,94 @@
#include "color_utils.hpp"
uint8_t desaturate_rgb_565(uint16_t rgb565Val)
{
const uint32_t r = (rgb565Val & 0xf800) >> 11;
const uint32_t g = (rgb565Val & 0x7e0) >> 5;
const uint32_t b = rgb565Val & 0x1f;
// Here we are doing a quicker (0.22 * r + 0.72 * g + 0.06 * b) which
// uses multiplies and shifts rather than division.
const uint32_t combined = 30480413 * r + 49085341 * g + 8312839 * b;
uint8_t shifted = (combined >> 24) & 0xff;
// Check if should round up shifted value.
if (shifted < 0xff && combined & 0x00800000)
{
shifted += 1;
}
return shifted;
}
uint16_t blend_overlay_rgb_565(uint8_t grayVal, GXColor color)
{
uint32_t rTimes255, gTimes255, bTimes255;
if (grayVal <= 0x7f)
{
const uint32_t grayTimesTwo = 2 * grayVal;
rTimes255 = grayTimesTwo * color.r;
gTimes255 = grayTimesTwo * color.g;
bTimes255 = grayTimesTwo * color.b;
}
else
{
const uint32_t multiplier = 2 * (255 - grayVal);
rTimes255 = 255 * 255 - multiplier * (255 - color.r);
gTimes255 = 255 * 255 - multiplier * (255 - color.g);
bTimes255 = 255 * 255 - multiplier * (255 - color.b);
}
// Divide each by 255
const uint32_t r = (rTimes255 + 1 + (rTimes255 >> 8)) >> 8;
const uint32_t g = (gTimes255 + 1 + (gTimes255 >> 8)) >> 8;
const uint32_t b = (bTimes255 + 1 + (bTimes255 >> 8)) >> 8;
return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
}
// Helper function to perform overlay blending on a single 8-bit color channel
uint8_t blend_overlay_channel(uint8_t base, uint8_t blend)
{
if (base < 128) {
return static_cast<uint8_t>((2 * base * blend) / 255);
}
return static_cast<uint8_t>(255 - (2 * (255 - base) * (255 - blend)) / 255);
}
bool is_valid_hex_color_str(std::string_view hexStr) {
return hexStr.find_first_not_of("0123456789ABCDEFabcdef") == std::string_view::npos && hexStr.length() == 6;
}
GXColor hex_color_str_to_gx_color(const std::string& hexColorStr) {
u8 r = std::stoi(hexColorStr.substr(0, 2), nullptr, 16);
u8 g = std::stoi(hexColorStr.substr(2, 2), nullptr, 16);
u8 b = std::stoi(hexColorStr.substr(4, 2), nullptr, 16);
return GXColor{r, g, b};
}
static f32 rainbowPhaseAngle = 0.f;
GXColor get_rainbow_rgb(f32 amplitude) {
f32 phase_rad = rainbowPhaseAngle * M_PI / 180.0f;
u8 r_val = (u8)(amplitude * (sinf(phase_rad) + 1.0f) + 0.5f);
u8 g_val = (u8)(amplitude * (sinf(phase_rad + 2.0f * M_PI / 3.0f) + 1.0f) + 0.5f);
u8 b_val = (u8)(amplitude * (sinf(phase_rad + 4.0f * M_PI / 3.0f) + 1.0f));
GXColor rgbColor;
rgbColor.r = r_val;
rgbColor.g = g_val;
rgbColor.b = b_val;
rgbColor.a = 0xff;
return rgbColor;
}
void update_rainbow_rgb(f32 increment) {
rainbowPhaseAngle += increment;
if (rainbowPhaseAngle >= 360.0f) {
rainbowPhaseAngle -= 360.0f;
}
}
@@ -0,0 +1,30 @@
#pragma once
/**
* File originally copied from console TPR with permission from isaac
* https://github.com/zsrtp/libtp_rel/blob/master/include/util/color_utils.h
*/
#include <gx.h>
#include <cstdint>
#include <string>
// Desaturates an RGB565 color to a u8 gray value (0xFF being white and 0x00
// being black).
uint8_t desaturate_rgb_565(uint16_t rgb565Val);
// Performs an "Overlay" blend of a u8 gray value and a pointer to a u8
// array of {r,g,b}. Returns the result as an RGB565.
uint16_t blend_overlay_rgb_565(uint8_t grayVal, GXColor color);
// Perform overlay blending on a single 8-bit color channel
uint8_t blend_overlay_channel(uint8_t base, uint8_t blend);
bool is_valid_hex_color_str(std::string_view hexStr);
GXColor hex_color_str_to_gx_color(const std::string& hexColorStr);
GXColor get_rainbow_rgb(f32 amplitude);
void update_rainbow_rgb(f32 increment);
+686
View File
@@ -0,0 +1,686 @@
#include "hooks.hpp"
#include "mod.hpp"
#include "color_utils.hpp"
#include "midna_hair_color.hpp"
#include "types.h"
#include "mods/svc/hook.hpp"
#include "mods/svc/log.hpp"
#include "d/actor/d_a_alink.h"
#include "d/actor/d_a_midna.h"
#include "d/d_a_item_static.h"
#include "d/d_bright_check.h"
#include "d/d_file_sel_info.h"
#include "d/d_file_select.h"
#include "d/d_kankyo.h"
#include "d/d_kantera_icon_meter.h"
#include "d/d_menu_collect.h"
#include "d/d_menu_fishing.h"
#include "d/d_menu_fmap2D.h"
#include "d/d_menu_insect.h"
#include "d/d_menu_letter.h"
#include "d/d_menu_option.h"
#include "d/d_menu_ring.h"
#include "d/d_menu_save.h"
#include "d/d_menu_skill.h"
#include "d/d_meter_button.h"
#include "d/d_meter_hakusha.h"
#include "d/d_meter2.h"
#include "d/d_meter2_draw.h"
#include "d/d_meter2_info.h"
#include "d/d_msg_object.h"
#include "d/d_msg_out_font.h"
#include "d/d_msg_scrn_base.h"
#include "d/d_pane_class.h"
#include "SSystem/SComponent/c_phase.h"
// Lantern ambience color
DEFINE_HOOK(&dKy_WolfEyeLight_set, WolfEyeLightSet);
void wolf_eye_light_set_post(ModContext*, void*, void*, void*) {
auto maybeLanternColor = get_config_var_color(get_cvars().lanternGlowColor, true);
if (maybeLanternColor.has_value()) {
auto lanternColor = maybeLanternColor.value();
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
kankyo->field_0x0c18[0].mColor.r = lanternColor.r;
kankyo->field_0x0c18[0].mColor.g = lanternColor.g;
kankyo->field_0x0c18[0].mColor.b = lanternColor.b;
}
}
// Lantern Sphere color
DEFINE_HOOK(&daAlink_c::preKandelaarDraw, PreKandelaarDraw);
void pre_kandelaar_draw_post(ModContext*, void*, void*, void*) {
auto maybeLanternColor = get_config_var_color(get_cvars().lanternGlowColor, true);
if (maybeLanternColor.has_value()) {
auto lanternColor = maybeLanternColor.value();
J3DMaterial* mat_p = daAlink_getAlinkActorClass()->mpKanteraGlowModel->getModelData()->getMaterialNodePointer(0);
J3DGXColorS10 color;
color.r = lanternColor.r;
color.g = lanternColor.g;
color.b = lanternColor.b;
color.a = 255;
mat_p->setTevColor(1, &color);
color.r = lanternColor.r;
color.g = lanternColor.g;
color.b = lanternColor.b;
mat_p->setTevColor(2, &color);
}
}
// Main Lantern Meter Color
DEFINE_HOOK(&CPaneMgr::setBlackWhite, CPaneMgrSetBlackWhite);
HookAction cpane_mgr_set_black_white_pre(ModContext*, void* args, void*, void*) {
// Check for magic meter
auto pane = mods::arg<CPaneMgr*>(args, 0);
if (dMeter2Info_getMeterClass() == NULL || pane != dMeter2Info_getMeterClass()->getMeterDrawPtr()->mpMagicMeter) {
return HOOK_CONTINUE;
}
// If magic meter, check to see we're setting lantern colors
auto& black = mods::arg_ref<JUtility::TColor>(args, 1);
auto& white = mods::arg_ref<JUtility::TColor>(args, 2);
if (black != JUtility::TColor(255, 255, 140, 255) &&
white != JUtility::TColor(230, 170, 0, 255)) {
return HOOK_CONTINUE;
}
auto maybeLanternColor = get_config_var_color(get_cvars().lanternGlowColor, true);
if (maybeLanternColor.has_value()) {
auto lanternColor = maybeLanternColor.value();
black = JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255);
white = JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255);
}
return HOOK_CONTINUE;
}
// Lantern Icon Meter Color
DEFINE_HOOK(&dKantera_icon_c::setNowGauge, KanteraIconSetNowGauge);
void kantera_icon_set_now_gauge_post(ModContext*, void* args, void*, void*) {
auto maybeLanternColor = get_config_var_color(get_cvars().lanternGlowColor, true);
if (maybeLanternColor.has_value()) {
auto lanternColor = maybeLanternColor.value();
auto kanteraIcon = mods::arg<dKantera_icon_c*>(args, 0);
kanteraIcon->mpGauge->setBlackWhite(
JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255),
JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255));
}
}
// Light Sword Effect Color
DEFINE_HOOK(&daAlink_c::setLightningSwordEffect, SetLightningSwordEffect);
void set_lightning_sword_effect_post(ModContext*, void* args, void*, void*) {
auto maybeGlowColor = get_config_var_color(get_cvars().lightSwordGlowColor, true);
if (maybeGlowColor.has_value()) {
auto glowColor = maybeGlowColor.value();
auto link = mods::arg<daAlink_c*>(args, 0);
// Check copied from inside the hooked function
if (link->mEquipItem == 0x103 && link->checkNoResetFlg3(daPy_py_c::FLG3_UNK_100000)) {
for (size_t i = 0; i < 3; i++) {
auto emitter = dComIfGp_particle_getEmitter(link->field_0x327c[i]);
if (emitter != NULL) {
emitter->setGlobalEnvColor(glowColor.r, glowColor.g, glowColor.b);
emitter->setGlobalPrmColor(glowColor.r, glowColor.g, glowColor.b);
}
}
}
}
}
void recolor_ui_button(ConfigVarHandle option, u64 tag, J2DScreen* screen) {
auto buttonColorStr = get_str_option(option, "");
if (is_valid_hex_color_str(buttonColorStr)) {
auto color = hex_color_str_to_gx_color(buttonColorStr);
auto element = static_cast<J2DPicture*>(screen->search(tag));
if (element != nullptr) {
element->setBlackWhite(JUtility::TColor(0, 0, 0, 0),
JUtility::TColor(color.r, color.g, color.b, 0xFF));
}
}
}
// Main gameplay UI. Top left hearts and top right buttons
DEFINE_HOOK(&dMeter2Draw_c::init, dMeter2Init);
void d_meter_2_init_post(ModContext*, void* args, void*, void*) {
auto dMeter2Draw = mods::arg<dMeter2Draw_c*>(args, 0);
auto screen = dMeter2Draw->getMainScreenPtr();
// Heart tags on main UI
static constexpr std::array kHeartTags = {
MULTI_CHAR('hear_00'), MULTI_CHAR('hear_01'), MULTI_CHAR('hear_02'), MULTI_CHAR('hear_03'), MULTI_CHAR('hear_04'), MULTI_CHAR('hear_05'), MULTI_CHAR('hear_06'),
MULTI_CHAR('hear_07'), MULTI_CHAR('hear_08'), MULTI_CHAR('hear_09'), MULTI_CHAR('hear_10'), MULTI_CHAR('hear_11'), MULTI_CHAR('hear_12'), MULTI_CHAR('hear_13'),
MULTI_CHAR('hear_14'), MULTI_CHAR('hear_15'), MULTI_CHAR('hear_16'), MULTI_CHAR('hear_17'), MULTI_CHAR('hear_18'), MULTI_CHAR('hear_19'), MULTI_CHAR('bigh_00'),
MULTI_CHAR('bigh_01'), MULTI_CHAR('bigh_02'), MULTI_CHAR('bigh_03')
};
auto maybeHeartColor = get_config_var_color(get_cvars().heartColor);
if (maybeHeartColor.has_value()) {
auto heartColor = maybeHeartColor.value();
for (auto tag : kHeartTags) {
auto element = static_cast<J2DPicture*>(screen->search(tag));
if (element != nullptr) {
element->setBlackWhite(heartColor, JUtility::TColor(200, 200, 200, 255));
}
}
}
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
recolor_ui_button(get_cvars().xButtonColor, MULTI_CHAR('x_btn'), screen);
recolor_ui_button(get_cvars().yButtonColor, MULTI_CHAR('y_btn'), screen);
recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('zbtn'), screen);
}
// Hearts on the file select screen
DEFINE_HOOK(&dFile_info_c::setHeartCnt, FileInfoSetHeartCount);
void file_info_set_heart_count_post(ModContext*, void* args, void*, void*) {
auto fileInfo = mods::arg<dFile_info_c*>(args, 0);
// Heart tags on file select
static constexpr std::array kFileSelectHeartTags {
MULTI_CHAR('hear_20'), MULTI_CHAR('hear_21'), MULTI_CHAR('hear_22'), MULTI_CHAR('hear_23'), MULTI_CHAR('hear_24'), MULTI_CHAR('hear_25'), MULTI_CHAR('hear_26'),
MULTI_CHAR('hear_27'), MULTI_CHAR('hear_28'), MULTI_CHAR('hear_29'), MULTI_CHAR('hear_30'), MULTI_CHAR('hear_31'), MULTI_CHAR('hear_32'), MULTI_CHAR('hear_33'),
MULTI_CHAR('hear_34'), MULTI_CHAR('hear_35'), MULTI_CHAR('hear_36'), MULTI_CHAR('hear_37'), MULTI_CHAR('hear_38'), MULTI_CHAR('hear_39'),
};
auto maybeHeartColor = get_config_var_color(get_cvars().heartColor);
if (maybeHeartColor.has_value()) {
auto heartColor = maybeHeartColor.value();
for (auto tag : kFileSelectHeartTags) {
auto element = static_cast<J2DPicture*>(fileInfo->mFileInfo.Scr->search(tag));
if (element != nullptr) {
element->setBlackWhite(heartColor, JUtility::TColor(200, 200, 200, 255));
}
}
}
}
// Buttons that appear contextually at the bottom of the screen during gameplay
// (Are X, Y ever used there?)
DEFINE_HOOK(&dMeterButton_c::screenInitButton, ScreenInitButton);
void screen_init_button_post(ModContext*, void* args, void*, void*) {
auto meterButton = mods::arg<dMeterButton_c*>(args, 0);
auto screen = meterButton->mpButtonScreen;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), screen);
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
recolor_ui_button(get_cvars().xButtonColor, MULTI_CHAR('x_btn'), screen);
recolor_ui_button(get_cvars().yButtonColor, MULTI_CHAR('y_btn'), screen);
recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('zbtn'), screen);
}
// A and B buttons when saving a file
DEFINE_HOOK(&dMenu_save_c::screenSet, MenuSaveScreenSet);
void menu_save_screen_set_post(ModContext*, void* args, void*, void*) {
auto menuSave = mods::arg<dMenu_save_c*>(args, 0);
auto screen = menuSave->mSaveSel.Scr;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('wabtn'), screen);
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('wbbtn'), screen);
}
// A and B buttons when selecting a file
DEFINE_HOOK(&dFile_select_c::screenSet, FileSelectScreenSet);
void file_select_screen_set_post(ModContext*, void* args, void*, void*) {
auto fileSelect = mods::arg<dFile_select_c*>(args, 0);
auto screen = fileSelect->fileSel.Scr;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('wabtn'), screen);
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('wbbtn'), screen);
}
// A button on brightness check screen
DEFINE_HOOK(&dBrightCheck_c::screenSet, BrightCheckScreenSet);
void bright_check_screen_set_post(ModContext*, void* args, void*, void*) {
auto brightCheck = mods::arg<dBrightCheck_c*>(args, 0);
auto screen = brightCheck->mBrightCheck.Scr;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), screen);
}
// X and Y buttons on the item wheel screen
DEFINE_HOOK(&dMenu_Ring_c::_create, MenuRingCreate);
void menu_ring_create_post(ModContext*, void* args, void*, void*) {
auto menuRing = mods::arg<dMenu_Ring_c*>(args, 0);
auto screen = menuRing->mpScreen;
recolor_ui_button(get_cvars().xButtonColor, MULTI_CHAR('xbtn'), screen);
recolor_ui_button(get_cvars().yButtonColor, MULTI_CHAR('ybtn'), screen);
}
// A and B buttons on the main pause screen
DEFINE_HOOK(&dMenu_Collect2D_c::_create, MenuCollect2DCreate);
void menu_collect_2D_create_post(ModContext*, void* args, void*, void*) {
auto menuCollect2D = mods::arg<dMenu_Collect2D_c*>(args, 0);
auto screen = menuCollect2D->mpScreenIcon;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
}
// A and B buttons on the fishing journal screen
DEFINE_HOOK(&dMenu_Fishing_c::screenSetDoIcon, MenuFishingScreenSetDoIcon);
void menu_fishing_screen_set_do_icon_post(ModContext*, void* args, void*, void*) {
auto menuFishing = mods::arg<dMenu_Fishing_c*>(args, 0);
auto screen = menuFishing->mpIconScreen;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
}
// A and B buttons on the insect collection screen
DEFINE_HOOK(&dMenu_Insect_c::screenSetDoIcon, MenuInsectScreenSetDoIcon);
void menu_insect_screen_set_do_icon_post(ModContext*, void* args, void*, void*) {
auto menuInsect = mods::arg<dMenu_Insect_c*>(args, 0);
auto screen = menuInsect->mpIconScreen;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
}
// A and B buttons on the letters screen
DEFINE_HOOK(&dMenu_Letter_c::screenSetDoIcon, MenuLetterScreenSetDoIcon);
void menu_letter_screen_set_do_icon_post(ModContext*, void* args, void*, void*) {
auto menuLetter = mods::arg<dMenu_Letter_c*>(args, 0);
auto screen = menuLetter->mpIconScreen;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
}
// A, B, and Z buttons on option screen
DEFINE_HOOK(&dMenu_Option_c::_create, MenuOptionCreate);
void menu_option_create_post(ModContext*, void* args, void*, void*) {
auto menuOption = mods::arg<dMenu_Option_c*>(args, 0);
auto screen = menuOption->mpScreenIcon;
auto backScreen = menuOption->mpBackScreen;
auto tvScreen = menuOption->mpTVScreen;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('g_zbtn'), backScreen);
// A Button on option's brightness check screen
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), tvScreen);
}
// A and B buttons on the hidden skills screen
DEFINE_HOOK(&dMenu_Skill_c::screenSetDoIcon, MenuSkillScreenSetDoIcon);
void menu_skill_screen_set_do_icon_post(ModContext*, void* args, void*, void*) {
auto menuSkill = mods::arg<dMenu_Skill_c*>(args, 0);
auto screen = menuSkill->mpIconScreen;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
}
// A, B, and Z buttons on the map screen
DEFINE_HOOK(&dMenu_Fmap_c::_create, MenuFMapCreate);
void menu_fmap_create_post(ModContext*, void* args, void*, void*) {
auto menuFMap = mods::arg<dMenu_Fmap_c*>(args, 0);
auto screen = menuFMap->mpDraw2DTop->mpTitleScreen;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn1'), screen);
recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('zbtn'), screen);
}
// A button on the howling screen
DEFINE_HOOK(&dMsgObject_c::talkStartInit, MsgObjectTalkStartInit);
void msg_object_talk_start_init_post(ModContext*, void* args, void*, void*) {
auto msgObject = mods::arg<dMsgObject_c*>(args, 0);
// If textbox kind is howling
if (msgObject->mFukiKind == 17) {
auto screen = msgObject->mpScrnDraw->mpScreen;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('abtn'), screen);
}
}
// A button when on Epona
DEFINE_HOOK(&dMeterHakusha_c::_create, MeterHakushaCreate);
void meter_hakusha_create_post(ModContext*, void* args, void*, void*) {
auto meterHakusha = mods::arg<dMeterHakusha_c*>(args, 0);
auto screen = meterHakusha->mpButtonScreen;
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), screen);
}
// A, B, X, and Y button icons in text
DEFINE_HOOK(&COutFont_c::createPane, OutFontCreatePane);
void out_font_create_pane_post(ModContext*, void* args, void*, void*) {
auto outFont = mods::arg<COutFont_c*>(args, 0);
auto paneArr = outFont->mpPane;
auto maybeAButtonColor = get_config_var_color(get_cvars().aButtonColor);
if (maybeAButtonColor.has_value()) {
auto aButtonColor = maybeAButtonColor.value();
paneArr[0]->setBlackWhite(
JUtility::TColor(255, 255, 255, 0),
JUtility::TColor(aButtonColor.r,aButtonColor.g,aButtonColor.b, 255));
}
auto maybeBButtonColor = get_config_var_color(get_cvars().bButtonColor);
if (maybeBButtonColor.has_value()) {
auto bButtonColor = maybeBButtonColor.value();
paneArr[1]->setBlackWhite(
JUtility::TColor(255, 255, 255, 0),
JUtility::TColor(bButtonColor.r,bButtonColor.g,bButtonColor.b, 255));
}
// Condition copied from hooked function
auto xyBlack = JUtility::TColor(255, 255, 255, 0);
if (outFont->field_0x242 == 1) {
xyBlack = JUtility::TColor(0, 0, 0, 0);
}
auto maybeXButtonColor = get_config_var_color(get_cvars().xButtonColor);
if (maybeXButtonColor.has_value()) {
auto xButtonColor = maybeXButtonColor.value();
paneArr[5]->setBlackWhite(xyBlack, JUtility::TColor(xButtonColor.r,xButtonColor.g,xButtonColor.b, 255));
}
auto maybeYButtonColor = get_config_var_color(get_cvars().yButtonColor);
if (maybeYButtonColor.has_value()) {
auto yButtonColor = maybeYButtonColor.value();
paneArr[6]->setBlackWhite(xyBlack, JUtility::TColor(yButtonColor.r,yButtonColor.g,yButtonColor.b, 255));
}
}
// Heart icon in text
DEFINE_HOOK(&COutFontSet_c::drawFont, OutFontSetDrawFont);
void out_font_set_draw_font_post(ModContext*, void* args, void*, void*) {
auto outFontSet = mods::arg<COutFontSet_c*>(args, 0);
auto maybeHeartColor = get_config_var_color(get_cvars().heartColor);
if (maybeHeartColor.has_value()) {
auto heartColor = maybeHeartColor.value();
u32 heartColor_u32 = heartColor.r << 24 | heartColor.g << 16 | heartColor.b << 8 | 0xFF;
if (outFontSet->getType() == 0x1B) { // Heart icon type
outFontSet->mColor = heartColor_u32;
}
}
}
// Heart Drop/Piece of Heart/Heart Container model color
DEFINE_HOOK(&daItemBase_c::CreateItemHeap, ItemBaseCreateItemHeap);
void item_base_create_item_heap_post(ModContext*, void* args, void*, void*) {
auto itemBase = mods::arg<daItemBase_c*>(args, 0);
if (itemBase == NULL) {
return;
}
auto itemNo = itemBase->m_itemNo;
if (itemNo == dItemNo_HEART_e || itemNo == dItemNo_UTAWA_HEART_e || itemNo == dItemNo_KAKERA_HEART_e) {
auto maybeHeartColor = get_config_var_color(get_cvars().heartColor);
if (maybeHeartColor.has_value()) {
auto heartColor = maybeHeartColor.value();
auto heartColorS10 = GXColorS10(heartColor.r, heartColor.g, heartColor.b, heartColor.a);
// Edit inner heart material color for Piece of Heart / Heart Container
if (itemNo == dItemNo_UTAWA_HEART_e || itemNo == dItemNo_KAKERA_HEART_e) {
*itemBase->mpModel->getModelData()->getMaterialNodePointer(3)->getTevKColor(1) = heartColor;
*itemBase->mpModel->getModelData()->getMaterialNodePointer(3)->getTevColor(1) = heartColorS10;
}
const u8 heartColorRGB[3] = {heartColor.r,heartColor.g,heartColor.b};
u8** cRegTable = reinterpret_cast<u8**>(&itemBase->mpBrkAnm->getBrkAnm()->mAnmCRegDataR);
u8** kRegTable = reinterpret_cast<u8**>(&itemBase->mpBrkAnm->getBrkAnm()->mAnmKRegDataR);
for (int i = 0; i < 3; i++) {
u8* cReg = cRegTable[i];
u8* kReg = kRegTable[i];
auto curColor = heartColorRGB[i];
// Set heart drop inner heart color
cReg[0x3] = curColor;
cReg[0xB] = curColor;
// Set heart drop outer heart color
kReg[0x3] = curColor;
kReg[0xB] = curColor;
if (itemNo == dItemNo_KAKERA_HEART_e) {
cReg[0x13] = curColor;
cReg[0x1B] = curColor;
kReg[0x13] = curColor;
kReg[0x1B] = curColor;
}
if (itemNo == dItemNo_UTAWA_HEART_e) {
cReg[0x13] = curColor;
kReg[0x13] = curColor;
kReg[0x1B] = curColor;
kReg[0x23] = curColor;
kReg[0x2B] = curColor;
}
}
}
}
}
// Midna Hair Color
DEFINE_HOOK(&daMidna_c::create, MidnaCreate);
void midna_create_post(ModContext*, void* args, void* retval, void*) {
auto step = reinterpret_cast<int*>(retval);
// Don't set colors if midna isn't done loading
if (*step != cPhs_COMPLEATE_e) {
return;
}
auto midna = mods::arg<daMidna_c*>(args, 0);
midna->field_0x6e0 = *get_midna_hair_normalColor();
if (dKy_darkworld_check()) {
midna->field_0x6e8 = *get_midna_hair_normalKColor();
midna->field_0x6ec = *get_midna_hair_normalKColor2();
} else {
midna->field_0x6e8 = *get_midna_hair_lNormalKColor();
midna->field_0x6ec = *get_midna_hair_lNormalKColor2();
}
}
// Override Midna Hair Color Part 2
DEFINE_HOOK(&daMidna_c::setBodyPartMatrix, MidnaSetBodyPartMatrix);
static GXColorS10 midnaField0x6e0{};
static GXColor midnaField0x6e8{};
static GXColor midnaField0x6ec{};
// Copy the original values before setBodyPartMatrix runs
HookAction midna_set_body_part_matrix_pre(ModContext*, void* args, void* retval, void* userdata) {
auto midna = mods::arg<daMidna_c*>(args, 0);
midnaField0x6e0 = midna->field_0x6e0;
midnaField0x6e8 = midna->field_0x6e8;
midnaField0x6ec = midna->field_0x6ec;
return HOOK_CONTINUE;
}
void midna_set_body_part_matrix_post(ModContext*, void* args, void* retval, void* userdata) {
auto midna = mods::arg<daMidna_c*>(args, 0);
if (midna->mpHairhandBmd != NULL) {
// Restore the original values from before setBodyPartMatrix ran (this undoes the chase)
midna->field_0x6e0 = midnaField0x6e0;
midna->field_0x6e8 = midnaField0x6e8;
midna->field_0x6ec = midnaField0x6ec;
// Statement copied from inside function to determine colors
bool bigColors = midna->checkStateFlg0(daMidna_c::FLG0_UNK_10000000) ||
midna->mBckHeap[2].getIdx() == daMidna_c::m_anmDataTable[daMidna_c::ANM_HAIR].mResID ||
midna->mBckHeap[2].getIdx() == daMidna_c::m_anmDataTable[daMidna_c::ANM_S_TAKES].mResID ||
midna->mBckHeap[2].getIdx() == daMidna_c::m_anmDataTable[daMidna_c::ANM_S_WAITS].mResID ||
midna->mBckHeap[2].getIdx() == daMidna_c::m_anmDataTable[daMidna_c::ANM_S_PACKAWAY].mResID ||
midna->mBckHeap[2].getIdx() == daMidna_c::m_anmDataTable[daMidna_c::ANM_GRABST].mResID ||
midna->checkEndResetStateFlg0(daMidna_c::ERFLG0_UNK_40) ||
dComIfGp_checkPlayerStatus1(0, 0x800000);
GXColorS10 color{};
GXColor kcolor1{};
GXColor kcolor2{};
// Set our own colors
if (bigColors) {
kcolor1 = *get_midna_hair_bigKColor();
if (dKy_darkworld_check()) {
color = *get_midna_hair_bigColor();
kcolor2 = *get_midna_hair_normalKColor2();
} else {
color = *get_midna_hair_lBigColor();
kcolor2 = *get_midna_hair_lBigKColor2();
}
} else {
color = *get_midna_hair_normalColor();
if (dKy_darkworld_check()) {
kcolor1 = *get_midna_hair_normalKColor();
kcolor2 = *get_midna_hair_normalKColor2();
} else {
kcolor1 = *get_midna_hair_lNormalKColor();
kcolor2 = *get_midna_hair_lNormalKColor2();
}
}
// Reapply the chase that happens in the function
cLib_chaseS(&midna->field_0x6e0.r, color.r, 10);
cLib_chaseS(&midna->field_0x6e0.g, color.g, 10);
cLib_chaseS(&midna->field_0x6e0.b, color.b, 10);
cLib_chaseUC(&midna->field_0x6e8.r, kcolor1.r, 10);
cLib_chaseUC(&midna->field_0x6e8.g, kcolor1.g, 10);
cLib_chaseUC(&midna->field_0x6e8.b, kcolor1.b, 10);
cLib_chaseUC(&midna->field_0x6ec.r, kcolor2.r, 10);
cLib_chaseUC(&midna->field_0x6ec.g, kcolor2.g, 10);
cLib_chaseUC(&midna->field_0x6ec.b, kcolor2.b, 10);
}
}
// Midna Charge Ring Color
DEFINE_HOOK(&daAlink_c::setWolfLockDomeModel, SetWolfLockDomeModel);
void wolf_lock_dome_model_post(ModContext*, void*, void*, void*) {
auto domeRingColorStr = get_str_option(get_cvars().midnaChargeRingColor, "");
if (is_valid_hex_color_str(domeRingColorStr)) {
auto domeRingColor = hex_color_str_to_gx_color(domeRingColorStr);
const u8 domeWave1RGBA[3] = {domeRingColor.r, domeRingColor.g, domeRingColor.b};
const u8 domeWave2RGBA[3] = {domeRingColor.r, domeRingColor.g, domeRingColor.b};
u8** chromaRegisterTable = reinterpret_cast<u8**>(&daAlink_getAlinkActorClass()->field_0x0724->mAnmCRegDataR);
for (int i = 0; i < 3; i++)
{
u8* currentTable = chromaRegisterTable[i];
const u8 currentWave1Color = domeWave1RGBA[i];
const u8 currentWave2Color = domeWave2RGBA[i];
const u8 currentBaseColor = (currentWave1Color + currentWave2Color) / 2;
currentTable[0x3] = currentBaseColor; // Set Alpha for the ring base
currentTable[0x13] = currentWave1Color; // Set Alpha for ring wave 1
currentTable[0x23] = currentWave2Color; // Set Alpha for ring wave 2
currentTable[0xB] = currentBaseColor; // Set Alpha for darkworld ring base
currentTable[0x1B] = currentWave1Color; // Set Alpha for darkworld ring wave 1
currentTable[0x2B] = currentWave2Color; // Set Alpha for darkworld ring wave 2
}
}
}
#define ADD_POST_HOOK(defined_hook, function, original) \
result = mods::hook::add_post<defined_hook>(function); \
if (result != MOD_OK) { \
mods::log::debug("failed to add post hook to" #original ", Result {}", static_cast<int>(result)); \
return result; \
}
#define ADD_PRE_HOOK(defined_hook, function, original) \
result = mods::hook::add_pre<defined_hook>(function); \
if (result != MOD_OK) { \
mods::log::debug("failed to add pre hook to" #original ", Result {}", static_cast<int>(result)); \
return result; \
}
ModResult add_all_hooks() {
ModResult result{};
// Hooks for lantern glow
ADD_POST_HOOK(WolfEyeLightSet, wolf_eye_light_set_post, dKy_WolfEyeLight_set)
ADD_POST_HOOK(PreKandelaarDraw, pre_kandelaar_draw_post, daAlink_c::preKandelaarDraw)
// Hooks for lantern meter color
ADD_PRE_HOOK(CPaneMgrSetBlackWhite, cpane_mgr_set_black_white_pre, CPaneMgr::setBlackWhite)
ADD_POST_HOOK(KanteraIconSetNowGauge, kantera_icon_set_now_gauge_post, dKantera_icon_c::setNowGauge)
// Hook for midna charge ring
ADD_POST_HOOK(SetWolfLockDomeModel, wolf_lock_dome_model_post, daAlink_c::setWolfLockDomeModel)
// Hook for light sword glow
ADD_POST_HOOK(SetLightningSwordEffect, set_lightning_sword_effect_post, daAlink_c::setLightningSwordEffect)
// Hooks for Midna Hair Color
ADD_POST_HOOK(MidnaCreate, midna_create_post, daMidna_c::create)
ADD_PRE_HOOK(MidnaSetBodyPartMatrix, midna_set_body_part_matrix_pre, daMidna_c::setBodyPartMatrix)
ADD_POST_HOOK(MidnaSetBodyPartMatrix, midna_set_body_part_matrix_post, daMidna_c::setBodyPartMatrix)
// Hooks for UI colors
ADD_POST_HOOK(dMeter2Init, d_meter_2_init_post, dMeter2Draw_c::init)
ADD_POST_HOOK(FileInfoSetHeartCount, file_info_set_heart_count_post, dFile_info_c::setHeartCnt)
ADD_POST_HOOK(ScreenInitButton, screen_init_button_post, dMeterButton_c::screenInitButton)
ADD_POST_HOOK(MenuSaveScreenSet, menu_save_screen_set_post, dMenu_save_c::screenSet)
ADD_POST_HOOK(FileSelectScreenSet, file_select_screen_set_post, dFile_select_c::screenSet)
ADD_POST_HOOK(BrightCheckScreenSet, bright_check_screen_set_post, dBrightCheck_c::screenSet)
ADD_POST_HOOK(MenuRingCreate, menu_ring_create_post, dMenu_Ring_c::_create)
ADD_POST_HOOK(MenuCollect2DCreate, menu_collect_2D_create_post, dMenu_Collect2D_c::_create)
ADD_POST_HOOK(MenuFishingScreenSetDoIcon, menu_fishing_screen_set_do_icon_post, dMenu_Fishing_c::screenSetDoIcon)
ADD_POST_HOOK(MenuInsectScreenSetDoIcon, menu_insect_screen_set_do_icon_post, dMenu_Insect_c::screenSetDoIcon)
ADD_POST_HOOK(MenuLetterScreenSetDoIcon, menu_letter_screen_set_do_icon_post, dMenu_Letter_c::screenSetDoIcon)
ADD_POST_HOOK(MenuOptionCreate, menu_option_create_post, dMenu_Option_c::_create)
ADD_POST_HOOK(MenuSkillScreenSetDoIcon, menu_skill_screen_set_do_icon_post, dMenu_Skill_c::screenSetDoIcon)
ADD_POST_HOOK(OutFontCreatePane, out_font_create_pane_post, COutFont_c::createPane)
ADD_POST_HOOK(OutFontSetDrawFont, out_font_set_draw_font_post, COutFontSet_c::drawFont)
ADD_POST_HOOK(MenuFMapCreate, menu_fmap_create_post, dMenu_Fmap_c::_create)
ADD_POST_HOOK(MsgObjectTalkStartInit, msg_object_talk_start_init_post, dMsgObject_c::talkStartInit)
ADD_POST_HOOK(MeterHakushaCreate, meter_hakusha_create_post, dMeterHakusha_c::_create)
// Heart Model Color
ADD_POST_HOOK(ItemBaseCreateItemHeap, item_base_create_item_heap_post, daItemBase_c::CreateItemHeap)
return MOD_OK;
}
#define UNINSTALL_HOOK(defined_hook) mods::hook::uninstall<defined_hook>(svc_hook);
ModResult remove_all_hooks() {
UNINSTALL_HOOK(WolfEyeLightSet)
UNINSTALL_HOOK(PreKandelaarDraw)
UNINSTALL_HOOK(CPaneMgrSetBlackWhite)
UNINSTALL_HOOK(KanteraIconSetNowGauge)
UNINSTALL_HOOK(SetWolfLockDomeModel)
UNINSTALL_HOOK(SetLightningSwordEffect)
UNINSTALL_HOOK(MidnaCreate)
UNINSTALL_HOOK(MidnaSetBodyPartMatrix)
UNINSTALL_HOOK(MidnaSetBodyPartMatrix)
UNINSTALL_HOOK(dMeter2Init)
UNINSTALL_HOOK(FileInfoSetHeartCount)
UNINSTALL_HOOK(ScreenInitButton)
UNINSTALL_HOOK(MenuSaveScreenSet)
UNINSTALL_HOOK(FileSelectScreenSet)
UNINSTALL_HOOK(BrightCheckScreenSet)
UNINSTALL_HOOK(MenuRingCreate)
UNINSTALL_HOOK(MenuCollect2DCreate)
UNINSTALL_HOOK(MenuFishingScreenSetDoIcon)
UNINSTALL_HOOK(MenuInsectScreenSetDoIcon)
UNINSTALL_HOOK(MenuLetterScreenSetDoIcon)
UNINSTALL_HOOK(MenuOptionCreate)
UNINSTALL_HOOK(MenuSkillScreenSetDoIcon)
UNINSTALL_HOOK(OutFontCreatePane)
UNINSTALL_HOOK(OutFontSetDrawFont)
UNINSTALL_HOOK(MenuFMapCreate)
UNINSTALL_HOOK(MsgObjectTalkStartInit)
UNINSTALL_HOOK(MeterHakushaCreate)
UNINSTALL_HOOK(ItemBaseCreateItemHeap)
return MOD_OK;
}
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include "mods/service.hpp"
ModResult add_all_hooks();
ModResult remove_all_hooks();
@@ -0,0 +1,141 @@
#include "midna_hair_color.hpp"
#include "mod.hpp"
#include "mods/svc/log.hpp"
#include <array>
static constexpr std::array<std::array<GXColor, 9>, 10> midnaHairColors = {{
// Default
{{
/*l_lNormalKColor*/ /*l_normalKColor*/ /*l_normalColor*/
{0xFF, 0xDC, 0x00}, {0xB4, 0x87, 0x00}, {0x50, 0x00, 0x00},
/*l_bigKColor*/ /*l_lBigColor*/ /*l_bigColor*/
{0x1E, 0x00, 0x00}, {0xFF, 0x78, 0x00}, {0xFF, 0x64, 0x78},
/*l_lNormalKColor2*//*l_normalKColor2*/ /*l_lBigKColor2*/
{0x00, 0xC3, 0xEB}, {0x00, 0xC3, 0xC3}, {0xAA, 0xFF, 0xC3}
}},
// Pink
{{
{0xF5, 0xCF, 0xF3}, {0xAD, 0x7F, 0x7F}, {0x1B, 0x00, 0x20},
{0x3C, 0x02, 0x58}, {0xE3, 0x72, 0xF2}, {0xE3, 0x5F, 0xF8},
{0xDD, 0x00, 0xEB}, {0xDD, 0x00, 0xC3}, {0xF6, 0x4C, 0xFF}
}},
// Red
{{
{0xE4, 0x65, 0x41}, {0xA1, 0x3E, 0x22}, {0x21, 0x00, 0x00},
{0x4F, 0x02, 0x01}, {0xF0, 0x3A, 0x25}, {0xF0, 0x30, 0x8C},
{0xEB, 0x00, 0x00}, {0xEB, 0x00, 0x00}, {0xFF, 0x4F, 0x3A}
}},
// Yellow
{{
{0x91, 0x83, 0x0E}, {0x66, 0x50, 0x07}, {0x0E, 0x0B, 0x00},
{0x24, 0x25, 0x02}, {0xCB, 0xB7, 0x00}, {0xCB, 0x99, 0x78},
{0xEB, 0xDE, 0x00}, {0xEB, 0xDE, 0x00}, {0xFF, 0xF8, 0xBF}
}},
// Green
{{
{0x35, 0x79, 0x53}, {0x25, 0x4A, 0x2B}, {0x00, 0x0E, 0x05},
{0x0A, 0x29, 0x10}, {0x00, 0xB6, 0x6F}, {0x00, 0x98, 0xB3},
{0x1F, 0xEB, 0x00}, {0x1F, 0xEB, 0x00}, {0x9A, 0xFF, 0x81}
}},
// Blue
{{
{0x00, 0x72, 0xFF}, {0x00, 0x46, 0x85}, {0x00, 0x08, 0x28},
{0x16, 0x1B, 0x5D}, {0x00, 0x60, 0xFF}, {0x00, 0x50, 0xFF},
{0x00, 0x48, 0xEB}, {0x00, 0x48, 0xC3}, {0x3A, 0x66, 0xFF}
}},
// Purple
{{
{0x6F, 0x34, 0xFF}, {0x4E, 0x20, 0x85}, {0x0D, 0x00, 0x34},
{0x15, 0x08, 0x79}, {0x62, 0x00, 0xFF}, {0x62, 0x00, 0xFF},
{0x7B, 0x00, 0xEB}, {0x7B, 0x00, 0xC3}, {0x94, 0x3E, 0xFF}
}},
// Brown
{{
{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x1A, 0x05, 0x00},
{0x3C, 0x19, 0x0E}, {0x3F, 0x1D, 0x0B}, {0x3F, 0x18, 0x7E},
{0x3F, 0x1D, 0x0B}, {0x3F, 0x1D, 0x09}, {0x59, 0x32, 0x1E}
}},
// White
{{
{0xF0, 0xF1, 0xF1}, {0xA9, 0x94, 0x7E}, {0x09, 0x0B, 0x0C},
{0x22, 0x24, 0x24}, {0xFF, 0xFF, 0xFF}, {0xFF, 0xD5, 0xFF},
{0xEA, 0xEA, 0xEA}, {0xEA, 0xEA, 0xC2}, {0xF3, 0xF3, 0xF3}
}},
// Black
{{
{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x0B, 0x0B, 0x0B},
{0x23, 0x23, 0x23}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x78},
{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}
}}
}};
static struct {
GXColorS10 l_normalColor = { 0x50, 0x00, 0x00, 0x00 };
GXColor l_normalKColor = { 0xB4, 0x87, 0x00, 0x00 };
GXColor l_normalKColor2 = { 0x00, 0xC3, 0xC3, 0x00 };
GXColorS10 l_bigColor = { 0xFF, 0x64, 0x78, 0x00 };
GXColor l_bigKColor = { 0x1E, 0x00, 0x00, 0x00 };
GXColor l_lNormalKColor = { 0xFF, 0xDC, 0x00, 0x00 };
GXColor l_lNormalKColor2 = { 0x00, 0xC3, 0xEB, 0x00 };
GXColorS10 l_lBigColor = { 0xFF, 0x78, 0x00, 0x00 };
GXColor l_lBigKColor2 = { 0xAA, 0xFF, 0xC3, 0x00 };
} currentMidnaHairColors;
void set_all_midna_hair_colors() {
auto& g_cvars = get_cvars();
auto hairBaseColor = get_int_option(g_cvars.midnaHairBaseColor, 0);
auto hairTipsColor = get_int_option(g_cvars.midnaHairTipsColor, 0);
// Colors we have to convert to GXColorS10
auto& normalColor = midnaHairColors.at(hairBaseColor)[2];
auto& bigColor = midnaHairColors.at(hairBaseColor)[5];
auto& lBigColor = midnaHairColors.at(hairBaseColor)[4];
currentMidnaHairColors.l_normalColor = GXColorS10{normalColor.r, normalColor.g, normalColor.b};
currentMidnaHairColors.l_normalKColor = midnaHairColors.at(hairBaseColor)[1];
currentMidnaHairColors.l_normalKColor2 = midnaHairColors.at(hairTipsColor)[7];
currentMidnaHairColors.l_bigColor = GXColorS10{bigColor.r, bigColor.g, bigColor.b};
currentMidnaHairColors.l_bigKColor = midnaHairColors.at(hairBaseColor)[3];
currentMidnaHairColors.l_lNormalKColor = midnaHairColors.at(hairBaseColor)[0];
currentMidnaHairColors.l_lNormalKColor2 = midnaHairColors.at(hairTipsColor)[6];
currentMidnaHairColors.l_lBigColor = GXColorS10{lBigColor.r, lBigColor.g, lBigColor.b};
currentMidnaHairColors.l_lBigKColor2 = midnaHairColors.at(hairTipsColor)[8];
}
const GXColorS10* get_midna_hair_normalColor() {
return &currentMidnaHairColors.l_normalColor;
}
const GXColor* get_midna_hair_normalKColor() {
return &currentMidnaHairColors.l_normalKColor;
}
const GXColor* get_midna_hair_normalKColor2() {
return &currentMidnaHairColors.l_normalKColor2;
}
const GXColorS10* get_midna_hair_bigColor() {
return &currentMidnaHairColors.l_bigColor;
}
const GXColor* get_midna_hair_bigKColor() {
return &currentMidnaHairColors.l_bigKColor;
}
const GXColor* get_midna_hair_lNormalKColor() {
return &currentMidnaHairColors.l_lNormalKColor;
}
const GXColor* get_midna_hair_lNormalKColor2() {
return &currentMidnaHairColors.l_lNormalKColor2;
}
const GXColorS10* get_midna_hair_lBigColor() {
return &currentMidnaHairColors.l_lBigColor;
}
const GXColor* get_midna_hair_lBigKColor2() {
return &currentMidnaHairColors.l_lBigKColor2;
}
@@ -0,0 +1,15 @@
#pragma once
#include <gx.h>
void set_all_midna_hair_colors();
const GXColorS10* get_midna_hair_normalColor();
const GXColor* get_midna_hair_normalKColor();
const GXColor* get_midna_hair_normalKColor2();
const GXColorS10* get_midna_hair_bigColor();
const GXColor* get_midna_hair_bigKColor();
const GXColor* get_midna_hair_lNormalKColor();
const GXColor* get_midna_hair_lNormalKColor2();
const GXColorS10* get_midna_hair_lBigColor();
const GXColor* get_midna_hair_lBigKColor2();
+460
View File
@@ -0,0 +1,460 @@
#include "mod.hpp"
#include "color_utils.hpp"
#include "hooks.hpp"
#include "midna_hair_color.hpp"
#include "option_descriptions.hpp"
#include "texture_utils.hpp"
#include "mods/service.hpp"
#include "mods/svc/config.h"
#include "mods/svc/hook.hpp"
#include "mods/svc/log.h"
#include "mods/svc/log.hpp"
#include "mods/svc/ui.h"
#include "d/d_com_inf_game.h"
#include <xxhash.h>
#include <optional>
#include <ranges>
#include <string>
DEFINE_MOD();
IMPORT_SERVICE(LogService, svc_log);
IMPORT_SERVICE(ConfigService, svc_config);
IMPORT_SERVICE(HookService, svc_hook);
IMPORT_SERVICE(TextureService, svc_texture);
IMPORT_SERVICE(UiService, svc_ui);
static cvars g_cvars;
cvars& get_cvars() {
return g_cvars;
}
std::string get_str_option(ConfigVarHandle handle, const std::string& fallback) {
std::string value{};
size_t outLength{};
svc_config->get_string(mod_ctx, handle, NULL, 0, &outLength);
value.resize(outLength);
if (handle == 0 || svc_config->get_string(mod_ctx, handle, value.data(), value.size() + 1, &outLength) != MOD_OK) {
return fallback;
}
return value;
}
int64_t get_int_option(ConfigVarHandle handle, int64_t fallback) {
int64_t value = fallback;
if (handle == 0 || svc_config->get_int(mod_ctx, handle, &value) != MOD_OK) {
return fallback;
}
return value;
}
// Helper for getting configVar color
std::optional<GXColor> get_config_var_color(ConfigVarHandle handle, bool allowRainbow /*= false*/) {
auto colorStr = get_str_option(handle, "");
// Convert to lowercase
for (auto& c : colorStr) {
c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
}
if (is_valid_hex_color_str(colorStr) || (colorStr == "rainbow" && allowRainbow)) {
if (is_valid_hex_color_str(colorStr)) {
return hex_color_str_to_gx_color(colorStr);
}
if (allowRainbow) {
// Assume rainbow if not a valid hex str
auto color = get_rainbow_rgb(127.5f);
color.r /= 2;
color.g /= 2;
color.b /= 2;
return color;
}
}
return std::nullopt;
}
namespace {
UiWindowHandle g_cosmeticsWindow = 0;
bool g_loadedAllBaseTextures = false;
ModResult register_str_option(
const char* name, const char* defaultValue, ConfigVarHandle& outHandle, ModError* error) {
ConfigVarDesc cvarDesc = CONFIG_VAR_DESC_INIT;
cvarDesc.name = name;
cvarDesc.type = CONFIG_VAR_STRING;
cvarDesc.default_string = defaultValue;
if (svc_config->register_var(mod_ctx, &cvarDesc, &outHandle) != MOD_OK) {
return mods::set_error(error, MOD_ERROR, "failed to register cosmetics option");
}
return MOD_OK;
}
ModResult register_int_option(
const char* name, int64_t defaultValue, ConfigVarHandle& outHandle, ModError* error) {
ConfigVarDesc cvarDesc = CONFIG_VAR_DESC_INIT;
cvarDesc.name = name;
cvarDesc.type = CONFIG_VAR_INT;
cvarDesc.default_int = defaultValue;
if (svc_config->register_var(mod_ctx, &cvarDesc, &outHandle) != MOD_OK) {
return mods::set_error(error, MOD_ERROR, "failed to register cosmetics option");
}
return MOD_OK;
}
void add_control(UiElementHandle pane, const UiControlDesc& desc) {
auto result = svc_ui->pane_add_control(mod_ctx, pane, &desc, nullptr);
if (result != MOD_OK) {
mods::log::debug("pane_add_control failed {}", static_cast<int>(result));
}
}
void add_cosmetic_option(UiElementHandle left, ConfigVarHandle cvar, const char* name, const char* helpRml) {
UiControlDesc control = UI_CONTROL_DESC_INIT;
control.kind = UI_CONTROL_STRING;
control.label = name;
control.help_rml = helpRml;
control.binding = UI_BINDING_CONFIG_VAR;
control.config_var = cvar;
control.max_length = 6;
add_control(left, control);
}
void add_cosmetic_option_with_rainbow(UiElementHandle left, ConfigVarHandle cvar, const char* name, const char* helpRml) {
UiControlDesc control = UI_CONTROL_DESC_INIT;
control.kind = UI_CONTROL_STRING;
control.label = name;
control.help_rml = helpRml;
control.binding = UI_BINDING_CONFIG_VAR;
control.config_var = cvar;
control.max_length = 7;
add_control(left, control);
}
void add_midna_hair_option(UiElementHandle left, ConfigVarHandle cvar, const std::string& name) {
static const char* kMidnaHairOptions[] = {
"Default", "Pink", "Red", "Yellow", "Green", "Blue", "Purple", "Brown", "White", "Black"
};
UiControlDesc control = UI_CONTROL_DESC_INIT;
control.kind = UI_CONTROL_SELECT;
control.label = name.c_str();
control.help_rml = "Choose Midna's hair color.";
control.binding = UI_BINDING_CONFIG_VAR;
control.config_var = cvar;
control.options = kMidnaHairOptions;
control.option_count = 10;
add_control(left, control);
}
ModResult build_equipment_colors_tab(
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
(void)right;
add_cosmetic_option(left, g_cvars.herosTunicCapColor, "Hero's Tunic Cap Color", kLinksCapColorsExplanation);
add_cosmetic_option(left, g_cvars.herosTunicTorsoColor, "Hero's Tunic Body Color", kLinksShirtColorsExplanation);
add_cosmetic_option(left, g_cvars.herosTunicSkirtColor, "Hero's Tunic Skirt Color", kLinksSkirtColorsExplanation);
add_cosmetic_option(left, g_cvars.zoraArmorCapColor, "Zora Armor Cap Color", kZoraCapColorsExplanation);
add_cosmetic_option(left, g_cvars.zoraArmorHelmetColor, "Zora Armor Helmet Color", kZoraHelmetColorsExplanation);
add_cosmetic_option(left, g_cvars.zoraArmorTorsoColor, "Zora Armor Torso Color", kZoraTorsoColorsExplanation);
add_cosmetic_option(left, g_cvars.zoraArmorScalesColor, "Zora Armor Scales Color", kZoraScalesColorsExplanation);
add_cosmetic_option(left, g_cvars.zoraArmorFlippersColor, "Zora Armor Flippers Color", kZoraFlippersColorsExplanation);
add_cosmetic_option_with_rainbow(left, g_cvars.lanternGlowColor, "Lantern Glow Color", kLanternGlowColorsExplanation);
add_cosmetic_option(left, g_cvars.woodenSwordColor, "Wooden Sword Color", kWoodenSwordColorsExplanation);
add_cosmetic_option(left, g_cvars.ordonSwordBladeColor, "Ordon Sword Blade Color", kOrdonBladeColorsExplanation);
add_cosmetic_option(left, g_cvars.ordonSwordHandleColor, "Ordon Sword Handle Color", kOrdonHandleColorsExplanation);
add_cosmetic_option(left, g_cvars.msBladeColor, "Master Sword Blade Color", kMSBladeColorsExplanation);
add_cosmetic_option(left, g_cvars.msHandleColor, "Master Sword Handle Color", kMSHandleColorsExplanation);
add_cosmetic_option_with_rainbow(left, g_cvars.lightSwordGlowColor, "Light Sword Glow Color", kSwordGlowColorsExplanation);
add_cosmetic_option(left, g_cvars.boomerangColor, "Boomerang Color", kBoomerangColorsExplanation);
add_cosmetic_option(left, g_cvars.ironBootsColor, "Iron Boots Color", kIronBootsColorsExplanation);
add_cosmetic_option(left, g_cvars.spinnerColor, "Spinner Color", kSpinnerColorsExplanation);
return MOD_OK;
}
ModResult build_ui_colors_tab(
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
(void)right;
add_cosmetic_option(left, g_cvars.aButtonColor, "A Button Color", kAButtonColorsExplanation);
add_cosmetic_option(left, g_cvars.bButtonColor, "B Button Color", kBButtonColorsExplanation);
add_cosmetic_option(left, g_cvars.xButtonColor, "X Button Color", kXButtonColorsExplanation);
add_cosmetic_option(left, g_cvars.yButtonColor, "Y Button Color", kYButtonColorsExplanation);
add_cosmetic_option(left, g_cvars.zButtonColor, "Z Button Color", kZButtonColorsExplanation);
add_cosmetic_option(left, g_cvars.heartColor, "Heart Color", kHeartColorsExplanation);
return MOD_OK;
}
ModResult build_misc_colors_tab(
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
(void)right;
add_midna_hair_option(left, g_cvars.midnaHairBaseColor, "Midna's Hair Base Color");
add_midna_hair_option(left, g_cvars.midnaHairTipsColor, "Midna's Hair Tips Color");
add_cosmetic_option(left, g_cvars.midnaChargeRingColor, "Midna Charge Ring Color", kChargeRingColorsExplanation);
add_cosmetic_option(left, g_cvars.linkHairColor, "Link's Hair Color", kLinksHairColorsExplanation);
add_cosmetic_option(left, g_cvars.wolfLinkColor, "Wolf Link Color", kWolfLinkColorsExplanation);
add_cosmetic_option(left, g_cvars.eponaColor, "Epona Color", kEponaColorsExplanation);
return MOD_OK;
}
void on_cosmetics_menu_window_closed(ModContext*, UiWindowHandle, void*) {
g_cosmeticsWindow = 0;
}
void on_open_cosmetics_menu(ModContext*, void*) {
if (g_cosmeticsWindow != 0) {
return;
}
UiTabDesc tabs[] = {UI_TAB_DESC_INIT, UI_TAB_DESC_INIT, UI_TAB_DESC_INIT};
tabs[0].title = "Equipment Colors";
tabs[0].build = build_equipment_colors_tab;
tabs[1].title = "UI Colors";
tabs[1].build = build_ui_colors_tab;
tabs[2].title = "Misc Colors";
tabs[2].build = build_misc_colors_tab;
UiWindowDesc desc = UI_WINDOW_DESC_INIT;
desc.tabs = tabs;
desc.tab_count = ARRAY_SIZE(tabs);
desc.on_closed = on_cosmetics_menu_window_closed;
if (svc_ui->window_push(mod_ctx, &desc, &g_cosmeticsWindow) != MOD_OK) {
svc_log->error(mod_ctx, "failed to open basic cosmetics window");
}
}
ModResult build_panel(ModContext*, UiElementHandle panel, void*, ModError*) {
UiControlDesc control = UI_CONTROL_DESC_INIT;
control.kind = UI_CONTROL_BUTTON;
control.label = "Open Cosmetics Menu";
control.on_pressed = on_open_cosmetics_menu;
add_control(panel, control);
return MOD_OK;
}
}
void load_base_texture_data() {
// Go through each texture we can recolor and attempt to load and store
// the texture data for future recoloring
for (auto& replacements : get_texture_replacements() | std::views::values) {
for (auto& replacement : replacements) {
// If we've already loaded the texture data, don't load it again
if (replacement.loadedTextureData) {
continue;
}
// Try to get the model this texture is part of. If we can't get it, try again later
auto model = static_cast<J3DModelData*>(dComIfG_getObjectRes(replacement.arc, replacement.modelFileName));
if (model == nullptr) {
continue;
}
J3DTexture* tex = model->getTexture();
JUTNameTab* nametable = model->getTextureName();
if (tex != nullptr && nametable != nullptr) {
for (u16 i = 0; i < tex->getNum(); i++) {
const char* texName = nametable->getName(i);
if (texName != nullptr && std::strcmp(texName, replacement.textureName) == 0) {
// Once we've found the texture, set all our TextureKey and TextureData fields
// that we can set right now.
auto imageHeader = tex->getResTIMG(i);
auto& key = replacement.key;
auto& data = replacement.data;
key.kind = TEXTURE_KEY_SOURCE;
key.has_tlut = imageHeader->numColors > 0;
key.width = imageHeader->width;
key.height = imageHeader->height;
key.gx_format = imageHeader->format;
// Currently, no replaced textures have a tlut
key.tlut_hash = replacement.tlutHash;
// Calculate the size of the image data
auto size = get_image_data_size(imageHeader->format, imageHeader->width,
imageHeader->height, imageHeader->mipmapEnabled ? imageHeader->mipmapCount : 1);
replacement.baseTextureData.resize(size);
std::memcpy(replacement.baseTextureData.data(), tex->getImgDataPtr(i), size);
// Calculate the texture hash
auto textureHash = XXH64(replacement.baseTextureData.data(), size, 0);
replacement.key.texture_hash = textureHash;
mods::log::debug("Loaded base texture data for {}. size: {:X} hash: {:X}", replacement.textureName, size, textureHash);
replacement.loadedTextureData = true;
data.width = imageHeader->width;
data.height = imageHeader->height;
data.mip_count = imageHeader->mipmapCount;
data.size = size;
data.gx_format = imageHeader->format;
break;
}
}
}
}
}
// If we've loaded all base textures for recoloring, then we don't need to call this function again
g_loadedAllBaseTextures = std::ranges::all_of(get_texture_replacements() | std::views::values, [](auto& replacementList) {
return std::ranges::all_of(replacementList, [](const TextureReplacementData& replacement) {
return replacement.loadedTextureData;
});
});
}
ModResult check_and_set_recolored_textures() {
for (auto& [configVar, replacements] : get_texture_replacements()) {
// If the configvar hasn't been set, don't continue
if (configVar == 0) {
continue;
}
// If we don't have a valid color, don't continue either
auto maybeColor = get_config_var_color(configVar);
if (!maybeColor.has_value()) {
continue;
}
auto color = maybeColor.value();
for (auto& replacement : replacements) {
// If we haven't loaded the base texture yet, don't try to recolor it
if (!replacement.loadedTextureData) {
continue;
}
// If our color hasn't changed, don't try to recolor
auto& curColor = replacement.curColor;
if (curColor == std::nullopt ||
curColor.value().r != color.r || curColor.value().g != color.g || curColor.value().b != color.b)
{
// Make a copy of the base texture data to recolor
auto newTexture = replacement.baseTextureData;
recolor_texture(replacement, color, newTexture);
replacement.data.data = newTexture.data();
replacement.data.size = newTexture.size();
// Register the new data
auto result = svc_texture->register_data(mod_ctx, &replacement.key, &replacement.data, &replacement.handle);
if (result != MOD_OK) {
mods::log::debug("Could not register_data for {}. Result: {}", replacement.textureName, static_cast<int>(result));
} else {
mods::log::debug("Registered replacement for {}.", replacement.textureName, static_cast<int>(result));
}
curColor = color;
}
}
}
return MOD_OK;
}
void unregister_all_texture_handles() {
for (auto& replacements : get_texture_replacements() | std::views::values) {
for (auto& replacement : replacements) {
if (replacement.handle != 0) {
svc_texture->unregister(mod_ctx, replacement.handle);
}
}
}
}
#define REGISTER_COSMETIC_OPTION(option) \
result = register_str_option(#option, NULL, g_cvars.option, error); \
if (result != MOD_OK) { \
return result; \
} \
extern "C" {
MOD_EXPORT ModResult mod_initialize(ModError* error) {
svc_log->info(mod_ctx, "basic_cosmetics_mod initialized");
ModResult result{};
REGISTER_COSMETIC_OPTION(herosTunicCapColor)
REGISTER_COSMETIC_OPTION(herosTunicTorsoColor)
REGISTER_COSMETIC_OPTION(herosTunicSkirtColor)
REGISTER_COSMETIC_OPTION(zoraArmorCapColor)
REGISTER_COSMETIC_OPTION(zoraArmorHelmetColor)
REGISTER_COSMETIC_OPTION(zoraArmorTorsoColor)
REGISTER_COSMETIC_OPTION(zoraArmorScalesColor)
REGISTER_COSMETIC_OPTION(zoraArmorFlippersColor)
REGISTER_COSMETIC_OPTION(lanternGlowColor)
REGISTER_COSMETIC_OPTION(woodenSwordColor)
REGISTER_COSMETIC_OPTION(ordonSwordBladeColor)
REGISTER_COSMETIC_OPTION(ordonSwordHandleColor)
REGISTER_COSMETIC_OPTION(msBladeColor)
REGISTER_COSMETIC_OPTION(msHandleColor)
REGISTER_COSMETIC_OPTION(lightSwordGlowColor)
REGISTER_COSMETIC_OPTION(boomerangColor)
REGISTER_COSMETIC_OPTION(ironBootsColor)
REGISTER_COSMETIC_OPTION(spinnerColor)
REGISTER_COSMETIC_OPTION(aButtonColor)
REGISTER_COSMETIC_OPTION(bButtonColor)
REGISTER_COSMETIC_OPTION(xButtonColor)
REGISTER_COSMETIC_OPTION(yButtonColor)
REGISTER_COSMETIC_OPTION(zButtonColor)
REGISTER_COSMETIC_OPTION(heartColor)
result = register_int_option("midnaHairBaseColor", 0, g_cvars.midnaHairBaseColor, error);
if (result != MOD_OK) {
return result;
}
result = register_int_option("midnaHairTipsColor", 0, g_cvars.midnaHairTipsColor, error);
if (result != MOD_OK) {
return result;
}
REGISTER_COSMETIC_OPTION(midnaChargeRingColor)
REGISTER_COSMETIC_OPTION(linkHairColor)
REGISTER_COSMETIC_OPTION(wolfLinkColor)
REGISTER_COSMETIC_OPTION(eponaColor)
UiModsPanelDesc panelDesc = UI_MODS_PANEL_DESC_INIT;
panelDesc.build = build_panel;
svc_ui->register_mods_panel(mod_ctx, &panelDesc);
// Add all our hooks
result = add_all_hooks();
if (result != MOD_OK) {
return result;
}
g_loadedAllBaseTextures = false;
return MOD_OK;
}
MOD_EXPORT ModResult mod_update(ModError*) {
update_rainbow_rgb(1.0f);
set_all_midna_hair_colors();
if (!g_loadedAllBaseTextures) {
load_base_texture_data();
}
check_and_set_recolored_textures();
return MOD_OK;
}
MOD_EXPORT ModResult mod_shutdown(ModError*) {
svc_log->info(mod_ctx, "basic_cosmetics_mod unloaded");
g_cosmeticsWindow = 0;
remove_all_hooks();
unregister_all_texture_handles();
get_texture_replacements().clear();
return MOD_OK;
}
}
+65
View File
@@ -0,0 +1,65 @@
#pragma once
#include "mods/svc/config.h"
#include "mods/svc/texture.h"
#include <gx.h>
#include <optional>
#include <string>
#include <vector>
struct cvars {
ConfigVarHandle herosTunicCapColor = 0;
ConfigVarHandle herosTunicTorsoColor = 0;
ConfigVarHandle herosTunicSkirtColor = 0;
ConfigVarHandle zoraArmorCapColor = 0;
ConfigVarHandle zoraArmorHelmetColor = 0;
ConfigVarHandle zoraArmorTorsoColor = 0;
ConfigVarHandle zoraArmorScalesColor = 0;
ConfigVarHandle zoraArmorFlippersColor = 0;
ConfigVarHandle lanternGlowColor = 0;
ConfigVarHandle woodenSwordColor = 0;
ConfigVarHandle ordonSwordBladeColor = 0;
ConfigVarHandle ordonSwordHandleColor = 0;
ConfigVarHandle msBladeColor = 0;
ConfigVarHandle msHandleColor = 0;
ConfigVarHandle lightSwordGlowColor = 0;
ConfigVarHandle boomerangColor = 0;
ConfigVarHandle ironBootsColor = 0;
ConfigVarHandle spinnerColor = 0;
ConfigVarHandle heartColor = 0;
ConfigVarHandle aButtonColor = 0;
ConfigVarHandle bButtonColor = 0;
ConfigVarHandle xButtonColor = 0;
ConfigVarHandle yButtonColor = 0;
ConfigVarHandle zButtonColor = 0;
ConfigVarHandle midnaHairBaseColor = 0;
ConfigVarHandle midnaHairTipsColor = 0;
ConfigVarHandle midnaChargeRingColor = 0;
ConfigVarHandle linkHairColor = 0;
ConfigVarHandle wolfLinkColor = 0;
ConfigVarHandle eponaColor = 0;
};
struct TextureReplacementData {
const char* arc{};
const char* modelFileName{};
const char* textureName{};
uint64_t textureHash{};
uint64_t tlutHash{};
TextureKey key = TEXTURE_KEY_INIT;
TextureData data = TEXTURE_DATA_INIT;
TextureReplacementHandle handle{};
std::vector<u8> baseTextureData{};
bool loadedTextureData = false;
std::optional<GXColor> curColor{};
};
cvars& get_cvars();
std::string get_str_option(ConfigVarHandle handle, const std::string& fallback);
int64_t get_int_option(ConfigVarHandle handle, int64_t fallback);
std::optional<GXColor> get_config_var_color(ConfigVarHandle handle, bool allowRainbow = false);
@@ -0,0 +1,353 @@
#pragma once
constexpr const char* kLinksCapColorsExplanation =
"Set the color of the Hero's Tunic cap with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kLinksShirtColorsExplanation =
"Set the color of the Hero's Tunic shirt with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kLinksSkirtColorsExplanation =
"Set the color of the Hero's Tunic skirt with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kZoraCapColorsExplanation =
"Set the color of the Zora Armor cap with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kZoraHelmetColorsExplanation =
"Set the color of the Zora Armor helmet with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kZoraTorsoColorsExplanation =
"Set the color of the Zora Armor torso with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kZoraScalesColorsExplanation =
"Set the color of the Zora Armor scales with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kZoraFlippersColorsExplanation =
"Set the color of the Zora Armor flippers with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kWoodenSwordColorsExplanation =
"Set the color of the wooden sword with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kLanternGlowColorsExplanation =
"Set the color of the lantern light with any 6 digit hex code, or with \"rainbow\" for a rainbow effect.<br/>"
"Common colors:<br/>"
"- Red: ff0000<br/>"
"- Orange: f68821<br/>"
"- Yellow: f6f321<br/>"
"- Green: 00ff00<br/>"
"- Blue: 0000ff<br/>"
"- Purple: 8000ff<br/>"
"- White: a0a0a0<br/>";
constexpr const char* kOrdonBladeColorsExplanation =
"Set the color of the Ordon Sword's blade with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ff0000<br/>"
"- Orange: f68821<br/>"
"- Yellow: f6f321<br/>"
"- Green: 00ff00<br/>"
"- Blue: 0000ff<br/>"
"- Purple: 8000ff<br/>"
"- White: a0a0a0<br/>"
"- Cyan: 30d0d0<br/>";
constexpr const char* kOrdonHandleColorsExplanation =
"Set the color of the Ordon Sword's handle with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ff0000<br/>"
"- Orange: f68821<br/>"
"- Yellow: f6f321<br/>"
"- Green: 00ff00<br/>"
"- Blue: 0000ff<br/>"
"- Purple: 8000ff<br/>"
"- White: a0a0a0<br/>"
"- Cyan: 30d0d0<br/>";
constexpr const char* kMSBladeColorsExplanation =
"Set the color of the Master Sword's blade with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ff0000<br/>"
"- Orange: f68821<br/>"
"- Yellow: f6f321<br/>"
"- Green: 00ff00<br/>"
"- Blue: 0000ff<br/>"
"- Purple: 8000ff<br/>"
"- White: a0a0a0<br/>"
"- Cyan: 30d0d0<br/>";
constexpr const char* kMSHandleColorsExplanation =
"Set the color of the Master Sword's handle with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ff0000<br/>"
"- Orange: f68821<br/>"
"- Yellow: f6f321<br/>"
"- Green: 00ff00<br/>"
"- Blue: 0000ff<br/>"
"- Purple: 8000ff<br/>"
"- White: a0a0a0<br/>"
"- Cyan: 30d0d0<br/>";
constexpr const char* kSwordGlowColorsExplanation =
"Set the color of the light sword glow with any 6 digit hex code, or with \"rainbow\" for a rainbow effect.<br/>"
"Common colors:<br/>"
"- Red: ff0000<br/>"
"- Orange: f68821<br/>"
"- Yellow: f6f321<br/>"
"- Green: 00ff00<br/>"
"- Blue: 0000ff<br/>"
"- Purple: 8000ff<br/>"
"- White: a0a0a0<br/>";
constexpr const char* kBoomerangColorsExplanation =
"Set the color of the Gale Boomerang with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kIronBootsColorsExplanation =
"Set the color of the Iron Boots with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kSpinnerColorsExplanation =
"Set the color of the Spinner with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kAButtonColorsExplanation =
"Set the color of the A button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
"Common colors:<br/>"
"- Red: ff0000<br/>"
"- Orange: ff5000<br/>"
"- Yellow: ffaf00<br/>"
"- Dark Green: 0080ff<br/>"
"- Blue: 0000ff<br/>"
"- Purple: 8000ff<br/>"
"- Grey: 5555ff<br/>"
"- Pink: ff20ff<br/>";
constexpr const char* kBButtonColorsExplanation =
"Set the color of the B button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
"Common colors:<br/>"
"- Orange: ffff40<br/>"
"- Pink: ffa0ff<br/>"
"- Green: 00e87b<br/>"
"- Blue: 00aaff<br/>"
"- Purple: 6078ff<br/>"
"- Black: 000000<br/>"
"- Teal: 00f3ff<br/>";
constexpr const char* kXButtonColorsExplanation =
"Set the color of the X button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
"Common colors:<br/>"
"- Red: ff0000<br/>"
"- Orange: ff8200<br/>"
"- Yellow: f7df00<br/>"
"- Lime Green: 70ff00<br/>"
"- Dark Green: 00bd11<br/>"
"- Blue: 0000ff<br/>"
"- Purple: 800088<br/>"
"- Black: 000000<br/>"
"- Pink: ff00aa<br/>"
"- Cyan: 00ffff<br/>";
constexpr const char* kYButtonColorsExplanation =
"Set the color of the Y button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
"Common colors:<br/>"
"- Red: ff0000<br/>"
"- Orange: ff8200<br/>"
"- Yellow: f7df00<br/>"
"- Lime Green: 70ff00<br/>"
"- Dark Green: 00bd11<br/>"
"- Blue: 0000ff<br/>"
"- Purple: 800088<br/>"
"- Black: 000000<br/>"
"- Pink: ff00aa<br/>"
"- Cyan: 00ffff<br/>";
constexpr const char* kZButtonColorsExplanation =
"Set the Z button color with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
"Common colors:<br/>"
"- Red: ff0000<br/>"
"- Orange: ff8200<br/>"
"- Yellow: f7df00<br/>"
"- Lime Green: 70ff00<br/>"
"- Dark Green: 00bd11<br/>"
"- Purple: 800088<br/>"
"- Black: 000000<br/>"
"- Light Blue: 00ffff<br/>";
constexpr const char* kHeartColorsExplanation =
"Set the heart color with any 6 digit hex code. This will also change the color of heart drops. A reload may be necessary to see changes.<br/>"
"Common colors:<br/>"
"- Orange: ffff40<br/>"
"- Pink: ffa0ff<br/>"
"- Green: 00e87b<br/>"
"- Blue: 00aaff<br/>"
"- Purple: 6078ff<br/>"
"- Black: 000000<br/>"
"- Teal: 00f3ff<br/>";
constexpr const char* kChargeRingColorsExplanation =
"Set the color of Midna's charge ring with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Pink: ff9f9f<br/>"
"- Red: ff0000<br/>"
"- Yellow: ffff00<br/>"
"- Green: 00ff00<br/>"
"- Blue: 0000ff<br/>"
"- Purple: ff00ff<br/>"
"- Brown: 331900<br/>"
"- White: feffff<br/>"
"- Black: 000000<br/>";
constexpr const char* kLinksHairColorsExplanation =
"Set the color of Link's hair with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kWolfLinkColorsExplanation =
"Set the color of Wolf Link with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
constexpr const char* kEponaColorsExplanation =
"Set the color of Epona with any 6 digit hex code.<br/>"
"Common colors:<br/>"
"- Red: ab706e<br/>"
"- Blue: 6382a0<br/>"
"- Purple: 94749a<br/>"
"- Orange: ec8644<br/>"
"- Yellow: b9ab00<br/>"
"- Pink: ec9fc8<br/>"
"- Black: 505154<br/>"
"- White: f8f7f4<br/>"
"- Brown: 91723e<br/>";
@@ -0,0 +1,672 @@
#include "texture_utils.hpp"
#include "color_utils.hpp"
#include "mod.hpp"
#include "mods/svc/config.h"
#include "mods/svc/log.hpp"
// Forward declaration needed for J3DModelLoader to be happy
class J3DVertexData;
#include "JSystem/J3DGraphLoader/J3DModelLoader.h"
#include "JSystem/JSupport/JSupport.h"
#include "JSystem/JUtility/JUTNameTab.h"
#include "d/actor/d_a_alink.h"
static void get_gx_tile_info(uint8_t format, uint32_t& tileWidth, uint32_t& tileHeight, uint32_t& tileSize) {
switch (format) {
case GX_TF_I8:
case GX_TF_IA4:
case GX_TF_C8:
tileWidth = 8; tileHeight = 4; tileSize = 32;
break;
case GX_TF_IA8:
case GX_TF_RGB565:
case GX_TF_RGB5A3:
case GX_TF_C14X2:
tileWidth = 4; tileHeight = 4; tileSize = 32;
break;
case GX_TF_RGBA8:
tileWidth = 4; tileHeight = 4; tileSize = 64;
break;
case GX_TF_I4:
case GX_TF_C4:
case GX_TF_CMPR:
default:
tileWidth = 8; tileHeight = 8; tileSize = 32;
break;
}
}
uint32_t get_image_data_size(uint32_t format, uint32_t width, uint32_t height, uint32_t mipmapCount) {
uint32_t tileWidth, tileHeight, tileSize;
get_gx_tile_info(format, tileWidth, tileHeight, tileSize);
uint32_t totalSize = 0;
for (uint8_t i = 0; i < mipmapCount; ++i) {
// Round dimensions up to nearest tile boundary
uint32_t paddedWidth = (width + tileWidth - 1) & ~(tileWidth - 1);
uint32_t paddedHeight = (height + tileHeight - 1) & ~(tileHeight - 1);
uint32_t tilesX = paddedWidth / tileWidth;
uint32_t tilesY = paddedHeight / tileHeight;
totalSize += tilesX * tilesY * tileSize;
// Downscale dimensions for next mipmap level
width = std::max(1u, width >> 1);
height = std::max(1u, height >> 1);
}
return totalSize;
}
// When left is greater than right
// 0b00 points to the left color
// 0b01 points to the right color
// 0b10 is closer to left color
// 0b11 is closer to right color
// When left is not greater than right
// 0b00 points to the left color
// 0b01 points to the right color
// 0b10 is midway between the colors
// 0b11 is transparent
// That means when maintaining the relative order, if we have to swap the colors:
// in the case of left being greater than right:
// 0b00 will swap to 0b01
// 0b01 will swap to 0b00
// 0b10 will swap to 0b11
// 0b11 will swap to 0b10
// So the left bit stays the same, and the right bit changes
// Can do xor (^) like 0b01010101 or 0x55 for each u16
// in the case of left not being greater than right:
// 0b00 will swap to 0b01
// 0b01 will swap to 0b00
// 0b10 will stay the same
// 0b11 will stay the same
// so if the left bit is a 0, the right bit will change
uint32_t swap_index_bits(bool leftIsGreater, uint32_t bits) {
if (leftIsGreater) {
return bits ^ 0x55555555;
}
const uint32_t mask = ((bits >> 1) & 0x55555555) ^ 0x55555555;
return bits ^ mask;
}
void recolor_cmpr_texture(const TextureReplacementData& replacementData, const GXColor color, std::vector<u8>& newTextureDataOut)
{
uint16_t recolors[0x100];
for (int32_t i = 0; i < 0x100; i++) {
recolors[i] = blend_overlay_rgb_565(i, color);
}
const uint8_t mipCount = (replacementData.data.mip_count > 0) ? replacementData.data.mip_count : 1;
uint32_t mipWidth = replacementData.key.width;
uint32_t mipHeight = replacementData.key.height;
uint8_t* currentAddr = newTextureDataOut.data();
for (uint8_t mip = 0; mip < mipCount; ++mip) {
// Round dimensions up to the nearest 8x8 tile boundary
const uint32_t roundedWidth = (mipWidth + 7) & ~7;
const uint32_t roundedHeight = (mipHeight + 7) & ~7;
const uint32_t numBlocks = (roundedWidth / 8) * (roundedHeight / 8);
const uint32_t iterations = numBlocks * 4; // 4 CMPR sub-blocks per 8x8 tile
for (uint32_t i = 0; i < iterations; i++) {
auto* rgb565Ptr = reinterpret_cast<BE<uint16_t>*>(currentAddr);
auto leftRgb565 = rgb565Ptr[0];
auto rightRgb565 = rgb565Ptr[1];
const bool leftIsGreater = leftRgb565 > rightRgb565;
const uint32_t leftGrayVal = desaturate_rgb_565(leftRgb565);
const uint32_t rightGrayVal = desaturate_rgb_565(rightRgb565);
uint16_t leftNewRgb565 = recolors[leftGrayVal];
uint16_t rightNewRgb565 = recolors[rightGrayVal];
bool needsBitSwap = false;
if (leftIsGreater) {
if (leftNewRgb565 == rightNewRgb565) {
// Need to make sure that subtracting 1 does not mess
// everything up. For example, 0x1000 - 1 => 0x0fff which is
// a completely different color.
if ((leftNewRgb565 & 0x1f) == 0) {
// If left value has 0 blue, we change its blue to 1.
leftNewRgb565 += 1;
}
rightNewRgb565 = leftNewRgb565 - 1;
}
else if (leftNewRgb565 < rightNewRgb565) {
needsBitSwap = true;
}
}
else if (leftNewRgb565 > rightNewRgb565) {
needsBitSwap = true;
}
if (needsBitSwap) {
// The left and right colors are swapping so that their values
// are relative in the same way. We need to update the bits
// referencing the palette entries to handle the swap.
const uint16_t temp = leftNewRgb565;
leftNewRgb565 = rightNewRgb565;
rightNewRgb565 = temp;
auto wordPtr = reinterpret_cast<BE<uint32_t>*>(currentAddr);
const uint32_t bits = wordPtr[1];
const uint32_t newBits = swap_index_bits(leftIsGreater, bits);
wordPtr[1] = newBits;
}
rgb565Ptr[0] = leftNewRgb565;
rgb565Ptr[1] = rightNewRgb565;
currentAddr += 8;
}
// Halve dimensions for the next mipmap level
mipWidth = std::max(1u, mipWidth >> 1);
mipHeight = std::max(1u, mipHeight >> 1);
}
}
void recolor_rgb5a3_texture(const TextureReplacementData& replacementData, const GXColor color, std::vector<u8>& newTextureDataOut)
{
// Precompute lookup tables for both RGB555 (opaque) and RGB444 (translucent) modes
uint16_t recolors_rgb555[0x100];
uint16_t recolors_rgb444[0x100];
for (int32_t i = 0; i < 0x100; i++) {
const uint8_t r = blend_overlay_channel(i, color.r);
const uint8_t g = blend_overlay_channel(i, color.g);
const uint8_t b = blend_overlay_channel(i, color.b);
// Pack as RGB555: Bit 15 set to 1 + 5 bits R, G, B
recolors_rgb555[i] = 0x8000 | ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
// Pack as RGB444: 4 bits R, G, B (Bit 15 remains 0)
recolors_rgb444[i] = ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4);
}
constexpr int32_t blockWidth = 4;
constexpr int32_t blockHeight = 4;
const int32_t roundedWidth = replacementData.key.width + ((blockWidth - (replacementData.key.width % blockWidth)) % blockWidth);
const int32_t roundedHeight = replacementData.key.height + ((blockHeight - (replacementData.key.height % blockHeight)) % blockHeight);
const int32_t totalPixels = roundedWidth * roundedHeight;
auto* pixelPtr = newTextureDataOut.data();
for (int32_t i = 0; i < totalPixels; i++) {
const uint16_t rawPixel = pixelPtr[i];
// MSB determines if pixel is opaque or translucent
if (rawPixel & 0x8000) {
// Pixel is opaque
const uint8_t r5 = (rawPixel >> 10) & 0x1F;
const uint8_t g5 = (rawPixel >> 5) & 0x1F;
const uint8_t b5 = rawPixel & 0x1F;
// Expand 5-bit to 8-bit
const uint8_t r8 = (r5 << 3) | (r5 >> 2);
const uint8_t g8 = (g5 << 3) | (g5 >> 2);
const uint8_t b8 = (b5 << 3) | (b5 >> 2);
const uint8_t grayVal = static_cast<uint8_t>((r8 * 77 + g8 * 150 + b8 * 29) >> 8);
pixelPtr[i] = recolors_rgb555[grayVal];
} else {
// Pixel is translucent
const uint16_t alpha3 = rawPixel & 0x7000;
const uint8_t r4 = (rawPixel >> 8) & 0x0F;
const uint8_t g4 = (rawPixel >> 4) & 0x0F;
const uint8_t b4 = rawPixel & 0x0F;
// Expand 4-bit to 8-bit
const uint8_t r8 = (r4 << 4) | r4;
const uint8_t g8 = (g4 << 4) | g4;
const uint8_t b8 = (b4 << 4) | b4;
const uint8_t grayVal = static_cast<uint8_t>((r8 * 77 + g8 * 150 + b8 * 29) >> 8);
// Combine original alpha with recolored RGB444
pixelPtr[i] = alpha3 | recolors_rgb444[grayVal];
}
}
}
// Function to encode a single 4x4 sub-block (16 pixels) into an 8-byte CMPR block
static void encode_cmpr_sub_block(uint8_t* dst, const uint8_t pixels[16]) {
uint8_t min_val = 255;
uint8_t max_val = 0;
for (int i = 0; i < 16; ++i) {
if (pixels[i] < min_val) min_val = pixels[i];
if (pixels[i] > max_val) max_val = pixels[i];
}
auto intensity_to_rgb565 = [](uint8_t val) -> uint16_t {
uint16_t r5 = val >> 3;
uint16_t g6 = val >> 2;
uint16_t b5 = val >> 3;
return static_cast<uint16_t>((r5 << 11) | (g6 << 5) | b5);
};
uint16_t c0_565 = intensity_to_rgb565(max_val);
uint16_t c1_565 = intensity_to_rgb565(min_val);
uint32_t indices = 0;
if (max_val > min_val) {
// Enforce c0_565 > c1_565 in unsigned 16-bit representation to use 4-color mode
if (c0_565 == c1_565) {
if ((c0_565 & 0x001F) < 0x001F) {
c0_565 += 1;
} else {
c1_565 -= 1;
}
}
// Interpolated 8-bit intensity values for quantization
const int c0 = max_val;
const int c1 = min_val;
const int c2 = (2 * max_val + min_val) / 3;
const int c3 = (max_val + 2 * min_val) / 3;
// Map each pixel to the nearest palette entry
for (int i = 0; i < 16; ++i) {
const int p = pixels[i];
const int d0 = std::abs(p - c0);
const int d1 = std::abs(p - c1);
const int d2 = std::abs(p - c2);
const int d3 = std::abs(p - c3);
uint32_t best_idx = 0;
int min_d = d0;
if (d1 < min_d) { min_d = d1; best_idx = 1; }
if (d2 < min_d) { min_d = d2; best_idx = 2; }
if (d3 < min_d) { min_d = d3; best_idx = 3; }
indices |= (best_idx << (30 - (2 * i)));
}
}
// Account for big endian data expectation
dst[0] = static_cast<uint8_t>(c0_565 >> 8);
dst[1] = static_cast<uint8_t>(c0_565 & 0xFF);
dst[2] = static_cast<uint8_t>(c1_565 >> 8);
dst[3] = static_cast<uint8_t>(c1_565 & 0xFF);
dst[4] = static_cast<uint8_t>(indices >> 24);
dst[5] = static_cast<uint8_t>((indices >> 16) & 0xFF);
dst[6] = static_cast<uint8_t>((indices >> 8) & 0xFF);
dst[7] = static_cast<uint8_t>(indices & 0xFF);
}
bool convert_i8_to_cmpr(TextureReplacementData& replacementData, std::vector<u8>& cmprOut) {
if (cmprOut.empty() || replacementData.key.width % 8 != 0 || replacementData.key.height % 8 != 0) {
return false;
}
const uint8_t mipCount = (replacementData.data.mip_count > 0) ? replacementData.data.mip_count : 1;
uint32_t mipWidth = replacementData.key.width;
uint32_t mipHeight = replacementData.key.height;
const uint8_t* readPtr = cmprOut.data();
uint8_t* writePtr = cmprOut.data();
for (uint8_t mip = 0; mip < mipCount; ++mip) {
const uint32_t paddedWidthI8 = (mipWidth + 7) & ~7;
const uint32_t paddedHeightI8 = (mipHeight + 3) & ~3;
const uint32_t tilesX_I8 = paddedWidthI8 / 8;
const uint32_t paddedWidthCMPR = (mipWidth + 7) & ~7;
const uint32_t paddedHeightCMPR = (mipHeight + 7) & ~7;
const uint32_t blocksX_CMPR = paddedWidthCMPR / 8;
const uint32_t blocksY_CMPR = paddedHeightCMPR / 8;
for (uint32_t by = 0; by < blocksY_CMPR; ++by) {
for (uint32_t bx = 0; bx < blocksX_CMPR; ++bx) {
const uint32_t topTileIdx = (2 * by) * tilesX_I8 + bx;
const uint32_t bottomTileIdx = (2 * by + 1) * tilesX_I8 + bx;
const uint8_t* topTileData = readPtr + (topTileIdx * 32);
const uint8_t* bottomTileData = readPtr + (bottomTileIdx * 32);
uint8_t subBlockPixels[4][16];
for (int row = 0; row < 4; ++row) {
for (int col = 0; col < 4; ++col) {
subBlockPixels[0][row * 4 + col] = topTileData[row * 8 + col];
subBlockPixels[1][row * 4 + col] = topTileData[row * 8 + col + 4];
}
}
for (int row = 0; row < 4; ++row) {
for (int col = 0; col < 4; ++col) {
subBlockPixels[2][row * 4 + col] = bottomTileData[row * 8 + col];
subBlockPixels[3][row * 4 + col] = bottomTileData[row * 8 + col + 4];
}
}
// Write 32 bytes of CMPR output into the same buffer
for (const auto& subBlockPixel : subBlockPixels) {
encode_cmpr_sub_block(writePtr, subBlockPixel);
writePtr += 8;
}
}
}
const uint32_t tilesY_I8 = paddedHeightI8 / 4;
readPtr += tilesX_I8 * tilesY_I8 * 32;
mipWidth = std::max(1u, mipWidth >> 1);
mipHeight = std::max(1u, mipHeight >> 1);
}
// Resize for new CMPR image
const size_t finalSize = writePtr - cmprOut.data();
cmprOut.resize(finalSize);
// Update format
replacementData.data.gx_format = GX_TF_CMPR;
return true;
}
void recolor_texture(TextureReplacementData& replacementData, GXColor color, std::vector<u8>& newTextureDataOut) {
switch (replacementData.key.gx_format) {
case GX_TF_CMPR:
recolor_cmpr_texture(replacementData, color, newTextureDataOut);
break;
case GX_TF_RGB5A3:
recolor_rgb5a3_texture(replacementData, color, newTextureDataOut);
break;
case GX_TF_I8:
if (convert_i8_to_cmpr(replacementData, newTextureDataOut)) {
recolor_cmpr_texture(replacementData, color, newTextureDataOut);
} else {
mods::log::debug("Could not convert {} from i8 to cmpr", replacementData.textureName);
}
break;
default:
break;
}
}
std::unordered_map<ConfigVarHandle, std::list<TextureReplacementData>>& get_texture_replacements() {
static std::unordered_map<ConfigVarHandle, std::list<TextureReplacementData>> replacements{};
if (replacements.empty()) {
replacements = {
{get_cvars().herosTunicCapColor, {
{
.arc = "Kmdl",
.modelFileName = "al_head.bmd",
.textureName = "al_cap",
}
}},
{get_cvars().herosTunicTorsoColor, {
{
.arc = "Kmdl",
.modelFileName = "al.bmd",
.textureName = "al_upbody",
}
}},
{get_cvars().herosTunicSkirtColor, {
{
.arc = "Kmdl",
.modelFileName = "al.bmd",
.textureName = "al_lowbody",
}
}},
{get_cvars().zoraArmorCapColor, {
{
.arc = "Zmdl",
.modelFileName = "zl_head.bmd",
.textureName = "zl_cap",
}
}},
{get_cvars().zoraArmorHelmetColor, {
{
.arc = "Zmdl",
.modelFileName = "zl_head.bmd",
.textureName = "zl_helmet",
}
}},
{get_cvars().zoraArmorTorsoColor, {
{
.arc = "Zmdl",
.modelFileName = "zl.bmd",
.textureName = "zl_armor",
},
{
.arc = "Zmdl",
.modelFileName = "zl.bmd",
.textureName = "zl_armL",
}
}},
{get_cvars().zoraArmorScalesColor, {
{
.arc = "Zmdl",
.modelFileName = "zl.bmd",
.textureName = "zl_body",
}
}},
{get_cvars().zoraArmorFlippersColor, {
{
.arc = "Zmdl",
.modelFileName = "zl.bmd",
.textureName = "zl_boots",
}
}},
{get_cvars().woodenSwordColor, {
{
.arc = "Bmdl", // Ordon Clothes Model
.modelFileName = "al_swb.bmd",
.textureName = "al_SWB",
},
{
.arc = "Kmdl", // Hero's Tunic Model
.modelFileName = "al_swb.bmd",
.textureName = "al_SWB",
},
{
.arc = "Zmdl", // Zora Armor Model
.modelFileName = "al_swb.bmd",
.textureName = "al_SWB",
},
{
.arc = "Mmdl", // Magic Armor Model
.modelFileName = "al_swb.bmd",
.textureName = "al_SWB",
},
{
.arc = "O_gD_SWB", // Get Item Model
.modelFileName = "o_gd_al_swb.bmd",
.textureName = "al_SWB",
}
}},
{get_cvars().ordonSwordHandleColor, {
{
.arc = "Alink",
.modelFileName = "al_swa.bmd",
.textureName = "al_SWgripA",
},
{
.arc = "O_gD_SWA", // Get Item Model
.modelFileName = "o_gd_al_swa.bmd",
.textureName = "al_SWgripA",
}
}},
{get_cvars().ordonSwordBladeColor, {
{
.arc = "Alink",
.modelFileName = "al_swa.bmd",
.textureName = "al_SWA",
}
}},
{get_cvars().msHandleColor, {
{
.arc = "Alink",
.modelFileName = "al_swm.bmd",
.textureName = "al_SWgripM",
}
}},
{get_cvars().msBladeColor, {
{
.arc = "Alink",
.modelFileName = "al_swm.bmd",
.textureName = "al_SWM",
}
}},
{get_cvars().boomerangColor, {
{
.arc = "Alink", // Boomerang in Link's hand
.modelFileName = "al_boom.bmd",
.textureName = "L_al_boom00",
},
{
.arc = "E_mk", // Boomerang in Ook's hand
.modelFileName = "bm.bmd",
.textureName = "L_al_boom00",
},
{
.arc = "E_mk", // Boomerang in Ook's hand
.modelFileName = "bm.bmd",
.textureName = "bm_boom",
},
{
.arc = "O_gD_boom", // Get Item Model
.modelFileName = "o_gd_boom.bmd",
.textureName = "L_al_boom00",
}
}},
{get_cvars().ironBootsColor, {
{
.arc = "Bmdl", // Ordon Clothes Model
.modelFileName = "al_bootsh.bmd",
.textureName = "al_bootsH",
},
{
.arc = "Kmdl", // Hero's Tunic Model
.modelFileName = "al_bootsh.bmd",
.textureName = "al_bootsH",
},
{
.arc = "Zmdl", // Zora Armor Model
.modelFileName = "al_bootsh.bmd",
.textureName = "al_bootsH",
},
{
.arc = "Mmdl", // Magic Armor Model
.modelFileName = "al_bootsh.bmd",
.textureName = "al_bootsH",
},
{
.arc = "O_gD_boot", // Get Item Model
.modelFileName = "o_gd_al_bootsh.bmd",
.textureName = "al_bootsH",
}
}},
{get_cvars().spinnerColor, {
{
.arc = "Alink", // Spinner used by Link
.modelFileName = "al_sp.bmd",
.textureName = "al_SP",
},
{
.arc = "O_gD_SP", // Get Item Model
.modelFileName = "o_gd_al_sp.bmd",
.textureName = "al_SP",
}
}},
{get_cvars().linkHairColor, {
{
.arc = "Bmdl", // Ordon Clothes Model
.modelFileName = "bl_head.bmd",
.textureName = "bl_hair",
},
{
.arc = "Kmdl", // Hero's Tunic Model
.modelFileName = "al_head.bmd",
.textureName = "al_hair",
},
{
.arc = "Mmdl", // Magic Armor Model
.modelFileName = "ml_head.bmd",
.textureName = "al_hair",
}
}},
{get_cvars().wolfLinkColor, {
{
.arc = "Wmdl",
.modelFileName = "wl.bmd",
.textureName = "wl_body",
},
{
.arc = "Wmdl",
.modelFileName = "wl.bmd",
.textureName = "wl_eye.1",
},
{
.arc = "Wmdl",
.modelFileName = "wl.bmd",
.textureName = "wl_eye.2",
},
{
.arc = "Wmdl",
.modelFileName = "wl.bmd",
.textureName = "wl_eye.3",
},
{
.arc = "Wmdl",
.modelFileName = "wl.bmd",
.textureName = "wl_eye.4",
},
{
.arc = "Wmdl",
.modelFileName = "wl.bmd",
.textureName = "wl_eye.5",
}
}},
{get_cvars().eponaColor, {
{
.arc = "Horse",
.modelFileName = "hs.bmd",
.textureName = "hs_body",
},
{
.arc = "Horse",
.modelFileName = "hs.bmd",
.textureName = "hs_eye.1",
},
{
.arc = "Horse",
.modelFileName = "hs.bmd",
.textureName = "hs_eye.2",
},
{
.arc = "Horse",
.modelFileName = "hs.bmd",
.textureName = "hs_eye.3",
},
}},
};
}
return replacements;
}
@@ -0,0 +1,19 @@
#pragma once
/**
* File originally copied from console TPR with permission from isaac
* https://github.com/zsrtp/libtp_rel/blob/master/include/util/texture_utils.h
*/
#include "mod.hpp"
#include <gx.h>
#include <list>
#include <unordered_map>
uint32_t get_image_data_size(uint32_t format, uint32_t width, uint32_t height, uint32_t mipmapCount);
void recolor_texture(TextureReplacementData& replacementData, GXColor color, std::vector<u8>& newTextureDataOut);
std::unordered_map<ConfigVarHandle, std::list<TextureReplacementData>>& get_texture_replacements();
+12 -14
View File
@@ -1,6 +1,6 @@
# Android Shell # Android Shell
This directory contains a minimal SDLActivity-based Android app wrapper for Dusklight. This directory contains Dusklight's Android shell built on top of Borealis.
## Prerequisites ## Prerequisites
@@ -25,24 +25,19 @@ cmake --build --preset android-arm64
This build produces `build/android-arm64/libmain.so` This build produces `build/android-arm64/libmain.so`
## Refresh SDL Java Shim (Optional)
If you update SDL and want to refresh the embedded Java shim files:
```bash
./android/scripts/sync-sdl-java.sh
```
## Build APK ## Build APK
```bash ```bash
cd android cd platforms/android
./gradlew :app:assembleDebug ./gradlew :app:assembleDebug
``` ```
Output APK: Output APK:
- `android/app/build/outputs/apk/debug/app-debug.apk` - `app/build/outputs/apk/debug/app-arm64-v8a-debug.apk`
Aurora needs a hardware-backed graphics adapter. If an AVD has GPU
acceleration disabled, launch it with `-gpu host`.
## Launch With Runtime Args (adb) ## Launch With Runtime Args (adb)
@@ -50,10 +45,13 @@ You can pass command-line args through the activity intent:
```bash ```bash
adb shell am start -n dev.twilitrealm.dusk/.DuskActivity \ adb shell am start -n dev.twilitrealm.dusk/.DuskActivity \
--es dusk_args "--backend vulkan" --es borealis_args "--backend vulkan"
``` ```
Supported extras: Supported extras:
- `dusk_args`: single shell-like argument string - `borealis_args`: single shell-like argument string
- `dusk_argv`: string-array argv - `borealis_argv`: string-array argv
The legacy `dusk_args` and `dusk_argv` names remain accepted during the shell
transition.

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