mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-15 20:15:32 -04:00
Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| af17623e69 | |||
| c01610dc37 | |||
| f4700c9636 | |||
| 5d01c93839 | |||
| 0c546819f4 | |||
| 094f0cd78d | |||
| c251aba39d | |||
| c722cb1be0 | |||
| 0f5a248401 | |||
| 045fbd9b46 | |||
| 46da33be37 | |||
| 008a18c142 | |||
| 5b4def820a | |||
| 635901d3bd | |||
| 5abc956448 | |||
| 0c3bbbaba0 | |||
| 0fc05028cc | |||
| 71b2eedc82 | |||
| 0da58ac91d | |||
| c29cafa8a2 | |||
| 5e669c8f0f | |||
| 3e625cf006 | |||
| c6f497b525 | |||
| 79d3c7c76a | |||
| 16dd1118d1 | |||
| e9918cc8ed | |||
| 058304dc26 | |||
| d55b44b5a5 | |||
| 7434a0f834 | |||
| 469575fd65 | |||
| 4883c11182 | |||
| 7ac2340312 | |||
| 3352ea3dde | |||
| 82e2fd4bea | |||
| fcd9dd0f70 | |||
| 8afe479d0f | |||
| c5933be631 | |||
| 928e9b4bc7 | |||
| 3ac0fcb156 | |||
| 6481d12a3d | |||
| 2c7ab755a0 | |||
| cf8ab52f55 | |||
| 960d016113 | |||
| 13b3b68fe5 | |||
| 4604304305 | |||
| 794bb130e2 | |||
| e02251a669 | |||
| 2c9f814ec6 | |||
| 76079b6294 | |||
| 519305b7d4 |
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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.
|
||||||
|
|||||||
Vendored
+1
-1
Submodule extern/aurora updated: 0bddb86249...1f84646de4
+1
Submodule extern/borealis added at 6fd955e7e6
+13
-18
@@ -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
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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*);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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] = {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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*);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,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,
|
||||||
|
|||||||
@@ -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,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)));
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -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);
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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 ¤tMidnaHairColors.l_normalColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GXColor* get_midna_hair_normalKColor() {
|
||||||
|
return ¤tMidnaHairColors.l_normalKColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GXColor* get_midna_hair_normalKColor2() {
|
||||||
|
return ¤tMidnaHairColors.l_normalKColor2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GXColorS10* get_midna_hair_bigColor() {
|
||||||
|
return ¤tMidnaHairColors.l_bigColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GXColor* get_midna_hair_bigKColor() {
|
||||||
|
return ¤tMidnaHairColors.l_bigKColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GXColor* get_midna_hair_lNormalKColor() {
|
||||||
|
return ¤tMidnaHairColors.l_lNormalKColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GXColor* get_midna_hair_lNormalKColor2() {
|
||||||
|
return ¤tMidnaHairColors.l_lNormalKColor2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GXColorS10* get_midna_hair_lBigColor() {
|
||||||
|
return ¤tMidnaHairColors.l_lBigColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GXColor* get_midna_hair_lBigKColor2() {
|
||||||
|
return ¤tMidnaHairColors.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();
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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
@@ -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
Reference in New Issue
Block a user