mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-25 14:45:45 -04:00
Compare commits
213 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f0d89473a | |||
| adaa52aa9d | |||
| 3dd9430576 | |||
| 6facff1297 | |||
| ba324dfdf6 | |||
| a775418c66 | |||
| 48b5c2e8c1 | |||
| 705e7f058b | |||
| e30e0fe062 | |||
| c4f4712d0e | |||
| 2d70c24b37 | |||
| 72ccb14d35 | |||
| c53f3f774b | |||
| 5a8622c6b2 | |||
| 29b86f938f | |||
| e02638ac6d | |||
| 622b782614 | |||
| 9a4b1edfe5 | |||
| 1db2a74192 | |||
| 595c621173 | |||
| ba95fdd4ab | |||
| a39c272985 | |||
| f3bbde4b7d | |||
| 46a2ac2c46 | |||
| 2885c7d9d8 | |||
| 19b8f7ede0 | |||
| b138735cbe | |||
| 1a6775eab1 | |||
| dd5da64332 | |||
| d281c34a65 | |||
| a6813841b8 | |||
| 39a84e67b7 | |||
| 788700daa6 | |||
| 3aa54ca170 | |||
| 81dfe701e9 | |||
| 16f2b954fa | |||
| a8a7513710 | |||
| 797d264a71 | |||
| c0293b1f52 | |||
| a9ea8aa935 | |||
| 7240c19566 | |||
| dbc56da290 | |||
| 41d5148793 | |||
| 14f9b6c762 | |||
| 44e02a9d53 | |||
| 63d431d058 | |||
| 87d96c2696 | |||
| 8f5ecdba1c | |||
| 42805210df | |||
| df522f1abb | |||
| c475d72110 | |||
| 3606ec64e3 | |||
| 1b51fa0112 | |||
| 1e8d72c3ed | |||
| 28479314c2 | |||
| 89a8384c7c | |||
| d9cac5befa | |||
| 3cd1f46e7b | |||
| 0b26cee96d | |||
| 42bba9c9a8 | |||
| 3869ac6423 | |||
| 54bed771ee | |||
| 83b10681c3 | |||
| 641855e49e | |||
| 9977e78758 | |||
| 9a62d8c86f | |||
| 2cee0db91f | |||
| 932c3aaba7 | |||
| 5d1dda7e94 | |||
| 75ae2767e9 | |||
| 829b0de69c | |||
| 5f0f3d4ebe | |||
| 283b3704bb | |||
| 6cc22e71a9 | |||
| 54ecdfe4d3 | |||
| 618eb90392 | |||
| 72ea47b973 | |||
| 172d06f38d | |||
| 338995ebe0 | |||
| b5724fb6fd | |||
| 05a1fe4485 | |||
| 6f06a33926 | |||
| 4d5fc47252 | |||
| 97d742a96a | |||
| 80c93957e9 | |||
| dc716329d8 | |||
| 62bf0fbeb1 | |||
| ce4682fd89 | |||
| acc8cc2e6d | |||
| c86d6918d6 | |||
| 5a4e6f3254 | |||
| 5d5c3d5c5f | |||
| 386d2f964b | |||
| 04b915d8c7 | |||
| fd4a5f0cfb | |||
| 33abcbfbe1 | |||
| 3ecd785ac2 | |||
| fd0e33460f | |||
| 6f840b050e | |||
| 88c6e28179 | |||
| f13f0319ec | |||
| 06735d1369 | |||
| 8525b0b40c | |||
| e40506dfeb | |||
| ff3dbfa8d5 | |||
| 5456d98fde | |||
| 2f0cb26ceb | |||
| 21bc055552 | |||
| 3a2dbf9fba | |||
| 2d1487aefd | |||
| f6b7448de3 | |||
| edfb93440c | |||
| f4f564b1b1 | |||
| 4ba25932de | |||
| d4868ea81a | |||
| cd6c82d0ff | |||
| 355ea73510 | |||
| c0d44d4a21 | |||
| f0f7031b3d | |||
| 85c2ddd8ff | |||
| de7f09a6a4 | |||
| 7129605035 | |||
| 0c09d71c0a | |||
| 947fb5b5a5 | |||
| 4c673eb04b | |||
| 9090ee80ab | |||
| 8953532fe7 | |||
| f1dc848ea5 | |||
| 548c843a9b | |||
| 34a753ed85 | |||
| 08e51f83f3 | |||
| b4ba0b5755 | |||
| 7c4338d7b3 | |||
| 85a1a2901c | |||
| a13932e901 | |||
| c880d46fb5 | |||
| 27d27e6d94 | |||
| ac45cac56e | |||
| 9d38af22ee | |||
| 7cac8284d7 | |||
| aa3db8f949 | |||
| 9f7360b359 | |||
| d319bb1049 | |||
| 1f43e16e2d | |||
| 2a67d6800e | |||
| 4cbb8762f6 | |||
| c722cb1be0 | |||
| c2dbdd385d | |||
| 9c52a059bd | |||
| 33a9db2e49 | |||
| e5a4323056 | |||
| 08cda98337 | |||
| b0d4c62903 | |||
| a2cd701203 | |||
| 0f5a248401 | |||
| 045fbd9b46 | |||
| 46da33be37 | |||
| 8143de6bbb | |||
| 162829a8cf | |||
| c65b8a42b8 | |||
| abbcb5a6b9 | |||
| 8229879aab | |||
| 11055282ff | |||
| 839d8fdb63 | |||
| 008a18c142 | |||
| 5b4def820a | |||
| 635901d3bd | |||
| 5abc956448 | |||
| 5830c41547 | |||
| 0c3bbbaba0 | |||
| 1e39c5e1be | |||
| 2f1375297a | |||
| 71b2eedc82 | |||
| 315897e45a | |||
| 25a736b9dc | |||
| a8089f1204 | |||
| 1f28fd1ca5 | |||
| e16c05211b | |||
| 8be95d3aa3 | |||
| ce6850acd3 | |||
| 4aa3b647a3 | |||
| a9767ad3e8 | |||
| 2f4d8a06d8 | |||
| 769f83db25 | |||
| 48cf860467 | |||
| cb564f7465 | |||
| cd2ed2843c | |||
| c853934a24 | |||
| 8c4ad273b8 | |||
| 2a0cd87246 | |||
| 8d677bf517 | |||
| 3160d1c370 | |||
| 0ed984a863 | |||
| 027e23d2e7 | |||
| 105413360e | |||
| d82cb08353 | |||
| 572e9633ab | |||
| 67a511a131 | |||
| 0ff615f991 | |||
| 2191b38c1d | |||
| 36d31e2bb8 | |||
| 2b489e1a7d | |||
| e93a720d8f | |||
| 66f6942dbb | |||
| 631cb99208 | |||
| a53b363905 | |||
| fae9add351 | |||
| f22bfcd9ba | |||
| 9c2e0e9331 | |||
| ecbec503dc | |||
| 91c6c5c137 | |||
| 449a8408ab | |||
| 61a4ab3117 |
@@ -68,13 +68,18 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
|
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
id: game-region
|
id: game-disc
|
||||||
attributes:
|
attributes:
|
||||||
label: Game Region
|
label: Game Disc
|
||||||
description: The game region you are playing on
|
description: The game disc you are playing on
|
||||||
options:
|
options:
|
||||||
- NTSC-U (North America)
|
- GameCube NTSC-U (North America)
|
||||||
- PAL (Europe)
|
- GameCube PAL (Europe)
|
||||||
|
- GameCube NTSC-J (Japan)
|
||||||
|
- Wii NTSC-U (North America) Revision 0
|
||||||
|
- Wii NTSC-U (North America) Revision 2
|
||||||
|
- Wii PAL (Europe)
|
||||||
|
- Wii NTSC-J (Japan)
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[submodule "extern/aurora"]
|
[submodule "extern/aurora"]
|
||||||
path = extern/aurora
|
path = extern/aurora
|
||||||
url = https://github.com/Lurs/aurora.git
|
url = https://github.com/encounter/aurora.git
|
||||||
[submodule "extern/borealis"]
|
[submodule "extern/borealis"]
|
||||||
path = extern/borealis
|
path = extern/borealis
|
||||||
url = https://github.com/encounter/borealis.git
|
url = https://github.com/encounter/borealis.git
|
||||||
|
|||||||
+48
-5
@@ -305,7 +305,7 @@ 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 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
|
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 ZLIB::ZLIB)
|
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 ()
|
||||||
@@ -411,7 +411,47 @@ if (DUSK_ENABLE_CODE_MODS)
|
|||||||
setup_symbol_manifest(dusklight)
|
setup_symbol_manifest(dusklight)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Hook reliability: guaranteed patchable entries on the game ABI surface, and no identical-code folding.
|
# Hook reliability: prevent auto-inlining, guarantee patchable function entries,
|
||||||
|
# and disable identical-code folding for game functions.
|
||||||
|
set(DUSK_GAME_ABI_INLINE_OPTIONS)
|
||||||
|
if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
|
||||||
|
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
list(APPEND DUSK_GAME_ABI_INLINE_OPTIONS
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:-finline-hint-functions>)
|
||||||
|
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
list(APPEND DUSK_GAME_ABI_INLINE_OPTIONS
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:-flive-patching=inline-clone>
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:-fno-inline-functions>
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:-fno-inline-small-functions>
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:-fno-inline-functions-called-once>
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:-fno-early-inlining>
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:-fno-ipa-cp>
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:-fno-ipa-cp-clone>
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:-fno-ipa-sra>
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:-fno-partial-inlining>)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DUSK_GAME_ABI_INLINE_OPTIONS)
|
||||||
|
set(_game_abi_files ${GAME_BASE_FILES} ${GAME_DEBUG_FILES})
|
||||||
|
list(FILTER _game_abi_files EXCLUDE REGEX "^src/dusk/")
|
||||||
|
set_property(SOURCE ${_game_abi_files} APPEND PROPERTY
|
||||||
|
COMPILE_OPTIONS ${DUSK_GAME_ABI_INLINE_OPTIONS})
|
||||||
|
|
||||||
|
foreach(jsystem_lib IN LISTS JSYSTEM_LIBRARIES)
|
||||||
|
target_compile_options(${jsystem_lib} PRIVATE ${DUSK_GAME_ABI_INLINE_OPTIONS})
|
||||||
|
endforeach()
|
||||||
|
foreach(_sdk_lib aurora_card aurora_core aurora_dvd aurora_gd aurora_gx aurora_mtx
|
||||||
|
aurora_os aurora_pad aurora_si aurora_vi)
|
||||||
|
if (TARGET ${_sdk_lib})
|
||||||
|
get_target_property(_sdk_lib_imported ${_sdk_lib} IMPORTED)
|
||||||
|
if (NOT _sdk_lib_imported)
|
||||||
|
target_compile_options(${_sdk_lib} PRIVATE ${DUSK_GAME_ABI_INLINE_OPTIONS})
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
set(DUSK_PATCHABLE_ENTRY_FLAG $<$<COMPILE_LANGUAGE:C,CXX>:/hotpatch>)
|
set(DUSK_PATCHABLE_ENTRY_FLAG $<$<COMPILE_LANGUAGE:C,CXX>:/hotpatch>)
|
||||||
@@ -421,11 +461,11 @@ if (MSVC)
|
|||||||
else ()
|
else ()
|
||||||
target_link_options(dusklight PRIVATE /FUNCTIONPADMIN /OPT:NOICF)
|
target_link_options(dusklight PRIVATE /FUNCTIONPADMIN /OPT:NOICF)
|
||||||
endif ()
|
endif ()
|
||||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "^(AppleClang|Clang)$")
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES "^(AppleClang|Clang|GNU)$")
|
||||||
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" OR CMAKE_OSX_ARCHITECTURES MATCHES "arm64")
|
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)$" OR CMAKE_OSX_ARCHITECTURES MATCHES "arm64")
|
||||||
set(DUSK_PATCHABLE_ENTRY_FLAG $<$<COMPILE_LANGUAGE:C,CXX>:-fpatchable-function-entry=2,1>)
|
set(DUSK_PATCHABLE_ENTRY_FLAG $<$<COMPILE_LANGUAGE:C,CXX>:-fpatchable-function-entry=2,1>)
|
||||||
else ()
|
else ()
|
||||||
set(DUSK_PATCHABLE_ENTRY_FLAG $<$<COMPILE_LANGUAGE:C,CXX>:-fpatchable-function-entry=10,5>)
|
set(DUSK_PATCHABLE_ENTRY_FLAG $<$<COMPILE_LANGUAGE:C,CXX>:-fpatchable-function-entry=10,4>)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
@@ -519,6 +559,9 @@ 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/flow_demo)
|
||||||
|
add_subdirectory(mods/basic_cosmetics_mod)
|
||||||
|
add_subdirectory(mods/randomizer)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
|||||||
@@ -26,7 +26,10 @@ It aims to be as accurate as possible to the original while also providing new o
|
|||||||
|
|
||||||
You must dump your own copy of the game. Please see [this article](https://wiki.dolphin-emu.org/index.php?title=Ripping_Games) for instructions. After dumping, you can use a program like [Dolphin](https://dolphin-emu.org/) or [nodtool](https://github.com/encounter/nod/releases) to convert the `.iso` to `.rvz` to save space.
|
You must dump your own copy of the game. Please see [this article](https://wiki.dolphin-emu.org/index.php?title=Ripping_Games) for instructions. After dumping, you can use a program like [Dolphin](https://dolphin-emu.org/) or [nodtool](https://github.com/encounter/nod/releases) to convert the `.iso` to `.rvz` to save space.
|
||||||
|
|
||||||
Currently, only the GameCube releases are supported. Support for other versions of the game is planned in the future.
|
Dusklight currently supports all commercial discs except for Wii's Korean release.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Dusklight is based on the [Twilight Princess decompilation](https://github.com/zeldaret/tp), which is currently only matching for GameCube. As a result, even when playing Dusklight with a Wii disc, you will be presented with the GameCube version's HUD and certain other specificities.
|
||||||
|
|
||||||
### 2. Install Dusklight
|
### 2. Install Dusklight
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ include_guard(GLOBAL)
|
|||||||
get_filename_component(_game_root "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
|
get_filename_component(_game_root "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
|
||||||
|
|
||||||
# PARTIAL_DEBUG makes debug and release share one struct/vtable ABI so a mod binary loads into either
|
# PARTIAL_DEBUG makes debug and release share one struct/vtable ABI so a mod binary loads into either
|
||||||
set(_game_compile_defs TARGET_PC=1 WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0 MTX_USE_PS=1 PARTIAL_DEBUG=1 DUSK_TPHD=1)
|
set(_game_compile_defs TARGET_PC=1 WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0 MTX_USE_PS=1 PARTIAL_DEBUG=1)
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
list(APPEND _game_compile_defs TARGET_ANDROID=1)
|
list(APPEND _game_compile_defs TARGET_ANDROID=1)
|
||||||
endif ()
|
endif ()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ include_guard(GLOBAL)
|
|||||||
|
|
||||||
get_filename_component(_SYMBOL_MANIFEST_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
|
get_filename_component(_SYMBOL_MANIFEST_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
|
||||||
|
|
||||||
set(_SYMGEN_VERSION "1.3.2")
|
set(_SYMGEN_VERSION "1.3.3")
|
||||||
set(_SYMGEN_RELEASE_BASE_URL "https://github.com/encounter/symgen/releases/download/v${_SYMGEN_VERSION}")
|
set(_SYMGEN_RELEASE_BASE_URL "https://github.com/encounter/symgen/releases/download/v${_SYMGEN_VERSION}")
|
||||||
set(SYMGEN_PATH "" CACHE FILEPATH "Path to a symgen executable; empty downloads the pinned release")
|
set(SYMGEN_PATH "" CACHE FILEPATH "Path to a symgen executable; empty downloads the pinned release")
|
||||||
mark_as_advanced(SYMGEN_PATH)
|
mark_as_advanced(SYMGEN_PATH)
|
||||||
@@ -15,32 +15,32 @@ function(symgen_host_asset out_name out_hash)
|
|||||||
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
if (_host_processor MATCHES "^(arm64|aarch64)$")
|
if (_host_processor MATCHES "^(arm64|aarch64)$")
|
||||||
set(_asset "symgen-macos-arm64")
|
set(_asset "symgen-macos-arm64")
|
||||||
set(_asset_hash "SHA256=0344838d1674df09c17c3eeddcf26eb89c333fdb85dfd78f68adc436070eccbe")
|
set(_asset_hash "SHA256=e8420df1160242c83bd0e5197efeeb25ceb9fecc69dbc82bdc4927476381e948")
|
||||||
elseif (_host_processor MATCHES "^(x86_64|amd64)$")
|
elseif (_host_processor MATCHES "^(x86_64|amd64)$")
|
||||||
set(_asset "symgen-macos-x86_64")
|
set(_asset "symgen-macos-x86_64")
|
||||||
set(_asset_hash "SHA256=ae0674f4a1e9d0dedfa02d35939ac28cdd229276b331c1f507df5df809cbec7e")
|
set(_asset_hash "SHA256=e51d13bbf0e982d1519f56850ff3c7b5910ca5a7095dd5a82cd8e59750e2d013")
|
||||||
endif ()
|
endif ()
|
||||||
elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
|
elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
|
||||||
if (_host_processor MATCHES "^(aarch64|arm64)$")
|
if (_host_processor MATCHES "^(aarch64|arm64)$")
|
||||||
set(_asset "symgen-linux-aarch64")
|
set(_asset "symgen-linux-aarch64")
|
||||||
set(_asset_hash "SHA256=af766de2bfaeb0a06f6d7bc17bb2510b4a9c40f44a56e49bc4a4b798a6223042")
|
set(_asset_hash "SHA256=331190dd21ecee12a52e857b7f90a8b3e0a114608173813f7df74a31cf783f70")
|
||||||
elseif (_host_processor MATCHES "^(x86_64|amd64)$")
|
elseif (_host_processor MATCHES "^(x86_64|amd64)$")
|
||||||
set(_asset "symgen-linux-x86_64")
|
set(_asset "symgen-linux-x86_64")
|
||||||
set(_asset_hash "SHA256=ebd62fb9623acc942b6295609e2306f85a73043b0a8a117f2072b761dd08e68f")
|
set(_asset_hash "SHA256=d727e0ba43242f92a92865af1b69c47aa9d81a0242c4570ce53b90e1ecd15e84")
|
||||||
elseif (_host_processor MATCHES "^(i[3-6]86|x86)$")
|
elseif (_host_processor MATCHES "^(i[3-6]86|x86)$")
|
||||||
set(_asset "symgen-linux-i686")
|
set(_asset "symgen-linux-i686")
|
||||||
set(_asset_hash "SHA256=07780a4513fd29726578efc4ff2d88736b22f407ed821b32a68e35ff1e9af5f4")
|
set(_asset_hash "SHA256=0c9f94d36b7fa46d15a199c9d0f1a633b73eb7d9c02621a6a76a676b83a135c7")
|
||||||
endif ()
|
endif ()
|
||||||
elseif (CMAKE_HOST_WIN32)
|
elseif (CMAKE_HOST_WIN32)
|
||||||
if (_host_processor MATCHES "^(arm64|aarch64)$")
|
if (_host_processor MATCHES "^(arm64|aarch64)$")
|
||||||
set(_asset "symgen-windows-arm64.exe")
|
set(_asset "symgen-windows-arm64.exe")
|
||||||
set(_asset_hash "SHA256=5bb22b4a4a9b5ad45646af411bfb09b8321a732ff3a077eb4c9de1feaef27d2b")
|
set(_asset_hash "SHA256=c699192957e2086ed68912ed39fa77858e1ae894476ab8b557711804cf2aa7cb")
|
||||||
elseif (_host_processor MATCHES "^(x86_64|amd64)$")
|
elseif (_host_processor MATCHES "^(x86_64|amd64)$")
|
||||||
set(_asset "symgen-windows-x86_64.exe")
|
set(_asset "symgen-windows-x86_64.exe")
|
||||||
set(_asset_hash "SHA256=1d1ac087f991a96932d108969e15998becfec643e88f3e7d182ca97ebfc6a46f")
|
set(_asset_hash "SHA256=6d56a45617c75065ab7a3192d09ca52ff735baf5637b0899f446138d46acc310")
|
||||||
elseif (_host_processor MATCHES "^(i[3-6]86|x86)$")
|
elseif (_host_processor MATCHES "^(i[3-6]86|x86)$")
|
||||||
set(_asset "symgen-windows-x86.exe")
|
set(_asset "symgen-windows-x86.exe")
|
||||||
set(_asset_hash "SHA256=c113f4cd05f813efe2b1878dbfcf44d6302aee3974271736e0036430b0cced78")
|
set(_asset_hash "SHA256=6cccc3a8d29e7525a4d1ade1dc4d89327b7c3002a604ab1c7decb43eea6fd4ab")
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,13 @@
|
|||||||
- A Windows, Linux, or macOS device
|
- A Windows, Linux, or macOS device
|
||||||
- iOS device connected to computer via USB
|
- iOS device connected to computer via USB
|
||||||
- Dusklight IPA file (download the latest `Dusklight-vX.X.X-ios-arm64.ipa` from the [releases page](https://github.com/TwilitRealm/dusklight/releases))
|
- Dusklight IPA file (download the latest `Dusklight-vX.X.X-ios-arm64.ipa` from the [releases page](https://github.com/TwilitRealm/dusklight/releases))
|
||||||
- Legally acquired game disc - `GZ2E01` (Gamecube USA) or `GZ2PE01` (Gamecube PAL)
|
- Legally acquired game disc:
|
||||||
|
- `GZ2E01` (GameCube USA)
|
||||||
|
- `GZ2P01` (GameCube PAL)
|
||||||
|
- `GZ2J01` (GameCube JPN)
|
||||||
|
- `RZDE01` (Wii USA Rev. 0 *or* Rev. 2)
|
||||||
|
- `RZDP01` (Wii PAL)
|
||||||
|
- `RZDJ01` (Wii JPN)
|
||||||
|
|
||||||
## 1. Install iloader
|
## 1. Install iloader
|
||||||
|
|
||||||
|
|||||||
+213
-11
@@ -262,14 +262,16 @@ Installs hooks on game functions and resolves symbols by name. You'll rarely cal
|
|||||||
### OverlayService (`mods/svc/overlay.h`)
|
### OverlayService (`mods/svc/overlay.h`)
|
||||||
|
|
||||||
Registers DVD file overlays at runtime: the dynamic counterpart to the static `overlay/` directory (see
|
Registers DVD file overlays at runtime: the dynamic counterpart to the static `overlay/` directory (see
|
||||||
[Asset Overlays](#asset-overlays)). Overlay a disc path with a file from your bundle, or with a caller-owned buffer
|
[Asset Overlays](#asset-overlays)). Overlay a disc path with a file from your bundle, a file within an archive,
|
||||||
|
or with a caller-owned buffer
|
||||||
(copied on registration):
|
(copied on registration):
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
IMPORT_SERVICE(OverlayService, svc_overlay);
|
IMPORT_SERVICE(OverlayService, svc_overlay);
|
||||||
|
|
||||||
OverlayHandle handle = 0;
|
OverlayHandle handle = 0;
|
||||||
svc_overlay->add_file(mod_ctx, "/res/Msgus.arc", "res/replacement.arc", &handle);
|
svc_overlay->add_file(mod_ctx, "/Movie/demo_movie98_00.thp", "res/replacement.thp", &handle); // Replaces the demo movie
|
||||||
|
svc_overlay->add_file(mod_ctx, "/res/Object/Kmdl/archive/bmwr/al.bmd", "res/link_model.bmd", &handle); // Replaces link's model
|
||||||
svc_overlay->add_buffer(mod_ctx, "/generated.txt", data, size, nullptr);
|
svc_overlay->add_buffer(mod_ctx, "/generated.txt", data, size, nullptr);
|
||||||
svc_overlay->remove(mod_ctx, handle);
|
svc_overlay->remove(mod_ctx, handle);
|
||||||
```
|
```
|
||||||
@@ -278,6 +280,9 @@ svc_overlay->remove(mod_ctx, handle);
|
|||||||
on the disc are added as new files. Changes are applied at the next frame boundary, and data the game already read
|
on the disc are added as new files. Changes are applied at the next frame boundary, and data the game already read
|
||||||
stays in memory until the file is re-read: sometimes a scene reload, and in the worst case, a full restart.
|
stays in memory until the file is re-read: sometimes a scene reload, and in the worst case, a full restart.
|
||||||
|
|
||||||
|
Dusklight reloads core archive files during scene transitions so modifications to Link, Midna or other globally-loaded
|
||||||
|
data get refreshed without a full restart.
|
||||||
|
|
||||||
See [Asset Overlays](#asset-overlays) for priority and conflict handling.
|
See [Asset Overlays](#asset-overlays) for priority and conflict handling.
|
||||||
|
|
||||||
### TextureService (`mods/svc/texture.h`)
|
### TextureService (`mods/svc/texture.h`)
|
||||||
@@ -469,8 +474,8 @@ per-window RCSS. A non-`MOD_OK` result from `build`/`update` fails your mod, as
|
|||||||
callback.
|
callback.
|
||||||
|
|
||||||
**Controls:** `pane_add_control` adds an input row described by a `UiControlDesc`: `UI_CONTROL_BUTTON`,
|
**Controls:** `pane_add_control` adds an input row described by a `UiControlDesc`: `UI_CONTROL_BUTTON`,
|
||||||
`UI_CONTROL_TOGGLE`, `UI_CONTROL_NUMBER`, `UI_CONTROL_STRING`, or `UI_CONTROL_SELECT`. Values bind with callbacks or
|
`UI_CONTROL_GROUP`, `UI_CONTROL_TOGGLE`, `UI_CONTROL_NUMBER`, `UI_CONTROL_STRING`, `UI_CONTROL_SELECT`, or
|
||||||
directly to a config var.
|
`UI_CONTROL_COLOR`. Values bind with callbacks or directly to a config var.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
UiControlDesc control = UI_CONTROL_DESC_INIT;
|
UiControlDesc control = UI_CONTROL_DESC_INIT;
|
||||||
@@ -483,9 +488,56 @@ svc_ui->pane_add_control(mod_ctx, leftPane, &control, nullptr);
|
|||||||
```
|
```
|
||||||
|
|
||||||
`UI_BINDING_CONFIG_VAR` wires persistence, change notifications, and the modified indicator automatically. The var
|
`UI_BINDING_CONFIG_VAR` wires persistence, change notifications, and the modified indicator automatically. The var
|
||||||
type must match the control: `TOGGLE` = bool, `NUMBER` and `SELECT` = int, `STRING` = string. Float vars are not
|
type must match the control: `TOGGLE` = bool, `NUMBER` and `SELECT` = int, `STRING` and `COLOR` = string. Float vars
|
||||||
bindable; use callbacks and convert. `help_rml` and `SELECT` option lists render in a help pane, so `SELECT` controls
|
are not bindable; use callbacks and convert. `help_rml` and `SELECT` option lists render in a help pane, so `SELECT`
|
||||||
are only available inside window tabs.
|
controls are only available inside window tabs.
|
||||||
|
|
||||||
|
`pane_add_group` adds a category button to a window tab's left pane. Focusing the button clears the paired right pane
|
||||||
|
and calls the group's build callback with that pane, which is useful for organizing related controls without adding
|
||||||
|
more tabs.
|
||||||
|
|
||||||
|
**Lists:** `pane_add_list` adds a scrollable virtualized list of items that can be efficiently updated and filtered.
|
||||||
|
Keys must be unique and remain stable across replacements.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
UiListHandle locationList = 0;
|
||||||
|
|
||||||
|
void replace_locations(std::string_view query) {
|
||||||
|
std::vector<UiListItem> items;
|
||||||
|
for (uint64_t i = 0; i < locations.size(); ++i) {
|
||||||
|
if (matches(locations[i], query)) {
|
||||||
|
UiListItem item = UI_LIST_ITEM_INIT;
|
||||||
|
item.key = i;
|
||||||
|
item.label = locations[i].c_str();
|
||||||
|
items.push_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
svc_ui->list_set_items(mod_ctx, locationList, items.data(), items.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_filter(ModContext*, void*, const UiControlValue* value) {
|
||||||
|
replace_locations(value->string_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool location_selected(ModContext*, UiListHandle, uint64_t key, void*) {
|
||||||
|
return selected_locations.contains(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
UiControlDesc filter = UI_CONTROL_DESC_INIT;
|
||||||
|
filter.kind = UI_CONTROL_STRING;
|
||||||
|
filter.label = "Filter";
|
||||||
|
filter.get = get_filter;
|
||||||
|
filter.set = set_filter;
|
||||||
|
filter.string_set_mode = UI_STRING_SET_ON_CHANGE; /* invoke `set` while typing */
|
||||||
|
svc_ui->pane_add_control(mod_ctx, pane, &filter, nullptr);
|
||||||
|
|
||||||
|
UiListDesc list = UI_LIST_DESC_INIT;
|
||||||
|
/* items may be passed as a part of list creation, or set afterwards */
|
||||||
|
list.on_pressed = location_pressed;
|
||||||
|
list.is_selected = location_selected;
|
||||||
|
svc_ui->pane_add_list(mod_ctx, pane, &list, &locationList);
|
||||||
|
replace_locations(""); /* calls `list_set_items` */
|
||||||
|
```
|
||||||
|
|
||||||
**Windows:** `window_push` pushes a tabbed two-pane window onto the document stack and shows it. Each tab's `build`
|
**Windows:** `window_push` pushes a tabbed two-pane window onto the document stack and shows it. Each tab's `build`
|
||||||
receives the window handle plus fresh left and right pane handles on every activation. The optional per-tab `update`
|
receives the window handle plus fresh left and right pane handles on every activation. The optional per-tab `update`
|
||||||
@@ -507,10 +559,36 @@ svc_ui->window_push(mod_ctx, &desc, &window);
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Dialogs:** `dialog_push` shows a modal dialog. `variant` picks the style, `icon` optionally overrides the variant's
|
**Dialogs:** `dialog_push` shows a modal dialog. `variant` picks the style, `icon` optionally overrides the variant's
|
||||||
default icon, and actions become buttons. After an action's `on_pressed` returns, the dialog closes unless the action
|
default icon, and actions become buttons. The optional `build` callback allows you to add controls to a pane between
|
||||||
sets `keep_open`. A `keep_open` action can close it later (or immediately) with `dialog_close`. Cancel fires
|
the body and actions. It uses the same text, progress, and control builders as panels.
|
||||||
`on_dismiss` if present and always closes. `dialog_set_body`, `dialog_set_icon`, and `dialog_add_action` mutate a live
|
|
||||||
dialog.
|
```cpp
|
||||||
|
ModResult build_dialog(ModContext*, UiElementHandle pane, void*, ModError*) {
|
||||||
|
UiControlDesc input = UI_CONTROL_DESC_INIT;
|
||||||
|
input.kind = UI_CONTROL_STRING;
|
||||||
|
input.label = "Name";
|
||||||
|
input.get = get_name;
|
||||||
|
input.set = set_name;
|
||||||
|
return svc_ui->pane_add_control(mod_ctx, pane, &input, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
UiDialogAction action = UI_DIALOG_ACTION_INIT;
|
||||||
|
action.label = "Save";
|
||||||
|
action.on_pressed = save;
|
||||||
|
action.is_disabled = is_save_disabled;
|
||||||
|
|
||||||
|
UiDialogDesc dialog = UI_DIALOG_DESC_INIT;
|
||||||
|
dialog.title = "New Preset";
|
||||||
|
dialog.body_rml = "Choose a name for the preset.";
|
||||||
|
dialog.actions = &action;
|
||||||
|
dialog.action_count = 1;
|
||||||
|
dialog.build = build_dialog;
|
||||||
|
svc_ui->dialog_push(mod_ctx, &dialog, nullptr);
|
||||||
|
```
|
||||||
|
|
||||||
|
After an action's `on_pressed`, the dialog closes unless the action sets `keep_open`. It can then be closed later
|
||||||
|
(or immediately) with `dialog_close`. Cancel fires `on_dismiss` and always closes. `dialog_set_body` and
|
||||||
|
`dialog_set_icon` mutate a live dialog.
|
||||||
|
|
||||||
**Toasts:** `push_toast` enqueues a notification. Titles and bodies accept RML. The optional `type` is applied as an
|
**Toasts:** `push_toast` enqueues a notification. Titles and bodies accept RML. The optional `type` is applied as an
|
||||||
RCSS class; `warning` uses the built-in warning appearance, and mods can define their own types. A duration of 0 uses
|
RCSS class; `warning` uses the built-in warning appearance, and mods can define their own types. A duration of 0 uses
|
||||||
@@ -636,6 +714,125 @@ first in-game frame. Projection matrices match the renderer's WebGPU clip conven
|
|||||||
Camera operators allow overriding the main camera. When an operator callback returns true, its values replace the camera
|
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`.
|
state for the current frame. Register and unregister using `register_camera_operator` / `unregister_camera_operator`.
|
||||||
|
|
||||||
|
### GameModeService (`mods/svc/game_mode.h`)
|
||||||
|
|
||||||
|
Allows a mod to register a game mode with callbacks for key gameplay and save lifecycle events. Registered game modes
|
||||||
|
appear in the prelaunch menu. Game modes may use a unique set of saves by configuring `save_name`; leave it empty to use
|
||||||
|
the vanilla `gczelda2` save.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
IMPORT_SERVICE(LogService, svc_log);
|
||||||
|
IMPORT_SERVICE(HookService, svc_hook);
|
||||||
|
IMPORT_SERVICE(GameModeService, svc_game_mode);
|
||||||
|
|
||||||
|
DEFINE_HOOK(fopAcM_createItem, CreateItem);
|
||||||
|
|
||||||
|
#define MY_GAME_MODE_ID "game-mode-id"
|
||||||
|
|
||||||
|
static HookAction my_function_hook(ModContext* ctx, void* args, void*, void*) {
|
||||||
|
// If we wish to have this hook only run while the gamemode is registered, we need to hook the function from the
|
||||||
|
// gamemode's onActivatedFunction, and uninstall the hook during the onDeactivatedFunction. Example below.
|
||||||
|
// Alternatively, check with `svc_game_mode->is_active(mod_ctx, MY_GAME_MODE_ID, &active) == MOD_OK && active`.
|
||||||
|
return HOOK_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult on_game_mode_activated(void*, ModError* outError) {
|
||||||
|
// Setup the gamemode, Add any hooks that are gamemode specific
|
||||||
|
// Overlay any files that are gamemode specific
|
||||||
|
ModResult result = mods::hook_add_pre<CreateItem>(svc_hook, my_function_hook);
|
||||||
|
if (result != MOD_OK) {
|
||||||
|
return mods::set_error(outError, result, "failed to install fopAcM_createItem hook");
|
||||||
|
}
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult on_game_mode_deactivated(void*, ModError* outError) {
|
||||||
|
// Uninstall any hooks that are gamemode specific
|
||||||
|
// Remove any file overlays that are gamemode specific
|
||||||
|
ModResult result = mods::hook_uninstall<CreateItem>();
|
||||||
|
if (result != MOD_OK) {
|
||||||
|
return mods::set_error(outError, result, "failed to uninstall fopAcM_createItem hook");
|
||||||
|
}
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult on_save_loaded(void*, ModError*) {
|
||||||
|
// This function will be invoked by the game as a save is loaded
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GameModeDesc gameModeDesc = {
|
||||||
|
.struct_size = sizeof(GameModeDesc),
|
||||||
|
.game_mode_id = MY_GAME_MODE_ID,
|
||||||
|
.full_name = "My Game Mode",
|
||||||
|
.save_name = "my-unique-save",
|
||||||
|
.user_data = nullptr,
|
||||||
|
.on_activated = on_game_mode_activated,
|
||||||
|
.on_deactivated = on_game_mode_deactivated,
|
||||||
|
.on_save_loaded = on_save_loaded,
|
||||||
|
};
|
||||||
|
svc_game_mode->register_game_mode(mod_ctx, &gameModeDesc);
|
||||||
|
```
|
||||||
|
|
||||||
|
A game mode can also open UI for per-save settings when creating a new file. The state begins as
|
||||||
|
`GAME_MODE_STATE_PENDING` and remains valid until the mod selects `PROCEED` or `RETURN`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
IMPORT_SERVICE(GameModeService, svc_game_mode);
|
||||||
|
IMPORT_SERVICE(UiService, svc_ui);
|
||||||
|
|
||||||
|
ModResult on_new_save_select(void*, GameModeNewSaveState* state, ModError* outError) {
|
||||||
|
static GameModeNewSaveState* newSaveState;
|
||||||
|
static UiWindowHandle windowHandle;
|
||||||
|
|
||||||
|
newSaveState = state;
|
||||||
|
|
||||||
|
UiTabDesc tabs[1]{};
|
||||||
|
|
||||||
|
tabs[0].struct_size = sizeof(UiTabDesc);
|
||||||
|
tabs[0].title = "Play";
|
||||||
|
tabs[0].build = [](ModContext* ctx, UiWindowHandle, UiElementHandle leftPane, UiElementHandle rightPane, void*, ModError*) {
|
||||||
|
UiControlDesc desc = UI_CONTROL_DESC_INIT;
|
||||||
|
desc.kind = UI_CONTROL_BUTTON;
|
||||||
|
desc.label = "Play";
|
||||||
|
desc.help_rml = "Play Button";
|
||||||
|
desc.on_pressed = [](ModContext* ctx, void* userdata) {
|
||||||
|
*newSaveState = GAME_MODE_STATE_PROCEED;
|
||||||
|
svc_ui->window_close(ctx, *static_cast<UiWindowHandle*>(userdata));
|
||||||
|
};
|
||||||
|
desc.user_data = &windowHandle;
|
||||||
|
svc_ui->pane_add_control(mod_ctx, leftPane, &desc, nullptr);
|
||||||
|
return MOD_OK;
|
||||||
|
};
|
||||||
|
|
||||||
|
UiWindowDesc desc = UI_WINDOW_DESC_INIT;
|
||||||
|
desc.tabs = tabs;
|
||||||
|
desc.tab_count = 1;
|
||||||
|
desc.on_closed = [](ModContext *, UiWindowHandle, void *userdata) {
|
||||||
|
// If closing the window through backing out, return to file select
|
||||||
|
if (*newSaveState == GAME_MODE_STATE_PENDING) {
|
||||||
|
*newSaveState = GAME_MODE_STATE_RETURN;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ModResult result = svc_ui->window_push(mod_ctx, &desc, &windowHandle);
|
||||||
|
if (result != MOD_OK) {
|
||||||
|
return mods::set_error(outError, result, "failed to open new-save settings");
|
||||||
|
}
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GameModeDesc gameModeDesc = {
|
||||||
|
.struct_size = sizeof(GameModeDesc),
|
||||||
|
.game_mode_id = "my-game-mode-id",
|
||||||
|
.full_name = "My Game Mode",
|
||||||
|
.save_name = "my-unique-save",
|
||||||
|
.on_new_save_select = on_new_save_select,
|
||||||
|
};
|
||||||
|
svc_game_mode->register_game_mode(mod_ctx, &gameModeDesc);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Hooking Game Functions
|
## Hooking Game Functions
|
||||||
@@ -763,6 +960,11 @@ For reference parameters (e.g. `const cXyz& pos`), `arg_ref<cXyz>` yields a dire
|
|||||||
|
|
||||||
Files placed under `overlay/` in the `.dusk` archive override game files at the corresponding path, equivalent to
|
Files placed under `overlay/` in the `.dusk` archive override game files at the corresponding path, equivalent to
|
||||||
replacing files in the .iso. This requires no code: an archive with just `mod.json` and `overlay/` is a complete mod.
|
replacing files in the .iso. This requires no code: an archive with just `mod.json` and `overlay/` is a complete mod.
|
||||||
|
To replace a file within an `.arc` archive, replace the archive suffix with a directory and place the replacement at
|
||||||
|
its path within the archive.
|
||||||
|
|
||||||
|
- `overlay/Audiores/Stream/menu_select.ast` replaces the main title's audio stream.
|
||||||
|
- `overlay/res/Layout/main2D/main2d/timg/midona64.bti` replaces Midna's UI icon inside `main2D.arc`.
|
||||||
|
|
||||||
Files placed under `textures/` register as texture replacements, and act just like the user's general
|
Files placed under `textures/` register as texture replacements, and act just like the user's general
|
||||||
`texture_replacements/` directory: Dolphin-style naming, matched by texture hash
|
`texture_replacements/` directory: Dolphin-style naming, matched by texture hash
|
||||||
|
|||||||
Vendored
+1
-1
Submodule extern/aurora updated: 8bb7159d3e...2c9c95cfed
+22
-10
@@ -1412,6 +1412,7 @@ set(DOLPHIN_FILES
|
|||||||
|
|
||||||
set(DUSK_FILES
|
set(DUSK_FILES
|
||||||
include/helpers/batch.hpp
|
include/helpers/batch.hpp
|
||||||
|
include/helpers/bits.hpp
|
||||||
include/helpers/endian_gx.hpp
|
include/helpers/endian_gx.hpp
|
||||||
src/d/actor/d_a_alink_dusk.cpp
|
src/d/actor/d_a_alink_dusk.cpp
|
||||||
src/dusk/OSContext.cpp
|
src/dusk/OSContext.cpp
|
||||||
@@ -1433,9 +1434,11 @@ set(DUSK_FILES
|
|||||||
src/dusk/extras.c
|
src/dusk/extras.c
|
||||||
src/dusk/frame_interpolation.cpp
|
src/dusk/frame_interpolation.cpp
|
||||||
src/dusk/game_clock.cpp
|
src/dusk/game_clock.cpp
|
||||||
|
src/dusk/game_mode.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/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
|
||||||
@@ -1456,6 +1459,8 @@ set(DUSK_FILES
|
|||||||
src/dusk/imgui/ImGuiStubLog.cpp
|
src/dusk/imgui/ImGuiStubLog.cpp
|
||||||
src/dusk/io.cpp
|
src/dusk/io.cpp
|
||||||
src/dusk/iso_validate.cpp
|
src/dusk/iso_validate.cpp
|
||||||
|
src/dusk/language.cpp
|
||||||
|
src/dusk/language.hpp
|
||||||
src/dusk/layout.cpp
|
src/dusk/layout.cpp
|
||||||
src/dusk/livesplit.cpp
|
src/dusk/livesplit.cpp
|
||||||
src/dusk/logging.cpp
|
src/dusk/logging.cpp
|
||||||
@@ -1472,6 +1477,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
|
||||||
@@ -1481,8 +1489,11 @@ set(DUSK_FILES
|
|||||||
src/dusk/mods/svc/config.hpp
|
src/dusk/mods/svc/config.hpp
|
||||||
src/dusk/mods/svc/game.cpp
|
src/dusk/mods/svc/game.cpp
|
||||||
src/dusk/mods/svc/gfx.cpp
|
src/dusk/mods/svc/gfx.cpp
|
||||||
|
src/dusk/mods/svc/flow.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
|
||||||
@@ -1491,6 +1502,7 @@ set(DUSK_FILES
|
|||||||
src/dusk/mods/svc/texture.cpp
|
src/dusk/mods/svc/texture.cpp
|
||||||
src/dusk/mods/svc/ui.cpp
|
src/dusk/mods/svc/ui.cpp
|
||||||
src/dusk/mods/svc/ui.hpp
|
src/dusk/mods/svc/ui.hpp
|
||||||
|
src/dusk/mods/svc/game_mode.cpp
|
||||||
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.cpp
|
||||||
@@ -1513,6 +1525,8 @@ set(DUSK_FILES
|
|||||||
src/dusk/ui/bool_button.hpp
|
src/dusk/ui/bool_button.hpp
|
||||||
src/dusk/ui/button.cpp
|
src/dusk/ui/button.cpp
|
||||||
src/dusk/ui/button.hpp
|
src/dusk/ui/button.hpp
|
||||||
|
src/dusk/ui/color_input.cpp
|
||||||
|
src/dusk/ui/color_input.hpp
|
||||||
src/dusk/ui/component.cpp
|
src/dusk/ui/component.cpp
|
||||||
src/dusk/ui/component.hpp
|
src/dusk/ui/component.hpp
|
||||||
src/dusk/ui/controller_config.cpp
|
src/dusk/ui/controller_config.cpp
|
||||||
@@ -1526,12 +1540,16 @@ set(DUSK_FILES
|
|||||||
src/dusk/ui/event.hpp
|
src/dusk/ui/event.hpp
|
||||||
src/dusk/ui/graphics_tuner.cpp
|
src/dusk/ui/graphics_tuner.cpp
|
||||||
src/dusk/ui/graphics_tuner.hpp
|
src/dusk/ui/graphics_tuner.hpp
|
||||||
|
src/dusk/ui/group_button.cpp
|
||||||
|
src/dusk/ui/group_button.hpp
|
||||||
src/dusk/ui/icon_provider.cpp
|
src/dusk/ui/icon_provider.cpp
|
||||||
src/dusk/ui/icon_provider.hpp
|
src/dusk/ui/icon_provider.hpp
|
||||||
src/dusk/ui/input.cpp
|
src/dusk/ui/input.cpp
|
||||||
src/dusk/ui/input.hpp
|
src/dusk/ui/input.hpp
|
||||||
src/dusk/ui/logs_window.cpp
|
src/dusk/ui/logs_window.cpp
|
||||||
src/dusk/ui/logs_window.hpp
|
src/dusk/ui/logs_window.hpp
|
||||||
|
src/dusk/ui/list.cpp
|
||||||
|
src/dusk/ui/list.hpp
|
||||||
src/dusk/ui/menu_bar.cpp
|
src/dusk/ui/menu_bar.cpp
|
||||||
src/dusk/ui/menu_bar.hpp
|
src/dusk/ui/menu_bar.hpp
|
||||||
src/dusk/ui/mod_texture_provider.cpp
|
src/dusk/ui/mod_texture_provider.cpp
|
||||||
@@ -1543,12 +1561,16 @@ set(DUSK_FILES
|
|||||||
src/dusk/ui/mods_window.cpp
|
src/dusk/ui/mods_window.cpp
|
||||||
src/dusk/ui/mods_window.hpp
|
src/dusk/ui/mods_window.hpp
|
||||||
src/dusk/ui/nav_types.hpp
|
src/dusk/ui/nav_types.hpp
|
||||||
|
src/dusk/ui/nav_group.cpp
|
||||||
|
src/dusk/ui/nav_group.hpp
|
||||||
src/dusk/ui/number_button.cpp
|
src/dusk/ui/number_button.cpp
|
||||||
src/dusk/ui/number_button.hpp
|
src/dusk/ui/number_button.hpp
|
||||||
src/dusk/ui/overlay.cpp
|
src/dusk/ui/overlay.cpp
|
||||||
src/dusk/ui/overlay.hpp
|
src/dusk/ui/overlay.hpp
|
||||||
src/dusk/ui/pane.cpp
|
src/dusk/ui/pane.cpp
|
||||||
src/dusk/ui/pane.hpp
|
src/dusk/ui/pane.hpp
|
||||||
|
src/dusk/ui/popover.cpp
|
||||||
|
src/dusk/ui/popover.hpp
|
||||||
src/dusk/ui/prelaunch.cpp
|
src/dusk/ui/prelaunch.cpp
|
||||||
src/dusk/ui/prelaunch.hpp
|
src/dusk/ui/prelaunch.hpp
|
||||||
src/dusk/ui/preset.cpp
|
src/dusk/ui/preset.cpp
|
||||||
@@ -1581,14 +1603,4 @@ set(DUSK_FILES
|
|||||||
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
|
||||||
src/dusk/tphd/TphdPack.hpp
|
|
||||||
src/dusk/tphd/TphdPack.cpp
|
|
||||||
src/dusk/tphd/GtxParser.hpp
|
|
||||||
src/dusk/tphd/GtxParser.cpp
|
|
||||||
src/dusk/tphd/AddrLib.hpp
|
|
||||||
src/dusk/tphd/AddrLib.cpp
|
|
||||||
src/dusk/tphd/HdAssetLayer.hpp
|
|
||||||
src/dusk/tphd/HdAssetLayer.cpp
|
|
||||||
src/dusk/tphd/LosTable.hpp
|
|
||||||
src/dusk/tphd/LosTable.cpp
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
s32 getBgmLoadStatus(u32 wave) { return getWaveLoadStatus(wave, 1); }
|
s32 getBgmLoadStatus(u32 wave) { return getWaveLoadStatus(wave, 1); }
|
||||||
u8 getDemoSeWaveNum() { return loadedDemoWave; }
|
u8 getDemoSeWaveNum() { return loadedDemoWave; }
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
/* 0x00 */ JAISoundID BGM_ID;
|
/* 0x00 */ JAISoundID BGM_ID;
|
||||||
/* 0x04 */ int sceneNum;
|
/* 0x04 */ int sceneNum;
|
||||||
/* 0x08 */ int timer;
|
/* 0x08 */ int timer;
|
||||||
@@ -158,10 +158,6 @@ enum Z2Scene {
|
|||||||
/* 0x4E */ Z2SCENE_GROTTO_ROCK_2,
|
/* 0x4E */ Z2SCENE_GROTTO_ROCK_2,
|
||||||
/* 0x4F */ Z2SCENE_GROTTO_POND,
|
/* 0x4F */ Z2SCENE_GROTTO_POND,
|
||||||
/* 0x50 */ Z2SCENE_FARON_WOODS_CAVE,
|
/* 0x50 */ Z2SCENE_FARON_WOODS_CAVE,
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
/* 0x51 */ Z2SCENE_CAVE_OF_SHADOWS,
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* Z2SCENEMGR_H */
|
#endif /* Z2SCENEMGR_H */
|
||||||
|
|||||||
@@ -4560,8 +4560,6 @@ public:
|
|||||||
|
|
||||||
void onIronBallChainInterpCallback();
|
void onIronBallChainInterpCallback();
|
||||||
|
|
||||||
f32 mLosStickValue;
|
|
||||||
|
|
||||||
static const int IRON_BALL_CHAIN_COUNT = 102;
|
static const int IRON_BALL_CHAIN_COUNT = 102;
|
||||||
cXyz mIBChainInterpPrevPos[IRON_BALL_CHAIN_COUNT];
|
cXyz mIBChainInterpPrevPos[IRON_BALL_CHAIN_COUNT];
|
||||||
cXyz mIBChainInterpCurrPos[IRON_BALL_CHAIN_COUNT];
|
cXyz mIBChainInterpCurrPos[IRON_BALL_CHAIN_COUNT];
|
||||||
@@ -8451,8 +8449,10 @@ struct daAlink_cutHorseParamTbl {
|
|||||||
/* 0xA */ u8 m_cutType;
|
/* 0xA */ u8 m_cutType;
|
||||||
}; // Size: 0xC
|
}; // Size: 0xC
|
||||||
|
|
||||||
|
#if !TARGET_PC
|
||||||
inline BOOL dComIfGs_isTransformLV(int i_no);
|
inline BOOL dComIfGs_isTransformLV(int i_no);
|
||||||
inline BOOL dComIfGs_isEventBit(const u16);
|
inline BOOL dComIfGs_isEventBit(const u16);
|
||||||
|
#endif
|
||||||
|
|
||||||
static fopAc_ac_c* daAlink_searchPortal(fopAc_ac_c* i_actor, void* i_data);
|
static fopAc_ac_c* daAlink_searchPortal(fopAc_ac_c* i_actor, void* i_data);
|
||||||
static fopAc_ac_c* daAlink_searchCanoe(fopAc_ac_c* i_actor, void* i_data);
|
static fopAc_ac_c* daAlink_searchCanoe(fopAc_ac_c* i_actor, void* i_data);
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ public:
|
|||||||
bool checkFlag(u16 flag) { return field_0x68e & flag; }
|
bool checkFlag(u16 flag) { return field_0x68e & flag; }
|
||||||
void setAction(u8 action) { mAction = action; }
|
void setAction(u8 action) { mAction = action; }
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
/* 0x56C */ request_of_phase_process_class mPhase1;
|
/* 0x56C */ request_of_phase_process_class mPhase1;
|
||||||
/* 0x574 */ request_of_phase_process_class mPhase2;
|
/* 0x574 */ request_of_phase_process_class mPhase2;
|
||||||
/* 0x57C */ J3DModel* mModel1;
|
/* 0x57C */ J3DModel* mModel1;
|
||||||
|
|||||||
@@ -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 mItemCheckHandled;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC_ASSERT(sizeof(daE_HP_c) == 0xdfc);
|
STATIC_ASSERT(sizeof(daE_HP_c) == 0xdfc);
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ struct daItemBase_data {
|
|||||||
class daItemBase_c : public fopAc_ac_c {
|
class daItemBase_c : public fopAc_ac_c {
|
||||||
public:
|
public:
|
||||||
u8 getItemNo();
|
u8 getItemNo();
|
||||||
|
#if TARGET_PC
|
||||||
|
u8 getDisplayItemNo() const {
|
||||||
|
return mDisplayItemNo != 0xFF ? mDisplayItemNo : m_itemNo;
|
||||||
|
}
|
||||||
|
void setDisplayItemNo(u8 itemNo) { mDisplayItemNo = itemNo; }
|
||||||
|
#endif
|
||||||
void hide();
|
void hide();
|
||||||
void show();
|
void show();
|
||||||
void changeDraw();
|
void changeDraw();
|
||||||
@@ -79,6 +85,9 @@ public:
|
|||||||
/* 0x928 */ s16 m_get_timer;
|
/* 0x928 */ s16 m_get_timer;
|
||||||
/* 0x92A */ u8 m_itemNo;
|
/* 0x92A */ u8 m_itemNo;
|
||||||
/* 0x92B */ u8 field_0x92b;
|
/* 0x92B */ u8 field_0x92b;
|
||||||
|
#if TARGET_PC
|
||||||
|
u8 mDisplayItemNo = 0xFF;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* D_A_D_A_ITEMBASE_H */
|
#endif /* D_A_D_A_ITEMBASE_H */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -18,24 +18,16 @@ public:
|
|||||||
TGXTexObj& getTexObj() { return mTexObj; }
|
TGXTexObj& getTexObj() { return mTexObj; }
|
||||||
cXyz* getQuad() { return mQuad; }
|
cXyz* getQuad() { return mQuad; }
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
// TP HD reflects across N floor quads (F_SP117 room 2 uses 6); GC uses 1.
|
|
||||||
static const int MAX_QUADS = 6;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 0x010 */ TGXTexObj mTexObj;
|
/* 0x010 */ TGXTexObj mTexObj;
|
||||||
/* 0x030 */ u8 mModelCount;
|
/* 0x030 */ u8 mModelCount;
|
||||||
/* 0x034 */ J3DModel* mModels[0x40];
|
/* 0x034 */ J3DModel* mModels[0x40];
|
||||||
/* 0x134 */ cXyz mQuad[DUSK_IF_ELSE(MAX_QUADS*4, 4)];
|
/* 0x134 */ cXyz mQuad[4];
|
||||||
/* 0x164 */ cXyz mMinVal;
|
/* 0x164 */ cXyz mMinVal;
|
||||||
/* 0x170 */ cXyz mMaxVal;
|
/* 0x170 */ cXyz mMaxVal;
|
||||||
/* 0x17C */ cXyz mViewScale;
|
/* 0x17C */ cXyz mViewScale;
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
bool mbReset = false;
|
bool mbReset = false;
|
||||||
bool mbHadEntry = false;
|
bool mbHadEntry = false;
|
||||||
cXyz mQuadBoxMin[MAX_QUADS];
|
|
||||||
cXyz mQuadBoxMax[MAX_QUADS];
|
|
||||||
int mQuadCount = 1;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ public:
|
|||||||
|
|
||||||
static DUSK_GAME_DATA char DUSK_CONST* DUSK_CONST mCutNameList[18];
|
static DUSK_GAME_DATA char DUSK_CONST* DUSK_CONST mCutNameList[18];
|
||||||
static DUSK_GAME_DATA cutFunc DUSK_CONST mCutList[18];
|
static DUSK_GAME_DATA cutFunc DUSK_CONST mCutList[18];
|
||||||
private:
|
// private:
|
||||||
/* 0x0E40 */ NPC_FAIRY_HIO_CLASS* mHIO;
|
/* 0x0E40 */ NPC_FAIRY_HIO_CLASS* mHIO;
|
||||||
/* 0x0E44 */ dCcD_Cyl mCyl;
|
/* 0x0E44 */ dCcD_Cyl mCyl;
|
||||||
/* 0x0F80 */ u8 mType;
|
/* 0x0F80 */ u8 mType;
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ public:
|
|||||||
|
|
||||||
static DUSK_GAME_DATA char DUSK_CONST* DUSK_CONST mCutNameList[10];
|
static DUSK_GAME_DATA char DUSK_CONST* DUSK_CONST mCutNameList[10];
|
||||||
static DUSK_GAME_DATA cutFunc DUSK_CONST mCutList[10];
|
static DUSK_GAME_DATA cutFunc DUSK_CONST mCutList[10];
|
||||||
private:
|
// private:
|
||||||
/* 0x0E40 */ mDoExt_McaMorfSO* mFishModelMorf;
|
/* 0x0E40 */ mDoExt_McaMorfSO* mFishModelMorf;
|
||||||
/* 0x0E44 */ mDoExt_McaMorfSO* mLeafModelMorf;
|
/* 0x0E44 */ mDoExt_McaMorfSO* mLeafModelMorf;
|
||||||
/* 0x0E48 */ NPC_YKM_HIO_CLASS* mpHIO;
|
/* 0x0E48 */ NPC_YKM_HIO_CLASS* mpHIO;
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public:
|
|||||||
static DUSK_GAME_DATA char DUSK_CONST* DUSK_CONST mEvtCutNameList[2];
|
static DUSK_GAME_DATA char DUSK_CONST* DUSK_CONST mEvtCutNameList[2];
|
||||||
static DUSK_GAME_DATA EventFn DUSK_CONST mEvtCutList[2];
|
static DUSK_GAME_DATA EventFn DUSK_CONST mEvtCutList[2];
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
/* 0xB48 */ Z2Creature mCreatureSound;
|
/* 0xB48 */ Z2Creature mCreatureSound;
|
||||||
/* 0xBD8 */ daNpcF_MatAnm_c* mpMatAnm;
|
/* 0xBD8 */ daNpcF_MatAnm_c* mpMatAnm;
|
||||||
/* 0xBDC */ daNpcF_Lookat_c mLookat;
|
/* 0xBDC */ daNpcF_Lookat_c mLookat;
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public:
|
|||||||
void himoCalc();
|
void himoCalc();
|
||||||
void adjustShapeAngle() {}
|
void adjustShapeAngle() {}
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
/* 0x0B48 */ Z2Creature mCreatureSound;
|
/* 0x0B48 */ Z2Creature mCreatureSound;
|
||||||
/* 0x0BD8 */ daNpcF_MatAnm_c* mpMatAnm;
|
/* 0x0BD8 */ daNpcF_MatAnm_c* mpMatAnm;
|
||||||
/* 0x0BDC */ mDoExt_invisibleModel mInvisibleModel;
|
/* 0x0BDC */ mDoExt_invisibleModel mInvisibleModel;
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
bool isFirst() { return fopAcM_GetParamBit(this, 0x1b, 1); }
|
bool isFirst() { return fopAcM_GetParamBit(this, 0x1b, 1); }
|
||||||
void setAction(u8 action) { mAction = action; }
|
void setAction(u8 action) { mAction = action; }
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
/* 0x568 */ request_of_phase_process_class mPhaseReq;
|
/* 0x568 */ request_of_phase_process_class mPhaseReq;
|
||||||
/* 0x570 */ J3DModel* mpModel;
|
/* 0x570 */ J3DModel* mpModel;
|
||||||
/* 0x574 */ mDoExt_btkAnm* mpBtkAnm[2];
|
/* 0x574 */ mDoExt_btkAnm* mpBtkAnm[2];
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
current.pos = new_pos;
|
current.pos = new_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
/* 0x92C */ fpc_ProcID mItemId;
|
/* 0x92C */ fpc_ProcID mItemId;
|
||||||
/* 0x930 */ int mCounter;
|
/* 0x930 */ int mCounter;
|
||||||
/* 0x934 */ u8 mStatus;
|
/* 0x934 */ u8 mStatus;
|
||||||
@@ -88,6 +88,12 @@ 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;
|
||||||
|
bool mGoldenWolfItem;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC_ASSERT(sizeof(daObjLife_c) == 0x9d4);
|
STATIC_ASSERT(sizeof(daObjLife_c) == 0x9d4);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public:
|
|||||||
static DUSK_GAME_DATA daObjMasterSword_Attr_c const mAttr;
|
static DUSK_GAME_DATA daObjMasterSword_Attr_c const mAttr;
|
||||||
static DUSK_GAME_DATA actionFunc ActionTable[];
|
static DUSK_GAME_DATA actionFunc ActionTable[];
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
/* 0x568 */ J3DModel* mpModel;
|
/* 0x568 */ J3DModel* mpModel;
|
||||||
/* 0x56C */ request_of_phase_process_class mPhase;
|
/* 0x56C */ request_of_phase_process_class mPhase;
|
||||||
/* 0x574 */ mDoExt_btkAnm mBtk;
|
/* 0x574 */ mDoExt_btkAnm mBtk;
|
||||||
|
|||||||
@@ -142,12 +142,12 @@ namespace daObjSwpush {
|
|||||||
int Mthd_Execute();
|
int Mthd_Execute();
|
||||||
int Mthd_Draw();
|
int Mthd_Draw();
|
||||||
|
|
||||||
static DUSK_GAME_DATA s16 const M_bmd[DUSK_IF_ELSE(4, 3)];
|
static DUSK_GAME_DATA s16 const M_bmd[3];
|
||||||
static DUSK_GAME_DATA s16 const M_dzb[DUSK_IF_ELSE(4, 3)];
|
static DUSK_GAME_DATA s16 const M_dzb[3];
|
||||||
static DUSK_GAME_DATA u32 const M_heap_size[DUSK_IF_ELSE(4, 3)];
|
static DUSK_GAME_DATA u32 const M_heap_size[3];
|
||||||
static DUSK_GAME_DATA Hio_c::Attr_c const M_attr[5];
|
static DUSK_GAME_DATA Hio_c::Attr_c const M_attr[5];
|
||||||
static DUSK_GAME_DATA u8 const M_op_vtx[4];
|
static DUSK_GAME_DATA u8 const M_op_vtx[4];
|
||||||
static DUSK_GAME_DATA DUSK_CONST char* M_arcname[DUSK_IF_ELSE(4, 3)];
|
static DUSK_GAME_DATA DUSK_CONST char* M_arcname[3];
|
||||||
|
|
||||||
/* 0x568 */ request_of_phase_process_class mPhase;
|
/* 0x568 */ request_of_phase_process_class mPhase;
|
||||||
/* 0x570 */ dBgWSv* mpBgW;
|
/* 0x570 */ dBgWSv* mpBgW;
|
||||||
|
|||||||
@@ -311,9 +311,11 @@ private:
|
|||||||
class daMidna_c;
|
class daMidna_c;
|
||||||
class daSpinner_c;
|
class daSpinner_c;
|
||||||
class daPy_py_c;
|
class daPy_py_c;
|
||||||
|
#if !TARGET_PC
|
||||||
inline daPy_py_c* dComIfGp_getLinkPlayer();
|
inline daPy_py_c* dComIfGp_getLinkPlayer();
|
||||||
inline BOOL dComIfGs_isEventBit(const u16);
|
inline BOOL dComIfGs_isEventBit(const u16);
|
||||||
inline u32 dComIfGs_getLastSceneMode();
|
inline u32 dComIfGs_getLastSceneMode();
|
||||||
|
#endif
|
||||||
|
|
||||||
class daPy_py_c : public fopAc_ac_c {
|
class daPy_py_c : public fopAc_ac_c {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public:
|
|||||||
u8 getModelType() { return fopAcM_GetParamBit(this, 8, 4); }
|
u8 getModelType() { return fopAcM_GetParamBit(this, 8, 4); }
|
||||||
u8 getItemNo() { return fopAcM_GetParamBit(this, 0, 8); }
|
u8 getItemNo() { return fopAcM_GetParamBit(this, 0, 8); }
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
/* 0x718 */ u8 mReturnRupee;
|
/* 0x718 */ u8 mReturnRupee;
|
||||||
/* 0x71C */ request_of_phase_process_class mPhase;
|
/* 0x71C */ request_of_phase_process_class mPhase;
|
||||||
/* 0x724 */ J3DModel* mpModel;
|
/* 0x724 */ J3DModel* mpModel;
|
||||||
@@ -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 */
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
#ifndef D_A_D_A_ITEMBASE_STATIC_H
|
#ifndef D_A_D_A_ITEMBASE_STATIC_H
|
||||||
#define D_A_D_A_ITEMBASE_STATIC_H
|
#define D_A_D_A_ITEMBASE_STATIC_H
|
||||||
|
|
||||||
|
#include "dolphin/types.h"
|
||||||
|
|
||||||
class fopAc_ac_c;
|
class fopAc_ac_c;
|
||||||
|
|
||||||
int CheckFieldItemCreateHeap(fopAc_ac_c* actor);
|
int CheckFieldItemCreateHeap(fopAc_ac_c* actor);
|
||||||
int CheckItemCreateHeap(fopAc_ac_c* i_this);
|
int CheckItemCreateHeap(fopAc_ac_c* i_this);
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
const char* dItem_fieldModelArc(u8 itemNo);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* D_A_D_A_ITEMBASE_STATIC_H */
|
#endif /* D_A_D_A_ITEMBASE_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);
|
||||||
|
|||||||
+934
-78
File diff suppressed because it is too large
Load Diff
@@ -27,11 +27,6 @@ public:
|
|||||||
void setSaveDate(dSv_save_c*);
|
void setSaveDate(dSv_save_c*);
|
||||||
void setPlayTime(dSv_save_c*);
|
void setPlayTime(dSv_save_c*);
|
||||||
void modeWait();
|
void modeWait();
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
void fileSelectWide();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void modeMove();
|
void modeMove();
|
||||||
void _draw();
|
void _draw();
|
||||||
|
|
||||||
@@ -42,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
-33
@@ -9,42 +9,13 @@
|
|||||||
#include "JSystem/J3DGraphLoader/J3DModelLoader.h"
|
#include "JSystem/J3DGraphLoader/J3DModelLoader.h"
|
||||||
#include "JSystem/J3DGraphLoader/J3DAnmLoader.h"
|
#include "JSystem/J3DGraphLoader/J3DAnmLoader.h"
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
#include "mods/svc/game_mode.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class dFile_info_c;
|
class dFile_info_c;
|
||||||
class J2DPicture;
|
class J2DPicture;
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
class dDlst_FileSel_c : public dDlst_base_c {
|
class dDlst_FileSel_c : public dDlst_base_c {
|
||||||
public:
|
public:
|
||||||
void draw();
|
void draw();
|
||||||
@@ -420,6 +391,13 @@ public:
|
|||||||
bool pointerMenuSelect();
|
bool pointerMenuSelect();
|
||||||
bool pointerCopyDataToSelect();
|
bool pointerCopyDataToSelect();
|
||||||
bool pointerYesNoSelect(bool errorSelect);
|
bool pointerYesNoSelect(bool errorSelect);
|
||||||
|
void backToDataSelectMove() {
|
||||||
|
headerTxtSet(0x43, 1, 0);
|
||||||
|
fileRecScaleAnmInitSet2(0.0f, 1.0f);
|
||||||
|
nameMoveAnmInitSet(0xd29, 0xd1f);
|
||||||
|
modoruTxtDispAnmInit(0);
|
||||||
|
mDataSelProc = DATASELPROC_NAME_TO_DATA_SELECT_MOVE;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
void _draw();
|
void _draw();
|
||||||
void errorMoveAnmInitSet(int, int);
|
void errorMoveAnmInitSet(int, int);
|
||||||
@@ -733,6 +711,8 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
dDlst_FileSelFade_c mFadeDlst;
|
dDlst_FileSelFade_c mFadeDlst;
|
||||||
|
bool mGameModeSaveStartBuildUi = true;
|
||||||
|
GameModeNewSaveState mGameModeNewSaveState = GAME_MODE_STATE_PENDING;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PLATFORM_WII || PLATFORM_SHIELD
|
#if PLATFORM_WII || PLATFORM_SHIELD
|
||||||
|
|||||||
+3
-5
@@ -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();
|
||||||
@@ -400,8 +402,4 @@ BOOL isBottleItem(u8 item_no);
|
|||||||
u8 check_itemno(int i_itemNo);
|
u8 check_itemno(int i_itemNo);
|
||||||
BOOL isInsect(u8 i_itemNo);
|
BOOL isInsect(u8 i_itemNo);
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
void item_func_WALLET_LV4();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* D_D_ITEM_H */
|
#endif /* D_D_ITEM_H */
|
||||||
|
|||||||
+6
-12
@@ -58,11 +58,7 @@ struct dItem_data {
|
|||||||
|
|
||||||
static s16 getTexture(u8 index) { return item_resource[index].mTexture; }
|
static s16 getTexture(u8 index) { return item_resource[index].mTexture; }
|
||||||
|
|
||||||
#if TARGET_PC
|
static u8 getTexScale (u8 index) { return item_resource[index].mTexScale; }
|
||||||
static u8 getTexScale(u8 index);
|
|
||||||
#else
|
|
||||||
static u8 getTexScale(u8 index) { return item_resource[index].mTexScale; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const char* getFieldArc(u8 index) { return field_item_res[index].mFieldArc; }
|
static const char* getFieldArc(u8 index) { return field_item_res[index].mFieldArc; }
|
||||||
|
|
||||||
@@ -146,7 +142,12 @@ enum {
|
|||||||
/* 0x2F */ dItemNo_WEAR_KOKIRI_e,
|
/* 0x2F */ dItemNo_WEAR_KOKIRI_e,
|
||||||
/* 0x30 */ dItemNo_ARMOR_e,
|
/* 0x30 */ dItemNo_ARMOR_e,
|
||||||
/* 0x31 */ dItemNo_WEAR_ZORA_e,
|
/* 0x31 */ dItemNo_WEAR_ZORA_e,
|
||||||
|
#if TARGET_PC
|
||||||
/* 0x32 */ dItemNo_MAGIC_LV1_e,
|
/* 0x32 */ dItemNo_MAGIC_LV1_e,
|
||||||
|
dItemNo_SHADOW_CRYSTAL_e = dItemNo_MAGIC_LV1_e,
|
||||||
|
#else
|
||||||
|
/* 0x32 */ dItemNo_MAGIC_LV1_e,
|
||||||
|
#endif
|
||||||
/* 0x33 */ dItemNo_DUNGEON_EXIT_2_e,
|
/* 0x33 */ dItemNo_DUNGEON_EXIT_2_e,
|
||||||
/* 0x34 */ dItemNo_WALLET_LV1_e,
|
/* 0x34 */ dItemNo_WALLET_LV1_e,
|
||||||
/* 0x35 */ dItemNo_WALLET_LV2_e,
|
/* 0x35 */ dItemNo_WALLET_LV2_e,
|
||||||
@@ -354,11 +355,4 @@ enum {
|
|||||||
/* 0xFF */ dItemNo_NONE_e,
|
/* 0xFF */ dItemNo_NONE_e,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
// HD item mappings
|
|
||||||
enum {
|
|
||||||
dItemNo_WALLET_LV4_e = 0xDA,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* D_D_ITEM_DATA_H */
|
#endif /* D_D_ITEM_DATA_H */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public:
|
|||||||
return &mpTypeGroupData[i_typeGroupNo];
|
return &mpTypeGroupData[i_typeGroupNo];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 0x0 */ fmpTresTypeGroupDataList_c mpTypeGroupData[DUSK_IF_ELSE(35, 17)];
|
/* 0x0 */ fmpTresTypeGroupDataList_c mpTypeGroupData[17];
|
||||||
};
|
};
|
||||||
|
|
||||||
class dMenu_Fmap_data_c {
|
class dMenu_Fmap_data_c {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -328,6 +328,150 @@ void dMeter2Info_onWide2D();
|
|||||||
void dMeter2Info_offWide2D();
|
void dMeter2Info_offWide2D();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
DUSK_NOINLINE void dMeter2Info_Initialize();
|
||||||
|
DUSK_NOINLINE dMeterMap_c* dMeter2Info_getMeterMapClass();
|
||||||
|
DUSK_NOINLINE dMw_c* dMeter2Info_getMenuWindowClass();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setWindowStatus(u8 i_status);
|
||||||
|
DUSK_NOINLINE CPaneMgr* dMeter2Info_getMeterItemPanePtr(s32 i_idx);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_getString(
|
||||||
|
u32 i_stringID, TEXT_SPAN o_string, JMSMesgEntry_c* i_msgEntry);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_getStringKanji(
|
||||||
|
u32 i_stringID, TEXT_SPAN o_string, JMSMesgEntry_c* i_msgEntry);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_getStringKana(
|
||||||
|
u32 i_stringID, TEXT_SPAN o_string, JMSMesgEntry_c* i_msgEntry);
|
||||||
|
DUSK_NOINLINE f32 dMeter2Info_getStringLength(
|
||||||
|
JUTFont* i_font, f32 param_2, f32 param_3, char* i_string);
|
||||||
|
DUSK_NOINLINE f32 dMeter2Info_getStringLength(J2DTextBox* i_textbox, char* i_string);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setHotSpringTimer(u8 i_slotNo);
|
||||||
|
DUSK_NOINLINE u16 dMeter2Info_getOilGaugeBackUp();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setOilGaugeBackUp(u16 param_1);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setSaveStageName(const char* i_stageName);
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getInsectSelectType();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setInsectSelectType(u8 i_type);
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getWarpStatus();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setWarpStatus(u8 i_status);
|
||||||
|
DUSK_NOINLINE int dMeter2Info_readItemTexture(u8 i_itemNo, void* i_texBuf1, J2DPicture* i_pic1,
|
||||||
|
void* i_texBuf2, J2DPicture* i_pic2, void* i_texBuf3, J2DPicture* i_pic3, void* i_texBuf4,
|
||||||
|
J2DPicture* i_pic4, int param_9);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setItemColor(
|
||||||
|
u8 i_itemNo, J2DPicture* i_pic1, J2DPicture* i_pic2, J2DPicture* i_pic3, J2DPicture* i_pic4);
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getWarpRoomNo();
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getWarpPlayerNo();
|
||||||
|
DUSK_NOINLINE cXyz& dMeter2Info_getWarpPos();
|
||||||
|
DUSK_NOINLINE const char* dMeter2Info_getWarpStageName();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setNowCount(u8 i_count);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMaxCount(u8 i_count);
|
||||||
|
DUSK_NOINLINE BOOL dMeter2Info_isDirectUseItem(int param_0);
|
||||||
|
DUSK_NOINLINE bool dMeter2Info_isUseButton(int i_buttonBit);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMeterMapClass(dMeterMap_c* i_map);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_decHotSpringTimer();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_allUseButton();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_offUseButton(int i_buttonBit);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_resetGameStatus();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_onGameStatus(int i_status);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMapStatus(u8 i_status);
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getMapStatus();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setPauseStatus(u8 i_status);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_resetPauseStatus();
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getPauseStatus();
|
||||||
|
DUSK_NOINLINE bool dMeter2Info_isGameStatus(int i_status);
|
||||||
|
DUSK_NOINLINE bool dMeter2Info_isTouchKeyCheck(int i_status);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMapKeyDirection(u16 i_direction);
|
||||||
|
DUSK_NOINLINE bool dMeter2Info_isSub2DStatus(int i_flag);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_offMenuInForce(int i_flag);
|
||||||
|
DUSK_NOINLINE bool dMeter2Info_isMenuInForce(int i_flag);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMenuWindowClass(dMw_c* i_menu);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_resetWarpStatus();
|
||||||
|
DUSK_NOINLINE u16 dMeter2Info_getMapKeyDirection();
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getWindowStatus();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMsgResource(void* i_res);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setStageMsgResource(void* i_res);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMsgUnitResource(void* i_res);
|
||||||
|
DUSK_NOINLINE void* dMeter2Info_getMsgResource();
|
||||||
|
DUSK_NOINLINE void* dMeter2Info_getStageMsgResource();
|
||||||
|
DUSK_NOINLINE void* dMeter2Info_getMsgUnitResource();
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getLightDropGetFlag(int i_no);
|
||||||
|
DUSK_NOINLINE s32 dMeter2Info_getMeterStringType();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMeterClass(dMeter2_c* i_meter);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_onLifeGaugeSE();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_offLifeGaugeSE();
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getLifeGaugeSE();
|
||||||
|
DUSK_NOINLINE const char* dMeter2Info_getSaveStageName();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_onShopTalkFlag();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setLightDropGetFlag(int i_no, u8 i_flag);
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getRentalBombBag();
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getMiniGameItemSetFlag();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMiniGameItem(u8 i_minigameFlag);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_resetMiniGameItem(bool i_saveItem);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setTableMapRegionNo(u8 i_regionNo);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setGoldWolfMapType(u8 i_mapType);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_changeWater(u8 i_slotNo);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_warpInProc();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_warpOutProc();
|
||||||
|
DUSK_NOINLINE dMeter2_c* dMeter2Info_getMeterClass();
|
||||||
|
DUSK_NOINLINE s16 dMeter2Info_getMsgKeyWaitTimer();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_onDirectUseItem(int param_0);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setFloatingFlow(u16 i_flowID, s16 i_msgTimer, bool i_wakuVisible);
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getGameOverType();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setGameOverType(u8 i_gameoverType);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMsgKeyWaitTimer(s16 i_waitTimer);
|
||||||
|
DUSK_NOINLINE s32 dMeter2Info_getMsgTimeMs();
|
||||||
|
DUSK_NOINLINE s32 dMeter2Info_getTimeMs();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMsgTimeMs(s32 i_msgTime);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setTimeMs(s32 i_time);
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getNowCount();
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getMaxCount();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setScopeZoomPointer(u8 param_0);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_decMsgKeyWaitTimer();
|
||||||
|
DUSK_NOINLINE bool dMeter2Info_isFloatingMessageVisible();
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getItemExplainWindowStatus();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setItemExplainWindowStatus(u8 i_value);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_resetDirectUseItem();
|
||||||
|
DUSK_NOINLINE u16 dMeter2Info_getFloatingFlowID();
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getCollectCursorPosX();
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getCollectCursorPosY();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setCollectCursorPosXY(u8 x, u8 y);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_onBlinkButton(int i_flag);
|
||||||
|
DUSK_NOINLINE bool dMeter2Info_isFloatingMessageWakuVisible();
|
||||||
|
DUSK_NOINLINE bool dMeter2Info_isBlinkButton(int i_flag);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_resetBlinkButton();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_resetFloatingMessage();
|
||||||
|
DUSK_NOINLINE s16 dMeter2Info_decFloatingMessageTimer();
|
||||||
|
DUSK_NOINLINE s16 dMeter2Info_getFloatingMessageTimer();
|
||||||
|
DUSK_NOINLINE u16 dMeter2Info_getFloatingMessageID();
|
||||||
|
DUSK_NOINLINE s16 dMeter2Info_getHorseLifeCount();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMeterString(s32 i_string);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_resetMeterString();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMeterItemPanePtr(int i_no, CPaneMgr* i_pane);
|
||||||
|
DUSK_NOINLINE bool dMeter2Info_isShopTalkFlag();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMapDrugFlag(bool i_flag);
|
||||||
|
DUSK_NOINLINE bool dMeter2Info_isTempBit(int i_bit);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_offSub2DStatus(int i_bit);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_onSub2DStatus(int i_bit);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_set2DWidth(f32 i_width);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_set2DHeight(f32 i_height);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_set2DPosH(f32 i_posH);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_set2DPosV(f32 i_posV);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_offShopTalkFlag();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_onUseButton(int i_button);
|
||||||
|
DUSK_NOINLINE f32 dMeter2Info_get2DWidth();
|
||||||
|
DUSK_NOINLINE f32 dMeter2Info_get2DHeight();
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setWarpInfo(const char* i_stageName, const cXyz& i_position,
|
||||||
|
s16 i_angle, u8 i_roomNo, u8 param_4, u8 i_warpPlayerNo);
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getTableMapRegionNo();
|
||||||
|
DUSK_NOINLINE u8 dMeter2Info_getGoldWolfMapType();
|
||||||
|
DUSK_NOINLINE bool dMeter2Info_isWindowAccept(int param_0);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setHorseLifeCount(s16 i_count);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_offTempBit(int i_bit);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_onTempBit(int i_bit);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setFloatingMessage(u16 i_msgID, s16 i_msgTimer, bool i_wakuVisible);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_setMiniGameCount(s8 i_count);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_onWindowAccept(int param_0);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_offWindowAccept(int param_0);
|
||||||
|
DUSK_NOINLINE void dMeter2Info_onMenuInForce(int param_0);
|
||||||
|
|
||||||
|
#else
|
||||||
inline void dMeter2Info_Initialize() {
|
inline void dMeter2Info_Initialize() {
|
||||||
g_meter2_info.init();
|
g_meter2_info.init();
|
||||||
}
|
}
|
||||||
@@ -865,4 +1009,6 @@ inline void dMeter2Info_onMenuInForce(int param_0) {
|
|||||||
g_meter2_info.onMenuInForce(param_0);
|
g_meter2_info.onMenuInForce(param_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* D_METER_D_METER2_INFO_H */
|
#endif /* D_METER_D_METER2_INFO_H */
|
||||||
|
|||||||
+47
-12
@@ -27,18 +27,20 @@ public:
|
|||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
/* 0x04 */ BE(u16) message_id;
|
/* 0x04 */ BE(u16) message_id;
|
||||||
/* 0x06 */ BE(u16) event_label_id;
|
/* 0x06 */ BE(u16) event_label_id; // saveBitLabels index set when the message displays
|
||||||
/* 0x08 */ u8 se_speaker;
|
/* 0x08 */ u8 speaker; // Z2SpeechMgr2 voice bank ID
|
||||||
/* 0x09 */ u8 fuki_kind;
|
/* 0x09 */ u8 box_kind; // screen class, see dMsgObject_c::talkStartInit
|
||||||
/* 0x0A */ u8 output_type;
|
/* 0x0A */ u8 draw_type; // text pacing, see jmessage_tSequenceProcessor::do_begin
|
||||||
/* 0x0B */ u8 fuki_pos_type;
|
/* 0x0B */ u8 box_position; // see dMsgObject_c::fukiPosCalc
|
||||||
/* 0x0C */ u8 unk_0xc;
|
/* 0x0C */ u8 item_no; // unused; legacy dItemNo, 0xFF = none
|
||||||
/* 0x0D */ u8 unk_0xd;
|
/* 0x0D */ u8 line_alignment; // 0 centered (JP only), 1 left; also copied to
|
||||||
/* 0x0E */ u8 se_mood;
|
// jmessage_tReference::mForm
|
||||||
/* 0x0F */ u8 camera_id;
|
/* 0x0E */ u8 speaker_mood; // grunt emotion index for the voice bank
|
||||||
/* 0x10 */ u8 base_anm_id;
|
/* 0x0F */ u8 camera_attr; // 1-10 talk-actor slot, >=11 talk-camera style
|
||||||
/* 0x11 */ u8 face_anm_id;
|
/* 0x10 */ u8 talk_anim; // NPC talk motion attribute
|
||||||
/* 0x12 */ BE(u16) unk_0x12;
|
/* 0x11 */ u8 face_anim; // NPC talk face attribute
|
||||||
|
/* 0x12 */ u8 lines_per_page; // unused; runtime uses getLineMax()
|
||||||
|
/* 0x13 */ u8 _pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JMSMesgInfo_c {
|
class JMSMesgInfo_c {
|
||||||
@@ -119,6 +121,25 @@ struct jmessage_tReference : public JMessage::TReference {
|
|||||||
void setDemoFrame(u32 i_frame) { mDemoFrame = i_frame; }
|
void setDemoFrame(u32 i_frame) { mDemoFrame = i_frame; }
|
||||||
void setTopColorType(u8 i_colorType) { mTopColorType = i_colorType; }
|
void setTopColorType(u8 i_colorType) { mTopColorType = i_colorType; }
|
||||||
void setNowColorType(u8 i_colorType) { mNowColorType = i_colorType; }
|
void setNowColorType(u8 i_colorType) { mNowColorType = i_colorType; }
|
||||||
|
#if TARGET_PC
|
||||||
|
void resetColors() {
|
||||||
|
mNowCCColor = 0xFFFFFFFF;
|
||||||
|
mNowGCColor = 0xFFFFFFFF;
|
||||||
|
mTopCCColor = 0xFFFFFFFF;
|
||||||
|
mTopGCColor = 0xFFFFFFFF;
|
||||||
|
mNowFullColor = false;
|
||||||
|
mTopFullColor = false;
|
||||||
|
}
|
||||||
|
void setFullColor(u32 ccColor, u32 gcColor) {
|
||||||
|
mNowCCColor = ccColor;
|
||||||
|
mNowGCColor = gcColor;
|
||||||
|
mNowFullColor = true;
|
||||||
|
}
|
||||||
|
void clearNowFullColor() { mNowFullColor = false; }
|
||||||
|
bool hasTopFullColor() { return mTopFullColor; }
|
||||||
|
u32 getTopCCColor() { return mTopCCColor; }
|
||||||
|
u32 getTopGCColor() { return mTopGCColor; }
|
||||||
|
#endif
|
||||||
void setTopTagScale(u16 i_tagScale) { mTopTagScale = i_tagScale; }
|
void setTopTagScale(u16 i_tagScale) { mTopTagScale = i_tagScale; }
|
||||||
void setNowTagScale(u16 i_tagScale) { mNowTagScale = i_tagScale; }
|
void setNowTagScale(u16 i_tagScale) { mNowTagScale = i_tagScale; }
|
||||||
void setRevoMessageID(u32 i_msgID) { mRevoMessageID = i_msgID; }
|
void setRevoMessageID(u32 i_msgID) { mRevoMessageID = i_msgID; }
|
||||||
@@ -363,6 +384,14 @@ struct jmessage_tReference : public JMessage::TReference {
|
|||||||
/* 0x1274 */ bool mSelectSetCancelFlag;
|
/* 0x1274 */ bool mSelectSetCancelFlag;
|
||||||
/* 0x1275 */ bool mBombNameUseFlag;
|
/* 0x1275 */ bool mBombNameUseFlag;
|
||||||
/* 0x1276 */ u8 mBatchColorFlag;
|
/* 0x1276 */ u8 mBatchColorFlag;
|
||||||
|
#if TARGET_PC
|
||||||
|
u32 mNowCCColor;
|
||||||
|
u32 mNowGCColor;
|
||||||
|
u32 mTopCCColor;
|
||||||
|
u32 mTopGCColor;
|
||||||
|
bool mNowFullColor;
|
||||||
|
bool mTopFullColor;
|
||||||
|
#endif
|
||||||
}; // Size: 0x1278
|
}; // Size: 0x1278
|
||||||
|
|
||||||
struct jmessage_tMeasureProcessor : public JMessage::TRenderingProcessor {
|
struct jmessage_tMeasureProcessor : public JMessage::TRenderingProcessor {
|
||||||
@@ -460,6 +489,9 @@ struct jmessage_tRenderingProcessor : public JMessage::TRenderingProcessor {
|
|||||||
void do_selwidthcenter(int);
|
void do_selwidthcenter(int);
|
||||||
void do_heightcenter();
|
void do_heightcenter();
|
||||||
void do_color(u8);
|
void do_color(u8);
|
||||||
|
#if TARGET_PC
|
||||||
|
void do_fullcolor(u32 ccColor, u32 gcColor);
|
||||||
|
#endif
|
||||||
void do_scale(f32);
|
void do_scale(f32);
|
||||||
void do_linedown(s16);
|
void do_linedown(s16);
|
||||||
void do_transY(s16, bool);
|
void do_transY(s16, bool);
|
||||||
@@ -638,6 +670,9 @@ struct jmessage_string_tRenderingProcessor : public JMessage::TRenderingProcesso
|
|||||||
void do_rubystrcat(char*);
|
void do_rubystrcat(char*);
|
||||||
void do_outfont(u8);
|
void do_outfont(u8);
|
||||||
void do_color(u8);
|
void do_color(u8);
|
||||||
|
#if TARGET_PC
|
||||||
|
void do_fullcolor(u32 ccColor, u32 gcColor);
|
||||||
|
#endif
|
||||||
void do_scale(f32);
|
void do_scale(f32);
|
||||||
void do_linedown(s16);
|
void do_linedown(s16);
|
||||||
void do_numset(s16);
|
void do_numset(s16);
|
||||||
|
|||||||
+4
-13
@@ -22,7 +22,7 @@ struct msg_class;
|
|||||||
// all mesg_flow_node structs members might be wrong
|
// all mesg_flow_node structs members might be wrong
|
||||||
struct mesg_flow_node {
|
struct mesg_flow_node {
|
||||||
/* 0x00 */ u8 type;
|
/* 0x00 */ u8 type;
|
||||||
/* 0x01 */ u8 field_0x1;
|
/* 0x01 */ u8 subtype;
|
||||||
/* 0x02 */ BE(u16) msg_index;
|
/* 0x02 */ BE(u16) msg_index;
|
||||||
/* 0x04 */ BE(u16) next_node_idx;
|
/* 0x04 */ BE(u16) next_node_idx;
|
||||||
/* 0x06 */ BE(u16) unk_0x6;
|
/* 0x06 */ BE(u16) unk_0x6;
|
||||||
@@ -30,7 +30,7 @@ struct mesg_flow_node {
|
|||||||
|
|
||||||
struct mesg_flow_node_branch {
|
struct mesg_flow_node_branch {
|
||||||
/* 0x00 */ u8 type;
|
/* 0x00 */ u8 type;
|
||||||
/* 0x01 */ u8 field_0x1;
|
/* 0x01 */ u8 result_count;
|
||||||
/* 0x02 */ BE(u16) query_idx;
|
/* 0x02 */ BE(u16) query_idx;
|
||||||
/* 0x04 */ BE(u16) param;
|
/* 0x04 */ BE(u16) param;
|
||||||
/* 0x06 */ BE(u16) next_node_idx;
|
/* 0x06 */ BE(u16) next_node_idx;
|
||||||
@@ -172,15 +172,6 @@ public:
|
|||||||
int event041(mesg_flow_node_event*, fopAc_ac_c*);
|
int event041(mesg_flow_node_event*, fopAc_ac_c*);
|
||||||
int event042(mesg_flow_node_event*, fopAc_ac_c*);
|
int event042(mesg_flow_node_event*, fopAc_ac_c*);
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
// HD additions
|
|
||||||
u16 query054(mesg_flow_node_branch*, fopAc_ac_c*, int);
|
|
||||||
u16 query055(mesg_flow_node_branch*, fopAc_ac_c*, int);
|
|
||||||
int event043(mesg_flow_node_event*, fopAc_ac_c*);
|
|
||||||
int event044(mesg_flow_node_event*, fopAc_ac_c*);
|
|
||||||
int event045(mesg_flow_node_event*, fopAc_ac_c*);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void initWord(fopAc_ac_c*, const char*, u8, int, fopAc_ac_c**);
|
void initWord(fopAc_ac_c*, const char*, u8, int, fopAc_ac_c**);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@@ -194,8 +185,8 @@ public:
|
|||||||
void setMsg(u32 msg) { mMsg = msg; }
|
void setMsg(u32 msg) { mMsg = msg; }
|
||||||
bool checkEndFlow() { return (u32)field_0x26 == 1; }
|
bool checkEndFlow() { return (u32)field_0x26 == 1; }
|
||||||
|
|
||||||
static DUSK_GAME_DATA queryFunc mQueryList[DUSK_IF_ELSE(55, 53)];
|
static DUSK_GAME_DATA queryFunc mQueryList[53];
|
||||||
static DUSK_GAME_DATA eventFunc mEventList[DUSK_IF_ELSE(46, 43)];
|
static DUSK_GAME_DATA eventFunc mEventList[43];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* 0x04 */ u8* mFlow_p;
|
/* 0x04 */ u8* mFlow_p;
|
||||||
|
|||||||
@@ -280,13 +280,13 @@ public:
|
|||||||
/* 0x150 */ f32 field_0x150;
|
/* 0x150 */ f32 field_0x150;
|
||||||
/* 0x154 */ u32 mMessageID;
|
/* 0x154 */ u32 mMessageID;
|
||||||
/* 0x158 */ u32 field_0x158;
|
/* 0x158 */ u32 field_0x158;
|
||||||
/* 0x15C */ u32 field_0x15c;
|
/* 0x15C */ u32 mSelectMessageID; // message ID of the selection options message; 1000 = none
|
||||||
/* 0x160 */ int mIdx;
|
/* 0x160 */ int mIdx;
|
||||||
/* 0x164 */ u16 mNodeIdx;
|
/* 0x164 */ u16 mNodeIdx;
|
||||||
/* 0x166 */ u16 field_0x166;
|
/* 0x166 */ u16 field_0x166;
|
||||||
/* 0x168 */ u16 field_0x168;
|
/* 0x168 */ u16 field_0x168;
|
||||||
/* 0x16A */ s16 field_0x16a;
|
/* 0x16A */ s16 field_0x16a;
|
||||||
/* 0x16C */ s16 field_0x16c;
|
/* 0x16C */ s16 mCurrentGroupID; // group whose BMG is parsed; -1 none, 0 common, 1-8 stage
|
||||||
/* 0x16E */ s16 field_0x16e;
|
/* 0x16E */ s16 field_0x16e;
|
||||||
/* 0x170 */ s16 mNowTalkFlowNo;
|
/* 0x170 */ s16 mNowTalkFlowNo;
|
||||||
/* 0x172 */ s16 field_0x172;
|
/* 0x172 */ s16 field_0x172;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
+1
-5
@@ -1291,6 +1291,7 @@ public:
|
|||||||
}
|
}
|
||||||
void set(const char*, s8, s16, s8, s8, u8);
|
void set(const char*, s8, s16, s8, s8, u8);
|
||||||
void offEnable() { enabled = 0; }
|
void offEnable() { enabled = 0; }
|
||||||
|
void onEnable() { enabled = 1; }
|
||||||
BOOL isEnable() const { return enabled; }
|
BOOL isEnable() const { return enabled; }
|
||||||
s8 getWipe() const { return wipe; }
|
s8 getWipe() const { return wipe; }
|
||||||
u8 getWipeSpeed() const { return wipe_speed; }
|
u8 getWipeSpeed() const { return wipe_speed; }
|
||||||
@@ -1416,11 +1417,6 @@ dStage_KeepDoorInfo* dStage_GetKeepDoorInfo();
|
|||||||
dStage_KeepDoorInfo* dStage_GetRoomKeepDoorInfo();
|
dStage_KeepDoorInfo* dStage_GetRoomKeepDoorInfo();
|
||||||
void dStage_dt_c_fieldMapLoader(void* i_data, dStage_dt_c* i_stage);
|
void dStage_dt_c_fieldMapLoader(void* i_data, dStage_dt_c* i_stage);
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
// TP HD Cave of Shadows (D_SB11): reveal the los next-floor when a descent gate opens.
|
|
||||||
void dStage_showLOSNextFloor(int fromRoom);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
void dStage_DebugDisp();
|
void dStage_DebugDisp();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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,22 @@ 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)
|
||||||
|
IF_DUSK_ARG(u8 i_itemOriginalNo = 0xFF));
|
||||||
|
|
||||||
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)
|
||||||
|
IF_DUSK_ARG(u8 i_itemOriginalNo = 0xFF));
|
||||||
|
|
||||||
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 +631,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 +649,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,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ struct msg_class {
|
|||||||
/* 0xDC */ fopAc_ac_c* talk_actor;
|
/* 0xDC */ fopAc_ac_c* talk_actor;
|
||||||
/* 0xE0 */ cXyz pos;
|
/* 0xE0 */ cXyz pos;
|
||||||
/* 0xEC */ u32 msg_idx;
|
/* 0xEC */ u32 msg_idx;
|
||||||
/* 0xF0 */ u32 field_0xf0;
|
/* 0xF0 */ u32 select_msg_idx; // selection options message ID; 1000 = none
|
||||||
/* 0xF4 */ u32 field_0xf4;
|
/* 0xF4 */ u32 field_0xf4;
|
||||||
/* 0xF8 */ u16 mode;
|
/* 0xF8 */ u16 mode;
|
||||||
/* 0xFA */ u8 select_idx;
|
/* 0xFA */ u8 select_idx;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ struct fopMsg_prm_class {
|
|||||||
/* 0x00 */ fopAc_ac_c* talk_actor;
|
/* 0x00 */ fopAc_ac_c* talk_actor;
|
||||||
/* 0x04 */ cXyz pos;
|
/* 0x04 */ cXyz pos;
|
||||||
/* 0x10 */ u32 msg_idx;
|
/* 0x10 */ u32 msg_idx;
|
||||||
/* 0x14 */ u32 field_0x14;
|
/* 0x14 */ u32 select_msg_idx; // selection options message ID; 1000 = none
|
||||||
/* 0x18 */ fpc_ProcID field_0x18;
|
/* 0x18 */ fpc_ProcID field_0x18;
|
||||||
}; // Size: 0x1C
|
}; // Size: 0x1C
|
||||||
|
|
||||||
@@ -46,8 +46,8 @@ void fopMsgM_setMessageID(fpc_ProcID msg_id);
|
|||||||
void fopMsgM_destroyExpHeap(JKRExpHeap* i_heap);
|
void fopMsgM_destroyExpHeap(JKRExpHeap* i_heap);
|
||||||
f32 fopMsgM_valueIncrease(int param_0, int param_1, u8 i_type);
|
f32 fopMsgM_valueIncrease(int param_0, int param_1, u8 i_type);
|
||||||
s32 fopMsgM_setStageLayer(void* i_process);
|
s32 fopMsgM_setStageLayer(void* i_process);
|
||||||
fpc_ProcID fopMsgM_messageSet(u32 i_msgIdx, fopAc_ac_c* i_talkActor, u32 param_2);
|
fpc_ProcID fopMsgM_messageSet(u32 i_msgIdx, fopAc_ac_c* i_talkActor, u32 i_selectMsgIdx);
|
||||||
fpc_ProcID fopMsgM_messageSet(u32 i_msgIdx, u32 param_1);
|
fpc_ProcID fopMsgM_messageSet(u32 i_msgIdx, u32 i_selectMsgIdx);
|
||||||
fpc_ProcID fopMsgM_messageSetDemo(u32 i_msgidx);
|
fpc_ProcID fopMsgM_messageSetDemo(u32 i_msgidx);
|
||||||
msg_class* fopMsgM_SearchByID(fpc_ProcID i_id);
|
msg_class* fopMsgM_SearchByID(fpc_ProcID i_id);
|
||||||
TEXT_SPAN fopMsgM_messageGet(TEXT_SPAN i_stringBuf, u32 i_msgId);
|
TEXT_SPAN fopMsgM_messageGet(TEXT_SPAN i_stringBuf, u32 i_msgId);
|
||||||
|
|||||||
@@ -123,6 +123,14 @@ inline int __builtin_clz(unsigned int v) {
|
|||||||
#endif
|
#endif
|
||||||
#define DUSK_GAME_EXTERN extern DUSK_GAME_DATA
|
#define DUSK_GAME_EXTERN extern DUSK_GAME_DATA
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define DUSK_NOINLINE __declspec(noinline)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define DUSK_NOINLINE __attribute__((noinline))
|
||||||
|
#else
|
||||||
|
#define DUSK_NOINLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FAST_DIV(x, n) (x >> (n / 2))
|
#define FAST_DIV(x, n) (x >> (n / 2))
|
||||||
|
|
||||||
#define SQUARE(x) ((x) * (x))
|
#define SQUARE(x) ((x) * (x))
|
||||||
@@ -256,4 +264,23 @@ 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_commit(name, (item_no), giver).itemNo
|
||||||
|
#define DUSK_ITEM_CHECK_EXPR(name, item_no, giver) \
|
||||||
|
(::dusk::mods::item_check_commit(name, (item_no), giver).itemNo)
|
||||||
|
#define DUSK_ITEM_CHECK_PREVIEW(name, item_no, giver) \
|
||||||
|
(item_no) = ::dusk::mods::item_check(name, (item_no), giver)
|
||||||
|
#define DUSK_ITEM_CHECK_PREVIEW_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_ITEM_CHECK_PREVIEW(name, item_no, giver)
|
||||||
|
#define DUSK_ITEM_CHECK_PREVIEW_EXPR(name, item_no, giver) (item_no)
|
||||||
|
#define DUSK_GIVE_TAG(name)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace dusk {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <size_t Size>
|
||||||
|
struct uint_of_size;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct uint_of_size<1> {
|
||||||
|
using type = uint8_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct uint_of_size<2> {
|
||||||
|
using type = uint16_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct uint_of_size<4> {
|
||||||
|
using type = uint32_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct uint_of_size<8> {
|
||||||
|
using type = uint64_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <size_t Size>
|
||||||
|
using uint_of_size_t = uint_of_size<Size>::type;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(std::is_trivially_copyable_v<T>)
|
||||||
|
T unaligned_load(const void* source) noexcept {
|
||||||
|
T value;
|
||||||
|
std::memcpy(&value, source, sizeof(value));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(std::is_trivially_copyable_v<T>)
|
||||||
|
void unaligned_store(void* destination, T value) noexcept {
|
||||||
|
std::memcpy(destination, &value, sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(std::is_unsigned_v<T>)
|
||||||
|
constexpr T bswap(T value) noexcept {
|
||||||
|
if constexpr (sizeof(T) == 1) {
|
||||||
|
return value;
|
||||||
|
} else if constexpr (sizeof(T) == 2) {
|
||||||
|
return static_cast<T>((value << 8) | (value >> 8));
|
||||||
|
} else if constexpr (sizeof(T) == 4) {
|
||||||
|
return static_cast<T>(((value & 0x000000ffU) << 24) | ((value & 0x0000ff00U) << 8) |
|
||||||
|
((value & 0x00ff0000U) >> 8) | ((value & 0xff000000U) >> 24));
|
||||||
|
} else {
|
||||||
|
static_assert(sizeof(T) == 8);
|
||||||
|
return static_cast<T>(
|
||||||
|
((value & 0x00000000000000ffULL) << 56) | ((value & 0x000000000000ff00ULL) << 40) |
|
||||||
|
((value & 0x0000000000ff0000ULL) << 24) | ((value & 0x00000000ff000000ULL) << 8) |
|
||||||
|
((value & 0x000000ff00000000ULL) >> 8) | ((value & 0x0000ff0000000000ULL) >> 24) |
|
||||||
|
((value & 0x00ff000000000000ULL) >> 40) | ((value & 0xff00000000000000ULL) >> 56));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads an unaligned integral value in the specified byte order.
|
||||||
|
template <typename T>
|
||||||
|
requires(std::is_integral_v<T> && !std::is_same_v<T, bool>)
|
||||||
|
T read_bits(const void* source, std::endian endian = std::endian::big) noexcept {
|
||||||
|
using Bits = std::make_unsigned_t<T>;
|
||||||
|
Bits value = detail::unaligned_load<Bits>(source);
|
||||||
|
if constexpr (sizeof(Bits) > 1) {
|
||||||
|
if (endian != std::endian::native) {
|
||||||
|
value = bswap(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::bit_cast<T>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(std::is_integral_v<T> && !std::is_same_v<T, bool>)
|
||||||
|
constexpr T read_bits(const uint8_t* source, std::endian endian = std::endian::big) noexcept {
|
||||||
|
if (!std::is_constant_evaluated()) {
|
||||||
|
return read_bits<T>(static_cast<const void*>(source), endian);
|
||||||
|
}
|
||||||
|
using Bits = std::make_unsigned_t<T>;
|
||||||
|
Bits value{};
|
||||||
|
if (endian == std::endian::big) {
|
||||||
|
for (size_t i = 0; i < sizeof(Bits); ++i) {
|
||||||
|
value = static_cast<Bits>((value << 8) | source[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < sizeof(Bits); ++i) {
|
||||||
|
value |= static_cast<Bits>(source[i]) << (i * 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::bit_cast<T>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads an unaligned floating-point value in the specified byte order.
|
||||||
|
template <typename T>
|
||||||
|
requires(
|
||||||
|
std::is_floating_point_v<T> && requires { typename detail::uint_of_size_t<sizeof(T)>; })
|
||||||
|
T read_bits(const void* source, std::endian endian = std::endian::big) noexcept {
|
||||||
|
using Bits = detail::uint_of_size_t<sizeof(T)>;
|
||||||
|
return std::bit_cast<T>(read_bits<Bits>(source, endian));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(
|
||||||
|
std::is_floating_point_v<T> && requires { typename detail::uint_of_size_t<sizeof(T)>; })
|
||||||
|
constexpr T read_bits(const uint8_t* source, std::endian endian = std::endian::big) noexcept {
|
||||||
|
using Bits = detail::uint_of_size_t<sizeof(T)>;
|
||||||
|
return std::bit_cast<T>(read_bits<Bits>(source, endian));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes an unaligned integral value in the specified byte order.
|
||||||
|
template <typename T>
|
||||||
|
requires(std::is_integral_v<T> && !std::is_same_v<T, bool>)
|
||||||
|
void write_bits(void* destination, T value, std::endian endian = std::endian::big) noexcept {
|
||||||
|
using Bits = std::make_unsigned_t<T>;
|
||||||
|
Bits bits = std::bit_cast<Bits>(value);
|
||||||
|
if constexpr (sizeof(Bits) > 1) {
|
||||||
|
if (endian != std::endian::native) {
|
||||||
|
bits = bswap(bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detail::unaligned_store(destination, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(std::is_integral_v<T> && !std::is_same_v<T, bool>)
|
||||||
|
constexpr void write_bits(
|
||||||
|
uint8_t* destination, T value, std::endian endian = std::endian::big) noexcept {
|
||||||
|
if (!std::is_constant_evaluated()) {
|
||||||
|
write_bits(static_cast<void*>(destination), value, endian);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
using Bits = std::make_unsigned_t<T>;
|
||||||
|
const Bits bits = std::bit_cast<Bits>(value);
|
||||||
|
if (endian == std::endian::big) {
|
||||||
|
for (size_t i = 0; i < sizeof(Bits); ++i) {
|
||||||
|
destination[sizeof(Bits) - i - 1] = static_cast<uint8_t>(bits >> (i * 8));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < sizeof(Bits); ++i) {
|
||||||
|
destination[i] = static_cast<uint8_t>(bits >> (i * 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes an unaligned floating-point value in the specified byte order.
|
||||||
|
template <typename T>
|
||||||
|
requires(
|
||||||
|
std::is_floating_point_v<T> && requires { typename detail::uint_of_size_t<sizeof(T)>; })
|
||||||
|
void write_bits(void* destination, T value, std::endian endian = std::endian::big) noexcept {
|
||||||
|
using Bits = detail::uint_of_size_t<sizeof(T)>;
|
||||||
|
write_bits(destination, std::bit_cast<Bits>(value), endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(
|
||||||
|
std::is_floating_point_v<T> && requires { typename detail::uint_of_size_t<sizeof(T)>; })
|
||||||
|
constexpr void write_bits(
|
||||||
|
uint8_t* destination, T value, std::endian endian = std::endian::big) noexcept {
|
||||||
|
using Bits = detail::uint_of_size_t<sizeof(T)>;
|
||||||
|
write_bits(destination, std::bit_cast<Bits>(value), endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dusk
|
||||||
@@ -112,6 +112,11 @@ public:
|
|||||||
mSerialNo = serial_no;
|
mSerialNo = serial_no;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
void setFileName(const std::string& fileName);
|
||||||
|
const char* getFileName();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 0x0000 */ u8 mData[SAVEFILE_SIZE];
|
/* 0x0000 */ u8 mData[SAVEFILE_SIZE];
|
||||||
/* 0x1FBC */ u8 mChannel;
|
/* 0x1FBC */ u8 mChannel;
|
||||||
/* 0x1FBD */ u8 mCopyToPos;
|
/* 0x1FBD */ u8 mCopyToPos;
|
||||||
@@ -124,6 +129,11 @@ public:
|
|||||||
/* 0x1FEC */ s32 mNandState;
|
/* 0x1FEC */ s32 mNandState;
|
||||||
/* 0x1FF0 */ u64 mSerialNo;
|
/* 0x1FF0 */ u64 mSerialNo;
|
||||||
/* 0x1FF8 */ u32 mDataVersion;
|
/* 0x1FF8 */ u32 mDataVersion;
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
bool mInitialized;
|
||||||
|
std::string mFileName;
|
||||||
|
#endif
|
||||||
|
|
||||||
}; // Size: 0x2000
|
}; // Size: 0x2000
|
||||||
|
|
||||||
STATIC_ASSERT(sizeof(mDoMemCd_Ctrl_c) == 8192);
|
STATIC_ASSERT(sizeof(mDoMemCd_Ctrl_c) == 8192);
|
||||||
@@ -230,4 +240,14 @@ inline s32 mDoMemCd_checkNANDFile() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
inline void mDoMemCd_SetFileName(const std::string& fileName) {
|
||||||
|
g_mDoMemCd_control.setFileName(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char* mDoMemCd_GetFileName() {
|
||||||
|
return g_mDoMemCd_control.getFileName();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* M_DO_M_DO_MEMCARD_H */
|
#endif /* M_DO_M_DO_MEMCARD_H */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -1761,16 +1761,6 @@ public:
|
|||||||
virtual ~J3DIndBlockNull() {}
|
virtual ~J3DIndBlockNull() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
struct PolygonOffset {
|
|
||||||
BE(f32) mFrontOffset;
|
|
||||||
BE(f32) mFrontScale;
|
|
||||||
BE(f32) mBackOffset;
|
|
||||||
BE(f32) mBackScale;
|
|
||||||
BE(f32) mClamp;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup jsystem-j3d
|
* @ingroup jsystem-j3d
|
||||||
*
|
*
|
||||||
@@ -1803,10 +1793,6 @@ public:
|
|||||||
virtual void setDither(u8 const*) {}
|
virtual void setDither(u8 const*) {}
|
||||||
virtual void setDither(u8) {}
|
virtual void setDither(u8) {}
|
||||||
virtual u8 getDither() const { return 0; }
|
virtual u8 getDither() const { return 0; }
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
virtual void setPolygonOffset(const PolygonOffset&) {}
|
|
||||||
virtual PolygonOffset* getPolygonOffset() { return NULL; }
|
|
||||||
#endif
|
|
||||||
virtual u32 getFogOffset() const { return 0; }
|
virtual u32 getFogOffset() const { return 0; }
|
||||||
virtual void setFogOffset(u32) {}
|
virtual void setFogOffset(u32) {}
|
||||||
virtual ~J3DPEBlock() {}
|
virtual ~J3DPEBlock() {}
|
||||||
@@ -1970,25 +1956,12 @@ public:
|
|||||||
virtual void setFogOffset(u32 fogOffset) { mFogOffset = fogOffset; }
|
virtual void setFogOffset(u32 fogOffset) { mFogOffset = fogOffset; }
|
||||||
virtual ~J3DPEBlockFull() {}
|
virtual ~J3DPEBlockFull() {}
|
||||||
|
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
virtual void setPolygonOffset(const PolygonOffset& offset) {
|
|
||||||
mPolygonOffset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual PolygonOffset* getPolygonOffset() {
|
|
||||||
return &mPolygonOffset;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 0x04 */ J3DFog mFog;
|
/* 0x04 */ J3DFog mFog;
|
||||||
/* 0x30 */ J3DAlphaComp mAlphaComp;
|
/* 0x30 */ J3DAlphaComp mAlphaComp;
|
||||||
/* 0x34 */ J3DBlend mBlend;
|
/* 0x34 */ J3DBlend mBlend;
|
||||||
/* 0x38 */ J3DZMode mZMode;
|
/* 0x38 */ J3DZMode mZMode;
|
||||||
/* 0x3A */ u8 mZCompLoc;
|
/* 0x3A */ u8 mZCompLoc;
|
||||||
/* 0x3B */ u8 mDither;
|
/* 0x3B */ u8 mDither;
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
PolygonOffset mPolygonOffset;
|
|
||||||
#endif
|
|
||||||
/* 0x3C */ u32 mFogOffset;
|
/* 0x3C */ u32 mFogOffset;
|
||||||
}; // Size: 0x40
|
}; // Size: 0x40
|
||||||
|
|
||||||
|
|||||||
@@ -46,13 +46,6 @@ struct J3DMaterialInitData {
|
|||||||
/* 0x14A */ BE(u16) mNBTScaleIdx;
|
/* 0x14A */ BE(u16) mNBTScaleIdx;
|
||||||
}; // size 0x14C
|
}; // size 0x14C
|
||||||
|
|
||||||
|
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
struct J3DMaterialInitData_MAT4 : public J3DMaterialInitData {
|
|
||||||
/* 0x14C */ BE(u16) mPolygonOffsetIdx;
|
|
||||||
}; // size 0x14E
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup jsystem-j3d
|
* @ingroup jsystem-j3d
|
||||||
*
|
*
|
||||||
@@ -150,29 +143,10 @@ public:
|
|||||||
J3DNBTScale newNBTScale(int) const;
|
J3DNBTScale newNBTScale(int) const;
|
||||||
|
|
||||||
u16 getMaterialID(int idx) const { return mpMaterialID[idx]; }
|
u16 getMaterialID(int idx) const { return mpMaterialID[idx]; }
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
u8 getMaterialMode(int idx) const { return getMatInitData(idx)->mMaterialMode; }
|
|
||||||
#else
|
|
||||||
u8 getMaterialMode(int idx) const { return mpMaterialInitData[mpMaterialID[idx]].mMaterialMode; }
|
u8 getMaterialMode(int idx) const { return mpMaterialInitData[mpMaterialID[idx]].mMaterialMode; }
|
||||||
#endif
|
|
||||||
|
|
||||||
#if DUSK_TPHD
|
|
||||||
const PolygonOffset newPolygonOffset(int) const;
|
|
||||||
|
|
||||||
J3DMaterialInitData* getMatInitData(int idx) const {
|
|
||||||
static const u32 sInitDataSizes[] = {0, 0, 0x138, 0x14C, 0x14E};
|
|
||||||
|
|
||||||
return (J3DMaterialInitData*)((u8*)mpMaterialInitData + sInitDataSizes[mBlockType] * getMaterialID(idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 mBlockType;
|
|
||||||
#endif
|
|
||||||
/* 0x00 */ u16 mMaterialNum;
|
/* 0x00 */ u16 mMaterialNum;
|
||||||
#if DUSK_TPHD
|
|
||||||
/* 0x04 */ void* mpMaterialInitData;
|
|
||||||
#else
|
|
||||||
/* 0x04 */ J3DMaterialInitData* mpMaterialInitData;
|
/* 0x04 */ J3DMaterialInitData* mpMaterialInitData;
|
||||||
#endif
|
|
||||||
/* 0x08 */ BE(u16)* mpMaterialID;
|
/* 0x08 */ BE(u16)* mpMaterialID;
|
||||||
/* 0x0C */ J3DIndInitData* mpIndInitData;
|
/* 0x0C */ J3DIndInitData* mpIndInitData;
|
||||||
/* 0x10 */ GXColor* mpMatColor;
|
/* 0x10 */ GXColor* mpMatColor;
|
||||||
@@ -201,9 +175,6 @@ public:
|
|||||||
/* 0x6C */ u8* mpZCompLoc;
|
/* 0x6C */ u8* mpZCompLoc;
|
||||||
/* 0x70 */ u8* mpDither;
|
/* 0x70 */ u8* mpDither;
|
||||||
/* 0x74 */ J3DNBTScaleInfo* mpNBTScaleInfo;
|
/* 0x74 */ J3DNBTScaleInfo* mpNBTScaleInfo;
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
PolygonOffset* mpPolygonOffsets;
|
|
||||||
#endif
|
|
||||||
/* 0x78 */ J3DDisplayListInit* mpDisplayListInit;
|
/* 0x78 */ J3DDisplayListInit* mpDisplayListInit;
|
||||||
/* 0x7C */ J3DPatchingInfo* mpPatchingInfo;
|
/* 0x7C */ J3DPatchingInfo* mpPatchingInfo;
|
||||||
/* 0x80 */ J3DCurrentMtxInfo* mpCurrentMtxInfo;
|
/* 0x80 */ J3DCurrentMtxInfo* mpCurrentMtxInfo;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
class J3DModelData;
|
class J3DModelData;
|
||||||
class J3DMaterialTable;
|
class J3DMaterialTable;
|
||||||
struct J3DModelHierarchy;
|
struct J3DModelHierarchy;
|
||||||
|
class J3DVertexData;
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
#define OFFSET_PTR_V0 BE(u32)
|
#define OFFSET_PTR_V0 BE(u32)
|
||||||
@@ -169,12 +170,6 @@ struct J3DMaterialBlock_v21 : public J3DModelBlock {
|
|||||||
/* 0x74 */ OFFSET_PTR_V0 mpNBTScaleInfo;
|
/* 0x74 */ OFFSET_PTR_V0 mpNBTScaleInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
struct J3DMaterialBlock_MAT4 : public J3DMaterialBlock {
|
|
||||||
/* 0x84 */ OFFSET_PTR_V0 mpPolygonOffsets;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup jsystem-j3d
|
* @ingroup jsystem-j3d
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -6,11 +6,17 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "helpers/endian.h"
|
#include "helpers/endian.h"
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
#include <atomic>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#endif
|
||||||
|
|
||||||
class JKRHeap;
|
class JKRHeap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup jsystem-jkernel
|
* @ingroup jsystem-jkernel
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct SArcHeader {
|
struct SArcHeader {
|
||||||
/* 0x00 */ BE(u32) signature;
|
/* 0x00 */ BE(u32) signature;
|
||||||
@@ -25,7 +31,7 @@ struct SArcHeader {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup jsystem-jkernel
|
* @ingroup jsystem-jkernel
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct SArcDataInfo {
|
struct SArcDataInfo {
|
||||||
/* 0x00 */ BE(u32) num_nodes;
|
/* 0x00 */ BE(u32) num_nodes;
|
||||||
@@ -59,7 +65,7 @@ extern u32 sCurrentDirID__10JKRArchive; // JKRArchive::sCurrentDirID
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup jsystem-jkernel
|
* @ingroup jsystem-jkernel
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class JKRArchive : public JKRFileLoader {
|
class JKRArchive : public JKRFileLoader {
|
||||||
public:
|
public:
|
||||||
@@ -192,9 +198,7 @@ public:
|
|||||||
u32 countFile() const { return mArcInfoBlock->num_file_entries; }
|
u32 countFile() const { return mArcInfoBlock->num_file_entries; }
|
||||||
s32 countDirectory() const { return mArcInfoBlock->num_nodes; }
|
s32 countDirectory() const { return mArcInfoBlock->num_nodes; }
|
||||||
u8 getMountMode() const { return mMountMode; }
|
u8 getMountMode() const { return mMountMode; }
|
||||||
bool isFileEntry(u32 param_0) const {
|
bool isFileEntry(u32 param_0) const { return getFileAttribute(param_0) & 1; }
|
||||||
return getFileAttribute(param_0) & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* 0x00 */ // vtable
|
/* 0x00 */ // vtable
|
||||||
@@ -210,7 +214,36 @@ public:
|
|||||||
/* 0x54 */ const char* mStringTable;
|
/* 0x54 */ const char* mStringTable;
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
|
u32 getFileSize(SDIFileEntry* entry) const;
|
||||||
|
void* getOverlayData(SDIFileEntry* entry, u32* outSize);
|
||||||
|
bool getOverlayFileSize(SDIFileEntry* entry, u32* outSize) const;
|
||||||
|
static void notifyOverlayFilesChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
void** mFileData;
|
void** mFileData;
|
||||||
|
|
||||||
|
struct ArcOverlayResource {
|
||||||
|
u32 entryIndex;
|
||||||
|
u32 size;
|
||||||
|
u64 generation;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Resource pointers remain valid until removed through the JKR resource APIs.
|
||||||
|
// That way, any pointers to old overlay data remain valid even when the overlay changed.
|
||||||
|
std::unordered_map<void*, ArcOverlayResource> mArcOverlayResources;
|
||||||
|
mutable std::unordered_map<u32, void*> mActiveArcOverlayResources;
|
||||||
|
mutable std::string mArcOverlaysPath;
|
||||||
|
mutable std::unordered_map<u32, std::string> mIdxToPathMap;
|
||||||
|
mutable bool mArcOverlaysPathResolved = false;
|
||||||
|
|
||||||
|
bool buildArcOverlaysPath() const;
|
||||||
|
void buildIndexToPathMap(u32 dirIndex, const std::string& currentPath) const;
|
||||||
|
bool getOverlayPath(SDIFileEntry* entry, std::string& path) const;
|
||||||
|
void* getActiveOverlayData(SDIFileEntry* entry, u32* outSize) const;
|
||||||
|
bool copyOverlayData(void* buffer, u32 bufferSize, SDIFileEntry* entry, u32* outSize);
|
||||||
|
bool getOverlayResourceSize(const void* data, u32* outSize) const;
|
||||||
|
bool removeOverlayResource(void* resource, bool freeResource);
|
||||||
|
void removeAllOverlayResources();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -234,7 +267,7 @@ public:
|
|||||||
} else if (attr & JKRARCHIVE_ATTR_YAZ0) {
|
} else if (attr & JKRARCHIVE_ATTR_YAZ0) {
|
||||||
return COMPRESSION_YAZ0;
|
return COMPRESSION_YAZ0;
|
||||||
} else {
|
} else {
|
||||||
return COMPRESSION_YAY0;
|
return COMPRESSION_YAY0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +276,9 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
static DUSK_GAME_DATA u32 sCurrentDirID;
|
static DUSK_GAME_DATA u32 sCurrentDirID;
|
||||||
|
#if TARGET_PC
|
||||||
|
static std::atomic<u64> sArcOverlayGeneration;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
inline JKRCompression JKRConvertAttrToCompressionType(int attr) {
|
inline JKRCompression JKRConvertAttrToCompressionType(int attr) {
|
||||||
@@ -261,8 +297,8 @@ inline bool JKRRemoveResource(void* resource, JKRFileLoader* fileLoader) {
|
|||||||
return JKRFileLoader::removeResource(resource, fileLoader);
|
return JKRFileLoader::removeResource(resource, fileLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JKRArchive* JKRMountArchive(void* ptr, JKRHeap* heap,
|
inline JKRArchive* JKRMountArchive(
|
||||||
JKRArchive::EMountDirection mountDirection) {
|
void* ptr, JKRHeap* heap, JKRArchive::EMountDirection mountDirection) {
|
||||||
return JKRArchive::mount(ptr, heap, mountDirection);
|
return JKRArchive::mount(ptr, heap, mountDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <new>
|
#include <new>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
class JKRHeap;
|
class JKRHeap;
|
||||||
typedef void (*JKRErrorHandler)(void*, u32, int);
|
typedef void (*JKRErrorHandler)(void*, u32, int);
|
||||||
|
|||||||
@@ -174,10 +174,14 @@ struct TProcessor {
|
|||||||
}
|
}
|
||||||
void on_character(int iCharacter) { do_character(iCharacter); }
|
void on_character(int iCharacter) { do_character(iCharacter); }
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
const char* on_message_limited(u16 u16Index) const;
|
||||||
|
#else
|
||||||
const char* on_message_limited(u16 u16Index) const {
|
const char* on_message_limited(u16 u16Index) const {
|
||||||
JUT_ASSERT(482, pResourceCache_!=NULL);
|
JUT_ASSERT(482, pResourceCache_!=NULL);
|
||||||
return pResourceCache_->getMessageText_messageIndex(u16Index);
|
return pResourceCache_->getMessageText_messageIndex(u16Index);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool on_setBegin_isReady_() const { return do_setBegin_isReady_(); }
|
bool on_setBegin_isReady_() const { return do_setBegin_isReady_(); }
|
||||||
|
|
||||||
@@ -195,6 +199,10 @@ struct TProcessor {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
void* getMessageEntry_messageCode(u16 u16Code, u16 u16Index) const;
|
||||||
|
const char* getMessageText_messageCode(u16 u16Code, u16 u16Index) const;
|
||||||
|
#else
|
||||||
void* getMessageEntry_messageCode(u16 u16Code, u16 u16Index) const {
|
void* getMessageEntry_messageCode(u16 u16Code, u16 u16Index) const {
|
||||||
const TResource* pResource = getResource_groupID(u16Code);
|
const TResource* pResource = getResource_groupID(u16Code);
|
||||||
|
|
||||||
@@ -214,6 +222,7 @@ struct TProcessor {
|
|||||||
|
|
||||||
return pResourceCache_->getMessageText_messageEntry(pEntry);
|
return pResourceCache_->getMessageText_messageEntry(pEntry);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void stack_pushCurrent_(const char* pszText) {
|
void stack_pushCurrent_(const char* pszText) {
|
||||||
oStack_.push(getCurrent());
|
oStack_.push(getCurrent());
|
||||||
|
|||||||
@@ -7,9 +7,6 @@
|
|||||||
#include "JSystem/J3DGraphBase/J3DMaterial.h"
|
#include "JSystem/J3DGraphBase/J3DMaterial.h"
|
||||||
#include "JSystem/JMath/JMath.h"
|
#include "JSystem/JMath/JMath.h"
|
||||||
#include "m_Do/m_Do_mtx.h"
|
#include "m_Do/m_Do_mtx.h"
|
||||||
#if TARGET_PC
|
|
||||||
#include "dusk/settings.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void J3DMtxCalcJ3DSysInitBasic::init(Vec const& scale, Mtx const& mtx) {
|
void J3DMtxCalcJ3DSysInitBasic::init(Vec const& scale, Mtx const& mtx) {
|
||||||
J3DSys::mCurrentS = scale;
|
J3DSys::mCurrentS = scale;
|
||||||
@@ -181,23 +178,7 @@ void J3DJoint::entryIn() {
|
|||||||
matPacket->setMaterialAnmID(mesh->getMaterialAnm());
|
matPacket->setMaterialAnmID(mesh->getMaterialAnm());
|
||||||
matPacket->setShapePacket(shapePacket);
|
matPacket->setShapePacket(shapePacket);
|
||||||
bool isDrawModeOpaTexEdge = mesh->isDrawModeOpaTexEdge() == FALSE;
|
bool isDrawModeOpaTexEdge = mesh->isDrawModeOpaTexEdge() == FALSE;
|
||||||
#if TARGET_PC
|
|
||||||
// TP HD J3DJoint::entryIn (FUN_02b57690):
|
|
||||||
J3DDrawBuffer* drawBuffer = j3dSys.getDrawBuffer(isDrawModeOpaTexEdge);
|
|
||||||
u8 r24;
|
|
||||||
if (dusk::tphd_active() && (mesh->mMaterialID & 0x80000000) != 0 &&
|
|
||||||
(mesh->getMaterialMode() & 0x20) != 0 &&
|
|
||||||
drawBuffer->getSortMode() == J3DDrawBufSortMode_Mat)
|
|
||||||
{
|
|
||||||
matPacket->drawClear();
|
|
||||||
shapePacket->drawClear();
|
|
||||||
r24 = drawBuffer->entryImm(matPacket, 1);
|
|
||||||
} else {
|
|
||||||
r24 = matPacket->entry(drawBuffer);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
u8 r24 = matPacket->entry(j3dSys.getDrawBuffer(isDrawModeOpaTexEdge));
|
u8 r24 = matPacket->entry(j3dSys.getDrawBuffer(isDrawModeOpaTexEdge));
|
||||||
#endif
|
|
||||||
if (r24) {
|
if (r24) {
|
||||||
j3dSys.setMatPacket(matPacket);
|
j3dSys.setMatPacket(matPacket);
|
||||||
J3DDrawBuffer::entryNum++;
|
J3DDrawBuffer::entryNum++;
|
||||||
|
|||||||
@@ -230,13 +230,6 @@ void J3DMatPacket::draw() {
|
|||||||
#endif
|
#endif
|
||||||
packet->getShape()->loadPreDrawSetting();
|
packet->getShape()->loadPreDrawSetting();
|
||||||
|
|
||||||
#if DUSK_TPHD
|
|
||||||
{
|
|
||||||
const auto* offs = mpMaterial->getPEBlock()->getPolygonOffset();
|
|
||||||
GX2SetPolygonOffset(offs->mFrontOffset, offs->mFrontScale, offs->mBackOffset, offs->mBackScale, offs->mClamp);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (packet != NULL) {
|
while (packet != NULL) {
|
||||||
if (packet->getDisplayListObj() != NULL) {
|
if (packet->getDisplayListObj() != NULL) {
|
||||||
packet->getDisplayListObj()->callDL();
|
packet->getDisplayListObj()->callDL();
|
||||||
|
|||||||
@@ -12,9 +12,6 @@
|
|||||||
#include "dusk/logging.h"
|
#include "dusk/logging.h"
|
||||||
|
|
||||||
J3DMaterialFactory::J3DMaterialFactory(J3DMaterialBlock const& i_block) {
|
J3DMaterialFactory::J3DMaterialFactory(J3DMaterialBlock const& i_block) {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
mBlockType = (i_block.mBlockType & 0xFF) - 0x30; // get number at last byte of block name
|
|
||||||
#endif
|
|
||||||
mMaterialNum = i_block.mMaterialNum;
|
mMaterialNum = i_block.mMaterialNum;
|
||||||
mpMaterialInitData = JSUConvertOffsetToPtr<J3DMaterialInitData>(&i_block, i_block.mpMaterialInitData);
|
mpMaterialInitData = JSUConvertOffsetToPtr<J3DMaterialInitData>(&i_block, i_block.mpMaterialInitData);
|
||||||
mpMaterialID = JSUConvertOffsetToPtr<BE(u16)>(&i_block, i_block.mpMaterialID);
|
mpMaterialID = JSUConvertOffsetToPtr<BE(u16)>(&i_block, i_block.mpMaterialID);
|
||||||
@@ -49,11 +46,6 @@ J3DMaterialFactory::J3DMaterialFactory(J3DMaterialBlock const& i_block) {
|
|||||||
mpZCompLoc = JSUConvertOffsetToPtr<u8>(&i_block, i_block.mpZCompLoc);
|
mpZCompLoc = JSUConvertOffsetToPtr<u8>(&i_block, i_block.mpZCompLoc);
|
||||||
mpDither = JSUConvertOffsetToPtr<u8>(&i_block, i_block.mpDither);
|
mpDither = JSUConvertOffsetToPtr<u8>(&i_block, i_block.mpDither);
|
||||||
mpNBTScaleInfo = JSUConvertOffsetToPtr<J3DNBTScaleInfo>(&i_block, i_block.mpNBTScaleInfo);
|
mpNBTScaleInfo = JSUConvertOffsetToPtr<J3DNBTScaleInfo>(&i_block, i_block.mpNBTScaleInfo);
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
if(mBlockType >= 4) {
|
|
||||||
mpPolygonOffsets = JSUConvertOffsetToPtr<PolygonOffset>(&i_block, reinterpret_cast<const J3DMaterialBlock_MAT4&>(i_block).mpPolygonOffsets);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
mpDisplayListInit = NULL;
|
mpDisplayListInit = NULL;
|
||||||
mpPatchingInfo = NULL;
|
mpPatchingInfo = NULL;
|
||||||
mpCurrentMtxInfo = NULL;
|
mpCurrentMtxInfo = NULL;
|
||||||
@@ -82,11 +74,7 @@ u16 J3DMaterialFactory::countUniqueMaterials() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 J3DMaterialFactory::countTexGens(int i_idx) const {
|
u32 J3DMaterialFactory::countTexGens(int i_idx) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mTexGenNumIdx != 0xff) {
|
if (mtl_init_data->mTexGenNumIdx != 0xff) {
|
||||||
return mpTexGenNum[mtl_init_data->mTexGenNumIdx];
|
return mpTexGenNum[mtl_init_data->mTexGenNumIdx];
|
||||||
}
|
}
|
||||||
@@ -94,11 +82,7 @@ u32 J3DMaterialFactory::countTexGens(int i_idx) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 J3DMaterialFactory::countStages(int i_idx) const {
|
u32 J3DMaterialFactory::countStages(int i_idx) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
u32 count1 = 0;
|
u32 count1 = 0;
|
||||||
u32 count2 = 0;
|
u32 count2 = 0;
|
||||||
if (mtl_init_data->mTevStageNumIdx != 0xff) {
|
if (mtl_init_data->mTevStageNumIdx != 0xff) {
|
||||||
@@ -173,9 +157,6 @@ J3DMaterial* J3DMaterialFactory::createNormalMaterial(J3DMaterial* i_material, i
|
|||||||
i_material->mPEBlock->setZMode(newZMode(i_idx));
|
i_material->mPEBlock->setZMode(newZMode(i_idx));
|
||||||
i_material->mPEBlock->setZCompLoc(newZCompLoc(i_idx));
|
i_material->mPEBlock->setZCompLoc(newZCompLoc(i_idx));
|
||||||
i_material->mPEBlock->setDither(newDither(i_idx));
|
i_material->mPEBlock->setDither(newDither(i_idx));
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
i_material->mPEBlock->setPolygonOffset(newPolygonOffset(i_idx));
|
|
||||||
#endif
|
|
||||||
i_material->mTevBlock->setTevStageNum(newTevStageNum(i_idx));
|
i_material->mTevBlock->setTevStageNum(newTevStageNum(i_idx));
|
||||||
for (u8 i = 0; i < tex_num; i++) {
|
for (u8 i = 0; i < tex_num; i++) {
|
||||||
i_material->mTevBlock->setTexNo(i, newTexNo(i_idx, i));
|
i_material->mTevBlock->setTexNo(i, newTexNo(i_idx, i));
|
||||||
@@ -184,11 +165,7 @@ J3DMaterial* J3DMaterialFactory::createNormalMaterial(J3DMaterial* i_material, i
|
|||||||
i_material->mTevBlock->setTevOrder(i, newTevOrder(i_idx, i));
|
i_material->mTevBlock->setTevOrder(i, newTevOrder(i_idx, i));
|
||||||
}
|
}
|
||||||
for (u8 i = 0; i < tev_stage_num_max; i++) {
|
for (u8 i = 0; i < tev_stage_num_max; i++) {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* material_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
i_material->mTevBlock->setTevStage(i, newTevStage(i_idx, i));
|
i_material->mTevBlock->setTevStage(i, newTevStage(i_idx, i));
|
||||||
if (material_init_data->mTevSwapModeIdx[i] != 0xffff) {
|
if (material_init_data->mTevSwapModeIdx[i] != 0xffff) {
|
||||||
i_material->mTevBlock->getTevStage(i)->setTexSel(
|
i_material->mTevBlock->getTevStage(i)->setTexSel(
|
||||||
@@ -223,11 +200,7 @@ J3DMaterial* J3DMaterialFactory::createNormalMaterial(J3DMaterial* i_material, i
|
|||||||
for (u8 i = 0; i < 8; i++) {
|
for (u8 i = 0; i < 8; i++) {
|
||||||
i_material->mTexGenBlock->setTexMtx(i, newTexMtx(i_idx, i));
|
i_material->mTexGenBlock->setTexMtx(i, newTexMtx(i_idx, i));
|
||||||
}
|
}
|
||||||
#ifdef DUSK_TPHD
|
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
J3DMaterialInitData* material_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
|
||||||
#endif
|
|
||||||
for (u8 i = 0; i < tev_stage_num_max; i++) {
|
for (u8 i = 0; i < tev_stage_num_max; i++) {
|
||||||
if (material_init_data->mTevKColorSel[i] != 0xff) {
|
if (material_init_data->mTevKColorSel[i] != 0xff) {
|
||||||
i_material->mTevBlock->setTevKColorSel(i, material_init_data->mTevKColorSel[i]);
|
i_material->mTevBlock->setTevKColorSel(i, material_init_data->mTevKColorSel[i]);
|
||||||
@@ -300,11 +273,7 @@ J3DMaterial* J3DMaterialFactory::createPatchedMaterial(J3DMaterial* i_material,
|
|||||||
i_material->mTevBlock->setTevColor(i, newTevColor(i_idx, i));
|
i_material->mTevBlock->setTevColor(i, newTevColor(i_idx, i));
|
||||||
}
|
}
|
||||||
for (u8 i = 0; i < tev_stage_num; i++) {
|
for (u8 i = 0; i < tev_stage_num; i++) {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* material_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* material_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
i_material->mTevBlock->setTevStage(i, newTevStage(i_idx, i));
|
i_material->mTevBlock->setTevStage(i, newTevStage(i_idx, i));
|
||||||
if (material_init_data->mTevSwapModeIdx[i] != 0xffff) {
|
if (material_init_data->mTevSwapModeIdx[i] != 0xffff) {
|
||||||
i_material->mTevBlock->getTevStage(i)->setTexSel(
|
i_material->mTevBlock->getTevStage(i)->setTexSel(
|
||||||
@@ -313,11 +282,7 @@ J3DMaterial* J3DMaterialFactory::createPatchedMaterial(J3DMaterial* i_material,
|
|||||||
mpTevSwapModeInfo[material_init_data->mTevSwapModeIdx[i]].mRasSel);
|
mpTevSwapModeInfo[material_init_data->mTevSwapModeIdx[i]].mRasSel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DUSK_TPHD
|
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
J3DMaterialInitData* init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
|
||||||
#endif
|
|
||||||
for (u8 i = 0; i < tev_stage_num; i++) {
|
for (u8 i = 0; i < tev_stage_num; i++) {
|
||||||
if (init_data->mTevKColorSel[i] != 0xff) {
|
if (init_data->mTevKColorSel[i] != 0xff) {
|
||||||
i_material->mTevBlock->setTevKColorSel(i, init_data->mTevKColorSel[i]);
|
i_material->mTevBlock->setTevKColorSel(i, init_data->mTevKColorSel[i]);
|
||||||
@@ -458,11 +423,7 @@ u32 J3DMaterialFactory::calcSizeNormalMaterial(J3DMaterial* i_material, int i_id
|
|||||||
size += J3DMaterial::calcSizeTevBlock((u16)tev_stage_num_max);
|
size += J3DMaterial::calcSizeTevBlock((u16)tev_stage_num_max);
|
||||||
size += J3DMaterial::calcSizeIndBlock(ind_flag);
|
size += J3DMaterial::calcSizeIndBlock(ind_flag);
|
||||||
size += J3DMaterial::calcSizePEBlock(pe_flag, getMaterialMode(i_idx));
|
size += J3DMaterial::calcSizePEBlock(pe_flag, getMaterialMode(i_idx));
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
for (u32 i = 0; i < 8; i++) {
|
for (u32 i = 0; i < 8; i++) {
|
||||||
if (init_data->mTexMtxIdx[i] != 0xffff) {
|
if (init_data->mTexMtxIdx[i] != 0xffff) {
|
||||||
size += sizeof(J3DTexMtx);
|
size += sizeof(J3DTexMtx);
|
||||||
@@ -483,11 +444,7 @@ u32 J3DMaterialFactory::calcSizePatchedMaterial(J3DMaterial* i_material, int i_i
|
|||||||
size += sizeof(J3DTevBlockPatched);
|
size += sizeof(J3DTevBlockPatched);
|
||||||
size += J3DMaterial::calcSizeIndBlock(ind_flag);
|
size += J3DMaterial::calcSizeIndBlock(ind_flag);
|
||||||
size += J3DMaterial::calcSizePEBlock(0x10000000, getMaterialMode(i_idx));
|
size += J3DMaterial::calcSizePEBlock(0x10000000, getMaterialMode(i_idx));
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
for (u32 i = 0; i < 8; i++) {
|
for (u32 i = 0; i < 8; i++) {
|
||||||
if (init_data->mTexMtxIdx[i] != 0xffff) {
|
if (init_data->mTexMtxIdx[i] != 0xffff) {
|
||||||
size += sizeof(J3DTexMtx);
|
size += sizeof(J3DTexMtx);
|
||||||
@@ -517,11 +474,7 @@ J3DGXColor J3DMaterialFactory::newMatColor(int i_idx, int i_no) const {
|
|||||||
#else
|
#else
|
||||||
J3DGXColor dflt = GXColor{0xff, 0xff, 0xff, 0xff};
|
J3DGXColor dflt = GXColor{0xff, 0xff, 0xff, 0xff};
|
||||||
#endif
|
#endif
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mMatColorIdx[i_no] != 0xffff) {
|
if (mtl_init_data->mMatColorIdx[i_no] != 0xffff) {
|
||||||
return (GXColor) mpMatColor[mtl_init_data->mMatColorIdx[i_no]];
|
return (GXColor) mpMatColor[mtl_init_data->mMatColorIdx[i_no]];
|
||||||
} else {
|
} else {
|
||||||
@@ -530,11 +483,7 @@ J3DGXColor J3DMaterialFactory::newMatColor(int i_idx, int i_no) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const u8 J3DMaterialFactory::newColorChanNum(int i_idx) const {
|
const u8 J3DMaterialFactory::newColorChanNum(int i_idx) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mColorChanNumIdx != 0xff) {
|
if (mtl_init_data->mColorChanNumIdx != 0xff) {
|
||||||
return mpColorChanNum[mtl_init_data->mColorChanNumIdx];
|
return mpColorChanNum[mtl_init_data->mColorChanNumIdx];
|
||||||
} else {
|
} else {
|
||||||
@@ -544,11 +493,7 @@ const u8 J3DMaterialFactory::newColorChanNum(int i_idx) const {
|
|||||||
|
|
||||||
J3DColorChan J3DMaterialFactory::newColorChan(int i_idx, int i_no) const {
|
J3DColorChan J3DMaterialFactory::newColorChan(int i_idx, int i_no) const {
|
||||||
u32 r29 = 0;
|
u32 r29 = 0;
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (init_data->mColorChanIdx[i_no] != 0xffff) {
|
if (init_data->mColorChanIdx[i_no] != 0xffff) {
|
||||||
return J3DColorChan(mpColorChanInfo[init_data->mColorChanIdx[i_no]]);
|
return J3DColorChan(mpColorChanInfo[init_data->mColorChanIdx[i_no]]);
|
||||||
} else {
|
} else {
|
||||||
@@ -562,11 +507,7 @@ J3DGXColor J3DMaterialFactory::newAmbColor(int i_idx, int i_no) const {
|
|||||||
#else
|
#else
|
||||||
J3DGXColor dflt = GXColor{0x32, 0x32, 0x32, 0x32};
|
J3DGXColor dflt = GXColor{0x32, 0x32, 0x32, 0x32};
|
||||||
#endif
|
#endif
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mAmbColorIdx[i_no] != 0xffff) {
|
if (mtl_init_data->mAmbColorIdx[i_no] != 0xffff) {
|
||||||
return (GXColor) mpAmbColor[mtl_init_data->mAmbColorIdx[i_no]];
|
return (GXColor) mpAmbColor[mtl_init_data->mAmbColorIdx[i_no]];
|
||||||
} else {
|
} else {
|
||||||
@@ -576,11 +517,7 @@ J3DGXColor J3DMaterialFactory::newAmbColor(int i_idx, int i_no) const {
|
|||||||
|
|
||||||
u32 J3DMaterialFactory::newTexGenNum(int i_idx) const {
|
u32 J3DMaterialFactory::newTexGenNum(int i_idx) const {
|
||||||
u32 r30 = 0;
|
u32 r30 = 0;
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mTexGenNumIdx != 0xff) {
|
if (mtl_init_data->mTexGenNumIdx != 0xff) {
|
||||||
return mpTexGenNum[mtl_init_data->mTexGenNumIdx];
|
return mpTexGenNum[mtl_init_data->mTexGenNumIdx];
|
||||||
} else {
|
} else {
|
||||||
@@ -589,11 +526,7 @@ u32 J3DMaterialFactory::newTexGenNum(int i_idx) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
J3DTexCoord J3DMaterialFactory::newTexCoord(int i_idx, int i_no) const {
|
J3DTexCoord J3DMaterialFactory::newTexCoord(int i_idx, int i_no) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mTexCoordIdx[i_no] != 0xffff) {
|
if (mtl_init_data->mTexCoordIdx[i_no] != 0xffff) {
|
||||||
return J3DTexCoord(mpTexCoordInfo[mtl_init_data->mTexCoordIdx[i_no]]);
|
return J3DTexCoord(mpTexCoordInfo[mtl_init_data->mTexCoordIdx[i_no]]);
|
||||||
} else {
|
} else {
|
||||||
@@ -603,11 +536,7 @@ J3DTexCoord J3DMaterialFactory::newTexCoord(int i_idx, int i_no) const {
|
|||||||
|
|
||||||
J3DTexMtx* J3DMaterialFactory::newTexMtx(int i_idx, int i_no) const {
|
J3DTexMtx* J3DMaterialFactory::newTexMtx(int i_idx, int i_no) const {
|
||||||
J3DTexMtx* tex_mtx = NULL;
|
J3DTexMtx* tex_mtx = NULL;
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mTexMtxIdx[i_no] != 0xffff) {
|
if (mtl_init_data->mTexMtxIdx[i_no] != 0xffff) {
|
||||||
#if TARGET_LITTLE_ENDIAN
|
#if TARGET_LITTLE_ENDIAN
|
||||||
auto tex_mtx_info = mpTexMtxInfo[mtl_init_data->mTexMtxIdx[i_no]];
|
auto tex_mtx_info = mpTexMtxInfo[mtl_init_data->mTexMtxIdx[i_no]];
|
||||||
@@ -629,11 +558,7 @@ J3DTexMtx* J3DMaterialFactory::newTexMtx(int i_idx, int i_no) const {
|
|||||||
|
|
||||||
u8 J3DMaterialFactory::newCullMode(int i_idx) const {
|
u8 J3DMaterialFactory::newCullMode(int i_idx) const {
|
||||||
u32 r30 = 0;
|
u32 r30 = 0;
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mCullModeIdx != 0xff) {
|
if (mtl_init_data->mCullModeIdx != 0xff) {
|
||||||
return mpCullMode[mtl_init_data->mCullModeIdx];
|
return mpCullMode[mtl_init_data->mCullModeIdx];
|
||||||
} else {
|
} else {
|
||||||
@@ -642,11 +567,7 @@ u8 J3DMaterialFactory::newCullMode(int i_idx) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u16 J3DMaterialFactory::newTexNo(int i_idx, int i_no) const {
|
u16 J3DMaterialFactory::newTexNo(int i_idx, int i_no) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mTexNoIdx[i_no] != 0xffff) {
|
if (mtl_init_data->mTexNoIdx[i_no] != 0xffff) {
|
||||||
return mpTexNo[mtl_init_data->mTexNoIdx[i_no]];
|
return mpTexNo[mtl_init_data->mTexNoIdx[i_no]];
|
||||||
} else {
|
} else {
|
||||||
@@ -655,11 +576,7 @@ u16 J3DMaterialFactory::newTexNo(int i_idx, int i_no) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
J3DTevOrder J3DMaterialFactory::newTevOrder(int i_idx, int i_no) const {
|
J3DTevOrder J3DMaterialFactory::newTevOrder(int i_idx, int i_no) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mTevOrderIdx[i_no] != 0xffff) {
|
if (mtl_init_data->mTevOrderIdx[i_no] != 0xffff) {
|
||||||
return J3DTevOrder(mpTevOrderInfo[mtl_init_data->mTevOrderIdx[i_no]]);
|
return J3DTevOrder(mpTevOrderInfo[mtl_init_data->mTevOrderIdx[i_no]]);
|
||||||
} else {
|
} else {
|
||||||
@@ -670,11 +587,7 @@ J3DTevOrder J3DMaterialFactory::newTevOrder(int i_idx, int i_no) const {
|
|||||||
J3DGXColorS10 J3DMaterialFactory::newTevColor(int i_idx, int i_no) const {
|
J3DGXColorS10 J3DMaterialFactory::newTevColor(int i_idx, int i_no) const {
|
||||||
GXColorS10 _dflt = {0, 0, 0, 0};
|
GXColorS10 _dflt = {0, 0, 0, 0};
|
||||||
J3DGXColorS10 dflt = _dflt;
|
J3DGXColorS10 dflt = _dflt;
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mTevColorIdx[i_no] != 0xffff) {
|
if (mtl_init_data->mTevColorIdx[i_no] != 0xffff) {
|
||||||
return (GXColorS10) mpTevColor[mtl_init_data->mTevColorIdx[i_no]];
|
return (GXColorS10) mpTevColor[mtl_init_data->mTevColorIdx[i_no]];
|
||||||
} else {
|
} else {
|
||||||
@@ -688,11 +601,7 @@ J3DGXColor J3DMaterialFactory::newTevKColor(int i_idx, int i_no) const {
|
|||||||
#else
|
#else
|
||||||
J3DGXColor dflt = GXColor{0xff, 0xff, 0xff, 0xff};
|
J3DGXColor dflt = GXColor{0xff, 0xff, 0xff, 0xff};
|
||||||
#endif
|
#endif
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mTevKColorIdx[i_no] != 0xffff) {
|
if (mtl_init_data->mTevKColorIdx[i_no] != 0xffff) {
|
||||||
return (GXColor) mpTevKColor[mtl_init_data->mTevKColorIdx[i_no]];
|
return (GXColor) mpTevKColor[mtl_init_data->mTevKColorIdx[i_no]];
|
||||||
} else {
|
} else {
|
||||||
@@ -701,11 +610,7 @@ J3DGXColor J3DMaterialFactory::newTevKColor(int i_idx, int i_no) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const u8 J3DMaterialFactory::newTevStageNum(int i_idx) const {
|
const u8 J3DMaterialFactory::newTevStageNum(int i_idx) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mTevStageNumIdx != 0xff) {
|
if (mtl_init_data->mTevStageNumIdx != 0xff) {
|
||||||
return mpTevStageNum[mtl_init_data->mTevStageNumIdx];
|
return mpTevStageNum[mtl_init_data->mTevStageNumIdx];
|
||||||
} else {
|
} else {
|
||||||
@@ -714,11 +619,7 @@ const u8 J3DMaterialFactory::newTevStageNum(int i_idx) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
J3DTevStage J3DMaterialFactory::newTevStage(int i_idx, int i_no) const {
|
J3DTevStage J3DMaterialFactory::newTevStage(int i_idx, int i_no) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mTevStageIdx[i_no] != 0xffff) {
|
if (mtl_init_data->mTevStageIdx[i_no] != 0xffff) {
|
||||||
return J3DTevStage(mpTevStageInfo[mtl_init_data->mTevStageIdx[i_no]]);
|
return J3DTevStage(mpTevStageInfo[mtl_init_data->mTevStageIdx[i_no]]);
|
||||||
} else {
|
} else {
|
||||||
@@ -727,11 +628,7 @@ J3DTevStage J3DMaterialFactory::newTevStage(int i_idx, int i_no) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
J3DTevSwapModeTable J3DMaterialFactory::newTevSwapModeTable(int i_idx, int i_no) const {
|
J3DTevSwapModeTable J3DMaterialFactory::newTevSwapModeTable(int i_idx, int i_no) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mTevSwapModeTableIdx[i_no] != 0xffff) {
|
if (mtl_init_data->mTevSwapModeTableIdx[i_no] != 0xffff) {
|
||||||
return J3DTevSwapModeTable(mpTevSwapModeTableInfo[mtl_init_data->mTevSwapModeTableIdx[i_no]]);
|
return J3DTevSwapModeTable(mpTevSwapModeTableInfo[mtl_init_data->mTevSwapModeTableIdx[i_no]]);
|
||||||
} else {
|
} else {
|
||||||
@@ -792,11 +689,7 @@ J3DIndTexCoordScale J3DMaterialFactory::newIndTexCoordScale(int i_idx, int i_no)
|
|||||||
|
|
||||||
J3DFog J3DMaterialFactory::newFog(int i_idx) const {
|
J3DFog J3DMaterialFactory::newFog(int i_idx) const {
|
||||||
J3DFog fog;
|
J3DFog fog;
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mFogIdx != 0xffff) {
|
if (mtl_init_data->mFogIdx != 0xffff) {
|
||||||
#if TARGET_LITTLE_ENDIAN
|
#if TARGET_LITTLE_ENDIAN
|
||||||
J3DFogInfo fogInfo = mpFogInfo[mtl_init_data->mFogIdx];
|
J3DFogInfo fogInfo = mpFogInfo[mtl_init_data->mFogIdx];
|
||||||
@@ -816,11 +709,7 @@ J3DFog J3DMaterialFactory::newFog(int i_idx) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
J3DAlphaComp J3DMaterialFactory::newAlphaComp(int i_idx) const {
|
J3DAlphaComp J3DMaterialFactory::newAlphaComp(int i_idx) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mAlphaCompIdx != 0xffff) {
|
if (mtl_init_data->mAlphaCompIdx != 0xffff) {
|
||||||
return J3DAlphaComp(mpAlphaCompInfo[mtl_init_data->mAlphaCompIdx]);
|
return J3DAlphaComp(mpAlphaCompInfo[mtl_init_data->mAlphaCompIdx]);
|
||||||
} else {
|
} else {
|
||||||
@@ -829,11 +718,7 @@ J3DAlphaComp J3DMaterialFactory::newAlphaComp(int i_idx) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
J3DBlend J3DMaterialFactory::newBlend(int i_idx) const {
|
J3DBlend J3DMaterialFactory::newBlend(int i_idx) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mBlendIdx != 0xffff) {
|
if (mtl_init_data->mBlendIdx != 0xffff) {
|
||||||
return J3DBlend(mpBlendInfo[mtl_init_data->mBlendIdx]);
|
return J3DBlend(mpBlendInfo[mtl_init_data->mBlendIdx]);
|
||||||
} else {
|
} else {
|
||||||
@@ -843,11 +728,7 @@ J3DBlend J3DMaterialFactory::newBlend(int i_idx) const {
|
|||||||
|
|
||||||
J3DZMode J3DMaterialFactory::newZMode(int i_idx) const {
|
J3DZMode J3DMaterialFactory::newZMode(int i_idx) const {
|
||||||
u32 r29 = 0;
|
u32 r29 = 0;
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mZModeIdx != 0xff) {
|
if (mtl_init_data->mZModeIdx != 0xff) {
|
||||||
return J3DZMode(mpZModeInfo[mtl_init_data->mZModeIdx]);
|
return J3DZMode(mpZModeInfo[mtl_init_data->mZModeIdx]);
|
||||||
} else {
|
} else {
|
||||||
@@ -856,11 +737,7 @@ J3DZMode J3DMaterialFactory::newZMode(int i_idx) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const u8 J3DMaterialFactory::newZCompLoc(int i_idx) const {
|
const u8 J3DMaterialFactory::newZCompLoc(int i_idx) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mZCompLocIdx != 0xff){
|
if (mtl_init_data->mZCompLocIdx != 0xff){
|
||||||
return mpZCompLoc[mtl_init_data->mZCompLocIdx];
|
return mpZCompLoc[mtl_init_data->mZCompLocIdx];
|
||||||
} else {
|
} else {
|
||||||
@@ -869,11 +746,7 @@ const u8 J3DMaterialFactory::newZCompLoc(int i_idx) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const u8 J3DMaterialFactory::newDither(int i_idx) const {
|
const u8 J3DMaterialFactory::newDither(int i_idx) const {
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mDitherIdx != 0xff){
|
if (mtl_init_data->mDitherIdx != 0xff){
|
||||||
return mpDither[mtl_init_data->mDitherIdx];
|
return mpDither[mtl_init_data->mDitherIdx];
|
||||||
} else {
|
} else {
|
||||||
@@ -881,24 +754,9 @@ const u8 J3DMaterialFactory::newDither(int i_idx) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
const PolygonOffset J3DMaterialFactory::newPolygonOffset(int i_idx) const {
|
|
||||||
J3DMaterialInitData_MAT4* mtl_init_data = (J3DMaterialInitData_MAT4*)getMatInitData(i_idx);
|
|
||||||
if (mBlockType >= 4 && mtl_init_data->mPolygonOffsetIdx != 0xffff){
|
|
||||||
return mpPolygonOffsets[mtl_init_data->mPolygonOffsetIdx];
|
|
||||||
} else {
|
|
||||||
return PolygonOffset{0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
J3DNBTScale J3DMaterialFactory::newNBTScale(int i_idx) const {
|
J3DNBTScale J3DMaterialFactory::newNBTScale(int i_idx) const {
|
||||||
J3DNBTScale dflt(j3dDefaultNBTScaleInfo);
|
J3DNBTScale dflt(j3dDefaultNBTScaleInfo);
|
||||||
#ifdef DUSK_TPHD
|
|
||||||
J3DMaterialInitData* mtl_init_data = getMatInitData(i_idx);
|
|
||||||
#else
|
|
||||||
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
J3DMaterialInitData* mtl_init_data = &mpMaterialInitData[mpMaterialID[i_idx]];
|
||||||
#endif
|
|
||||||
if (mtl_init_data->mNBTScaleIdx != 0xffff) {
|
if (mtl_init_data->mNBTScaleIdx != 0xffff) {
|
||||||
return J3DNBTScale(mpNBTScaleInfo[mtl_init_data->mNBTScaleIdx]);
|
return J3DNBTScale(mpNBTScaleInfo[mtl_init_data->mNBTScaleIdx]);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -103,9 +103,6 @@ J3DModelData* J3DModelLoader::load(void const* i_data, u32 i_flags) {
|
|||||||
readJoint((J3DJointBlock*)block);
|
readJoint((J3DJointBlock*)block);
|
||||||
break;
|
break;
|
||||||
case 'MAT3':
|
case 'MAT3':
|
||||||
#if DUSK_TPHD
|
|
||||||
case 'MAT4':
|
|
||||||
#endif
|
|
||||||
readMaterial((J3DMaterialBlock*)block, (s32)i_flags);
|
readMaterial((J3DMaterialBlock*)block, (s32)i_flags);
|
||||||
break;
|
break;
|
||||||
case 'MAT2':
|
case 'MAT2':
|
||||||
@@ -150,9 +147,6 @@ J3DMaterialTable* J3DModelLoader::loadMaterialTable(void const* i_data) {
|
|||||||
for (u32 block_no = 0; block_no < data->mBlockNum; block_no++) {
|
for (u32 block_no = 0; block_no < data->mBlockNum; block_no++) {
|
||||||
switch (block->mBlockType) {
|
switch (block->mBlockType) {
|
||||||
case 'MAT3':
|
case 'MAT3':
|
||||||
#if DUSK_TPHD
|
|
||||||
case 'MAT4':
|
|
||||||
#endif
|
|
||||||
readMaterialTable((J3DMaterialBlock*)block, flags);
|
readMaterialTable((J3DMaterialBlock*)block, flags);
|
||||||
break;
|
break;
|
||||||
case 'MAT2':
|
case 'MAT2':
|
||||||
@@ -218,9 +212,6 @@ J3DModelData* J3DModelLoader::loadBinaryDisplayList(void const* i_data, u32 i_fl
|
|||||||
modifyMaterial(i_flags);
|
modifyMaterial(i_flags);
|
||||||
break;
|
break;
|
||||||
case 'MAT3':
|
case 'MAT3':
|
||||||
#if DUSK_TPHD
|
|
||||||
case 'MAT4':
|
|
||||||
#endif
|
|
||||||
flags = 0x50100000;
|
flags = 0x50100000;
|
||||||
flags |= (i_flags & 0x3000000);
|
flags |= (i_flags & 0x3000000);
|
||||||
mpMaterialBlock = (J3DMaterialBlock*)block;
|
mpMaterialBlock = (J3DMaterialBlock*)block;
|
||||||
@@ -317,22 +308,8 @@ static GXVtxAttrFmtList getFmt(GXVtxAttrFmtList* i_fmtList, GXAttr i_attr) {
|
|||||||
return *i_fmtList;
|
return *i_fmtList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if DUSK_TPHD
|
|
||||||
// HD BMDs occasionally have vertex arrays without a format entry. Mirror
|
|
||||||
// the GC runtime: fall back to J3DSys::initGX defaults.
|
|
||||||
GXVtxAttrFmtList def{};
|
|
||||||
def.attr = i_attr;
|
|
||||||
def.frac = 0;
|
|
||||||
if (i_attr == GX_VA_POS) { def.cnt = GX_POS_XYZ; def.type = GX_F32; }
|
|
||||||
else if (i_attr == GX_VA_NRM) { def.cnt = GX_NRM_XYZ; def.type = GX_F32; }
|
|
||||||
else if (i_attr == GX_VA_NBT) { def.cnt = GX_NRM_NBT; def.type = GX_F32; }
|
|
||||||
else if (i_attr >= GX_VA_CLR0 &&
|
|
||||||
i_attr <= GX_VA_CLR1) { def.cnt = GX_CLR_RGBA; def.type = GX_RGBA8; }
|
|
||||||
else { def.cnt = GX_TEX_ST; def.type = GX_F32; }
|
|
||||||
return def;
|
|
||||||
#else
|
|
||||||
OSPanic(__FILE__, __LINE__, "Unable to find vertex attribute format!");
|
OSPanic(__FILE__, __LINE__, "Unable to find vertex attribute format!");
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ u16 J3DModelLoader::countMaterialNum(const void* stream) {
|
|||||||
const J3DModelBlock* block = header->mBlocks;
|
const J3DModelBlock* block = header->mBlocks;
|
||||||
for (int i = 0; i < header->mBlockNum; i++)
|
for (int i = 0; i < header->mBlockNum; i++)
|
||||||
{
|
{
|
||||||
if (block->mBlockType == 'MAT3' || block->mBlockType == 'MAT4') {
|
if (block->mBlockType == 'MAT3') {
|
||||||
const J3DMaterialBlock* materialBlock = (const J3DMaterialBlock*)block;
|
const J3DMaterialBlock* materialBlock = (const J3DMaterialBlock*)block;
|
||||||
return materialBlock->mMaterialNum;
|
return materialBlock->mMaterialNum;
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,6 @@ u32 J3DModelLoader::calcLoadSize(void const* stream, u32 flags_) {
|
|||||||
size += calcSizeJoint((const J3DJointBlock*)nextBlock);
|
size += calcSizeJoint((const J3DJointBlock*)nextBlock);
|
||||||
break;
|
break;
|
||||||
case 'MAT3':
|
case 'MAT3':
|
||||||
case 'MAT4':
|
|
||||||
size += calcSizeMaterial((const J3DMaterialBlock*)nextBlock, flags);
|
size += calcSizeMaterial((const J3DMaterialBlock*)nextBlock, flags);
|
||||||
break;
|
break;
|
||||||
case 'SHP1':
|
case 'SHP1':
|
||||||
@@ -87,7 +86,6 @@ u32 J3DModelLoader::calcLoadMaterialTableSize(const void* stream) {
|
|||||||
for (u32 i = 0; i < header->mBlockNum; i++) {
|
for (u32 i = 0; i < header->mBlockNum; i++) {
|
||||||
switch (nextBlock->mBlockType) {
|
switch (nextBlock->mBlockType) {
|
||||||
case 'MAT3':
|
case 'MAT3':
|
||||||
case 'MAT4':
|
|
||||||
size += calcSizeMaterialTable((const J3DMaterialBlock*)nextBlock, flags);
|
size += calcSizeMaterialTable((const J3DMaterialBlock*)nextBlock, flags);
|
||||||
break;
|
break;
|
||||||
case 'TEX1':
|
case 'TEX1':
|
||||||
@@ -137,8 +135,7 @@ u32 J3DModelLoader::calcLoadBinaryDisplayListSize(const void* stream, u32 flags)
|
|||||||
case 'MDL3':
|
case 'MDL3':
|
||||||
size += calcSizeMaterialDL((const J3DMaterialDLBlock*)nextBlock, flags);
|
size += calcSizeMaterialDL((const J3DMaterialDLBlock*)nextBlock, flags);
|
||||||
break;
|
break;
|
||||||
case 'MAT3':
|
case 'MAT3': {
|
||||||
case 'MAT4': {
|
|
||||||
u32 flags2 = (J3DMLF_21 | J3DMLF_Material_PE_Full | J3DMLF_Material_Color_LightOn);
|
u32 flags2 = (J3DMLF_21 | J3DMLF_Material_PE_Full | J3DMLF_Material_Color_LightOn);
|
||||||
flags2 |= (u32)flags & (J3DMLF_Material_UseIndirect | J3DMLF_26);
|
flags2 |= (u32)flags & (J3DMLF_Material_UseIndirect | J3DMLF_26);
|
||||||
mpMaterialBlock = (const J3DMaterialBlock*)nextBlock;
|
mpMaterialBlock = (const J3DMaterialBlock*)nextBlock;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ size_t JASResArcLoader::getResSize(JKRArchive const* i_archiveP, u16 i_resourceI
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return file->data_size;
|
return DUSK_IF_ELSE(i_archiveP->getFileSize(file), file->data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t JASResArcLoader::getResMaxSize(JKRArchive const* i_archiveP) {
|
size_t JASResArcLoader::getResMaxSize(JKRArchive const* i_archiveP) {
|
||||||
@@ -27,9 +27,16 @@ size_t JASResArcLoader::getResMaxSize(JKRArchive const* i_archiveP) {
|
|||||||
for (index = 0; index < fileEntries; index++) {
|
for (index = 0; index < fileEntries; index++) {
|
||||||
JKRArchive::SDIFileEntry* file = i_archiveP->findIdxResource(index);
|
JKRArchive::SDIFileEntry* file = i_archiveP->findIdxResource(index);
|
||||||
if (file) {
|
if (file) {
|
||||||
|
#if TARGET_PC
|
||||||
|
const u32 fileSize = i_archiveP->getFileSize(file);
|
||||||
|
if (maxSize < fileSize) {
|
||||||
|
maxSize = fileSize;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (maxSize < file->data_size) {
|
if (maxSize < file->data_size) {
|
||||||
maxSize = file->data_size;
|
maxSize = file->data_size;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
dusk::frameUsagePct = 0.f;
|
limiter.Reset();
|
||||||
return;
|
dusk::frameUsagePct = 0.f;
|
||||||
|
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();
|
||||||
|
|||||||
@@ -11,11 +11,6 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "os_report.h"
|
#include "os_report.h"
|
||||||
|
|
||||||
#if DUSK_TPHD
|
|
||||||
#include "dusk/settings.h"
|
|
||||||
#include "dusk/tphd/HdAssetLayer.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JKRAramArchive::JKRAramArchive() {}
|
JKRAramArchive::JKRAramArchive() {}
|
||||||
|
|
||||||
JKRAramArchive::JKRAramArchive(s32 entryNumber, JKRArchive::EMountDirection mountDirection)
|
JKRAramArchive::JKRAramArchive(s32 entryNumber, JKRArchive::EMountDirection mountDirection)
|
||||||
@@ -201,6 +196,13 @@ cleanup:
|
|||||||
|
|
||||||
void* JKRAramArchive::fetchResource(SDIFileEntry* pEntry, u32* pOutSize) {
|
void* JKRAramArchive::fetchResource(SDIFileEntry* pEntry, u32* pOutSize) {
|
||||||
JUT_ASSERT(442, isMounted());
|
JUT_ASSERT(442, isMounted());
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (void* data = getOverlayData(pEntry, pOutSize); data != nullptr) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 outSize;
|
u32 outSize;
|
||||||
u8* outBuf;
|
u8* outBuf;
|
||||||
if (pOutSize == NULL) {
|
if (pOutSize == NULL) {
|
||||||
@@ -222,13 +224,6 @@ void* JKRAramArchive::fetchResource(SDIFileEntry* pEntry, u32* pOutSize) {
|
|||||||
if (compression == COMPRESSION_YAZ0) {
|
if (compression == COMPRESSION_YAZ0) {
|
||||||
this->setExpandSize(pEntry, *pOutSize);
|
this->setExpandSize(pEntry, *pOutSize);
|
||||||
}
|
}
|
||||||
#if DUSK_TPHD
|
|
||||||
// ARAM mounts bypass register_mounted_hd_archive; hook the fresh per-file buffer here.
|
|
||||||
if (dusk::tphd_active() && mStringTable != NULL) {
|
|
||||||
dusk::tphd::register_copied_hd_resource(
|
|
||||||
mEntryNum, mStringTable + pEntry->getNameOffset(), outBuf, *pOutSize);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
if (compression == COMPRESSION_YAZ0) {
|
if (compression == COMPRESSION_YAZ0) {
|
||||||
*pOutSize = this->getExpandSize(pEntry);
|
*pOutSize = this->getExpandSize(pEntry);
|
||||||
@@ -243,6 +238,13 @@ void* JKRAramArchive::fetchResource(SDIFileEntry* pEntry, u32* pOutSize) {
|
|||||||
void* JKRAramArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* pEntry,
|
void* JKRAramArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* pEntry,
|
||||||
u32* resourceSize) {
|
u32* resourceSize) {
|
||||||
JUT_ASSERT(515, isMounted());
|
JUT_ASSERT(515, isMounted());
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (copyOverlayData(buffer, bufferSize, pEntry, resourceSize)) {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 size = pEntry->data_size;
|
u32 size = pEntry->data_size;
|
||||||
if (size > bufferSize) {
|
if (size > bufferSize) {
|
||||||
size = bufferSize;
|
size = bufferSize;
|
||||||
@@ -349,6 +351,12 @@ u32 JKRAramArchive::getExpandedResSize(const void* ptr) const {
|
|||||||
return this->getResSize(ptr);
|
return this->getResSize(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (u32 size; getOverlayResourceSize(ptr, &size)) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
JKRArchive::SDIFileEntry* entry = this->findPtrResource(ptr);
|
JKRArchive::SDIFileEntry* entry = this->findPtrResource(ptr);
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
|
|||||||
@@ -7,6 +7,37 @@
|
|||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <limits>
|
||||||
|
#include <ranges>
|
||||||
|
#include <string_view>
|
||||||
|
#include "JSystem/JKernel/JKRDvdRipper.h"
|
||||||
|
#if _WIN32
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::atomic<u64> JKRArchive::sArcOverlayGeneration{0};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void* alloc_overlay_buffer(u32 size) {
|
||||||
|
#if _WIN32
|
||||||
|
return _aligned_malloc(size, alignof(std::max_align_t));
|
||||||
|
#else
|
||||||
|
return std::malloc(size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_overlay_buffer(void* data) {
|
||||||
|
#if _WIN32
|
||||||
|
_aligned_free(data);
|
||||||
|
#else
|
||||||
|
std::free(data);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DUSK_GAME_DATA u32 JKRArchive::sCurrentDirID;
|
DUSK_GAME_DATA u32 JKRArchive::sCurrentDirID;
|
||||||
@@ -42,6 +73,7 @@ JKRArchive::JKRArchive(s32 entryNumber, JKRArchive::EMountMode mountMode) {
|
|||||||
|
|
||||||
JKRArchive::~JKRArchive() {
|
JKRArchive::~JKRArchive() {
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
|
removeAllOverlayResources();
|
||||||
if (mFileData != nullptr) {
|
if (mFileData != nullptr) {
|
||||||
JKRHeap::getSystemHeap()->free(mFileData);
|
JKRHeap::getSystemHeap()->free(mFileData);
|
||||||
mFileData = nullptr;
|
mFileData = nullptr;
|
||||||
@@ -270,4 +302,240 @@ void JKRArchive::initFileDataPointers() {
|
|||||||
mFiles[i].index = i;
|
mFiles[i].index = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JKRArchive::notifyOverlayFilesChanged() {
|
||||||
|
sArcOverlayGeneration.fetch_add(1, std::memory_order_release);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JKRArchive::buildArcOverlaysPath() const {
|
||||||
|
if (mArcOverlaysPathResolved) {
|
||||||
|
return !mArcOverlaysPath.empty();
|
||||||
|
}
|
||||||
|
mArcOverlaysPathResolved = true;
|
||||||
|
|
||||||
|
if (mEntryNum < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char pathBuffer[1024];
|
||||||
|
if (!DVDConvertEntrynumToPath(mEntryNum, pathBuffer, sizeof(pathBuffer))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string path{pathBuffer};
|
||||||
|
constexpr std::string_view extension{".arc"};
|
||||||
|
if (path.size() < extension.size() ||
|
||||||
|
path.compare(path.size() - extension.size(), extension.size(), extension) != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
path.resize(path.size() - extension.size());
|
||||||
|
path.push_back('/');
|
||||||
|
|
||||||
|
mArcOverlaysPath = std::move(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKRArchive::buildIndexToPathMap(u32 dirIndex, const std::string& currentPath) const {
|
||||||
|
const SDIDirEntry& dir = mNodes[dirIndex];
|
||||||
|
for (int i = 0; i < dir.num_entries; i++) {
|
||||||
|
const SDIFileEntry& entry = mFiles[dir.first_file_index + i];
|
||||||
|
std::string entryName{&mStringTable[entry.getNameOffset()]};
|
||||||
|
if (entryName == "." || entryName == "..") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
buildIndexToPathMap(entry.data_offset, currentPath + entryName + "/");
|
||||||
|
} else {
|
||||||
|
mIdxToPathMap[entry.index] = currentPath + entryName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JKRArchive::getOverlayPath(SDIFileEntry* entry, std::string& path) const {
|
||||||
|
if (entry == nullptr || !buildArcOverlaysPath()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIdxToPathMap.empty()) {
|
||||||
|
buildIndexToPathMap(0, std::string{&mStringTable[mNodes[0].name_offset]} + "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto pathIt = mIdxToPathMap.find(entry->index);
|
||||||
|
if (pathIt == mIdxToPathMap.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = mArcOverlaysPath + pathIt->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* JKRArchive::getActiveOverlayData(SDIFileEntry* entry, u32* outSize) const {
|
||||||
|
const auto activeIt = mActiveArcOverlayResources.find(entry->index);
|
||||||
|
if (activeIt == mActiveArcOverlayResources.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto resourceIt = mArcOverlayResources.find(activeIt->second);
|
||||||
|
const u64 generation = sArcOverlayGeneration.load(std::memory_order_acquire);
|
||||||
|
if (resourceIt == mArcOverlayResources.end() || resourceIt->second.generation != generation) {
|
||||||
|
// Keep the allocation owned so raw pointers returned by earlier fetches remain valid.
|
||||||
|
mActiveArcOverlayResources.erase(activeIt);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outSize != nullptr) {
|
||||||
|
*outSize = resourceIt->second.size;
|
||||||
|
}
|
||||||
|
return resourceIt->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* JKRArchive::getOverlayData(SDIFileEntry* entry, u32* outSize) {
|
||||||
|
if (entry == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (void* data = getActiveOverlayData(entry, outSize)) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string path;
|
||||||
|
if (!getOverlayPath(entry, path)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u32 alignmentMask = 0x1f;
|
||||||
|
const u64 generation = sArcOverlayGeneration.load(std::memory_order_acquire);
|
||||||
|
DVDFileInfo fileInfo{};
|
||||||
|
if (!DVDOpen(path.c_str(), &fileInfo)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 logicalSize = fileInfo.length;
|
||||||
|
if (logicalSize > static_cast<u32>(std::numeric_limits<s32>::max()) - alignmentMask) {
|
||||||
|
DVDClose(&fileInfo);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 readSize = ALIGN_NEXT(logicalSize, 0x20);
|
||||||
|
const u32 allocationSize = readSize == 0 ? 1 : readSize;
|
||||||
|
void* data = alloc_overlay_buffer(allocationSize);
|
||||||
|
if (data == nullptr) {
|
||||||
|
DVDClose(&fileInfo);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const s32 status = DVDReadPrio(&fileInfo, data, readSize, 0, 2);
|
||||||
|
DVDClose(&fileInfo);
|
||||||
|
if (status < DVD_RESULT_GOOD || static_cast<u32>(status) != logicalSize) {
|
||||||
|
free_overlay_buffer(data);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
mArcOverlayResources.emplace(data, ArcOverlayResource{
|
||||||
|
.entryIndex = entry->index,
|
||||||
|
.size = logicalSize,
|
||||||
|
.generation = generation,
|
||||||
|
});
|
||||||
|
mActiveArcOverlayResources[entry->index] = data;
|
||||||
|
|
||||||
|
if (outSize != nullptr) {
|
||||||
|
*outSize = logicalSize;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JKRArchive::copyOverlayData(void* buffer, u32 bufferSize, SDIFileEntry* entry, u32* outSize) {
|
||||||
|
u32 overlaySize;
|
||||||
|
const void* overlayData = getOverlayData(entry, &overlaySize);
|
||||||
|
if (overlayData == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 copySize = overlaySize < bufferSize ? overlaySize : bufferSize;
|
||||||
|
if (copySize != 0) {
|
||||||
|
memcpy(buffer, overlayData, copySize);
|
||||||
|
}
|
||||||
|
if (outSize != nullptr) {
|
||||||
|
*outSize = copySize;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JKRArchive::getOverlayResourceSize(const void* data, u32* outSize) const {
|
||||||
|
const auto resourceIt = mArcOverlayResources.find(const_cast<void*>(data));
|
||||||
|
if (resourceIt == mArcOverlayResources.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outSize != nullptr) {
|
||||||
|
*outSize = resourceIt->second.size;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JKRArchive::getOverlayFileSize(SDIFileEntry* entry, u32* outSize) const {
|
||||||
|
if (entry == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 activeSize;
|
||||||
|
if (getActiveOverlayData(entry, &activeSize) != nullptr) {
|
||||||
|
if (outSize != nullptr) {
|
||||||
|
*outSize = activeSize;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string path;
|
||||||
|
if (!getOverlayPath(entry, path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DVDFileInfo fileInfo{};
|
||||||
|
if (!DVDOpen(path.c_str(), &fileInfo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outSize != nullptr) {
|
||||||
|
*outSize = fileInfo.length;
|
||||||
|
}
|
||||||
|
DVDClose(&fileInfo);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 JKRArchive::getFileSize(SDIFileEntry* entry) const {
|
||||||
|
u32 size;
|
||||||
|
if (getOverlayFileSize(entry, &size)) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
return entry != nullptr ? entry->getSize() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JKRArchive::removeOverlayResource(void* resource, bool freeResource) {
|
||||||
|
const auto resourceIt = mArcOverlayResources.find(resource);
|
||||||
|
if (resourceIt == mArcOverlayResources.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto activeIt = mActiveArcOverlayResources.find(resourceIt->second.entryIndex);
|
||||||
|
if (activeIt != mActiveArcOverlayResources.end() && activeIt->second == resource) {
|
||||||
|
mActiveArcOverlayResources.erase(activeIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (freeResource) {
|
||||||
|
free_overlay_buffer(resource);
|
||||||
|
}
|
||||||
|
mArcOverlayResources.erase(resourceIt);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKRArchive::removeAllOverlayResources() {
|
||||||
|
mActiveArcOverlayResources.clear();
|
||||||
|
for (const auto& key : mArcOverlayResources | std::views::keys) {
|
||||||
|
free_overlay_buffer(key);
|
||||||
|
}
|
||||||
|
mArcOverlayResources.clear();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,24 +9,6 @@
|
|||||||
#include "JSystem/JKernel/JKRMemArchive.h"
|
#include "JSystem/JKernel/JKRMemArchive.h"
|
||||||
#include "JSystem/JUtility/JUTAssert.h"
|
#include "JSystem/JUtility/JUTAssert.h"
|
||||||
|
|
||||||
#if DUSK_TPHD
|
|
||||||
#include "dusk/tphd/HdAssetLayer.hpp"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
void register_copied_hd_resource(
|
|
||||||
JKRArchive* archive, JKRArchive::SDIFileEntry* fileEntry, void* buffer, u32 resourceSize) {
|
|
||||||
if (archive == NULL || fileEntry == NULL || buffer == NULL || resourceSize == 0 ||
|
|
||||||
archive->mStringTable == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dusk::tphd::register_copied_hd_resource(archive->mEntryNum,
|
|
||||||
archive->mStringTable + fileEntry->getNameOffset(), buffer, resourceSize);
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JKRArchive* JKRArchive::check_mount_already(s32 entryNum, JKRHeap* heap) {
|
JKRArchive* JKRArchive::check_mount_already(s32 entryNum, JKRHeap* heap) {
|
||||||
if (heap == NULL) {
|
if (heap == NULL) {
|
||||||
heap = JKRGetCurrentHeap();
|
heap = JKRGetCurrentHeap();
|
||||||
@@ -214,9 +196,6 @@ u32 JKRArchive::readResource(void* buffer, u32 bufferSize, u32 type, const char*
|
|||||||
if (fileEntry) {
|
if (fileEntry) {
|
||||||
u32 resourceSize;
|
u32 resourceSize;
|
||||||
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
||||||
#if DUSK_TPHD
|
|
||||||
register_copied_hd_resource(this, fileEntry, buffer, resourceSize);
|
|
||||||
#endif
|
|
||||||
return resourceSize;
|
return resourceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,9 +214,6 @@ u32 JKRArchive::readResource(void* buffer, u32 bufferSize, const char* path) {
|
|||||||
if (fileEntry) {
|
if (fileEntry) {
|
||||||
u32 resourceSize;
|
u32 resourceSize;
|
||||||
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
||||||
#if DUSK_TPHD
|
|
||||||
register_copied_hd_resource(this, fileEntry, buffer, resourceSize);
|
|
||||||
#endif
|
|
||||||
return resourceSize;
|
return resourceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,9 +226,6 @@ u32 JKRArchive::readIdxResource(void* buffer, u32 bufferSize, u32 index) {
|
|||||||
if (fileEntry) {
|
if (fileEntry) {
|
||||||
u32 resourceSize;
|
u32 resourceSize;
|
||||||
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
||||||
#if DUSK_TPHD
|
|
||||||
register_copied_hd_resource(this, fileEntry, buffer, resourceSize);
|
|
||||||
#endif
|
|
||||||
return resourceSize;
|
return resourceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,9 +238,6 @@ u32 JKRArchive::readResource(void* buffer, u32 bufferSize, u16 id) {
|
|||||||
if (fileEntry) {
|
if (fileEntry) {
|
||||||
u32 resourceSize;
|
u32 resourceSize;
|
||||||
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
|
||||||
#if DUSK_TPHD
|
|
||||||
register_copied_hd_resource(this, fileEntry, buffer, resourceSize);
|
|
||||||
#endif
|
|
||||||
return resourceSize;
|
return resourceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,6 +246,7 @@ u32 JKRArchive::readResource(void* buffer, u32 bufferSize, u16 id) {
|
|||||||
|
|
||||||
void JKRArchive::removeResourceAll() {
|
void JKRArchive::removeResourceAll() {
|
||||||
if (mArcInfoBlock && mMountMode != MOUNT_MEM) {
|
if (mArcInfoBlock && mMountMode != MOUNT_MEM) {
|
||||||
|
IF_DUSK(removeAllOverlayResources();)
|
||||||
SDIFileEntry* fileEntry = mFiles;
|
SDIFileEntry* fileEntry = mFiles;
|
||||||
for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) {
|
for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) {
|
||||||
if (JKAR_DATA(fileEntry)) {
|
if (JKAR_DATA(fileEntry)) {
|
||||||
@@ -289,6 +260,13 @@ void JKRArchive::removeResourceAll() {
|
|||||||
|
|
||||||
bool JKRArchive::removeResource(void* resource) {
|
bool JKRArchive::removeResource(void* resource) {
|
||||||
JUT_ASSERT(678, resource != NULL);
|
JUT_ASSERT(678, resource != NULL);
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (removeOverlayResource(resource, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDIFileEntry* fileEntry = findPtrResource(resource);
|
SDIFileEntry* fileEntry = findPtrResource(resource);
|
||||||
if (fileEntry == NULL)
|
if (fileEntry == NULL)
|
||||||
return false;
|
return false;
|
||||||
@@ -300,6 +278,13 @@ bool JKRArchive::removeResource(void* resource) {
|
|||||||
|
|
||||||
bool JKRArchive::detachResource(void* resource) {
|
bool JKRArchive::detachResource(void* resource) {
|
||||||
JUT_ASSERT(707, resource != NULL);
|
JUT_ASSERT(707, resource != NULL);
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (removeOverlayResource(resource, false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDIFileEntry* fileEntry = findPtrResource(resource);
|
SDIFileEntry* fileEntry = findPtrResource(resource);
|
||||||
if (fileEntry == NULL)
|
if (fileEntry == NULL)
|
||||||
return false;
|
return false;
|
||||||
@@ -310,6 +295,13 @@ bool JKRArchive::detachResource(void* resource) {
|
|||||||
|
|
||||||
u32 JKRArchive::getResSize(const void* resource) const {
|
u32 JKRArchive::getResSize(const void* resource) const {
|
||||||
JUT_ASSERT(732, resource != NULL);
|
JUT_ASSERT(732, resource != NULL);
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (u32 size; getOverlayResourceSize(resource, &size)) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDIFileEntry* fileEntry = findPtrResource(resource);
|
SDIFileEntry* fileEntry = findPtrResource(resource);
|
||||||
if (fileEntry == NULL)
|
if (fileEntry == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -226,6 +226,13 @@ bool JKRCompArchive::open(s32 entryNum) {
|
|||||||
|
|
||||||
void* JKRCompArchive::fetchResource(SDIFileEntry *fileEntry, u32 *pSize) {
|
void* JKRCompArchive::fetchResource(SDIFileEntry *fileEntry, u32 *pSize) {
|
||||||
JUT_ASSERT(597, isMounted());
|
JUT_ASSERT(597, isMounted());
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (void* data = getOverlayData(fileEntry, pSize); data != nullptr) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 ptrSize;
|
u32 ptrSize;
|
||||||
u32 size = fileEntry->data_size;
|
u32 size = fileEntry->data_size;
|
||||||
int compression = JKRConvertAttrToCompressionType(u8(fileEntry->type_flags_and_name_offset >> 0x18));
|
int compression = JKRConvertAttrToCompressionType(u8(fileEntry->type_flags_and_name_offset >> 0x18));
|
||||||
@@ -274,6 +281,13 @@ void *JKRCompArchive::fetchResource(void *data, u32 compressedSize, SDIFileEntry
|
|||||||
{
|
{
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
JUT_ASSERT(708, isMounted());
|
JUT_ASSERT(708, isMounted());
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (copyOverlayData(data, compressedSize, fileEntry, pSize)) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 fileSize = fileEntry->data_size;
|
u32 fileSize = fileEntry->data_size;
|
||||||
u32 alignedSize = ALIGN_NEXT(fileSize, 32);
|
u32 alignedSize = ALIGN_NEXT(fileSize, 32);
|
||||||
u32 fileFlag = fileEntry->type_flags_and_name_offset >> 0x18;
|
u32 fileFlag = fileEntry->type_flags_and_name_offset >> 0x18;
|
||||||
@@ -319,6 +333,7 @@ void *JKRCompArchive::fetchResource(void *data, u32 compressedSize, SDIFileEntry
|
|||||||
|
|
||||||
void JKRCompArchive::removeResourceAll() {
|
void JKRCompArchive::removeResourceAll() {
|
||||||
if (mArcInfoBlock != NULL && mMountMode != MOUNT_MEM) {
|
if (mArcInfoBlock != NULL && mMountMode != MOUNT_MEM) {
|
||||||
|
IF_DUSK(removeAllOverlayResources();)
|
||||||
SDIFileEntry* fileEntry = mFiles;
|
SDIFileEntry* fileEntry = mFiles;
|
||||||
for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) {
|
for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) {
|
||||||
int tmp = fileEntry->type_flags_and_name_offset >> 0x18;
|
int tmp = fileEntry->type_flags_and_name_offset >> 0x18;
|
||||||
@@ -336,6 +351,12 @@ void JKRCompArchive::removeResourceAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool JKRCompArchive::removeResource(void* resource) {
|
bool JKRCompArchive::removeResource(void* resource) {
|
||||||
|
#if TARGET_PC
|
||||||
|
if (removeOverlayResource(resource, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDIFileEntry* fileEntry = findPtrResource(resource);
|
SDIFileEntry* fileEntry = findPtrResource(resource);
|
||||||
if (!fileEntry)
|
if (!fileEntry)
|
||||||
return false;
|
return false;
|
||||||
@@ -356,6 +377,12 @@ u32 JKRCompArchive::getExpandedResSize(const void *resource) const
|
|||||||
return getResSize(resource);
|
return getResSize(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (u32 size; getOverlayResourceSize(resource, &size)) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDIFileEntry *fileEntry = findPtrResource(resource);
|
SDIFileEntry *fileEntry = findPtrResource(resource);
|
||||||
if(!fileEntry) {
|
if(!fileEntry) {
|
||||||
return 0xffffffff;
|
return 0xffffffff;
|
||||||
|
|||||||
@@ -147,6 +147,13 @@ cleanup:
|
|||||||
|
|
||||||
void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* returnSize) {
|
void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* returnSize) {
|
||||||
JUT_ASSERT(428, isMounted());
|
JUT_ASSERT(428, isMounted());
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (void* data = getOverlayData(fileEntry, returnSize); data != nullptr) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 tempReturnSize;
|
u32 tempReturnSize;
|
||||||
if (returnSize == NULL) {
|
if (returnSize == NULL) {
|
||||||
returnSize = &tempReturnSize;
|
returnSize = &tempReturnSize;
|
||||||
@@ -181,6 +188,13 @@ void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* returnSize) {
|
|||||||
void* JKRDvdArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* fileEntry,
|
void* JKRDvdArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* fileEntry,
|
||||||
u32* returnSize) {
|
u32* returnSize) {
|
||||||
JUT_ASSERT(504, isMounted());
|
JUT_ASSERT(504, isMounted());
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (copyOverlayData(buffer, bufferSize, fileEntry, returnSize)) {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 size = fileEntry->data_size;
|
u32 size = fileEntry->data_size;
|
||||||
JKRCompression fileCompression = JKRConvertAttrToCompressionType(u8(fileEntry->type_flags_and_name_offset >> 24));
|
JKRCompression fileCompression = JKRConvertAttrToCompressionType(u8(fileEntry->type_flags_and_name_offset >> 24));
|
||||||
|
|
||||||
@@ -344,6 +358,12 @@ u32 JKRDvdArchive::getExpandedResSize(const void* resource) const {
|
|||||||
return getResSize(resource);
|
return getResSize(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (u32 size; getOverlayResourceSize(resource, &size)) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDIFileEntry* fileEntry = findPtrResource(resource);
|
SDIFileEntry* fileEntry = findPtrResource(resource);
|
||||||
if (!fileEntry) {
|
if (!fileEntry) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -10,10 +10,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "os_report.h"
|
#include "os_report.h"
|
||||||
|
|
||||||
#if DUSK_TPHD
|
|
||||||
#include "dusk/tphd/HdAssetLayer.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JKRMemArchive::JKRMemArchive(s32 entryNum, JKRArchive::EMountDirection mountDirection)
|
JKRMemArchive::JKRMemArchive(s32 entryNum, JKRArchive::EMountDirection mountDirection)
|
||||||
: JKRArchive(entryNum, MOUNT_MEM) {
|
: JKRArchive(entryNum, MOUNT_MEM) {
|
||||||
mIsMounted = false;
|
mIsMounted = false;
|
||||||
@@ -71,13 +67,8 @@ bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirectio
|
|||||||
mIsOpen = false;
|
mIsOpen = false;
|
||||||
mMountDirection = mountDirection;
|
mMountDirection = mountDirection;
|
||||||
|
|
||||||
#ifdef TARGET_PC
|
|
||||||
u32 loadedSize = 0;
|
|
||||||
#endif
|
|
||||||
if (mMountDirection == JKRArchive::MOUNT_DIRECTION_HEAD) {
|
if (mMountDirection == JKRArchive::MOUNT_DIRECTION_HEAD) {
|
||||||
#ifndef TARGET_PC
|
|
||||||
u32 loadedSize;
|
u32 loadedSize;
|
||||||
#endif
|
|
||||||
mArcHeader = (SArcHeader *)JKRDvdToMainRam(
|
mArcHeader = (SArcHeader *)JKRDvdToMainRam(
|
||||||
entryNum, NULL, EXPAND_SWITCH_UNKNOWN1, 0, mHeap, JKRDvdRipper::ALLOC_DIRECTION_FORWARD,
|
entryNum, NULL, EXPAND_SWITCH_UNKNOWN1, 0, mHeap, JKRDvdRipper::ALLOC_DIRECTION_FORWARD,
|
||||||
0, (int *)&mCompression, &loadedSize);
|
0, (int *)&mCompression, &loadedSize);
|
||||||
@@ -86,9 +77,7 @@ bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirectio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#ifndef TARGET_PC
|
|
||||||
u32 loadedSize;
|
u32 loadedSize;
|
||||||
#endif
|
|
||||||
mArcHeader = (SArcHeader *)JKRDvdToMainRam(
|
mArcHeader = (SArcHeader *)JKRDvdToMainRam(
|
||||||
entryNum, NULL, EXPAND_SWITCH_UNKNOWN1, 0, mHeap,
|
entryNum, NULL, EXPAND_SWITCH_UNKNOWN1, 0, mHeap,
|
||||||
JKRDvdRipper::ALLOC_DIRECTION_BACKWARD, 0, (int *)&mCompression, &loadedSize);
|
JKRDvdRipper::ALLOC_DIRECTION_BACKWARD, 0, (int *)&mCompression, &loadedSize);
|
||||||
@@ -101,9 +90,6 @@ bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirectio
|
|||||||
mMountMode = UNKNOWN_MOUNT_MODE;
|
mMountMode = UNKNOWN_MOUNT_MODE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if DUSK_TPHD
|
|
||||||
dusk::tphd::register_mounted_hd_archive(entryNum, mArcHeader, loadedSize);
|
|
||||||
#endif
|
|
||||||
JUT_ASSERT(438, mArcHeader->signature == 'RARC');
|
JUT_ASSERT(438, mArcHeader->signature == 'RARC');
|
||||||
mArcInfoBlock = (SArcDataInfo *)((u8 *)mArcHeader + mArcHeader->header_length);
|
mArcInfoBlock = (SArcDataInfo *)((u8 *)mArcHeader + mArcHeader->header_length);
|
||||||
mNodes = (SDIDirEntry *)((u8 *)&mArcInfoBlock->num_nodes + mArcInfoBlock->node_offset);
|
mNodes = (SDIDirEntry *)((u8 *)&mArcInfoBlock->num_nodes + mArcInfoBlock->node_offset);
|
||||||
@@ -149,6 +135,13 @@ bool JKRMemArchive::open(void* buffer, u32 bufferSize, JKRMemBreakFlag flag) {
|
|||||||
|
|
||||||
void* JKRMemArchive::fetchResource(SDIFileEntry* fileEntry, u32* resourceSize) {
|
void* JKRMemArchive::fetchResource(SDIFileEntry* fileEntry, u32* resourceSize) {
|
||||||
JUT_ASSERT(555, isMounted());
|
JUT_ASSERT(555, isMounted());
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (void* data = getOverlayData(fileEntry, resourceSize); data != nullptr) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!JKAR_DATA(fileEntry)) {
|
if (!JKAR_DATA(fileEntry)) {
|
||||||
JKAR_DATA(fileEntry) = mArchiveData + fileEntry->data_offset;
|
JKAR_DATA(fileEntry) = mArchiveData + fileEntry->data_offset;
|
||||||
}
|
}
|
||||||
@@ -163,6 +156,13 @@ void* JKRMemArchive::fetchResource(SDIFileEntry* fileEntry, u32* resourceSize) {
|
|||||||
void* JKRMemArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* fileEntry,
|
void* JKRMemArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* fileEntry,
|
||||||
u32* resourceSize) {
|
u32* resourceSize) {
|
||||||
JUT_ASSERT(595, isMounted());
|
JUT_ASSERT(595, isMounted());
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (copyOverlayData(buffer, bufferSize, fileEntry, resourceSize)) {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 srcLength = fileEntry->data_size;
|
u32 srcLength = fileEntry->data_size;
|
||||||
if (srcLength > bufferSize) {
|
if (srcLength > bufferSize) {
|
||||||
srcLength = bufferSize;
|
srcLength = bufferSize;
|
||||||
@@ -187,6 +187,8 @@ void* JKRMemArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* f
|
|||||||
void JKRMemArchive::removeResourceAll(void) {
|
void JKRMemArchive::removeResourceAll(void) {
|
||||||
JUT_ASSERT(642, isMounted());
|
JUT_ASSERT(642, isMounted());
|
||||||
|
|
||||||
|
IF_DUSK(removeAllOverlayResources();)
|
||||||
|
|
||||||
if (mArcInfoBlock == NULL)
|
if (mArcInfoBlock == NULL)
|
||||||
return;
|
return;
|
||||||
if (mMountMode == MOUNT_MEM)
|
if (mMountMode == MOUNT_MEM)
|
||||||
@@ -206,6 +208,12 @@ void JKRMemArchive::removeResourceAll(void) {
|
|||||||
bool JKRMemArchive::removeResource(void* resource) {
|
bool JKRMemArchive::removeResource(void* resource) {
|
||||||
JUT_ASSERT(673, isMounted());
|
JUT_ASSERT(673, isMounted());
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
if (removeOverlayResource(resource, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDIFileEntry* fileEntry = findPtrResource(resource);
|
SDIFileEntry* fileEntry = findPtrResource(resource);
|
||||||
if (!fileEntry)
|
if (!fileEntry)
|
||||||
return false;
|
return false;
|
||||||
@@ -245,6 +253,12 @@ u32 JKRMemArchive::fetchResource_subroutine(u8* src, u32 srcLength, u8* dst, u32
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 JKRMemArchive::getExpandedResSize(const void* resource) const {
|
u32 JKRMemArchive::getExpandedResSize(const void* resource) const {
|
||||||
|
#if TARGET_PC
|
||||||
|
if (u32 overlaySize; getOverlayResourceSize(resource, &overlaySize)) {
|
||||||
|
return overlaySize;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDIFileEntry* fileEntry = findPtrResource(resource);
|
SDIFileEntry* fileEntry = findPtrResource(resource);
|
||||||
if (fileEntry == NULL)
|
if (fileEntry == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -7,6 +7,10 @@
|
|||||||
|
|
||||||
#include "JSystem/JMessage/control.h"
|
#include "JSystem/JMessage/control.h"
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
#include "dusk/mods/svc/flow.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
JMessage::TControl::TControl()
|
JMessage::TControl::TControl()
|
||||||
: pSequenceProcessor_(NULL),
|
: pSequenceProcessor_(NULL),
|
||||||
pRenderingProcessor_(NULL),
|
pRenderingProcessor_(NULL),
|
||||||
@@ -19,9 +23,16 @@ JMessage::TControl::TControl()
|
|||||||
pMessageText_current_(NULL)
|
pMessageText_current_(NULL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
JMessage::TControl::~TControl() {}
|
JMessage::TControl::~TControl() {
|
||||||
|
#if TARGET_PC
|
||||||
|
dusk::flow::release_message_control(this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void JMessage::TControl::reset() {
|
void JMessage::TControl::reset() {
|
||||||
|
#if TARGET_PC
|
||||||
|
dusk::flow::release_message_control(this);
|
||||||
|
#endif
|
||||||
pEntry_ = NULL;
|
pEntry_ = NULL;
|
||||||
pMessageText_begin_ = NULL;
|
pMessageText_begin_ = NULL;
|
||||||
pszText_update_current_ = NULL;
|
pszText_update_current_ = NULL;
|
||||||
@@ -78,18 +89,57 @@ int JMessage::TControl::setMessageID(u32 uMsgID, u32 param_1, bool* pbValid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool JMessage::TControl::setMessageCode_inSequence_(JMessage::TProcessor const* pProcessor, u16 u16GroupID, u16 u16Index) {
|
bool JMessage::TControl::setMessageCode_inSequence_(JMessage::TProcessor const* pProcessor, u16 u16GroupID, u16 u16Index) {
|
||||||
|
#if TARGET_PC
|
||||||
|
const TResource* resource = NULL;
|
||||||
|
const void* resolvedEntry = NULL;
|
||||||
|
const char* resolvedText = NULL;
|
||||||
|
if (u16Index >= dusk::flow::kCustomMessageMin) {
|
||||||
|
if (!dusk::flow::custom_message_for_processor(
|
||||||
|
this, pProcessor, u16Index, resource, resolvedEntry, resolvedText))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const_cast<TProcessor*>(pProcessor)->setResourceCache(const_cast<TResource*>(resource));
|
||||||
|
} else {
|
||||||
|
resource = pProcessor->getResource_groupID(u16GroupID);
|
||||||
|
if (resource == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const void* nativeEntry = resource->getMessageEntry_messageIndex(u16Index);
|
||||||
|
const char* nativeText =
|
||||||
|
nativeEntry != NULL ? resource->getMessageText_messageEntry(nativeEntry) : NULL;
|
||||||
|
resolvedEntry = nativeEntry;
|
||||||
|
resolvedText = nativeText;
|
||||||
|
dusk::flow::resolve_message_for_control(this, resource->oParse_THeader_.getRaw(), u16Index,
|
||||||
|
nativeEntry, nativeText, resolvedEntry, resolvedText);
|
||||||
|
}
|
||||||
|
pEntry_ = const_cast<void*>(resolvedEntry);
|
||||||
|
if (pEntry_ == NULL || resolvedText == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
pEntry_ = pProcessor->getMessageEntry_messageCode(u16GroupID, u16Index);
|
pEntry_ = pProcessor->getMessageEntry_messageCode(u16GroupID, u16Index);
|
||||||
if (pEntry_ == NULL) {
|
if (pEntry_ == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
uMessageGroupID_ = resource->getGroupID();
|
||||||
|
pResourceCache_ = resource;
|
||||||
|
#else
|
||||||
uMessageGroupID_ = u16GroupID;
|
uMessageGroupID_ = u16GroupID;
|
||||||
uMessageID_ = u16Index;
|
|
||||||
|
|
||||||
pResourceCache_ = pProcessor->getResourceCache();
|
pResourceCache_ = pProcessor->getResourceCache();
|
||||||
|
#endif
|
||||||
|
uMessageID_ = u16Index;
|
||||||
|
|
||||||
JUT_ASSERT(155, pResourceCache_!=NULL);
|
JUT_ASSERT(155, pResourceCache_!=NULL);
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
pMessageText_begin_ = resolvedText;
|
||||||
|
#else
|
||||||
pMessageText_begin_ = pResourceCache_->getMessageText_messageEntry(pEntry_);
|
pMessageText_begin_ = pResourceCache_->getMessageText_messageEntry(pEntry_);
|
||||||
|
#endif
|
||||||
pMessageText_current_ = pMessageText_begin_;
|
pMessageText_current_ = pMessageText_begin_;
|
||||||
oStack_renderingProcessor_.clear();
|
oStack_renderingProcessor_.clear();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -5,15 +5,26 @@
|
|||||||
#include "JSystem/JUtility/JUTAssert.h"
|
#include "JSystem/JUtility/JUTAssert.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
#include "dusk/mods/svc/flow.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
JMessage::TReference::~TReference() {}
|
JMessage::TReference::~TReference() {}
|
||||||
|
|
||||||
const char* JMessage::TReference::do_word(u32 param_0) const {
|
const char* JMessage::TReference::do_word(u32 param_0) const {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
JMessage::TProcessor::~TProcessor() {}
|
JMessage::TProcessor::~TProcessor() {
|
||||||
|
#if TARGET_PC
|
||||||
|
dusk::flow::release_message_processor(this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void JMessage::TProcessor::reset() {
|
void JMessage::TProcessor::reset() {
|
||||||
|
#if TARGET_PC
|
||||||
|
dusk::flow::release_message_processor(this);
|
||||||
|
#endif
|
||||||
on_resetStatus_(NULL);
|
on_resetStatus_(NULL);
|
||||||
do_reset();
|
do_reset();
|
||||||
}
|
}
|
||||||
@@ -44,6 +55,15 @@ const JMessage::TResource* JMessage::TProcessor::getResource_groupID(u16 u16Grou
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 JMessage::TProcessor::toMessageCode_messageID(u32 uMsgID, u32 param_1, bool* pbValid) const {
|
u32 JMessage::TProcessor::toMessageCode_messageID(u32 uMsgID, u32 param_1, bool* pbValid) const {
|
||||||
|
#if TARGET_PC
|
||||||
|
u32 customCode = 0;
|
||||||
|
if (dusk::flow::message_code_for_id(this, uMsgID, customCode)) {
|
||||||
|
if (pbValid != NULL) {
|
||||||
|
*pbValid = true;
|
||||||
|
}
|
||||||
|
return customCode;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
const TResource* pResourceCache = (const TResource*)getResourceCache();
|
const TResource* pResourceCache = (const TResource*)getResourceCache();
|
||||||
if (pResourceCache != NULL) {
|
if (pResourceCache != NULL) {
|
||||||
u16 u16Index = pResourceCache->toMessageIndex_messageID(uMsgID, param_1, pbValid);
|
u16 u16Index = pResourceCache->toMessageIndex_messageID(uMsgID, param_1, pbValid);
|
||||||
@@ -73,6 +93,74 @@ u32 JMessage::TProcessor::toMessageCode_messageID(u32 uMsgID, u32 param_1, bool*
|
|||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
void* JMessage::TProcessor::getMessageEntry_messageCode(u16 groupId, u16 index) const {
|
||||||
|
if (index >= dusk::flow::kCustomMessageMin) {
|
||||||
|
const TResource* customResource = NULL;
|
||||||
|
const void* customEntry = NULL;
|
||||||
|
const char* customText = NULL;
|
||||||
|
if (!dusk::flow::custom_message_for_processor(
|
||||||
|
NULL, this, index, customResource, customEntry, customText))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const_cast<TProcessor*>(this)->setResourceCache(const_cast<TResource*>(customResource));
|
||||||
|
return const_cast<void*>(customEntry);
|
||||||
|
}
|
||||||
|
const TResource* resource = getResource_groupID(groupId);
|
||||||
|
if (resource == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void* nativeEntry = resource->getMessageEntry_messageIndex(index);
|
||||||
|
const char* nativeText =
|
||||||
|
nativeEntry != NULL ? resource->getMessageText_messageEntry(nativeEntry) : NULL;
|
||||||
|
const void* resolvedEntry = nativeEntry;
|
||||||
|
const char* resolvedText = nativeText;
|
||||||
|
dusk::flow::resolve_message(this, resource->oParse_THeader_.getRaw(), index, nativeEntry,
|
||||||
|
nativeText, resolvedEntry, resolvedText);
|
||||||
|
return const_cast<void*>(resolvedEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* JMessage::TProcessor::getMessageText_messageCode(u16 groupId, u16 index) const {
|
||||||
|
if (index >= dusk::flow::kCustomMessageMin) {
|
||||||
|
const TResource* customResource = NULL;
|
||||||
|
const void* customEntry = NULL;
|
||||||
|
const char* customText = NULL;
|
||||||
|
if (!dusk::flow::custom_message_for_processor(
|
||||||
|
NULL, this, index, customResource, customEntry, customText))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const_cast<TProcessor*>(this)->setResourceCache(const_cast<TResource*>(customResource));
|
||||||
|
return customText;
|
||||||
|
}
|
||||||
|
const TResource* resource = getResource_groupID(groupId);
|
||||||
|
if (resource == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const void* nativeEntry = resource->getMessageEntry_messageIndex(index);
|
||||||
|
const char* nativeText =
|
||||||
|
nativeEntry != NULL ? resource->getMessageText_messageEntry(nativeEntry) : NULL;
|
||||||
|
const void* resolvedEntry = nativeEntry;
|
||||||
|
const char* resolvedText = nativeText;
|
||||||
|
dusk::flow::resolve_message(this, resource->oParse_THeader_.getRaw(), index, nativeEntry,
|
||||||
|
nativeText, resolvedEntry, resolvedText);
|
||||||
|
return resolvedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* JMessage::TProcessor::on_message_limited(u16 index) const {
|
||||||
|
JUT_ASSERT(482, pResourceCache_!=NULL);
|
||||||
|
const void* nativeEntry = pResourceCache_->getMessageEntry_messageIndex(index);
|
||||||
|
const char* nativeText =
|
||||||
|
nativeEntry != NULL ? pResourceCache_->getMessageText_messageEntry(nativeEntry) : NULL;
|
||||||
|
const void* resolvedEntry = nativeEntry;
|
||||||
|
const char* resolvedText = nativeText;
|
||||||
|
dusk::flow::resolve_message(this, pResourceCache_->oParse_THeader_.getRaw(), index,
|
||||||
|
nativeEntry, nativeText, resolvedEntry, resolvedText);
|
||||||
|
return resolvedText;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void JMessage::TProcessor::on_select_begin(char const* (*pfn)(JMessage::TProcessor*),
|
void JMessage::TProcessor::on_select_begin(char const* (*pfn)(JMessage::TProcessor*),
|
||||||
void const* pOffset, char const* pcBase, u32 uNumber) {
|
void const* pOffset, char const* pcBase, u32 uNumber) {
|
||||||
JUT_ASSERT(191, uNumber>0);
|
JUT_ASSERT(191, uNumber>0);
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ void JUTResFont::initJoinedTexture() {
|
|||||||
int pageCount = 0;
|
int pageCount = 0;
|
||||||
u32 pageNumCells = block.numRows * block.numColumns;
|
u32 pageNumCells = block.numRows * block.numColumns;
|
||||||
|
|
||||||
if (dusk::version::getGameVersion() == dusk::version::GameVersion::GcnJpn) {
|
if (dusk::version::isRegionJpn()) {
|
||||||
pageCount = 1;
|
pageCount = 1;
|
||||||
if (pageNumCells > 0 && block.endCode > block.startCode) {
|
if (pageNumCells > 0 && block.endCode > block.startCode) {
|
||||||
pageCount = (block.endCode - block.startCode + pageNumCells - 1) / pageNumCells;
|
pageCount = (block.endCode - block.startCode + pageNumCells - 1) / pageNumCells;
|
||||||
|
|||||||
@@ -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,8 +68,13 @@ 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;
|
||||||
|
#if TARGET_PC
|
||||||
|
if (sVideoInterval <= 0) {
|
||||||
|
sVideoInterval = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
sVideoLastTick = tick;
|
sVideoLastTick = tick;
|
||||||
|
|
||||||
JUTXfb* xfb = JUTXfb::getManager();
|
JUTXfb* xfb = JUTXfb::getManager();
|
||||||
|
|||||||
+12
-10
@@ -53,6 +53,7 @@ ResourceBuffer g_denoiseSource = RESOURCE_BUFFER_INIT;
|
|||||||
ResourceBuffer g_compositeSource = RESOURCE_BUFFER_INIT;
|
ResourceBuffer g_compositeSource = RESOURCE_BUFFER_INIT;
|
||||||
|
|
||||||
GfxDeviceInfo g_deviceInfo = GFX_DEVICE_INFO_INIT;
|
GfxDeviceInfo g_deviceInfo = GFX_DEVICE_INFO_INIT;
|
||||||
|
GfxRenderTargetLayout g_sceneTargetLayout = GFX_RENDER_TARGET_LAYOUT_INIT;
|
||||||
WGPUComputePipeline g_preprocessPipeline = nullptr;
|
WGPUComputePipeline g_preprocessPipeline = nullptr;
|
||||||
WGPUComputePipeline g_mip4Pipeline = nullptr;
|
WGPUComputePipeline g_mip4Pipeline = nullptr;
|
||||||
WGPUComputePipeline g_gtaoPipeline = nullptr;
|
WGPUComputePipeline g_gtaoPipeline = nullptr;
|
||||||
@@ -226,19 +227,17 @@ bool build_composite_pipeline(
|
|||||||
.dstFactor = WGPUBlendFactor_One,
|
.dstFactor = WGPUBlendFactor_One,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
WGPUColorTargetState colorTarget = WGPU_COLOR_TARGET_STATE_INIT;
|
WGPUColorTargetState colorTargets[GFX_MAX_COLOR_ATTACHMENTS];
|
||||||
colorTarget.format = g_deviceInfo.color_format;
|
const uint32_t colorTargetCount = gfx_init_color_target_states(
|
||||||
if (blend) {
|
&g_sceneTargetLayout, colorTargets, blend ? &blendState : nullptr, WGPUColorWriteMask_All);
|
||||||
colorTarget.blend = &blendState;
|
|
||||||
}
|
|
||||||
WGPUFragmentState fragment = WGPU_FRAGMENT_STATE_INIT;
|
WGPUFragmentState fragment = WGPU_FRAGMENT_STATE_INIT;
|
||||||
fragment.module = module;
|
fragment.module = module;
|
||||||
fragment.entryPoint = {"fs_main", WGPU_STRLEN};
|
fragment.entryPoint = {"fs_main", WGPU_STRLEN};
|
||||||
fragment.targetCount = 1;
|
fragment.targetCount = colorTargetCount;
|
||||||
fragment.targets = &colorTarget;
|
fragment.targets = colorTargets;
|
||||||
// Depth state must match the EFB pass despite never touching depth.
|
// Depth state must match the EFB pass despite never touching depth.
|
||||||
WGPUDepthStencilState depthStencil = WGPU_DEPTH_STENCIL_STATE_INIT;
|
WGPUDepthStencilState depthStencil = WGPU_DEPTH_STENCIL_STATE_INIT;
|
||||||
depthStencil.format = g_deviceInfo.depth_format;
|
depthStencil.format = g_sceneTargetLayout.depth_stencil_format;
|
||||||
depthStencil.depthWriteEnabled = WGPUOptionalBool_False;
|
depthStencil.depthWriteEnabled = WGPUOptionalBool_False;
|
||||||
depthStencil.depthCompare = WGPUCompareFunction_Always;
|
depthStencil.depthCompare = WGPUCompareFunction_Always;
|
||||||
|
|
||||||
@@ -248,7 +247,7 @@ bool build_composite_pipeline(
|
|||||||
pipelineDesc.vertex.entryPoint = {"vs_main", WGPU_STRLEN};
|
pipelineDesc.vertex.entryPoint = {"vs_main", WGPU_STRLEN};
|
||||||
pipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
|
pipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
|
||||||
pipelineDesc.depthStencil = &depthStencil;
|
pipelineDesc.depthStencil = &depthStencil;
|
||||||
pipelineDesc.multisample.count = g_deviceInfo.sample_count;
|
pipelineDesc.multisample.count = g_sceneTargetLayout.sample_count;
|
||||||
pipelineDesc.fragment = &fragment;
|
pipelineDesc.fragment = &fragment;
|
||||||
outPipeline = wgpuDeviceCreateRenderPipeline(g_deviceInfo.device, &pipelineDesc);
|
outPipeline = wgpuDeviceCreateRenderPipeline(g_deviceInfo.device, &pipelineDesc);
|
||||||
wgpuShaderModuleRelease(module);
|
wgpuShaderModuleRelease(module);
|
||||||
@@ -504,7 +503,7 @@ void on_compute(
|
|||||||
// Render worker thread: composite the AO over the scene (or show it, in debug view).
|
// Render worker thread: composite the AO over the scene (or show it, in debug view).
|
||||||
void on_draw(
|
void on_draw(
|
||||||
ModContext*, const GfxDrawContext* ctx, const void* payload, size_t payloadSize, void*) {
|
ModContext*, const GfxDrawContext* ctx, const void* payload, size_t payloadSize, void*) {
|
||||||
if (payloadSize != sizeof(CompositePayload)) {
|
if (payloadSize != sizeof(CompositePayload) || ctx->layout.key != g_sceneTargetLayout.key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CompositePayload data;
|
CompositePayload data;
|
||||||
@@ -816,6 +815,9 @@ MOD_EXPORT ModResult mod_initialize(ModError* error) {
|
|||||||
if (svc_gfx->get_device_info(mod_ctx, &g_deviceInfo) != MOD_OK) {
|
if (svc_gfx->get_device_info(mod_ctx, &g_deviceInfo) != MOD_OK) {
|
||||||
return mods::set_error(error, MOD_ERROR, "failed to query device info");
|
return mods::set_error(error, MOD_ERROR, "failed to query device info");
|
||||||
}
|
}
|
||||||
|
if (svc_gfx->get_scene_target_layout(mod_ctx, &g_sceneTargetLayout) != MOD_OK) {
|
||||||
|
return mods::set_error(error, MOD_ERROR, "failed to query scene target layout");
|
||||||
|
}
|
||||||
if (!build_compute_pipeline("AO preprocess depth", g_preprocessSource, "preprocess_depth",
|
if (!build_compute_pipeline("AO preprocess depth", g_preprocessSource, "preprocess_depth",
|
||||||
g_preprocessPipeline, g_preprocessLayout) ||
|
g_preprocessPipeline, g_preprocessLayout) ||
|
||||||
!build_compute_pipeline("AO downsample mip4", g_preprocessSource, "downsample_mip4",
|
!build_compute_pipeline("AO downsample mip4", g_preprocessSource, "downsample_mip4",
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
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
|
||||||
|
BUNDLE
|
||||||
|
)
|
||||||
|
|
||||||
|
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,88 @@
|
|||||||
|
#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,745 @@
|
|||||||
|
#include "hooks.hpp"
|
||||||
|
|
||||||
|
#include "color_utils.hpp"
|
||||||
|
#include "midna_hair_color.hpp"
|
||||||
|
#include "mod.hpp"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#include "mods/svc/hook.hpp"
|
||||||
|
#include "mods/svc/log.hpp"
|
||||||
|
|
||||||
|
#include "SSystem/SComponent/c_phase.h"
|
||||||
|
#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_dmap.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_meter2.h"
|
||||||
|
#include "d/d_meter2_draw.h"
|
||||||
|
#include "d/d_meter2_info.h"
|
||||||
|
#include "d/d_meter_button.h"
|
||||||
|
#include "d/d_meter_hakusha.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"
|
||||||
|
|
||||||
|
// 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 field 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 and B buttons on the dungeon map screen
|
||||||
|
DEFINE_HOOK_SYMBOL("dMenu_DmapBg_c::buttonIconScreenInit", void(dMenu_DmapBg_c*), MenuDMapButtonIconScreenInit);
|
||||||
|
void menu_dmap_button_icon_screen_init_post(ModContext*, void* args, void*, void*) {
|
||||||
|
auto menuDMap = mods::arg<dMenu_DmapBg_c*>(args, 0);
|
||||||
|
auto screen = menuDMap->mButtonScreen;
|
||||||
|
|
||||||
|
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
|
||||||
|
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), 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 = g_currentMidnaHairColors.normalColor;
|
||||||
|
if (dKy_darkworld_check()) {
|
||||||
|
midna->field_0x6e8 = g_currentMidnaHairColors.normalKColor;
|
||||||
|
midna->field_0x6ec = g_currentMidnaHairColors.normalKColor2;
|
||||||
|
} else {
|
||||||
|
midna->field_0x6e8 = g_currentMidnaHairColors.lNormalKColor;
|
||||||
|
midna->field_0x6ec = g_currentMidnaHairColors.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 = g_currentMidnaHairColors.bigKColor;
|
||||||
|
if (dKy_darkworld_check()) {
|
||||||
|
color = g_currentMidnaHairColors.bigColor;
|
||||||
|
kcolor2 = g_currentMidnaHairColors.normalKColor2;
|
||||||
|
} else {
|
||||||
|
color = g_currentMidnaHairColors.lBigColor;
|
||||||
|
kcolor2 = g_currentMidnaHairColors.lBigKColor2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
color = g_currentMidnaHairColors.normalColor;
|
||||||
|
if (dKy_darkworld_check()) {
|
||||||
|
kcolor1 = g_currentMidnaHairColors.normalKColor;
|
||||||
|
kcolor2 = g_currentMidnaHairColors.normalKColor2;
|
||||||
|
} else {
|
||||||
|
kcolor1 = g_currentMidnaHairColors.lNormalKColor;
|
||||||
|
kcolor2 = g_currentMidnaHairColors.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(MenuDMapButtonIconScreenInit, menu_dmap_button_icon_screen_init_post,
|
||||||
|
dMenu_DmapBg_c::buttonIconScreenInit)
|
||||||
|
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(MenuDMapButtonIconScreenInit)
|
||||||
|
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,115 @@
|
|||||||
|
#include "midna_hair_color.hpp"
|
||||||
|
#include "mod.hpp"
|
||||||
|
|
||||||
|
#include "mods/svc/log.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr std::array<std::array<GXColor, 9>, 10> kMidnaHairColors = {{
|
||||||
|
// 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}
|
||||||
|
}}
|
||||||
|
}};
|
||||||
|
|
||||||
|
size_t get_midna_hair_color_index(ConfigVarHandle handle) {
|
||||||
|
const auto optionIndex = get_int_option(handle, 0);
|
||||||
|
if (optionIndex < 0 || optionIndex >= static_cast<int64_t>(kMidnaHairColors.size())) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return static_cast<size_t>(optionIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MidnaHairColors g_currentMidnaHairColors = {
|
||||||
|
.normalColor = {0x50, 0x00, 0x00, 0x00},
|
||||||
|
.normalKColor = {0xB4, 0x87, 0x00, 0x00},
|
||||||
|
.normalKColor2 = {0x00, 0xC3, 0xC3, 0x00},
|
||||||
|
.bigColor = {0xFF, 0x64, 0x78, 0x00},
|
||||||
|
.bigKColor = {0x1E, 0x00, 0x00, 0x00},
|
||||||
|
.lNormalKColor = {0xFF, 0xDC, 0x00, 0x00},
|
||||||
|
.lNormalKColor2 = {0x00, 0xC3, 0xEB, 0x00},
|
||||||
|
.lBigColor = {0xFF, 0x78, 0x00, 0x00},
|
||||||
|
.lBigKColor2 = {0xAA, 0xFF, 0xC3, 0x00},
|
||||||
|
};
|
||||||
|
|
||||||
|
void set_all_midna_hair_colors() {
|
||||||
|
auto& g_cvars = get_cvars();
|
||||||
|
auto hairBaseColor = get_midna_hair_color_index(g_cvars.midnaHairBaseColor);
|
||||||
|
auto hairTipsColor = get_midna_hair_color_index(g_cvars.midnaHairTipsColor);
|
||||||
|
|
||||||
|
// Colors we have to convert to GXColorS10
|
||||||
|
auto& normalColor = kMidnaHairColors.at(hairBaseColor)[2];
|
||||||
|
auto& bigColor = kMidnaHairColors.at(hairBaseColor)[5];
|
||||||
|
auto& lBigColor = kMidnaHairColors.at(hairBaseColor)[4];
|
||||||
|
|
||||||
|
g_currentMidnaHairColors.normalColor = GXColorS10{normalColor.r, normalColor.g, normalColor.b};
|
||||||
|
g_currentMidnaHairColors.normalKColor = kMidnaHairColors.at(hairBaseColor)[1];
|
||||||
|
g_currentMidnaHairColors.normalKColor2 = kMidnaHairColors.at(hairTipsColor)[7];
|
||||||
|
g_currentMidnaHairColors.bigColor = GXColorS10{bigColor.r, bigColor.g, bigColor.b};
|
||||||
|
g_currentMidnaHairColors.bigKColor = kMidnaHairColors.at(hairBaseColor)[3];
|
||||||
|
g_currentMidnaHairColors.lNormalKColor = kMidnaHairColors.at(hairBaseColor)[0];
|
||||||
|
g_currentMidnaHairColors.lNormalKColor2 = kMidnaHairColors.at(hairTipsColor)[6];
|
||||||
|
g_currentMidnaHairColors.lBigColor = GXColorS10{lBigColor.r, lBigColor.g, lBigColor.b};
|
||||||
|
g_currentMidnaHairColors.lBigKColor2 = kMidnaHairColors.at(hairTipsColor)[8];
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gx.h>
|
||||||
|
|
||||||
|
struct MidnaHairColors {
|
||||||
|
GXColorS10 normalColor;
|
||||||
|
GXColor normalKColor;
|
||||||
|
GXColor normalKColor2;
|
||||||
|
GXColorS10 bigColor;
|
||||||
|
GXColor bigKColor;
|
||||||
|
GXColor lNormalKColor;
|
||||||
|
GXColor lNormalKColor2;
|
||||||
|
GXColorS10 lBigColor;
|
||||||
|
GXColor lBigKColor2;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern MidnaHairColors g_currentMidnaHairColors;
|
||||||
|
|
||||||
|
void set_all_midna_hair_colors();
|
||||||
@@ -0,0 +1,653 @@
|
|||||||
|
#include "mod.hpp"
|
||||||
|
#include "color_utils.hpp"
|
||||||
|
#include "hooks.hpp"
|
||||||
|
#include "midna_hair_color.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) {
|
||||||
|
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 (colorStr == "rainbow" && allowRainbow) {
|
||||||
|
auto color = get_rainbow_rgb(127.5f);
|
||||||
|
color.r /= 2;
|
||||||
|
color.g /= 2;
|
||||||
|
color.b /= 2;
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
if (is_valid_hex_color_str(colorStr)) {
|
||||||
|
return hex_color_str_to_gx_color(colorStr);
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
UiWindowHandle g_cosmeticsWindow = 0;
|
||||||
|
bool g_loadedAllBaseTextures = false;
|
||||||
|
constexpr uint32_t kTextureLoadRetryFrames = 30;
|
||||||
|
uint32_t g_textureLoadRetryCountdown = 0;
|
||||||
|
|
||||||
|
constexpr const char* kOverlayPresets[] = {
|
||||||
|
"ab706e",
|
||||||
|
"6382a0",
|
||||||
|
"94749a",
|
||||||
|
"ec8644",
|
||||||
|
"b9ab00",
|
||||||
|
"ec9fc8",
|
||||||
|
"505154",
|
||||||
|
"f8f7f4",
|
||||||
|
"91723e",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr const char* kLightPresets[] = {
|
||||||
|
"ff0000",
|
||||||
|
"f68821",
|
||||||
|
"f6f321",
|
||||||
|
"00ff00",
|
||||||
|
"0000ff",
|
||||||
|
"8000ff",
|
||||||
|
"a0a0a0",
|
||||||
|
"30d0d0",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr const char* kRainbowLightPresets[] = {
|
||||||
|
"rainbow",
|
||||||
|
"ff0000",
|
||||||
|
"f68821",
|
||||||
|
"f6f321",
|
||||||
|
"00ff00",
|
||||||
|
"0000ff",
|
||||||
|
"8000ff",
|
||||||
|
"a0a0a0",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr const char* kAButtonPresets[] = {
|
||||||
|
"ff0000",
|
||||||
|
"ff5000",
|
||||||
|
"ffaf00",
|
||||||
|
"0080ff",
|
||||||
|
"0000ff",
|
||||||
|
"8000ff",
|
||||||
|
"5555ff",
|
||||||
|
"ff20ff",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr const char* kBButtonPresets[] = {
|
||||||
|
"ffff40",
|
||||||
|
"ffa0ff",
|
||||||
|
"00e87b",
|
||||||
|
"00aaff",
|
||||||
|
"6078ff",
|
||||||
|
"000000",
|
||||||
|
"00f3ff",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr const char* kXyButtonPresets[] = {
|
||||||
|
"ff0000",
|
||||||
|
"ff8200",
|
||||||
|
"f7df00",
|
||||||
|
"70ff00",
|
||||||
|
"00bd11",
|
||||||
|
"0000ff",
|
||||||
|
"800088",
|
||||||
|
"000000",
|
||||||
|
"ff00aa",
|
||||||
|
"00ffff",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr const char* kZButtonPresets[] = {
|
||||||
|
"ff0000",
|
||||||
|
"ff8200",
|
||||||
|
"f7df00",
|
||||||
|
"70ff00",
|
||||||
|
"00bd11",
|
||||||
|
"800088",
|
||||||
|
"000000",
|
||||||
|
"00ffff",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr const char* kChargeRingPresets[] = {
|
||||||
|
"ff9f9f",
|
||||||
|
"ff0000",
|
||||||
|
"ffff00",
|
||||||
|
"00ff00",
|
||||||
|
"0000ff",
|
||||||
|
"ff00ff",
|
||||||
|
"331900",
|
||||||
|
"feffff",
|
||||||
|
"000000",
|
||||||
|
};
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
void add_cosmetic_option(
|
||||||
|
UiElementHandle pane, ConfigVarHandle cvar, const char* name, const char* const (&presets)[N]) {
|
||||||
|
UiControlDesc control = UI_CONTROL_DESC_INIT;
|
||||||
|
control.kind = UI_CONTROL_COLOR;
|
||||||
|
control.label = name;
|
||||||
|
control.binding = UI_BINDING_CONFIG_VAR;
|
||||||
|
control.config_var = cvar;
|
||||||
|
control.color_presets = presets;
|
||||||
|
control.color_preset_count = N;
|
||||||
|
add_control(pane, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_group(
|
||||||
|
UiElementHandle groups, UiElementHandle colors, const char* label, UiGroupBuildFn build) {
|
||||||
|
UiGroupDesc group = UI_GROUP_DESC_INIT;
|
||||||
|
group.label = label;
|
||||||
|
group.build = build;
|
||||||
|
const auto result = svc_ui->pane_add_group(mod_ctx, groups, colors, &group, nullptr);
|
||||||
|
if (result != MOD_OK) {
|
||||||
|
mods::log::debug("pane_add_group failed {}", static_cast<int>(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_hero_tunic_colors(ModContext*, UiElementHandle pane, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, pane, "Hero's Tunic");
|
||||||
|
add_cosmetic_option(pane, g_cvars.herosTunicCapColor, "Cap", kOverlayPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.herosTunicTorsoColor, "Body", kOverlayPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.herosTunicSkirtColor, "Skirt", kOverlayPresets);
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_zora_armor_colors(ModContext*, UiElementHandle pane, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, pane, "Zora Armor");
|
||||||
|
add_cosmetic_option(pane, g_cvars.zoraArmorCapColor, "Cap", kOverlayPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.zoraArmorHelmetColor, "Helmet", kOverlayPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.zoraArmorTorsoColor, "Torso", kOverlayPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.zoraArmorScalesColor, "Scales", kOverlayPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.zoraArmorFlippersColor, "Flippers", kOverlayPresets);
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_sword_colors(ModContext*, UiElementHandle pane, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, pane, "Swords");
|
||||||
|
add_cosmetic_option(pane, g_cvars.woodenSwordColor, "Wooden Sword", kOverlayPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.ordonSwordBladeColor, "Ordon Blade", kLightPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.ordonSwordHandleColor, "Ordon Handle", kLightPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.msBladeColor, "Master Sword Blade", kLightPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.msHandleColor, "Master Sword Handle", kLightPresets);
|
||||||
|
add_cosmetic_option(
|
||||||
|
pane, g_cvars.lightSwordGlowColor, "Light Sword Glow", kRainbowLightPresets);
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_equipment_colors(ModContext*, UiElementHandle pane, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, pane, "Equipment");
|
||||||
|
add_cosmetic_option(pane, g_cvars.lanternGlowColor, "Lantern Glow", kRainbowLightPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.boomerangColor, "Gale Boomerang", kOverlayPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.ironBootsColor, "Iron Boots", kOverlayPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.spinnerColor, "Spinner", kOverlayPresets);
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_button_colors(ModContext*, UiElementHandle pane, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, pane, "Buttons");
|
||||||
|
add_cosmetic_option(pane, g_cvars.aButtonColor, "A Button", kAButtonPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.bButtonColor, "B Button", kBButtonPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.xButtonColor, "X Button", kXyButtonPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.yButtonColor, "Y Button", kXyButtonPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.zButtonColor, "Z Button", kZButtonPresets);
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_hud_colors(ModContext*, UiElementHandle pane, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, pane, "HUD");
|
||||||
|
add_cosmetic_option(pane, g_cvars.heartColor, "Hearts", kBButtonPresets);
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_link_colors(ModContext*, UiElementHandle pane, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, pane, "Link");
|
||||||
|
add_cosmetic_option(pane, g_cvars.linkHairColor, "Hair", kOverlayPresets);
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_midna_colors(ModContext*, UiElementHandle pane, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, pane, "Midna");
|
||||||
|
add_cosmetic_option(pane, g_cvars.midnaChargeRingColor, "Charge Ring", kChargeRingPresets);
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_companion_colors(ModContext*, UiElementHandle pane, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, pane, "Companions");
|
||||||
|
add_cosmetic_option(pane, g_cvars.wolfLinkColor, "Wolf Link", kOverlayPresets);
|
||||||
|
add_cosmetic_option(pane, g_cvars.eponaColor, "Epona", kOverlayPresets);
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_equipment_colors_tab(
|
||||||
|
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, left, "Color Groups");
|
||||||
|
add_group(left, right, "Hero's Tunic", build_hero_tunic_colors);
|
||||||
|
add_group(left, right, "Zora Armor", build_zora_armor_colors);
|
||||||
|
add_group(left, right, "Swords", build_sword_colors);
|
||||||
|
add_group(left, right, "Equipment", build_equipment_colors);
|
||||||
|
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_ui_colors_tab(
|
||||||
|
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, left, "Color Groups");
|
||||||
|
add_group(left, right, "Buttons", build_button_colors);
|
||||||
|
add_group(left, right, "HUD", build_hud_colors);
|
||||||
|
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModResult build_misc_colors_tab(
|
||||||
|
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
|
||||||
|
svc_ui->pane_add_section(mod_ctx, left, "Hair Presets");
|
||||||
|
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");
|
||||||
|
svc_ui->pane_add_section(mod_ctx, left, "Color Groups");
|
||||||
|
add_group(left, right, "Link", build_link_colors);
|
||||||
|
add_group(left, right, "Midna", build_midna_colors);
|
||||||
|
add_group(left, right, "Companions", build_companion_colors);
|
||||||
|
|
||||||
|
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";
|
||||||
|
tabs[0].build = build_equipment_colors_tab;
|
||||||
|
tabs[1].title = "Interface";
|
||||||
|
tabs[1].build = build_ui_colors_tab;
|
||||||
|
tabs[2].title = "Characters";
|
||||||
|
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_GROUP;
|
||||||
|
control.label = "Open Cosmetics Menu";
|
||||||
|
control.on_pressed = on_open_cosmetics_menu;
|
||||||
|
add_control(panel, control);
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid noisy resource lookups until the archive has finished loading.
|
||||||
|
auto* resInfo = dComIfG_getObjectResInfo(replacement.arc);
|
||||||
|
if (resInfo == nullptr || resInfo->getArchive() == nullptr) {
|
||||||
|
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
|
||||||
|
const uint32_t mipCount =
|
||||||
|
imageHeader->mipmapEnabled ?
|
||||||
|
std::max<uint32_t>(imageHeader->mipmapCount, 1) :
|
||||||
|
1;
|
||||||
|
auto size = get_image_data_size(
|
||||||
|
imageHeader->format, imageHeader->width, imageHeader->height, mipCount);
|
||||||
|
replacement.baseTextureData.resize(size);
|
||||||
|
std::memcpy(
|
||||||
|
replacement.baseTextureData.data(), tex->getImgDataPtr(i), size);
|
||||||
|
|
||||||
|
// Source texture keys hash only the base mip level.
|
||||||
|
const auto baseMipSize = get_image_data_size(
|
||||||
|
imageHeader->format, imageHeader->width, imageHeader->height, 1);
|
||||||
|
auto textureHash =
|
||||||
|
XXH64(replacement.baseTextureData.data(), baseMipSize, 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 = mipCount;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto maybeColor = get_config_var_color(configVar);
|
||||||
|
if (!maybeColor.has_value()) {
|
||||||
|
// An empty or invalid option means the original texture should be restored.
|
||||||
|
for (auto& replacement : replacements) {
|
||||||
|
if (replacement.handle != 0) {
|
||||||
|
auto result = svc_texture->unregister(mod_ctx, replacement.handle);
|
||||||
|
if (result != MOD_OK) {
|
||||||
|
mods::log::debug("Could not unregister replacement for {}. Result: {}",
|
||||||
|
replacement.textureName, static_cast<int>(result));
|
||||||
|
}
|
||||||
|
replacement.handle = 0;
|
||||||
|
}
|
||||||
|
replacement.curColor.reset();
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
|
TextureData newTextureData = replacement.data;
|
||||||
|
newTextureData.data = newTexture.data();
|
||||||
|
newTextureData.size = newTexture.size();
|
||||||
|
|
||||||
|
// Keep the current replacement active if registering the new one fails.
|
||||||
|
TextureReplacementHandle newHandle{};
|
||||||
|
auto result = svc_texture->register_data(
|
||||||
|
mod_ctx, &replacement.key, &newTextureData, &newHandle);
|
||||||
|
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));
|
||||||
|
auto oldHandle = replacement.handle;
|
||||||
|
replacement.handle = newHandle;
|
||||||
|
curColor = color;
|
||||||
|
|
||||||
|
if (oldHandle != 0) {
|
||||||
|
result = svc_texture->unregister(mod_ctx, oldHandle);
|
||||||
|
if (result != MOD_OK) {
|
||||||
|
mods::log::debug(
|
||||||
|
"Could not unregister previous replacement for {}. Result: {}",
|
||||||
|
replacement.textureName, static_cast<int>(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
replacement.handle = 0;
|
||||||
|
}
|
||||||
|
replacement.curColor.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#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;
|
||||||
|
g_textureLoadRetryCountdown = 0;
|
||||||
|
return MOD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOD_EXPORT ModResult mod_update(ModError*) {
|
||||||
|
update_rainbow_rgb(1.0f);
|
||||||
|
set_all_midna_hair_colors();
|
||||||
|
|
||||||
|
if (!g_loadedAllBaseTextures) {
|
||||||
|
if (g_textureLoadRetryCountdown == 0) {
|
||||||
|
load_base_texture_data();
|
||||||
|
g_textureLoadRetryCountdown = kTextureLoadRetryFrames;
|
||||||
|
} else {
|
||||||
|
--g_textureLoadRetryCountdown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
g_loadedAllBaseTextures = false;
|
||||||
|
g_textureLoadRetryCountdown = 0;
|
||||||
|
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,682 @@
|
|||||||
|
#include "texture_utils.hpp"
|
||||||
|
#include "color_utils.hpp"
|
||||||
|
#include "mod.hpp"
|
||||||
|
|
||||||
|
#include "mods/svc/config.h"
|
||||||
|
#include "mods/svc/log.hpp"
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
auto* pixelPtr = reinterpret_cast<BE<uint16_t>*>(newTextureDataOut.data());
|
||||||
|
|
||||||
|
for (uint8_t mip = 0; mip < mipCount; ++mip) {
|
||||||
|
const uint32_t roundedWidth = (mipWidth + 3) & ~3;
|
||||||
|
const uint32_t roundedHeight = (mipHeight + 3) & ~3;
|
||||||
|
const uint32_t totalPixels = roundedWidth * roundedHeight;
|
||||||
|
|
||||||
|
for (uint32_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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pixelPtr += totalPixels;
|
||||||
|
mipWidth = std::max(1u, mipWidth >> 1);
|
||||||
|
mipHeight = std::max(1u, mipHeight >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t mipCount = (replacementData.data.mip_count > 0) ? replacementData.data.mip_count : 1;
|
||||||
|
const auto expectedInputSize = get_image_data_size(
|
||||||
|
GX_TF_I8, replacementData.key.width, replacementData.key.height, mipCount);
|
||||||
|
if (cmprOut.size() < expectedInputSize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto sourceData = cmprOut;
|
||||||
|
std::vector<u8> convertedData(get_image_data_size(
|
||||||
|
GX_TF_CMPR, replacementData.key.width, replacementData.key.height, mipCount));
|
||||||
|
uint32_t mipWidth = replacementData.key.width;
|
||||||
|
uint32_t mipHeight = replacementData.key.height;
|
||||||
|
|
||||||
|
const uint8_t* readPtr = sourceData.data();
|
||||||
|
uint8_t* writePtr = convertedData.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) {
|
||||||
|
uint8_t subBlockPixels[4][16]{};
|
||||||
|
|
||||||
|
for (uint32_t subBlockY = 0; subBlockY < 2; ++subBlockY) {
|
||||||
|
for (uint32_t subBlockX = 0; subBlockX < 2; ++subBlockX) {
|
||||||
|
const uint32_t subBlock = subBlockY * 2 + subBlockX;
|
||||||
|
for (uint32_t row = 0; row < 4; ++row) {
|
||||||
|
for (uint32_t col = 0; col < 4; ++col) {
|
||||||
|
const uint32_t x = bx * 8 + subBlockX * 4 + col;
|
||||||
|
const uint32_t y = by * 8 + subBlockY * 4 + row;
|
||||||
|
if (x >= mipWidth || y >= mipHeight) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t tile = (y / 4) * tilesX_I8 + (x / 8);
|
||||||
|
const uint32_t tileOffset = (y % 4) * 8 + (x % 8);
|
||||||
|
subBlockPixels[subBlock][row * 4 + col] =
|
||||||
|
readPtr[tile * 32 + tileOffset];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmprOut.swap(convertedData);
|
||||||
|
|
||||||
|
// 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,21 @@
|
|||||||
|
#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();
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user