Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dd9cab3829 | |||
| 7d402a5a2d | |||
| 6f9d979fb8 | |||
| 441c5c27c0 | |||
| 036b380276 | |||
| c93bb43d46 | |||
| ea5d021d74 | |||
| 1e1004cbfa | |||
| c2a047a3b7 | |||
| 8c46312948 | |||
| 1b2b40bc6e | |||
| dc687ab318 | |||
| 61842d980c | |||
| 6f53279cf0 | |||
| b4f8db80e2 | |||
| e1e786ef1b | |||
| d14731120b | |||
| ce12002c28 | |||
| 1ac45d11a6 | |||
| d8f8d056f5 | |||
| 77d720d640 | |||
| f7500550cd | |||
| 9fa9602772 | |||
| 261ed2b44b | |||
| e4a8338e25 | |||
| 01638373c0 | |||
| 61c842cbc8 | |||
| b2395b5d3a | |||
| ac51bee933 | |||
| 447d282eed | |||
| b887dd99e7 | |||
| b1f0f1b3ac | |||
| f8ba7ac002 | |||
| 7a14a33f55 | |||
| 78334bff14 | |||
| 1b933908c1 | |||
| a7a4aabeed | |||
| 9247fc6b43 |
@@ -13,12 +13,8 @@ RecompiledPatches/
|
||||
|
||||
# Linux build output
|
||||
build/
|
||||
build-cmake/
|
||||
*.o
|
||||
|
||||
# Flatpak build process
|
||||
repo/
|
||||
|
||||
# Windows build output
|
||||
*.exe
|
||||
*.dll
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
[submodule "lib/N64ModernRuntime"]
|
||||
path = lib/N64ModernRuntime
|
||||
url = https://github.com/N64Recomp/N64ModernRuntime
|
||||
[submodule "lib/RmlUi"]
|
||||
path = lib/RmlUi
|
||||
url = https://github.com/mikke89/RmlUi
|
||||
[submodule "lib/freetype-windows-binaries"]
|
||||
path = lib/freetype-windows-binaries
|
||||
url = https://github.com/ubawurinna/freetype-windows-binaries/
|
||||
[submodule "lib/lunasvg"]
|
||||
path = lib/lunasvg
|
||||
url = https://github.com/sammycage/lunasvg
|
||||
[submodule "lib/rt64"]
|
||||
path = lib/rt64
|
||||
url = https://github.com/rt64/rt64
|
||||
[submodule "lib/slot_map"]
|
||||
path = lib/slot_map
|
||||
url = https://github.com/SergeyMakeev/slot_map
|
||||
[submodule "lib/bk-decomp"]
|
||||
path = lib/bk-decomp
|
||||
url = https://gitlab.com/banjo.decomp/banjo-kazooie
|
||||
[submodule "BanjoRecompSyms"]
|
||||
path = BanjoRecompSyms
|
||||
url = https://github.com/BanjoRecomp/BanjoRecompSyms
|
||||
[submodule "lib/RecompFrontend"]
|
||||
path = lib/RecompFrontend
|
||||
url = https://github.com/N64Recomp/RecompFrontend
|
||||
|
||||
@@ -51,9 +51,18 @@ endif()
|
||||
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/rt64 ${CMAKE_BINARY_DIR}/rt64)
|
||||
|
||||
# set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}")
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
SET(LUNASVG_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/lunasvg)
|
||||
# set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}")
|
||||
SET(RMLUI_SVG_PLUGIN ON CACHE BOOL "" FORCE)
|
||||
SET(RMLUI_TESTS_ENABLED OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/RmlUi)
|
||||
target_compile_definitions(rmlui_core PRIVATE LUNASVG_BUILD_STATIC)
|
||||
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/N64ModernRuntime)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/RecompFrontend)
|
||||
|
||||
target_include_directories(rt64 PRIVATE ${CMAKE_BINARY_DIR}/rt64/src)
|
||||
|
||||
@@ -140,7 +149,6 @@ add_custom_command(OUTPUT
|
||||
add_executable(BanjoRecompiled)
|
||||
|
||||
set (SOURCES
|
||||
${CMAKE_SOURCE_DIR}/src/main/launcher_animation.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/main/main.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/main/register_overlays.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/main/register_patches.cpp
|
||||
@@ -149,17 +157,22 @@ set (SOURCES
|
||||
${CMAKE_SOURCE_DIR}/src/game/config.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/debug.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/recomp_api.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/recomp_extension_api.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/recomp_actor_api.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/recomp_data_api.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/game/rom_decompression.cpp
|
||||
|
||||
${CMAKE_SOURCE_DIR}/rsp/n_aspMain.cpp
|
||||
|
||||
${CMAKE_SOURCE_DIR}/lib/RmlUi/Backends/RmlUi_Platform_SDL.cpp
|
||||
)
|
||||
|
||||
target_include_directories(BanjoRecompiled PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_SOURCE_DIR}/lib/N64ModernRuntime/N64Recomp/include
|
||||
${CMAKE_SOURCE_DIR}/lib/concurrentqueue
|
||||
${CMAKE_SOURCE_DIR}/lib/GamepadMotionHelpers
|
||||
${CMAKE_SOURCE_DIR}/lib/RmlUi/Include
|
||||
${CMAKE_SOURCE_DIR}/lib/RmlUi/Backends
|
||||
${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib
|
||||
${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib/hlslpp/include
|
||||
${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib/dxc/inc
|
||||
@@ -171,18 +184,11 @@ target_include_directories(BanjoRecompiled PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/lib/RecompFrontend/recompui/src
|
||||
${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/include
|
||||
${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib/nativefiledialog-extended/src/include
|
||||
${CMAKE_SOURCE_DIR}/lib/SlotMap
|
||||
${CMAKE_SOURCE_DIR}/lib/slot_map/slot_map
|
||||
${CMAKE_BINARY_DIR}/shaders
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
# Generate icon_bytes.c from the app icon PNG.
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.c ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.h
|
||||
COMMAND file_to_c ${CMAKE_SOURCE_DIR}/icons/app.png icon_bytes ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.c ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.h
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/icons/app.png
|
||||
)
|
||||
|
||||
target_sources(BanjoRecompiled PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.c)
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|AMD64")
|
||||
target_compile_options(BanjoRecompiled PRIVATE
|
||||
-march=nehalem
|
||||
@@ -242,12 +248,12 @@ if (WIN32)
|
||||
PROPERTIES
|
||||
LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE"
|
||||
LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
|
||||
LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
|
||||
LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE" # "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
|
||||
LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
|
||||
)
|
||||
|
||||
target_sources(BanjoRecompiled PRIVATE ${CMAKE_SOURCE_DIR}/icons/app.rc)
|
||||
target_link_libraries(BanjoRecompiled PRIVATE SDL2 Winmm.lib)
|
||||
# target_sources(BanjoRecompiled PRIVATE ${CMAKE_SOURCE_DIR}/icons/app.rc)
|
||||
target_link_libraries(BanjoRecompiled PRIVATE SDL2)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
@@ -267,9 +273,15 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
find_package(SDL2 REQUIRED)
|
||||
find_package(X11 REQUIRED)
|
||||
|
||||
add_compile_definitions("PLUME_SDL_VULKAN_ENABLED")
|
||||
add_compile_definitions("RT64_SDL_WINDOW_VULKAN")
|
||||
|
||||
# Generate icon_bytes.c from the app icon PNG.
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.c ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.h
|
||||
COMMAND file_to_c ${CMAKE_SOURCE_DIR}/icons/512.png icon_bytes ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.c ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.h
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/icons/512.png
|
||||
)
|
||||
target_sources(BanjoRecompiled PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.c)
|
||||
|
||||
message(STATUS "SDL2_FOUND = ${SDL2_FOUND}")
|
||||
message(STATUS "SDL2_INCLUDE_DIRS = ${SDL2_INCLUDE_DIRS}")
|
||||
|
||||
@@ -299,6 +311,20 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
target_link_libraries(BanjoRecompiled PRIVATE "-latomic -static-libstdc++" ${CMAKE_DL_LIBS} Threads::Threads)
|
||||
endif()
|
||||
|
||||
target_link_libraries(BanjoRecompiled PRIVATE
|
||||
PatchesLib
|
||||
RecompiledFuncs
|
||||
librecomp
|
||||
ultramodern
|
||||
rt64
|
||||
RmlUi::Core
|
||||
RmlUi::Debugger
|
||||
recompinput
|
||||
recompui
|
||||
nfd
|
||||
lunasvg
|
||||
)
|
||||
|
||||
# TODO fix the rt64 CMake script so that this doesn't need to be duplicated here
|
||||
# For DXC
|
||||
set (DXC_COMMON_OPTS "-I${PROJECT_SOURCE_DIR}/src")
|
||||
@@ -331,21 +357,8 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(RECOMP_FRONTEND_N64MODERNRUNTIME_PATH ${CMAKE_SOURCE_DIR}/lib/N64ModernRuntime)
|
||||
set(RECOMP_FRONTEND_RT64_PATH ${CMAKE_SOURCE_DIR}/lib/rt64)
|
||||
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/RecompFrontend)
|
||||
|
||||
target_link_libraries(BanjoRecompiled PRIVATE
|
||||
PatchesLib
|
||||
RecompiledFuncs
|
||||
recompui
|
||||
recompinput
|
||||
librecomp
|
||||
ultramodern
|
||||
rt64
|
||||
nfd
|
||||
)
|
||||
build_vertex_shader(BanjoRecompiled "shaders/InterfaceVS.hlsl" "shaders/InterfaceVS.hlsl")
|
||||
build_pixel_shader(BanjoRecompiled "shaders/InterfacePS.hlsl" "shaders/InterfacePS.hlsl")
|
||||
|
||||
# Embed all .nrm files in the "mods" directory
|
||||
file(GLOB NRM_FILES "${CMAKE_SOURCE_DIR}/mods/*.nrm")
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 649 622" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-367,-304)">
|
||||
<g transform="matrix(0.946016,0,0,0.946016,29.4118,58.1121)">
|
||||
<g id="Banjo" transform="matrix(19.8117,0,0,19.8117,336.522,82.7412)">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M15.411,23.721L16.802,21.264L15.038,16.771C14.44,13.215 16.372,8.93 20.504,9.189C28.893,10.832 37.74,18.394 35.195,32.829C34.692,35.685 31.138,37.414 29.053,36.96" style="fill:rgb(111,36,6);"/>
|
||||
<path d="M15.038,35.777C15.056,39.159 17.023,42.13 19.725,42.13C26.084,42.13 30.194,36.258 31.12,34.02C32.045,31.782 33.531,27.026 31.12,24.615C29.348,22.843 25.753,21.06 19.991,23.173" style="fill:rgb(255,206,140);"/>
|
||||
<path d="M28.506,13.481C30.336,11.364 31.158,10.191 33.077,12.435C34.465,14.058 34.168,15.414 31.874,17.788" style="fill:rgb(111,36,6);"/>
|
||||
<g transform="matrix(0.74875,0,0,0.727217,7.57778,3.95431)">
|
||||
<path d="M28.941,12.931C30.707,10.695 31.557,9.588 33.539,12.106C34.861,13.784 34.44,15.653 31.992,17.508C31.479,15.668 30.044,14.066 28.941,12.931Z" style="fill:rgb(255,206,140);"/>
|
||||
</g>
|
||||
<path d="M16.108,35.523C16.325,39.271 20.035,39.854 22.515,38.056C24.764,36.425 25.913,32.747 24.171,29.342" style="fill:rgb(186,87,87);"/>
|
||||
<clipPath id="_clip1">
|
||||
<path d="M16.108,35.523C16.325,39.271 20.035,39.854 22.515,38.056C24.764,36.425 25.913,32.747 24.171,29.342"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip1)">
|
||||
<path d="M17.337,37.397C19.65,34.474 22.629,33.498 24.081,35.425L23.994,39.036L16.623,39.792L17.337,37.397Z" style="fill:rgb(225,151,151);"/>
|
||||
<path d="M16.709,35.345C16.811,37.082 17.425,37.886 18.875,38.022C21.324,38.253 24.213,36.316 25.008,33.12C28.305,38.592 25.787,40.96 18.875,40.981C15.876,39.827 14.338,38.095 15.374,35.345" style="fill:white;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M19.427,17.547C18.324,14.059 15.417,15.606 14.776,17.152C14.267,18.381 14.228,20.129 14.776,21.21C15.506,22.65 17.747,24.305 19.427,21.279C19.865,20.49 19.735,18.522 19.427,17.547Z" style="fill:white;"/>
|
||||
<path d="M23.5,14.989C20.518,14.838 18.529,17.828 19.101,20.275C19.38,21.474 20.275,22.542 21.968,23.047C26.221,24.314 28.194,15.65 23.5,14.989" style="fill:white;"/>
|
||||
<g transform="matrix(1.05952,0.153499,-0.15249,1.05255,1.44489,-4.37471)">
|
||||
<clipPath id="_clip2">
|
||||
<path d="M22.982,15.046C20.205,15.306 18.767,18.357 19.623,20.557C20.042,21.635 21.012,22.509 22.645,22.75C26.746,23.356 27.41,15.027 22.982,15.046"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip2)">
|
||||
<path d="M23.062,17.048C24.572,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.441,22.556 23.062,22.556C21.552,22.556 21.037,21.322 21.037,19.802C21.037,18.282 21.755,17.048 23.062,17.048Z" style="fill:rgb(65,175,239);"/>
|
||||
<clipPath id="_clip3">
|
||||
<path d="M23.062,17.048C24.572,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.441,22.556 23.062,22.556C21.552,22.556 21.037,21.322 21.037,19.802C21.037,18.282 21.755,17.048 23.062,17.048Z"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip3)">
|
||||
<g transform="matrix(1,0,0,1,0.368837,-1.57879)">
|
||||
<path d="M23.062,17.048C24.572,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.441,22.556 23.062,22.556C21.552,22.556 21.044,21.376 21.044,19.856C21.044,18.336 21.755,17.048 23.062,17.048Z" style="fill:rgb(7,121,188);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.53744,1.64783e-17,-1.64783e-17,0.53744,11.0687,9.25602)">
|
||||
<clipPath id="_clip4">
|
||||
<path d="M22.982,15.046C20.205,15.306 18.767,18.357 19.623,20.557C20.042,21.635 21.012,22.509 22.645,22.75C26.746,23.356 27.41,15.027 22.982,15.046"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip4)">
|
||||
<path d="M23.062,17.048C24.572,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.441,22.556 23.062,22.556C21.552,22.556 21.037,21.322 21.037,19.802C21.037,18.282 21.755,17.048 23.062,17.048Z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.264491,0.0301672,-0.0297719,0.264491,17.1628,13.1906)">
|
||||
<clipPath id="_clip5">
|
||||
<path d="M22.982,15.046C20.205,15.306 18.767,18.357 19.623,20.557C20.042,21.635 21.012,22.509 22.645,22.75C26.746,23.356 27.41,15.027 22.982,15.046"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip5)">
|
||||
<path d="M23.062,17.048C24.572,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.441,22.556 23.062,22.556C21.552,22.556 21.037,21.322 21.037,19.802C21.037,18.282 21.755,17.048 23.062,17.048Z" style="fill:white;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M25.086,19.953C25.086,19.962 25.085,19.97 25.085,19.978C25.067,20.476 24.984,20.868 24.875,21.175C25.011,20.789 25.073,20.363 25.086,19.953ZM24.325,22.071C24.007,22.377 23.588,22.556 23.062,22.556C21.552,22.556 21.037,21.322 21.037,19.802C21.037,18.282 21.755,17.048 23.062,17.048C24.498,17.048 25.035,18.164 25.084,19.58C25.07,19.213 25.019,18.875 24.95,18.61C24.561,17.118 23.478,17.07 23.062,17.067L23.062,17.299C23.062,17.306 22.531,17.235 22.045,17.628C21.357,18.183 21.1,19.281 21.19,20.41C21.316,21.985 22.134,22.536 23.157,22.522C23.751,22.515 24.131,22.252 24.325,22.071ZM24.875,21.175C24.87,21.188 24.865,21.202 24.861,21.215C24.773,21.452 24.66,21.665 24.522,21.848C24.638,21.694 24.769,21.476 24.875,21.175Z" style="fill:rgb(7,121,188);"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.976398,-0.00871671,0.0091843,1.02877,-5.67531,-0.415767)">
|
||||
<path d="M23.062,17.048C24.664,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.416,22.556 23.062,22.556C21.461,22.556 21.11,21.416 21.11,19.896C21.11,18.375 21.869,17.048 23.062,17.048Z" style="fill:rgb(65,175,239);"/>
|
||||
<clipPath id="_clip6">
|
||||
<path d="M23.062,17.048C24.664,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.416,22.556 23.062,22.556C21.461,22.556 21.11,21.416 21.11,19.896C21.11,18.375 21.869,17.048 23.062,17.048Z"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip6)">
|
||||
<g transform="matrix(1,0,0,1,0.661429,-1.55465)">
|
||||
<path d="M23.062,17.048C24.664,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.416,22.556 23.062,22.556C21.461,22.556 20.622,20.935 21.017,19.398C21.396,17.921 21.869,17.048 23.062,17.048Z" style="fill:rgb(7,121,188);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.53744,-2.16183e-18,-2.27597e-17,0.53744,11.0608,9.33321)">
|
||||
<clipPath id="_clip7">
|
||||
<path d="M25.328,17.462C23.752,13.788 20.732,15.77 19.87,17.392C17.949,21.006 21.567,25.434 25.638,21.482C25.656,21.464 25.675,21.446 25.694,21.428"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip7)">
|
||||
<path d="M23.062,17.048C24.664,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.416,22.556 23.062,22.556C21.461,22.556 21.037,21.322 21.037,19.802C21.037,18.282 21.869,17.048 23.062,17.048Z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.280835,0.0606888,-0.0622655,0.25954,17.4675,12.6085)">
|
||||
<clipPath id="_clip8">
|
||||
<path d="M25.328,17.462C23.752,13.788 20.732,15.77 19.87,17.392C17.949,21.006 21.567,25.434 25.638,21.482C25.656,21.464 25.675,21.446 25.694,21.428"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip8)">
|
||||
<path d="M23.062,17.048C24.664,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.416,22.556 23.062,22.556C21.461,22.556 21.037,21.322 21.037,19.802C21.037,18.282 21.869,17.048 23.062,17.048Z" style="fill:white;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M25.052,20.39C25.052,20.391 25.052,20.391 25.052,20.391C25.025,20.607 24.983,20.813 24.925,21.007C25.031,20.648 25.084,20.249 25.088,19.832C25.088,19.855 25.087,19.878 25.087,19.9C25.083,20.058 25.073,20.225 25.052,20.39ZM23.948,22.34C23.695,22.479 23.4,22.556 23.062,22.556C21.461,22.556 21.11,21.416 21.11,19.896C21.11,18.376 21.869,17.048 23.062,17.048L23.062,17.307C22.89,17.304 22.333,17.294 21.83,17.998C21.555,18.383 21.285,19.033 21.255,19.896C21.197,21.55 21.606,22.497 23.078,22.532C23.508,22.542 23.818,22.414 23.99,22.317C23.98,22.323 23.971,22.328 23.961,22.333C23.956,22.336 23.952,22.339 23.948,22.34ZM24.302,22.082C24.251,22.13 24.198,22.174 24.143,22.216C24.216,22.161 24.285,22.101 24.349,22.036C24.333,22.052 24.318,22.067 24.302,22.082ZM24.349,22.036C24.502,21.879 24.672,21.651 24.811,21.325C24.72,21.54 24.607,21.733 24.471,21.9C24.432,21.947 24.392,21.992 24.349,22.036ZM23.062,17.048C24.589,17.048 25.045,18.168 25.085,19.589C25.08,19.443 25.07,19.296 25.054,19.147C24.985,18.494 24.805,17.971 24.482,17.613C24.003,17.084 23.343,17.07 23.062,17.068L23.062,17.048Z" style="fill:rgb(7,121,188);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.260875,0.114682,-0.0945952,0.215183,19.9731,15.1626)">
|
||||
<clipPath id="_clip9">
|
||||
<path d="M22.982,15.046C20.205,15.306 18.767,18.357 19.623,20.557C20.042,21.635 21.012,22.509 22.645,22.75C26.746,23.356 27.41,15.027 22.982,15.046"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip9)">
|
||||
<path d="M23.062,17.048C24.572,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.441,22.556 23.062,22.556C21.552,22.556 21.037,21.322 21.037,19.802C21.037,18.282 21.755,17.048 23.062,17.048Z" style="fill:white;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.27972,0.0291679,-0.0255573,0.245094,12.2906,16.2888)">
|
||||
<clipPath id="_clip10">
|
||||
<path d="M25.328,17.462C23.752,13.788 20.732,15.77 19.87,17.392C17.949,21.006 21.567,25.434 25.638,21.482C25.656,21.464 25.675,21.446 25.694,21.428"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip10)">
|
||||
<path d="M23.062,17.048C24.664,17.048 25.088,18.282 25.088,19.802C25.088,21.322 24.416,22.556 23.062,22.556C21.461,22.556 21.037,21.322 21.037,19.802C21.037,18.282 21.869,17.048 23.062,17.048Z" style="fill:white;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M22.021,9.551C17.546,8.366 12.927,8.618 10.575,14.496C13.332,15.58 16.969,14.792 20.963,12.389" style="fill:rgb(111,36,6);"/>
|
||||
<g transform="matrix(0.99548,-0.0949726,0.0949726,0.99548,-0.729626,2.03017)">
|
||||
<path d="M20.504,9.189C16.028,8.005 12.927,8.618 10.575,14.496C13.332,15.58 16.969,14.792 20.963,12.389" style="fill:rgb(111,36,6);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.932428,-0.164274,0.175814,0.997929,-0.109592,3.46156)">
|
||||
<path d="M20.504,9.189C16.028,8.005 12.927,8.618 10.575,14.496C13.332,15.58 16.969,14.792 20.963,12.389" style="fill:rgb(111,36,6);"/>
|
||||
</g>
|
||||
<path d="M21.228,22.768C17.758,23.429 15.151,21.035 12.225,20.129C8.051,18.838 3.034,23.309 2.945,24.615C2.399,32.669 6.556,35.739 11.337,36.053C16.118,36.366 23.547,33.798 24.983,26.952" style="fill:rgb(255,206,140);"/>
|
||||
<clipPath id="_clip11">
|
||||
<path d="M21.228,22.768C17.758,23.429 15.151,21.035 12.225,20.129C8.051,18.838 3.034,23.309 2.945,24.615C2.399,32.669 6.556,35.739 11.337,36.053C16.118,36.366 23.547,33.798 24.983,26.952"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip11)">
|
||||
<path d="M14.98,35.788C13.095,36.183 9.808,35.962 7.43,33.8C4.424,31.068 4.608,26.832 4.776,25.035C4.786,24.927 4.861,24.866 4.874,24.856C4.901,24.835 4.932,24.818 4.964,24.808C5.072,24.777 5.155,24.823 5.17,24.831C5.265,24.883 5.291,24.972 5.296,24.988C5.306,25.021 5.305,25.057 5.306,25.092C5.307,25.149 5.082,26.554 5.219,28.18C5.782,34.87 11.575,36.34 14.934,35.795L14.98,35.788Z" style="fill:rgb(180,138,80);"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M5.583,25.051C3.978,25 2.552,24.013 1.936,22.53C1.188,20.728 0.716,18.644 1.413,16.951C2.107,15.266 4.098,14.029 6.544,13.982C8.55,13.943 11.204,15.606 11.897,17.253C12.608,18.94 12.621,21.373 10.011,23.906C9.283,24.611 8.32,25.02 7.307,25.056C6.781,25.074 6.209,25.071 5.583,25.051Z" style="fill:rgb(49,49,49);"/>
|
||||
<path d="M5.291,19.898C5.039,19.32 4.979,18.579 5.104,18.052C5.24,17.478 8.438,17.548 8.072,18.561C7.976,18.828 7.077,19.806 7.077,19.806C7.785,18.616 7.609,18.466 7.395,18.461C6.487,18.437 5.784,18.913 5.291,19.898Z"/>
|
||||
<g transform="matrix(-0.540336,-0.220184,-0.310328,0.761552,11.9366,5.53434)">
|
||||
<path d="M5.291,19.898C5.039,19.32 4.979,18.579 5.104,18.052C5.24,17.478 8.438,17.548 8.072,18.561C7.976,18.828 7.077,19.806 7.077,19.806C7.785,18.616 7.609,18.466 7.395,18.461C6.487,18.437 5.784,18.913 5.291,19.898Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 461 154" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-104,-128)">
|
||||
<path id="Cloud1" d="M541.776,256.714C556.651,258.998 565,261.564 565,264.275C565,273.809 461.716,281.55 334.5,281.55C207.284,281.55 104,273.809 104,264.275C104,260.866 117.201,257.687 139.978,255.009C136.85,250.725 135,245.429 135,239.7C135,225.461 146.426,213.9 160.5,213.9C166.004,213.9 171.103,215.668 175.272,218.673C177.641,197.762 195.214,181.5 216.512,181.5C231.842,181.5 245.242,189.926 252.431,202.446C257.117,190.196 268.878,181.5 282.631,181.5C290.836,181.5 298.332,184.596 304.04,189.694C304.013,188.966 304,188.235 304,187.5C304,154.661 330.661,128 363.5,128C380.444,128 395.742,135.098 406.583,146.479C410.731,137.908 419.439,132 429.5,132C441.276,132 451.198,140.093 454.124,151.077C457.505,150.371 461.007,150 464.593,150C492.936,150 515.972,173.174 516.185,201.801C516.786,201.767 517.391,201.75 518,201.75C535.865,201.75 550.369,216.425 550.369,234.5C550.369,243.07 547.109,250.875 541.776,256.714Z" style="fill:white;"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 461 167" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-659,-115)">
|
||||
<g id="Cloud2" transform="matrix(1,0,0,1,555,0)">
|
||||
<path d="M542.735,256.863C557.009,259.11 565,261.623 565,264.275C565,273.809 461.716,281.55 334.5,281.55C207.284,281.55 104,273.809 104,264.275C104,261.041 115.882,258.014 136.55,255.424C133.075,251.144 130.988,245.666 130.988,239.7C130.988,226.013 141.972,214.9 155.5,214.9C160.086,214.9 164.379,216.177 168.051,218.398C168.017,217.769 168,217.137 168,216.5C168,197.459 183.279,182 202.099,182C209.626,182 216.587,184.473 222.23,188.659C226.718,160.251 251.339,138.5 281,138.5C288.882,138.5 296.409,140.036 303.296,142.825C317.767,126.151 339.111,115.6 362.9,115.6C391.852,115.6 417.183,131.228 430.91,154.501C435.157,152.885 439.757,152 444.56,152C465.981,152 483.372,169.596 483.372,191.269C483.372,192.715 483.295,194.143 483.144,195.548C487.017,193.597 491.383,192.5 496,192.5C511.956,192.5 524.91,205.606 524.91,221.75C524.91,223.717 524.718,225.638 524.351,227.496C526.498,226.534 528.873,226 531.371,226C540.958,226 548.741,233.875 548.741,243.575C548.741,248.88 546.413,253.64 542.735,256.863Z" style="fill:white;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 295 167" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-1190,-115)">
|
||||
<g id="Cloud3" transform="matrix(1,0,0,1,991.5,2.84217e-14)">
|
||||
<path d="M211.793,257.103C203.71,250.792 198.5,240.894 198.5,229.775C198.5,210.734 213.779,195.275 232.599,195.275L232.611,195.275C234.309,170.098 255.297,150.174 280.901,150.174C287.974,150.174 294.694,151.694 300.753,154.426C311.82,131.462 335.322,115.6 362.5,115.6C391.518,115.6 416.345,133.682 426.32,159.183C430.023,156.91 434.367,155.6 439.012,155.6C452.54,155.6 463.523,166.713 463.523,180.4C463.523,182.645 463.228,184.821 462.674,186.89C479.579,191.132 492.124,206.599 492.124,225.006C492.124,237.763 486.099,249.107 476.773,256.282C487.456,258.673 493.5,261.392 493.5,264.275C493.5,273.809 427.407,281.55 346,281.55C264.593,281.55 198.5,273.809 198.5,264.275C198.5,261.717 203.258,259.288 211.793,257.103Z" style="fill:white;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 301 293" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-446,-345)">
|
||||
<path id="Cloud4" d="M507.232,547.816C501.885,550.184 495.97,551.5 489.75,551.5C465.88,551.5 446.5,532.12 446.5,508.25C446.5,484.38 465.88,465 489.75,465C496.442,465 502.78,466.523 508.438,469.241C508.211,467.861 508.092,466.444 508.092,465C508.092,456.045 512.646,448.144 519.562,443.49C516.331,439.168 514.417,433.806 514.417,428C514.417,413.701 526.026,402.092 540.325,402.092C544.387,402.092 548.232,403.029 551.656,404.698C558.101,398.629 566.782,394.908 576.325,394.908C578.586,394.908 580.798,395.117 582.943,395.516C582.325,392.678 582,389.731 582,386.709C582,363.919 600.502,345.417 623.291,345.417C645.367,345.417 663.42,362.779 664.529,384.581C666.116,384.142 667.782,383.908 669.5,383.908C680.262,383.908 689,393.094 689,404.408L688.998,404.729C692.46,401.423 697.058,399.408 702.099,399.408C708.585,399.408 714.336,402.744 717.882,407.873C719.085,407.628 720.328,407.5 721.599,407.5C732.361,407.5 741.099,416.686 741.099,428C741.099,432.836 739.502,437.284 736.833,440.791C739.534,445.046 741.099,450.092 741.099,455.5C741.099,470.678 728.777,483 713.599,483C707.252,483 701.405,480.845 696.749,477.228C695.363,487.436 688.367,495.872 678.972,499.323C678.991,499.879 679,500.439 679,501C679,507.623 677.683,513.941 675.297,519.706C676.122,521.635 676.733,523.677 677.1,525.803C685.992,530.361 692.083,539.62 692.083,550.291C692.083,550.59 692.078,550.888 692.069,551.184C695.81,551.993 699.161,553.931 701.787,556.643C706.24,553.716 711.501,552.024 717.135,552.024C733.148,552.024 746.147,565.691 746.147,582.524C746.147,589.606 743.847,596.127 739.989,601.306C741.31,604.095 742.049,607.212 742.049,610.5C742.049,622.38 732.404,632.024 720.524,632.024C715.35,632.024 710.599,630.194 706.885,627.147C701.859,633.741 693.923,638 685,638C669.822,638 657.5,625.678 657.5,610.5C657.5,607.508 657.979,604.626 658.864,601.929C649.258,601.088 641.62,592.914 641.036,582.753C640.047,582.915 639.033,583 638,583C631.267,583 625.326,579.405 621.822,573.942C618.019,576.272 613.811,578.004 609.33,579.006C606.616,586.84 599.485,592.451 591.111,592.5C591.691,594.787 592,597.182 592,599.648C592,615.654 579.006,628.648 563,628.648C555.88,628.648 549.356,626.077 544.307,621.813C541.916,622.913 539.275,623.524 536.5,623.524C525.738,623.524 517,614.339 517,603.024C517,597.125 519.376,591.804 523.175,588.063C519.493,585.907 517,581.774 517,577.033C517,574.591 517.661,572.31 518.806,570.377C511.821,567.258 506.917,559.976 506.917,551.5C506.917,550.242 507.025,549.011 507.232,547.816Z" style="fill:white;"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.0 KiB |
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 1054 1044" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-348,-18)">
|
||||
<g transform="matrix(0.965901,0,0,0.965901,29.8367,18.4135)">
|
||||
<rect x="330" y="0" width="1090" height="1080" style="fill:rgb(255,201,69);"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 682 B |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 2180 2160" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(0.837799,0,0,0.823158,362.599,628.361)">
|
||||
<path d="M2169.26,-763.354L2169.26,1860.69L-432.8,1860.69L-432.8,-763.354L2169.26,-763.354ZM576.269,847.984L660.512,1167.98L950.699,1088.84C912.269,1067.12 882.2,1030.18 869.936,983.6C845.93,892.416 899.177,798.549 988.767,774.117C1078.36,749.684 1170.58,803.878 1194.59,895.062C1206.85,941.647 1198.96,988.933 1176.35,1027.3L1466.53,948.162L1382.27,628.092C1360.47,662.883 1326.33,689.805 1284.12,701.316C1194.53,725.75 1102.3,671.558 1078.3,580.372C1054.29,489.188 1107.54,395.321 1197.13,370.888C1239.34,359.377 1282.13,365.317 1318.1,384.358L1250.56,127.805L960.463,206.919C983.019,168.569 990.892,121.33 978.639,74.789C954.634,-16.395 862.407,-70.589 772.817,-46.157C683.227,-21.724 629.98,72.143 653.985,163.327C666.238,209.868 696.263,246.771 734.637,268.505L444.539,347.619L512.06,604.091C476.111,585.098 433.361,579.18 391.193,590.679C301.6,615.113 248.356,708.979 272.362,800.163C296.368,891.349 388.591,945.541 478.184,921.108C520.352,909.608 554.468,882.73 576.269,847.984Z" style="fill:#1F63C2"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 1275 1346" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-505,-288)">
|
||||
<g transform="matrix(1,0,0,1,182,432)">
|
||||
<g transform="matrix(1.60405,0.926099,-0.849835,1.47196,-1141.53,-1729.71)">
|
||||
<path d="M1708.78,2.179L1708.78,916.607L1476.3,1062.88L1476.3,148.447L1708.78,2.179Z" style="fill:white;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 800 B |
@@ -1,98 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 626 774" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(18.7432,0,0,18.7432,-523.058,-16.6354)">
|
||||
<path d="M27.907,26.263C28.143,24.255 29.853,23.644 30.51,21.766C31.989,17.547 33.536,12.065 38.499,11.647C42.804,11.285 46.114,18.297 46.269,20.704" style="fill:rgb(255,8,0);"/>
|
||||
<path d="M43.914,24.141L49.374,21.553L61.231,20.771C56.596,22.793 54.56,24.744 52.176,26.175C50.874,26.957 47.438,26.469 46.145,25.919" style="fill:rgb(147,73,55);"/>
|
||||
<path d="M33.358,24.754L37.467,23.743L47.922,25.487C47.383,28.654 46.443,34.187 46.585,37.22C46.768,41.132 46.802,42.424 46.139,42.146C42.525,40.635 38.206,35.972 35.282,32.266" style="fill:rgb(255,247,82);"/>
|
||||
<clipPath id="_clip1">
|
||||
<path d="M33.358,24.754L37.467,23.743L47.922,25.487C47.383,28.654 46.443,34.187 46.585,37.22C46.768,41.132 46.802,42.424 46.139,42.146C42.525,40.635 38.206,35.972 35.282,32.266"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip1)">
|
||||
<path d="M43.6,21.343L43.875,30.283C46.057,30.917 47.599,29.129 49.287,27.789L50.722,20.771L43.6,21.343Z" style="fill:rgb(255,152,82);"/>
|
||||
</g>
|
||||
<path d="M37.467,26.47C35.161,26.605 40.2,34.968 43.039,38.061" style="fill:rgb(255,152,82);"/>
|
||||
<path d="M37.467,26.47C39.247,33.527 42.035,37.894 45.617,40.282C45.691,34.495 45.504,29.033 46.702,26.47L37.467,26.47Z" style="fill:rgb(255,107,140);"/>
|
||||
<g transform="matrix(1,0,0,1,0.34705,-0.563957)">
|
||||
<g transform="matrix(1.0402,0,0,1.03343,2.01974,-0.750564)">
|
||||
<path d="M38.377,15.224C40.611,15.039 41.442,17.13 41.442,19.136C41.442,21.141 40.627,21.872 38.76,21.872C37.848,21.872 36.545,20.671 36.545,18.665C36.545,16.66 37.384,15.306 38.377,15.224Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.0402,0,0,1.03343,-1.44414,-0.706384)">
|
||||
<path d="M38.038,15.181C39.905,15.181 41.442,17.13 41.442,19.136C41.442,21.141 40.244,22.547 38.377,22.547C36.51,22.547 34.728,21.521 34.655,18.815C34.6,16.81 35.767,15.181 38.038,15.181Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.763712,0,0,0.933729,13.3761,0.911446)">
|
||||
<path d="M38.239,17.388C39.269,17.373 40.106,18.427 40.106,19.707C40.106,20.987 39.27,22.027 38.239,22.027C37.209,22.027 36.373,20.987 36.373,19.707C36.373,18.427 36.826,17.407 38.239,17.388Z" style="fill:rgb(20,219,51);"/>
|
||||
<clipPath id="_clip2">
|
||||
<path d="M38.239,17.388C39.269,17.373 40.106,18.427 40.106,19.707C40.106,20.987 39.27,22.027 38.239,22.027C37.209,22.027 36.373,20.987 36.373,19.707C36.373,18.427 36.826,17.407 38.239,17.388Z"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip2)">
|
||||
<g transform="matrix(1.07989,0,0,0.943665,-2.82912,-0.546845)">
|
||||
<path d="M38.239,17.388C39.269,17.373 40.106,18.427 40.106,19.707C40.106,20.987 39.27,22.027 38.239,22.027C37.209,22.027 36.373,20.987 36.373,19.707C36.373,18.427 36.826,17.407 38.239,17.388Z" style="fill:rgb(12,133,22);"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.763712,0,0,0.933729,13.3761,0.911446)">
|
||||
<path d="M39.038,21.804C38.795,21.947 38.525,22.027 38.239,22.027C37.209,22.027 36.373,20.987 36.373,19.707C36.373,18.427 36.826,17.407 38.239,17.388C39.269,17.373 40.106,18.427 40.106,19.707C40.106,19.793 40.102,19.878 40.095,19.961C40.075,20.177 40.032,20.391 39.964,20.595C39.929,20.699 39.889,20.799 39.842,20.895C40.203,20.141 40.208,19.154 39.751,18.365C39.566,18.046 39.333,17.813 39.097,17.661C38.696,17.403 38.343,17.409 38.24,17.41L38.386,17.673C37.862,17.663 36.964,17.751 36.767,19.414C36.741,19.629 36.582,20.489 37.094,21.246C37.656,22.075 38.427,22.165 39.048,21.798C39.045,21.8 39.041,21.802 39.038,21.804ZM39.515,21.4C39.388,21.547 39.245,21.673 39.089,21.773C39.075,21.781 39.062,21.79 39.048,21.798C39.227,21.688 39.382,21.553 39.515,21.4Z" style="fill:rgb(12,133,22);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.399715,0,0,0.412466,27.3537,11.0962)">
|
||||
<path d="M38.239,17.388C39.269,17.373 40.106,18.427 40.106,19.707C40.106,20.987 39.27,22.027 38.239,22.027C37.209,22.027 36.373,20.987 36.373,19.707C36.373,18.427 36.826,17.407 38.239,17.388Z"/>
|
||||
</g>
|
||||
<g transform="matrix(0.240395,0.0616877,-0.0641565,0.250016,34.2748,11.2529)">
|
||||
<path d="M38.239,17.388C39.269,17.373 40.106,18.427 40.106,19.707C40.106,20.987 39.27,22.027 38.239,22.027C37.209,22.027 36.373,20.987 36.373,19.707C36.373,18.427 36.826,17.407 38.239,17.388Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.944849,0,0,0.933729,1.79968,1.16243)">
|
||||
<ellipse cx="38.239" cy="19.707" rx="1.867" ry="2.319" style="fill:rgb(20,219,51);"/>
|
||||
<clipPath id="_clip3">
|
||||
<ellipse cx="38.239" cy="19.707" rx="1.867" ry="2.319"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip3)">
|
||||
<g transform="matrix(0.942334,0,0,1,2.31274,-1.38757)">
|
||||
<ellipse cx="38.239" cy="19.707" rx="1.867" ry="2.319" style="fill:rgb(12,133,22);"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.944849,0,0,0.933729,1.79968,1.16243)">
|
||||
<path d="M39.028,21.81C39.021,21.814 39.013,21.818 39.004,21.823C39.071,21.785 39.12,21.752 39.148,21.733C39.109,21.761 39.069,21.786 39.028,21.81ZM38.239,17.388C38.343,17.388 38.444,17.398 38.543,17.418C38.568,17.424 38.594,17.43 38.62,17.437C38.503,17.407 38.376,17.389 38.239,17.388ZM39.004,21.823C38.771,21.954 38.512,22.027 38.239,22.027C37.209,22.027 36.373,20.987 36.373,19.707C36.373,18.427 37.209,17.388 38.239,17.388L38.24,17.673C37.454,17.643 37.06,18.287 36.829,18.962C36.365,20.317 36.923,21.898 38.18,21.998C38.598,22.031 38.906,21.878 39.004,21.823ZM38.62,17.437C38.652,17.445 38.683,17.454 38.714,17.464C38.872,17.515 39.021,17.592 39.16,17.69C38.966,17.553 38.776,17.478 38.62,17.437ZM39.376,17.868C39.47,17.958 39.557,18.058 39.636,18.169C39.687,18.24 39.735,18.316 39.778,18.395C39.71,18.272 39.579,18.063 39.376,17.868ZM40.091,19.409C40.101,19.507 40.106,19.606 40.106,19.707C40.106,19.733 40.106,19.759 40.105,19.785C40.1,19.962 40.078,20.138 40.041,20.309C40.104,20.017 40.121,19.711 40.091,19.409ZM40.041,20.309C39.998,20.508 39.934,20.702 39.849,20.882C39.822,20.939 39.793,20.995 39.762,21.048C39.89,20.823 39.984,20.572 40.041,20.309Z" style="fill:rgb(12,133,22);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.455702,0,0,0.450339,20.5043,10.6887)">
|
||||
<ellipse cx="38.239" cy="19.707" rx="1.867" ry="2.319"/>
|
||||
</g>
|
||||
<g transform="matrix(0.240395,0.0616877,-0.0714623,0.278486,29.3898,11.0009)">
|
||||
<path d="M38.239,17.388C39.269,17.373 40.106,18.427 40.106,19.707C40.106,20.987 39.27,22.027 38.239,22.027C37.209,22.027 36.373,20.987 36.373,19.707C36.373,18.427 36.826,17.407 38.239,17.388Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.240395,0.0616877,-0.0641565,0.250016,35.9349,12.8745)">
|
||||
<path d="M38.239,17.388C39.269,17.373 40.106,18.427 40.106,19.707C40.106,20.987 39.27,22.027 38.239,22.027C37.209,22.027 36.373,20.987 36.373,19.707C36.373,18.427 36.826,17.407 38.239,17.388Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.240395,0.0616877,-0.0714623,0.278486,31.4342,12.886)">
|
||||
<path d="M38.239,17.388C39.269,17.373 40.106,18.427 40.106,19.707C40.106,20.987 39.27,22.027 38.239,22.027C37.209,22.027 36.373,20.987 36.373,19.707C36.373,18.427 36.826,17.407 38.239,17.388Z" style="fill:white;"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M34.949,26.47C45.991,30.923 49.398,22.609 61.231,20.771C56.331,18.491 47.094,19.43 40.335,20.771C34.477,21.934 29.498,23.59 28.13,25.595C26.823,27.513 31.911,30.95 36.88,32.959" style="fill:rgb(255,247,82);"/>
|
||||
<clipPath id="_clip4">
|
||||
<path d="M34.949,26.47C45.991,30.923 49.398,22.609 61.231,20.771C56.331,18.491 47.094,19.43 40.335,20.771C34.477,21.934 29.498,23.59 28.13,25.595C26.823,27.513 31.911,30.95 36.88,32.959"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip4)">
|
||||
<path d="M62.518,20.767L57.185,19.666C55.674,19.774 54.3,23.016 56.708,23.584" style="fill:rgb(247,132,16);"/>
|
||||
</g>
|
||||
<g>
|
||||
<g transform="matrix(0.970003,-0.154382,0.15857,1.02858,0.0314522,6.52731)">
|
||||
<path d="M36.982,11.628C36.695,7.2 36.995,2.859 40.066,0.878C40.807,0.628 41.65,0.686 42.38,0.969C39.087,3.153 39.139,8.22 39.064,11.626L38.091,11.715L37.004,11.962C37.001,11.913 36.997,11.864 36.994,11.814L36.97,11.817C36.973,11.754 36.977,11.691 36.982,11.628Z" style="fill:url(#_Radial5);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.978973,0.0797037,-0.0925252,1.07184,2.61052,-2.90073)">
|
||||
<path d="M36.982,11.628C36.695,7.2 36.995,2.859 40.066,0.878C40.915,0.615 41.659,0.75 42.38,0.969C39.087,3.153 39.139,8.22 39.064,11.626L38.091,11.715L37.004,11.962C37.001,11.913 36.997,11.864 36.994,11.814L36.97,11.817C36.973,11.754 36.977,11.691 36.982,11.628Z" style="fill:url(#_Radial6);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.932256,0.309256,-0.344847,1.02284,7.32634,-11.0721)">
|
||||
<path d="M36.982,11.628C36.695,7.2 36.995,2.859 40.066,0.878C40.558,0.663 41.699,0.839 42.424,1.166C39.132,3.351 39.139,8.22 39.064,11.626L38.091,11.715L37.004,11.962C37.001,11.913 36.997,11.864 36.994,11.814L36.97,11.817C36.973,11.754 36.977,11.691 36.982,11.628Z" style="fill:url(#_Radial7);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.83251,0.521217,-0.556563,0.879409,13.5819,-17.463)">
|
||||
<path d="M36.982,11.628C36.695,7.2 36.741,3.068 39.813,1.087C40.656,1.113 41.659,1.428 42.132,1.96C38.866,3.835 38.481,9.299 39.456,10.905L38.091,11.715L37.004,11.962C37.001,11.913 36.997,11.864 36.994,11.814L36.97,11.817C36.973,11.754 36.977,11.691 36.982,11.628Z" style="fill:url(#_Radial8);"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<radialGradient id="_Radial5" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.36904,-9.3704,9.9501,4.16909,36.9827,11.4974)"><stop offset="0" style="stop-color:rgb(255,8,0);stop-opacity:1"/><stop offset="0.52" style="stop-color:rgb(249,29,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(231,99,0);stop-opacity:1"/></radialGradient>
|
||||
<radialGradient id="_Radial6" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.36904,-9.3704,9.9501,4.16909,36.9827,11.4974)"><stop offset="0" style="stop-color:rgb(255,8,0);stop-opacity:1"/><stop offset="0.52" style="stop-color:rgb(249,29,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(231,99,0);stop-opacity:1"/></radialGradient>
|
||||
<radialGradient id="_Radial7" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.36904,-9.3704,9.9501,4.16909,36.9827,11.4974)"><stop offset="0" style="stop-color:rgb(255,8,0);stop-opacity:1"/><stop offset="0.52" style="stop-color:rgb(249,29,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(231,99,0);stop-opacity:1"/></radialGradient>
|
||||
<radialGradient id="_Radial8" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.36904,-9.3704,9.9501,4.16909,36.9827,11.4974)"><stop offset="0" style="stop-color:rgb(255,8,0);stop-opacity:1"/><stop offset="0.52" style="stop-color:rgb(249,29,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(231,99,0);stop-opacity:1"/></radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 56 KiB |
@@ -0,0 +1,37 @@
|
||||
<svg width="1920" height="1280" viewBox="0 0 1920 1280" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_540_3892)">
|
||||
<path d="M640.284 1159.76C639.797 1155.45 450.469 1282.17 509.25 1013.98C558.275 790.302 931.74 830.287 935.414 1080.11C934.13 1082.73 817.852 1271.15 640.284 1159.76Z" fill="#F7FAFA"/>
|
||||
<path d="M840.342 1153.98C848.276 1149.28 858.618 1146.39 863.738 1139.58C889.655 1105.09 876.419 1006.88 843.177 979.092C807.939 949.633 781.195 946.456 745.196 976.366C712.989 1003.12 687.729 1001.8 654.91 977.124C608.969 942.579 573.886 949.503 534.1 992.979C530.091 997.36 525.037 1000.78 515.791 1007.7C512.957 1009.82 509.73 1012.26 506.019 1015.17C523.951 896.876 489.547 810.372 389.215 748.43C440.937 733.701 492.005 709.847 544.513 706.085C665.308 697.43 786.953 700.842 904.341 736.144C944.472 748.212 981.097 771.589 1020.21 787.649C1029.63 791.52 1044.09 790.074 1053.65 785.575C1129.56 749.85 1163.71 762.009 1200.28 845.599C1203.26 890.116 1201.35 923.722 1159.61 946.421C1141.33 956.364 1131.25 983.91 1120.83 1005.12C1108.07 1031.07 1098.32 1058.55 1088.28 1085.75C1079.27 1110.16 1071.64 1135.09 1061.45 1161.61C1038.31 1177.6 1017.14 1191.77 993.45 1204.76C982.508 1198.92 974.59 1192.22 965.556 1189.93C923.594 1179.3 881.322 1169.89 839.497 1158.53C839.833 1157.02 840.342 1153.98 840.342 1153.98ZM663.696 811.922C614.42 828.006 559.256 829.022 510.459 870.041C535.005 881.377 554.123 888.103 570.95 898.525C590.764 910.798 603.621 907.893 621.516 892.344C646.88 870.307 676.37 852.559 705.603 835.571C731.945 820.262 760.316 808.444 787.791 795.087C787.396 792.979 787.001 790.871 786.606 788.763C747.539 795.752 708.472 802.74 663.696 811.922ZM1060.89 840.786C1071.07 865.99 1081.26 891.193 1092.28 918.453C1118.02 922.553 1146.64 917.172 1153.07 886.418C1157.78 863.91 1155.74 830.123 1141.84 815.877C1120.28 793.79 1090.16 809.888 1066.52 826.569C1063.74 828.534 1062.19 832.254 1060.89 840.786Z" fill="#62300F"/>
|
||||
<path d="M995.96 1205.93C1017.14 1191.77 1038.31 1177.6 1064.05 1162.62C1099.11 1159.53 1129.99 1159.44 1160.02 1154.32C1186.05 1149.89 1211.11 1139.75 1239.34 1132.84C1279.43 1125.11 1316.77 1116.66 1356.71 1107.84C1367.44 1105.02 1375.56 1102.58 1386.68 1101.06C1417.57 1098.78 1445.46 1095.58 1476.26 1092.02C1489.79 1088.14 1500.41 1084.62 1512.05 1080.84C1513.07 1080.57 1515.17 1080.52 1515.17 1080.52C1607.17 1076.03 1699.17 1071.54 1793.59 1070.03C1795.74 1094.85 1795.44 1116.71 1793.29 1140.42C1786.58 1145.78 1782.2 1150.47 1776.81 1152.62C1717.36 1176.32 1657.39 1198.78 1598.41 1223.58C1581.3 1230.78 1566.9 1244.4 1548.45 1255.19C1456.27 1288.6 1366.76 1321.29 1259.62 1311.31C1271.98 1337.18 1280.5 1355.02 1288.93 1375.16C1290.9 1379.07 1292.97 1380.68 1294.77 1382.11C1294.5 1381.94 1293.99 1382.32 1293.4 1385.03C1361.57 1517.62 1439.36 1639.59 1575.52 1710.42C1520.53 1726.41 1479.19 1691.16 1436.71 1668.82C1390.82 1644.69 1350.75 1609.66 1307.32 1580.62C1250.71 1542.77 1193.24 1506.22 1136.26 1468.94C1113.13 1453.8 1090.32 1438.2 1063.15 1420.27C980.139 1371.54 972.652 1273.71 995.96 1205.93Z" fill="#FEE003"/>
|
||||
<path d="M473.743 1137.47C476.779 1137.08 479.815 1136.68 488.691 1136.06C498.038 1136.38 501.546 1136.92 505.055 1137.47C514.058 1137.92 523.061 1138.36 536.733 1141.44C558.37 1149.77 575.005 1156.93 592.37 1160.91C641.457 1172.15 684.637 1194.46 716.199 1233.43C729.906 1250.36 745.604 1276.19 742.184 1294.6C729.101 1365.01 701.55 1435.73 646.084 1479.14C574.848 1534.91 503.547 1599.29 403.882 1604.24C392.443 1604.81 381.314 1611.63 370.041 1615.55C361.764 1614.25 353.487 1612.95 341.848 1608.22C271.197 1515.55 272.792 1408.28 262.912 1304.01C293.108 1296.61 320.801 1291.47 347.486 1283.11C454.72 1249.5 469.282 1232.16 473.743 1137.47Z" fill="#F1AF85"/>
|
||||
<path d="M1236.59 1132.13C1211.11 1139.75 1186.05 1149.89 1160.02 1154.32C1129.99 1159.44 1099.11 1159.53 1066 1160.8C1071.64 1135.09 1079.27 1110.16 1088.28 1085.75C1098.32 1058.55 1108.07 1031.07 1120.83 1005.12C1131.25 983.91 1141.33 956.364 1159.61 946.421C1201.35 923.722 1203.26 890.116 1200.65 848.276C1229.54 780.721 1254.15 714.307 1287.66 652.732C1320.75 591.925 1361.11 534.774 1401.61 478.407C1426.62 443.594 1485.69 445.705 1519.17 474.27C1539.63 491.721 1565.11 503.276 1588.34 517.482C1599.16 524.101 1617.62 529.49 1618.94 537.652C1620.77 548.935 1611.81 563.927 1603.77 574.514C1564.05 626.791 1523.41 678.379 1482.51 729.751C1434.55 790.009 1453.6 850.044 1481.3 910.739C1489.86 929.474 1496.03 949.298 1501.48 973.875C1494.24 981.438 1488.81 983.75 1481.87 984.024C1466.62 959.458 1452.39 937.21 1439.27 914.33C1422.7 885.447 1404.33 891.008 1388.89 913.221C1372.36 936.982 1356.98 933.105 1332.79 924.059C1312.8 916.588 1276.64 914.068 1266.73 925.662C1243.63 952.713 1232.02 989.581 1215.66 1025.64C1222.58 1063.24 1229.59 1097.69 1236.59 1132.13Z" fill="#FF2904"/>
|
||||
<path d="M993.45 1204.76C972.652 1273.71 980.139 1371.54 1060.66 1419.33C1052.6 1431.2 1041.31 1440.41 1033.31 1451.92C961.96 1554.66 883.013 1650.58 773.747 1714.87C717.841 1747.76 653.326 1755.11 589.315 1747.89C529.296 1741.13 492.999 1694.78 480.317 1611.52C485.92 1604.94 490.262 1603.37 495.067 1604.41C506.742 1626.81 513.468 1652.19 529.943 1665.44C598.66 1720.72 739.644 1672.44 767.512 1584.68C805.086 1528.67 835.282 1472.97 824.279 1401.41C831.53 1374.04 842.141 1349.96 844.002 1325.23C845.721 1302.37 845.917 1272.14 832.967 1256.87C802.4 1220.85 763.609 1191.8 728.144 1159.94C728.144 1159.94 728.634 1159.86 731.981 1160.38C743.988 1160.73 752.648 1160.56 764.513 1160.12C791.532 1159.91 815.347 1159.97 839.161 1160.04C881.322 1169.89 923.594 1179.3 965.556 1189.93C974.59 1192.22 982.508 1198.92 993.45 1204.76Z" fill="#F2B085"/>
|
||||
<path d="M472.524 1135.06C469.282 1232.16 454.72 1249.5 347.486 1283.11C320.801 1291.47 293.108 1296.61 260.622 1302.34C246.885 1303.39 238.404 1305.33 227.06 1306.78C205.015 1298.55 185.833 1290.82 166.651 1283.08C114.696 1234.84 110.751 1171.2 115.315 1107.59C119.09 1054.98 194.335 999.957 264.464 991.678C374.636 978.67 444.355 1026.19 472.524 1135.06Z" fill="#030303"/>
|
||||
<path d="M725.034 1159.56C763.609 1191.81 802.4 1220.85 832.967 1256.87C845.917 1272.14 845.721 1302.37 844.002 1325.23C842.141 1349.96 831.53 1374.04 821.921 1401.64C804.038 1416.78 790.026 1430.44 773.721 1440.31C687.531 1492.49 600.763 1543.7 512.022 1595.26C504.768 1597.45 499.685 1599.63 494.603 1601.81C490.262 1603.37 485.92 1604.94 480.405 1608.58C444.759 1612.81 410.287 1614.96 372.928 1616.33C381.314 1611.63 392.443 1604.81 403.882 1604.24C503.547 1599.29 574.848 1534.91 646.084 1479.15C701.55 1435.73 729.101 1365.01 742.184 1294.6C745.604 1276.19 729.906 1250.36 716.199 1233.43C684.637 1194.46 641.457 1172.15 592.37 1160.91C575.005 1156.93 558.37 1149.77 540.102 1141.73C542.031 1138.9 545.26 1138.39 552.654 1137.76C558.036 1137.47 559.252 1137.3 563.1 1138.21C590.92 1144.08 616.109 1148.87 643.195 1154C646.36 1154.13 647.628 1153.93 648.897 1153.73C673.239 1155.55 697.582 1157.36 725.034 1159.56Z" fill="#D69A76"/>
|
||||
<path d="M1551.26 1255.07C1566.9 1244.4 1581.3 1230.78 1598.41 1223.58C1657.39 1198.78 1717.36 1176.32 1776.81 1152.62C1782.2 1150.47 1786.58 1145.78 1795.71 1141.55C1806.27 1150.46 1812.55 1160.1 1818.83 1169.74C1801.57 1184.19 1785.13 1199.77 1766.9 1212.88C1719.12 1247.22 1670.57 1280.49 1617.82 1315.33C1603.14 1319.41 1592.97 1322.34 1581.84 1322.63C1571.02 1298.35 1561.14 1276.71 1551.26 1255.07Z" fill="#684004"/>
|
||||
<path d="M839.497 1158.53C815.347 1159.97 791.532 1159.91 762.191 1158.36C749.054 1155.45 741.443 1154.03 733.832 1152.61C725.362 1122.91 713.629 1093.66 709.433 1063.37C705.937 1038.13 722.181 1023.98 749.438 1022.26C827.461 1017.34 854.162 1047.41 839.312 1125.01C837.797 1132.93 837.988 1141.17 838.864 1151.62C840.342 1153.98 839.833 1157.02 839.497 1158.53ZM760.158 1111.74C763.782 1114.96 767.883 1121.33 770.947 1120.86C785.23 1118.69 809.287 1117.55 811.275 1110.67C815.713 1095.32 812.437 1075.2 805.443 1060.23C802.308 1053.52 777.394 1048.42 771.724 1053.36C761.776 1062.01 758.401 1078.73 753.708 1092.57C752.471 1096.21 756.494 1101.64 760.158 1111.74Z" fill="#30C4FB"/>
|
||||
<path d="M641.299 1153.67C616.109 1148.87 590.92 1144.08 562.615 1136.48C558.536 1131.32 556.887 1129.63 554.55 1128.61C552.893 1125.38 550.868 1122.28 549.634 1118.89C536.146 1081.9 543.329 1045.31 568.005 1029.72C596.236 1011.87 621.649 1021.11 644.43 1040.7C666.907 1060.03 669.292 1103.25 648.149 1137.82C644.117 1145.7 642.708 1149.68 641.299 1153.67ZM638.523 1102.35C632.818 1085.45 629.577 1066.83 619.806 1052.75C617.114 1048.87 586.227 1055.35 583.587 1062.63C578.67 1076.19 579.38 1100.91 588.147 1107.85C597.74 1115.45 619.101 1108.19 638.523 1102.35Z" fill="#30C4FB"/>
|
||||
<path d="M1820.95 1168.31C1812.55 1160.1 1806.27 1150.46 1797.57 1139.69C1795.44 1116.71 1795.74 1094.85 1797.22 1070.46C1803.11 1066.88 1808.44 1063.85 1812.41 1065.11C1833.98 1071.99 1855.22 1079.92 1876.57 1087.49C1863.83 1105.44 1851.09 1123.39 1838.74 1144.12C1839.12 1146.9 1839.28 1147.28 1839.28 1147.28C1833.88 1153.81 1828.47 1160.35 1820.95 1168.31Z" fill="#A94105"/>
|
||||
<path d="M1483.38 986.062C1488.81 983.75 1494.24 981.438 1501.42 976.661C1508.08 1007.89 1512.99 1041.59 1516.54 1077.9C1515.17 1080.52 1513.07 1080.57 1510.37 1078.28C1499.58 1046.01 1491.48 1016.03 1483.38 986.062Z" fill="#FF4120"/>
|
||||
<path d="M507.013 1136.52C502.665 1139.78 499.233 1139.06 494.555 1137.98C497.34 1094.73 497.591 1058.23 505.576 1013.98C509.529 1012.62 516.598 1006.72 516.598 1006.72C513.708 1048.66 510.819 1090.6 507.013 1136.52Z" fill="#62300F"/>
|
||||
<path d="M732.275 1153.46C741.443 1154.03 749.054 1155.45 758.987 1158.63C752.648 1160.56 743.988 1160.73 732.096 1160.6C727.352 1157.64 727.969 1155.64 732.275 1153.46Z" fill="#D69A76"/>
|
||||
<path d="M1838.96 1146.77C1838.8 1146.64 1839.97 1147.65 1839.97 1147.65C1839.97 1147.65 1839.45 1145.93 1839.37 1146.61C1839.28 1147.28 1839.12 1146.9 1838.96 1146.77Z" fill="#A94105"/>
|
||||
<path d="M554.155 1130.62C556.887 1129.63 558.536 1131.32 559.984 1135.4C559.252 1137.3 558.036 1137.47 555.035 1137.17C553.421 1135.35 553.59 1133.99 554.155 1130.62Z" fill="#F7FAFA"/>
|
||||
<path d="M666.551 810.825C708.472 802.74 747.539 795.752 786.606 788.763C787.001 790.871 787.396 792.979 787.791 795.087C760.316 808.444 731.945 820.262 705.603 835.571C676.37 852.559 646.88 870.307 621.516 892.344C603.621 907.893 590.764 910.798 570.95 898.525C554.123 888.103 535.005 881.377 510.459 870.041C559.256 829.022 614.42 828.006 666.551 810.825Z" fill="#351907"/>
|
||||
<path d="M1060.48 837.973C1062.19 832.254 1063.74 828.534 1066.52 826.569C1090.16 809.888 1120.28 793.79 1141.84 815.877C1155.74 830.123 1157.78 863.91 1153.07 886.418C1146.64 917.172 1118.02 922.553 1092.28 918.453C1081.26 891.193 1071.07 865.99 1060.48 837.973Z" fill="#EEAE83"/>
|
||||
<path d="M1581.84 1322.63C1582.05 1328.39 1581.3 1331.5 1580 1336.99C1573.43 1339.03 1565.84 1336.16 1561.61 1338.76C1506.88 1372.38 1445.66 1380.68 1383.57 1384.21C1356.03 1385.78 1328.25 1383.01 1297.28 1382.26C1293.99 1382.32 1294.5 1381.94 1294.26 1380.26C1292.35 1376.68 1290.69 1374.77 1289.03 1372.86C1280.5 1355.02 1271.98 1337.18 1259.61 1311.31C1366.76 1321.29 1456.27 1288.6 1548.45 1255.19C1561.14 1276.71 1571.02 1298.35 1581.84 1322.63Z" fill="#A22986"/>
|
||||
<path d="M1239.34 1132.85C1229.59 1097.69 1222.58 1063.24 1218.09 1024.71C1227.89 1016.4 1235.14 1012.14 1242.44 1007.97C1296.64 977.059 1322.84 983.561 1357.79 1036.17C1359.41 1038.6 1363.69 1039.27 1367.07 1040.93C1371.26 988.879 1379.6 982.11 1434.52 985.249C1468.22 987.175 1488.77 1012.11 1485.84 1051.1C1484.79 1065.1 1477.69 1078.64 1473.36 1092.38C1445.46 1095.58 1417.57 1098.78 1386.23 1098.86C1373.23 1099.9 1363.67 1104.05 1354.11 1108.21C1316.77 1116.66 1279.43 1125.11 1239.34 1132.85ZM1296.93 1101.79C1317.5 1093 1343.26 1083.66 1323.77 1056.05C1314.69 1043.19 1292.53 1034.86 1275.87 1034.13C1268.13 1033.79 1253.81 1055.79 1252.26 1068.83C1249.2 1094.4 1270.71 1099.46 1296.93 1101.79ZM1400.93 1065.13C1416.53 1082.98 1434.49 1082.16 1447.13 1064.76C1453.01 1056.68 1452.77 1033.16 1447.64 1030.27C1435.53 1023.47 1417.91 1021.29 1404.46 1024.75C1399.4 1026.04 1399.68 1048.12 1400.93 1065.13ZM1369.82 1071.19C1370.64 1072.02 1371.35 1073.29 1372.32 1073.54C1372.96 1073.7 1374.68 1072.44 1374.71 1071.76C1374.92 1067.05 1374.82 1062.33 1374.82 1057.61C1373.55 1057.58 1372.29 1057.56 1371.02 1057.54C1370.4 1060.8 1369.78 1064.06 1369.82 1071.19Z" fill="#099805"/>
|
||||
<path d="M1476.26 1092.02C1477.69 1078.64 1484.79 1065.1 1485.84 1051.1C1488.77 1012.11 1468.22 987.175 1434.52 985.249C1379.6 982.11 1371.26 988.879 1367.07 1040.93C1363.69 1039.27 1359.41 1038.6 1357.79 1036.17C1322.84 983.561 1296.64 977.059 1242.44 1007.97C1235.14 1012.14 1227.89 1016.4 1218.19 1021.54C1232.02 989.581 1243.63 952.713 1266.73 925.662C1276.64 914.068 1312.8 916.588 1332.79 924.058C1356.98 933.105 1372.36 936.982 1388.89 913.22C1404.33 891.008 1422.7 885.447 1439.27 914.33C1452.39 937.21 1466.62 959.457 1481.87 984.024C1491.48 1016.03 1499.58 1046.01 1509.36 1078.54C1500.41 1084.62 1489.79 1088.14 1476.26 1092.02Z" fill="#FBF8F4"/>
|
||||
<path d="M1356.71 1107.84C1363.67 1104.05 1373.23 1099.9 1383.23 1097.94C1375.56 1102.58 1367.44 1105.02 1356.71 1107.84Z" fill="#0B9909"/>
|
||||
<path d="M759.13 1108.99C756.494 1101.64 752.471 1096.21 753.708 1092.56C758.401 1078.73 761.776 1062.01 771.724 1053.36C777.394 1048.42 802.308 1053.52 805.443 1060.23C812.437 1075.2 815.713 1095.32 811.275 1110.67C809.287 1117.55 785.23 1118.69 770.947 1120.86C767.883 1121.33 763.782 1114.96 759.13 1108.99Z" fill="#02090C"/>
|
||||
<path d="M636.928 1104.88C619.101 1108.19 597.74 1115.45 588.147 1107.85C579.38 1100.91 578.67 1076.19 583.587 1062.63C586.227 1055.35 617.114 1048.87 619.806 1052.75C629.577 1066.83 632.818 1085.44 636.928 1104.88Z" fill="#02090C"/>
|
||||
<path d="M1294.06 1101.9C1270.71 1099.46 1249.2 1094.4 1252.26 1068.83C1253.81 1055.79 1268.13 1033.79 1275.87 1034.13C1292.53 1034.86 1314.69 1043.19 1323.77 1056.05C1343.26 1083.66 1317.5 1093 1294.06 1101.9Z" fill="#010901"/>
|
||||
<path d="M1399.23 1062.93C1399.68 1048.12 1399.4 1026.04 1404.46 1024.75C1417.91 1021.29 1435.53 1023.47 1447.64 1030.27C1452.77 1033.16 1453.01 1056.68 1447.13 1064.76C1434.49 1082.16 1416.53 1082.98 1399.23 1062.93Z" fill="#010901"/>
|
||||
<path d="M1369.5 1069.25C1369.78 1064.06 1370.4 1060.8 1371.02 1057.54C1372.29 1057.56 1373.55 1057.58 1374.82 1057.61C1374.82 1062.33 1374.93 1067.05 1374.71 1071.76C1374.68 1072.44 1372.96 1073.7 1372.32 1073.54C1371.35 1073.29 1370.64 1072.02 1369.5 1069.25Z" fill="#0B9909"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_540_3892">
|
||||
<rect width="1920" height="1280" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
@@ -4,40 +4,23 @@
|
||||
entrypoint = 0x80000400
|
||||
# Paths are relative to the location of this config file.
|
||||
output_func_path = "RecompiledFuncs"
|
||||
rom_file_path = "banjo.us.v10.decompressed.z64"
|
||||
symbols_file_path = "BanjoRecompSyms/bk.us.rev0.syms.toml"
|
||||
rom_file_path = "banjo.us.v10.decompressed.z64"
|
||||
# elf_path = "banjo.us.v10.elf"
|
||||
# use_mdebug = true
|
||||
# trace_mode = true
|
||||
bss_section_suffix = "_bss"
|
||||
|
||||
manual_funcs = [
|
||||
{ name = "boot___osLeoAbnormalResume", section = ".boot_bk_boot", vram = 0x800037E4, size = 0xE8 },
|
||||
{ name = "boot___osLeoResume", section = ".boot_bk_boot", vram = 0x800038CC, size = 0xEC },
|
||||
]
|
||||
|
||||
mdebug_file_mappings = [
|
||||
{ filename = "src/TTC/ch/clam.c", input_section = ".text", output_section = ".TTC" },
|
||||
{ filename = "src/TTC/ch/blubber.c", input_section = ".text", output_section = ".TTC" },
|
||||
{ filename = "src/TTC/ch/lockup.c", input_section = ".text", output_section = ".TTC" },
|
||||
{ filename = "src/TTC/ch/treasure.c", input_section = ".text", output_section = ".TTC" },
|
||||
{ filename = "src/SM/ch/attacktutorial.c", input_section = ".text", output_section = ".SM" },
|
||||
{ filename = "src/SM/ch/vegetables.c", input_section = ".text", output_section = ".SM" },
|
||||
{ name = "__n_CSPVoiceHandler", section = ".core1", vram = 0x8025E438, size = 0x684 },
|
||||
]
|
||||
|
||||
[patches]
|
||||
|
||||
ignored = [
|
||||
"boot_n_aspMainTextStart",
|
||||
"boot_gSPF3DEX_fifoTextStart",
|
||||
"boot_gSPL3DEX_fifoTextStart",
|
||||
stubs = [
|
||||
]
|
||||
|
||||
renamed = [
|
||||
"wmemcpy"
|
||||
]
|
||||
|
||||
stubs = [
|
||||
ignored = [
|
||||
# Boot segment libultra duplicates
|
||||
"boot___ll_div",
|
||||
"boot___ll_lshift",
|
||||
@@ -49,6 +32,7 @@ stubs = [
|
||||
"boot___ull_divremi",
|
||||
"boot___ull_rem",
|
||||
"boot___ull_rshift",
|
||||
"boot___osInitialize_common",
|
||||
"boot_osPiRawStartDma",
|
||||
"boot_osPiGetStatus",
|
||||
"boot___osSetSR",
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
.flatpak-builder
|
||||
builddir
|
||||
repo
|
||||
*.flatpak
|
||||
@@ -1,15 +0,0 @@
|
||||
Before building the Flatpak, you must build the patches on the root directory first. **The LLVM Extension for freedesktop does not include the MIPS compiler and will fail to build the patches inside the flatpak**.
|
||||
```sh
|
||||
make -C patches CC=clang LD=ld.lld
|
||||
```
|
||||
|
||||
Build
|
||||
```sh
|
||||
flatpak-builder --force-clean --user --install-deps-from=flathub --repo=repo --install builddir io.github.banjorecomp.banjorecomp.json
|
||||
```
|
||||
|
||||
Bundle
|
||||
```sh
|
||||
flatpak build-bundle repo io.github.banjorecomp.banjorecomp.flatpak io.github.banjorecomp.banjorecomp --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo
|
||||
```
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Banjo: Recompiled
|
||||
Exec=/app/bin/BanjoRecompiled
|
||||
Type=Application
|
||||
Icon=io.github.banjorecomp.banjorecomp
|
||||
Categories=Game;
|
||||
Comment=Static recompilation of Banjo-Kazooie for PC.
|
||||
MimeType=x-scheme-handler/banjorecomp
|
||||
@@ -1,62 +0,0 @@
|
||||
{
|
||||
"id": "io.github.banjorecomp.banjorecomp",
|
||||
"runtime": "org.freedesktop.Platform",
|
||||
"runtime-version": "25.08",
|
||||
"sdk": "org.freedesktop.Sdk",
|
||||
"sdk-extensions" : [ "org.freedesktop.Sdk.Extension.llvm20" ],
|
||||
"finish-args": [
|
||||
"--share=network",
|
||||
"--socket=wayland",
|
||||
"--socket=fallback-x11",
|
||||
"--socket=pulseaudio",
|
||||
"--device=all",
|
||||
"--filesystem=host",
|
||||
"--filesystem=/media",
|
||||
"--filesystem=/run/media",
|
||||
"--filesystem=/mnt"
|
||||
],
|
||||
"modules": [
|
||||
{
|
||||
"name": "BanjoRecompiled",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_MAKE_PROGRAM=ninja -G Ninja -S lib/N64Recomp -B lib/N64Recomp/cmake-build",
|
||||
"cmake --build lib/N64Recomp/cmake-build --config Release --target N64Recomp --parallel",
|
||||
"cmake --build lib/N64Recomp/cmake-build --config Release --target RSPRecomp --parallel",
|
||||
"cp lib/N64Recomp/cmake-build/N64Recomp N64Recomp",
|
||||
"cp lib/N64Recomp/cmake-build/RSPRecomp RSPRecomp",
|
||||
"./N64Recomp banjo.us.rev0.toml",
|
||||
"./RSPRecomp n_aspMain.us.rev0.toml",
|
||||
"cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_MAKE_PROGRAM=ninja -DPATCHES_C_COMPILER=clang -DPATCHES_LD=ld.lld -DRECOMP_FLATPAK=ON -G Ninja -S . -B cmake-build",
|
||||
"cmake --build cmake-build --config Release --target BanjoRecompiled --parallel",
|
||||
"rm -rf assets/scss",
|
||||
"mkdir -p /app/bin",
|
||||
"cp cmake-build/BanjoRecompiled /app/bin/BanjoRecompiled",
|
||||
"cp recompcontrollerdb.txt /app/bin/recompcontrollerdb.txt",
|
||||
"cp -R assets /app/bin/assets",
|
||||
"install -Dm644 icons/app.png /app/share/icons/hicolor/512x512/apps/${FLATPAK_ID}.png",
|
||||
"install -Dm644 flatpak/io.github.banjorecomp.banjorecomp.metainfo.xml /app/share/metainfo/${FLATPAK_ID}.metainfo.xml",
|
||||
"install -Dm644 flatpak/io.github.banjorecomp.banjorecomp.desktop /app/share/applications/${FLATPAK_ID}.desktop"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/N64Recomp/N64Recomp.git",
|
||||
"commit": "2b6f05688de2abc7d86da5b4a89b84c2c6acbabe",
|
||||
"dest": "lib/N64Recomp"
|
||||
},
|
||||
{
|
||||
"type": "dir",
|
||||
"path": "../"
|
||||
}
|
||||
],
|
||||
"build-options": {
|
||||
"append-path": "/usr/lib/sdk/llvm20/bin",
|
||||
"prepend-ld-library-path": "/usr/lib/sdk/llvm20/lib",
|
||||
"build-args": [
|
||||
"--share=network"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>io.github.banjorecomp.banjorecomp</id>
|
||||
|
||||
<name>Banjo: Recompiled</name>
|
||||
<summary>Static recompilation of Banjo-Kazooie for PC.</summary>
|
||||
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-3.0+</project_license>
|
||||
|
||||
<supports>
|
||||
<control>pointing</control>
|
||||
<control>keyboard</control>
|
||||
<control>touch</control>
|
||||
<control>gamepad</control>
|
||||
</supports>
|
||||
|
||||
<description>
|
||||
<p>
|
||||
Banjo: Recompiled is a project that uses N64: Recompiled to statically recompile Banjo-Kazoie into a native port with many new features and enhancements. This project uses RT64 as the rendering engine to provide some of these enhancements.
|
||||
|
||||
The original game is required to run this project.
|
||||
|
||||
https://github.com/BanjoRecomp/BanjoRecomp
|
||||
</p>
|
||||
</description>
|
||||
|
||||
<launchable type="desktop-id">io.github.banjorecomp.banjorecomp.desktop</launchable>
|
||||
</component>
|
||||
@@ -1,18 +0,0 @@
|
||||
When making icons for Windows, it is important to generate the multiple ICO files on different sizes and pack them into one single ICO file.
|
||||
|
||||
Using a tool such as `icomake` is recommended for this: https://github.com/tringi/icomake
|
||||
|
||||
The recommended workflow is to progressively downscale the icon into the following sizes and export them from a tool that supports exporting to ICO:
|
||||
|
||||
- 256.ico, 256x256
|
||||
- 128.ico, 128x128
|
||||
- 64.ico, 64x64
|
||||
- 32.ico, 32x32
|
||||
- 16.ico, 16x16
|
||||
|
||||
Once these are ready, `icomake` can pack these into one icon with the following command:
|
||||
```
|
||||
.\icomake.exe app.ico 16.ico 32.ico 64.ico 128.ico 256.ico
|
||||
```
|
||||
|
||||
If done correctly, Windows will now pick the icon with the correct size on the title bar, the taskbar and as a shortcut.
|
||||
|
Before Width: | Height: | Size: 74 KiB |
@@ -1,2 +0,0 @@
|
||||
1 ICON "appb.ico"
|
||||
2 ICON "appk.ico"
|
||||
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 45 KiB |
@@ -5,30 +5,20 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "json/json.hpp"
|
||||
|
||||
namespace banjo {
|
||||
inline const std::u8string program_id = u8"BanjoRecompiled";
|
||||
inline const std::string program_name = "Banjo: Recompiled";
|
||||
|
||||
namespace configkeys {
|
||||
namespace general {
|
||||
inline const std::string note_saving_mode = "note_saving_mode";
|
||||
inline const std::string camera_invert_mode = "camera_invert_mode";
|
||||
inline const std::string analog_cam_mode = "analog_cam_mode";
|
||||
inline const std::string third_person_camera_invert_mode = "third_person_camera_invert_mode";
|
||||
inline const std::string flying_and_swimming_invert_mode = "flying_and_swimming_invert_mode";
|
||||
inline const std::string first_person_invert_mode = "first_person_invert_mode";
|
||||
inline const std::string analog_camera_sensitivity = "analog_camera_sensitivity";
|
||||
inline const std::string analog_camera_invert_mode = "analog_camera_invert_mode";
|
||||
}
|
||||
|
||||
namespace sound {
|
||||
inline const std::string bgm_volume = "bgm_volume";
|
||||
}
|
||||
|
||||
namespace graphics {
|
||||
inline const std::string cutscene_aspect_ratio_mode = "cutscene_aspect_ratio_mode";
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move loading configs to the runtime once we have a way to allow per-project customization.
|
||||
@@ -43,48 +33,9 @@ namespace banjo {
|
||||
|
||||
CameraInvertMode get_camera_invert_mode();
|
||||
|
||||
CameraInvertMode get_third_person_camera_mode();
|
||||
CameraInvertMode get_analog_camera_invert_mode();
|
||||
|
||||
CameraInvertMode get_flying_and_swimming_invert_mode();
|
||||
|
||||
CameraInvertMode get_first_person_invert_mode();
|
||||
|
||||
enum class AnalogCamMode {
|
||||
On,
|
||||
Off,
|
||||
OptionCount
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(banjo::AnalogCamMode, {
|
||||
{banjo::AnalogCamMode::On, "On"},
|
||||
{banjo::AnalogCamMode::Off, "Off"}
|
||||
});
|
||||
|
||||
AnalogCamMode get_analog_cam_mode();
|
||||
|
||||
uint32_t get_analog_cam_sensitivity();
|
||||
|
||||
enum class NoteSavingMode {
|
||||
On,
|
||||
Off,
|
||||
OptionCount
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(banjo::NoteSavingMode, {
|
||||
{banjo::NoteSavingMode::On, "On"},
|
||||
{banjo::NoteSavingMode::Off, "Off"}
|
||||
});
|
||||
|
||||
NoteSavingMode get_note_saving_mode();
|
||||
|
||||
enum class CutsceneAspectRatioMode {
|
||||
Original,
|
||||
Clamp16x9,
|
||||
Full,
|
||||
OptionCount
|
||||
};
|
||||
|
||||
CutsceneAspectRatioMode get_cutscene_aspect_ratio_mode();
|
||||
bool get_analog_cam_mode();
|
||||
|
||||
void open_quit_game_prompt();
|
||||
};
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef __BANJO_LAUNCHER_H__
|
||||
#define __BANJO_LAUNCHER_H__
|
||||
|
||||
#include "recompui/recompui.h"
|
||||
|
||||
namespace banjo {
|
||||
void launcher_animation_setup(recompui::LauncherMenu *menu);
|
||||
void launcher_animation_update(recompui::LauncherMenu *menu);
|
||||
|
||||
constexpr float launcher_options_right_position_start = 96.0f;
|
||||
constexpr float launcher_options_right_position_end = 96.0f + 24.0f;
|
||||
constexpr float launcher_options_top_offset = 96.0f;
|
||||
constexpr float launcher_options_title_offset = 120.0f;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
#ifndef __BANJO_RENDER_H__
|
||||
#define __BANJO_RENDER_H__
|
||||
|
||||
#include <unordered_set>
|
||||
#include <filesystem>
|
||||
|
||||
#include "common/rt64_user_configuration.h"
|
||||
#include "ultramodern/renderer_context.hpp"
|
||||
#include "librecomp/config.hpp"
|
||||
#include "librecomp/mods.hpp"
|
||||
|
||||
namespace RT64 {
|
||||
struct Application;
|
||||
}
|
||||
|
||||
namespace banjo {
|
||||
namespace renderer {
|
||||
inline const std::string special_option_texture_pack_enabled = "_recomp_texture_pack_enabled";
|
||||
|
||||
class RT64Context final : public ultramodern::renderer::RendererContext {
|
||||
public:
|
||||
~RT64Context() override;
|
||||
RT64Context(uint8_t *rdram, ultramodern::renderer::WindowHandle window_handle, bool developer_mode);
|
||||
|
||||
bool valid() override { return static_cast<bool>(app); }
|
||||
|
||||
bool update_config(const ultramodern::renderer::GraphicsConfig &old_config, const ultramodern::renderer::GraphicsConfig &new_config) override;
|
||||
|
||||
void enable_instant_present() override;
|
||||
void send_dl(const OSTask *task) override;
|
||||
void update_screen(uint32_t vi_origin) override;
|
||||
void shutdown() override;
|
||||
uint32_t get_display_framerate() const override;
|
||||
float get_resolution_scale() const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<RT64::Application> app;
|
||||
std::unordered_set<std::string> enabled_texture_packs;
|
||||
std::unordered_set<std::string> secondary_disabled_texture_packs;
|
||||
|
||||
void check_texture_pack_actions();
|
||||
};
|
||||
|
||||
std::unique_ptr<ultramodern::renderer::RendererContext> create_render_context(uint8_t *rdram, ultramodern::renderer::WindowHandle window_handle, bool developer_mode);
|
||||
|
||||
RT64::UserConfiguration::Antialiasing RT64MaxMSAA();
|
||||
bool RT64SamplePositionsSupported();
|
||||
bool RT64HighPrecisionFBEnabled();
|
||||
|
||||
void trigger_texture_pack_update();
|
||||
void enable_texture_pack(const recomp::mods::ModContext& context, const recomp::mods::ModHandle& mod);
|
||||
void disable_texture_pack(const recomp::mods::ModHandle& mod);
|
||||
void secondary_enable_texture_pack(const std::string& mod_id);
|
||||
void secondary_disable_texture_pack(const std::string& mod_id);
|
||||
|
||||
// Texture pack enable option. Must be an enum with two options.
|
||||
// The first option is treated as disabled and the second option is treated as enabled.
|
||||
bool is_texture_pack_enable_config_option(const recomp::config::ConfigOption& option, bool show_errors);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -2,8 +2,8 @@
|
||||
#define __RECOMP_DATA_H__
|
||||
|
||||
namespace recomputil {
|
||||
void init_extended_object_data(size_t num_types);
|
||||
void clear_all_object_data(size_t type_index);
|
||||
void init_extended_actor_data();
|
||||
void reset_actor_data();
|
||||
|
||||
void register_data_api_exports();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
"project": "CMakeLists.txt",
|
||||
"projectTarget": "BanjoRecompiled.exe",
|
||||
"name": "BanjoRecompiled.exe",
|
||||
"currentDir": "${workspaceRoot}",
|
||||
"args": ["--show-console"]
|
||||
"currentDir": "${workspaceRoot}"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
set(FREETYPE_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/include)
|
||||
set(FREETYPE_LIBRARIES "${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/release static/vs2015-2022/win64/freetype.lib")
|
||||
add_library(Freetype::Freetype STATIC IMPORTED)
|
||||
set_target_properties(Freetype::Freetype PROPERTIES
|
||||
IMPORTED_LOCATION ${FREETYPE_LIBRARIES}
|
||||
)
|
||||
target_include_directories(Freetype::Freetype INTERFACE
|
||||
${FREETYPE_INCLUDE_DIRS}
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
@@ -0,0 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
|
||||
project(GamepadMotionHelpers LANGUAGES CXX)
|
||||
|
||||
add_library(${PROJECT_NAME} INTERFACE)
|
||||
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020-2023 Julian "Jibb" Smart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,76 @@
|
||||
# GamepadMotionHelpers
|
||||
GamepadMotionHelpers is a lightweight header-only library for sensor fusion, gyro calibration, etc. BYO input library (eg [SDL2](https://github.com/libsdl-org/SDL)).
|
||||
|
||||
## Units
|
||||
Convert your gyro units into **degrees per second** and accelerometer units to **g-force** (1 g = 9.8 m/s^2). You don't have to use these units in your application, but convert to these units when writing to GamepadMotionHelpers and convert back when reading from it. Your input reader might prefer radians per second and metres per second squared, but the datasheets for every IMU I've seen talk about degrees per second and g-force.
|
||||
|
||||
## Coordinate Space
|
||||
This library uses a Y-up coordinate system. While Z-up is (only slightly) preferable for many games, PlayStation controllers use Y-up, and have set the standard for input libraries like [SDL2](https://github.com/libsdl-org/SDL) and [JSL](https://github.com/JibbSmart/JoyShockLibrary). These libraries convert inputs from other controller types to the same space used by PlayStation's DualShock 4 and DualSense, so that's what's used here.
|
||||
|
||||
## Basic Use
|
||||
Include the GamepadMotion.hpp file in your C++ project. That's it! Everything you need is in that file, and its only dependency is ```<math.h>```.
|
||||
|
||||
For each controller with gyro (and optionally accelerometer), create a ```GamepadMotion``` object. At regular intervals, whether when a new report comes in from the controller or when polling the controller's state, you should call ```ProcessMotion(...)```. This is when you tell your GamepadMotion object the latest gyro (in degrees per second) and accelerometer (in g-force) inputs. You'll also give it the time since the last update for this controller (in seconds).
|
||||
|
||||
ProcessMotion takes these inputs, updates some internal values, and then you can use any of the following to read its current state:
|
||||
- ```GetCalibratedGyro(float& x, float& y, float& z)``` - Get the controller's angular velocity in degrees per second. This is just the raw gyro you gave it minus the gyro's bias as determined by your calibration settings (more on that below).
|
||||
- ```GetGravity(float& x, float& y, float& z)``` - Get the gravity direction in the controller's local space. When the controller is still on a flat surface it'll be approximately (0, -1, 0). The controller can't detect the gravity direction when it's in freefall or being shaken around, but it can make a pretty good guess if its gyro is correctly calibrated and then make further corrections when the controller is still again.
|
||||
- ```GetProcessedAcceleration(float& x, float& y, float& z)``` - Get the controller's current acceleration in g-force with gravity removed. Raw accelerometer input includes gravity -- it is only (0, 0, 0) when the controller is in freefall. However, using the gravity direction as calculated for GetGravity, it can remove that component and detect how you're shaking the controller about. This function gives you that acceleration vector with the gravity removed.
|
||||
- ```GetOrientation(float& w, float& x, float& y, float& z)``` - Get the controller's orientation. Gyro and accelerometer input are combined to give a good estimate of the controller's orientation.
|
||||
|
||||
Additional helper functions are available for taking gravity into account and returning a "world space" or "player space" rotation in two axes. Bear in mind that the **X** and **Y** set by these functions is still around the controller's axes. This means **Y** is the *horizontal* part of the rotation, and **X** is the vertical part. To convert to a mouse-like input, you'll treat the **Y** as the horizontal or yaw input and **X** as the vertical or pitch input. This might be unintuitive, but since it's also true of the "local space" angular velocities obtained from GetCalibratedGyro, this makes it simple to let the user choose between *local space*, *world space*, and *player space* in your game or application by just swapping GetCalibratedGyro for these functions depending on that selection:
|
||||
- ```GetWorldSpaceGyro(float& x, float& y, const float sideReductionThreshold = 0.125f)``` - Get the controller's angular velocity in *world space* as described on GyroWiki in the [player space article here](http://gyrowiki.jibbsmart.com/blog:player-space-gyro-and-alternatives-explained#toc6). Yaw input will be derived from motion around the gravity axis, and pitch input from an appropriate pitch axis calculated from the controller's orientation with respect to the gravity axis. Any errors in the calculated gravity axis (though likely very small) will be taken on by the calculated world space gyro rotation, making it slightly less robust than using calibrated gyro directly ("local space" gyro) or using *player space* gyro below. More info in the linked article.
|
||||
- ```GetPlayerSpaceGyro(float& x, float& y, const float yawRelaxFactor = 1.41f)``` - Get the controller's angular velocity in *player space* as described on GyroWiki in the [player space article here](http://gyrowiki.jibbsmart.com/blog:player-space-gyro-and-alternatives-explained#toc7). Yaw input will be derived from motion approximately around the gravity axis, without any impact from errors in the gravity calculation. Pitch is just local pitch. It is robust, accommodates players who are used to both local space and world space gyro, while taking on most of the advantages of each. It is proven in popular games and is an ideal default for players using a standalone controller. For handheld (where the screen is part of the controller, such as mobile, Switch, or Steam Deck) local space (using the calibrated gyro input directly) may be preferable. More info in the linked article.
|
||||
|
||||
If you want to plug in the gyro and gravity values yourself (perhaps you're using an externally calculated gravity), you can use ```CalculateWorldSpaceGyro``` and ```CalculatePlayerSpaceGyro``` instead. Make sure you use this GamepadMotionHelpers' coordinate space, units, and gravity is normalized, since those are all assumed for these functions.
|
||||
|
||||
## Sensor Fusion
|
||||
Combining multiple types of sensor like this to get a better picture of the controller's state is called "sensor fusion". Moment-to-moment changes in orientation are detected using the gyro, but that only gives local angular velocity and needs to be correctly calibrated. Errors can accumulate over time. The gravity vector as detected by the accelerometer is used to make corrections to the relevant components of the controller's orientation.
|
||||
|
||||
But this cannot be used to correct the controller's orientation around the gravity vector (the **yaw** axis). If you're using the controller's absolute orientation for some reason, this "yaw drift" may need to be accounted for somehow. Some devices also have a magnetometer (compass) to counter yaw drift, but since popular game controllers don't have a magnetometer, I haven't tried it myself. In future, if I get such a device, I'd like to add the option for GamepadMotionHelpers to accept magnetometer input and account for it when calculating values for the above functions.
|
||||
|
||||
## Gyro Calibration
|
||||
Modern gyroscopes often need calibration. This is like how a [weighing scale](https://en.wikipedia.org/wiki/Weighing_scale) can need calibration to tell it what 'zero' is. Like a weighing scale, a correctly calibrated gyroscope will give an accurate reading. If you're using the gyro input as a mouse, which is the simplest application of a controller's gyro, you can find essential reading on [GyroWiki here](http://gyrowiki.jibbsmart.com/blog:good-gyro-controls-part-1:the-gyro-is-a-mouse).
|
||||
|
||||
Calibration just means having the controller sit still and remembering the average reported angular velocity in each axis. This is the gyro's "bias". In GamepadMotionHelpers, I call our best guess at the controller's bias the "calibration offset". GamepadMotionHelpers has some options to help with calibrating:
|
||||
|
||||
At any time, you can begin manually calibrating a controller by calling ```StartContinuousCalibration()```. This will start recording the average angular velocity and apply it immediately to any subsequent **GetGalibratedGyro(...)** call. At any time you can ```PauseContinuousCalibration()``` to no longer add current values to the average angular velocity being recorded. You can ```ResetContinousCalibration()``` to remove the recorded average before starting over with **StartContinuousCalibration** again.
|
||||
|
||||
You can read the stored calibration values using ```GetCalibrationOffset(float& xOffset, float& yOffset, float& zOffset)```. You can manually set the calibration offset yourself with ```SetCalibrationOffset(float xOffset, float yOffset, float zOffset, int weight)```. This will override all stored values. The **weight** argument at the end determines how strongly these values should be considered over time if Continuous Calibration is still active (new values are still being added to the average). Each new sample has a weight of 1, so if you **SetCalibrationOffset** with a weight of 10, it'll have the weight of 10 samples when calculating the average. If you're not continuing to add samples (Continuous Calibration is not active), the weight will be meaningless. Setting this manually is unusual, so don't worry about it too much if that sounds complicated.
|
||||
|
||||
Most games don't ask the user to calibrate the gyro themselves. They have built-in automatic calibration, which I like to call "auto-calibration". There's no such thing as a "good enough" auto-calibration solution -- at least not with only gyro and accelerometer. Every game that has an auto-calibration solution would be made better for more serious players with the option to manually calibrate their gyro, so I urge you to provide players the option to do the same in your game. Having said that, auto-calibration is a useful option for casual players, and you may choose to have it enabled in your game by default.
|
||||
|
||||
So GamepadMotionHelpers provides some auto-calibration options. You can call ```SetCalibrationMode(CalibrationMode)``` on each GamepadMotion instance with the following options:
|
||||
- ```CalibrationMode::Manual``` - No auto-calibration. This is the default.
|
||||
- ```CalibrationMode::Stillness``` - Automatically try to detect when the controller is being held still and update the calibration offset accordingly.
|
||||
- ```CalibrationMode::SensorFusion``` - Calculate an angular velocity from changes in the gravity direction as detected by the accelerometer. If these are steady enough, use them to make corrections to the calibration offset. This will only apply to relevant axes.
|
||||
|
||||
Many players are already aware of the shortcomings of trying to automatically detect stillness to automatically calibrate the gyro. Whether on Switch, PlayStation, or using PlayStation controllers on PC, players have tried to track a slow or distant target only to have the aimer suddenly stop moving! The game or the platform has **misinterpreted their slow and steady input as the controller being held still**, and they've incorrectly recalibrated accordingly. Players *hate it* when this happens.
|
||||
|
||||
**This is why it's important to let players manually calibrate their gyro** if they want to.
|
||||
|
||||
Auto-calibration is used so widely in console games that it's speculated that game developers may not have the option to disable it on these platforms. If this is the case, GamepadMotionHelpers offers a big advantage over those platforms: you can disable it and enable it at any time.
|
||||
|
||||
You, the game developer, can have your game tell if the player is tracking a distant or slow-moving target. You can tell if the player's aimer is moving towards a visible target or roughly following the movement of one. When it is, maybe disabling the auto-calibration (```SetCalibrationMode(CalibrationMode::Manual)```) could be the difference between good and bad auto-calibration. I don't know if the GamepadMotionHelpers auto-calibration functions are better or worse than their Switch and PlayStation counterparts generally, but by letting you take the game's context into account, you may be able to offer players a way better experience without them having to manually calibrate.
|
||||
|
||||
But still give them the option to calibrate manually, please :)
|
||||
|
||||
The **SensorFusion** calibration mode has shortcomings of its own. It's much harder to accidentally trick the game into incorrectly calibrating, but the angular velocity calculated from the accelerometer moment-to-moment is generally much less precise. Leaving the controller still, you'll notice the calibrated gyro moving slightly up and down over time. So while the **Stillness** mode is characterised by good behaviour occasionally punctuated by frustrating errors, the **SensorFusion** mode will tend to be more consistently not-quite-right without being terrible.
|
||||
|
||||
Secondly, this library currently only combines accelerometer and gyro, so the **SensorFusion** auto-calibration cannot correct the gyro in all axes at the same time. The **SensorFusion**-only mode will be more useful in future when magnetometer input is supported, which can account for the axes that the accelerometer can't.
|
||||
|
||||
Both auto-calibration modes can be combined by passing ```CalibrationMode::Stillness | CalibrationMode::SensorFusion``` to **SetCalibrationMode**. In this case, it'll use **Stillness** auto-calibration, but it'll adjust the calibration offset based on any angular velocity implied by changes in the accelerometer input. This tends to give better results than just using **Stillness** or **SensorFusion** on their own.
|
||||
|
||||
If you aren't sure what to choose, I'd suggest using the combined ```CalibrationMode::Stillness | CalibrationMode::SensorFusion``` when auto calibration is enabled, but also allowing the player to manually calibrate.
|
||||
|
||||
**TODO** This is a clunky way to let the user set up what is obviously the best solution. Maybe I should just call it "hybrid" or something and be done with it?
|
||||
|
||||
Auto-calibration can also be used to communicate manual calibration to the player. ```GetAutoCalibrationIsSteady()``` will tell you whether GamepadMotionHelpers thinks the controller is currently being held steady (if auto-calibration is enabled). ```GetAutoCalibrationConfidence()``` will tell you how confident GamepadMotionHelpers is that it has a good calibration value from auto-calibration, from 0-1. Higher confidence means that new calibration changes will be applied more gradually. You can use these functions to detect when a controller needs to be calibrated, prompt the player to put their controller down, detect when they have put their controller down, and show progress for calibration (default 1 second once it starts). You can also override the confidence yourself (```SetAutoCalibrationConfidence()```), and resetting calibration will reset confidence to 0. How quickly confidence grows as well as other calibration settings can be customised in **GamepadMotionSettings**.
|
||||
|
||||
## In the Wild
|
||||
GamepadMotionHelpers is currently used in:
|
||||
- [JoyShockMapper](https://github.com/Electronicks/JoyShockMapper)
|
||||
- [JoyShockLibrary](https://github.com/JibbSmart/JoyShockLibrary)
|
||||
- JoyShockOverlay
|
||||
|
||||
If you know of any other games or applications using GamepadMotionHelpers, please let me know!
|
||||
@@ -1,257 +0,0 @@
|
||||
This file is originally from the repo: https://github.com/SergeyMakeev/SlotMap
|
||||
|
||||
The original license and README are as follows:
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Sergey Makeev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
# Slot Map
|
||||
|
||||
[](https://github.com/SergeyMakeev/slot_map/actions)
|
||||
[](https://ci.appveyor.com/project/SergeyMakeev/slot-map)
|
||||
[](https://codecov.io/gh/SergeyMakeev/slot_map)
|
||||

|
||||
|
||||
A Slot Map is a high-performance associative container with persistent unique keys to access stored values. Upon insertion, a key is returned that can be used to later access or remove the values. Insertion, removal, and access are all guaranteed to take `O(1)` time (best, worst, and average case)
|
||||
Great for storing collections of objects that need stable, safe references but have no clear ownership.
|
||||
|
||||
The difference between a `std::unordered_map` and a `dod::slot_map` is that the slot map generates and returns the key when inserting a value. A key is always unique and will only refer to the value that was inserted.
|
||||
|
||||
Usage example:
|
||||
```cpp
|
||||
slot_map<std::string> strings;
|
||||
auto red = strings.emplace("Red");
|
||||
auto green = strings.emplace("Green");
|
||||
auto blue = strings.emplace("Blue");
|
||||
|
||||
const std::string* val1 = strings.get(red);
|
||||
if (val1)
|
||||
{
|
||||
printf("red = '%s'\n", val1->c_str());
|
||||
}
|
||||
|
||||
strings.erase(green);
|
||||
printf("%d\n", strings.has(green));
|
||||
printf("%d\n", strings.has(blue));
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
red = 'Red'
|
||||
0
|
||||
1
|
||||
```
|
||||
|
||||
# Implementation details
|
||||
|
||||
The slot map container will allocate memory in pages (default page size = 4096 elements) to avoid memory spikes during growth and be able to deallocate pages that are no longer needed.
|
||||
Also, the page-based memory allocator is very important since it guarantees "pointers stability"; hence, we never move values in memory.
|
||||
|
||||
|
||||
Keys are always uses `uint64_t/uint32_t` (configurable) and technically typless, but we "artificially" make them typed to get a few extra compile-time checks.
|
||||
i.e., the following code will produce a compiler error
|
||||
```cpp
|
||||
slot_map<std::string> strings;
|
||||
slot_map<int> numbers;
|
||||
slot_map<int>::key numKey = numbers.emplace(3);
|
||||
const std::string* value = strings.get(numKey); // <---- can not use slot_map<int>::key to index slot_map<std::string> !
|
||||
```
|
||||
|
||||
The keys can be converted to/from their numeric types if you do not need additional type checks.
|
||||
```cpp
|
||||
slot_map<int> numbers;
|
||||
slot_map<int>::key numKey = numbers.emplace(3);
|
||||
uint64_t rawKey = numKey; // convert to numeric type (like cast pointer to void*)
|
||||
...
|
||||
slot_map<int>::key numKey2{rawKey}; // create key from numeric type
|
||||
```
|
||||
|
||||
When a slot is reused, its version is automatically incremented (to invalidate all existing keys that refers to the same slot).
|
||||
But since we only use 20-bits *(10-bits for 32 bit keys)* for version counter, there is a possibility that the version counter will wrap around,
|
||||
and a new item will get the same key as a removed item.
|
||||
|
||||
To mitigate this potential issue, once the version counter overflows, we disable that slot so that no new keys are returned for this slot
|
||||
(this gives us a guarantee that there are no key collisions)
|
||||
|
||||
To prevent version overflow from happening too often, we need to ensure that we don't reuse the same slot too often.
|
||||
So we do not reuse recently freed slot-indices as long as their number is below a certain threshold (`kMinFreeIndices = 64`).
|
||||
|
||||
Keys also can carry a few extra bits of information provided by a user that we called `tag`.
|
||||
That might be handy to add application-specific data to keys.
|
||||
|
||||
For example:
|
||||
```cpp
|
||||
slot_map<std::string> strings;
|
||||
auto red = strings.emplace("Red");
|
||||
red.set_tag(13);
|
||||
|
||||
auto tag = red.get_tag();
|
||||
assert(tag == 13);
|
||||
```
|
||||
|
||||
Here is how a key structure looks like internally
|
||||
|
||||
64-bit key type
|
||||
|
||||
| Component | Number of bits |
|
||||
| ---------------|------------------------|
|
||||
| tag | 12 |
|
||||
| version | 20 (0..1,048,575 |
|
||||
| index | 32 (0..4,294,967,295) |
|
||||
|
||||
32-bit key type
|
||||
|
||||
| Component | Number of bits |
|
||||
| ---------------|---------------------|
|
||||
| tag | 2 |
|
||||
| version | 10 (0..1023) |
|
||||
| index | 20 (0..1,048,575) |
|
||||
|
||||
Note: To use your custom memory allocator define `SLOT_MAP_ALLOC`/`SLOT_MAP_FREE` before including `"slot_map.h"`
|
||||
|
||||
```cpp
|
||||
#define SLOT_MAP_ALLOC(sizeInBytes, alignment) aligned_alloc(alignment, sizeInBytes)
|
||||
#define SLOT_MAP_FREE(ptr) free(ptr)
|
||||
#include "slot_map.h"
|
||||
```
|
||||
|
||||
|
||||
# API
|
||||
|
||||
`bool has_key(key k) const noexcept`
|
||||
Returns true if the slot map contains a specific key
|
||||
|
||||
`void reset()`
|
||||
Clears the slot map and releases any allocated memory.
|
||||
Note: By calling this function, you must guarantee that no handles are in use!
|
||||
Otherwise calling this function might be dangerous and lead to key "collisions".
|
||||
You might consider using "clear()" instead.
|
||||
|
||||
`void clear()`
|
||||
Clears the slot map but keeps the allocated memory for reuse.
|
||||
Automatically increases version for all the removed elements (the same as calling "erase()" for all existing elements)
|
||||
|
||||
`const T* get(key k) const noexcept`
|
||||
If key exists returns a const pointer to the value corresponding to the given key or returns null elsewere.
|
||||
|
||||
`T* get(key k)`
|
||||
If key exists returns a pointer to the value corresponding to the given key or returns null elsewere.
|
||||
|
||||
`key emplace(Args&&... args)`
|
||||
Constructs element in-place and returns a unique key that can be used to access this value.
|
||||
|
||||
`void erase(key k)`
|
||||
Removes element (if such key exists) from the slot map.
|
||||
|
||||
`std::optional<T> pop(key k)`
|
||||
Removes element (if such key exists) from the slot map, returning the value at the key if the key was not previously removed.
|
||||
|
||||
`bool empty() const noexcept`
|
||||
Returns true if the slot map is empty.
|
||||
|
||||
`size_type size() const noexcept`
|
||||
Returns the number of elements in the slot map.
|
||||
|
||||
`void swap(slot_map& other) noexcept`
|
||||
Exchanges the content of the slot map by the content of another slot map object of the same type.
|
||||
|
||||
`slot_map(const slot_map& other)`
|
||||
Copy constructor
|
||||
|
||||
`slot_map& operator=(const slot_map& other)`
|
||||
Copy assignment
|
||||
|
||||
`slot_map(slot_map&& other) noexcept`
|
||||
Move constructor
|
||||
|
||||
`slot_map& operator=(slot_map&& other) noexcept`
|
||||
Move asignment
|
||||
|
||||
|
||||
`const_values_iterator begin() const noexcept`
|
||||
`const_values_iterator end() const noexcept`
|
||||
Const values iterator
|
||||
|
||||
```cpp
|
||||
for (const auto& value : slotMap)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
`Items items() const noexcept`
|
||||
Const key/value iterator
|
||||
|
||||
```cpp
|
||||
for (const auto& [key, value] : slotMap.items())
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
# References
|
||||
|
||||
Sean Middleditch
|
||||
Data Structures for Game Developers: The Slot Map, 2013
|
||||
https://web.archive.org/web/20180121142549/http://seanmiddleditch.com/data-structures-for-game-developers-the-slot-map/
|
||||
|
||||
Niklas Gray
|
||||
Building a Data-Oriented Entity System (part 1), 2014
|
||||
http://bitsquid.blogspot.com/2014/08/building-data-oriented-entity-system.html
|
||||
|
||||
Noel Llopis
|
||||
Managing Data Relationships, 2010
|
||||
https://gamesfromwithin.com/managing-data-relationships
|
||||
|
||||
Stefan Reinalter
|
||||
Adventures in data-oriented design - Part 3c: External References, 2013
|
||||
https://blog.molecular-matters.com/2013/07/24/adventures-in-data-oriented-design-part-3c-external-references/
|
||||
|
||||
Niklas Gray
|
||||
Managing Decoupling Part 4 - The ID Lookup Table, 2011
|
||||
https://bitsquid.blogspot.com/2011/09/managing-decoupling-part-4-id-lookup.html
|
||||
|
||||
Sander Mertens
|
||||
Making the most of ECS identifiers, 2020
|
||||
https://ajmmertens.medium.com/doing-a-lot-with-a-little-ecs-identifiers-25a72bd2647
|
||||
|
||||
Michele Caini
|
||||
ECS back and forth. Part 9 - Sparse sets and EnTT, 2020
|
||||
https://skypjack.github.io/2020-08-02-ecs-baf-part-9/
|
||||
|
||||
Andre Weissflog
|
||||
Handles are the better pointers, 2018
|
||||
https://floooh.github.io/2018/06/17/handles-vs-pointers.html
|
||||
|
||||
Allan Deutsch
|
||||
C++Now 2017: "The Slot Map Data Structure", 2017
|
||||
https://www.youtube.com/watch?v=SHaAR7XPtNU
|
||||
|
||||
Jeff Gates
|
||||
Init, Update, Draw - Data Arrays, 2012
|
||||
https://greysphere.tumblr.com/post/31601463396/data-arrays
|
||||
|
||||
Niklas Gray
|
||||
Data Structures Part 1: Bulk Data, 2019
|
||||
https://ourmachinery.com/post/data-structures-part-1-bulk-data/
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ single_file_output = true
|
||||
use_absolute_symbols = true
|
||||
# Point the recompiler at the symbol files so that it can resolve relocations during recompilation.
|
||||
func_reference_syms_file = "BanjoRecompSyms/bk.us.rev0.syms.toml"
|
||||
data_reference_syms_files = [ "BanjoRecompSyms/bk.us.rev0.datasyms.toml" ]
|
||||
data_reference_syms_files = [ "BanjoRecompSyms/bk.us.rev0.datasyms.toml", "BanjoRecompSyms/bk.us.rev0.datasyms_static.toml" ]
|
||||
# Tell the recompiler to write the output binary. Doing this instead of using objcopy allows the recompiler to patch MIPS32 relocs.
|
||||
output_binary_path = "patches/patches.bin"
|
||||
# Do not emit warnings for unpaired LO16 values, as clang produces many of them.
|
||||
|
||||
@@ -5,9 +5,9 @@ LD ?= ld.lld
|
||||
|
||||
GBI_DEFINE := -DF3DEX_GBI
|
||||
CFLAGS := -target mips -mips2 -mabi=32 -O2 -G0 -mno-abicalls -mno-odd-spreg -mno-check-zero-division \
|
||||
-fomit-frame-pointer -ffast-math -fno-unsafe-math-optimizations -fno-builtin-memset -funsigned-char -fno-builtin-sinf -fno-builtin-cosf \
|
||||
-Wall -Wextra -Wno-incompatible-library-redeclaration -Wno-unused-parameter -Wno-unknown-pragmas -Wno-unused-variable -Wno-missing-braces -Wno-unsupported-floating-point-opt -Wno-cast-function-type-mismatch -Werror=pointer-bool-conversion
|
||||
CPPFLAGS := -nostdinc -D_LANGUAGE_C -DMIPS -I ../lib/bk-decomp/include -I ../lib/bk-decomp/include/2.0L -I ../lib/bk-decomp/include/2.0L/PR -I../lib/rt64/include -I../lib/N64ModernRuntime/ultramodern/include $(GBI_DEFINE)
|
||||
-fomit-frame-pointer -ffast-math -fno-unsafe-math-optimizations -fno-builtin-memset \
|
||||
-Wall -Wextra -Wno-incompatible-library-redeclaration -Wno-unused-parameter -Wno-unknown-pragmas -Wno-unused-variable -Wno-missing-braces -Wno-unsupported-floating-point-opt
|
||||
CPPFLAGS := -nostdinc -D_LANGUAGE_C -DMIPS -I ../lib/bk-decomp/include -I ../lib/bk-decomp/include/2.0L -I ../lib/bk-decomp/include/2.0L/PR -I../lib/rt64/include $(GBI_DEFINE)
|
||||
LDFLAGS := -nostdlib -T patches.ld -T syms.ld -Map patches.map --unresolved-symbols=ignore-all --emit-relocs
|
||||
|
||||
C_SRCS := $(wildcard *.c)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef __MEM_FUNCS_H__
|
||||
#define __MEM_FUNCS_H__
|
||||
|
||||
#include "patch_helpers.h"
|
||||
|
||||
DECLARE_FUNC(u32, recomp_register_actor_extension, u32 actor_type, u32 size);
|
||||
DECLARE_FUNC(u32, recomp_register_actor_extension_generic, u32 size);
|
||||
DECLARE_FUNC(void, recomp_clear_all_actor_data);
|
||||
DECLARE_FUNC(u32, recomp_create_actor_data, u32 actor_type);
|
||||
DECLARE_FUNC(void, recomp_destroy_actor_data, u32 actor_handle);
|
||||
DECLARE_FUNC(void*, recomp_get_actor_data, u32 actor_handle, u32 extension_handle, u32 actor_type);
|
||||
DECLARE_FUNC(u32, recomp_get_actor_spawn_index, u32 actor_handle);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,379 @@
|
||||
#include "patches.h"
|
||||
#include "prop.h"
|
||||
#include "actor.h"
|
||||
#include "functions.h"
|
||||
#include "mem_funcs.h"
|
||||
#include "bk_api.h"
|
||||
|
||||
extern ActorArray *suBaddieActorArray;
|
||||
extern Actor *suLastBaddie;
|
||||
|
||||
void func_803255FC(Actor *this);
|
||||
void func_8032B5C0(ActorMarker *arg0, ActorMarker *arg1, struct5Cs *arg2);
|
||||
s32 func_80326C18(void);
|
||||
void func_8032FFD4(ActorMarker *this, s32 arg1);
|
||||
void marker_setModelId(ActorMarker *this, enum asset_e modelIndex);
|
||||
s32 func_80306DDC(s32 *position);
|
||||
s32 func_80307258(f32 arg0[3], s32 arg1, s32 arg2);
|
||||
struct5Bs *func_8034A2C8(void);
|
||||
void func_8033F738(ActorMarker *arg0);
|
||||
void func_8034BFF8(ActorMarker *marker);
|
||||
Struct83s *func_803406B0(void);
|
||||
|
||||
// @recomp Patched to create extension data for the actor.
|
||||
RECOMP_PATCH Actor *actor_new(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags){
|
||||
ActorAnimationInfo * sp54;
|
||||
s32 i;
|
||||
f32 sp44[3];
|
||||
|
||||
if(suBaddieActorArray == NULL){
|
||||
// @recomp Reset actor data when suBaddieActorArray is initially allocated.
|
||||
recomp_clear_all_actor_data();
|
||||
suBaddieActorArray = (ActorArray *)malloc(sizeof(ActorArray) + 20*sizeof(Actor));
|
||||
suBaddieActorArray->cnt = 0;
|
||||
suBaddieActorArray->max_cnt = 20;
|
||||
}
|
||||
|
||||
if(suBaddieActorArray->cnt + 1 > suBaddieActorArray->max_cnt){
|
||||
suBaddieActorArray->max_cnt = suBaddieActorArray->cnt + 5;
|
||||
suBaddieActorArray = (ActorArray *)realloc(suBaddieActorArray, sizeof(ActorArray) + suBaddieActorArray->max_cnt*sizeof(Actor));
|
||||
}
|
||||
|
||||
++suBaddieActorArray->cnt;
|
||||
suLastBaddie = &suBaddieActorArray->data[suBaddieActorArray->cnt - 1];
|
||||
|
||||
suLastBaddie->actor_info = actorInfo;
|
||||
suLastBaddie->unk10_25 = 0;
|
||||
suLastBaddie->unk10_18 = 0;
|
||||
suLastBaddie->state = actorInfo->startAnimation;
|
||||
suLastBaddie->position_x = (f32)position[0];
|
||||
suLastBaddie->position_y = (f32)position[1];
|
||||
suLastBaddie->position_z = (f32)position[2];
|
||||
suLastBaddie->unkF4_8 = 0;
|
||||
suLastBaddie->yaw = (f32) yaw;
|
||||
suLastBaddie->yaw_ideal = (f32) yaw;
|
||||
suLastBaddie->pitch = 0.0f;
|
||||
suLastBaddie->roll = 0.0f;
|
||||
suLastBaddie->unk6C = 0.0f;
|
||||
suLastBaddie->actor_specific_1_f = 0.0f;
|
||||
suLastBaddie->unk10_12 = 0;
|
||||
suLastBaddie->unk38_0 = 0;
|
||||
suLastBaddie->unk38_31 = 0;
|
||||
suLastBaddie->unk58_0 = 1;
|
||||
suLastBaddie->unk40 = 0;
|
||||
suLastBaddie->unk44_31 = 0;
|
||||
suLastBaddie->despawn_flag = 0;
|
||||
suLastBaddie->unk44_14 = -1;
|
||||
suLastBaddie->unk48 = 0.0f;
|
||||
suLastBaddie->unk4C = 100.0f;
|
||||
suLastBaddie->unk10_1 = 1;
|
||||
suLastBaddie->unkF4_30 = 0;
|
||||
suLastBaddie->unkF4_29 = 0;
|
||||
suLastBaddie->scale = 1.0f;
|
||||
suLastBaddie->unk124_7 = 0;
|
||||
suLastBaddie->unk124_6 = 1;
|
||||
suLastBaddie->modelCacheIndex = actorInfo->actorId;
|
||||
suLastBaddie->unk44_2 = func_80326C18();
|
||||
suLastBaddie->marker = marker_init(position, actorInfo->draw_func, (asset_getFlag(actorInfo->modelId) == 1) ? 0 : 1, actorInfo->markerId, (flags & 0x400) ? 1 : 0);
|
||||
suLastBaddie->marker->unk3E_0 = 1;
|
||||
suLastBaddie->unk138_28 = 1;
|
||||
suLastBaddie->unk10_3 = -1;
|
||||
suLastBaddie->unk10_4 = 0;
|
||||
suLastBaddie->unk10_8 = 0;
|
||||
suLastBaddie->unk10_7 = 0;
|
||||
suLastBaddie->unk10_6 = 0;
|
||||
suLastBaddie->unk54 = 0.0f;
|
||||
suLastBaddie->anctrl_asset_id = 0;
|
||||
suLastBaddie->unk5C = 0.0f;
|
||||
suLastBaddie->unkF4_31 = 0;
|
||||
suLastBaddie->unk138_30 = 0;
|
||||
suLastBaddie->unk138_3 = 0;
|
||||
suLastBaddie->unk38_21 = 0;
|
||||
suLastBaddie->unk38_13 = 0;
|
||||
suLastBaddie->unk78_22 = 0;
|
||||
suLastBaddie->unk78_31 = 0;
|
||||
suLastBaddie->unk74 = 0.0f;
|
||||
suLastBaddie->unk70 = 0.0f;
|
||||
suLastBaddie->unkF4_24 = 0;
|
||||
suLastBaddie->unk140 = 0.0f;
|
||||
suLastBaddie->unk144 = 0.0f;
|
||||
suLastBaddie->unk44_1 = 0;
|
||||
suLastBaddie->unk44_0 = 0;
|
||||
suLastBaddie->initialized = FALSE;
|
||||
suLastBaddie->volatile_initialized = FALSE;
|
||||
suLastBaddie->lifetime_value = 0.0f;
|
||||
suLastBaddie->is_bundle = FALSE;
|
||||
suLastBaddie->unk104 = NULL;
|
||||
suLastBaddie->unk100 = NULL;
|
||||
suLastBaddie->unk158[0] = NULL;
|
||||
suLastBaddie->unk158[1] = NULL;
|
||||
suLastBaddie->unk78_13 = 0;
|
||||
suLastBaddie->unk124_31 = 0;
|
||||
suLastBaddie->unkF4_20 = 0;
|
||||
suLastBaddie->sound_timer = 0.0f;
|
||||
func_8032FFD4(suLastBaddie->marker, suBaddieActorArray->cnt - 1);
|
||||
marker_setModelId(suLastBaddie->marker, actorInfo->modelId);
|
||||
marker_setActorUpdateFunc(suLastBaddie->marker, actorInfo->update_func);
|
||||
marker_setActorUpdate2Func(suLastBaddie->marker, actorInfo->update2_func);
|
||||
ml_vec3f_clear(suLastBaddie->unk1C);
|
||||
ml_vec3f_clear(suLastBaddie->velocity);
|
||||
ml_vec3f_clear(suLastBaddie->spawn_position);
|
||||
suLastBaddie->stored_anctrl_index = 0;
|
||||
suLastBaddie->unk58_2 = 1;
|
||||
suLastBaddie->stored_anctrl_playbackType_ = 0;
|
||||
suLastBaddie->stored_anctrl_forwards = 0;
|
||||
suLastBaddie->stored_anctrl_smoothTransistion = 0;
|
||||
suLastBaddie->stored_anctrl_duration = 0.0f;
|
||||
suLastBaddie->stored_anctrl_timer = 0.0f;
|
||||
suLastBaddie->unk138_19 = 0;
|
||||
suLastBaddie->stored_anctrl_subrangeMin = 0.0f;
|
||||
suLastBaddie->stored_anctrl_subrangeMax = 1.0f;
|
||||
suLastBaddie->unkF4_22 = 0;
|
||||
suLastBaddie->unk58_1 = 0;
|
||||
suLastBaddie->unk138_29 = 0;
|
||||
suLastBaddie->unk18 = actorInfo->animations;
|
||||
suLastBaddie->anctrl = NULL;
|
||||
suLastBaddie->stored_anctrl_timer = 0.0f;
|
||||
suLastBaddie->unk130 = 0;
|
||||
suLastBaddie->unk124_5 = 0;
|
||||
suLastBaddie->unk124_3 = 0;
|
||||
suLastBaddie->unk138_9 = 0;
|
||||
suLastBaddie->unk138_8 = 0;
|
||||
suLastBaddie->unk138_25 = 0;
|
||||
suLastBaddie->unk16C_3 = 0;
|
||||
suLastBaddie->unk16C_2 = 0;
|
||||
suLastBaddie->unk16C_1 = 0;
|
||||
suLastBaddie->unk16C_0 = 0;
|
||||
suLastBaddie->unk17C_31 = 0;
|
||||
suLastBaddie->unk14C[0] = NULL;
|
||||
suLastBaddie->unk14C[1] = NULL;
|
||||
suLastBaddie->unk138_27 = 0;
|
||||
suLastBaddie->has_met_before = FALSE;
|
||||
suLastBaddie->unk138_23 = 0;
|
||||
suLastBaddie->unk138_22 = 0;
|
||||
suLastBaddie->unk138_21 = 0;
|
||||
suLastBaddie->unk138_20 = 0;
|
||||
suLastBaddie->unk174 = 0.0f;
|
||||
suLastBaddie->unk178 = 0.0f;
|
||||
if( actorInfo->animations){
|
||||
sp54 = &suLastBaddie->unk18[suLastBaddie->state];
|
||||
if(sp54->index != 0){
|
||||
suLastBaddie->anctrl = anctrl_new(0);
|
||||
anctrl_reset(suLastBaddie->anctrl);
|
||||
anctrl_setIndex(suLastBaddie->anctrl, sp54->index);
|
||||
anctrl_setDuration(suLastBaddie->anctrl, sp54->duration);
|
||||
anctrl_start(suLastBaddie->anctrl, "subaddie.c", 0x4A5);
|
||||
}
|
||||
}//L80327BA8
|
||||
suLastBaddie->unk124_11 = 0;
|
||||
suLastBaddie->alpha_124_19 = 0xff;
|
||||
suLastBaddie->depth_mode = MODEL_RENDER_DEPTH_FULL;
|
||||
suLastBaddie->unk124_0 = suLastBaddie->unk138_31 = 1;
|
||||
for(i = 0; i < 0x10; i++){
|
||||
((s32 *)suLastBaddie->unk7C)[i] = 0;
|
||||
}
|
||||
for(i = 0; i < 0x0C; i++){
|
||||
((s32 *)suLastBaddie->unkBC)[i] = 0;
|
||||
}
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_0){
|
||||
suLastBaddie->unk10_25 = func_80306DDC(position) + 1;
|
||||
if(suLastBaddie->unk10_25 == 0){
|
||||
suLastBaddie->unk10_25 = 0;
|
||||
}else{
|
||||
sp44[0] = (f32)position[0];
|
||||
sp44[1] = (f32)position[1];
|
||||
sp44[2] = (f32)position[2];
|
||||
suLastBaddie->unk10_18 = func_80307258(sp44, suLastBaddie->unk10_25 - 1, 0) + 1;
|
||||
}
|
||||
}//L80327D30
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_2){
|
||||
suLastBaddie->unk10_1 = 0;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_3){
|
||||
suLastBaddie->unkF4_30 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_1){
|
||||
suLastBaddie->marker->unk44 = (struct5Bs*)1;
|
||||
}
|
||||
else if(flags & ACTOR_FLAG_UNKNOWN_6){
|
||||
suLastBaddie->marker->unk44 = func_8034A2C8();
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_12){
|
||||
func_8033F738(suLastBaddie->marker);
|
||||
func_8034BFF8(suLastBaddie->marker);
|
||||
}
|
||||
|
||||
suLastBaddie->unk148 = 0;
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_11){
|
||||
suLastBaddie->unk148 = skeletalAnim_new();
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_14){
|
||||
suLastBaddie->marker->unk50 = (s32)func_803406B0();
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_4){
|
||||
suLastBaddie->unk124_31 = -1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_7){
|
||||
suLastBaddie->unkF4_22 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_19){
|
||||
suLastBaddie->unk58_1 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_8){
|
||||
suLastBaddie->unk130 = func_803255FC;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_9){
|
||||
suLastBaddie->marker->unk40_21 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_15){
|
||||
suLastBaddie->marker->unk40_20 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_17){
|
||||
suLastBaddie->marker->unk40_22 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_22){
|
||||
suLastBaddie->marker->unk40_19 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_16){
|
||||
suLastBaddie->unk138_9 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_18){
|
||||
suLastBaddie->unk138_8 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_21){
|
||||
suLastBaddie->unk138_25 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_23){
|
||||
suLastBaddie->unk16C_3 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_24){
|
||||
suLastBaddie->unk16C_2 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_25){
|
||||
suLastBaddie->unk16C_1 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_26){
|
||||
suLastBaddie->unk17C_31 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_13){
|
||||
suLastBaddie->unk138_29 = 1;
|
||||
}
|
||||
|
||||
if(flags & ACTOR_FLAG_UNKNOWN_20){
|
||||
suLastBaddie->unk58_2 = 0;
|
||||
}
|
||||
|
||||
suLastBaddie->unk154 = 0x005e0000;
|
||||
suLastBaddie->marker->unk54 = (void (*)(struct actorMarker_s *, struct actorMarker_s *, u16 *))func_8032B5C0;
|
||||
|
||||
|
||||
for(i = 0; i < 3; ++i){
|
||||
suLastBaddie->unk164[i] = 0x63;
|
||||
}
|
||||
|
||||
suLastBaddie->unk170 = -10.0f;
|
||||
suLastBaddie->unk138_7 = 0;
|
||||
suLastBaddie->unk3C = flags;
|
||||
|
||||
// @recomp Allocate extension data for this actor and place it in padding.
|
||||
suLastBaddie->pad17C_30 = recomp_create_actor_data(actorInfo->actorId) & 0x7FFFFFFFU;
|
||||
|
||||
return suLastBaddie;
|
||||
}
|
||||
|
||||
void func_8032BB88(Actor *this, s32 arg1, s32 arg2);
|
||||
void func_8033E7CC(ActorMarker *arg0);
|
||||
void func_8034A2A8(struct5Bs *this);
|
||||
void func_8034BF54(ActorMarker *marker);
|
||||
void func_8033F784(ActorMarker *arg0);
|
||||
void func_80340690(Struct83s *self);
|
||||
void func_8032ACA8(Actor *arg0);
|
||||
|
||||
// @recomp Patched to destroy the extended actor data.
|
||||
RECOMP_PATCH void func_80325FE8(Actor *this) {
|
||||
ActorMarker *marker;
|
||||
u8 temp_v0;
|
||||
|
||||
// @recomp Destroy the extended actor data.
|
||||
recomp_destroy_actor_data(this->pad17C_30);
|
||||
|
||||
marker = this->marker;
|
||||
marker->id = 0;
|
||||
if (this->anctrl != NULL) {
|
||||
anctrl_free(this->anctrl);
|
||||
}
|
||||
temp_v0 = this->unk44_31;
|
||||
if (temp_v0 != 0) {
|
||||
sfxsource_freeSfxsourceByIndex(temp_v0);
|
||||
}
|
||||
this->anctrl = NULL;
|
||||
this->unk44_31 = 0;
|
||||
|
||||
if (this->unk138_7 != 0) {
|
||||
func_8032BB88(this, -1, 8000);
|
||||
this->unk138_7 = 0;
|
||||
}
|
||||
if (marker->actorFreeFunc != NULL) {
|
||||
marker->actorFreeFunc(this);
|
||||
marker->actorFreeFunc = NULL;
|
||||
}
|
||||
if ((s32)marker->unk44 < 0) {
|
||||
func_8033E7CC(marker);
|
||||
func_8034A2A8(marker->unk44);
|
||||
marker->unk44 = 0;
|
||||
}
|
||||
if (marker->unk4C != 0) {
|
||||
func_8034BF54(this->marker);
|
||||
marker->unk4C = 0;
|
||||
}
|
||||
if (marker->unk48 != 0) {
|
||||
func_8033F784(marker);
|
||||
marker->unk48 = 0;
|
||||
}
|
||||
if (this->unk148 != NULL) {
|
||||
skeletalAnim_free(this->unk148);
|
||||
this->unk148 = NULL;
|
||||
}
|
||||
if (marker->unk50 != 0) {
|
||||
func_80340690((Struct83s *)marker->unk50);
|
||||
marker->unk50 = 0;
|
||||
}
|
||||
func_8032ACA8(this);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT ActorExtensionId bkrecomp_extend_actor(enum actor_e type, u32 size) {
|
||||
return recomp_register_actor_extension(type, size);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT ActorExtensionId bkrecomp_extend_actor_all(u32 size) {
|
||||
return recomp_register_actor_extension_generic(size);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT void* bkrecomp_get_extended_actor_data(Actor* actor, ActorExtensionId extension) {
|
||||
return recomp_get_actor_data(actor->pad17C_30, extension, actor->actor_info->actorId);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT u32 bkrecomp_get_actor_spawn_index(Actor* actor) {
|
||||
return recomp_get_actor_spawn_index(actor->pad17C_30);
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "core1/mlmtx.h"
|
||||
|
||||
typedef struct {
|
||||
s32 cmd_0;
|
||||
s32 size_4;
|
||||
s16 unk8[];
|
||||
}GeoCmd5;
|
||||
|
||||
typedef struct {
|
||||
s32 cmd_0;
|
||||
s32 size_4;
|
||||
u8 pad8;
|
||||
s16 unkA;
|
||||
}GeoCmd7;
|
||||
|
||||
extern s32 D_80370990;
|
||||
extern BKGfxList *modelRenderDisplayList;
|
||||
|
||||
// @recomp Patched to remove unnecessary osVirtualToPhysical use to allow extended addresses.
|
||||
RECOMP_PATCH void func_80338970(Gfx **gfx, Mtx **mtx, void *arg2){
|
||||
GeoCmd5 *cmd = (GeoCmd5 *)arg2;
|
||||
int i;
|
||||
|
||||
if(D_80370990){
|
||||
// @recomp Remove unnecessary usage of osVirtualToPhysical to allow extended addresses.
|
||||
gSPDisplayList((*gfx)++, /*osVirtualToPhysical*/(modelRenderDisplayList->list + cmd->unk8[0]));
|
||||
}
|
||||
|
||||
if(D_80370990){
|
||||
for(i = 1; cmd->unk8[i]; i++){
|
||||
mlMtxApply(*mtx);
|
||||
gSPMatrix((*gfx)++, (*mtx)++, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList((*gfx)++, /*osVirtualToPhysical*/(modelRenderDisplayList->list + cmd->unk8[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @recomp Patched to remove unnecessary osVirtualToPhysical use to allow extended addresses.
|
||||
RECOMP_PATCH void func_80338AE8(Gfx **gfx, Mtx **mtx, void *arg2){
|
||||
if(D_80370990){
|
||||
// @recomp Remove unnecessary usage of osVirtualToPhysical to allow extended addresses.
|
||||
gSPDisplayList((*gfx)++, /*osVirtualToPhysical*/(modelRenderDisplayList->list + ((GeoCmd7*)arg2)->unkA));
|
||||
}
|
||||
}
|
||||
@@ -5,26 +5,12 @@
|
||||
#include "enums.h"
|
||||
#include "prop.h"
|
||||
|
||||
typedef enum {
|
||||
EXTENSION_TYPE_MARKER,
|
||||
EXTENSION_TYPE_PROP,
|
||||
} ExtensionType;
|
||||
typedef u32 ActorExtensionId;
|
||||
|
||||
// ActorMarkers
|
||||
typedef u32 MarkerExtensionId;
|
||||
ActorExtensionId bkrecomp_extend_actor(enum actor_e type, u32 size);
|
||||
ActorExtensionId bkrecomp_extend_actor_all(u32 size);
|
||||
|
||||
MarkerExtensionId bkrecomp_extend_marker(enum marker_e type, u32 size);
|
||||
MarkerExtensionId bkrecomp_extend_marker_all(u32 size);
|
||||
|
||||
void* bkrecomp_get_extended_marker_data(ActorMarker* marker, MarkerExtensionId extension);
|
||||
u32 bkrecomp_get_marker_spawn_index(ActorMarker* marker);
|
||||
|
||||
// Props
|
||||
typedef u32 PropExtensionId;
|
||||
|
||||
PropExtensionId bkrecomp_extend_prop_all(u32 size);
|
||||
|
||||
void *bkrecomp_get_extended_prop_data(Cube* cube, Prop* prop, PropExtensionId extension_id);
|
||||
u32 bkrecomp_get_prop_spawn_index(Cube* cube, Prop* prop);
|
||||
void* bkrecomp_get_extended_actor_data(Actor* actor, ActorExtensionId extension);
|
||||
u32 bkrecomp_get_actor_spawn_index(Actor* actor);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,797 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
#include "input.h"
|
||||
|
||||
#define DYNAMIC_CAMERA_STATE_R_LOOK 0x13
|
||||
|
||||
extern u8 D_8037C060;
|
||||
extern u8 D_8037C061;
|
||||
extern u8 D_8037C062;
|
||||
extern u8 D_8037DB40;
|
||||
extern f32 D_8037DBA0;
|
||||
extern f32 D_8037DBA4;
|
||||
extern f32 D_8037DBA8;
|
||||
extern f32 D_8037DBAC;
|
||||
extern f32 D_8037D994;
|
||||
extern f32 D_8037D998;
|
||||
extern f32 D_8037D99C;
|
||||
extern f32 D_8037D9E0[3];
|
||||
extern f32 D_8037D9C8[3];
|
||||
extern f32 D_8037DC10;
|
||||
extern s32 D_8037C064;
|
||||
extern s32 D_8037C068;
|
||||
extern s32 D_8037C06C;
|
||||
extern s32 D_8037C070;
|
||||
extern s32 D_8037C074;
|
||||
extern s32 D_8037C078;
|
||||
extern s32 D_8037C07C;
|
||||
extern s32 D_8037C080;
|
||||
extern s32 D_8037C084;
|
||||
extern f32 D_8037DB10;
|
||||
extern f32 D_8037DB14;
|
||||
extern f32 D_8037DB18;
|
||||
extern f32 D_8037DB1C;
|
||||
extern f32 D_8037DB20;
|
||||
extern OSContStatus pfsManagerContStatus;
|
||||
extern OSContPad pfsManagerContPadData[4];
|
||||
|
||||
extern void func_8024F35C(s32 arg0);
|
||||
extern void func_80290B60(s32 arg0);
|
||||
extern int func_80290D48(void);
|
||||
extern int func_80290E8C(void);
|
||||
extern void func_8029103C(void);
|
||||
extern void func_80291488(s32 arg0);
|
||||
extern s32 func_80298850(void);
|
||||
extern s32 func_802BC84C(s32 arg0);
|
||||
extern void func_802BD4C0(f32 arg0[3]);
|
||||
extern f32 func_802BD51C(void);
|
||||
extern void func_802BD720(f32 arg0[3]);
|
||||
extern void func_802BDB30(f32 arg0, f32 *arg1, f32 *arg2, f32 arg3, f32 arg4, f32 arg5);
|
||||
extern int func_802BE60C(void);
|
||||
extern void func_802BE6FC(f32 arg0[3], f32 arg1[3]);
|
||||
extern void func_802C0150(s32 arg0);
|
||||
extern void func_802C019C(f32 arg0[3]);
|
||||
extern void func_802C01BC(f32 arg0[3]);
|
||||
extern void func_802C01DC(f32 arg0[3]);
|
||||
extern void func_802C0234(f32 arg0[3]);
|
||||
extern void func_802C026C(f32 arg0[3]);
|
||||
extern void func_802C02B4(f32 arg0[3]);
|
||||
extern void func_802C02D4(f32 arg0[3]);
|
||||
extern void func_802C04B0(void);
|
||||
extern bool func_802C0640(void);
|
||||
extern void func_802C095C(void);
|
||||
extern void func_802C2264(f32 duration);
|
||||
extern void ncDynamicCamera_setPosition(f32 arg0[3]);
|
||||
extern void ncDynamicCamera_getPosition(f32 arg0[3]);
|
||||
extern void ncDynamicCamera_setRotation(f32 arg0[3]);
|
||||
extern void ncDynamicCamera_getRotation(f32 arg0[3]);
|
||||
extern void ncDynamicCamera_setState(s32);
|
||||
extern int ncDynamicCamera_getState(void);
|
||||
extern enum bsgroup_e player_movementGroup(void);
|
||||
extern int bainput_should_rotate_camera_left(void);
|
||||
extern int bainput_should_rotate_camera_right(void);
|
||||
extern int bainput_should_zoom_out_camera(void);
|
||||
extern int can_view_first_person(void);
|
||||
extern s32 bs_getState(void);
|
||||
extern s32 getGameMode(void);
|
||||
extern f32 player_getYaw(void);
|
||||
extern f32 player_getPitch(void);
|
||||
extern enum bswatergroup_e player_getWaterState(void);
|
||||
extern enum map_e map_get(void);
|
||||
|
||||
f32 dynamic_camera_targets[2][3];
|
||||
u32 dynamic_camera_target_frames[2];
|
||||
u32 dynamic_camera_target_frame;
|
||||
f32 analog_zoom = 2.0f;
|
||||
f32 analog_inherited_distance = 100.0f;
|
||||
f32 r_look_initial_position_offset[3];
|
||||
f32 r_look_initial_target_offset[3];
|
||||
f32 r_look_initial_offset_weight;
|
||||
bool analog_swimming_look_started;
|
||||
bool r_look_initialized_from_r_button;
|
||||
bool r_look_get_target_from_previous_frame_fix;
|
||||
|
||||
extern bool recomp_in_demo_playback_game_mode();
|
||||
|
||||
// @recomp Advances the reference frame for storing camera targets.
|
||||
void recomp_advance_dynamic_camera_targets() {
|
||||
dynamic_camera_target_frame++;
|
||||
}
|
||||
|
||||
// @recomp Check whether the analog camera was enabled by the user. Analog camera can have effects
|
||||
// over vanilla behavior, so we ignore the user setting while on demo playback modes.
|
||||
bool recomp_analog_camera_enabled() {
|
||||
if (recomp_in_demo_playback_game_mode()) {
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
return recomp_get_analog_cam_enabled();
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Check whether analog camera movement is currently allowed. Analog camera movement is disabled while crouching and its
|
||||
// related states to allow the user to use the right stick as C Button inputs without rotating the camera.
|
||||
bool recomp_analog_camera_allowed(bool allow_transition_states) {
|
||||
switch (bs_getState()) {
|
||||
case BS_CROUCH:
|
||||
case BS_9_EGG_HEAD:
|
||||
case BS_A_EGG_ASS:
|
||||
return FALSE;
|
||||
case BS_14_BTROT_ENTER:
|
||||
case BS_1A_WONDERWING_ENTER:
|
||||
return allow_transition_states;
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Apply per-axis deadzone to a value.
|
||||
f32 recomp_apply_per_axis_deadzone(f32 value) {
|
||||
const f32 per_axis_deadzone = 0.2f;
|
||||
if (value > per_axis_deadzone) {
|
||||
return (value - per_axis_deadzone) / (1.0f - per_axis_deadzone);
|
||||
}
|
||||
else if (value < -per_axis_deadzone) {
|
||||
return (value + per_axis_deadzone) / (1.0f - per_axis_deadzone);
|
||||
}
|
||||
else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Functions to get the current values of the analog camera inputs.
|
||||
void recomp_analog_camera_get(f32 *x, f32 *y) {
|
||||
float input_x, input_y;
|
||||
s32 inverted_x, inverted_y;
|
||||
recomp_get_right_analog_inputs(&input_x, &input_y);
|
||||
recomp_get_analog_inverted_axes(&inverted_x, &inverted_y);
|
||||
*x = recomp_apply_per_axis_deadzone(input_x) * (inverted_x ? 1.0f : -1.0f);
|
||||
*y = recomp_apply_per_axis_deadzone(input_y) * (inverted_y ? -1.0f : 1.0f);
|
||||
}
|
||||
|
||||
f32 recomp_analog_camera_get_x() {
|
||||
float x, y;
|
||||
recomp_analog_camera_get(&x, &y);
|
||||
return x;
|
||||
}
|
||||
|
||||
f32 recomp_analog_camera_get_y() {
|
||||
float x, y;
|
||||
recomp_analog_camera_get(&x, &y);
|
||||
return y;
|
||||
}
|
||||
|
||||
s32 recomp_get_third_person_inverted_x() {
|
||||
s32 inverted_x, inverted_y;
|
||||
if (recomp_in_demo_playback_game_mode()) {
|
||||
inverted_x = TRUE;
|
||||
} else {
|
||||
recomp_get_analog_inverted_axes(&inverted_x, &inverted_y);
|
||||
}
|
||||
|
||||
return inverted_x;
|
||||
}
|
||||
|
||||
s32 recomp_get_third_person_inverted_y() {
|
||||
s32 inverted_x, inverted_y;
|
||||
if (recomp_in_demo_playback_game_mode()) {
|
||||
inverted_y = FALSE;
|
||||
} else {
|
||||
recomp_get_analog_inverted_axes(&inverted_x, &inverted_y);
|
||||
}
|
||||
|
||||
return inverted_y;
|
||||
}
|
||||
|
||||
s32 recomp_get_flying_and_swimming_inverted_x() {
|
||||
s32 inverted_x, inverted_y;
|
||||
if (recomp_in_demo_playback_game_mode()) {
|
||||
inverted_x = FALSE;
|
||||
} else {
|
||||
recomp_get_flying_and_swimming_inverted_axes(&inverted_x, &inverted_y);
|
||||
}
|
||||
return inverted_x;
|
||||
}
|
||||
|
||||
s32 recomp_get_flying_and_swimming_inverted_y() {
|
||||
s32 inverted_x, inverted_y;
|
||||
if (recomp_in_demo_playback_game_mode()) {
|
||||
inverted_y = TRUE;
|
||||
} else {
|
||||
recomp_get_flying_and_swimming_inverted_axes(&inverted_x, &inverted_y);
|
||||
}
|
||||
return inverted_y;
|
||||
}
|
||||
|
||||
s32 recomp_get_first_person_inverted_x() {
|
||||
s32 inverted_x, inverted_y;
|
||||
if (recomp_in_demo_playback_game_mode()) {
|
||||
inverted_x = TRUE;
|
||||
} else {
|
||||
recomp_get_first_person_inverted_axes(&inverted_x, &inverted_y);
|
||||
}
|
||||
return inverted_x;
|
||||
}
|
||||
|
||||
s32 recomp_get_first_person_inverted_y() {
|
||||
s32 inverted_x, inverted_y;
|
||||
if (recomp_in_demo_playback_game_mode()) {
|
||||
inverted_y = FALSE;
|
||||
} else {
|
||||
recomp_get_first_person_inverted_axes(&inverted_x, &inverted_y);
|
||||
}
|
||||
return inverted_y;
|
||||
}
|
||||
|
||||
|
||||
// @recomp Check whether the analog camera stick is currently held.
|
||||
bool recomp_analog_camera_held(bool read_x, bool read_y) {
|
||||
if (recomp_analog_camera_enabled() && recomp_analog_camera_allowed(FALSE)) {
|
||||
float input_x, input_y;
|
||||
recomp_analog_camera_get(&input_x, &input_y);
|
||||
return ((mlAbsF(input_x) > 1e-6f) && read_x) || ((mlAbsF(input_y) > 1e-6f) && read_y);
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp If movement is allowed, update the current camera mode's yaw with the input.
|
||||
void recomp_analog_camera_update() {
|
||||
if (recomp_analog_camera_enabled() && recomp_analog_camera_allowed(FALSE)) {
|
||||
f32 analog_yaw = recomp_analog_camera_get_x() * recomp_get_analog_cam_sensitivity() * 40.0f * time_getDelta();
|
||||
if (mlAbsF(analog_yaw) > 1e-6f) {
|
||||
if (ncDynamicCamera_getState() != DYNAMIC_CAMERA_STATE_R_LOOK) {
|
||||
ncDynamicCamera_setState(DYNAMIC_CAMERA_STATE_R_LOOK);
|
||||
func_80291488(0x4);
|
||||
}
|
||||
|
||||
D_8037DBA4 = mlNormalizeAngle(D_8037DBA4 + analog_yaw);
|
||||
D_8037DBA8 = mlNormalizeAngle(D_8037DBA8 + analog_yaw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Updates the current yaw based on the analog camera's horizontal movement.
|
||||
// Also allows axis inversion for vanilla (non-analog) camera.
|
||||
RECOMP_PATCH int func_8029105C(s32 arg0) {
|
||||
if (func_80298850())
|
||||
return FALSE;
|
||||
|
||||
// @recomp: Allow camera axis inversion on the vanilla camera
|
||||
float axisInversionModifier = -1;
|
||||
bool inverted_x = recomp_get_third_person_inverted_x();
|
||||
if (inverted_x) {
|
||||
axisInversionModifier = 1;
|
||||
}
|
||||
|
||||
// @recomp Update the analog camera input.
|
||||
recomp_analog_camera_update();
|
||||
|
||||
// @recomp Account for axis inversion
|
||||
if (bainput_should_rotate_camera_left() && ncDynamicCamA_func_802C1DB0(-45.0f * axisInversionModifier)) {
|
||||
func_80291488(arg0);
|
||||
func_8029103C();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// @recomp Account for axis inversion
|
||||
if (bainput_should_rotate_camera_right() && ncDynamicCamA_func_802C1DB0(45.0f * axisInversionModifier)) {
|
||||
func_80291488(arg0);
|
||||
func_8029103C();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// @recomp Computes the zoom value coordinate using a 2nd order polynomial and the three
|
||||
// reference coordinate values.
|
||||
f32 zoom_value(f32 a, f32 b, f32 c) {
|
||||
// 2nd order polynomial.
|
||||
// https://math.stackexchange.com/a/680695
|
||||
const f32 x1 = 1.0f;
|
||||
const f32 x2 = 2.0f;
|
||||
const f32 x3 = 3.0f;
|
||||
f32 pa = (x1 * (c - b) + x2 * (a - c) + x3 * (b - a)) / ((x1 - x2) * (x1 - x3) * (x2 - x3));
|
||||
f32 pb = (b - a) / (x2 - x1) - pa * (x1 + x2);
|
||||
f32 pc = a - pa * x1 * x1 - pb * x1;
|
||||
f32 x = analog_zoom;
|
||||
return pa * x * x + pb * x + pc;
|
||||
}
|
||||
|
||||
// @recomp Check whether the camera is in a state that has inherited its target from a previous mode.
|
||||
bool recomp_analog_camera_r_look_inherit_mode() {
|
||||
bool swimming_state = player_getWaterState() == BSWATERGROUP_2_UNDERWATER;
|
||||
bool prev_camera_is_pole = D_8037C060 == 0x10;
|
||||
return swimming_state || prev_camera_is_pole;
|
||||
}
|
||||
|
||||
// @recomp Check whether the camera is in flight mode by checking what the previous stored camera mode is.
|
||||
bool recomp_analog_camera_r_look_flight_mode() {
|
||||
bool prev_camera_is_flying = D_8037C060 == 0x4;
|
||||
return prev_camera_is_flying;
|
||||
}
|
||||
|
||||
// @recomp Patched to return the smoothed X value of the current camera offset based on the zoom level.
|
||||
RECOMP_PATCH f32 func_802BD8D4(void) {
|
||||
if (recomp_analog_camera_enabled()) {
|
||||
bool r_look_mode = ncDynamicCamera_getState() == DYNAMIC_CAMERA_STATE_R_LOOK;
|
||||
if (r_look_mode && recomp_analog_camera_r_look_flight_mode()) {
|
||||
return D_8037DB18 + 300.0f;
|
||||
}
|
||||
else if (r_look_mode && recomp_analog_camera_r_look_inherit_mode()) {
|
||||
return analog_inherited_distance;
|
||||
}
|
||||
else {
|
||||
return zoom_value(D_8037C064, D_8037C070, D_8037C07C);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return D_8037D994;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to return the smoothed Y value of the current camera offset based on the zoom level.
|
||||
RECOMP_PATCH f32 func_802BD8E0(void) {
|
||||
if (recomp_analog_camera_enabled()) {
|
||||
return zoom_value(D_8037C068, D_8037C074, D_8037C080);
|
||||
}
|
||||
else {
|
||||
return D_8037D998;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to return the smoothed Z value of the current camera offset based on the zoom level.
|
||||
RECOMP_PATCH f32 func_802BD8C8(void) {
|
||||
if (recomp_analog_camera_enabled()) {
|
||||
return zoom_value(D_8037C06C, D_8037C078, D_8037C084);
|
||||
}
|
||||
else {
|
||||
return D_8037D99C;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to store the last retrieved camera target for the current frame.
|
||||
RECOMP_PATCH void func_802C02D4(f32 arg0[3]) {
|
||||
switch (D_8037DB40) {
|
||||
case 1:
|
||||
func_802C019C(arg0);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
func_802C01BC(arg0);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
func_802C01DC(arg0);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
func_802C0234(arg0);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
func_802C026C(arg0);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
func_802C02B4(arg0);
|
||||
break;
|
||||
}
|
||||
|
||||
// @recomp Store the camera target to be used in a future frame as well as the frame number that wrote it.
|
||||
u32 index = dynamic_camera_target_frame & 1;
|
||||
ml_vec3f_copy(dynamic_camera_targets[index], arg0);
|
||||
dynamic_camera_target_frames[index] = dynamic_camera_target_frame;
|
||||
}
|
||||
|
||||
// @recomp Patched to replace the camera target used for computing the yaw with a version that uses the previous
|
||||
// frame's camera target. The regular version of this function has a bug where the camera target is the one
|
||||
// determined by the current frame, so it is never able to compute the yaw properly by using the previous frame's
|
||||
// camera position and ends up causing a slight rotation of the resulting yaw.
|
||||
RECOMP_PATCH void func_802C069C(void) {
|
||||
f32 sp34[3];
|
||||
f32 sp28[3];
|
||||
f32 sp1C[3];
|
||||
|
||||
ncDynamicCamera_getPosition(sp34);
|
||||
|
||||
// @recomp If the camera target was written last frame and the bug fix is required, we use that value instead
|
||||
// to compute the yaw. Otherwise, use the original function.
|
||||
//func_802C02D4(sp1C);
|
||||
u32 index = (dynamic_camera_target_frame & 1) ^ 1;
|
||||
if (r_look_get_target_from_previous_frame_fix && recomp_analog_camera_enabled() && (dynamic_camera_target_frames[index] == (dynamic_camera_target_frame - 1))) {
|
||||
ml_vec3f_copy(sp1C, dynamic_camera_targets[index]);
|
||||
}
|
||||
else {
|
||||
func_802C02D4(sp1C);
|
||||
}
|
||||
|
||||
ml_vec3f_diff_copy(sp28, sp34, sp1C);
|
||||
D_8037DBA0 = gu_sqrtf(sp28[0] * sp28[0] + sp28[2] * sp28[2]);
|
||||
func_8025801C(sp28, &D_8037DBA8);
|
||||
D_8037DBAC = 0.0f;
|
||||
}
|
||||
|
||||
// @recomp Patched to skip over initialization of the target yaw based on the player's angle if analog cam is enabled.
|
||||
RECOMP_PATCH void ncDynamicCam13_init(void) {
|
||||
func_802BE230(5.0f, 8.0f);
|
||||
func_802BE244(8.0f, 15.0f);
|
||||
|
||||
// @recomp We don't change the target type in this initialization routine when the analog camera is enabled,
|
||||
// unless the the R button is currently held. We also compute the current camera distance to use it as the zoom
|
||||
// level in the case the current mode does not support camera zoom.
|
||||
// func_802C0150(6);
|
||||
if (recomp_analog_camera_enabled() && !r_look_initialized_from_r_button) {
|
||||
f32 camera_position[3];
|
||||
f32 camera_target[3];
|
||||
f32 camera_delta[3];
|
||||
ncDynamicCamera_getPosition(camera_position);
|
||||
func_802C02D4(camera_target);
|
||||
ml_vec3f_diff_copy(camera_delta, camera_position, camera_target);
|
||||
analog_inherited_distance = gu_sqrtf(camera_delta[0] * camera_delta[0] + camera_delta[2] * camera_delta[2]);
|
||||
}
|
||||
else {
|
||||
func_802C0150(6);
|
||||
}
|
||||
|
||||
// @recomp Reduce the duration of the interpolation to this mode when the analog cam is enabled. Thanks to the
|
||||
// bug fix to the target computation, this is less necessary than before.
|
||||
//func_802C2264(0.5f);
|
||||
func_802C2264(recomp_analog_camera_enabled() ? (7.0f / 30.0f) : 0.5f);
|
||||
|
||||
// @recomp Enable the global variable that controls whether the previous frame target fix is used.
|
||||
r_look_get_target_from_previous_frame_fix = TRUE;
|
||||
|
||||
func_802C069C();
|
||||
|
||||
// @recomp Clear the global variable.
|
||||
r_look_get_target_from_previous_frame_fix = FALSE;
|
||||
|
||||
// @recomp We don't update the target yaw to match the player's angle if analog camera is enabled,
|
||||
// unless the the R button is currently held.
|
||||
// func_802C095C();
|
||||
if (!recomp_analog_camera_enabled() || r_look_initialized_from_r_button) {
|
||||
func_802C095C();
|
||||
}
|
||||
else {
|
||||
D_8037DBA4 = D_8037DBA8;
|
||||
}
|
||||
|
||||
// @recomp A bug exists in the game where the velocity for both the position and rotation of the camera
|
||||
// mode is not reset when another mode that doesn't use it is initialized, carrying over the velocity
|
||||
// from the last time it was used.
|
||||
//
|
||||
// This results in visible shifting of the camera when returning from this mode to another one that uses
|
||||
// the velocity. Since it seems like a bug and not intentional behavior, we only fix this if not playing
|
||||
// pre-recorded inputs.
|
||||
//
|
||||
// This fixes large discontinuities when going back from the analog camera mode and can be reproduced in
|
||||
// vanilla by using the R button after moving for a while and standing still.
|
||||
if (!recomp_in_demo_playback_game_mode()) {
|
||||
ml_vec3f_clear(D_8037D9E0);
|
||||
ml_vec3f_clear(D_8037D9C8);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to adjust the target height of the R Look camera mode if it inherited a target mode from another camera mode.
|
||||
RECOMP_PATCH f32 func_802C0780(void) {
|
||||
// @recomp Adjust the target height of this mode based on the inherited target from a previous mode.
|
||||
// On these other modes, just use the current camera position as the target height.
|
||||
if (recomp_analog_camera_r_look_flight_mode()) {
|
||||
f32 player_pos[3];
|
||||
player_getPosition(player_pos);
|
||||
return player_pos[1] + 250.0f;
|
||||
}
|
||||
else if (recomp_analog_camera_r_look_inherit_mode()) {
|
||||
f32 camera_pos[3];
|
||||
ncDynamicCamera_getPosition(camera_pos);
|
||||
return camera_pos[1];
|
||||
}
|
||||
|
||||
return func_802BD51C();
|
||||
}
|
||||
|
||||
// @recomp Updates the current zoom level based on the analog camera's vertical movement.
|
||||
// The zoom level is a variable between 0.5 and 3.0, with 1.0 indicating the closest
|
||||
// original zoom level possible and 3.0 the furthest one. The range is lowered to 0.5
|
||||
// to allow the player to look a bit closer than normally allowed.
|
||||
RECOMP_PATCH void func_80290F14(void) {
|
||||
// @recomp Replicate the existing group of conditions to check if zoom level changes are allowed.
|
||||
// If they are, use the vertical movement to update the zoom level.
|
||||
if (recomp_analog_camera_enabled()) {
|
||||
if (!func_80298850() && player_movementGroup() != BSGROUP_4_LOOK && batimer_get(7) == 0.0f && recomp_analog_camera_allowed(FALSE)) {
|
||||
analog_zoom = ml_clamp_f(analog_zoom + recomp_analog_camera_get_y() * recomp_get_analog_cam_sensitivity() * 1.5f * time_getDelta(), 0.5f, 3.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (!func_80298850()
|
||||
&& player_movementGroup() != BSGROUP_4_LOOK
|
||||
&& batimer_get(7) == 0.0f
|
||||
&& bainput_should_zoom_out_camera()
|
||||
) {
|
||||
switch (D_8037C061) {
|
||||
case 1://L80290FA4
|
||||
basfx_80299D2C(SFX_12E_CAMERA_ZOOM_MEDIUM, 1.0f, 12000);
|
||||
func_80290B60(2);
|
||||
break;
|
||||
case 2://L80290FBC
|
||||
if (D_8037C07C) {
|
||||
basfx_80299D2C(SFX_12E_CAMERA_ZOOM_MEDIUM, 1.2f, 12000);
|
||||
func_80290B60(3);
|
||||
}
|
||||
else {
|
||||
basfx_80299D2C(SFX_12D_CAMERA_ZOOM_CLOSEST, 1.0f, 12000);
|
||||
func_80290B60(1);
|
||||
}
|
||||
break;
|
||||
case 3://L80291008
|
||||
basfx_80299D2C(SFX_12D_CAMERA_ZOOM_CLOSEST, 1.0f, 12000);
|
||||
func_80290B60(1);
|
||||
break;
|
||||
}
|
||||
batimer_set(0x7, 0.4f);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to update the analog zoom level every time the original one is modified.
|
||||
RECOMP_PATCH void func_80290B60(s32 arg0) {
|
||||
D_8037C061 = arg0;
|
||||
|
||||
// @recomp Update the analog zoom level.
|
||||
analog_zoom = (f32)arg0;
|
||||
}
|
||||
|
||||
// @recomp Patched to allow the flying camera to switch to analog look.
|
||||
RECOMP_PATCH void func_80291108(void) {
|
||||
if (!func_80290D48() && ncDynamicCamera_getState() == 0x10) {
|
||||
func_80290F14();
|
||||
func_8029105C(8);
|
||||
}
|
||||
|
||||
// @recomp Switch to the analog camera mode.
|
||||
if (!func_80290D48() && recomp_analog_camera_held(TRUE, FALSE) && ncDynamicCamera_getState() == 0x4) {
|
||||
ncDynamicCamera_setState(DYNAMIC_CAMERA_STATE_R_LOOK);
|
||||
func_80291488(0x4);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to add the target yaw initialization back on the cases where the camera state was changed when pressing the R button.
|
||||
// Also patched to switch the camera to the R look mode if the analog camera input is held.
|
||||
RECOMP_PATCH void func_80291154(void) {
|
||||
int tmp;
|
||||
if (!func_80290D48() && !func_80290E8C()) {
|
||||
if (bakey_held(BUTTON_R)) {
|
||||
// @recomp Set a global flag to indicate the camera initialization was done by pressing the R button.
|
||||
r_look_initialized_from_r_button = TRUE;
|
||||
|
||||
ncDynamicCamera_setState(0x13);
|
||||
func_80291488(0x4);
|
||||
func_80290F14();
|
||||
|
||||
// @recomp Clear the R button initialization flag.
|
||||
r_look_initialized_from_r_button = FALSE;
|
||||
}
|
||||
// @recomp Switch to the R Look mode if the analog camera input is held. Unlike the R Button input, this one will not initialize the
|
||||
// target yaw to match the player's angle, but will rather use whatever current yaw is present.
|
||||
else if (recomp_analog_camera_held(TRUE, TRUE)) {
|
||||
ncDynamicCamera_setState(DYNAMIC_CAMERA_STATE_R_LOOK);
|
||||
func_80291488(0x4);
|
||||
func_80290F14();
|
||||
}
|
||||
else {
|
||||
tmp = func_8029105C(7);
|
||||
func_80290F14();
|
||||
if (!tmp) {
|
||||
ncDynamicCamera_setState(0xB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to extend the condition of the R button in this function to consider the analog camera movement.
|
||||
RECOMP_PATCH void func_802911E0(void) {
|
||||
if (!func_80290D48() && !func_80290E8C() && !func_8029105C(7)) {
|
||||
func_80290F14();
|
||||
if (bakey_held(BUTTON_R)) {
|
||||
func_802C095C();
|
||||
}
|
||||
// @recomp Don't execute the other branch if analog camera movement is present.
|
||||
else if (recomp_analog_camera_held(TRUE, TRUE)) {
|
||||
// Do nothing.
|
||||
}
|
||||
else {
|
||||
if (func_802C0640())
|
||||
func_80291488(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to allow swimming to use the analog camera mode.
|
||||
RECOMP_PATCH int func_80290E8C(void) {
|
||||
if (player_getWaterState() != BSWATERGROUP_2_UNDERWATER) {
|
||||
// @recomp Clear the analog look flag when not underwater.
|
||||
analog_swimming_look_started = FALSE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// @recomp Check whether the analog camera is active or if it was activated.
|
||||
// Switching to a diving state will reset back to the regular camera.
|
||||
//ncDynamicCamera_setState(3);
|
||||
bool analog_camera_held = recomp_analog_camera_held(TRUE, FALSE);
|
||||
if (analog_camera_held || analog_swimming_look_started) {
|
||||
ncDynamicCamera_setState(DYNAMIC_CAMERA_STATE_R_LOOK);
|
||||
recomp_analog_camera_update();
|
||||
analog_swimming_look_started = analog_camera_held || (bs_getState() != BS_2C_DIVE_B && bs_getState() != BS_39_DIVE_A);
|
||||
}
|
||||
else {
|
||||
ncDynamicCamera_setState(3);
|
||||
}
|
||||
|
||||
func_80291488(0xB);
|
||||
|
||||
if (map_get() == MAP_B_CC_CLANKERS_CAVERN
|
||||
&& player_getYPosition() < 1201.0f
|
||||
) {
|
||||
func_802C1B20(1100.0f);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// @recomp Patched to supress right stick analog inputs on situations where the analog camera is allowed.
|
||||
RECOMP_PATCH void pfsManager_readData() {
|
||||
// @recomp Supress right stick analog input if analog camera movement is allowed. This will prevent
|
||||
// any bindings associated to the right analog stick from triggering.
|
||||
recomp_set_right_analog_suppressed(recomp_analog_camera_enabled() && recomp_analog_camera_allowed(TRUE));
|
||||
|
||||
func_8024F35C(0);
|
||||
if (!pfsManagerContStatus.errno)
|
||||
osContGetReadData(pfsManagerContPadData);
|
||||
}
|
||||
|
||||
extern f32 bastick_getX(void);
|
||||
extern f32 bastick_getY(void);
|
||||
|
||||
// @recomp Patched to allow configuring Y axis inversion when flying
|
||||
RECOMP_PATCH void func_802A3648(void){
|
||||
// @recomp Get the axis inversion setting
|
||||
s32 inverted_y = recomp_get_flying_and_swimming_inverted_y();
|
||||
|
||||
// @recomp Apply axis inversion setting
|
||||
f32 tmp_f0 = inverted_y ? bastick_getY() : -bastick_getY();
|
||||
|
||||
if(tmp_f0 < 0.0f)
|
||||
pitch_setIdeal(ml_map_f(tmp_f0, -1.0f, 0.0f, 300.0f, 360.0f));
|
||||
else
|
||||
pitch_setIdeal(ml_map_f(tmp_f0, 0.0f, 1.0f, 0.0f, 80.0f));
|
||||
}
|
||||
|
||||
// @recomp Patched to allow configuring X axis inversion when flying
|
||||
RECOMP_PATCH void func_802A354C(void){
|
||||
f32 yaw_range;
|
||||
f32 roll_range;
|
||||
f32 sp2C;
|
||||
|
||||
// @recomp Get the axis inversion setting
|
||||
s32 inverted_x = recomp_get_flying_and_swimming_inverted_x();
|
||||
|
||||
// @recomp Apply axis inversion setting
|
||||
sp2C = inverted_x ? -bastick_getX() : bastick_getX();
|
||||
if(bakey_held(BUTTON_R)){
|
||||
yaw_setVelocityBounded(500.0f, 30.0f);
|
||||
yaw_range = 6.0f;
|
||||
roll_range = 85.0f;
|
||||
}
|
||||
else{
|
||||
yaw_setVelocityBounded(500.0f, 2.0f);
|
||||
yaw_range = 3.0f;
|
||||
roll_range = 75.0f;
|
||||
}
|
||||
roll_setIdeal(ml_map_f(sp2C, -1.0f, 1.0f, -roll_range, roll_range));
|
||||
yaw_setIdeal(mlNormalizeAngle(yaw_getIdeal() + ml_map_f(sp2C, -1.0f, 1.0f, yaw_range, -yaw_range)));
|
||||
}
|
||||
|
||||
// @recomp Patched to allow configuring Y axis inversion when swimming
|
||||
f32 func_802A716C();
|
||||
RECOMP_PATCH void func_802A7304() {
|
||||
f32 temp_f0;
|
||||
|
||||
// @recomp Get the axis inversion setting
|
||||
s32 inverted_y = recomp_get_flying_and_swimming_inverted_y();
|
||||
|
||||
pitch_setAngVel(ml_interpolate_f(func_802A716C(), 70.0f, 30.0f), 0.9f);
|
||||
|
||||
// @recomp Apply axis inversion setting
|
||||
temp_f0 = inverted_y ? bastick_getY() : -bastick_getY();
|
||||
if (temp_f0 < 0.0f) {
|
||||
pitch_setIdeal(ml_map_f(temp_f0, -1.0f, 0.0f, 275.0f, 360.0f));
|
||||
return;
|
||||
}
|
||||
pitch_setIdeal(ml_map_f(temp_f0, 0.0f, 1.0f, 0.0f, 85.0f));
|
||||
}
|
||||
|
||||
// @recomp Patched to allow configuring X axis inversion when swimming
|
||||
RECOMP_PATCH void func_802A71D8(void) {
|
||||
f32 yaw_range;
|
||||
f32 sp38;
|
||||
f32 roll_range;
|
||||
f32 sp30;
|
||||
|
||||
// @recomp Get the axis inversion setting
|
||||
s32 inverted_x = recomp_get_flying_and_swimming_inverted_x();
|
||||
|
||||
// @recomp Apply axis inversion setting
|
||||
sp30 = inverted_x ? -bastick_getX() : bastick_getX();
|
||||
sp38 = func_802A716C();
|
||||
if (bakey_held(BUTTON_R)) {
|
||||
roll_range = 45.0f;
|
||||
yaw_range = 4.3f;
|
||||
yaw_setVelocityBounded(250.0f, 20.0f);
|
||||
} else {
|
||||
roll_range = 35.0f;
|
||||
yaw_range = ml_interpolate_f(sp38, 3.1f, 2.4f);
|
||||
yaw_setVelocityBounded(90.0f, ml_interpolate_f(sp38, 3.8f, 2.2f));
|
||||
}
|
||||
roll_setIdeal(ml_map_f(sp30, -1.0f, 1.0f, -roll_range, roll_range));
|
||||
yaw_setIdeal(mlNormalizeAngle(yaw_getIdeal() + ml_map_f(sp30, -1.0f, 1.0f, yaw_range, -yaw_range)));
|
||||
}
|
||||
|
||||
extern s32 ncFirstPersonCamera_getState(void);
|
||||
extern void ncFirstPersonCamera_getZoomedInRotation(f32 *);
|
||||
extern void ncFirstPersonCamera_setZoomedOutRotation(f32 src[3]);
|
||||
extern bool func_8028B254(s32 arg0);
|
||||
extern void __bsDroneLook_getEyePos(f32 arg0[3]);
|
||||
extern enum bs_e func_8029BDBC(void);
|
||||
extern void ncFirstPersonCamera_setZoomedOutPosition(f32 src[3]);
|
||||
|
||||
// @recomp: Patched to allow inverting the first person camera
|
||||
RECOMP_PATCH void bsDroneLook_update(void) {
|
||||
s32 next_state;
|
||||
f32 eye_rotation[3];
|
||||
f32 eye_position[3];
|
||||
f32 dt;
|
||||
s32 exit_first_person;
|
||||
|
||||
// @recomp: Get the axis inversion setting
|
||||
s32 inverted_x = recomp_get_first_person_inverted_x();
|
||||
s32 inverted_y = recomp_get_first_person_inverted_y();
|
||||
float x = inverted_x ? -bastick_getX() : bastick_getX();
|
||||
float y = inverted_y ? bastick_getY() : -bastick_getY();
|
||||
|
||||
next_state = 0;
|
||||
dt = time_getDelta();
|
||||
if (ncFirstPersonCamera_getState() == FIRSTPERSON_STATE_2_IDLE) {
|
||||
//camera is in "idle" state
|
||||
ncFirstPersonCamera_getZoomedInRotation(eye_rotation);
|
||||
// @recomp: Apply the axis inversion setting
|
||||
eye_rotation[0] -= y * 90.0f * dt;
|
||||
eye_rotation[1] -= x * 90.0f * dt;
|
||||
eye_rotation[2] = 0.0f;
|
||||
eye_rotation[0] = (eye_rotation[0] > 180.0f) ? ml_max_f(305.0f, eye_rotation[0]) : ml_min_f(70.0f, eye_rotation[0]);
|
||||
ncFirstPersonCamera_setZoomedOutRotation(eye_rotation);
|
||||
yaw_setIdeal(eye_rotation[1] + 180.0f);
|
||||
|
||||
exit_first_person = FALSE;
|
||||
// 1st person cancelled via input
|
||||
if (bakey_pressed(BUTTON_B) || bakey_pressed(BUTTON_A) || bakey_pressed(BUTTON_C_UP)) {
|
||||
exit_first_person = TRUE;
|
||||
}
|
||||
// 1st person cancelled via entering water
|
||||
if (player_inWater()) {
|
||||
if (player_getTransformation() == TRANSFORM_1_BANJO && player_getWaterState() == BSWATERGROUP_0_NONE) {
|
||||
exit_first_person += TRUE;
|
||||
}
|
||||
} else if (func_8028B254(25) == 0) {
|
||||
exit_first_person += TRUE;
|
||||
}
|
||||
if (exit_first_person) {
|
||||
next_state = func_8029BDBC();
|
||||
}
|
||||
}
|
||||
__bsDroneLook_getEyePos(eye_position);
|
||||
ncFirstPersonCamera_setZoomedOutPosition(eye_position);
|
||||
bs_setState(next_state);
|
||||
}
|
||||
@@ -1,270 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "core1/core1.h"
|
||||
#include "core2/nc/camera.h"
|
||||
|
||||
s32 cur_perspective_projection_transform_id = 0;
|
||||
s32 backup_perspective_projection_transform_id = 0;
|
||||
|
||||
s32 cur_ortho_projection_transform_id = 0;
|
||||
s32 backup_ortho_projection_transform_id = 0;
|
||||
|
||||
void reset_projection_ids() {
|
||||
cur_perspective_projection_transform_id = 0;
|
||||
cur_ortho_projection_transform_id = 0;
|
||||
}
|
||||
|
||||
bool skip_perspective_interpolation = FALSE;
|
||||
|
||||
bool perspective_interpolation_skipped() {
|
||||
return skip_perspective_interpolation;
|
||||
}
|
||||
|
||||
s32 getGameMode(void);
|
||||
|
||||
extern f32 sViewportFOVy;
|
||||
extern f32 sViewportAspect;
|
||||
extern f32 sViewportNear;
|
||||
extern f32 sViewportFar;
|
||||
extern f32 sViewportLookVector[3];
|
||||
extern f32 sViewportPosition[3];
|
||||
extern f32 sViewportRotation[3];
|
||||
extern Vp sViewportStack[];
|
||||
extern MtxF sViewportMatrix;
|
||||
extern s32 sViewportStackIndex;
|
||||
|
||||
extern f32 sViewportBackupPosition[3];
|
||||
extern f32 sViewportBackupRotation[3];
|
||||
extern f32 sViewportBackupFrustumPlanes[4][4];
|
||||
extern f32 sViewportBackupLookVector[3];
|
||||
extern MtxF sViewportBackupMatrix;
|
||||
|
||||
// @recomp Patched to specify the view matrix for better transform interpolation and set up a matrix group for the new projection.
|
||||
RECOMP_PATCH void viewport_setRenderPerspectiveMatrix(Gfx **gfx, Mtx **mtx, f32 near, f32 far) {
|
||||
u16 perspNorm;
|
||||
|
||||
near = MAX(sViewportNear, near);
|
||||
far = MIN(sViewportFar, far);
|
||||
|
||||
if(*(u32*)OS_PHYSICAL_TO_K0(0x1D8) + 0x53D4FFF0) {
|
||||
near = 750.0f;
|
||||
far = 1250.0f;
|
||||
}
|
||||
|
||||
guPerspective(*mtx, &perspNorm, sViewportFOVy, sViewportAspect, near, far, 0.5f);
|
||||
gSPPerspNormalize((*gfx)++, perspNorm);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
||||
|
||||
guRotate(*mtx, -sViewportRotation[2], 0.0f, 0.0f, -1.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
||||
|
||||
guRotate(*mtx, -sViewportRotation[0], 1.0f, 0.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
||||
|
||||
guRotate(*mtx, -sViewportRotation[1], 0.0f, 1.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
||||
|
||||
guTranslate(*mtx, 0.0f, 0.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_PHYSICAL_TO_K0((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Create an isolated view matrix for the viewport translation and provide it as the view matrix to counteract the camera translation.
|
||||
MtxF* view = (MtxF*)*mtx;
|
||||
(*mtx)++;
|
||||
if (cur_perspective_projection_transform_id == PROJECTION_GAMEPLAY_TRANSFORM_ID) {
|
||||
guTranslateF(view->m, sViewportPosition[0], sViewportPosition[1], sViewportPosition[2]);
|
||||
}
|
||||
else {
|
||||
guMtxIdentF(view->m);
|
||||
}
|
||||
|
||||
gEXSetViewMatrixFloat((*gfx)++, view->m);
|
||||
|
||||
// @recomp If a perspective projection transform ID is set, apply it as the projection matrix group. Otherwise, use auto as the projection matrix group.
|
||||
bool skip_interpolation = all_interpolation_skipped() || perspective_interpolation_skipped();
|
||||
if (cur_perspective_projection_transform_id != 0) {
|
||||
// Force the projection to not adjust itself for a wider aspect ratio when it's being rendered for the Bottles' bonus puzzle or the Mumbo photo.
|
||||
u16 aspect = G_EX_ASPECT_AUTO;
|
||||
bool inPictureGameMode = (getGameMode() == GAME_MODE_8_BOTTLES_BONUS) || (getGameMode() == GAME_MODE_A_SNS_PICTURE);
|
||||
bool isGameplayTransformId = (cur_perspective_projection_transform_id == PROJECTION_GAMEPLAY_TRANSFORM_ID);
|
||||
bool isTransitionTransformId = (cur_perspective_projection_transform_id == PROJECTION_TRANSITION_TRANSFORM_ID);
|
||||
if (inPictureGameMode && (isGameplayTransformId || isTransitionTransformId)) {
|
||||
aspect = G_EX_ASPECT_STRETCH;
|
||||
}
|
||||
if (skip_interpolation) {
|
||||
gEXMatrixGroupSkipAllAspect((*gfx)++, cur_perspective_projection_transform_id, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE, aspect);
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroup((*gfx)++, cur_perspective_projection_transform_id, G_EX_INTERPOLATE_SIMPLE, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, G_EX_EDIT_NONE, aspect, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_AUTO);
|
||||
}
|
||||
}
|
||||
else if (skip_interpolation) {
|
||||
gEXMatrixGroupNoInterpolate((*gfx)++, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, G_EX_ID_AUTO, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
float identity_matrix[4][4] = {
|
||||
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 1.0f }
|
||||
};
|
||||
|
||||
// @recomp Patched to set up an identity view matrix to prevent bleeding the perspective projection's view matrix.
|
||||
RECOMP_PATCH void viewport_setRenderViewportAndOrthoMatrix(Gfx **gfx, Mtx **mtx) {
|
||||
gSPViewport((*gfx)++, &sViewportStack[sViewportStackIndex]);
|
||||
|
||||
// @recomp Use a high precision version of the projection matrix instead of the fixed precision one. This fixes accuracy issues when rendering text using the orthographic projection.
|
||||
guOrthoF(*mtx, -(2 * (f32)gFramebufferWidth), (2 * (f32)gFramebufferWidth), -(2 * (f32)gFramebufferHeight), (2 * (f32)gFramebufferHeight), 1.0f, 20.0f, 1.0f);
|
||||
gEXMatrixFloat((*gfx)++, OS_K0_TO_PHYSICAL((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
||||
|
||||
#if 0
|
||||
guOrtho(*mtx, -(2*(f32)gFramebufferWidth), (2*(f32)gFramebufferWidth), -(2*(f32)gFramebufferHeight), (2*(f32)gFramebufferHeight), 1.0f, 20.0f, 1.0f);
|
||||
gSPMatrix((*gfx)++, OS_K0_TO_PHYSICAL((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
||||
#endif
|
||||
|
||||
guTranslate(*mtx, 0.0f, 0.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_K0_TO_PHYSICAL((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Set an identity view matrix.
|
||||
gEXSetViewMatrixFloat((*gfx)++, identity_matrix);
|
||||
|
||||
// @recomp If an ortho projection transform ID is set, apply it as the projection matrix group. Otherwise, use auto as the projection matrix group.
|
||||
if (cur_ortho_projection_transform_id != 0) {
|
||||
if (all_interpolation_skipped()) {
|
||||
gEXMatrixGroupSkipAll((*gfx)++, cur_ortho_projection_transform_id, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, cur_ortho_projection_transform_id, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
}
|
||||
else if (all_interpolation_skipped()) {
|
||||
gEXMatrixGroupNoInterpolate((*gfx)++, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, G_EX_ID_AUTO, G_EX_NOPUSH, G_MTX_PROJECTION, G_EX_EDIT_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to also back up the projection matrix transform ID and reset the current one.
|
||||
RECOMP_PATCH void viewport_backupState(void) {
|
||||
s32 i, j;
|
||||
|
||||
viewport_getPosition_vec3f(sViewportBackupPosition);
|
||||
viewport_getRotation_vec3f(sViewportBackupRotation);
|
||||
viewport_getFrustumPlanes(sViewportBackupFrustumPlanes[0], sViewportBackupFrustumPlanes[1], sViewportBackupFrustumPlanes[2], sViewportBackupFrustumPlanes[3]);
|
||||
viewport_getLookVector(sViewportBackupLookVector);
|
||||
|
||||
for(i = 0; i < 4; i++){
|
||||
for(j = 0; j < 4; j++){
|
||||
sViewportBackupMatrix.m[i][j] = sViewportMatrix.m[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Back up the projection transform IDs and reset them.
|
||||
backup_perspective_projection_transform_id = cur_perspective_projection_transform_id;
|
||||
cur_perspective_projection_transform_id = 0;
|
||||
backup_ortho_projection_transform_id = cur_ortho_projection_transform_id;
|
||||
cur_ortho_projection_transform_id = 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to also restore the backed up projection matrix transform ID.
|
||||
RECOMP_PATCH void viewport_restoreState(void) {
|
||||
s32 i, j;
|
||||
|
||||
viewport_setPosition_vec3f(sViewportBackupPosition);
|
||||
viewport_setRotation_vec3f(sViewportBackupRotation);
|
||||
viewport_setFrustumPlanes(sViewportBackupFrustumPlanes[0], sViewportBackupFrustumPlanes[1], sViewportBackupFrustumPlanes[2], sViewportBackupFrustumPlanes[3]);
|
||||
ml_vec3f_copy(sViewportLookVector, sViewportBackupLookVector);
|
||||
|
||||
for(i = 0; i < 4; i++){
|
||||
for(j = 0; j < 4; j++){
|
||||
sViewportMatrix.m[i][j] = sViewportBackupMatrix.m[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Restore the backed up projection transform IDs.
|
||||
cur_perspective_projection_transform_id = backup_perspective_projection_transform_id;
|
||||
cur_ortho_projection_transform_id = backup_ortho_projection_transform_id;
|
||||
}
|
||||
|
||||
extern s32 ncCameraType;
|
||||
extern u8 D_8037D8C5;
|
||||
extern u8 D_8037D8C6;
|
||||
void ncDynamicCamera_update(void);
|
||||
void ncStaticCamera_update(void);
|
||||
void ncRandomCamera_update(void);
|
||||
void func_802BB4D8(f32 position[3], f32 rotation[3]);
|
||||
void func_802BEFB0(void);
|
||||
void func_802BBA84(void);
|
||||
|
||||
// @recomp Patched to detect camera type changes or sudden camera movements and skip perspective interpolation when they happen.
|
||||
RECOMP_PATCH void ncCamera_update(void) {
|
||||
f32 vpPos[3];
|
||||
f32 vpRot[3];
|
||||
s32 camType;
|
||||
|
||||
camType = ncCameraType;
|
||||
if (!D_8037D8C5 && !D_8037D8C6) {
|
||||
camType = 0;
|
||||
}
|
||||
|
||||
switch (camType) {
|
||||
case CAMERA_TYPE_2_DYNAMIC://dynamic viewport position
|
||||
ncDynamicCamera_update();
|
||||
break;
|
||||
case CAMERA_TYPE_3_STATIC://set viewport to static location
|
||||
ncStaticCamera_update();
|
||||
break;
|
||||
case CAMERA_TYPE_4_RANDOM: //set viewport to random location
|
||||
ncRandomCamera_update();
|
||||
break;
|
||||
}
|
||||
|
||||
viewport_getPosition_vec3f(vpPos);
|
||||
viewport_getRotation_vec3f(vpRot);
|
||||
func_802BB4D8(vpPos, vpRot);
|
||||
viewport_setPosition_vec3f(vpPos);
|
||||
viewport_setRotation_vec3f(vpRot);
|
||||
|
||||
// @recomp Detect camera type changes or sudden camera movements.
|
||||
static s32 camTypePrev = 0;
|
||||
static f32 vpPosPrev[3] = {};
|
||||
static f32 vpPosVel[3] = {};
|
||||
f32 vpPosDelta[3];
|
||||
ml_vec3f_diff_copy(vpPosDelta, vpPos, vpPosPrev);
|
||||
if (camType != camTypePrev) {
|
||||
// Always skip perspective interpolation on camera type changes.
|
||||
skip_perspective_interpolation = TRUE;
|
||||
}
|
||||
else if (camType == CAMERA_TYPE_2_DYNAMIC) {
|
||||
// Never skip interpolation during controllable gameplay.
|
||||
skip_perspective_interpolation = FALSE;
|
||||
}
|
||||
else {
|
||||
// Check for sudden position differences. They must be within an arbitrary threshold o
|
||||
// the projected position from using the previous frame's velocity.
|
||||
f32 vpPosProjected[3];
|
||||
ml_vec3f_add(vpPosProjected, vpPosPrev, vpPosVel);
|
||||
|
||||
f32 distToProjected = ml_vec3f_distance(vpPos, vpPosProjected);
|
||||
const f32 SkipThreshold = 100.0f;
|
||||
if (distToProjected > SkipThreshold) {
|
||||
ml_vec3f_clear(vpPosVel);
|
||||
skip_perspective_interpolation = TRUE;
|
||||
}
|
||||
else {
|
||||
ml_vec3f_copy(vpPosVel, vpPosDelta);
|
||||
skip_perspective_interpolation = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
camTypePrev = camType;
|
||||
ml_vec3f_copy(vpPosPrev, vpPos);
|
||||
|
||||
viewport_update();
|
||||
func_802BEFB0();
|
||||
func_802BBA84();
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
|
||||
int overlayManagergetLoadedId(void);
|
||||
|
||||
extern struct {
|
||||
u8 unk0;
|
||||
u8 unk1;
|
||||
u8 pad2[2];
|
||||
void (*init)(void);
|
||||
void (*update)(void);
|
||||
void (*release)(void);
|
||||
void (*draw)(Gfx **, Mtx **, Vtx **);
|
||||
void (*unk14)(s32, s32);
|
||||
} sOverlay;
|
||||
|
||||
void recomp_setup_overlay_skinning(int overlay_id);
|
||||
void recomp_clear_overlay_skinning();
|
||||
|
||||
// @recomp: Patched to assign an ID to Clanker.
|
||||
RECOMP_PATCH void func_80322E64(Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
// @recomp If the current level is Clanker's Cavern, set up the model ID for Clanker.
|
||||
u32 prev_transform_id = cur_drawn_model_transform_id;
|
||||
if (overlayManagergetLoadedId() == OVERLAY_2_WHALE) {
|
||||
cur_drawn_model_transform_id = CLANKER_TRANSFORM_ID_START;
|
||||
}
|
||||
|
||||
// @recomp Setup the overlay skinning data.
|
||||
recomp_setup_overlay_skinning(overlayManagergetLoadedId());
|
||||
|
||||
if(sOverlay.draw)
|
||||
sOverlay.draw(gfx, mtx, vtx);
|
||||
|
||||
// @recomp Clear the overlay skinning setup.
|
||||
recomp_clear_overlay_skinning();
|
||||
|
||||
// @recomp Reset the current transform ID.
|
||||
cur_drawn_model_transform_id = prev_transform_id;
|
||||
}
|
||||
@@ -1,220 +1,5 @@
|
||||
#include "patches.h"
|
||||
#include "core1/ml.h"
|
||||
#include "core1/mlmtx.h"
|
||||
#include "core1/core1.h"
|
||||
#include "core1/vimgr.h"
|
||||
#include "functions.h"
|
||||
|
||||
extern f32 sViewportPosition[3];
|
||||
extern f32 sViewportFrustumPlanes[4][4];
|
||||
void animMtxList_setBoned(AnimMtxList **this_ptr, BKAnimationList *anim_list, BoneTransformList *arg2);
|
||||
|
||||
extern s32 cur_model_would_have_been_culled_in_demo;
|
||||
bool recomp_in_demo_playback_game_mode();
|
||||
void recomp_setup_marker_skinning(ActorMarker *marker);
|
||||
|
||||
int frustum_checks_enabled = TRUE;
|
||||
void set_frustum_checks_enabled(int enabled) {
|
||||
frustum_checks_enabled = enabled;
|
||||
}
|
||||
|
||||
// Unpatched copy of viewport_isBoundingBoxInFrustum, used to check if a cube would have been culled originally.
|
||||
bool viewport_isBoundingBoxInFrustumCopy(f32 min[3], f32 max[3]) {
|
||||
if (((sViewportFrustumPlanes[0][0] * min[0] + sViewportFrustumPlanes[0][1] * min[1] + sViewportFrustumPlanes[0][2] * min[2] + sViewportFrustumPlanes[0][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[0][0] * min[0] + sViewportFrustumPlanes[0][1] * min[1] + sViewportFrustumPlanes[0][2] * max[2] + sViewportFrustumPlanes[0][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[0][0] * min[0] + sViewportFrustumPlanes[0][1] * max[1] + sViewportFrustumPlanes[0][2] * min[2] + sViewportFrustumPlanes[0][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[0][0] * min[0] + sViewportFrustumPlanes[0][1] * max[1] + sViewportFrustumPlanes[0][2] * max[2] + sViewportFrustumPlanes[0][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[0][0] * max[0] + sViewportFrustumPlanes[0][1] * min[1] + sViewportFrustumPlanes[0][2] * min[2] + sViewportFrustumPlanes[0][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[0][0] * max[0] + sViewportFrustumPlanes[0][1] * min[1] + sViewportFrustumPlanes[0][2] * max[2] + sViewportFrustumPlanes[0][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[0][0] * max[0] + sViewportFrustumPlanes[0][1] * max[1] + sViewportFrustumPlanes[0][2] * min[2] + sViewportFrustumPlanes[0][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[0][0] * max[0] + sViewportFrustumPlanes[0][1] * max[1] + sViewportFrustumPlanes[0][2] * max[2] + sViewportFrustumPlanes[0][3]) >= 0.0f))
|
||||
return FALSE;
|
||||
|
||||
if (((sViewportFrustumPlanes[1][0] * min[0] + sViewportFrustumPlanes[1][1] * min[1] + sViewportFrustumPlanes[1][2] * min[2] + sViewportFrustumPlanes[1][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[1][0] * min[0] + sViewportFrustumPlanes[1][1] * min[1] + sViewportFrustumPlanes[1][2] * max[2] + sViewportFrustumPlanes[1][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[1][0] * min[0] + sViewportFrustumPlanes[1][1] * max[1] + sViewportFrustumPlanes[1][2] * min[2] + sViewportFrustumPlanes[1][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[1][0] * min[0] + sViewportFrustumPlanes[1][1] * max[1] + sViewportFrustumPlanes[1][2] * max[2] + sViewportFrustumPlanes[1][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[1][0] * max[0] + sViewportFrustumPlanes[1][1] * min[1] + sViewportFrustumPlanes[1][2] * min[2] + sViewportFrustumPlanes[1][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[1][0] * max[0] + sViewportFrustumPlanes[1][1] * min[1] + sViewportFrustumPlanes[1][2] * max[2] + sViewportFrustumPlanes[1][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[1][0] * max[0] + sViewportFrustumPlanes[1][1] * max[1] + sViewportFrustumPlanes[1][2] * min[2] + sViewportFrustumPlanes[1][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[1][0] * max[0] + sViewportFrustumPlanes[1][1] * max[1] + sViewportFrustumPlanes[1][2] * max[2] + sViewportFrustumPlanes[1][3]) >= 0.0f))
|
||||
return FALSE;
|
||||
|
||||
if (((sViewportFrustumPlanes[2][0] * min[0] + sViewportFrustumPlanes[2][1] * min[1] + sViewportFrustumPlanes[2][2] * min[2] + sViewportFrustumPlanes[2][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[2][0] * min[0] + sViewportFrustumPlanes[2][1] * min[1] + sViewportFrustumPlanes[2][2] * max[2] + sViewportFrustumPlanes[2][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[2][0] * min[0] + sViewportFrustumPlanes[2][1] * max[1] + sViewportFrustumPlanes[2][2] * min[2] + sViewportFrustumPlanes[2][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[2][0] * min[0] + sViewportFrustumPlanes[2][1] * max[1] + sViewportFrustumPlanes[2][2] * max[2] + sViewportFrustumPlanes[2][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[2][0] * max[0] + sViewportFrustumPlanes[2][1] * min[1] + sViewportFrustumPlanes[2][2] * min[2] + sViewportFrustumPlanes[2][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[2][0] * max[0] + sViewportFrustumPlanes[2][1] * min[1] + sViewportFrustumPlanes[2][2] * max[2] + sViewportFrustumPlanes[2][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[2][0] * max[0] + sViewportFrustumPlanes[2][1] * max[1] + sViewportFrustumPlanes[2][2] * min[2] + sViewportFrustumPlanes[2][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[2][0] * max[0] + sViewportFrustumPlanes[2][1] * max[1] + sViewportFrustumPlanes[2][2] * max[2] + sViewportFrustumPlanes[2][3]) >= 0.0f))
|
||||
return FALSE;
|
||||
|
||||
if (((sViewportFrustumPlanes[3][0] * min[0] + sViewportFrustumPlanes[3][1] * min[1] + sViewportFrustumPlanes[3][2] * min[2] + sViewportFrustumPlanes[3][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[3][0] * min[0] + sViewportFrustumPlanes[3][1] * min[1] + sViewportFrustumPlanes[3][2] * max[2] + sViewportFrustumPlanes[3][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[3][0] * min[0] + sViewportFrustumPlanes[3][1] * max[1] + sViewportFrustumPlanes[3][2] * min[2] + sViewportFrustumPlanes[3][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[3][0] * min[0] + sViewportFrustumPlanes[3][1] * max[1] + sViewportFrustumPlanes[3][2] * max[2] + sViewportFrustumPlanes[3][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[3][0] * max[0] + sViewportFrustumPlanes[3][1] * min[1] + sViewportFrustumPlanes[3][2] * min[2] + sViewportFrustumPlanes[3][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[3][0] * max[0] + sViewportFrustumPlanes[3][1] * min[1] + sViewportFrustumPlanes[3][2] * max[2] + sViewportFrustumPlanes[3][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[3][0] * max[0] + sViewportFrustumPlanes[3][1] * max[1] + sViewportFrustumPlanes[3][2] * min[2] + sViewportFrustumPlanes[3][3]) >= 0.0f) &&
|
||||
((sViewportFrustumPlanes[3][0] * max[0] + sViewportFrustumPlanes[3][1] * max[1] + sViewportFrustumPlanes[3][2] * max[2] + sViewportFrustumPlanes[3][3]) >= 0.0f))
|
||||
return FALSE;
|
||||
|
||||
RECOMP_PATCH bool viewport_isBoundingBoxInFrustum(f32 arg0[3], f32 arg1[3]) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
s32 cmd_0;
|
||||
s32 size_4;
|
||||
s16 unk8[3];
|
||||
s16 unkE[3];
|
||||
s16 unk14;
|
||||
}GeoCmdD;
|
||||
|
||||
void func_80339124(Gfx **, Mtx **, BKGeoList *);
|
||||
|
||||
// @recomp Patched to disable culling in model rendering.
|
||||
RECOMP_PATCH void func_80338DCC(Gfx ** gfx, Mtx ** mtx, void *arg2){
|
||||
f32 sp2C[3];
|
||||
f32 sp20[3];
|
||||
GeoCmdD * cmd = (GeoCmdD *)arg2;
|
||||
if(cmd->unk14){
|
||||
// @recomp Always run the child command.
|
||||
// sp2C[0] = (f32)cmd->unk8[0] * modelRenderScale;
|
||||
// sp2C[1] = (f32)cmd->unk8[1] * modelRenderScale;
|
||||
// sp2C[2] = (f32)cmd->unk8[2] * modelRenderScale;
|
||||
|
||||
// sp20[0] = (f32)cmd->unkE[0] * modelRenderScale;
|
||||
// sp20[1] = (f32)cmd->unkE[1] * modelRenderScale;
|
||||
// sp20[2] = (f32)cmd->unkE[2] * modelRenderScale;
|
||||
if(TRUE){//viewport_isBoundingBoxInFrustum(sp2C, sp20)){
|
||||
func_80339124(gfx, mtx, (BKGeoList*)((s32)cmd + cmd->unk14));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to disable frustum culling.
|
||||
RECOMP_PATCH bool viewport_isBoundingBoxInFrustum(f32 min[3], f32 max[3]) {
|
||||
// @recomp Disable frustum culling for cubes outside of demos. Demos need to maintain the original
|
||||
// culling for cubes to prevent them from behaving differently than the original game.
|
||||
if (recomp_in_demo_playback_game_mode()) {
|
||||
return viewport_isBoundingBoxInFrustumCopy(min, max);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// @recomp Patched to allow globally disabling frustum checks.
|
||||
RECOMP_PATCH bool viewport_func_8024DB50(f32 pos[3], f32 distance) {
|
||||
// @recomp Return true if frustum checks are disabled (always pass the frustum check).
|
||||
if (!frustum_checks_enabled) {
|
||||
return TRUE;
|
||||
}
|
||||
f32 delta[3];
|
||||
s32 i;
|
||||
|
||||
delta[0] = pos[0] - sViewportPosition[0];
|
||||
delta[1] = pos[1] - sViewportPosition[1];
|
||||
delta[2] = pos[2] - sViewportPosition[2];
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
if(distance <= ml_vec3f_dot_product(delta, sViewportFrustumPlanes[i])) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// @recomp Patched to use the frustum culling result to set the marker's field.
|
||||
// This is only enabled during demos, and is needed so that demos play back correctly.
|
||||
RECOMP_PATCH void actor_postdrawMethod(ActorMarker *marker){
|
||||
if (!cur_model_would_have_been_culled_in_demo) {
|
||||
marker->unk14_21 = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
extern struct5Bs *D_8036E568;
|
||||
bool func_80330534(Actor *actor);
|
||||
bool func_8033056C(Actor *actor);
|
||||
void anim_802897D4(AnimMtxList *this, BKAnimationList *arg0, Animation *dst);
|
||||
void modelRender_setBoneTransformList(s32);
|
||||
void modelRender_setAnimatedTexturesCacheId(s32 arg0);
|
||||
s32 actor_getAnimatedTexturesCacheId(Actor *actor);
|
||||
|
||||
// @recomp Patched to not call the actor's callback if the actor's model would have been culled.
|
||||
// This is only enabled during demos, and is needed so that demos play back correctly.
|
||||
RECOMP_PATCH void actor_predrawMethod(Actor *this){
|
||||
s32 pad4C;
|
||||
BKModelBin *sp48;
|
||||
bool sp44;
|
||||
BKVertexList *sp40;
|
||||
f32 sp34[3];
|
||||
|
||||
sp48 = marker_loadModelBin(this->marker);
|
||||
func_80330534(this);
|
||||
if(this->anctrl != NULL){
|
||||
anctrl_drawSetup(this->anctrl, this->position, 1);
|
||||
}
|
||||
|
||||
if(this->marker->unk20 != NULL){
|
||||
sp44 = FALSE;
|
||||
if(this->unk148 != NULL){
|
||||
animMtxList_setBoned(&this->marker->unk20, model_getAnimationList(sp48), skeletalAnim_getBoneTransformList(this->unk148));
|
||||
sp44 = TRUE;
|
||||
}//L8032542C
|
||||
else if(this->anctrl != NULL && model_getAnimationList(sp48)){
|
||||
anim_802897D4(&this->marker->unk20, model_getAnimationList(sp48), anctrl_getAnimPtr(this->anctrl));
|
||||
sp44 = TRUE;
|
||||
}//L80325474
|
||||
|
||||
if(sp44){
|
||||
func_8033A444((AnimMtxList*)this->marker->unk20);
|
||||
}
|
||||
}//L8032548C
|
||||
|
||||
if(this->alpha_124_19 < 0xFF){
|
||||
modelRender_setAlpha(this->alpha_124_19);
|
||||
}
|
||||
|
||||
modelRender_setDepthMode(this->depth_mode);
|
||||
if(this->marker->unk44 != 0){
|
||||
if((s32)this->marker->unk44 == 1){
|
||||
func_8033A450(D_8036E568);
|
||||
}
|
||||
else{
|
||||
func_8033A450(this->marker->unk44);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Set up skinning data for this actor.
|
||||
recomp_setup_marker_skinning(this->marker);
|
||||
|
||||
if(this->unkF4_30){
|
||||
sp40 = func_80330C74(this);
|
||||
if(this->unk138_29){
|
||||
sp34[0] = this->pitch;
|
||||
sp34[1] = this->yaw;
|
||||
sp34[2] = this->roll;
|
||||
codeAC520_func_80333D48(sp40, this->position, sp34, this->scale, 0, model_getVtxList(sp48));
|
||||
}//L80325560
|
||||
modelRender_setVertexList(sp40);
|
||||
this->unkF4_29 = NOT(this->unkF4_29);
|
||||
}//L80325594
|
||||
|
||||
// @recomp Only call the actor's callback if the model wouldn't have been frustum culled.
|
||||
// This only has an effect during demos, as the in frustum flag always set to true outside of demos.
|
||||
if (!cur_model_would_have_been_culled_in_demo) {
|
||||
if(this->unk130){
|
||||
this->unk130(this);
|
||||
}
|
||||
}
|
||||
|
||||
if(this->unk148 && !this->marker->unk20){
|
||||
modelRender_setBoneTransformList((s32)skeletalAnim_getBoneTransformList(this->unk148));
|
||||
}
|
||||
|
||||
func_8033056C(this);
|
||||
modelRender_setAnimatedTexturesCacheId(actor_getAnimatedTexturesCacheId(this));
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#include "patches.h"
|
||||
|
||||
extern s32 getGameMode(void);
|
||||
|
||||
// @recomp Check whether the game is currently on a mode that uses demo playback instead of the player's inputs.
|
||||
bool recomp_in_demo_playback_game_mode() {
|
||||
switch (getGameMode()) {
|
||||
case GAME_MODE_2_UNKNOWN:
|
||||
case GAME_MODE_6_FILE_PLAYBACK:
|
||||
case GAME_MODE_7_ATTRACT_DEMO:
|
||||
case GAME_MODE_8_BOTTLES_BONUS:
|
||||
case GAME_MODE_A_SNS_PICTURE:
|
||||
case GAME_MODE_9_BANJO_AND_KAZOOIE:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -1,257 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "functions.h"
|
||||
|
||||
extern struct {
|
||||
u8 unk0;
|
||||
char* ptr;
|
||||
s32 index;
|
||||
} s_dialogBin;
|
||||
|
||||
extern s32 code94620_func_8031B5B0(void);
|
||||
|
||||
static char dialog_bytes[1024];
|
||||
char* dialog_byte_cursor = NULL;
|
||||
char* dialog_byte_character_cursor = NULL;
|
||||
|
||||
void start_dialog_bin() {
|
||||
dialog_byte_cursor = &dialog_bytes[0];
|
||||
dialog_byte_character_cursor = dialog_byte_cursor;
|
||||
*(dialog_byte_cursor++) = 0;
|
||||
}
|
||||
|
||||
void add_dialog_bin_string(char command, const char* string) {
|
||||
u32 length_with_zero = strlen(string) + 1;
|
||||
*(dialog_byte_cursor++) = command;
|
||||
*(dialog_byte_cursor++) = length_with_zero;
|
||||
memcpy(dialog_byte_cursor, string, length_with_zero);
|
||||
dialog_byte_cursor += length_with_zero;
|
||||
*dialog_byte_character_cursor += 1;
|
||||
}
|
||||
|
||||
void next_dialog_bin_character() {
|
||||
dialog_byte_character_cursor = dialog_byte_cursor;
|
||||
*(dialog_byte_cursor++) = 0;
|
||||
}
|
||||
|
||||
char *end_dialog_bin() {
|
||||
u32 dialog_size = dialog_byte_cursor - dialog_bytes;
|
||||
char *alloc = malloc_recomp(dialog_size);
|
||||
memcpy(alloc, dialog_bytes, dialog_size);
|
||||
#if 0
|
||||
recomp_printf("[%d]: ", dialog_size);
|
||||
|
||||
for (u32 i = 0; i < dialog_size; i++) {
|
||||
recomp_printf("0x%X ", dialog_bytes[i]);
|
||||
}
|
||||
#endif
|
||||
return alloc;
|
||||
}
|
||||
|
||||
RECOMP_PATCH char* dialogBin_get(enum asset_e text_id) {
|
||||
char* sp1C;
|
||||
char* var_v0;
|
||||
s32 var_a0; //offset where text starts (normally 0x3)
|
||||
|
||||
//get text_bin from asset cache
|
||||
s_dialogBin.ptr = assetcache_get(text_id);
|
||||
sp1C = s_dialogBin.ptr + 1;
|
||||
sp1C += code94620_func_8031B5B0() * 2;
|
||||
var_a0 = *(sp1C++);
|
||||
var_a0 += *(sp1C++) << 8;
|
||||
if (sp1C);
|
||||
var_v0 = s_dialogBin.ptr + var_a0;
|
||||
s_dialogBin.index = text_id;
|
||||
|
||||
#if 0
|
||||
recomp_printf("static char dialog_%d[] = {", text_id);
|
||||
|
||||
char* c = var_v0;
|
||||
for (u32 i = 0; i < 2; i++) {
|
||||
char count = *(c++);
|
||||
recomp_printf("0x%X, ", count);
|
||||
|
||||
for (char j = 0; j < count; j++) {
|
||||
char cmd = *(c++);
|
||||
char len = *(c++);
|
||||
recomp_printf("0x%X, ", cmd);
|
||||
recomp_printf("0x%X, ", len);
|
||||
|
||||
for (char k = 0; k < len; k++) {
|
||||
if (*c == '\'') {
|
||||
recomp_printf("'\\'', ");
|
||||
}
|
||||
else if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') || (*c >= '0' && *c <= '9') || (*c >= ' ' && *c <= '?')) {
|
||||
recomp_printf("'%c', ", *c);
|
||||
}
|
||||
else {
|
||||
recomp_printf("0x%X, ", *c);
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recomp_printf("}\n");
|
||||
#endif
|
||||
|
||||
#define DIALOGUE_BANJO_HEAD 0x80
|
||||
#define DIALOGUE_KAZOOIE_HEAD 0x81
|
||||
#define DIALOGUE_BOTTLES_HEAD 0x83
|
||||
#define DIALOGUE_MUMBO_HEAD 0x84
|
||||
#define DIALOGUE_COMMAND_END 0x4
|
||||
|
||||
switch (text_id) {
|
||||
case 3599:
|
||||
static char* dialog_3599;
|
||||
if (dialog_3599 == NULL) {
|
||||
start_dialog_bin();
|
||||
add_dialog_bin_string(DIALOGUE_BANJO_HEAD, "WOW! THAT LOOKS SO SMOOTH!");
|
||||
add_dialog_bin_string(DIALOGUE_MUMBO_HEAD, "CAN RUN AT 60, 120 OR WHATEVER FPS YOU WANT. MUMBO'S MAGIC PC DOES 360 FPS.");
|
||||
add_dialog_bin_string(DIALOGUE_KAZOOIE_HEAD, "STOP SHOWING OFF SHAMAN BOY. WHAT ABOUT ON MY ULTRAWIDE MONITOR?");
|
||||
add_dialog_bin_string(DIALOGUE_MUMBO_HEAD, "RUDE BIRD NEED NOT WORRY. WIDESCREEN AND MORE SUPPORTED.");
|
||||
add_dialog_bin_string(DIALOGUE_KAZOOIE_HEAD, "IT RUNS WELL TOO. BANJO, EVEN THAT PC YOU GOT OUT OF THE DUMPSTER CAN PROBABLY RUN IT.");
|
||||
add_dialog_bin_string(DIALOGUE_BANJO_HEAD, "KAZOOIE!!!");
|
||||
add_dialog_bin_string(DIALOGUE_BOTTLES_HEAD, "HEY GUYS! CHECK OUT HOW COOL MY MINIGAME LOOKS IN THIS PORT!");
|
||||
add_dialog_bin_string(DIALOGUE_BANJO_HEAD, "OOOH! LOOKS GREAT! CAN'T WAIT TO TRY IT!");
|
||||
add_dialog_bin_string(DIALOGUE_KAZOOIE_HEAD, "I DON'T CARE ABOUT YOUR PUZZLES BOTTLE BRAIN. WHAT ABOUT NEW FEATURES?");
|
||||
add_dialog_bin_string(DIALOGUE_BOTTLES_HEAD, "I'M GLAD YOU ASKED, TAKE A LOOK!");
|
||||
add_dialog_bin_string(DIALOGUE_BANJO_HEAD, "NOTE SAVING? WHAT DOES THAT DO?");
|
||||
add_dialog_bin_string(DIALOGUE_BOTTLES_HEAD, "WHEN YOU USE IT, YOU WON'T LOSE YOUR NOTES EVERY TIME YOU EXIT A WORLD. NEAT, ISN'T IT?");
|
||||
add_dialog_bin_string(DIALOGUE_BANJO_HEAD, "AWESOME! DO WE GET ANY OTHER NEW FEATURES?");
|
||||
add_dialog_bin_string(DIALOGUE_BOTTLES_HEAD, "YES! IF YOU WANT, YOU CAN USE THE RIGHT ANALOG STICK FOR SMOOTHER CAMERA CONTROLS.");
|
||||
add_dialog_bin_string(DIALOGUE_BOTTLES_HEAD, "YOU CAN ALSO USE HIGH DEFINITION TEXTURE PACKS AND CUSTOM MODS!");
|
||||
add_dialog_bin_string(DIALOGUE_BANJO_HEAD, "NEAT! WHAT KIND OF MODS CAN PEOPLE MAKE FOR THIS PORT?");
|
||||
add_dialog_bin_string(DIALOGUE_BOTTLES_HEAD, "PRETTY MUCH ANYTHING! NEW ASSETS, GAMEPLAY CHANGES, YOU NAME IT.");
|
||||
add_dialog_bin_string(DIALOGUE_KAZOOIE_HEAD, "YAWN. DOOM. HOW ORIGINAL. GOT ANYTHING WORTH PLAYING SOIL BRAIN?");
|
||||
add_dialog_bin_string(DIALOGUE_BOTTLES_HEAD, "SURE! MAYBE THESE ONES ARE MORE TO YOUR LIKING...");
|
||||
add_dialog_bin_string(DIALOGUE_BANJO_HEAD, "WOAH! THESE LOOK COOL! ARE THESE NEW ADVENTURES FOR US TO PLAY?");
|
||||
add_dialog_bin_string(DIALOGUE_KAZOOIE_HEAD, "HEY, I THOUGHT OCARINA OF TIME WASN'T READY YET?");
|
||||
add_dialog_bin_string(DIALOGUE_BOTTLES_HEAD, "NO FEATHER BRAIN. IT'S JIGGIES OF TIME BY KURKO MODS, WHICH YOU CAN PLAY IN THIS PORT!");
|
||||
add_dialog_bin_string(DIALOGUE_BOTTLES_HEAD, "WE MADE TOOLS FOR MODDERS TO CONVERT THEIR COMPATIBLE ROMHACKS INTO RECOMP MODS!");
|
||||
add_dialog_bin_string(DIALOGUE_BOTTLES_HEAD, "NOSTALGIA 64 IS ALSO AVAILABLE, AND MORE MODS WILL BE RELEASED IN THE FUTURE!");
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
next_dialog_bin_character();
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
dialog_3599 = end_dialog_bin();
|
||||
}
|
||||
|
||||
return dialog_3599;
|
||||
case 3705:
|
||||
static char* dialog_3705;
|
||||
if (dialog_3705 == NULL) {
|
||||
start_dialog_bin();
|
||||
add_dialog_bin_string(DIALOGUE_MUMBO_HEAD, "HEY...MUMBO GOT SECRET PICTURES!");
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
next_dialog_bin_character();
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
dialog_3705 = end_dialog_bin();
|
||||
}
|
||||
|
||||
return dialog_3705;
|
||||
case 3706:
|
||||
static char* dialog_3706;
|
||||
if (dialog_3706 == NULL) {
|
||||
start_dialog_bin();
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
next_dialog_bin_character();
|
||||
add_dialog_bin_string(DIALOGUE_KAZOOIE_HEAD, "NICE ONE, BONE BRAIN! WHAT'S ON THEM?");
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
dialog_3706 = end_dialog_bin();
|
||||
}
|
||||
|
||||
return dialog_3706;
|
||||
case 3707:
|
||||
static char* dialog_3707;
|
||||
if (dialog_3707 == NULL) {
|
||||
start_dialog_bin();
|
||||
add_dialog_bin_string(DIALOGUE_MUMBO_HEAD, "GOT PICTURES OF NEXT PORT. WISEGUY GAVE THEM TO ME.");
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
next_dialog_bin_character();
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
dialog_3707 = end_dialog_bin();
|
||||
}
|
||||
|
||||
return dialog_3707;
|
||||
case 3708:
|
||||
static char* dialog_3708;
|
||||
if (dialog_3708 == NULL) {
|
||||
start_dialog_bin();
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
next_dialog_bin_character();
|
||||
add_dialog_bin_string(DIALOGUE_BANJO_HEAD, "OOOH...DID YOU HEAR THAT KAZOOIE? THERE'S GOING TO BE ANOTHER RECOMP!");
|
||||
add_dialog_bin_string(DIALOGUE_KAZOOIE_HEAD, "IS IT THE ELF BOY AGAIN? HE ALWAYS GETS ALL THE ATTENTION.");
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
dialog_3708 = end_dialog_bin();
|
||||
}
|
||||
|
||||
return dialog_3708;
|
||||
case 3709:
|
||||
static char* dialog_3709;
|
||||
if (dialog_3709 == NULL) {
|
||||
start_dialog_bin();
|
||||
add_dialog_bin_string(DIALOGUE_MUMBO_HEAD, "NO OCARINA. TAKING FOREVER. OTHER INSTRUMENTS FIRST.");
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
next_dialog_bin_character();
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
dialog_3709 = end_dialog_bin();
|
||||
}
|
||||
|
||||
return dialog_3709;
|
||||
case 3717:
|
||||
static char* dialog_3717;
|
||||
if (dialog_3717 == NULL) {
|
||||
start_dialog_bin();
|
||||
add_dialog_bin_string(DIALOGUE_BANJO_HEAD, "SOUNDS EXCITING. WHAT COULD IT BE?");
|
||||
add_dialog_bin_string(DIALOGUE_KAZOOIE_HEAD, "YEAH, SHOW US!");
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
next_dialog_bin_character();
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
dialog_3717 = end_dialog_bin();
|
||||
}
|
||||
|
||||
return dialog_3717;
|
||||
case 3719:
|
||||
static char* dialog_3719;
|
||||
if (dialog_3719 == NULL) {
|
||||
start_dialog_bin();
|
||||
add_dialog_bin_string(DIALOGUE_BANJO_HEAD, "THAT WAS GREAT! SO WHEN CAN WE PLAY THIS PORT?");
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
next_dialog_bin_character();
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
dialog_3719 = end_dialog_bin();
|
||||
}
|
||||
|
||||
return dialog_3719;
|
||||
case 3720:
|
||||
static char* dialog_3720;
|
||||
if (dialog_3720 == NULL) {
|
||||
start_dialog_bin();
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
next_dialog_bin_character();
|
||||
add_dialog_bin_string(DIALOGUE_MUMBO_HEAD, "YOU CAN PLAY IT...NOW!");
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
dialog_3720 = end_dialog_bin();
|
||||
}
|
||||
|
||||
return dialog_3720;
|
||||
case 3721:
|
||||
static char* dialog_3721;
|
||||
if (dialog_3721 == NULL) {
|
||||
start_dialog_bin();
|
||||
add_dialog_bin_string(DIALOGUE_KAZOOIE_HEAD, "REALLY?! COME ON BANJO, I WANT TO GO HOME AND PLAY IT!");
|
||||
add_dialog_bin_string(DIALOGUE_BANJO_HEAD, "WAHEY! SOUNDS LIKE A PLAN!");
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
next_dialog_bin_character();
|
||||
add_dialog_bin_string(DIALOGUE_COMMAND_END, "");
|
||||
dialog_3721 = end_dialog_bin();
|
||||
}
|
||||
|
||||
return dialog_3721;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return var_v0;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,5 @@ DECLARE_FUNC(float, recomp_get_target_aspect_ratio, float);
|
||||
DECLARE_FUNC(s32, recomp_get_target_framerate, s32);
|
||||
DECLARE_FUNC(s32, recomp_high_precision_fb_enabled);
|
||||
DECLARE_FUNC(float, recomp_get_resolution_scale);
|
||||
DECLARE_FUNC(float, recomp_get_cutscene_aspect_ratio);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "patches.h"
|
||||
#include "ultra_extensions.h"
|
||||
#include "misc_funcs.h"
|
||||
#include "note_saving.h"
|
||||
#include "core1/core1.h"
|
||||
#include "core1/vimgr.h"
|
||||
|
||||
@@ -24,7 +22,7 @@ extern struct{
|
||||
|
||||
void func_802E39D0(Gfx **gdl, Mtx **mptr, Vtx **vptr, s32 framebuffer_idx, s32 arg4);
|
||||
|
||||
// 16x the original sizes.
|
||||
// 10x the original sizes.
|
||||
#define GFX_BUFFER_COUNT 37000
|
||||
#define MTX_BUFFER_COUNT 7000
|
||||
#define VTX_BUFFER_COUNT 4300
|
||||
@@ -41,11 +39,6 @@ extern Vtx *sVtxStack[2];
|
||||
extern s32 sStackSelector;
|
||||
extern s32 gTextureFilterPoint;
|
||||
extern u32 heap_occupiedBytes;
|
||||
extern u32 dynamic_camera_target_index;
|
||||
|
||||
extern void recomp_reset_skinning_stack();
|
||||
extern void recomp_reset_map_model_skinning();
|
||||
extern void recomp_advance_dynamic_camera_targets();
|
||||
|
||||
// @recomp Patched to not free anything.
|
||||
RECOMP_PATCH void graphicsCache_release(void) {
|
||||
@@ -71,9 +64,7 @@ RECOMP_PATCH void graphicsCache_init(void){
|
||||
gTextureFilterPoint = 0;
|
||||
}
|
||||
|
||||
void handle_cutscene_timings(void);
|
||||
// @recomp Patched to check for graphics stack overflow after processing a frame.
|
||||
// Also patched to wait for a message when the displaylist is completed immediately after queueing it to solve vertex modification race conditions.
|
||||
RECOMP_PATCH void game_draw(s32 arg0){
|
||||
Gfx *gfx;
|
||||
Gfx *gfx_start;
|
||||
@@ -90,17 +81,6 @@ RECOMP_PATCH void game_draw(s32 arg0){
|
||||
if(D_8037E8E0.unkC == 1){
|
||||
getGraphicsStacks(&gfx, &mtx, &vtx);
|
||||
}
|
||||
|
||||
// @recomp Reset the high precision position skinning stacks.
|
||||
recomp_reset_skinning_stack();
|
||||
recomp_reset_map_model_skinning();
|
||||
|
||||
// @recomp Advance the frame used as reference by the dynamic camera target changes for analog camera.
|
||||
recomp_advance_dynamic_camera_targets();
|
||||
|
||||
// @recomp Update note saving state.
|
||||
note_saving_update();
|
||||
|
||||
// @recomp Track the original values.
|
||||
Mtx* mtx_start = mtx;
|
||||
Vtx* vtx_start = vtx;
|
||||
@@ -109,15 +89,8 @@ RECOMP_PATCH void game_draw(s32 arg0){
|
||||
|
||||
// @recomp Enable the extended gbi.
|
||||
gEXEnable(gfx++);
|
||||
gEXSetRDRAMExtended(gfx++, TRUE);
|
||||
gEXSetRefreshRate(gfx++, 60 / viMgr_func_8024BFA0()); // Input framerate is equal to 60 Hz divided by the frame divisor
|
||||
|
||||
// @recomp Turn off nearclipping (i.e. turn on depth clamp) to prevent the camera from clipping through lots of geometry in ultrawide aspect ratios.
|
||||
gEXSetNearClipping(gfx++, FALSE);
|
||||
|
||||
// @recomp Set the global wrapping point for texture coordinate interpolation to 256.
|
||||
gEXSetTexcoordWrapPoint(gfx++, 256 * 4, 256 * 4);
|
||||
|
||||
func_802E39D0(&gfx, &mtx, &vtx, getActiveFramebuffer(), arg0);
|
||||
|
||||
// @recomp Check for graphics stack overflow
|
||||
@@ -142,27 +115,10 @@ RECOMP_PATCH void game_draw(s32 arg0){
|
||||
if(D_8037E8E0.unkC == 0){
|
||||
sp2C = gfx;
|
||||
viMgr_func_8024C1DC();
|
||||
|
||||
// @recomp Set up the message queue and event for waiting on DL completion.
|
||||
OSMesgQueue dl_complete_queue;
|
||||
OSMesg dl_complete_queue_buf;
|
||||
osCreateMesgQueue(&dl_complete_queue, &dl_complete_queue_buf, 1);
|
||||
osExQueueDisplaylistEvent(&dl_complete_queue, NULL, gfx_start, OS_EX_DISPLAYLIST_EVENT_PARSED);
|
||||
|
||||
func_80253EC4(gfx_start, sp2C);
|
||||
|
||||
// @recomp Wait for the displaylist to be completed after submitting it. This removes the race condition
|
||||
// that exists with vertex modifications for texture scrolling.
|
||||
osRecvMesg(&dl_complete_queue, NULL, OS_MESG_BLOCK);
|
||||
|
||||
if(arg0) {
|
||||
scissorBox_setDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Call the relevant function to fix cutscene timings, if there is one.
|
||||
handle_cutscene_timings();
|
||||
|
||||
// Allow interpolation for the next frame.
|
||||
set_all_interpolation_skipped(FALSE);
|
||||
}
|
||||
|
||||
@@ -1,891 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
#include "../src/core2/gc/zoombox.h"
|
||||
|
||||
#define AIRSCORE_COUNT (6)
|
||||
|
||||
extern u8 D_80381E58[5];
|
||||
extern u16 D_80381620[0xD][5][0x10];
|
||||
extern u16 gScissorBoxLeft;
|
||||
extern u16 gScissorBoxRight;
|
||||
extern u16 gScissorBoxTop;
|
||||
extern u16 gScissorBoxBottom;
|
||||
extern s32 D_803815C0;
|
||||
extern s32 D_803815E4;
|
||||
extern s32 D_803815EC;
|
||||
extern s32 D_8036A018[];
|
||||
extern s32 D_80381EC4;
|
||||
extern s32 gTotalHealth;
|
||||
extern f32 D_803815C8;
|
||||
extern f32 D_803815CC;
|
||||
extern f32 D_803815D0;
|
||||
extern f32 D_803815D4;
|
||||
extern f32 D_803815D8;
|
||||
extern f32 D_803815DC;
|
||||
extern f32 D_803815E0;
|
||||
extern f32 D_80381E54;
|
||||
extern f32 D_80381E60[5];
|
||||
extern f32 D_80381E78[5];
|
||||
extern f32 D_80381EB8;
|
||||
extern f32 D_80381EBC;
|
||||
extern f32 D_80381EFC;
|
||||
extern f32 D_80381F08[8];
|
||||
extern f32 D_80381F68[AIRSCORE_COUNT];
|
||||
extern f32 s_texture_scale;
|
||||
extern f32 s_active_count;
|
||||
extern s32 D_803815E8;
|
||||
extern f32 gHealth;
|
||||
extern void *D_8036A010;
|
||||
extern void *D_8036A014;
|
||||
extern Gfx D_80369920[];
|
||||
extern Gfx D_8036A030[];
|
||||
extern Gfx D_8036A228[];
|
||||
extern Gfx D_8036A278[];
|
||||
extern Gfx D_8036A918[];
|
||||
extern Gfx s_fxairscore_context[];
|
||||
extern void *D_80381EB0[2];
|
||||
extern char code_78E50_ItemValueString[8];
|
||||
extern BKSprite *D_80381E40[5];
|
||||
extern BKSprite *gSpriteHealth;
|
||||
extern BKSprite *gSpriteRedHealth;
|
||||
extern BKSprite *s_sprite;
|
||||
extern struct1Cs_1 D_8036C58C[0xD];
|
||||
|
||||
extern void func_80347FC0(Gfx **gfx, BKSprite *sprite, s32 frame, s32 tmem, s32 rtile, s32 uls, s32 ult, s32 cms, s32 cmt, s32 *width, s32 *height);
|
||||
extern void func_80348044(Gfx **gfx, BKSprite *sprite, s32 frame, s32 tmem, s32 rtile, s32 uls, s32 ult, s32 cms, s32 cmt, s32 *width, s32 *height, s32 *frame_width, s32 *frame_height, s32 *texture_x, s32 *texture_y, s32 *textureCount);
|
||||
extern f32 func_802FDE60(f32 arg0);
|
||||
extern f32 func_802FB0E4(struct8s *this);
|
||||
extern s32 func_802FB0D4(struct8s *this);
|
||||
extern f32 func_802FB0DC(struct8s *this);
|
||||
extern void func_802FD360(struct8s *arg0, Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
extern s32 itemPrint_getValue(s32 item_id);
|
||||
extern s32 level_get(void);
|
||||
extern s32 itemscore_noteScores_getTotal(void);
|
||||
extern s32 getGameMode(void);
|
||||
extern f32 vtxList_getGlobalNorm(BKVertexList *);
|
||||
|
||||
s32 itemPrint_lastValues[0x2C];
|
||||
|
||||
typedef struct {
|
||||
u8 pad0[0x14];
|
||||
s32 unk14;
|
||||
u8 pad18[0x8];
|
||||
s32 item_id; //item_id
|
||||
s32 model_id; //model_id
|
||||
s32 anim_id; //anim_id
|
||||
f32 anim_duration; //anim_duration
|
||||
f32 unk30;
|
||||
f32 unk34;
|
||||
f32 unk38;
|
||||
f32 unk3C; //scale?
|
||||
f32 unk40;
|
||||
f32 unk44;
|
||||
f32 unk48;
|
||||
f32 unk4C;
|
||||
f32 unk50;
|
||||
f32 unk54;
|
||||
BKModelBin *model;
|
||||
char value_string[0xC];
|
||||
f32 unk68;
|
||||
f32 unk6C;
|
||||
AnimCtrl *anim_ctrl;
|
||||
}Struct_core2_79830_0;
|
||||
|
||||
extern struct {
|
||||
u8 state;
|
||||
u8 menu;
|
||||
u8 selection; //menu page
|
||||
u8 exit_pause : 1;
|
||||
u8 unk3_6 : 1; //busy?
|
||||
u8 unk3_5 : 1;
|
||||
u8 unk3_4 : 1;
|
||||
u8 left_joystick_visible : 1;
|
||||
u8 right_joystick_visible : 1;
|
||||
u8 b_button_visible : 1;
|
||||
u8 unk3_0 : 1;
|
||||
s8 zoombox_opening_count;
|
||||
s8 zoombox_closing_count;
|
||||
u8 unk6;
|
||||
u8 unk7;
|
||||
s8 unk8; //header position
|
||||
s8 page;
|
||||
s8 joystick_frame;
|
||||
u8 joystick_frame_count;
|
||||
f32 unkC;
|
||||
GcZoombox *zoombox[4];
|
||||
f32 unk20;
|
||||
BKSprite *joystick_sprite;
|
||||
f32 unk28;
|
||||
BKSprite *b_button_sprite;
|
||||
u8 b_button_frame;
|
||||
u8 b_button_frame_count; //B-button total frames
|
||||
s16 b_button_alpha; //B-button alpha
|
||||
s16 left_joystick_alpha; //left joystick alpha
|
||||
s16 right_joystick_alpha; //right joystick alpha
|
||||
u8 page_cnt;
|
||||
u8 sns_items;
|
||||
u8 sns_visible;
|
||||
// u8 pad3B[1];
|
||||
s16 sns_alpha; //sns opacity
|
||||
s16 unk3E[7];
|
||||
s16 unk4C[7];
|
||||
// u8 pad5A[0x3];
|
||||
BKModelBin *sns_egg_model; //SnS Egg Model
|
||||
BKModelBin *ice_key_model; //Ice key model
|
||||
u8 pad64[12];
|
||||
u32 unk70_31 : 1;
|
||||
u32 unk70_30 : 1;
|
||||
u32 return_to_lair_disabled : 1;
|
||||
u32 pad70_28 : 29;
|
||||
} D_80383010;
|
||||
|
||||
extern u32 cur_pushed_text_transform_id;
|
||||
extern u32 cur_pushed_text_transform_origin;
|
||||
extern u32 cur_pushed_text_transform_skip_interpolation;
|
||||
|
||||
ModelSkinningData sScore3SkinningData[ITEM_2B_UNKNOWN];
|
||||
|
||||
void bkrecomp_setup_custom_skinning(ModelSkinningData* skinning_data, u32 model_id);
|
||||
|
||||
// @recomp Tag the matrices for each honeycomb piece.
|
||||
RECOMP_PATCH void fxhoneycarrierscore_draw(s32 arg0, struct8s *arg1, Gfx **arg2, Mtx **arg3, Vtx **arg4) {
|
||||
f64 var_f24;
|
||||
s32 sp13C;
|
||||
s32 sp138;
|
||||
s32 sp134;
|
||||
f32 sp130;
|
||||
f32 sp12C;
|
||||
f32 sp128;
|
||||
f32 sp124;
|
||||
s32 var_v0;
|
||||
s32 var_v1;
|
||||
u32 sp118;
|
||||
f32 pad;
|
||||
f32 sp110;
|
||||
|
||||
sp118 = D_803815C0 == 2;
|
||||
if (D_8036A010 != 0) {
|
||||
func_80347FC0(arg2, (sp118) ? (D_8036A014 != 0) ? D_8036A014 : D_8036A010 : D_8036A010, 0, 0, 0, 0, 0, 2, 2, &sp13C, &sp138);
|
||||
|
||||
// @recomp Align the honeycomb pieces to the right side of the screen.
|
||||
// NOTE: gScissorBoxRight/gScissorBoxTop are incorrectly named in the decompilation and must be swapped.
|
||||
gEXPushScissor((*arg2)++);
|
||||
gEXSetScissor((*arg2)++, G_SC_NON_INTERLACE, G_EX_ORIGIN_RIGHT, G_EX_ORIGIN_RIGHT, gScissorBoxLeft - gScissorBoxTop, gScissorBoxRight, 0, gScissorBoxBottom);
|
||||
gEXSetViewportAlign((*arg2)++, G_EX_ORIGIN_RIGHT, -gScissorBoxTop * 4, 0);
|
||||
|
||||
viewport_setRenderViewportAndOrthoMatrix(arg2, arg3);
|
||||
gSPDisplayList((*arg2)++, D_8036A030);
|
||||
for (sp134 = 0; sp134 < ((sp118) ? ((D_8036A014 != 0) ? 2 : 1) : 6); sp134++) {
|
||||
sp110 = D_8036A018[sp134] * -0x3C;
|
||||
gDPPipeSync((*arg2)++);
|
||||
if (sp118) {
|
||||
if (sp134 != 0) {
|
||||
func_80347FC0(arg2, D_8036A010, 0, 0, 0, 0, 0, 2, 2, &sp13C, &sp138);
|
||||
gDPSetPrimColor((*arg2)++, 0, 0, 0x00, 0x00, 0x00, (0xFF - D_803815E4));
|
||||
}
|
||||
else {
|
||||
gDPSetPrimColor((*arg2)++, 0, 0, 0x00, 0x00, 0x00, D_803815E4);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (D_803815D4 <= D_8036A018[sp134]) {
|
||||
gDPSetPrimColor((*arg2)++, 0, 0, 0x00, 0x00, 0x00, 0x50);
|
||||
}
|
||||
else {
|
||||
if ((D_803815EC != 0) && ((D_803815D4 - 1.0f) == D_8036A018[sp134])) {
|
||||
gDPSetPrimColor((*arg2)++, 0, 0, 0x00, 0x00, 0x00, D_803815E8);
|
||||
}
|
||||
else {
|
||||
gDPSetPrimColor((*arg2)++, 0, 0, 0x00, 0x00, 0x00, 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Set a matrix group.
|
||||
gEXMatrixGroupSimpleVerts((*arg2)++, HUD_HONEYCOMB_TRANSFORM_ID_START + sp134, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
sp128 = (244.0f - ((f32)gFramebufferWidth / 2));
|
||||
sp124 = func_802FB0E4(arg1) + ((f32)gFramebufferHeight / 2) - 246.0f;
|
||||
guTranslate(*arg3, sp128 * 4.0f, sp124 * 4.0f, 0.0f);
|
||||
gSPMatrix((*arg2)++, OS_K0_TO_PHYSICAL((*arg3)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
guRotate(*arg3, func_802FDE60(D_803815D8 + D_803815DC), 0.0f, 0.0f, 1.0f);
|
||||
gSPMatrix((*arg2)++, OS_K0_TO_PHYSICAL((*arg3)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
|
||||
guScale(*arg3, D_803815E0, D_803815E0, D_803815E0);
|
||||
gSPMatrix((*arg2)++, OS_K0_TO_PHYSICAL((*arg3)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
|
||||
guTranslate(*arg3, -sp128 * 4.0f, -sp124 * 4.0f, 0.0f);
|
||||
gSPMatrix((*arg2)++, OS_K0_TO_PHYSICAL((*arg3)++), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
|
||||
var_f24 = MIN(1.0, MAX(0.0, D_803815C8));
|
||||
sp130 = cosf(((D_803815CC + sp110) * 0.017453292519943295)) * (var_f24 * 24.5) * D_803815D0;
|
||||
var_f24 = MIN(1.0, MAX(0.0, D_803815C8));
|
||||
sp12C = sinf(((D_803815CC + sp110) * 0.017453292519943295)) * (var_f24 * 24.5) * D_803815D0;
|
||||
gSPVertex((*arg2)++, *arg4, 4, 0);
|
||||
for (var_v1 = 0; var_v1 < 2; var_v1++) {
|
||||
for (var_v0 = 0; var_v0 < 2; var_v0++, (*arg4)++) {
|
||||
(*arg4)->v.ob[0] = ((((sp13C * D_803815D0) * var_v0) - ((sp13C * D_803815D0) / 2)) + (s32)(sp130 + sp128)) * 4.0f;
|
||||
(*arg4)->v.ob[1] = ((((sp138 * D_803815D0) / 2) - ((sp138 * D_803815D0) * var_v1)) + (s32)(sp12C + sp124)) * 4.0f;
|
||||
(*arg4)->v.ob[2] = -0x14;
|
||||
(*arg4)->v.tc[0] = (s16)((sp13C - 1) * var_v0 << 9);
|
||||
(*arg4)->v.tc[1] = (s16)((sp138 - 1) * var_v1 << 9);
|
||||
|
||||
}
|
||||
}
|
||||
gSP1Quadrangle((*arg2)++, 0, 1, 3, 2, 0);
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXPopMatrixGroup((*arg2)++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXSetViewportAlign((*arg2)++, G_EX_ORIGIN_NONE, 0, 0);
|
||||
gEXPopScissor((*arg2)++);
|
||||
|
||||
gDPPipeSync((*arg2)++);
|
||||
gDPSetTextureLUT((*arg2)++, G_TT_NONE);
|
||||
gDPPipelineMode((*arg2)++, G_PM_NPRIMITIVE);
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(arg2, arg3);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to tag the Jinjos on the HUD.
|
||||
RECOMP_PATCH void fxjinjoscore_draw(s32 arg0, struct8s *arg1, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
BKSprite *sprite; // s1
|
||||
s32 draw_index; // s5
|
||||
s32 texture_width; // sp11C
|
||||
s32 texture_height; // sp118
|
||||
s32 jinjo_id; // sp114
|
||||
f32 center_y; // f14 (sp110)
|
||||
f32 center_x; // f20 (sp10C)
|
||||
f32 x_offset; // f26 (sp108)
|
||||
f32 y_offset; // f28 (sp104)
|
||||
f32 pos_x; // f30 (sp100)
|
||||
s32 i; // v1 (spFC)
|
||||
s32 j; // v0_2 (spF8)
|
||||
|
||||
// @recomp Align the Jinjos to the left side of the screen.
|
||||
// NOTE: gScissorBoxRight/gScissorBoxTop are incorrectly named in the decompilation and must be swapped.
|
||||
gEXPushScissor((*gfx)++);
|
||||
gEXSetScissor((*gfx)++, G_SC_NON_INTERLACE, G_EX_ORIGIN_LEFT, G_EX_ORIGIN_LEFT, gScissorBoxLeft, gScissorBoxRight, gScissorBoxTop, gScissorBoxBottom);
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_LEFT, 0, 0);
|
||||
|
||||
gSPDisplayList((*gfx)++, D_8036A228);
|
||||
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
|
||||
pos_x = 44.0f;
|
||||
// Draw all jinjo heads
|
||||
for (jinjo_id = 0; jinjo_id < 5; jinjo_id++) {
|
||||
s32 jinjo_collected; // spF0 <----
|
||||
sprite = D_80381E40[jinjo_id];
|
||||
jinjo_collected = (D_80381E58[jinjo_id] != 0) ? 1 : 0;
|
||||
if (sprite != NULL) {
|
||||
func_80347FC0(gfx, sprite, (s32)D_80381E60[jinjo_id], 0, 0, 0, 0, 2, 2, &texture_width, &texture_height);
|
||||
// Load the palette for the corresponding jinjo color
|
||||
gDPLoadTLUT_pal16((*gfx)++, 0, D_80381620[(s32)D_80381E60[jinjo_id]][jinjo_id]);
|
||||
x_offset = 0.0f;
|
||||
y_offset = 0.0f;
|
||||
// Draw the jinjo head, once if uncollected and twice if collected
|
||||
// If the head is drawn twice then the first draw will be the drop shadow
|
||||
for (draw_index = jinjo_collected; draw_index >= 0; draw_index--) {
|
||||
gDPPipeSync((*gfx)++);
|
||||
// Draw 0 is the jinjo's head, anything else is a shadow
|
||||
if (draw_index != 0) {
|
||||
// Use only primitive color as the color input in order to make a solid color shadow
|
||||
gDPSetCombineLERP((*gfx)++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0);
|
||||
// Set up a translucent black for primitive color to draw the shadow
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0x00, 0x00, 0x00, 0x8C);
|
||||
}
|
||||
else {
|
||||
// Use the texture as the color input
|
||||
gDPSetCombineLERP((*gfx)++, 0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE, 0);
|
||||
// If the jinjo is collected then it's drawn fully opaque, otherwise it's drawn with partial alpha
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0x00, 0x00, 0x00, jinjo_collected ? 0xFF : 0x6E);
|
||||
}
|
||||
center_x = pos_x - (f32)gFramebufferWidth / 2 + x_offset;
|
||||
|
||||
// @recomp Remove vertical translation from the vertices.
|
||||
center_y = (f32)gFramebufferHeight / 2 - 266.0f + 40.0f + y_offset;
|
||||
//center_y = (f32)gFramebufferHeight / 2 + func_802FB0E4(arg1) - 266.0f + 40.0f + y_offset - D_80381E78[jinjo_id];
|
||||
|
||||
// @recomp Assign the matrix group for each Jinjo and its shadow separately.
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, HUD_JINJOSCORE_TRANSFORM_ID_START + jinjo_id * 2 + draw_index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
// @recomp Add vertical translation to matrix.
|
||||
guTranslate(*mtx, 0.0f, (func_802FB0E4(arg1) - D_80381E78[jinjo_id]) * 4.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_K0_TO_PHYSICAL((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
gSPVertex((*gfx)++, *vtx, 4, 0);
|
||||
// Set up the positions of the four vertices
|
||||
for (i = 0; i < 2; i++) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
(*vtx)->v.ob[0] = ((texture_width * D_80381E54 * j) - (texture_width * D_80381E54 / 2) + center_x) * 4;
|
||||
(*vtx)->v.ob[1] = ((texture_height * D_80381E54 / 2) - (texture_height * D_80381E54 * i) + center_y) * 4;
|
||||
(*vtx)->v.ob[2] = -20;
|
||||
(*vtx)->v.tc[0] = ((texture_width - 1) * j) << 6;
|
||||
(*vtx)->v.tc[1] = ((texture_height - 1) * i) << 6;
|
||||
(*vtx)++;
|
||||
}
|
||||
}
|
||||
// Draw a quad made of the four vertices
|
||||
gSP1Quadrangle((*gfx)++, 0, 1, 3, 2, 0);
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
|
||||
x_offset += -2;
|
||||
y_offset += 2;
|
||||
}
|
||||
}
|
||||
// Move the next jinjo head over by 32 pixels
|
||||
pos_x += 32.0f;
|
||||
}
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_NONE, 0, 0);
|
||||
gEXPopScissor((*gfx)++);
|
||||
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetTextureLUT((*gfx)++, G_TT_NONE);
|
||||
gDPPipelineMode((*gfx)++, G_PM_NPRIMITIVE);
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
}
|
||||
|
||||
// @recomp Patched to tag the pieces of air and also align them to the left side of the screen.
|
||||
RECOMP_PATCH void fxairscore_draw(enum item_e item_id, struct8s *arg1, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
f32 y;
|
||||
f32 x;
|
||||
s32 texture_width;
|
||||
s32 texture_height;
|
||||
s32 i_part;
|
||||
s32 var_s6;
|
||||
s32 v_x;
|
||||
s32 v_y;
|
||||
|
||||
if (s_sprite != 0) {
|
||||
gSPDisplayList((*gfx)++, s_fxairscore_context);
|
||||
func_80347FC0(gfx, s_sprite, 0, 0, 0, 0, 0, 2, 2, &texture_width, &texture_height);
|
||||
|
||||
// @recomp Align the pieces of air to the left side of the screen.
|
||||
// NOTE: gScissorBoxRight/gScissorBoxTop are incorrectly named in the decompilation and must be swapped.
|
||||
gEXPushScissor((*gfx)++);
|
||||
gEXSetScissor((*gfx)++, G_SC_NON_INTERLACE, G_EX_ORIGIN_LEFT, G_EX_ORIGIN_LEFT, gScissorBoxLeft, gScissorBoxRight, gScissorBoxTop, gScissorBoxBottom);
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_LEFT, 0, 0);
|
||||
|
||||
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
//render all 6 air pieces
|
||||
for (i_part = 0; i_part < AIRSCORE_COUNT; i_part++) {
|
||||
if ((i_part != 0) && (i_part != 5)) {
|
||||
var_s6 = (i_part & 1) ? i_part + 1 : i_part - 1;
|
||||
}
|
||||
else {
|
||||
var_s6 = i_part;
|
||||
}
|
||||
gDPPipeSync((*gfx)++);
|
||||
if ((f32)(5 - i_part) < s_active_count) {
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0x00, 0x00, 0x00, 0xFF);
|
||||
}
|
||||
else {
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0x00, 0x00, 0x00, 0x78);
|
||||
}
|
||||
x = func_802FB0E4(arg1);
|
||||
x = ((-40 + x) + D_80381F68[var_s6]) - ((f32)gFramebufferWidth / 2);
|
||||
y = ((78 + (i_part * 15.5)) - ((f32)gFramebufferHeight / 2));
|
||||
|
||||
// @recomp Assign a matrix group to each piece of air.
|
||||
gEXMatrixGroupSimpleVerts((*gfx)++, HUD_AIRSCORE_TRANSFORM_ID_START + i_part, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
//stagger x position
|
||||
x = (i_part & 1) ? x + 5.0f : x - 5.0f;
|
||||
gSPVertex((*gfx)++, *vtx, 4, 0);
|
||||
for (v_y = 0; v_y < 2; v_y++) {
|
||||
for (v_x = 0; v_x < 2; v_x++) {
|
||||
(*vtx)->v.ob[0] = (x + (((texture_width * s_texture_scale) * v_x) - ((texture_width * s_texture_scale) / 2))) * 4.0f;
|
||||
(*vtx)->v.ob[1] = (y + (((texture_height * s_texture_scale) / 2) - (texture_height * s_texture_scale) * v_y)) * 4.0f;
|
||||
(*vtx)->v.ob[2] = -0x14;
|
||||
(*vtx)->v.tc[0] = ((texture_width - 1) * v_x) << 6;
|
||||
(*vtx)->v.tc[1] = ((texture_height - 1) * v_y) << 6;
|
||||
(*vtx)++;
|
||||
}
|
||||
}
|
||||
gSP1Quadrangle((*gfx)++, 0, 1, 3, 2, 0);
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_NONE, 0, 0);
|
||||
gEXPopScissor((*gfx)++);
|
||||
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetTextureLUT((*gfx)++, G_TT_NONE);
|
||||
gDPPipelineMode((*gfx)++, G_PM_NPRIMITIVE);
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to tag the health bar and align it to the left side of the screen.
|
||||
RECOMP_PATCH void fxhealthscore_draw(enum item_e item_id, struct8s *arg1, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
int i;
|
||||
int tmp_v1;
|
||||
s32 honeycomb_width;
|
||||
s32 honeycomb_height;
|
||||
int tmp_v0;
|
||||
f32 f18;
|
||||
f32 f14;
|
||||
f32 f20;
|
||||
s32 is_red_health_initialized = FALSE;
|
||||
s32 s6;
|
||||
|
||||
if (gSpriteHealth == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
gSPDisplayList((*gfx)++, D_8036A918);
|
||||
func_80347FC0(gfx, gSpriteHealth, 0, 0, 0, 0, 0, 2, 2, &honeycomb_width, &honeycomb_height);
|
||||
|
||||
// @recomp Align the health bar to the left side of the screen.
|
||||
// NOTE: gScissorBoxRight/gScissorBoxTop are incorrectly named in the decompilation and must be swapped.
|
||||
gEXPushScissor((*gfx)++);
|
||||
gEXSetScissor((*gfx)++, G_SC_NON_INTERLACE, G_EX_ORIGIN_LEFT, G_EX_ORIGIN_LEFT, gScissorBoxLeft, gScissorBoxRight, gScissorBoxTop, gScissorBoxBottom);
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_LEFT, 0, 0);
|
||||
|
||||
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
|
||||
//loop over each honeycomb piece
|
||||
for (i = gTotalHealth - 1; i >= 0; i--) {//L80300E40
|
||||
if (i != 0 && (i + 1 != gTotalHealth || gTotalHealth & 1)) {
|
||||
s6 = (i & 1) ? i + 1 : i - 1;
|
||||
}
|
||||
else {//L80300E84
|
||||
s6 = i;
|
||||
}
|
||||
|
||||
gDPPipeSync((*gfx)++);
|
||||
|
||||
if (gHealth > i) {
|
||||
if (0 < (gHealth - 8.0f) && (gHealth - 8.0f) > i) {
|
||||
if (!is_red_health_initialized) {
|
||||
func_80347FC0(gfx, gSpriteRedHealth, 0, 0, 0, 0, 0, 2, 2, &honeycomb_width, &honeycomb_height);
|
||||
is_red_health_initialized = TRUE;
|
||||
}
|
||||
}//L80300F38
|
||||
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
}
|
||||
else {//L80300F58
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0xFF, 0xFF, 0xFF, 0x78);
|
||||
}
|
||||
|
||||
f20 = 96.0f - (f32)gFramebufferWidth / 2 + (i * 13);
|
||||
f14 = (f32)gFramebufferHeight / 2 - func_802FB0E4(arg1) - D_80381F08[s6] - -48.0f;
|
||||
f14 = (i & 1) ? f14 + 5.75 : f14 - 5.75;
|
||||
|
||||
// @recomp Assign a matrix group to each piece of health.
|
||||
gEXMatrixGroupSimpleVerts((*gfx)++, HUD_HEALTHSCORE_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
gSPVertex((*gfx)++, *vtx, 4, 0);
|
||||
|
||||
for (tmp_v1 = 0; tmp_v1 < 2; tmp_v1++) {//L8030101C
|
||||
for (tmp_v0 = 0; tmp_v0 < 2; tmp_v0++) {//L80301030
|
||||
(*vtx)->v.ob[0] = (((honeycomb_width * D_80381EFC) * tmp_v0 - (honeycomb_width * D_80381EFC) / 2) + f20) * 4.0f;
|
||||
(*vtx)->v.ob[1] = (((honeycomb_height * D_80381EFC) / 2 - (honeycomb_height * D_80381EFC) * tmp_v1) + f14) * 4.0f;
|
||||
(*vtx)->v.ob[2] = -0x14;
|
||||
|
||||
(*vtx)->v.tc[0] = ((honeycomb_width - 1) * tmp_v0) << 6;
|
||||
(*vtx)->v.tc[1] = ((honeycomb_height - 1) * tmp_v1) << 6;
|
||||
(*vtx)++;
|
||||
}
|
||||
}
|
||||
|
||||
gSP1Quadrangle((*gfx)++, 0, 1, 3, 2, 0);
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_NONE, 0, 0);
|
||||
gEXPopScissor((*gfx)++);
|
||||
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetTextureLUT((*gfx)++, G_TT_NONE);
|
||||
gDPPipelineMode((*gfx)++, G_PM_NPRIMITIVE);
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
}
|
||||
|
||||
// @recomp Patched to tag the life icon and align it to the left side of the screen.
|
||||
RECOMP_PATCH void fxlifescore_draw(enum item_e item_id, struct8s *arg1, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
s32 sp10C;
|
||||
Vtx *sp108;
|
||||
s32 sp104;
|
||||
s32 var_v0;
|
||||
s32 var_v1;
|
||||
s32 var_s5;
|
||||
s32 var_s4;
|
||||
s32 spF0;
|
||||
s32 spEC;
|
||||
s32 spE8;
|
||||
s32 spE4;
|
||||
s32 spE0;
|
||||
s32 spDC;
|
||||
|
||||
sp10C = -1;
|
||||
sp108 = *vtx;
|
||||
code_78E50_ItemValueString[0] = '\0';
|
||||
strIToA(code_78E50_ItemValueString, MIN(9, itemPrint_getValue(item_id)));
|
||||
|
||||
// @recomp Assign an ID to the text and align it to the left side of the screen.
|
||||
cur_pushed_text_transform_id = HUD_LIFESCORE_TRANSFORM_PRINT_ID_START;
|
||||
cur_pushed_text_transform_origin = G_EX_ORIGIN_LEFT;
|
||||
|
||||
// @recomp Keep track of the last item value. If the value has changed, skip vertex interpolation this frame.
|
||||
if (itemPrint_lastValues[item_id] != itemPrint_getValue(item_id)) {
|
||||
cur_pushed_text_transform_skip_interpolation = TRUE;
|
||||
itemPrint_lastValues[item_id] = itemPrint_getValue(item_id);
|
||||
}
|
||||
|
||||
print_bold_spaced(0x4E, (s32)(func_802FB0E4(arg1) + -16.0f + 4.0f), (char *)&code_78E50_ItemValueString);
|
||||
|
||||
// @recomp Clear the ID and alignment for the text.
|
||||
cur_pushed_text_transform_id = 0;
|
||||
cur_pushed_text_transform_origin = G_EX_ORIGIN_NONE;
|
||||
cur_pushed_text_transform_skip_interpolation = FALSE;
|
||||
|
||||
if (1); //fake
|
||||
if (D_80381EB0[D_80381EC4] != NULL) {
|
||||
// @recomp Align the life icon to the left side of the screen.
|
||||
// NOTE: gScissorBoxRight/gScissorBoxTop are incorrectly named in the decompilation and must be swapped.
|
||||
gEXPushScissor((*gfx)++);
|
||||
gEXSetScissor((*gfx)++, G_SC_NON_INTERLACE, G_EX_ORIGIN_LEFT, G_EX_ORIGIN_LEFT, gScissorBoxLeft, gScissorBoxRight, gScissorBoxTop, gScissorBoxBottom);
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_LEFT, 0, 0);
|
||||
|
||||
gSPDisplayList((*gfx)++, D_8036A278);
|
||||
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
if (gfx);
|
||||
|
||||
// @recomp Assign a matrix group to the life icon.
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, HUD_LIFESCORE_TRANSFORM_ID_START, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetCombineLERP((*gfx)++, 0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE, 0);
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0x00, 0x00, 0x00, 0xFF);
|
||||
do {
|
||||
func_80348044(gfx, D_80381EB0[D_80381EC4], (s32)D_80381EBC % 4, 0, 0, 0, 0, 2, 2, &spF0, &spEC, &spE8, &spE4, &spE0, &spDC, &sp10C);
|
||||
|
||||
if (((*vtx - sp108) & 0xF) == 0) {
|
||||
gSPVertex((*gfx)++, *vtx, MIN(0x10, (1 + sp10C) << 2), 0);
|
||||
sp104 = 0;
|
||||
}
|
||||
else {
|
||||
sp104 = sp104 + 4;
|
||||
}
|
||||
|
||||
var_s5 = (40.0f - ((f32)gFramebufferWidth / 2)) + spE0;
|
||||
var_s4 = (((((f32)gFramebufferHeight / 2) - func_802FB0E4(arg1)) - -16.0f) - spDC);
|
||||
|
||||
// @recomp Assign the vertical translation of the life icon to the matrix.
|
||||
guTranslate(*mtx - 1, 0.0f, -func_802FB0E4(arg1) * 4.0f, 0.0f);
|
||||
var_s4 += func_802FB0E4(arg1);
|
||||
|
||||
for (var_v1 = 0; var_v1 < 2; var_v1++) {
|
||||
for (var_v0 = 0; var_v0 < 2; var_v0++) {
|
||||
(*vtx)->v.ob[0] = (s16)(s32)(((((f32)spF0 * D_80381EB8 * (f32)var_v0) - (((f32)spE8 * D_80381EB8) / 2)) + var_s5) * 4.0f);
|
||||
(*vtx)->v.ob[1] = (s16)(s32)((((((f32)spE4 * D_80381EB8) / 2) - ((f32)spEC * D_80381EB8 * var_v1)) + var_s4) * 4.0f);
|
||||
(*vtx)->v.ob[2] = -0x14;
|
||||
(*vtx)->v.tc[0] = ((spF0 - 1) * var_v0) << 6;
|
||||
(*vtx)->v.tc[1] = ((spEC - 1) * var_v1) << 6;
|
||||
(*vtx)++;
|
||||
}
|
||||
}
|
||||
gSP1Quadrangle((*gfx)++, sp104, sp104 + 1, sp104 + 3, sp104 + 2, 0);
|
||||
} while (sp10C != 0);
|
||||
|
||||
// @recomp Clear the matrix group and the viewport alignment.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_NONE, 0, 0);
|
||||
gEXPopScissor((*gfx)++);
|
||||
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetTextureLUT((*gfx)++, G_TT_NONE);
|
||||
gDPPipelineMode((*gfx)++, G_PM_NPRIMITIVE);
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to remove translation of the score element from the vertices and move it to the matrix.
|
||||
RECOMP_PATCH void func_802FD360(struct8s *arg0, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
s32 tmp_s2 = 0;
|
||||
s32 tmp_s4;
|
||||
s32 texture_width;
|
||||
s32 texture_height;
|
||||
f32 tmp_f26;
|
||||
f32 f2;
|
||||
|
||||
|
||||
if (arg0->unk50 == NULL) return;
|
||||
|
||||
gSPDisplayList((*gfx)++, &D_80369920);
|
||||
if (arg0->unk20 == ITEM_C_NOTE) {
|
||||
gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA, G_CC_MODULATEIA);
|
||||
}
|
||||
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
|
||||
// @recomp Add vertical animation component to the matrix.
|
||||
guTranslate(*mtx - 1, 0.0f, -func_802FB0E4(arg0) * arg0->unk4C * 4.0f, 0.0f);
|
||||
|
||||
gSPVertex((*gfx)++, *vtx, 4, 0);
|
||||
if (arg0->unk20 == ITEM_0_HOURGLASS_TIMER) {
|
||||
tmp_s2 = 0xC;
|
||||
}
|
||||
func_80347FC0(gfx, (BKSprite *)(arg0->unk50), ((s32)arg0->unk60 + tmp_s2) % arg0->unk2C, 0, 0, 0, 0, 2, 2, &texture_width, &texture_height);
|
||||
tmp_f26 = (arg0->unk20 == ITEM_0_HOURGLASS_TIMER && texture_width == 0x10) ? 1.0f : 0.0f;
|
||||
for (tmp_s4 = 0; tmp_s4 < 2; tmp_s4++) {//L802FD528
|
||||
for (tmp_s2 = 0; tmp_s2 < 2; tmp_s2++) {//
|
||||
(*vtx)->v.ob[0] = ((func_802FB0DC(arg0) + (((texture_width * arg0->unk40 * tmp_s2 - texture_width * arg0->unk40 / 2) - (f32)gFramebufferWidth / 2) + arg0->unk38)) + tmp_f26) * 4.0f;
|
||||
// @recomp Removed vertical animation component from the vertices.
|
||||
//(*vtx)->v.ob[1] = ((((texture_height * arg0->unk40 / 2 - texture_height * arg0->unk40 * tmp_s4) + (f32)gFramebufferHeight / 2) - arg0->unk3C) - func_802FB0E4(arg0) * arg0->unk4C) * 4.0f;
|
||||
(*vtx)->v.ob[1] = ((((texture_height * arg0->unk40 / 2 - texture_height * arg0->unk40 * tmp_s4) + (f32)gFramebufferHeight / 2) - arg0->unk3C)) * 4.0f;
|
||||
(*vtx)->v.ob[2] = -0x14;
|
||||
(*vtx)->v.tc[0] = ((texture_width - 1) * tmp_s2) << 6;
|
||||
(*vtx)->v.tc[1] = ((texture_height - 1) * tmp_s4) << 6;
|
||||
if (arg0->unk20 == ITEM_C_NOTE) {
|
||||
if (tmp_s4 == 0) {
|
||||
(*vtx)->v.cn[0] = 0xff;
|
||||
(*vtx)->v.cn[1] = 0xff;
|
||||
(*vtx)->v.cn[2] = 0x0;
|
||||
(*vtx)->v.cn[3] = 0xff;
|
||||
}
|
||||
else if (tmp_s2 != 0) {
|
||||
(*vtx)->v.cn[0] = 0xff;
|
||||
(*vtx)->v.cn[1] = 100;
|
||||
(*vtx)->v.cn[2] = 0x0;
|
||||
(*vtx)->v.cn[3] = 0xff;
|
||||
}
|
||||
else {
|
||||
(*vtx)->v.cn[0] = 0xff;
|
||||
(*vtx)->v.cn[1] = 200;
|
||||
(*vtx)->v.cn[2] = 0x0;
|
||||
(*vtx)->v.cn[3] = 0xff;
|
||||
}
|
||||
}
|
||||
(*vtx)++;
|
||||
}
|
||||
}
|
||||
gSP1Quadrangle((*gfx)++, 0, 1, 3, 2, 0);
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetTextureLUT((*gfx)++, G_TT_NONE);
|
||||
gDPPipelineMode((*gfx)++, G_PM_NPRIMITIVE);
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
}
|
||||
|
||||
// @recomp Patch to tag any 2D score elements and align them to the right side of the screen.
|
||||
RECOMP_PATCH void fxcommon2score_draw(enum item_e item_id, struct8s *arg1, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
f32 pad;
|
||||
s32 sp38;
|
||||
f32 sp34;
|
||||
|
||||
|
||||
sp38 = itemPrint_getValue(item_id);
|
||||
sp34 = 0.0f;
|
||||
if (item_id == ITEM_C_NOTE) {
|
||||
if (level_get() == LEVEL_6_LAIR || level_get() == LEVEL_C_BOSS) {
|
||||
sp38 = itemscore_noteScores_getTotal();
|
||||
}
|
||||
}
|
||||
if (item_id < 6) {
|
||||
sp38 = ((sp38) ? 1 : 0) + sp38 / 60;
|
||||
}//L802FDBA8
|
||||
if (item_id == ITEM_1B_VILE_VILE_SCORE && 9 < sp38) {
|
||||
sp34 = -16.0f;
|
||||
}
|
||||
if (item_id == ITEM_1C_MUMBO_TOKEN || item_id == ITEM_25_MUMBO_TOKEN_TOTAL) {
|
||||
if (sp38 >= 100) {
|
||||
sp38 = 99;
|
||||
}
|
||||
}
|
||||
arg1->string_54[0] = 0;
|
||||
//convert to string
|
||||
strIToA(arg1->string_54, sp38);
|
||||
|
||||
// @recomp Assign an ID to the text and align it to the left or the right side of the screen.
|
||||
bool left_alignment = arg1->unk38 < (gFramebufferWidth * 1.0f / 3.0f);
|
||||
cur_pushed_text_transform_id = HUD_SCORE2_TRANSFORM_PRINT_ID_START + item_id * HUD_SCORE2_TRANSFORM_PRINT_ID_COUNT;
|
||||
cur_pushed_text_transform_origin = left_alignment ? G_EX_ORIGIN_LEFT : G_EX_ORIGIN_RIGHT;
|
||||
|
||||
// @recomp Keep track of the last item value. If the value has changed, skip vertex interpolation this frame.
|
||||
if (itemPrint_lastValues[item_id] != sp38) {
|
||||
cur_pushed_text_transform_skip_interpolation = TRUE;
|
||||
itemPrint_lastValues[item_id] = sp38;
|
||||
}
|
||||
|
||||
//print text (blue egg font)
|
||||
print_bold_spaced(
|
||||
(s32)(func_802FB0DC(arg1) + arg1->unk38 + arg1->unk44 + sp34),
|
||||
(s32)(func_802FB0E4(arg1) * arg1->unk4C + (arg1->unk3C + arg1->unk48)),
|
||||
arg1->string_54
|
||||
);
|
||||
|
||||
// @recomp Clear the ID and alignment for the text.
|
||||
cur_pushed_text_transform_id = 0;
|
||||
cur_pushed_text_transform_origin = G_EX_ORIGIN_NONE;
|
||||
cur_pushed_text_transform_skip_interpolation = FALSE;
|
||||
|
||||
// @recomp Align the score element to either the left or the right side of the screen.
|
||||
// NOTE: gScissorBoxRight/gScissorBoxTop are incorrectly named in the decompilation and must be swapped.
|
||||
gEXPushScissor((*gfx)++);
|
||||
gEXSetScissor((*gfx)++, G_SC_NON_INTERLACE, G_EX_ORIGIN_LEFT, G_EX_ORIGIN_RIGHT, 0, gScissorBoxRight, 0, gScissorBoxBottom);
|
||||
gEXSetViewportAlign((*gfx)++, left_alignment ? G_EX_ORIGIN_LEFT : G_EX_ORIGIN_RIGHT, left_alignment ? 0 : gScissorBoxTop * -4, 0);
|
||||
|
||||
// @recomp Assign a matrix group to the score element.
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, HUD_SCORE2_TRANSFORM_ID_START + item_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
//draw sprite?
|
||||
func_802FD360(arg1, gfx, mtx, vtx);
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_NONE, 0, 0);
|
||||
gEXPopScissor((*gfx)++);
|
||||
}
|
||||
|
||||
#define RM_DEPTH_SET(clk) \
|
||||
Z_UPD | CVG_DST_FULL | ALPHA_CVG_SEL | FORCE_BL | G_ZS_PRIM | \
|
||||
ZMODE_OPA | \
|
||||
GBL_c##clk(G_BL_CLR_BL, G_BL_0, G_BL_CLR_MEM, G_BL_1MA)
|
||||
|
||||
// @recomp Tag the matrices for any model using this score type.
|
||||
RECOMP_PATCH void fxcommon3score_draw(enum item_e item_id, void *arg1, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
Struct_core2_79830_0 *a1 = (Struct_core2_79830_0 *)arg1;
|
||||
f32 sp68[3];
|
||||
f32 sp5C[3];
|
||||
f32 sp50[3];
|
||||
f32 sp44[3];
|
||||
f32 sp40;
|
||||
f32 sp3C;
|
||||
|
||||
sp40 = func_802FB0E4(arg1) * a1->unk54 + a1->unk34;
|
||||
if (a1->model != NULL && func_802FB0D4(arg1)) {
|
||||
a1->value_string[0] = '\0';
|
||||
strIToA(a1->value_string, itemPrint_getValue(item_id));
|
||||
|
||||
// @recomp Align the score element's text to the right or use its default alignment.
|
||||
bool aligned_to_the_right = a1->unk30 > (gFramebufferWidth * 2 / 3);
|
||||
cur_pushed_text_transform_id = HUD_SCORE3_TRANSFORM_PRINT_ID_START + item_id * HUD_SCORE3_TRANSFORM_PRINT_ID_COUNT;
|
||||
cur_pushed_text_transform_origin = aligned_to_the_right ? G_EX_ORIGIN_RIGHT : G_EX_ORIGIN_NONE;
|
||||
|
||||
// @recomp Keep track of the last item value. If the value has changed, skip vertex interpolation this frame.
|
||||
if (itemPrint_lastValues[item_id] != itemPrint_getValue(item_id)) {
|
||||
cur_pushed_text_transform_skip_interpolation = TRUE;
|
||||
itemPrint_lastValues[item_id] = itemPrint_getValue(item_id);
|
||||
}
|
||||
|
||||
print_bold_spaced(a1->unk30 + a1->unk40, sp40 + a1->unk44, a1->value_string);
|
||||
|
||||
// @recomp Clear the ID and alignment for the text.
|
||||
cur_pushed_text_transform_id = 0;
|
||||
cur_pushed_text_transform_origin = G_EX_ORIGIN_NONE;
|
||||
cur_pushed_text_transform_skip_interpolation = FALSE;
|
||||
|
||||
sp3C = viewport_transformCoordinate(a1->unk30, sp40, sp5C, sp68);
|
||||
|
||||
sp44[0] = 0.0f;
|
||||
sp44[1] = a1->unk38;
|
||||
sp44[2] = 0.0f;
|
||||
|
||||
sp50[0] = 0.0f;
|
||||
sp50[1] = a1->unk68;
|
||||
sp50[2] = 0.0f;
|
||||
func_8033A308(sp50);
|
||||
if (getGameMode() != GAME_MODE_4_PAUSED) {
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL);
|
||||
}
|
||||
sp68[0] += a1->unk4C;
|
||||
if (a1->unk6C == 0.0f) {
|
||||
a1->unk6C = 1.1 * (vtxList_getGlobalNorm(model_getVtxList(a1->model)) * a1->unk3C);
|
||||
}
|
||||
|
||||
if (a1->anim_ctrl != NULL) {
|
||||
anctrl_drawSetup(a1->anim_ctrl, sp5C, 1);
|
||||
}
|
||||
|
||||
// @recomp If necessary, align the score element to the right of the screen.
|
||||
// NOTE: gScissorBoxRight/gScissorBoxTop are incorrectly named in the decompilation and must be swapped.
|
||||
if (aligned_to_the_right) {
|
||||
gEXPushScissor((*gfx)++);
|
||||
gEXSetScissor((*gfx)++, G_SC_NON_INTERLACE, G_EX_ORIGIN_RIGHT, G_EX_ORIGIN_RIGHT, gScissorBoxLeft - gScissorBoxTop, gScissorBoxRight, 0, gScissorBoxBottom);
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_RIGHT, gScissorBoxTop * -4, 0);
|
||||
}
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
|
||||
// @recomp Draw a rectangle that clears the depth and gets interpolated along with the 3D model.
|
||||
// This fixes an issue where the rectangle would teleport ahead of the movement of the model in HFR
|
||||
// and it also provides a minor performance boost by skipping the need to switch render targets.
|
||||
if (getGameMode() != GAME_MODE_4_PAUSED) {
|
||||
u32 depth_rect_transform_id = HUD_SCORE3_DEPTH_RECT_TRANSFORM_ID_START + item_id;
|
||||
guMtxIdent(*mtx);
|
||||
gSPMatrix((*gfx)++, OS_K0_TO_PHYSICAL((*mtx)++), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gEXMatrixGroupSimpleVerts((*gfx)++, depth_rect_transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
f32 x = a1->unk30 - a1->unk6C;
|
||||
f32 y = sp40 - a1->unk6C;
|
||||
f32 w = 2 * a1->unk6C;
|
||||
f32 h = 2 * a1->unk6C;
|
||||
gSPVertex((*gfx)++, *vtx, 4, 0);
|
||||
|
||||
f32 vpos[3];
|
||||
f32 vrot[3];
|
||||
for (u32 v_y = 0; v_y < 2; v_y++) {
|
||||
for (u32 v_x = 0; v_x < 2; v_x++) {
|
||||
viewport_transformCoordinate(x + (w * v_x), y + (h * v_y), vpos, vrot);
|
||||
(*vtx)->v.ob[0] = vpos[0];
|
||||
(*vtx)->v.ob[1] = vpos[1];
|
||||
(*vtx)->v.ob[2] = vpos[2];
|
||||
(*vtx)++;
|
||||
}
|
||||
}
|
||||
|
||||
gEXPushOtherMode((*gfx)++);
|
||||
gEXPushCombineMode((*gfx)++);
|
||||
gDPSetRenderMode((*gfx)++, RM_DEPTH_SET(1), RM_DEPTH_SET(2));
|
||||
gDPSetCycleType((*gfx)++, G_CYC_1CYCLE);
|
||||
gDPSetCombineLERP((*gfx)++, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
gDPSetPrimDepth((*gfx)++, 0xFFFF, 0xFFFF);
|
||||
gSP1Quadrangle((*gfx)++, 0, 1, 3, 2, 0);
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
gEXPopOtherMode((*gfx)++);
|
||||
gEXPopCombineMode((*gfx)++);
|
||||
}
|
||||
|
||||
// @recomp Set the skinning data for this score.
|
||||
if (item_id < ITEM_2B_UNKNOWN) {
|
||||
bkrecomp_setup_custom_skinning(&sScore3SkinningData[item_id], a1->model_id);
|
||||
}
|
||||
|
||||
// @recomp Set the model transform ID.
|
||||
cur_drawn_model_transform_id = HUD_SCORE3_TRANSFORM_ID_START + item_id * MARKER_TRANSFORM_ID_COUNT;
|
||||
|
||||
modelRender_draw(gfx, mtx, sp5C, sp68, a1->unk3C * sp3C, sp44, a1->model);
|
||||
|
||||
// @recomp Clear the model transform ID.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
|
||||
if (aligned_to_the_right) {
|
||||
// @recomp Clear the matrix group.
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_NONE, 0, 0);
|
||||
gEXPopScissor((*gfx)++);
|
||||
}
|
||||
}//L80300BA4
|
||||
}
|
||||
|
||||
// @recomp: Patched to interpolate the header of the totals screen on the pause menu.
|
||||
RECOMP_PATCH void gcpausemenu_printTotalsHeader(s32 page_id) {
|
||||
// @recomp Assign an ID for the totals text.
|
||||
cur_pushed_text_transform_id = HUD_TOTALS_PRINT_TRANSFORM_ID_START;
|
||||
|
||||
struct1Cs_1 *v0 = D_8036C58C + page_id;
|
||||
print_bold_overlapping(v0->x, D_80383010.unk8, -1.05f, v0->string);
|
||||
|
||||
// @recomp Clear the ID text.
|
||||
cur_pushed_text_transform_id = 0;
|
||||
}
|
||||
@@ -1,42 +1,21 @@
|
||||
#include "patches.h"
|
||||
#include "note_saving.h"
|
||||
#include "transform_ids.h"
|
||||
#include "bk_api.h"
|
||||
#include "misc_funcs.h"
|
||||
|
||||
#include "core1/core1.h"
|
||||
#include "core1/main.h"
|
||||
#include "core1/vimgr.h"
|
||||
|
||||
RECOMP_DECLARE_EVENT(recomp_on_init());
|
||||
|
||||
void recomp_init_vertex_skinning(void);
|
||||
|
||||
// @recomp Patched to perform some initialization after core2 has been loaded.
|
||||
RECOMP_PATCH void dummy_func_8025AFB0(void) {
|
||||
// @recomp Initialize note saving data before the init event is run.
|
||||
// This will allow mods to override it as necessary.
|
||||
init_note_saving();
|
||||
|
||||
// @recomp Perform the necessary initialization for vertex skinning.
|
||||
recomp_init_vertex_skinning();
|
||||
void core1_init();
|
||||
void sns_write_payload_over_heap();
|
||||
void mainLoop();
|
||||
|
||||
RECOMP_PATCH void mainThread_entry(void *arg) {
|
||||
// @recomp Register actor extension data and call the init event.
|
||||
recomp_on_init();
|
||||
|
||||
// @recomp Calculate the note start indices for each map after the init event.
|
||||
// This allows the start indices to account for any changes made by mods.
|
||||
calculate_map_start_note_indices();
|
||||
core1_init();
|
||||
sns_write_payload_over_heap();
|
||||
|
||||
while (1) {
|
||||
mainLoop();
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
|
||||
RECOMP_PATCH enum map_e getDefaultBootMap(void) {
|
||||
return MAP_95_CS_END_ALL_100;
|
||||
}
|
||||
|
||||
RECOMP_PATCH int ability_hasLearned(enum ability_e ability) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -20,12 +20,9 @@ extern RecompAimingOverideMode recomp_aiming_override_mode;
|
||||
DECLARE_FUNC(void, recomp_get_gyro_deltas, float* x, float* y);
|
||||
DECLARE_FUNC(void, recomp_get_mouse_deltas, float* x, float* y);
|
||||
DECLARE_FUNC(void, recomp_get_inverted_axes, s32* x, s32* y);
|
||||
DECLARE_FUNC(u32, recomp_get_analog_cam_sensitivity);
|
||||
DECLARE_FUNC(s32, recomp_get_analog_cam_enabled);
|
||||
DECLARE_FUNC(void, recomp_get_analog_inverted_axes, s32* x, s32* y);
|
||||
DECLARE_FUNC(void, recomp_get_flying_and_swimming_inverted_axes, s32* x, s32* y);
|
||||
DECLARE_FUNC(void, recomp_get_first_person_inverted_axes, s32* x, s32* y);
|
||||
DECLARE_FUNC(void, recomp_get_right_analog_inputs, float* x, float* y);
|
||||
DECLARE_FUNC(void, recomp_get_camera_inputs, float* x, float* y);
|
||||
DECLARE_FUNC(void, recomp_set_right_analog_suppressed, s32 suppressed);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "misc_funcs.h"
|
||||
#include "functions.h"
|
||||
#include "bk_api.h"
|
||||
#include "object_extension_funcs.h"
|
||||
#include "note_saving.h"
|
||||
|
||||
extern ActorMarker *D_8036E7C8;
|
||||
extern u8 D_80383428[0x1C];
|
||||
|
||||
typedef struct {
|
||||
s16 map_id; //enum map_e
|
||||
s16 opa_model_id; //enum asset_e level_model_id
|
||||
s16 xlu_model_id; //enum asset_e level2_model_id
|
||||
s16 unk6[3]; // min bounds (for cubes?)
|
||||
s16 unkC[3]; // max bounds (for cubes?)
|
||||
// u8 pad12[0x2];
|
||||
f32 scale;
|
||||
}MapModelDescription;
|
||||
|
||||
extern struct {
|
||||
void *unk0;
|
||||
void *unk4;
|
||||
BKCollisionList *collision_opa;
|
||||
BKCollisionList *collision_xlu;
|
||||
BKModel *model_opa;
|
||||
BKModel *model_xlu;
|
||||
BKModelBin *model_bin_opa;
|
||||
BKModelBin *model_bin_xlu;
|
||||
s32 unk20;
|
||||
struct5Bs *unk24;
|
||||
MapModelDescription *description;
|
||||
u8 env_red;
|
||||
u8 env_green;
|
||||
u8 env_blue;
|
||||
f32 scale;
|
||||
}mapModel;
|
||||
|
||||
BKGfxList *model_getDisplayList(BKModelBin *arg0);
|
||||
|
||||
|
||||
#define INTRO_OPA_DL_LENGTH 97
|
||||
#define INTRO_OPA_DL_GRASS_PATCH_INDEX 63
|
||||
#define INTRO_OPA_DL_WALL_PATCH_INDEX 84
|
||||
#define INTRO_OPA_DL_HASH 0xA912614C535FA0BBULL
|
||||
|
||||
Vtx intro_grass_extension_verts[3] = {
|
||||
{{ {-1262, 20, 1040}, 0, {230, 538}, {51, 190, 133, 255} }},
|
||||
{{ {-10, 20, 5107}, 0, {3124, -10067}, {0, 13, 169, 255} }},
|
||||
{{ {-10, 20, 1372}, 0, {3376, -195}, {51, 190, 133, 255} }},
|
||||
};
|
||||
|
||||
Gfx intro_grass_extension_dl[] = {
|
||||
// Copy of the replaced command.
|
||||
gsSP1Triangle(31, 28, 29, 0),
|
||||
// New commands.
|
||||
gsSPVertex(intro_grass_extension_verts + 0, 3, 0),
|
||||
gsSP1Triangle(0, 1, 2, 0),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
||||
Vtx intro_wall_extension_verts[4] = {
|
||||
{{ {-1262, 20, 1040}, 0, {-15, 49}, {51, 190, 133, 255} }},
|
||||
{{ {-1262, 1004, 1040}, 0, {-44, 1966}, {255, 255, 255, 255} }},
|
||||
{{ {189, 1004, 4315}, 0, {-7400, 1817}, {255, 255, 255, 255} }},
|
||||
{{ {189, 20, 4315}, 0, {-7371, -100}, {51, 190, 133, 255} }},
|
||||
};
|
||||
|
||||
Gfx intro_wall_extension_dl[] = {
|
||||
// Copy of the replaced command.
|
||||
gsSP1Triangle(22, 24, 21, 0),
|
||||
// New commands.
|
||||
gsSPVertex(intro_wall_extension_verts + 0, 4, 0),
|
||||
gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
||||
void hotpatch_intro_opa_map_model(BKModelBin* model_bin) {
|
||||
BKGfxList *gfx_list = model_getDisplayList(model_bin);
|
||||
Gfx* dl = &gfx_list->list[0];
|
||||
|
||||
// Hash the displaylist of the model to make sure it's unmodified. This will prevent the hotpatch from
|
||||
// affecting mods.
|
||||
u64 hash = recomp_xxh3(dl, INTRO_OPA_DL_LENGTH * sizeof(Gfx));
|
||||
if (hash != INTRO_OPA_DL_HASH) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Patch a call to the new displaylist after the grass material.
|
||||
gSPDisplayList(&dl[INTRO_OPA_DL_GRASS_PATCH_INDEX], intro_grass_extension_dl);
|
||||
|
||||
// Patch a call to the new displaylist after the wall material.
|
||||
gSPDisplayList(&dl[INTRO_OPA_DL_WALL_PATCH_INDEX], intro_wall_extension_dl);
|
||||
}
|
||||
|
||||
void reset_cutscene_timings_state(void);
|
||||
|
||||
// @recomp Patched to act as a point to run code when a new map is loaded.
|
||||
// This includes:
|
||||
// * Resetting all extended marker data and skip interpolation for the next frame.
|
||||
// * Hotpatching the map model for the title cutscene to fix ultrawide effects.
|
||||
// * Resetting the spawned static note count.
|
||||
// * Resetting the variables used to keep track of correcting the intro cutscene timings
|
||||
RECOMP_PATCH void func_803329AC(void){
|
||||
s32 i;
|
||||
|
||||
D_8036E7C8 = (ActorMarker *)malloc(0xE0*sizeof(ActorMarker));
|
||||
|
||||
for( i = 0; i < 0x1C; i++){
|
||||
D_80383428[i] = 0;
|
||||
}
|
||||
|
||||
for(i =0; i<0xE0; i++){
|
||||
D_8036E7C8[i].unk5C = 0;
|
||||
}
|
||||
|
||||
// @recomp Run any new code on map load.
|
||||
|
||||
// @recomp If the current map's model is ASSET_149D_MODEL_CS_START_NINTENDO_OPA,
|
||||
// hotpatch it to fill in some regions for widescreen.
|
||||
if (mapModel.description->opa_model_id == ASSET_149D_MODEL_CS_START_NINTENDO_OPA) {
|
||||
hotpatch_intro_opa_map_model(mapModel.model_bin_opa);
|
||||
}
|
||||
|
||||
// @recomp Reset all actor data and skip interpolation for the next frame.
|
||||
// Interpolation is skipped as the next frame will potentially reuse IDs from the previous frame,
|
||||
// as the marker ID tracking gets reset here.
|
||||
recomp_clear_all_object_data(EXTENSION_TYPE_MARKER);
|
||||
set_all_interpolation_skipped(TRUE);
|
||||
|
||||
// @recomp Run note saving map load code.
|
||||
note_saving_on_map_load();
|
||||
|
||||
// @recomp Reset the intro cutscene timing corrections so the cutscene can be played again
|
||||
reset_cutscene_timings_state();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "core1/mlmtx.h"
|
||||
|
||||
typedef struct {
|
||||
s32 cmd_0;
|
||||
s32 size_4;
|
||||
f32 max_8;
|
||||
f32 min_C;
|
||||
f32 unk10[3];
|
||||
s32 subgeo_offset_1C;
|
||||
}GeoCmd8;
|
||||
|
||||
extern f32 D_80383C98[3];
|
||||
extern void func_80339124(Gfx **gfx, Mtx **mtx, BKGeoList *geo_list);
|
||||
extern float gu_sqrtf(float val);
|
||||
|
||||
// @recomp Patched to force all LODs to act as if they were a fixed distance from the camera.
|
||||
RECOMP_PATCH void func_80338B50(Gfx **gfx, Mtx **mtx, void *arg2) {
|
||||
GeoCmd8 *cmd = (GeoCmd8 *)arg2;
|
||||
f32 dist;
|
||||
|
||||
if (cmd->subgeo_offset_1C) {
|
||||
mlMtx_apply_vec3f(D_80383C98, cmd->unk10);
|
||||
// @recomp Force distance for LOD to be 50.
|
||||
dist = 50.0f; //gu_sqrtf(D_80383C98[0] * D_80383C98[0] + D_80383C98[1] * D_80383C98[1] + D_80383C98[2] * D_80383C98[2]);
|
||||
if (cmd->min_C < dist && dist <= cmd->max_8) {
|
||||
func_80339124(gfx, mtx, (BKGeoList *)((s32)cmd + cmd->subgeo_offset_1C));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,398 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
#include "core2/anctrl.h"
|
||||
#include "core2/modelRender.h"
|
||||
|
||||
typedef struct struct_1D_s {
|
||||
BKModel *model;
|
||||
s16 unk4;
|
||||
u8 xform_id;
|
||||
// u8 pad7[1];
|
||||
Struct70s unk8;//union of subtypes
|
||||
}struct1Ds;
|
||||
|
||||
extern struct {
|
||||
u8 unk0;
|
||||
vector(struct1Ds) *unk4;
|
||||
} D_80386140;
|
||||
|
||||
typedef struct struct_1E_s {
|
||||
void (*unk0)(void *arg0, s32 arg1, s32 arg2, s32 arg3);
|
||||
void (*unk4)(void *arg0, s32 arg1, s32 arg2);
|
||||
void (*unk8)(void *arg0);
|
||||
}struct1Es;
|
||||
|
||||
extern struct1Es D_80372030[];
|
||||
|
||||
s32 func_80320708(void);
|
||||
s32 levelSpecificFlags_validateCRC2(void);
|
||||
s32 dummy_func_80320248(void);
|
||||
enum asset_e mapModel_getOpaModelId(void);
|
||||
enum map_e map_get(void);
|
||||
s32 mapSpecificFlags_get(s32 i);
|
||||
s32 levelSpecificFlags_get(s32 i);
|
||||
u32 jiggyscore_isCollected(enum jiggy_e);
|
||||
enum bsgroup_e player_movementGroup(void);
|
||||
bool jigsawPicture_isJigsawPictureComplete(s32 world);
|
||||
bool fileProgressFlag_get(enum file_progress_e index);
|
||||
void modelRender_setAnimatedTexturesCacheId(s32 arg0);
|
||||
bool mapModel_has_xlu_bin(void);
|
||||
void func_802F7BC0(Gfx **, Mtx **, Vtx **);
|
||||
void func_8034E660(s32 arg0, BKVtxRef *src, Vtx *dst, s32 arg3);
|
||||
void func_8034EC50(s32 arg0, BKVtxRef* ref, Vtx* dst, s32 arg3);
|
||||
void BKModel_transformMesh(BKModel *model, s32 mesh_id, void (*fn)(s32, BKVtxRef *, Vtx *, s32), s32 arg3);
|
||||
|
||||
void recomp_setup_map_skinning(int map_model_id, float *pos_floats);
|
||||
void recomp_clear_map_skinning();
|
||||
|
||||
typedef struct {
|
||||
s16 map_id; //enum map_e
|
||||
s16 opa_model_id; //enum asset_e level_model_id
|
||||
s16 xlu_model_id; //enum asset_e level2_model_id
|
||||
s16 unk6[3]; // min bounds (for cubes?)
|
||||
s16 unkC[3]; // max bounds (for cubes?)
|
||||
// u8 pad12[0x2];
|
||||
f32 scale;
|
||||
}MapModelDescription;
|
||||
|
||||
extern struct {
|
||||
s32 unk0; // Changed from void* in the decomp
|
||||
s32 unk4; // Changed from void* in the decomp
|
||||
BKCollisionList *collision_opa;
|
||||
BKCollisionList *collision_xlu;
|
||||
BKModel *model_opa;
|
||||
BKModel *model_xlu;
|
||||
BKModelBin *model_bin_opa;
|
||||
BKModelBin *model_bin_xlu;
|
||||
s32 unk20;
|
||||
struct5Bs *unk24;
|
||||
MapModelDescription *description;
|
||||
u8 env_red;
|
||||
u8 env_green;
|
||||
u8 env_blue;
|
||||
f32 scale;
|
||||
}mapModel;
|
||||
|
||||
// @recomp Patched to set the transform ID when drawing the map's opaque model.
|
||||
RECOMP_PATCH void mapModel_opa_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
s32 temp_a0;
|
||||
|
||||
if (func_80320708() && levelSpecificFlags_validateCRC2() && dummy_func_80320248()) {
|
||||
if (mapModel_getOpaModelId() == ASSET_14CF_MODEL_SM_SPIRAL_MOUNTAIN_OPA) {
|
||||
func_8033A45C(1, 0);
|
||||
func_8033A45C(2, 1);
|
||||
}
|
||||
switch (map_get()) { /* irregular */
|
||||
case MAP_88_CS_SPIRAL_MOUNTAIN_6:
|
||||
if (mapSpecificFlags_get(0) != 0) {
|
||||
func_8033A45C(1, 1);
|
||||
func_8033A45C(2, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case MAP_12_GV_GOBIS_VALLEY:
|
||||
func_8033A45C(1, levelSpecificFlags_get(LEVEL_FLAG_6_GV_UNKNOWN) ? 1 : 0);
|
||||
func_8033A45C(2, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 0 : 1);
|
||||
func_8033A45C(5, jiggyscore_isCollected(JIGGY_42_GV_WATER_PYRAMID) ? 1 : 0);
|
||||
break;
|
||||
|
||||
case MAP_14_GV_SANDYBUTTS_MAZE:
|
||||
func_8033A45C(5, (player_movementGroup() == BSGROUP_4_LOOK) ? 1 : 0);
|
||||
break;
|
||||
|
||||
case MAP_E_MM_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 1);
|
||||
func_8033A45C(5, 1);
|
||||
break;
|
||||
|
||||
case MAP_47_BGS_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 2);
|
||||
func_8033A45C(5, 2);
|
||||
break;
|
||||
|
||||
case MAP_48_FP_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 3);
|
||||
func_8033A45C(5, 3);
|
||||
break;
|
||||
|
||||
case MAP_30_MMM_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 4);
|
||||
func_8033A45C(5, 4);
|
||||
break;
|
||||
|
||||
case MAP_4A_CCW_SPRING_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 5);
|
||||
func_8033A45C(5, 5);
|
||||
break;
|
||||
case MAP_4B_CCW_SUMMER_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 6);
|
||||
func_8033A45C(5, 6);
|
||||
break;
|
||||
case MAP_4C_CCW_AUTUMN_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 7);
|
||||
func_8033A45C(5, 7);
|
||||
break;
|
||||
case MAP_4D_CCW_WINTER_MUMBOS_SKULL:
|
||||
func_8033A45C(1, 8);
|
||||
func_8033A45C(5, 8);
|
||||
break;
|
||||
case MAP_5E_CCW_SPRING_NABNUTS_HOUSE:
|
||||
case MAP_5F_CCW_SUMMER_NABNUTS_HOUSE:
|
||||
case MAP_60_CCW_AUTUMN_NABNUTS_HOUSE:
|
||||
func_8033A45C(1, 1);
|
||||
func_8033A45C(2, 0);
|
||||
break;
|
||||
case MAP_61_CCW_WINTER_NABNUTS_HOUSE:
|
||||
func_8033A45C(1, 0);
|
||||
func_8033A45C(2, 1);
|
||||
break;
|
||||
case MAP_1D_MMM_CELLAR:
|
||||
func_8033A45C(1, actorArray_findActorFromActorId(0x191) ? 0 : 1);
|
||||
break;
|
||||
case MAP_7C_CS_INTRO_BANJOS_HOUSE_1:
|
||||
case MAP_89_CS_INTRO_BANJOS_HOUSE_2:
|
||||
case MAP_8A_CS_INTRO_BANJOS_HOUSE_3:
|
||||
case MAP_8C_SM_BANJOS_HOUSE:
|
||||
case MAP_91_FILE_SELECT:
|
||||
func_8033A45C(5, 1);
|
||||
break;
|
||||
case MAP_7B_CS_INTRO_GL_DINGPOT_1:
|
||||
case MAP_81_CS_INTRO_GL_DINGPOT_2:
|
||||
func_8033A45C(4, 0);
|
||||
func_8033A45C(5, 0);
|
||||
func_8033A45C(6, 0);
|
||||
break;
|
||||
case MAP_82_CS_ENTERING_GL_MACHINE_ROOM:
|
||||
case MAP_83_CS_GAME_OVER_MACHINE_ROOM:
|
||||
case MAP_84_CS_UNUSED_MACHINE_ROOM:
|
||||
func_8033A45C(4, 1);
|
||||
func_8033A45C(5, 1);
|
||||
func_8033A45C(6, 1);
|
||||
break;
|
||||
case MAP_93_GL_DINGPOT:
|
||||
func_8033A45C(4, 1);
|
||||
func_8033A45C(5, 1);
|
||||
func_8033A45C(6, (jigsawPicture_isJigsawPictureComplete(0xA) || fileProgressFlag_get(FILEPROG_E2_DOOR_OF_GRUNTY_OPEN) || volatileFlag_get(VOLATILE_FLAG_C1_IN_FINAL_CHARACTER_PARADE)));
|
||||
break;
|
||||
}
|
||||
func_8033A450(mapModel.unk24);
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL);
|
||||
temp_a0 = mapModel.unk0;
|
||||
if (temp_a0 != 0) {
|
||||
modelRender_setAnimatedTexturesCacheId(temp_a0);
|
||||
}
|
||||
modelRender_setEnvColor(mapModel.env_red, mapModel.env_green, mapModel.env_blue, 0xFF);
|
||||
|
||||
// @recomp Set the map opaque model transform id.
|
||||
cur_drawn_model_is_map = TRUE;
|
||||
cur_drawn_model_transform_id = MAP_MODEL_OPA_TRANSFORM_ID_START;
|
||||
|
||||
modelRender_draw(gfx, mtx, NULL, NULL, mapModel.description->scale, NULL, mapModel.model_bin_opa);
|
||||
|
||||
// @recomp Clear the current model transform id after drawing.
|
||||
cur_drawn_model_is_map = FALSE;
|
||||
cur_drawn_model_transform_id = 0;
|
||||
|
||||
if (!mapModel_has_xlu_bin()) {
|
||||
func_802F7BC0(gfx, mtx, vtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Reserve a static amount of memory to be used for storing the current modifications to the map model with higher precision floats.
|
||||
#define MAP_MODEL_XLU_VERTEX_COUNT_MAX 0x400
|
||||
f32 map_model_xlu_pos_floats[MAP_MODEL_XLU_VERTEX_COUNT_MAX * 3];
|
||||
u32 map_model_xlu_pos_floats_count = 0;
|
||||
|
||||
void recomp_reset_map_model_skinning() {
|
||||
map_model_xlu_pos_floats_count = 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to store the moved water vertices with higher precision floats for TTC.
|
||||
RECOMP_PATCH void func_8034E8E4(Struct73s *arg0, BKModel *arg1, s32 arg2) {
|
||||
f32 sp3C;
|
||||
f32 sp38;
|
||||
f32 sp30[2];
|
||||
f32 sin;
|
||||
f32 cos;
|
||||
f32 sp2C;
|
||||
f32 sp28;
|
||||
|
||||
sp38 = time_getDelta();
|
||||
arg0->unk4 += sp38;
|
||||
cos = cosf(arg0->unk4 * 0.2 * BAD_PI);
|
||||
sin = sinf(arg0->unk4 * 0.08 * BAD_PI);
|
||||
sp30[0] = (sin * 100.0f + 150.0f * cos) * 0.8;
|
||||
|
||||
|
||||
cos = sinf(arg0->unk4 * 0.5 * BAD_PI);
|
||||
sin = cosf(arg0->unk4 * 0.22 * BAD_PI);
|
||||
sp30[1] = (sin * 100.0f + 50.0f * cos) * 0.8;
|
||||
|
||||
arg0->d_tc[0] = (sp30[0] >= 0.0) ? sp30[0] + 0.5 : sp30[0] - 0.5;
|
||||
arg0->d_tc[1] = (sp30[1] >= 0.0) ? sp30[1] + 0.5 : sp30[1] - 0.5;
|
||||
|
||||
cos = cosf(arg0->unk4 * 0.5 * BAD_PI);
|
||||
sin = sinf(arg0->unk4 * 0.11 * BAD_PI);
|
||||
sp2C = sin * (arg0->unk8 * 0.25) + (arg0->unk8 * 0.75) * cos;
|
||||
|
||||
if (arg0->unk14 < arg0->unk1C) {
|
||||
arg0->unk18 = arg0->unk14;
|
||||
arg0->unk14 += sp38;
|
||||
if (arg0->unk1C < arg0->unk14) {
|
||||
arg0->unk14 = arg0->unk1C;
|
||||
}
|
||||
}
|
||||
sp28 = ((arg0->unk14 < arg0->unk1C) ? arg0->unkC + ((arg0->unk14 / arg0->unk1C) * (arg0->unkE - arg0->unkC)) : arg0->unkE);
|
||||
sp28 += sp2C;
|
||||
arg0->dy = (sp28 >= 0.0) ? sp28 + 0.5 : sp28 - 0.5;
|
||||
BKModel_transformMesh(arg1, arg2, func_8034E660, (s32)arg0);
|
||||
|
||||
// @recomp Don't use high precision floats if the model exceeds the bounds of the floats array, in case the model was modified.
|
||||
if (arg1->vtxList_4->count <= MAP_MODEL_XLU_VERTEX_COUNT_MAX) {
|
||||
// @recomp Make sure to copy all the vertices from the model to the higher precision floats at least once per frame.
|
||||
s32 i, j = 0;
|
||||
if (map_model_xlu_pos_floats_count < arg1->vtxList_4->count) {
|
||||
Vtx *vtx = vtxList_getVertices(arg1->vtxList_4);
|
||||
for (i = 0; i < arg1->vtxList_4->count; i++) {
|
||||
map_model_xlu_pos_floats[j++] = vtx->v.ob[0];
|
||||
map_model_xlu_pos_floats[j++] = vtx->v.ob[1];
|
||||
map_model_xlu_pos_floats[j++] = vtx->v.ob[2];
|
||||
vtx++;
|
||||
}
|
||||
|
||||
map_model_xlu_pos_floats_count = arg1->vtxList_4->count;
|
||||
}
|
||||
|
||||
// @recomp Run the logic of BKModel_transformMesh again with only the modification of the Y component as seen in func_8034E660.
|
||||
// The result is stored in the higher precision floats instead of the model binary itself. The original value of dy is used
|
||||
// before it's rounded to make the animation smoother.
|
||||
BKMesh *iMesh = (BKMesh *)(arg1 + 1);
|
||||
BKVtxRef *iVtx;
|
||||
BKVtxRef *start_vtx_ref;
|
||||
BKVtxRef *end_vtx_ref;
|
||||
for (i = 0; i < arg1->meshList_0->meshCount_0; i++) {
|
||||
if (arg2 == iMesh->uid_0) {
|
||||
start_vtx_ref = (BKVtxRef *)(iMesh + 1);
|
||||
end_vtx_ref = start_vtx_ref + iMesh->vtxCount_2;
|
||||
for (iVtx = start_vtx_ref; iVtx < end_vtx_ref; iVtx++) {
|
||||
j = iVtx->unk10 * 3;
|
||||
map_model_xlu_pos_floats[j + 0] = iVtx->v.v.ob[0];
|
||||
map_model_xlu_pos_floats[j + 1] = iVtx->v.v.ob[1] + sp28;
|
||||
map_model_xlu_pos_floats[j + 2] = iVtx->v.v.ob[2];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
iMesh = (BKMesh *)(((BKVtxRef *)(iMesh + 1)) + iMesh->vtxCount_2);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to store the moved water vertices with higher precision floats for the ending cutscene.
|
||||
RECOMP_PATCH void func_8034EF60(Struct77s* arg0, BKModel* arg1, s32 arg2) {
|
||||
f32 temp_f0;
|
||||
f32 sp2C[2];
|
||||
|
||||
temp_f0 = time_getDelta();
|
||||
arg0->unk2C += temp_f0;
|
||||
arg0->unk4 += temp_f0 * arg0->unk0 * 3;
|
||||
arg0->unk8 += temp_f0 * (arg0->unk0 + 0.01) * 3;
|
||||
sp2C[0] = ((150.0f * cosf(arg0->unk2C * 0.2 * BAD_PI)) + (sinf(arg0->unk2C * 0.08 * BAD_PI) * 100.0f)) * 0.8;
|
||||
sp2C[1] = ((50.0f * sinf(arg0->unk2C * 0.5 * BAD_PI)) + (cosf(arg0->unk2C * 0.22 * BAD_PI) * 100.0f)) * 0.8;
|
||||
arg0->unk28[0] = (sp2C[0] >= 0.0) ? (sp2C[0] + 0.5) : (sp2C[0] - 0.5);
|
||||
arg0->unk28[1] = (sp2C[1] >= 0.0) ? (sp2C[1] + 0.5) : (sp2C[1] - 0.5);
|
||||
BKModel_transformMesh(arg1, arg2, &func_8034EC50, (s32)arg0);
|
||||
|
||||
// @recomp Don't use high precision floats if the model exceeds the bounds of the floats array, in case the model was modified.
|
||||
if (arg1->vtxList_4->count <= MAP_MODEL_XLU_VERTEX_COUNT_MAX) {
|
||||
// @recomp Make sure to copy all the vertices from the model to the higher precision floats at least once per frame.
|
||||
s32 i, j = 0;
|
||||
if (map_model_xlu_pos_floats_count < arg1->vtxList_4->count) {
|
||||
Vtx* vtx = vtxList_getVertices(arg1->vtxList_4);
|
||||
for (i = 0; i < arg1->vtxList_4->count; i++) {
|
||||
map_model_xlu_pos_floats[j++] = vtx->v.ob[0];
|
||||
map_model_xlu_pos_floats[j++] = vtx->v.ob[1];
|
||||
map_model_xlu_pos_floats[j++] = vtx->v.ob[2];
|
||||
vtx++;
|
||||
}
|
||||
|
||||
map_model_xlu_pos_floats_count = arg1->vtxList_4->count;
|
||||
}
|
||||
|
||||
// @recomp Run the logic of BKModel_transformMesh again with only the modification of the Y component as seen in func_8034EC50.
|
||||
// The result is stored in the higher precision floats instead of the model binary itself. The original value of dy is used
|
||||
// before it's rounded to make the animation smoother.
|
||||
BKMesh* iMesh = (BKMesh*)(arg1 + 1);
|
||||
BKVtxRef* iVtx;
|
||||
BKVtxRef* start_vtx_ref;
|
||||
BKVtxRef* end_vtx_ref;
|
||||
f32 tmp0, tmp1, temp_f2;
|
||||
for (i = 0; i < arg1->meshList_0->meshCount_0; i++) {
|
||||
if (arg2 == iMesh->uid_0) {
|
||||
start_vtx_ref = (BKVtxRef*)(iMesh + 1);
|
||||
end_vtx_ref = start_vtx_ref + iMesh->vtxCount_2;
|
||||
for (iVtx = start_vtx_ref; iVtx < end_vtx_ref; iVtx++) {
|
||||
j = iVtx->unk10 * 3;
|
||||
tmp0 = arg0->unk4 + (iVtx->v.v.ob[0] - arg0->unk10) * 200.0f;
|
||||
tmp1 = arg0->unk8 + (iVtx->v.v.ob[2] - arg0->unk14) * 200.0f;
|
||||
temp_f2 = (sinf(tmp0) + cosf(tmp1)) * arg0->unk20;
|
||||
map_model_xlu_pos_floats[j + 0] = iVtx->v.v.ob[0];
|
||||
map_model_xlu_pos_floats[j + 1] = arg0->unkC + temp_f2;
|
||||
map_model_xlu_pos_floats[j + 2] = iVtx->v.v.ob[2];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
iMesh = (BKMesh*)(((BKVtxRef*)(iMesh + 1)) + iMesh->vtxCount_2);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set the transform ID when drawing the map's translucent model.
|
||||
RECOMP_PATCH void mapModel_xlu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
s32 temp_a0;
|
||||
|
||||
if (mapModel.model_bin_xlu != NULL) {
|
||||
if (map_get() == MAP_1D_MMM_CELLAR) {
|
||||
func_8033A45C(1, (actorArray_findActorFromActorId(0x191) != NULL) ? 0 : 1);
|
||||
}
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE);
|
||||
temp_a0 = mapModel.unk4;
|
||||
if (temp_a0 != 0) {
|
||||
modelRender_setAnimatedTexturesCacheId(temp_a0);
|
||||
}
|
||||
modelRender_setEnvColor(mapModel.env_red, mapModel.env_green, mapModel.env_blue, 0xFF);
|
||||
|
||||
// @recomp Set the map opaque model transform id.
|
||||
cur_drawn_model_is_map = TRUE;
|
||||
cur_drawn_model_transform_id = MAP_MODEL_XLU_TRANSFORM_ID_START;
|
||||
|
||||
// @recomp Because the patched water functions run after this function, run through the vector and see if there's a model
|
||||
// that uses the vertex modification function that was patched. The addresses must be hardcoded as it's not possible to
|
||||
// retrieve the right function address inside a recompiled patch instead.
|
||||
BKVertexList *vtxList = (BKVertexList *)((s32)mapModel.model_bin_xlu + mapModel.model_bin_xlu->vtx_list_offset_10);
|
||||
if (vtxList->count <= MAP_MODEL_XLU_VERTEX_COUNT_MAX) {
|
||||
struct1Ds *iPtr;
|
||||
struct1Ds *endPtr = vector_getEnd(D_80386140.unk4);
|
||||
for (iPtr = vector_getBegin(D_80386140.unk4); iPtr < endPtr; iPtr++) {
|
||||
if (D_80372030[iPtr->xform_id].unk4 == 0x8034E8E4 || D_80372030[iPtr->xform_id].unk4 == 0x8034EF60) {
|
||||
recomp_setup_map_skinning(mapModel.description->xlu_model_id, map_model_xlu_pos_floats);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modelRender_draw(gfx, mtx, NULL, NULL, mapModel.description->scale, NULL, mapModel.model_bin_xlu);
|
||||
|
||||
// @recomp Clear the current model transform id after drawing.
|
||||
cur_drawn_model_is_map = FALSE;
|
||||
cur_drawn_model_transform_id = 0;
|
||||
recomp_clear_map_skinning();
|
||||
|
||||
func_802F7BC0(gfx, mtx, vtx);
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "prop.h"
|
||||
#include "actor.h"
|
||||
#include "functions.h"
|
||||
#include "object_extension_funcs.h"
|
||||
#include "bk_api.h"
|
||||
#include "note_saving.h"
|
||||
|
||||
// Array of handles for ActorMarker instances.
|
||||
// Normally the game only has at most 0xE0 ActorMarker instances, but this is larger to account for mods increasing
|
||||
// the ActorMarker count.
|
||||
u32 marker_handles[0x1000];
|
||||
|
||||
extern ActorMarker *D_8036E7C8;
|
||||
extern u8 D_80383428[0x1C];
|
||||
void func_8032F3D4(s32 arg0[3], ActorMarker *marker, s32 arg2);
|
||||
ActorMarker * func_80332A60(void);
|
||||
|
||||
extern Actor *suLastBaddie;
|
||||
|
||||
// @recomp Patched to create extension data for the marker.
|
||||
RECOMP_PATCH ActorMarker * marker_init(s32 *pos, MarkerDrawFunc draw_func, int arg2, int marker_id, int arg4){
|
||||
ActorMarker * marker = func_80332A60();
|
||||
marker->propPtr = NULL;
|
||||
marker->cubePtr = NULL;
|
||||
marker->drawFunc = draw_func;
|
||||
marker->id = marker_id;
|
||||
marker->unk40_23 = arg4;
|
||||
func_8032F3D4(pos, marker, arg2);
|
||||
marker->actrArrayIdx = 0;
|
||||
marker->unk14_10 = 0;
|
||||
marker->modelId = 0;
|
||||
marker->isBanjoOnTop = 0;
|
||||
marker->unk14_22 = 0;
|
||||
marker->unk14_21 = 0;
|
||||
marker->yaw = 0;
|
||||
marker->pitch = 0;
|
||||
marker->roll = 0;
|
||||
marker->unk2C_2 = 0;
|
||||
marker->unk2C_1 = 0;
|
||||
marker->collidable = TRUE;
|
||||
marker->unk3E_0 = 0;
|
||||
marker->unk40_22 = 0;
|
||||
marker->unk40_19 = 0;
|
||||
marker->unk40_21 = 0;
|
||||
marker->collisionFunc = NULL;
|
||||
marker->collision2Func = NULL;
|
||||
marker->dieFunc = NULL;
|
||||
marker->unk54 = NULL;
|
||||
marker->unk58 = 0;
|
||||
marker->unk18 = 0;
|
||||
marker->actorUpdateFunc = NULL;
|
||||
marker->actorFreeFunc = NULL;
|
||||
marker->commonParticleIndex = 0;
|
||||
marker->actorUpdate2Func = NULL;
|
||||
marker->unk38[0] = 0;
|
||||
marker->unk38[1] = 0;
|
||||
marker->unk38[2] = 0;
|
||||
marker->unk44 = 0;
|
||||
marker->unk20 = 0;
|
||||
marker->unk50 = 0;
|
||||
marker->unk48 = 0;
|
||||
marker->unk4C = 0;
|
||||
marker->unk40_20 = 0;
|
||||
marker->unk40_31 = 0;
|
||||
|
||||
// @recomp Set the marker's handle.
|
||||
u32 index = marker - D_8036E7C8;
|
||||
marker_handles[index] = recomp_create_object_data(EXTENSION_TYPE_MARKER, marker_id);
|
||||
|
||||
// @recomp If this is a note marker, initialize it. Make sure that this marker belongs to suLastBaddie.
|
||||
if (marker->id == MARKER_5F_MUSIC_NOTE && suLastBaddie && suLastBaddie->actor_info->markerId == marker_id) {
|
||||
note_saving_handle_dynamic_note(suLastBaddie, marker);
|
||||
}
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
// @recomp Patched to destroy the marker's extended data.
|
||||
RECOMP_PATCH void func_80332B2C(ActorMarker * arg0){
|
||||
static s32 D_8036E804[8] = {(u8)~(1 << 7), (u8)~(1 << 6), (u8)~(1 << 5), (u8)~(1 << 4), (u8)~(1 << 3), (u8)~(1 << 2), (u8)~(1 << 1), (u8)~(1 << 0)};
|
||||
|
||||
s32 index = (arg0 - D_8036E7C8);
|
||||
arg0->unk5C = 0;
|
||||
D_80383428[index >> 3] = D_80383428[index >> 3] & D_8036E804[index & 7];
|
||||
|
||||
// @recomp Delete the handle for this marker.
|
||||
recomp_destroy_object_data(EXTENSION_TYPE_MARKER, marker_handles[index]);
|
||||
marker_handles[index] = 0;
|
||||
}
|
||||
|
||||
RECOMP_EXPORT MarkerExtensionId bkrecomp_extend_marker(enum marker_e type, u32 size) {
|
||||
return recomp_register_object_extension(EXTENSION_TYPE_MARKER, type, size);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT MarkerExtensionId bkrecomp_extend_marker_all(u32 size) {
|
||||
return recomp_register_object_extension_generic(EXTENSION_TYPE_MARKER, size);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT void* bkrecomp_get_extended_marker_data(ActorMarker* marker, MarkerExtensionId extension) {
|
||||
s32 index = (marker - D_8036E7C8);
|
||||
u32 handle = marker_handles[index];
|
||||
return recomp_get_object_data(EXTENSION_TYPE_MARKER, marker->id, handle, extension);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT u32 bkrecomp_get_marker_spawn_index(ActorMarker* marker) {
|
||||
s32 index = (marker - D_8036E7C8);
|
||||
u32 handle = marker_handles[index];
|
||||
return recomp_get_object_spawn_index(EXTENSION_TYPE_MARKER, handle);
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "bk_api.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
|
||||
extern u8 D_8037BFB8;
|
||||
extern s32 D_8036E7B0;
|
||||
|
||||
void eggShatter_draw(Gfx **gPtr, Mtx **mPtr, Vtx **vPtr);
|
||||
void baModel_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
enum asset_e baModel_getModelId(void);
|
||||
void func_8033A28C(bool arg0);
|
||||
void func_8033A244(f32);
|
||||
void func_8033A280(f32);
|
||||
|
||||
ModelSkinningData sPlayerSkinningData;
|
||||
|
||||
void bkrecomp_setup_custom_skinning(ModelSkinningData* skinning_data, u32 model_id);
|
||||
|
||||
// @recomp Patched to set the current transform ID to banjo's when drawing the player.
|
||||
RECOMP_PATCH void player_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
if (D_8037BFB8) {
|
||||
eggShatter_draw(gfx, mtx, vtx);
|
||||
|
||||
// @recomp Set the custom skinning data for Banjo, so CPU-skinning forms such as the seal are interpolated.
|
||||
bkrecomp_setup_custom_skinning(&sPlayerSkinningData, baModel_getModelId());
|
||||
|
||||
// @recomp Set the current transform ID to banjo's.
|
||||
u32 prev_transform_id = cur_drawn_model_transform_id;
|
||||
cur_drawn_model_transform_id = BANJO_TRANSFORM_ID_START;
|
||||
|
||||
baModel_draw(gfx, mtx, vtx);
|
||||
|
||||
// @recomp Reset the current transform ID.
|
||||
cur_drawn_model_transform_id = prev_transform_id;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set the actor being drawn before the actor's draw func is called.
|
||||
RECOMP_PATCH void __marker_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
Actor *actor;
|
||||
u32 draw_dist;
|
||||
f32 draw_dist_f;
|
||||
f32 percentage;
|
||||
|
||||
// @recomp Calculate the current drawn marker's transform ID.
|
||||
s32 cur_drawn_marker_spawn_index = bkrecomp_get_marker_spawn_index(this);
|
||||
u32 prev_transform_id = cur_drawn_model_transform_id;
|
||||
u32 transform_id = MARKER_TRANSFORM_ID_START + cur_drawn_marker_spawn_index * MARKER_TRANSFORM_ID_COUNT;
|
||||
if(!this->unk3E_0){
|
||||
// @recomp Set the current drawn marker's transform ID.
|
||||
cur_drawn_model_transform_id = transform_id;
|
||||
this->drawFunc(this, gfx, mtx, vtx);
|
||||
// @recomp Clear the current transform ID after drawing.
|
||||
cur_drawn_model_transform_id = prev_transform_id;
|
||||
return;
|
||||
}
|
||||
actor = marker_getActor(this);
|
||||
func_8033A28C(actor->unk58_2);
|
||||
if( actor->unk58_2 && !this->unk40_23 && !this->unk40_21 && !D_8036E7B0){
|
||||
func_8033A244(3700.0f);
|
||||
}
|
||||
|
||||
if(actor->unk124_7 && !actor->despawn_flag && actor->unk58_0){
|
||||
draw_dist = actor->actor_info->draw_distance;
|
||||
if(draw_dist != 0){
|
||||
percentage = (f32)draw_dist*(1/(f64)0x400);
|
||||
}
|
||||
else if(this->unk40_21){
|
||||
percentage = 2.0f;
|
||||
}
|
||||
else{
|
||||
percentage = 1.0f;
|
||||
}
|
||||
func_8033A280(percentage);
|
||||
// @recomp Set the current drawn marker's transform ID.
|
||||
cur_drawn_model_transform_id = transform_id;
|
||||
this->drawFunc(this, gfx, mtx, vtx);
|
||||
// @recomp Set the current drawn marker to null after drawing.
|
||||
cur_drawn_model_transform_id = prev_transform_id;
|
||||
}//L8032D300
|
||||
func_8033A244(30000.0f);
|
||||
func_8033A280(1.0f);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef __MEM_FUNCS_H__
|
||||
#define __MEM_FUNCS_H__
|
||||
|
||||
#include "patch_helpers.h"
|
||||
|
||||
DECLARE_FUNC(u32, recomp_register_actor_extension, u32 actor_type, u32 size);
|
||||
DECLARE_FUNC(u32, recomp_register_actor_extension_generic, u32 size);
|
||||
DECLARE_FUNC(void, recomp_clear_all_actor_data);
|
||||
DECLARE_FUNC(u32, recomp_create_actor_data, u32 actor_type);
|
||||
DECLARE_FUNC(void, recomp_destroy_actor_data, u32 actor_handle);
|
||||
DECLARE_FUNC(void*, recomp_get_actor_data, u32 actor_handle, u32 extension_handle, u32 actor_type);
|
||||
DECLARE_FUNC(u32, recomp_get_actor_spawn_index, u32 actor_handle);
|
||||
|
||||
#endif
|
||||
@@ -7,7 +7,5 @@ DECLARE_FUNC(void, recomp_load_overlays, u32 rom, void* ram, u32 size);
|
||||
DECLARE_FUNC(void, recomp_puts, const char* data, u32 size);
|
||||
DECLARE_FUNC(void, recomp_exit);
|
||||
DECLARE_FUNC(void, recomp_error, const char* str);
|
||||
DECLARE_FUNC(u64, recomp_xxh3, void* data, u32 size);
|
||||
DECLARE_FUNC(s32, recomp_get_note_saving_enabled);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "prop.h"
|
||||
|
||||
enum map_e map_get(void);
|
||||
s32 func_80307164(s32 position[3]);
|
||||
s32 func_80306DBC(s32 arg0);
|
||||
|
||||
bool mumbo_token_fixes_enabled = TRUE;
|
||||
|
||||
RECOMP_EXPORT void bkrecomp_set_mumbo_token_fixes_enabled(bool val) {
|
||||
mumbo_token_fixes_enabled = val;
|
||||
}
|
||||
|
||||
// @recomp Patched to replace the IDs of duplicate tokens.
|
||||
RECOMP_PATCH enum mumbotoken_e func_802E0A90(Actor *this){
|
||||
s32 id;
|
||||
s32 pos[3];
|
||||
|
||||
// @recomp Record the map ID.
|
||||
enum map_e map_id = map_get();
|
||||
pos[0] = (s32)this->position[0];
|
||||
pos[1] = (s32)this->position[1];
|
||||
pos[2] = (s32)this->position[2];
|
||||
id = func_80307164(pos);
|
||||
if(id < 0){
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
// @recomp Replace the IDs of duplicate tokens.
|
||||
// return func_80306DBC(id) - 199;
|
||||
s32 ret = func_80306DBC(id) - 199;
|
||||
|
||||
// @recomp Only replace token IDs if the fixes are enabled.
|
||||
if (mumbo_token_fixes_enabled) {
|
||||
// @recomp Replace the ID for the following token:
|
||||
// Mumbo token ID: 0x3D @ 424, 170, 304 (Map 0x8D)
|
||||
if (ret == 0x3D && pos[0] == 424 && pos[1] == 170 && pos[2] == 304 && map_id == MAP_8D_MMM_INSIDE_LOGGO) {
|
||||
// @recomp Swap to unused ID 0x74
|
||||
ret = 0x74;
|
||||
}
|
||||
|
||||
// @recomp Replace the ID for the following token:
|
||||
// Mumbo token ID: 0x5E @ -2649, 0, -395 (Map 0x43)
|
||||
if (ret == 0x5E && pos[0] == -2649 && pos[1] == 0 && pos[2] == -395 && map_id == MAP_43_CCW_SPRING) {
|
||||
// @recomp Swap to unused ID 0x5D
|
||||
ret = 0x5D;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Return the modified ID.
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1,466 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "bk_api.h"
|
||||
#include "misc_funcs.h"
|
||||
#include "save_extension.h"
|
||||
#include "note_saving.h"
|
||||
|
||||
#include "functions.h"
|
||||
#include "prop.h"
|
||||
#include "core2/timedfunc.h"
|
||||
|
||||
// Vanilla declarations.
|
||||
typedef struct map_info{
|
||||
s16 map_id;
|
||||
s16 level_id;
|
||||
char* name;
|
||||
}MapInfo;
|
||||
|
||||
extern struct {
|
||||
s32 unk0;
|
||||
s32 unk4;
|
||||
u8 unk8[0x25];
|
||||
} gFileProgressFlags;
|
||||
|
||||
MapInfo * func_8030AD00(enum map_e map_id);
|
||||
enum map_e map_get(void);
|
||||
enum level_e level_get(void);
|
||||
void progressDialog_showDialogMaskZero(s32);
|
||||
void fxSparkle_musicNote(s16 position[3]);
|
||||
void item_inc(enum item_e item);
|
||||
void item_adjustByDiffWithoutHud(enum item_e item, s32 diff);
|
||||
bool func_802FADD4(enum item_e item_id);
|
||||
s32 item_getCount(enum item_e item);
|
||||
s32 jiggyscore_leveltotal(s32 lvl);
|
||||
void itemPrint_reset(void);
|
||||
s32 bitfield_get_bit(u8 *array, s32 index);
|
||||
|
||||
extern s32 D_80385F30[0x2C];
|
||||
extern s32 D_80385FE8;
|
||||
|
||||
extern struct {
|
||||
Cube *cubes;
|
||||
f32 margin;
|
||||
s32 min[3];
|
||||
s32 max[3];
|
||||
s32 stride[2];
|
||||
s32 cubeCnt;
|
||||
s32 unk2C;
|
||||
s32 width[3];
|
||||
Cube *unk3C; // fallback cube?
|
||||
Cube *unk40; // some other fallback cube?
|
||||
s32 unk44; // index of some sort
|
||||
} sCubeList;
|
||||
|
||||
// New declarations.
|
||||
typedef struct {
|
||||
u16 static_note_count;
|
||||
u16 dynamic_note_count;
|
||||
u16 start_note_index;
|
||||
u16 level_id;
|
||||
} MapNoteData;
|
||||
|
||||
MapNoteData map_note_data[512]; // One entry per map, with room for extras in case any mods add additional maps.
|
||||
u16 level_note_counts[256]; // One entry per level, with room for extras in case any mods add additional levels.
|
||||
|
||||
typedef struct {
|
||||
u32 note_index;
|
||||
} NoteSavingExtensionData;
|
||||
|
||||
PropExtensionId note_saving_prop_extension_id;
|
||||
|
||||
// Note saving can only savely be changed while in the lair, so this value is only updated when in the lair.
|
||||
bool note_saving_enabled_cached = FALSE;
|
||||
// Override for allowing mods to disable note saving.
|
||||
bool note_saving_override_disabled = FALSE;
|
||||
|
||||
u32 spawned_static_note_count = 0;
|
||||
|
||||
// Per-map values containing the number of dynamic notes to despawn for the current session.
|
||||
// This is calculated when a new level is entered for every map in the level.
|
||||
u8 map_dynamic_note_despawn_counts[512];
|
||||
|
||||
bool recomp_in_demo_playback_game_mode();
|
||||
|
||||
void init_note_saving() {
|
||||
note_saving_prop_extension_id = bkrecomp_extend_prop_all(sizeof(NoteSavingExtensionData));
|
||||
|
||||
// Collected from map data.
|
||||
map_note_data[MAP_2_MM_MUMBOS_MOUNTAIN].static_note_count = 85;
|
||||
map_note_data[MAP_2_MM_MUMBOS_MOUNTAIN].dynamic_note_count = 5;
|
||||
map_note_data[MAP_5_TTC_BLUBBERS_SHIP].static_note_count = 8;
|
||||
map_note_data[MAP_6_TTC_NIPPERS_SHELL].static_note_count = 6;
|
||||
map_note_data[MAP_7_TTC_TREASURE_TROVE_COVE].static_note_count = 82;
|
||||
map_note_data[MAP_A_TTC_SANDCASTLE].static_note_count = 4;
|
||||
map_note_data[MAP_B_CC_CLANKERS_CAVERN].static_note_count = 72;
|
||||
map_note_data[MAP_C_MM_TICKERS_TOWER].static_note_count = 6;
|
||||
map_note_data[MAP_D_BGS_BUBBLEGLOOP_SWAMP].static_note_count = 83;
|
||||
map_note_data[MAP_D_BGS_BUBBLEGLOOP_SWAMP].dynamic_note_count = 5;
|
||||
map_note_data[MAP_E_MM_MUMBOS_SKULL].static_note_count = 4;
|
||||
map_note_data[MAP_10_BGS_MR_VILE].static_note_count = 6;
|
||||
map_note_data[MAP_11_BGS_TIPTUP].static_note_count = 6;
|
||||
map_note_data[MAP_12_GV_GOBIS_VALLEY].static_note_count = 70;
|
||||
map_note_data[MAP_13_GV_MEMORY_GAME].static_note_count = 4;
|
||||
map_note_data[MAP_14_GV_SANDYBUTTS_MAZE].static_note_count = 7;
|
||||
map_note_data[MAP_15_GV_WATER_PYRAMID].static_note_count = 4;
|
||||
map_note_data[MAP_16_GV_RUBEES_CHAMBER].static_note_count = 8;
|
||||
map_note_data[MAP_1A_GV_INSIDE_JINXY].static_note_count = 7;
|
||||
map_note_data[MAP_1B_MMM_MAD_MONSTER_MANSION].static_note_count = 47;
|
||||
map_note_data[MAP_1C_MMM_CHURCH].static_note_count = 10;
|
||||
map_note_data[MAP_1D_MMM_CELLAR].static_note_count = 4;
|
||||
map_note_data[MAP_21_CC_WITCH_SWITCH_ROOM].static_note_count = 6;
|
||||
map_note_data[MAP_22_CC_INSIDE_CLANKER].static_note_count = 16;
|
||||
map_note_data[MAP_23_CC_GOLDFEATHER_ROOM].static_note_count = 6;
|
||||
map_note_data[MAP_24_MMM_TUMBLARS_SHED].static_note_count = 4;
|
||||
map_note_data[MAP_25_MMM_WELL].static_note_count = 7;
|
||||
map_note_data[MAP_26_MMM_NAPPERS_ROOM].static_note_count = 8;
|
||||
map_note_data[MAP_27_FP_FREEZEEZY_PEAK].static_note_count = 82;
|
||||
map_note_data[MAP_29_MMM_NOTE_ROOM].static_note_count = 9;
|
||||
map_note_data[MAP_2D_MMM_BEDROOM].static_note_count = 4;
|
||||
map_note_data[MAP_2F_MMM_WATERDRAIN_BARREL].static_note_count = 5;
|
||||
map_note_data[MAP_30_MMM_MUMBOS_SKULL].static_note_count = 2;
|
||||
map_note_data[MAP_31_RBB_RUSTY_BUCKET_BAY].static_note_count = 43;
|
||||
map_note_data[MAP_34_RBB_ENGINE_ROOM].static_note_count = 16;
|
||||
map_note_data[MAP_35_RBB_WAREHOUSE].static_note_count = 4;
|
||||
map_note_data[MAP_37_RBB_CONTAINER_1].static_note_count = 8;
|
||||
map_note_data[MAP_38_RBB_CONTAINER_3].static_note_count = 4;
|
||||
map_note_data[MAP_39_RBB_CREW_CABIN].static_note_count = 4;
|
||||
map_note_data[MAP_3B_RBB_STORAGE_ROOM].static_note_count = 5;
|
||||
map_note_data[MAP_3C_RBB_KITCHEN].static_note_count = 5;
|
||||
map_note_data[MAP_3D_RBB_NAVIGATION_ROOM].static_note_count = 4;
|
||||
map_note_data[MAP_3F_RBB_CAPTAINS_CABIN].static_note_count = 3;
|
||||
map_note_data[MAP_40_CCW_HUB].static_note_count = 4;
|
||||
map_note_data[MAP_43_CCW_SPRING].static_note_count = 16;
|
||||
map_note_data[MAP_44_CCW_SUMMER].static_note_count = 16;
|
||||
map_note_data[MAP_45_CCW_AUTUMN].static_note_count = 37;
|
||||
map_note_data[MAP_46_CCW_WINTER].static_note_count = 16;
|
||||
map_note_data[MAP_48_FP_MUMBOS_SKULL].static_note_count = 6;
|
||||
map_note_data[MAP_4C_CCW_AUTUMN_MUMBOS_SKULL].static_note_count = 4;
|
||||
map_note_data[MAP_53_FP_CHRISTMAS_TREE].static_note_count = 12;
|
||||
map_note_data[MAP_5C_CCW_AUTUMN_ZUBBA_HIVE].static_note_count = 4;
|
||||
map_note_data[MAP_60_CCW_AUTUMN_NABNUTS_HOUSE].static_note_count = 3;
|
||||
map_note_data[MAP_8B_RBB_ANCHOR_ROOM].static_note_count = 4;
|
||||
}
|
||||
|
||||
RECOMP_EXPORT void bkrecomp_notesaving_clear_all_map_note_counts() {
|
||||
for (u32 i = 0; i < ARRLEN(map_note_data); i++) {
|
||||
map_note_data[i].static_note_count = 0;
|
||||
map_note_data[i].dynamic_note_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
RECOMP_EXPORT void bkrecomp_notesaving_set_map_static_note_count(u32 map_id, u16 static_note_count) {
|
||||
if (map_id >= ARRLEN(map_note_data)) {
|
||||
recomp_error("Mod error: Attempted to set static note count of an invalid map ID\n");
|
||||
}
|
||||
map_note_data[map_id].static_note_count = static_note_count;
|
||||
}
|
||||
|
||||
RECOMP_EXPORT void bkrecomp_notesaving_set_map_dynamic_note_count(u32 map_id, u16 dynamic_note_count) {
|
||||
if (map_id >= ARRLEN(map_note_data)) {
|
||||
recomp_error("Mod error: Attempted to set dynamic note count of an invalid map ID\n");
|
||||
}
|
||||
map_note_data[map_id].dynamic_note_count = dynamic_note_count;
|
||||
}
|
||||
|
||||
RECOMP_EXPORT void bkrecomp_notesaving_force_disabled(bool disabled) {
|
||||
note_saving_override_disabled = disabled;
|
||||
}
|
||||
|
||||
// Notes are always saved, but this function controls whether to use the saved data to prevent notes from spawning and adjust the note score.
|
||||
RECOMP_EXPORT s32 bkrecomp_note_saving_enabled() {
|
||||
return recomp_get_note_saving_enabled();
|
||||
}
|
||||
|
||||
RECOMP_EXPORT s32 bkrecomp_note_saving_active() {
|
||||
return note_saving_enabled_cached;
|
||||
}
|
||||
|
||||
void calculate_map_start_note_indices() {
|
||||
for (u32 map_id = 0; map_id < ARRLEN(map_note_data); map_id++) {
|
||||
MapNoteData* note_data = &map_note_data[map_id];
|
||||
MapInfo* info = func_8030AD00(map_id);
|
||||
if (info != NULL) {
|
||||
note_data->level_id = info->level_id;
|
||||
note_data->start_note_index = level_note_counts[info->level_id];
|
||||
level_note_counts[info->level_id] += note_data->static_note_count + note_data->dynamic_note_count;
|
||||
}
|
||||
else {
|
||||
note_data->level_id = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 level_id_to_level_array_index(enum level_e level_id) {
|
||||
switch (level_id) {
|
||||
case LEVEL_1_MUMBOS_MOUNTAIN:
|
||||
return 0;
|
||||
case LEVEL_2_TREASURE_TROVE_COVE:
|
||||
return 1;
|
||||
case LEVEL_3_CLANKERS_CAVERN:
|
||||
return 2;
|
||||
case LEVEL_4_BUBBLEGLOOP_SWAMP:
|
||||
return 3;
|
||||
case LEVEL_5_FREEZEEZY_PEAK:
|
||||
return 4;
|
||||
case LEVEL_7_GOBIS_VALLEY:
|
||||
return 5;
|
||||
case LEVEL_A_MAD_MONSTER_MANSION:
|
||||
return 6;
|
||||
case LEVEL_9_RUSTY_BUCKET_BAY:
|
||||
return 7;
|
||||
case LEVEL_8_CLICK_CLOCK_WOOD:
|
||||
return 8;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_note_collected(enum map_e map_id, enum level_e level_id, u8 note_index) {
|
||||
if (map_id >= ARRLEN(map_note_data)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 level_array_index = level_id_to_level_array_index(level_id);
|
||||
if (level_array_index == -1 || level_array_index >= ARRLEN(loaded_file_extension_data.level_notes)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MapNoteData *note_data = &map_note_data[map_id];
|
||||
note_index += note_data->start_note_index;
|
||||
|
||||
u32 byte_index = note_index / 8;
|
||||
u32 bit_index = note_index % 8;
|
||||
|
||||
return (loaded_file_extension_data.level_notes[level_array_index].bytes[byte_index] & (1 << bit_index)) != 0;
|
||||
}
|
||||
|
||||
void set_note_collected(enum map_e map_id, enum level_e level_id, u8 note_index) {
|
||||
if (map_id >= ARRLEN(map_note_data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
s32 level_array_index = level_id_to_level_array_index(level_id);
|
||||
if (level_array_index == -1 || level_array_index >= ARRLEN(loaded_file_extension_data.level_notes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MapNoteData *note_data = &map_note_data[map_id];
|
||||
note_index += note_data->start_note_index;
|
||||
|
||||
u32 byte_index = note_index / 8;
|
||||
u32 bit_index = note_index % 8;
|
||||
|
||||
loaded_file_extension_data.level_notes[level_array_index].bytes[byte_index] |= (1 << bit_index);
|
||||
}
|
||||
|
||||
void collect_dynamic_note(enum map_e map_id, enum level_e level_id) {
|
||||
if (map_id < ARRLEN(map_note_data)) {
|
||||
MapNoteData *map_data = &map_note_data[map_id];
|
||||
s32 start_note_index = map_data->static_note_count + map_data->start_note_index;
|
||||
s32 map_dynamic_note_count = map_data->dynamic_note_count;
|
||||
|
||||
// Set the first unset dynamic note bit for this map.
|
||||
for (s32 i = 0; i < map_dynamic_note_count; i++) {
|
||||
s32 note_index = start_note_index + i;
|
||||
if (!is_note_collected(map_id, level_id, note_index)) {
|
||||
set_note_collected(map_id, level_id, note_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 dynamic_note_collected_count(enum map_e map_id) {
|
||||
s32 ret = 0;
|
||||
if (map_id < ARRLEN(map_note_data)) {
|
||||
MapNoteData *map_data = &map_note_data[map_id];
|
||||
s32 start_note_index = map_data->static_note_count + map_data->start_note_index;
|
||||
s32 map_dynamic_note_count = map_data->dynamic_note_count;
|
||||
|
||||
// Check the dynamic note bits for this map.
|
||||
for (s32 i = 0; i < map_dynamic_note_count; i++) {
|
||||
s32 note_index = start_note_index + i;
|
||||
if (is_note_collected(map_id, map_data->level_id, note_index)) {
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void note_saving_on_map_load() {
|
||||
spawned_static_note_count = 0;
|
||||
|
||||
// Prevent the note score passed dialog from running if note saving is enabled.
|
||||
if (note_saving_enabled_cached) {
|
||||
// This flag controls whether Bottles will tell you when you pass your note score.
|
||||
levelSpecificFlags_set(LEVEL_FLAG_34_UNKNOWN, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void note_saving_update() {
|
||||
// When in the lair or file select, update the cached note saving enabled state.
|
||||
if (level_get() == LEVEL_6_LAIR || map_get() == MAP_91_FILE_SELECT) {
|
||||
if (note_saving_override_disabled) {
|
||||
note_saving_enabled_cached = FALSE;
|
||||
}
|
||||
else {
|
||||
note_saving_enabled_cached = bkrecomp_note_saving_enabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void note_saving_handle_static_note(Cube *c, Prop *p) {
|
||||
|
||||
// If note saving is enabled, check if this note has been collected and remove it if so.
|
||||
if (note_saving_enabled_cached) {
|
||||
if (is_note_collected(map_get(), level_get(), spawned_static_note_count)) {
|
||||
// Clear the note's alive bit.
|
||||
p->spriteProp.unk8_4 = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
NoteSavingExtensionData* note_data = (NoteSavingExtensionData*)bkrecomp_get_extended_prop_data(c, p, note_saving_prop_extension_id);
|
||||
note_data->note_index = spawned_static_note_count;
|
||||
|
||||
spawned_static_note_count++;
|
||||
}
|
||||
|
||||
void note_saving_handle_dynamic_note(Actor *actor, ActorMarker *marker) {
|
||||
if (note_saving_enabled_cached) {
|
||||
s32 map_id = map_get();
|
||||
if (map_id < ARRLEN(map_dynamic_note_despawn_counts)) {
|
||||
if (map_dynamic_note_despawn_counts[map_id] > 0) {
|
||||
map_dynamic_note_despawn_counts[map_id]--;
|
||||
// Clear the note's alive bit so it doesn't draw for good measure.
|
||||
marker->propPtr->unk8_4 = FALSE;
|
||||
// Set the actor as despawned.
|
||||
actor->despawn_flag = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool prop_in_cube(Cube *c, Prop *p) {
|
||||
s32 prop_index = p - c->prop2Ptr;
|
||||
if (prop_index >= 0 && prop_index < c->prop2Cnt) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Cube *find_cube_for_prop(Prop *p) {
|
||||
for (s32 i = 0; i < sCubeList.cubeCnt; i++) {
|
||||
Cube *cur_cube = &sCubeList.cubes[i];
|
||||
if (prop_in_cube(cur_cube, p)) {
|
||||
return cur_cube;
|
||||
}
|
||||
}
|
||||
|
||||
if (prop_in_cube(sCubeList.unk3C, p)) {
|
||||
return sCubeList.unk3C;
|
||||
}
|
||||
|
||||
if (prop_in_cube(sCubeList.unk40, p)) {
|
||||
return sCubeList.unk40;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// @recomp Patched to track collected notes.
|
||||
RECOMP_PATCH void __baMarker_resolveMusicNoteCollision(Prop *arg0) {
|
||||
// @recomp Set that the note was collected if this isn't demo playback.
|
||||
if (!recomp_in_demo_playback_game_mode()) {
|
||||
// Check if this is an actor prop and collect a dynamic note if so.
|
||||
if (arg0->is_actor) {
|
||||
collect_dynamic_note(map_get(), level_get());
|
||||
}
|
||||
// Otherwise, make sure this is a sprite prop and use the prop data.
|
||||
else if (!arg0->is_3d) {
|
||||
Cube *prop_cube = find_cube_for_prop(arg0);
|
||||
if (prop_cube != NULL) {
|
||||
NoteSavingExtensionData* note_data = (NoteSavingExtensionData*)bkrecomp_get_extended_prop_data(prop_cube, arg0, note_saving_prop_extension_id);
|
||||
set_note_collected(map_get(), level_get(), note_data->note_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!func_802FADD4(ITEM_1B_VILE_VILE_SCORE)) {
|
||||
item_inc(ITEM_C_NOTE);
|
||||
} else {
|
||||
item_adjustByDiffWithoutHud(ITEM_C_NOTE, 1);
|
||||
}
|
||||
if (item_getCount(ITEM_C_NOTE) < 100) {
|
||||
coMusicPlayer_playMusic(COMUSIC_9_NOTE_COLLECTED, 16000);
|
||||
timedFunc_set_1(0.75f, progressDialog_showDialogMaskZero, FILEPROG_3_MUSIC_NOTE_TEXT);
|
||||
}
|
||||
fxSparkle_musicNote(arg0->unk4);
|
||||
}
|
||||
|
||||
s32 get_collected_note_count(enum level_e level) {
|
||||
s32 level_array_index = level_id_to_level_array_index(level);
|
||||
if (level_array_index == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 count = 0;
|
||||
for (int i = 0; i < ARRLEN(loaded_file_extension_data.level_notes[0].bytes); i++) {
|
||||
u8 cur_byte = loaded_file_extension_data.level_notes[level_array_index].bytes[i];
|
||||
count += __builtin_popcount(cur_byte);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// @recomp Patched to restore the saved note count when entering a level and reset the per-map collected dynamic note counts.
|
||||
RECOMP_PATCH void itemscore_levelReset(enum level_e level){
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 6; i++){
|
||||
D_80385F30[ITEM_0_HOURGLASS_TIMER + i] = 0;
|
||||
D_80385F30[ITEM_6_HOURGLASS + i] = 0;
|
||||
}
|
||||
|
||||
D_80385F30[ITEM_C_NOTE] = 0;
|
||||
D_80385F30[ITEM_E_JIGGY] = jiggyscore_leveltotal(level);
|
||||
D_80385F30[ITEM_12_JINJOS] = 0;
|
||||
D_80385F30[ITEM_17_AIR] = 3600;
|
||||
D_80385F30[ITEM_18_GOLD_BULLIONS] = 0;
|
||||
D_80385F30[ITEM_19_ORANGE] = 0;
|
||||
D_80385F30[ITEM_23_ACORNS] = 0;
|
||||
D_80385F30[ITEM_1A_PLAYER_VILE_SCORE] = 0;
|
||||
D_80385F30[ITEM_1B_VILE_VILE_SCORE] = 0;
|
||||
D_80385F30[ITEM_1F_GREEN_PRESENT] = 0;
|
||||
D_80385F30[ITEM_20_BLUE_PRESENT] = 0;
|
||||
D_80385F30[ITEM_21_RED_PRESENT] = 0;
|
||||
D_80385F30[ITEM_22_CATERPILLAR] = 0;
|
||||
itemPrint_reset();
|
||||
D_80385FE8 = 1;
|
||||
|
||||
// @recomp If note saving is currently enabled, set load the note count for the current level.
|
||||
if (note_saving_enabled_cached) {
|
||||
D_80385F30[ITEM_C_NOTE] = get_collected_note_count(level);
|
||||
}
|
||||
|
||||
// @recomp Set the number of dynamic notes to respawn for each map in the level.
|
||||
for (s32 map_id = 0; map_id < ARRLEN(map_note_data); map_id++) {
|
||||
MapNoteData *map_data = &map_note_data[map_id];
|
||||
if (map_data->level_id == level) {
|
||||
map_dynamic_note_despawn_counts[map_id] = dynamic_note_collected_count(map_id);
|
||||
}
|
||||
else {
|
||||
map_dynamic_note_despawn_counts[map_id] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to return true for FILEPROG_99_PAST_50_NOTE_DOOR_TEXT if note saving is enabled.
|
||||
// That flag controls whether to show the "Grunty's magic stops you from taking the notes..." dialog.
|
||||
RECOMP_PATCH bool fileProgressFlag_get(enum file_progress_e index) {
|
||||
if (note_saving_enabled_cached && index == FILEPROG_99_PAST_50_NOTE_DOOR_TEXT) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return bitfield_get_bit(gFileProgressFlags.unk8, index);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#ifndef __NOTE_SAVING_H__
|
||||
#define __NOTE_SAVING_H__
|
||||
|
||||
#include "prop.h"
|
||||
|
||||
void init_note_saving();
|
||||
void calculate_map_start_note_indices();
|
||||
|
||||
// Notes are always saved, but this function controls whether to use the saved data to prevent notes from spawning and adjust the note score.
|
||||
bool note_saving_enabled();
|
||||
|
||||
void note_saving_on_map_load();
|
||||
void note_saving_update();
|
||||
void note_saving_handle_static_note(Cube *c, Prop *p);
|
||||
void note_saving_handle_dynamic_note(Actor *actor, ActorMarker *marker);
|
||||
|
||||
#endif
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef __MEM_FUNCS_H__
|
||||
#define __MEM_FUNCS_H__
|
||||
|
||||
#include "patch_helpers.h"
|
||||
|
||||
DECLARE_FUNC(u32, recomp_register_object_extension, u32 type_index, u32 subtype_index, u32 size);
|
||||
DECLARE_FUNC(u32, recomp_register_object_extension_generic, u32 type_index, u32 size);
|
||||
DECLARE_FUNC(void, recomp_clear_all_object_data, u32 type_index);
|
||||
DECLARE_FUNC(u32, recomp_create_object_data, u32 type_index, u32 subtype_index);
|
||||
DECLARE_FUNC(void, recomp_destroy_object_data, u32 type_index, u32 object_handle);
|
||||
DECLARE_FUNC(void*, recomp_get_object_data, u32 type_index, u32 subtype_index, u32 object_handle, u32 extension_handle);
|
||||
DECLARE_FUNC(u32, recomp_get_object_spawn_index, u32 type_index, u32 object_handle);
|
||||
|
||||
#endif
|
||||
@@ -54,8 +54,37 @@ MAKE_OVERLAYS()
|
||||
#define OVERLAY_END(ovl) boot_##ovl##_rzip_ROM_END
|
||||
|
||||
// @recomp Patched to load overlays, prefixed with boot_ to account for the decomp build system.
|
||||
RECOMP_PATCH void boot___osInitialize_common(void) {
|
||||
// Nothing of the original function needs to happen, so the body can be empty besides the overlay load.
|
||||
RECOMP_PATCH void boot_overlay_table_init(void) {
|
||||
gOverlayTable[ 0].start = OVERLAY_START(core2);
|
||||
gOverlayTable[ 0].end = OVERLAY_END(core2);
|
||||
gOverlayTable[ 1].start = OVERLAY_START(emptyLvl);
|
||||
gOverlayTable[ 1].end = OVERLAY_END(emptyLvl);
|
||||
gOverlayTable[ 2].start = OVERLAY_START(CC);
|
||||
gOverlayTable[ 2].end = OVERLAY_END(CC);
|
||||
gOverlayTable[ 3].start = OVERLAY_START(MMM);
|
||||
gOverlayTable[ 3].end = OVERLAY_END(MMM);
|
||||
gOverlayTable[ 4].start = OVERLAY_START(GV);
|
||||
gOverlayTable[ 4].end = OVERLAY_END(GV);
|
||||
gOverlayTable[ 5].start = OVERLAY_START(TTC);
|
||||
gOverlayTable[ 5].end = OVERLAY_END(TTC);
|
||||
gOverlayTable[ 6].start = OVERLAY_START(MM);
|
||||
gOverlayTable[ 6].end = OVERLAY_END(MM);
|
||||
gOverlayTable[ 7].start = OVERLAY_START(BGS);
|
||||
gOverlayTable[ 7].end = OVERLAY_END(BGS);
|
||||
gOverlayTable[ 8].start = OVERLAY_START(RBB);
|
||||
gOverlayTable[ 8].end = OVERLAY_END(RBB);
|
||||
gOverlayTable[ 9].start = OVERLAY_START(FP);
|
||||
gOverlayTable[ 9].end = OVERLAY_END(FP);
|
||||
gOverlayTable[10].start = OVERLAY_START(CCW);
|
||||
gOverlayTable[10].end = OVERLAY_END(CCW);
|
||||
gOverlayTable[11].start = OVERLAY_START(SM);
|
||||
gOverlayTable[11].end = OVERLAY_END(SM);
|
||||
gOverlayTable[12].start = OVERLAY_START(cutscenes);
|
||||
gOverlayTable[12].end = OVERLAY_END(cutscenes);
|
||||
gOverlayTable[13].start = OVERLAY_START(lair);
|
||||
gOverlayTable[13].end = OVERLAY_END(lair);
|
||||
gOverlayTable[14].start = OVERLAY_START(fight);
|
||||
gOverlayTable[14].end = OVERLAY_END(fight);
|
||||
|
||||
// @recomp Load core1.
|
||||
recomp_load_overlays_by_rom((u32)core1_ROM_START, core1_VRAM, core1_ROM_END - core1_ROM_START);
|
||||
@@ -84,7 +113,7 @@ RECOMP_PATCH void overlay_load(
|
||||
u32 uncompressed_rom_start = rom_start;
|
||||
u32 uncompressed_rom_size = rom_end - rom_start;
|
||||
u32 overlay_vram_start = ram_start;
|
||||
u8* sp34;
|
||||
void* sp34;
|
||||
u32 sp30;
|
||||
u32 sp2C;
|
||||
u32 *tmp;
|
||||
@@ -108,10 +137,10 @@ RECOMP_PATCH void overlay_load(
|
||||
sp34 = &D_8002D500;
|
||||
}
|
||||
piMgr_read(sp34, rom_start, rom_end - rom_start);
|
||||
rarezip_uncompress(&sp34, (u8**)&ram_start);
|
||||
rarezip_uncompress(&sp34, &ram_start);
|
||||
sp2C = D_8027BF2C;
|
||||
sp30 = D_8027BF30;
|
||||
rarezip_uncompress(&sp34, (u8**)&ram_start);
|
||||
rarezip_uncompress(&sp34, &ram_start);
|
||||
|
||||
if(bss_start){
|
||||
bzero((void*)bss_start, bss_end - bss_start);
|
||||
|
||||
@@ -1,348 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
#include "rand.h"
|
||||
#include "core1/ml.h"
|
||||
#include "core2/anctrl.h"
|
||||
#include "core2/modelRender.h"
|
||||
#include "core2/particle.h"
|
||||
#include "core2/timedfunc.h"
|
||||
|
||||
u32 particle_spawn_count = 0;
|
||||
|
||||
extern ParticleEmitter **partEmitMgr;
|
||||
extern s32 partEmitMgrLength;
|
||||
|
||||
typedef struct particle{
|
||||
f32 acceleration[3];
|
||||
f32 fade;
|
||||
f32 frame; //frame
|
||||
f32 framerate; //framerate
|
||||
f32 position[3];
|
||||
f32 rotation[3];
|
||||
f32 scale; //size
|
||||
f32 initialSize_34; //initial_size
|
||||
f32 finalSizeDiff; //delta_size
|
||||
f32 angluar_velocity[3];
|
||||
f32 age_48;
|
||||
f32 lifetime_4C;
|
||||
f32 velocity_50[3];
|
||||
u8 unk5C;
|
||||
//u8 pad5D[3];
|
||||
} Particle;
|
||||
|
||||
u32 get_particle_id(Particle *p) {
|
||||
u8 *padding = &p->unk5C + 1;
|
||||
|
||||
u32 id = (padding[0] << 16) | (padding[1] << 8) | (padding[2] << 0);
|
||||
return id;
|
||||
}
|
||||
|
||||
void set_particle_id(Particle *p, u32 id) {
|
||||
u8 *padding = &p->unk5C + 1;
|
||||
|
||||
padding[0] = (id >> 16) & 0xFF;
|
||||
padding[1] = (id >> 8) & 0xFF;
|
||||
padding[2] = (id >> 0) & 0xFF;
|
||||
}
|
||||
|
||||
extern Gfx D_80368978[];
|
||||
extern Gfx D_80368940[];
|
||||
|
||||
void __particleEmitter_drawOnPass(ParticleEmitter *this, Gfx **gfx, Mtx **mtx, Vtx **vtx, u32 draw_pass);
|
||||
void func_803382E4(s32);
|
||||
void func_80338338(s32, s32, s32);
|
||||
void func_803382B4(s32 arg0, s32 arg1, s32 arg2, s32 arg3);
|
||||
void func_80338370(void);
|
||||
void func_80335D30(Gfx **);
|
||||
void func_802EED1C(ParticleEmitter *this, f32 age, f32 arg2[3]);
|
||||
void func_80344C2C(bool arg0);
|
||||
void func_80344720(BKSpriteDisplayData *arg0, s32 frame, bool mirrored, f32 position[3], f32 rotation[3], f32 scale[3], Gfx **gfx, Mtx **mtx);
|
||||
void func_80344424(BKSpriteDisplayData *arg0, s32 frame, bool mirrored, f32 position[3], f32 scale[3], f32 rotation, Gfx **gfx, Mtx **mtx);
|
||||
void func_8033687C(Gfx **);
|
||||
s32 func_8034E698(Struct73s *arg0);
|
||||
|
||||
// @recomp Patched to tag particles as they're drawn.
|
||||
RECOMP_PATCH void __particleEmitter_drawOnPass(ParticleEmitter *this, Gfx **gfx, Mtx **mtx, Vtx **vtx, u32 draw_pass){
|
||||
f32 position[3];
|
||||
f32 flat_rotation[3];
|
||||
f32 scale[3];
|
||||
Particle *iPtr;
|
||||
|
||||
if(reinterpret_cast(u32, draw_pass) != (this->draw_mode & 0x4) != 0)
|
||||
return;
|
||||
|
||||
if(this->model_20 != NULL){
|
||||
for(iPtr = this->pList_start_124; iPtr < this->pList_end_128; iPtr++){
|
||||
position[0] = iPtr->position[0] + this->unk4[0];
|
||||
position[1] = iPtr->position[1] + this->unk4[1];
|
||||
position[2] = iPtr->position[2] + this->unk4[2];
|
||||
if( 0.0f != this->fade_in || 1.0 != this->fade_out || this->alpha != 0xff ){
|
||||
modelRender_setAlpha((s32) (iPtr->fade*this->alpha));
|
||||
}//L802EEF5C
|
||||
modelRender_setDepthMode((this->draw_mode & PART_EMIT_NO_DEPTH)? MODEL_RENDER_DEPTH_NONE : MODEL_RENDER_DEPTH_FULL);
|
||||
// @recomp Get the particle's ID and use it to set the current model transform ID.
|
||||
cur_drawn_model_transform_id = MODEL_PARTICLE_TRANSFORM_ID_START + (get_particle_id(iPtr) % MODEL_PARTICLE_ID_MAX) * MARKER_TRANSFORM_ID_COUNT;
|
||||
|
||||
modelRender_draw(gfx, mtx, position, iPtr->rotation, iPtr->scale, NULL, this->model_20);
|
||||
|
||||
// @recomp Reset the current model transform ID.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(this->unk34){//L802EEFC4
|
||||
if( this->rgb[0] != 0xff
|
||||
|| this->rgb[1] != 0xff
|
||||
|| this->rgb[2] != 0xff
|
||||
|| this->alpha != 0xff
|
||||
){
|
||||
func_803382E4((this->draw_mode & PART_EMIT_NO_DEPTH)? 9: 0xf);
|
||||
func_80338338(this->rgb[0], this->rgb[1], this->rgb[2]);
|
||||
func_803382B4(
|
||||
(this->rgb[0] < 8)? 0 : this->rgb[0] - 8,
|
||||
(this->rgb[1] < 8)? 0 : this->rgb[1] - 8,
|
||||
(this->rgb[2] < 8)? 0 : this->rgb[2] - 8,
|
||||
(this->draw_mode & PART_EMIT_NO_OPA)? 0xff : this->alpha
|
||||
);
|
||||
func_80338370();
|
||||
func_80335D30(gfx);
|
||||
}
|
||||
else if(this->draw_mode & PART_EMIT_NO_DEPTH){//L802EF0C0
|
||||
gSPDisplayList((*gfx)++, D_80368978);
|
||||
}
|
||||
else{//L802EF0EC
|
||||
gSPDisplayList((*gfx)++, D_80368940);
|
||||
}//L802EF10C
|
||||
flat_rotation[0] = 90.0f;
|
||||
flat_rotation[1] = 0.0f;
|
||||
flat_rotation[2] = 0.0f;
|
||||
for(iPtr = this->pList_start_124; iPtr < this->pList_end_128; iPtr++){
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, this->rgb[0], this->rgb[1], this->rgb[2], iPtr->fade*this->alpha);
|
||||
position[0] = iPtr->position[0] + this->unk4[0];
|
||||
position[1] = iPtr->position[1] + this->unk4[1];
|
||||
position[2] = iPtr->position[2] + this->unk4[2];
|
||||
|
||||
scale[0] = iPtr->scale;
|
||||
scale[1] = iPtr->scale;
|
||||
scale[2] = iPtr->scale;
|
||||
if(0.0f != this->unk108){
|
||||
func_802EED1C(this, iPtr->age_48, scale);
|
||||
}
|
||||
func_80344C2C(this->unk0_16);
|
||||
// @recomp Get the particle's ID and use it to set a matrix group for this particle.
|
||||
u32 transform_id = NORMAL_PARTICLE_TRANSFORM_ID_START + get_particle_id(iPtr);
|
||||
gEXMatrixGroupDecomposedNormal((*gfx)++, transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
if(this->draw_mode & PART_EMIT_ROTATABLE){
|
||||
func_80344720(this->unk34, (s32)iPtr->frame, 0, position, flat_rotation, scale, gfx, mtx);
|
||||
}//L802EF2F8
|
||||
else{
|
||||
func_80344424(this->unk34, (s32)iPtr->frame, 0, position, scale, iPtr->rotation[2], gfx, mtx);
|
||||
}//L802EF324
|
||||
|
||||
// @recomp Pop the particle's matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
}//L802EF338
|
||||
if( this->rgb[0] != 0xff || this->rgb[1] != 0xff || this->rgb[2] != 0xff || this->alpha != 0xff
|
||||
){
|
||||
func_8033687C(gfx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set an incrementing ID for the particle.
|
||||
RECOMP_PATCH void __particleEmitter_initParticle(ParticleEmitter *this, Particle *particle){
|
||||
particle->acceleration[0] = randf2(this->particleAccerationRange_4C_min_x, this->particleAccerationRange_4C_max_x);
|
||||
particle->acceleration[1] = randf2(this->particleAccerationRange_4C_min_y, this->particleAccerationRange_4C_max_y);
|
||||
particle->acceleration[2] = randf2(this->particleAccerationRange_4C_min_z, this->particleAccerationRange_4C_max_z);
|
||||
particle->unk5C = this->unk64;
|
||||
|
||||
particle->fade = (0.0f == this->fade_in) ? 1.0f : 0;
|
||||
particle->frame = randf2((f32)this->particleStartingFrameRange_84_min, (f32)this->particleStartingFrameRange_84_max);
|
||||
particle->framerate = randf2(this->particleFramerateRange_8C_min, this->particleFramerateRange_8C_max);
|
||||
|
||||
particle->position[0] = this->postion_28[0];
|
||||
particle->position[1] = this->postion_28[1];
|
||||
particle->position[2] = this->postion_28[2];
|
||||
|
||||
particle->position[0] = particle->position[0] + randf2(this->particleSpawnPositionRange_94_min_x, this->particleSpawnPositionRange_94_max_x);
|
||||
particle->position[1] = particle->position[1] + randf2(this->particleSpawnPositionRange_94_min_y, this->particleSpawnPositionRange_94_max_y);
|
||||
particle->position[2] = particle->position[2] + randf2(this->particleSpawnPositionRange_94_min_z, this->particleSpawnPositionRange_94_max_z);
|
||||
|
||||
// @recomp This bit of code was copied over from particleEmitter_update. Particles can be attached to entities that can move vertically,
|
||||
// like water surfaces, and will teleport accordingly based on their movement. This can introduce interpolation issues the first time
|
||||
// a particle is updated, as they'll teleport from the spawner's position to the amount that the entity has moved since.
|
||||
//
|
||||
// Replicating the logic here fixes the teleporting ripple particles on levels that change the water level, like the water pyramid in
|
||||
// Gobi's Valley after the jiggy is collected.
|
||||
if (this->unk100) {
|
||||
particle->position[1] = func_8034E698((Struct73s *)(this->unk100)) + this->unk104;
|
||||
}
|
||||
|
||||
particle->initialSize_34 = particle->scale = randf2(this->particleStartingScaleRange_AC_min, this->particleStartingScaleRange_AC_max);
|
||||
if(0.0f == this->particleFinalScaleRange_B4_min && 0.0f == this->particleFinalScaleRange_B4_max)
|
||||
particle->finalSizeDiff = 0.0f;
|
||||
else
|
||||
particle->finalSizeDiff = randf2(this->particleFinalScaleRange_B4_min, this->particleFinalScaleRange_B4_max)- particle->initialSize_34;
|
||||
|
||||
particle->rotation[2] = 0.0f;
|
||||
particle->rotation[1] = 0.0f;
|
||||
particle->rotation[0] = 0.0f;
|
||||
|
||||
particle->angluar_velocity[0] = randf2(this->unkBC[0], this->unkC8[0]);
|
||||
particle->angluar_velocity[1] = randf2(this->unkBC[1], this->unkC8[1]);
|
||||
particle->angluar_velocity[2] = randf2(this->unkBC[2], this->unkC8[2]);
|
||||
|
||||
particle->age_48 = 0.0f;
|
||||
particle->lifetime_4C = randf2(this->particleLifeTimeRange[0], this->particleLifeTimeRange[1]) + 0.001;
|
||||
if(!this->sphericalParticleVelocity_48){
|
||||
particle->velocity_50[0] = randf2(this->particleVelocityRange_E4.cartisian_min_x, this->particleVelocityRange_E4.cartisian_max_x);
|
||||
particle->velocity_50[1] = randf2(this->particleVelocityRange_E4.cartisian_min_y, this->particleVelocityRange_E4.cartisian_max_y);
|
||||
particle->velocity_50[2] = randf2(this->particleVelocityRange_E4.cartisian_min_z, this->particleVelocityRange_E4.cartisian_max_z);
|
||||
}
|
||||
else{
|
||||
func_80256E24(particle->velocity_50,
|
||||
mlNormalizeAngle(randf2(this->particleVelocityRange_E4.spherical.pitch_min, this->particleVelocityRange_E4.spherical.pitch_max)),
|
||||
mlNormalizeAngle(randf2(this->particleVelocityRange_E4.spherical.yaw_min, this->particleVelocityRange_E4.spherical.yaw_max)),
|
||||
0.0f,
|
||||
0.0f,
|
||||
randf2(this->particleVelocityRange_E4.spherical.radius_min, this->particleVelocityRange_E4.spherical.radius_max)
|
||||
);
|
||||
}
|
||||
|
||||
// @recomp Set the particle's ID based on the particle spawn count.
|
||||
set_particle_id(particle, particle_spawn_count);
|
||||
// @recomp Increment the particle spawn count.
|
||||
particle_spawn_count++;
|
||||
if (particle_spawn_count >= NORMAL_PARTICLE_ID_MAX) {
|
||||
particle_spawn_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern void mlMtxRotatePYR(f32, f32, f32);
|
||||
|
||||
typedef struct {
|
||||
BKSprite *sprite_0;
|
||||
f32 position[3];
|
||||
f32 rotation[3];
|
||||
f32 unk1C;
|
||||
s16 unk20[2];
|
||||
u8 color[3];
|
||||
u8 unk27;
|
||||
u32 frame_28_31:8;
|
||||
u32 unk28_23:2;
|
||||
u32 unk28_21:8;
|
||||
u32 unk28_13:1;
|
||||
u32 unk28_12:1;
|
||||
u32 pad28_11:12;
|
||||
} Struct_B8860_0s;
|
||||
|
||||
void projectile_setRoll(u8 indx, f32 angle);
|
||||
f32 projectile_getRoll(u8 indx);
|
||||
void projectile_freeByIndex(u8 arg0);
|
||||
void func_803382FC(s32);
|
||||
void func_80338308(s32 arg0, s32 arg1);
|
||||
void func_8033837C(s32 arg0);
|
||||
void spriteRender_draw(Gfx **gfx, Vtx **vtx, BKSprite *sp, u32 frame);
|
||||
|
||||
#define PROJECTILE_RESET_FLAG 0x1
|
||||
#define PROJECTILE_MOVED_FLAG 0x2
|
||||
|
||||
extern Struct_B8860_0s D_80385000[0x32];
|
||||
u8 projectileSkipFlags[0x32];
|
||||
|
||||
// @recomp Patched to indicate a projectile has been moved.
|
||||
RECOMP_PATCH void projectile_setPosition(u8 indx, f32 position[3]) {
|
||||
ml_vec3f_copy(D_80385000[indx].position, position);
|
||||
|
||||
// @recomp Mark the projectile as moved only if the position is not at the origin.
|
||||
if (ml_isNonzero_vec3f(position)) {
|
||||
projectileSkipFlags[indx] |= PROJECTILE_MOVED_FLAG;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to indicate when projectiles have been reset.
|
||||
RECOMP_PATCH u8 func_8033FA84(void) {
|
||||
int i;
|
||||
for (i = 1; i < 0x32; i++) {
|
||||
if (!D_80385000[i].unk28_13) {
|
||||
ml_vec3f_clear(D_80385000[i].position);
|
||||
ml_vec3f_clear(D_80385000[i].rotation);
|
||||
D_80385000[i].frame_28_31 = 0;
|
||||
D_80385000[i].unk28_13 = TRUE;
|
||||
D_80385000[i].unk28_23 = 0;
|
||||
D_80385000[i].unk28_21 = 0xb;
|
||||
D_80385000[i].sprite_0 = NULL;
|
||||
D_80385000[i].unk28_12 = TRUE;
|
||||
D_80385000[i].unk20[0] = 100;
|
||||
D_80385000[i].unk20[1] = 100;
|
||||
D_80385000[i].color[0] = 0xff;
|
||||
D_80385000[i].color[1] = 0xff;
|
||||
D_80385000[i].color[2] = 0xff;
|
||||
D_80385000[i].unk27 = 0xff;
|
||||
D_80385000[i].unk1C = 0.0f;
|
||||
|
||||
// @recomp Mark the projectile as reset.
|
||||
projectileSkipFlags[i] = PROJECTILE_RESET_FLAG;
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to tag projectiles.
|
||||
RECOMP_PATCH void func_8033F7F0(u8 indx, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
Struct_B8860_0s *sp54;
|
||||
f32 sp48[3];
|
||||
f32 sp3C[3];
|
||||
f32 sp30[3];
|
||||
|
||||
sp54 = &D_80385000[indx];
|
||||
if(sp54->unk28_23 != 1){
|
||||
ml_vec3f_copy(sp48, sp54->position);
|
||||
sp48[1] += (sp54->unk1C*sp54->unk20[1])/100.0;
|
||||
viewport_getPosition_vec3f(sp3C);
|
||||
ml_vec3f_diff_copy(sp30, sp48, sp3C);
|
||||
if(sp54->unk28_12){
|
||||
mlMtxSet(viewport_getMatrix());
|
||||
}
|
||||
else{
|
||||
mlMtxIdent();
|
||||
}
|
||||
mlMtxRotatePYR(sp54->rotation[0], sp54->rotation[1], sp54->rotation[2]);
|
||||
func_80252330(sp30[0], sp30[1], sp30[2]);
|
||||
mlMtxApply(*mtx);
|
||||
// @recomp Remove unnecessary usage of OS_PHYSICAL_TO_K0 (which should actually be OS_K0_TO_PHYSICAL) to allow extended addresses.
|
||||
gSPMatrix((*gfx)++, /*OS_PHYSICAL_TO_K0*/((*mtx)++), G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
func_803382E4(sp54->unk28_21);
|
||||
func_80338338(sp54->color[0], sp54->color[1],sp54->color[2]);
|
||||
func_803382FC(sp54->unk27);
|
||||
func_80338308(sp54->unk20[0], sp54->unk20[1]);
|
||||
func_8033837C(1);
|
||||
func_80338370();
|
||||
|
||||
// @recomp Set a matrix group before drawing the sprite. Skip interpolation if it was just freed.
|
||||
u32 projectileID = PROJECTILE_TRANSFORM_ID_START + indx;
|
||||
if (projectileSkipFlags[indx] & PROJECTILE_RESET_FLAG) {
|
||||
gEXMatrixGroupSkipAll((*gfx)++, projectileID, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
// @recomp Some projectiles are spawned but not used right away and are visible at (0, 0, 0) due to a bug
|
||||
// (visible on the magic carpets and jiggies), so the reset flag is not cleared until the projectile is moved.
|
||||
if (projectileSkipFlags[indx] & PROJECTILE_MOVED_FLAG) {
|
||||
projectileSkipFlags[indx] &= ~PROJECTILE_RESET_FLAG;
|
||||
}
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, projectileID, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
}
|
||||
|
||||
spriteRender_draw(gfx, vtx, sp54->sprite_0, sp54->frame_28_31);
|
||||
gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@
|
||||
#define osCreateMesgQueue osCreateMesgQueue_recomp
|
||||
void osWriteBackDCacheAll(void);
|
||||
#define bzero bzero_recomp
|
||||
#define bcopy bcopy_recomp
|
||||
#define osDpSetStatus osDpSetStatus_recomp
|
||||
#define malloc malloc_recomp
|
||||
#define free free_recomp
|
||||
@@ -29,10 +28,6 @@ void osWriteBackDCacheAll(void);
|
||||
#define strchr strchr_recomp
|
||||
#define strlen strlen_recomp
|
||||
#define osVirtualToPhysical osVirtualToPhysical_recomp
|
||||
#define osPiStartDma osPiStartDma_recomp
|
||||
#define sinf sinf_recomp
|
||||
#define cosf __cosf_recomp
|
||||
#define osContGetReadData osContGetReadData_recomp
|
||||
|
||||
#include "ultra64.h"
|
||||
#pragma GCC diagnostic push
|
||||
@@ -41,10 +36,6 @@ void osWriteBackDCacheAll(void);
|
||||
#pragma GCC diagnostic pop
|
||||
#include "rt64_extended_gbi.h"
|
||||
|
||||
#ifndef ARRLEN
|
||||
# define ARRLEN(x) ((s32)(sizeof(x) / sizeof(x[0])))
|
||||
#endif
|
||||
|
||||
#ifndef gEXFillRectangle
|
||||
#define gEXFillRectangle(cmd, lorigin, rorigin, ulx, uly, lrx, lry) \
|
||||
G_EX_COMMAND2(cmd, \
|
||||
@@ -56,41 +47,29 @@ void osWriteBackDCacheAll(void);
|
||||
)
|
||||
#endif
|
||||
|
||||
#define gEXMatrixGroupSkipAll(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, id, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_ORDER_LINEAR, edit, G_EX_ASPECT_AUTO, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP)
|
||||
#define gEXMatrixGroupNoInterpolation(cmd, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, G_EX_ID_IGNORE, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_ORDER_LINEAR, edit)
|
||||
|
||||
#define gEXMatrixGroupSkipAllAspect(cmd, id, push, proj, edit, aspect) \
|
||||
gEXMatrixGroup(cmd, id, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_ORDER_LINEAR, edit, aspect, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP)
|
||||
|
||||
#define gEXMatrixGroupSimpleNormal(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, id, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_ASPECT_AUTO, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_AUTO)
|
||||
|
||||
#define gEXMatrixGroupSimpleVerts(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, id, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_ASPECT_AUTO, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_AUTO)
|
||||
|
||||
#define gEXMatrixGroupSimpleVertsSkipRot(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, id, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_ASPECT_AUTO, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_AUTO)
|
||||
#define gEXMatrixGroupInterpolateOnlyTiles(cmd, push, proj, edit) \
|
||||
gEXMatrixGroup(cmd, G_EX_ID_IGNORE, G_EX_INTERPOLATE_SIMPLE, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
|
||||
#define gEXMatrixGroupDecomposedNormal(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_AUTO)
|
||||
|
||||
#define gEXMatrixGroupDecomposedNormalTcs(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_AUTO)
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
|
||||
#define gEXMatrixGroupDecomposedSkipRot(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_AUTO)
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
|
||||
#define gEXMatrixGroupDecomposedSkipPosRot(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_AUTO)
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
|
||||
#define gEXMatrixGroupDecomposedSkipAll(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
|
||||
#define gEXMatrixGroupDecomposedVerts(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_AUTO)
|
||||
|
||||
#define gEXMatrixGroupDecomposedVertsSkipRot(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_AUTO)
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit)
|
||||
|
||||
#define gEXMatrixGroupDecomposedVertsOrderAuto(cmd, id, push, proj, edit) \
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_AUTO, edit, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_AUTO)
|
||||
gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_AUTO, edit)
|
||||
|
||||
typedef int bool;
|
||||
|
||||
@@ -99,10 +78,4 @@ void memcpy(void * dst, void *src, int size);
|
||||
char* strchr(const char* s, int c);
|
||||
int recomp_printf(const char* fmt, ...);
|
||||
|
||||
void set_additional_model_scale(f32 x, f32 y, f32 z);
|
||||
void set_frustum_checks_enabled(int enabled);
|
||||
void set_all_interpolation_skipped(bool skipped);
|
||||
bool all_interpolation_skipped();
|
||||
bool perspective_interpolation_skipped();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "core1/core1.h"
|
||||
|
||||
extern Gfx D_8036C630[];
|
||||
extern Gfx D_8036C690[];
|
||||
|
||||
// @recomp Patched to fix artifacts in the pause menu background when using wide aspect ratios. Rewritten to draw rows instead of tiles to avoid issues when upscaling the effect.
|
||||
RECOMP_PATCH void func_80314BB0(Gfx **gfx, Mtx **mtx, Vtx **vtx, void *frame_buffer_1, void *frame_buffer_2) {
|
||||
s32 x;
|
||||
s32 y;
|
||||
|
||||
gSPDisplayList((*gfx)++, D_8036C630);
|
||||
gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_PHYSICAL_TO_K0(frame_buffer_1));
|
||||
|
||||
#if 1
|
||||
// @recomp New implementation that uses rows instead of tiles. Remove unnecessary usage of osVirtualToPhysical.
|
||||
for (y = 0; y < gFramebufferHeight / 7 + 1; y++) {
|
||||
gDPLoadTextureTile((*gfx)++, /*osVirtualToPhysical*/(frame_buffer_2), G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, gFramebufferHeight,
|
||||
0, y * 7, gFramebufferWidth - 1, MIN((y + 1) * 7, gFramebufferHeight) - 1,
|
||||
NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, 0, 0
|
||||
);
|
||||
gSPScisTextureRectangle((*gfx)++, 0, (y * 7) * 4, gFramebufferWidth * 4, MIN((y + 1) * 7, gFramebufferHeight) * 4,
|
||||
G_TX_RENDERTILE, 0, (y * 7) << 5, 0x400, 0x400
|
||||
);
|
||||
}
|
||||
#else
|
||||
for (y = 0; y < gFramebufferHeight / 32 + 1; y++) {
|
||||
for (x = 0; x < gFramebufferWidth / 32 + 1; x++) {
|
||||
gDPLoadTextureTile((*gfx)++, osVirtualToPhysical(frame_buffer_2), G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, gFramebufferHeight,
|
||||
0x20 * x, 0x20 * y, 0x20 * (x + 1) - 1, 0x20 * (y + 1) - 1,
|
||||
NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, 0, 0
|
||||
);
|
||||
gSPScisTextureRectangle((*gfx)++, (0x20 * x) * 4, (0x20 * y) * 4, 0x20 * (x + 1) * 4, (0x20 * (y + 1) * 4),
|
||||
G_TX_RENDERTILE, (0x20 * x) << 5, (0x20 * y) << 5, 0x400, 0x400
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gSPDisplayList((*gfx)++, D_8036C690);
|
||||
gDPSetColorImage((*gfx)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, gFramebufferWidth, OS_PHYSICAL_TO_K0(gFramebuffers[getActiveFramebuffer()]));
|
||||
}
|
||||
@@ -1,207 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
|
||||
#define TILE_SIZE 32
|
||||
#define TILE_COUNT_X 5
|
||||
#define TILE_COUNT_Y 4
|
||||
#define IMAGE_WIDTH (TILE_SIZE * TILE_COUNT_X)
|
||||
#define IMAGE_HEIGHT (TILE_SIZE * TILE_COUNT_Y)
|
||||
#define FROM_XZ 0
|
||||
#define FROM_YZ 1
|
||||
|
||||
extern f32 D_80368250;
|
||||
extern f32 D_80368360[3];
|
||||
extern f32 D_8037DFF0[3];
|
||||
extern BKModelBin *D_8037DEA8;
|
||||
extern BKModelBin *D_8037DFE8;
|
||||
extern BKModelBin *chBottleBonusBookselfModelBin;
|
||||
extern ActorMarker *D_8037E000;
|
||||
|
||||
extern s32 getGameMode(void);
|
||||
extern s16 *func_8030C704(void);
|
||||
extern void chBottlesBonus_func_802DD080(Gfx **gfx, Mtx **mtx);
|
||||
extern Actor *func_802DF160(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
extern void actor_postdrawMethod(ActorMarker *);
|
||||
extern void chBottlesBonusCursor_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
extern void chBottlesBonus_func_802DD158(Gfx **gfx, Mtx **mtx);
|
||||
extern BKGfxList *model_getDisplayList(BKModelBin *arg0);
|
||||
|
||||
void patch_picture_model(BKModelBin *model_bin, s32 min_xy, s32 max_xy, s32 min_z, s32 max_z, u32 from) {
|
||||
// Use pad0 to indicate if the model's been patched already.
|
||||
if (model_bin->pad0[0] == 0xBA) {
|
||||
return;
|
||||
}
|
||||
|
||||
model_bin->pad0[0] = 0xBA;
|
||||
|
||||
BKGfxList *gfx_list = model_getDisplayList(model_bin);
|
||||
Vtx *vtx_list = model_getVtxList(model_bin)->vtx_18;
|
||||
Gfx *cur_gfx = &gfx_list->list[0];
|
||||
Gfx *end_gfx = (Gfx *)((char *)model_bin + model_bin->vtx_list_offset_10);
|
||||
bool in_framebuffer_tile = FALSE;
|
||||
while (cur_gfx < end_gfx) {
|
||||
if (cur_gfx->words.w0 >> 24 == G_SETTIMG) {
|
||||
in_framebuffer_tile = cur_gfx->words.w1 == 0x04000000;
|
||||
if (in_framebuffer_tile) {
|
||||
// Patch the settimg and the 6 commands after it, replacing with a load of the framebuffer texture.
|
||||
Gfx* g = cur_gfx;
|
||||
Gfx* ng = cur_gfx + 1;
|
||||
u8 fmt = (ng->words.w0 >> 21) & 0x7;
|
||||
gDPLoadTextureTile(g++, 0x04000000, fmt, G_IM_SIZ_16b, 160, 128, 0, 0, 160 - 1, 128 - 1, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
}
|
||||
}
|
||||
else if (cur_gfx->words.w0 >> 24 == G_VTX) {
|
||||
// Patch vertices. Get the loaded vertex count for this command.
|
||||
u32 cur_vtx_count = (cur_gfx->words.w0 >> 10) & 0b111111;
|
||||
|
||||
// Get the vertex address, converting from a segmented address if necessary.
|
||||
Vtx *cur_vtx;
|
||||
if (cur_gfx->words.w1 >> 24 == 0x01) {
|
||||
cur_vtx = (Vtx *)(SEGMENT_OFFSET(cur_gfx->words.w1) + (char *)vtx_list);
|
||||
}
|
||||
else {
|
||||
// Not a segmented address (should never happen, but may help with compatibility for future mods).
|
||||
cur_vtx = (Vtx *)cur_gfx->words.w1;
|
||||
}
|
||||
|
||||
if (in_framebuffer_tile) {
|
||||
if (from == FROM_YZ) {
|
||||
for (u32 i = 0; i < cur_vtx_count; i++) {
|
||||
float xy_frac = (cur_vtx[i].v.ob[1] - (float)min_xy) / (max_xy - min_xy);
|
||||
float z_frac = (cur_vtx[i].v.ob[2] - (float)min_z) / (max_z - min_z);
|
||||
cur_vtx[i].v.tc[0] = z_frac * 160.0f * 64.0f;
|
||||
cur_vtx[i].v.tc[1] = (1.0f - xy_frac) * 128.0f * 64.0f;
|
||||
}
|
||||
}
|
||||
else if (from == FROM_XZ) {
|
||||
for (u32 i = 0; i < cur_vtx_count; i++) {
|
||||
float xy_frac = (cur_vtx[i].v.ob[0] - (float)min_xy) / (max_xy - min_xy);
|
||||
float z_frac = (cur_vtx[i].v.ob[2] - (float)min_z) / (max_z - min_z);
|
||||
cur_vtx[i].v.tc[0] = xy_frac * 160.0f * 64.0f;
|
||||
cur_vtx[i].v.tc[1] = (1.0f - z_frac) * 128.0f * 64.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < cur_vtx_count; i++) {
|
||||
if (cur_vtx[i].v.ob[0] == 568) {
|
||||
cur_vtx[i].v.ob[0] = 567;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur_gfx++;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patches the model for the puzzle to fix the seams.
|
||||
RECOMP_PATCH Actor *chBottlesBonus_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
Actor *sp6C;
|
||||
f32 sp60[3];
|
||||
f32 sp54[3];
|
||||
void *sp50;
|
||||
|
||||
sp6C = marker_getActor(marker);
|
||||
sp50 = func_8030C704(); //grabs frame as texture?
|
||||
if ((sp50 == NULL) || (getGameMode() != GAME_MODE_8_BOTTLES_BONUS))
|
||||
return sp6C;
|
||||
|
||||
chBottlesBonus_func_802DD080(gfx, mtx);
|
||||
{ sp60[0] = 0.0f; sp60[1] = 0.0f; sp60[2] = 0.0f; };
|
||||
{ sp54[0] = 0.0f; sp54[1] = 0.0f; sp54[2] = 0.0f; };
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL);
|
||||
modelRender_draw(gfx, mtx, sp60, NULL, 1.0f, sp54, chBottleBonusBookselfModelBin);
|
||||
modelRender_draw(gfx, mtx, sp60, NULL, 1.0f, sp54, D_8037DEA8);
|
||||
|
||||
gDPSetTextureFilter((*gfx)++, G_TF_POINT);
|
||||
gDPSetColorDither((*gfx)++, G_CD_DISABLE);
|
||||
func_802DF160(gfx, mtx, vtx);
|
||||
func_80253190(gfx);
|
||||
|
||||
gDPSetTextureFilter((*gfx)++, G_TF_POINT);
|
||||
// @recomp Remove unnecessary usage of osVirtualToPhysical to allow extended addresses.
|
||||
gSPSegment((*gfx)++, 0x04, /*osVirtualToPhysical*/(sp50));
|
||||
modelRender_preDraw((GenFunction_1)actor_predrawMethod, (s32)sp6C);
|
||||
modelRender_postDraw((GenFunction_1)actor_postdrawMethod, (s32)marker);
|
||||
|
||||
// @recomp Load and patch the puzzle model.
|
||||
BKModelBin *model_bin = marker_loadModelBin(marker);
|
||||
patch_picture_model(model_bin, 260, 398, -273, -100, FROM_YZ);
|
||||
|
||||
modelRender_draw(gfx, mtx, sp60, NULL, D_80368250, sp54, model_bin);
|
||||
gDPSetTextureFilter((*gfx)++, G_TF_BILERP);
|
||||
gDPSetColorDither((*gfx)++, G_CD_MAGICSQ);
|
||||
chBottlesBonusCursor_draw(gfx, mtx, vtx);
|
||||
chBottlesBonus_func_802DD158(gfx, mtx);
|
||||
return sp6C;
|
||||
}
|
||||
|
||||
// @recomp Patches the model for the background picture to fix the seams.
|
||||
RECOMP_PATCH Actor *func_802DF160(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
Actor *this;
|
||||
void *sp38;
|
||||
|
||||
this = marker_getActor(D_8037E000);
|
||||
sp38 = func_8030C704();
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL);
|
||||
gDPSetTextureFilter((*gfx)++, G_TF_POINT);
|
||||
// @recomp Remove unnecessary usage of osVirtualToPhysical to allow extended addresses.
|
||||
gSPSegment((*gfx)++, 0x04, /*osVirtualToPhysical*/(sp38));
|
||||
modelRender_preDraw((GenFunction_1)actor_predrawMethod, (s32)this);
|
||||
modelRender_postDraw((GenFunction_1)actor_postdrawMethod, (s32)D_8037E000);
|
||||
|
||||
// @recomp Load and patch the picture model.
|
||||
BKModelBin *model_bin = marker_loadModelBin(D_8037E000);
|
||||
patch_picture_model(model_bin, 262, 397, -273, -100, FROM_YZ);
|
||||
|
||||
modelRender_draw(gfx, mtx, &D_80368360, NULL, 1.0f, NULL, model_bin);
|
||||
gDPSetTextureFilter((*gfx)++, G_TF_BILERP);
|
||||
return this;
|
||||
}
|
||||
|
||||
// @recomp Patches the model for the photo to fix the seams.
|
||||
RECOMP_PATCH Actor *func_802DEC00(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
Actor *this;
|
||||
f32 sp58[3];
|
||||
f32 sp4C[3];
|
||||
void *sp48;
|
||||
|
||||
|
||||
this = marker_getActor(marker);
|
||||
sp48 = func_8030C704();
|
||||
|
||||
if ((sp48 == 0) || (getGameMode() != GAME_MODE_A_SNS_PICTURE))
|
||||
return this;
|
||||
|
||||
chBottlesBonus_func_802DD080(gfx, mtx);
|
||||
sp58[0] = 0.0f;
|
||||
sp58[1] = 0.0f;
|
||||
sp58[2] = 50.0f;
|
||||
|
||||
sp4C[0] = 0.0f;
|
||||
sp4C[1] = 0.0f;
|
||||
sp4C[2] = 0.0f;
|
||||
|
||||
D_8037DFF0[0] = 0.0f;
|
||||
D_8037DFF0[1] = 270.0f;
|
||||
D_8037DFF0[2] = 0.0f;
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL);
|
||||
modelRender_draw(gfx, mtx, sp58, NULL, 1.0f, sp4C, D_8037DFE8);
|
||||
gDPSetColorDither((*gfx)++, G_CD_DISABLE);
|
||||
func_80253190(gfx);
|
||||
// @recomp Remove unnecessary usage of osVirtualToPhysical to allow extended addresses.
|
||||
gSPSegment((*gfx)++, 0x04, /*osVirtualToPhysical*/(sp48));
|
||||
modelRender_preDraw((GenFunction_1)actor_predrawMethod, (s32)this);
|
||||
modelRender_postDraw((GenFunction_1)actor_postdrawMethod, (s32)marker);
|
||||
|
||||
// @recomp Load and patch the photo model.
|
||||
BKModelBin *model_bin = marker_loadModelBin(marker);
|
||||
patch_picture_model(model_bin, -55, -5, -6, 34, FROM_XZ);
|
||||
|
||||
modelRender_draw(gfx, mtx, this->position, NULL, 4.5f, sp4C, model_bin);
|
||||
gDPSetTextureFilter((*gfx)++, G_TF_BILERP);
|
||||
gDPSetColorDither((*gfx)++, G_CD_MAGICSQ);
|
||||
chBottlesBonus_func_802DD158(gfx, mtx);
|
||||
return this;
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#define ANIMATED_PILLARBOX_SCALE 0
|
||||
|
||||
extern enum map_e map_get(void);
|
||||
|
||||
#if ANIMATED_PILLARBOX_SCALE
|
||||
f32 pillarbox_scale = 0.0f;
|
||||
#else
|
||||
f32 pillarbox_scale = 1.0f;
|
||||
#endif
|
||||
|
||||
bool pillarbox_active() {
|
||||
switch (map_get()) {
|
||||
case MAP_1E_CS_START_NINTENDO:
|
||||
case MAP_1F_CS_START_RAREWARE:
|
||||
case MAP_20_CS_END_NOT_100:
|
||||
case MAP_7B_CS_INTRO_GL_DINGPOT_1:
|
||||
case MAP_7C_CS_INTRO_BANJOS_HOUSE_1:
|
||||
case MAP_7D_CS_SPIRAL_MOUNTAIN_1:
|
||||
case MAP_7E_CS_SPIRAL_MOUNTAIN_2:
|
||||
case MAP_81_CS_INTRO_GL_DINGPOT_2:
|
||||
case MAP_82_CS_ENTERING_GL_MACHINE_ROOM:
|
||||
case MAP_83_CS_GAME_OVER_MACHINE_ROOM:
|
||||
case MAP_84_CS_UNUSED_MACHINE_ROOM:
|
||||
case MAP_85_CS_SPIRAL_MOUNTAIN_3:
|
||||
case MAP_86_CS_SPIRAL_MOUNTAIN_4:
|
||||
case MAP_87_CS_SPIRAL_MOUNTAIN_5:
|
||||
case MAP_88_CS_SPIRAL_MOUNTAIN_6:
|
||||
case MAP_89_CS_INTRO_BANJOS_HOUSE_2:
|
||||
case MAP_8A_CS_INTRO_BANJOS_HOUSE_3:
|
||||
case MAP_94_CS_INTRO_SPIRAL_7:
|
||||
case MAP_95_CS_END_ALL_100:
|
||||
case MAP_96_CS_END_BEACH_1:
|
||||
case MAP_97_CS_END_BEACH_2:
|
||||
case MAP_98_CS_END_SPIRAL_MOUNTAIN_1:
|
||||
case MAP_99_CS_END_SPIRAL_MOUNTAIN_2:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void pillarbox_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
#if ANIMATED_PILLARBOX_SCALE
|
||||
const f32 pillarbox_scale_speed = 1.0f * time_getDelta();
|
||||
if (pillarbox_active()) {
|
||||
pillarbox_scale = MIN(pillarbox_scale + pillarbox_scale_speed, 1.0f);
|
||||
}
|
||||
else {
|
||||
pillarbox_scale = MAX(pillarbox_scale - pillarbox_scale_speed, 0.0f);
|
||||
}
|
||||
#else
|
||||
if (!pillarbox_active()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
float original_aspect = (float)DEFAULT_FRAMEBUFFER_WIDTH / DEFAULT_FRAMEBUFFER_HEIGHT;
|
||||
float cur_aspect = recomp_get_target_aspect_ratio(original_aspect);
|
||||
float target_aspect = MIN(recomp_get_cutscene_aspect_ratio(), cur_aspect);
|
||||
float target_width = DEFAULT_FRAMEBUFFER_HEIGHT * target_aspect;
|
||||
float wide_width = DEFAULT_FRAMEBUFFER_HEIGHT * cur_aspect;
|
||||
float pillar_width = wide_width - target_width * pillarbox_scale;
|
||||
if (pillar_width >= 0.0f) {
|
||||
u32 prev_ortho_id = cur_ortho_projection_transform_id;
|
||||
cur_ortho_projection_transform_id = PROJECTION_PILLARBOX_TRANSFORM_ID;
|
||||
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
|
||||
Vtx *verts = *vtx;
|
||||
for (s32 ix = -1; ix < 2; ix += 2) {
|
||||
for (s32 iy = 0; iy < 2; iy++) {
|
||||
(*vtx)->v.ob[0] = ix * pillar_width * 2;
|
||||
(*vtx)->v.ob[1] = iy * DEFAULT_FRAMEBUFFER_HEIGHT * 4 - DEFAULT_FRAMEBUFFER_HEIGHT * 2;
|
||||
(*vtx)->v.ob[2] = -0x14;
|
||||
(*vtx)++;
|
||||
}
|
||||
}
|
||||
|
||||
gEXPushOtherMode((*gfx)++);
|
||||
gEXPushCombineMode((*gfx)++);
|
||||
gEXPushGeometryMode((*gfx)++);
|
||||
gSPClearGeometryMode((*gfx)++, G_CULL_BOTH);
|
||||
gDPSetRenderMode((*gfx)++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
|
||||
gDPSetCycleType((*gfx)++, G_CYC_1CYCLE);
|
||||
gDPSetCombineLERP((*gfx)++, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
u32 id = PILLARBOX_RECTANGLE_TRANSFORM_ID_START;
|
||||
for (s32 ix = -1; ix < 2; ix += 2) {
|
||||
guTranslate(*mtx, ix * wide_width * 2, 0.0f, 0.0f);
|
||||
gSPMatrix((*gfx)++, OS_K0_TO_PHYSICAL(*mtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
(*mtx)++;
|
||||
|
||||
gEXMatrixGroupSimpleVerts((*gfx)++, id++, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
gSPVertex((*gfx)++, verts, 4, 0);
|
||||
gSP1Quadrangle((*gfx)++, 0, 1, 3, 2, 0);
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
gEXPopOtherMode((*gfx)++);
|
||||
gEXPopCombineMode((*gfx)++);
|
||||
gEXPopGeometryMode((*gfx)++);
|
||||
|
||||
cur_ortho_projection_transform_id = prev_ortho_id;
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,3 @@ RECOMP_EXPORT int recomp_printf(const char* fmt, ...) {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rmonPrintf_recomp(const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
int ret = _Printf(&proutPrintf, NULL, fmt, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@@ -1,512 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "core1/core1.h"
|
||||
#include "functions.h"
|
||||
#include "../src/core2/gc/zoombox.h"
|
||||
|
||||
extern u16 gScissorBoxLeft;
|
||||
extern u16 gScissorBoxRight;
|
||||
extern u16 gScissorBoxTop;
|
||||
extern u16 gScissorBoxBottom;
|
||||
extern MtxF sViewportMatrix;
|
||||
extern f32 sViewportLookVector[3];
|
||||
extern u32 D_803835E0;
|
||||
void func_802BBD2C(f32 *arg0, f32 *arg1);
|
||||
s32 func_80320708(void);
|
||||
void spawnQueue_unlock(void);
|
||||
void sky_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
bool mapModel_has_xlu_bin(void);
|
||||
void mapModel_opa_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
int game_is_frozen(void);
|
||||
void func_80322E64(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void player_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void func_80302C94(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void jiggylist_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void func_803500D8(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void func_802F2ED0(Struct64s *arg0, Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
Struct64s* func_8032994C(void);
|
||||
void partEmitMgr_drawPass0(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void mapModel_xlu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void func_8032D3D8(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void partEmitMgr_drawPass1(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void func_8034F6F0(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void func_802D520C(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void partEmitMgr_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void func_80350818(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void func_802BBD0C(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
void spawnQueue_lock(void);
|
||||
s32 getGameMode(void);
|
||||
void sfx_rand_sync_to_rand(void);
|
||||
void func_803162B4(GcZoombox *this);
|
||||
void rand_sync_to_sfx_rand(void);
|
||||
void func_80338338(s32, s32, s32);
|
||||
void func_803382FC(s32);
|
||||
void func_803382E4(s32);
|
||||
void func_8033687C(Gfx **);
|
||||
void func_80335D30(Gfx **);
|
||||
void func_80344090(BKSpriteDisplayData *self, s32 frame, Gfx **gfx);
|
||||
void func_802F7B90(s32 arg0, s32 arg1, s32 arg2);
|
||||
void gcpausemenu_zoombox_callback(s32 portrait_id, s32 zoombox_state);
|
||||
|
||||
void actor_predrawMethod(Actor *);
|
||||
void actor_postdrawMethod(ActorMarker *);
|
||||
extern bool D_8037DE84;
|
||||
|
||||
extern struct {
|
||||
s32 unk0;
|
||||
s32 game_mode; //game_mode
|
||||
f32 unk8;
|
||||
s32 unkC; //freeze_scene_flag (used for pause menu)
|
||||
f32 unk10;
|
||||
u8 transition;
|
||||
u8 map;
|
||||
u8 exit;
|
||||
u8 unk17; //reset_on_map_load
|
||||
u8 unk18;
|
||||
u8 unk19;
|
||||
u8 unk1A;
|
||||
u8 unk1B;
|
||||
u8 unk1C;
|
||||
} D_8037E8E0;
|
||||
|
||||
extern void func_80334540(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
extern void func_802E67AC(void);
|
||||
extern void func_802E3BD0(s32 frame_buffer_indx);
|
||||
extern void func_802E67C4(void);
|
||||
extern void func_802E5F10(Gfx **gdl);
|
||||
extern void func_8030C2D4(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
extern s32 func_80335134();
|
||||
extern void func_8032D474(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
extern void gcpausemenu_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
extern void dummy_func_8025AFC0(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
extern void gcdialog_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
extern void itemPrint_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
extern void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
|
||||
extern u32 cur_pushed_text_transform_id;
|
||||
extern u32 cur_pushed_text_transform_origin;
|
||||
extern void pillarbox_draw(Gfx **gdl, Mtx **mptr, Vtx **vptr);
|
||||
|
||||
// @recomp Patched to set the projection transform ID for the main projection.
|
||||
RECOMP_PATCH void func_802E39D0(Gfx **gdl, Mtx **mptr, Vtx **vptr, s32 framebuffer_idx, s32 arg4) {
|
||||
// @recomp Set the perspective projection transform ID.
|
||||
cur_perspective_projection_transform_id = PROJECTION_GAMEPLAY_TRANSFORM_ID;
|
||||
|
||||
Mtx *m_start = *mptr;
|
||||
Vtx *v_start = *vptr;
|
||||
|
||||
scissorBox_SetForGameMode(gdl, framebuffer_idx);
|
||||
D_8037E8E0.unkC = FALSE;
|
||||
func_80334540(gdl, mptr, vptr);
|
||||
if (!arg4) {
|
||||
func_802E67AC();
|
||||
func_802E3BD0(getActiveFramebuffer());
|
||||
func_802E67C4();
|
||||
func_802E5F10(gdl);
|
||||
}
|
||||
if (D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE
|
||||
&& D_8037E8E0.unk19 != 6
|
||||
&& D_8037E8E0.unk19 != 5
|
||||
) {
|
||||
gctransition_draw(gdl, mptr, vptr);
|
||||
}
|
||||
|
||||
if (D_8037E8E0.game_mode == GAME_MODE_8_BOTTLES_BONUS
|
||||
|| D_8037E8E0.game_mode == GAME_MODE_A_SNS_PICTURE
|
||||
) {
|
||||
func_8030C2D4(gdl, mptr, vptr);
|
||||
}
|
||||
|
||||
if (!game_is_frozen() && func_80335134()) {
|
||||
func_8032D474(gdl, mptr, vptr);
|
||||
}
|
||||
|
||||
// @recomp Set the HUD projection transform ID.
|
||||
cur_perspective_projection_transform_id = PROJECTION_HUD_TRANSFORM_ID;
|
||||
|
||||
// @recomp Create a new projection for HUD elements to prevent them from being drawn in world space.
|
||||
// This helps with high framerates, as they no longer have to interpolate in space which would cause minor jittering.
|
||||
|
||||
// @recomp Create a backup of the viewport state. Avoid using viewport_backupState so that calls in the following
|
||||
// functions don't override the saved state.
|
||||
f32 saved_viewport_pos[3];
|
||||
f32 saved_viewport_rot[3];
|
||||
f32 saved_viewport_planes[4][4];
|
||||
f32 saved_viewport_look[3];
|
||||
MtxF saved_viewport_matrix;
|
||||
viewport_getPosition_vec3f(saved_viewport_pos);
|
||||
viewport_getRotation_vec3f(saved_viewport_rot);
|
||||
viewport_getFrustumPlanes(saved_viewport_planes[0], saved_viewport_planes[1], saved_viewport_planes[2], saved_viewport_planes[3]);
|
||||
viewport_getLookVector(saved_viewport_look);
|
||||
saved_viewport_matrix = sViewportMatrix;
|
||||
|
||||
// @recomp Zero out the viewport position and rotation, then update the viewport.
|
||||
viewport_setPosition_f3(0.0f, 0.0f, 0.0f);
|
||||
viewport_setRotation_f3(0.0f, 0.0f, 0.0f);
|
||||
viewport_update();
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr);
|
||||
|
||||
gcpausemenu_draw(gdl, mptr, vptr);
|
||||
if (!game_is_frozen()) {
|
||||
dummy_func_8025AFC0(gdl, mptr, vptr);
|
||||
}
|
||||
|
||||
gcdialog_draw(gdl, mptr, vptr);
|
||||
if (!game_is_frozen()) {
|
||||
itemPrint_draw(gdl, mptr, vptr);
|
||||
}
|
||||
|
||||
printbuffer_draw(gdl, mptr, vptr);
|
||||
|
||||
// @recomp Return to the normal gameplay projection transform ID.
|
||||
cur_perspective_projection_transform_id = PROJECTION_GAMEPLAY_TRANSFORM_ID;
|
||||
|
||||
// @recomp Restore the saved viewport state.
|
||||
viewport_setPosition_vec3f(saved_viewport_pos);
|
||||
viewport_setRotation_vec3f(saved_viewport_rot);
|
||||
viewport_setFrustumPlanes(saved_viewport_planes[0], saved_viewport_planes[1], saved_viewport_planes[2], saved_viewport_planes[3]);
|
||||
ml_vec3f_copy(sViewportLookVector, saved_viewport_look);
|
||||
sViewportMatrix = saved_viewport_matrix;
|
||||
|
||||
if (D_8037E8E0.game_mode != GAME_MODE_A_SNS_PICTURE
|
||||
|| D_8037E8E0.unk19 == 6
|
||||
|| D_8037E8E0.unk19 == 5
|
||||
) {
|
||||
gctransition_draw(gdl, mptr, vptr);
|
||||
}
|
||||
|
||||
// @recomp Draw a pillarbox over the current scene to hide the extended widescreen area if active (e.g. cutscenes).
|
||||
pillarbox_draw(gdl, mptr, vptr);
|
||||
|
||||
finishFrame(gdl);
|
||||
osWritebackDCache(m_start, sizeof(Mtx) * (*mptr - m_start));
|
||||
osWritebackDCache(v_start, sizeof(Vtx) * (*vptr - v_start));
|
||||
|
||||
// @recomp Clear the perspective projection transform ID.
|
||||
cur_perspective_projection_transform_id = 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to set the transform ID for the press start projection.
|
||||
RECOMP_PATCH Actor *chOverlayPressStart_draw(ActorMarker *marker, Gfx **gdl, Mtx **mptr, Vtx **vptr){
|
||||
Actor * actor;
|
||||
f32 sp58[3];
|
||||
f32 sp4C[3];
|
||||
f32 sp40[3];
|
||||
f32 sp34[3];
|
||||
|
||||
|
||||
actor = marker_getActor(marker);
|
||||
if(D_8037DE84)
|
||||
return actor;
|
||||
|
||||
modelRender_preDraw((GenFunction_1)actor_predrawMethod, (s32)actor);
|
||||
modelRender_postDraw((GenFunction_1)actor_postdrawMethod, (s32)marker);
|
||||
viewport_backupState();
|
||||
{sp58[0] = 0.0f; sp58[1] = 0.0f; sp58[2] = 1312.5f;};
|
||||
{sp4C[0] = 0.0f; sp4C[1] = 0.0f; sp4C[2] = 0.0f;};
|
||||
viewport_setPosition_vec3f(sp58);
|
||||
viewport_setRotation_vec3f(sp4C);
|
||||
viewport_update();
|
||||
|
||||
// @recomp Record the current projection transform, then set the projection transform ID for the press start projection.
|
||||
s32 prev_perspective_projection_transform = cur_perspective_projection_transform_id;
|
||||
cur_perspective_projection_transform_id = PROJECTION_PRESS_START_TRANSFORM_ID;
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr);
|
||||
{sp40[0] = 0.0f; sp40[1] = 0.0f; sp40[2] = 0.0f;};
|
||||
{sp34[0] = 0.0f; sp34[1] = 400.0f; sp34[2] = 0.0f;};
|
||||
modelRender_draw(gdl, mptr, sp40, 0, 1.0f, sp34, marker_loadModelBin(marker));
|
||||
|
||||
// @recomp Restore the previous perpsective projection transform ID.
|
||||
cur_perspective_projection_transform_id = prev_perspective_projection_transform;
|
||||
|
||||
viewport_restoreState();
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gdl, mptr);
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
#define ASSET_54D_MODEL_BK_TITLE_LOGO 0x54D
|
||||
#define ASSET_56C_MODEL_THE_END 0x56C
|
||||
|
||||
// @recomp Patched to set the transform ID for the title logo and copyright text projections.
|
||||
RECOMP_PATCH Actor *func_802DC7E0(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
Actor *this;
|
||||
f32 sp58[3];
|
||||
f32 sp4C[3];
|
||||
f32 sp40[3];
|
||||
f32 sp34[3];
|
||||
|
||||
this = marker_getActor(marker);
|
||||
modelRender_preDraw( (GenFunction_1)actor_predrawMethod, (s32)this);
|
||||
modelRender_postDraw((GenFunction_1)actor_postdrawMethod, (s32)marker);
|
||||
viewport_backupState();
|
||||
sp58[0] = 0.0f;
|
||||
sp58[1] = 0.0f;
|
||||
sp58[2] = 860.0f;
|
||||
sp4C[0] = 0.0f;
|
||||
sp4C[1] = 0.0f;
|
||||
sp4C[2] = 0.0f;
|
||||
viewport_setPosition_vec3f(sp58);
|
||||
viewport_setRotation_vec3f(sp4C);
|
||||
viewport_update();
|
||||
|
||||
// @recomp Record the current projection transform, then set the projection transform ID for the projection determined by the model ID.
|
||||
s32 prev_perspective_projection_transform = cur_perspective_projection_transform_id;
|
||||
if (marker->modelId == ASSET_54D_MODEL_BK_TITLE_LOGO) {
|
||||
cur_perspective_projection_transform_id = PROJECTION_BK_LOGO_TRANSFORM_ID;
|
||||
}
|
||||
else if (marker->modelId == ASSET_54E_MODEL_COPYRIGHT_OVERLAY) {
|
||||
cur_perspective_projection_transform_id = PROJECTION_COPYRIGHT_TRANSFORM_ID;
|
||||
}
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
sp40[0] = 0.0f;
|
||||
sp40[1] = 0.0f;
|
||||
sp40[2] = 0.0f;
|
||||
sp34[0] = 0.0f;
|
||||
sp34[1] = -87.0f;
|
||||
sp34[2] = 0.0f;
|
||||
modelRender_draw(gfx, mtx, sp40, NULL, 1.0f, sp34, marker_loadModelBin(marker));
|
||||
|
||||
// @recomp Restore the previous perpsective projection transform ID.
|
||||
cur_perspective_projection_transform_id = prev_perspective_projection_transform;
|
||||
viewport_restoreState();
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
return this;
|
||||
}
|
||||
|
||||
// @recomp Patched to set the transform ID for the game over and THE END projections.
|
||||
RECOMP_PATCH Actor *func_802DC320(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
Actor *this;
|
||||
f32 vp_position[3];
|
||||
f32 vp_rotation[3];
|
||||
f32 model_position[3];
|
||||
f32 sp34[3];
|
||||
|
||||
this = marker_getActor(marker);
|
||||
modelRender_preDraw( (GenFunction_1)actor_predrawMethod, (s32)this);
|
||||
modelRender_postDraw((GenFunction_1)actor_postdrawMethod, (s32)marker);
|
||||
viewport_backupState();
|
||||
vp_position[0] = 0.0f;
|
||||
vp_position[1] = 0.0f;
|
||||
vp_position[2] = 937.5f;
|
||||
vp_rotation[0] = 0.0f;
|
||||
vp_rotation[1] = 0.0f;
|
||||
vp_rotation[2] = 0.0f;
|
||||
viewport_setPosition_vec3f(vp_position);
|
||||
viewport_setRotation_vec3f(vp_rotation);
|
||||
viewport_update();
|
||||
|
||||
// @recomp Record the current projection transform, then set the projection transform ID for the projection determined by the model ID.
|
||||
s32 prev_perspective_projection_transform = cur_perspective_projection_transform_id;
|
||||
if (marker->modelId == ASSET_54C_MODEL_GAME_OVER) {
|
||||
cur_perspective_projection_transform_id = PROJECTION_GAME_OVER_TRANSFORM_ID;
|
||||
}
|
||||
else if (marker->modelId == ASSET_56C_MODEL_THE_END) {
|
||||
cur_perspective_projection_transform_id = PROJECTION_THE_END_TRANSFORM_ID;
|
||||
}
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
model_position[0] = 0.0f;
|
||||
model_position[1] = 0.0f;
|
||||
model_position[2] = 0.0f;
|
||||
sp34[0] = 0.0f;
|
||||
sp34[1] = 137.5f;
|
||||
sp34[2] = 0.0f;
|
||||
modelRender_draw(gfx, mtx, model_position, NULL, 1.0f, sp34, marker_loadModelBin(marker));
|
||||
|
||||
// @recomp Restore the previous perpsective projection transform ID.
|
||||
cur_perspective_projection_transform_id = prev_perspective_projection_transform;
|
||||
viewport_restoreState();
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
return this;
|
||||
}
|
||||
|
||||
bool left_aligned_zoombox(GcZoombox *this) {
|
||||
return !this->unk1A4_15 && this->callback == &gcpausemenu_zoombox_callback;
|
||||
}
|
||||
|
||||
// @recomp Patched to set the zoombox's model transform ID.
|
||||
RECOMP_PATCH void func_803163A8(GcZoombox *this, Gfx **gfx, Mtx **mtx) {
|
||||
f32 sp5C[3];
|
||||
f32 sp50[3];
|
||||
f32 sp44[3];
|
||||
f32 sp38[3];
|
||||
f32 sp34;
|
||||
|
||||
#if 0
|
||||
// @recomp Greenscreen for recording.
|
||||
const u32 half_height = DEFAULT_FRAMEBUFFER_HEIGHT / 2;
|
||||
const u32 uly = (this->unk172 / half_height) * half_height;
|
||||
const u32 blue = 0x003F003F;
|
||||
const u32 green = 0x07C107C1;
|
||||
const u32 white = 0xFFFFFFFF;
|
||||
gDPSetCycleType((*gfx)++, G_CYC_FILL);
|
||||
gDPSetRenderMode((*gfx)++, G_RM_NOOP, G_RM_NOOP2);
|
||||
gDPSetFillColor((*gfx)++, white);
|
||||
gDPScisFillRectangle((*gfx)++, 0, uly, DEFAULT_FRAMEBUFFER_WIDTH - 1, uly + half_height - 1);
|
||||
#endif
|
||||
|
||||
// @recomp Align the zoombox to the left of the screen if necessary.
|
||||
// NOTE: gScissorBoxRight/gScissorBoxTop are incorrectly named in the decompilation and must be swapped.
|
||||
if (left_aligned_zoombox(this)) {
|
||||
gEXPushScissor((*gfx)++);
|
||||
gEXSetScissor((*gfx)++, G_SC_NON_INTERLACE, G_EX_ORIGIN_LEFT, G_EX_ORIGIN_RIGHT, 0, gScissorBoxRight, 0, gScissorBoxBottom);
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_LEFT, 0, 0);
|
||||
}
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
|
||||
sp34 = viewport_transformCoordinate(this->unk170, this->unk172, sp50, sp5C);
|
||||
if (this->unk1A4_24) {
|
||||
sp5C[1] += 180.0f;
|
||||
sp5C[0] -= 2*sp5C[0];
|
||||
}
|
||||
sp38[0] = 0.0f; sp38[1] = 0.0f; sp38[2] = 0.0f;
|
||||
sp44[0] = 0.0f; sp44[1] = 0.0f; sp44[2] = 0.0f;
|
||||
func_8033A308(sp44);
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_NONE);
|
||||
if (this->anim_ctrl != NULL) {
|
||||
anctrl_drawSetup(this->anim_ctrl, sp50, 1);
|
||||
}
|
||||
|
||||
// @recomp Set the model transform ID. Skip interpolation when the camera does a cut.
|
||||
u32 prev_transform_id = cur_drawn_model_transform_id;
|
||||
cur_drawn_model_transform_id = ZOOMBOX_TRANSFORM_ID_START + this->portrait_id;
|
||||
|
||||
#if 1
|
||||
modelRender_draw(gfx, mtx, sp50, sp5C, this->unk198 * sp34, sp38, this->model);
|
||||
#endif
|
||||
|
||||
// @recomp Reset the model transform ID.
|
||||
cur_drawn_model_transform_id = prev_transform_id;
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
if (left_aligned_zoombox(this)) {
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_NONE, 0, 0);
|
||||
gEXPopScissor((*gfx)++);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set the zoombox portrait's model and ortho projection transform IDs.
|
||||
RECOMP_PATCH void func_803164B0(GcZoombox *this, Gfx **gfx, Mtx **mtx, s32 arg3, s32 arg4, BKSpriteDisplayData *arg5, f32 arg6) {
|
||||
f32 sp2C[3];
|
||||
f32 temp_f12;
|
||||
|
||||
if (this->portrait_id == ZOOMBOX_SPRITE_46_TUMBLAR) {
|
||||
arg6 = 0.75f;
|
||||
}
|
||||
|
||||
#if 0
|
||||
arg6 = arg6 < 1.0f ? 0.0f : 1.0f;
|
||||
#endif
|
||||
|
||||
func_80338338(0xFF, 0xFF, 0xFF);
|
||||
func_803382FC(this->unk168 * arg6);
|
||||
func_803382E4(5);
|
||||
func_80335D30(gfx);
|
||||
|
||||
// @recomp Set the ortho projection transform ID for the portrait.
|
||||
u32 prev_ortho_id = cur_ortho_projection_transform_id;
|
||||
cur_ortho_projection_transform_id = PROJECTION_PORTRAIT_TRANSFORM_ID_START + this->portrait_id;
|
||||
|
||||
// @recomp Align the zoombox's portrait to the left of the screen if necessary.
|
||||
// NOTE: gScissorBoxRight/gScissorBoxTop are incorrectly named in the decompilation and must be swapped.
|
||||
if (left_aligned_zoombox(this)) {
|
||||
gEXPushScissor((*gfx)++);
|
||||
gEXSetScissor((*gfx)++, G_SC_NON_INTERLACE, G_EX_ORIGIN_LEFT, G_EX_ORIGIN_RIGHT, 0, gScissorBoxRight, 0, gScissorBoxBottom);
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_LEFT, 0, 0);
|
||||
}
|
||||
|
||||
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
|
||||
// @recomp Reset the ortho projection transform ID.
|
||||
cur_ortho_projection_transform_id = prev_ortho_id;
|
||||
|
||||
mlMtxIdent();
|
||||
if (this->unk1A4_24) {
|
||||
mlMtxRotYaw(180.0f);
|
||||
sp2C[0] = (f32) this->unk170 - ((f32) arg3 * this->unk198);
|
||||
} else {
|
||||
sp2C[0] = (f32) this->unk170 + ((f32) arg3 * this->unk198);
|
||||
}
|
||||
sp2C[1] = this->unk172 + ((f32) arg4 * this->unk198);
|
||||
sp2C[2] = -10.0f;
|
||||
func_80252330((sp2C[0] * 4.0f) - ((f32)gFramebufferWidth * 2), ((f32)gFramebufferHeight * 2) - (sp2C[1] * 4.0f), sp2C[2]);
|
||||
temp_f12 = (f32) ((f64) this->unk198 * 0.8);
|
||||
mlMtxScale_xyz(temp_f12, temp_f12, 1.0f);
|
||||
mlMtxApply(*mtx);
|
||||
gSPMatrix((*gfx)++, (*mtx)++, G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Create a matrix group for the portrait's model matrix.
|
||||
gEXMatrixGroupDecomposedVerts((*gfx)++, ZOOMBOX_PORTRAIT_TRANSFORM_ID_START + this->portrait_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
|
||||
#if 1
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_NONE);
|
||||
func_80344090(arg5, this->unk186, gfx);
|
||||
func_8033687C(gfx);
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
#endif
|
||||
|
||||
// @recomp Pop the model matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
|
||||
if (left_aligned_zoombox(this)) {
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_NONE, 0, 0);
|
||||
gEXPopScissor((*gfx)++);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to assign an ID to the text drawn by the zoombox.
|
||||
RECOMP_PATCH void func_803162B4(GcZoombox *this) {
|
||||
#if 1
|
||||
// @recomp Align the zoombox to the left of the screen if necessary.
|
||||
if (left_aligned_zoombox(this)) {
|
||||
cur_pushed_text_transform_origin = G_EX_ORIGIN_LEFT;
|
||||
}
|
||||
|
||||
// @recomp Only push the transform ID while the text is actively scrolling or has finished scrolling. It is
|
||||
// necessary to switch the IDs around when it has finished scrolling so the previous text finishes interpolation
|
||||
// and doesn't skip ahead for one frame.
|
||||
if (this->state == 1 || this->state == 4) {
|
||||
cur_pushed_text_transform_id = ZOOMBOX_PRINT_TRANSFORM_ID_START + (this->portrait_id * 2 + (this->state == 1)) * ZOOMBOX_PRINT_TRANSFORM_ID_COUNT;
|
||||
}
|
||||
|
||||
func_802F7B90(this->unk168, this->unk168, this->unk168);
|
||||
if (this->unk1A4_30) {
|
||||
if (this->unk1A4_17) {
|
||||
func_802F79D0(this->unk16A, this->unk16C, this->unk0, this->unk166, -1);
|
||||
}
|
||||
else if (this->unk1A4_15) {
|
||||
print_bold_spaced(this->unk16A, this->unk16C, this->unk0);
|
||||
}
|
||||
else {
|
||||
print_dialog(this->unk16A, this->unk16C, this->unk0);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Only interpolate the second line of text while scrolling. The second line isn't moving nor is visible
|
||||
// after finishing scrolling.
|
||||
if (this->state == 4) {
|
||||
cur_pushed_text_transform_id = ZOOMBOX_PRINT_TRANSFORM_ID_START + (this->portrait_id * 2 + 1) * ZOOMBOX_PRINT_TRANSFORM_ID_COUNT;
|
||||
}
|
||||
|
||||
if (this->unk1A4_29) {
|
||||
if (this->unk1A4_15) {
|
||||
print_bold_spaced(this->unk16A, this->unk16E, this->unk30);
|
||||
}
|
||||
else {
|
||||
print_dialog(this->unk16A, this->unk16E, this->unk30);
|
||||
}
|
||||
}
|
||||
func_802F7B90(0xff, 0xff, 0xff);
|
||||
|
||||
if (left_aligned_zoombox(this)) {
|
||||
cur_pushed_text_transform_origin = G_EX_ORIGIN_NONE;
|
||||
}
|
||||
|
||||
// @recomp Clear ID assigned to the text.
|
||||
cur_pushed_text_transform_id = 0;
|
||||
#endif
|
||||
}
|
||||
@@ -1,422 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "prop.h"
|
||||
#include "actor.h"
|
||||
#include "functions.h"
|
||||
#include "object_extension_funcs.h"
|
||||
#include "bk_api.h"
|
||||
#include "core2/coords.h"
|
||||
#include "core2/file.h"
|
||||
#include "note_saving.h"
|
||||
|
||||
// Max props per cube, limited by cube->prop2Cnt which is only 6 bits.
|
||||
#define CUBE_MAX_PROPS 63
|
||||
// Hardcoded cube limit, TODO implement a better solution that doesn't involve dedicating this much memory and allows for larger cube counts.
|
||||
#define MAX_CUBES 4000
|
||||
|
||||
typedef struct {
|
||||
u32 prop_handles[CUBE_MAX_PROPS];
|
||||
} CubeHandle;
|
||||
|
||||
CubeHandle all_cube_handles[MAX_CUBES];
|
||||
CubeHandle cube_3C_handle;
|
||||
CubeHandle cube_40_handle;
|
||||
|
||||
extern s32 *D_8036A9E0;
|
||||
extern s32 D_80383450[0x40];
|
||||
|
||||
void vtxList_getBounds_s32(BKVertexList *, s32[3], s32[3]);
|
||||
enum map_e map_get(void);
|
||||
void code7AF80_initCubeFromFile(File *file_ptr, Cube *cube);
|
||||
bool func_80305D14(void);
|
||||
void func_80305CD8(s32 idx, s32 count);
|
||||
s32 func_803058C0(f32 arg0);
|
||||
void code_A5BC0_initCubePropActorProp(Cube*);
|
||||
void func_80332B2C(ActorMarker * arg0);
|
||||
void bitfield_free(s32 *arg0);
|
||||
void func_8032DE78(SpriteProp *sprite_prop, enum asset_e *sprite_id_ptr);
|
||||
|
||||
extern struct {
|
||||
Cube *cubes;
|
||||
f32 margin;
|
||||
s32 min[3];
|
||||
s32 max[3];
|
||||
s32 stride[2];
|
||||
s32 cubeCnt;
|
||||
s32 unk2C;
|
||||
s32 width[3];
|
||||
Cube *unk3C; // fallback cube?
|
||||
Cube *unk40; // some other fallback cube?
|
||||
s32 unk44; // index of some sort
|
||||
} sCubeList;
|
||||
|
||||
typedef struct {
|
||||
s16 map_id; //enum map_e
|
||||
s16 opa_model_id; //enum asset_e level_model_id
|
||||
s16 xlu_model_id; //enum asset_e level2_model_id
|
||||
s16 unk6[3]; // min bounds (for cubes?)
|
||||
s16 unkC[3]; // max bounds (for cubes?)
|
||||
// u8 pad12[0x2];
|
||||
f32 scale;
|
||||
}MapModelDescription;
|
||||
|
||||
extern struct {
|
||||
void *unk0;
|
||||
void *unk4;
|
||||
BKCollisionList *collision_opa;
|
||||
BKCollisionList *collision_xlu;
|
||||
BKModel *model_opa;
|
||||
BKModel *model_xlu;
|
||||
BKModelBin *model_bin_opa;
|
||||
BKModelBin *model_bin_xlu;
|
||||
s32 unk20;
|
||||
struct5Bs *unk24;
|
||||
MapModelDescription *description;
|
||||
u8 env_red;
|
||||
u8 env_green;
|
||||
u8 env_blue;
|
||||
f32 scale;
|
||||
}mapModel;
|
||||
|
||||
void recomp_abort(const char* msg);
|
||||
|
||||
// @recomp Patched to verify the cube count is less than the fixed amount.
|
||||
RECOMP_PATCH void mapModel_getCubeBounds(s32 min[3], s32 max[3]) {
|
||||
vtxList_getBounds_s32(model_getVtxList(mapModel.model_bin_opa), min, max);
|
||||
coords_scale(min, max, 1000);
|
||||
min[0] = min[0] + mapModel.description->unk6[0];
|
||||
min[1] = min[1] + mapModel.description->unk6[1];
|
||||
min[2] = min[2] + mapModel.description->unk6[2];
|
||||
max[0] = max[0] + mapModel.description->unkC[0];
|
||||
max[1] = max[1] + mapModel.description->unkC[1];
|
||||
max[2] = max[2] + mapModel.description->unkC[2];
|
||||
|
||||
// @recomp Calculate and validate the cube count.
|
||||
u32 width0 = max[0] - min[0] + 1;
|
||||
u32 width1 = max[1] - min[1] + 1;
|
||||
u32 width2 = max[2] - min[2] + 1;
|
||||
u32 stride0 = width0;
|
||||
u32 stride1 = stride0 * width1;
|
||||
u32 cubeCnt = stride1 * width2;
|
||||
|
||||
if (cubeCnt > MAX_CUBES) {
|
||||
recomp_abort("Cube count too high\n");
|
||||
}
|
||||
}
|
||||
|
||||
CubeHandle* get_cube_handle(Cube *cube) {
|
||||
if (cube == sCubeList.unk3C) {
|
||||
return &cube_3C_handle;
|
||||
}
|
||||
else if (cube == sCubeList.unk40) {
|
||||
return &cube_40_handle;
|
||||
}
|
||||
else {
|
||||
s32 cube_index = cube - sCubeList.cubes;
|
||||
if (cube_index < 0 || cube_index >= sCubeList.cubeCnt) {
|
||||
recomp_printf("Invalid cube index %d\n", cube_index);
|
||||
recomp_abort("Got invalid cube\n");
|
||||
}
|
||||
return &all_cube_handles[cube_index];
|
||||
}
|
||||
}
|
||||
|
||||
// Alloc prop handles:
|
||||
// __codeA5BC0_initProp2Ptr
|
||||
// code7AF80_initCubeFromFile (covered by __code7AF80_initCubeFromFile)
|
||||
|
||||
// Delete prop handles:
|
||||
// func_8032D9C0
|
||||
// cube_free
|
||||
|
||||
// Swap prop handles:
|
||||
// __cube_sort
|
||||
|
||||
// Reset all prop handles candidates:
|
||||
// cubeList_free
|
||||
|
||||
// @recomp Patched to create a handle for the new prop.
|
||||
RECOMP_PATCH Prop *__codeA5BC0_initProp2Ptr(Cube *cube) {
|
||||
Prop *sp1C;
|
||||
|
||||
if (cube->prop2Ptr != NULL) {
|
||||
cube->prop2Cnt++;
|
||||
cube->prop2Ptr = realloc(cube->prop2Ptr, cube->prop2Cnt * sizeof(Prop));
|
||||
} else {
|
||||
cube->prop2Cnt = 1;
|
||||
cube->prop2Ptr = malloc(sizeof(Prop));
|
||||
}
|
||||
sp1C = &cube->prop2Ptr[cube->prop2Cnt-1];
|
||||
sp1C->is_actor = FALSE;
|
||||
code_A5BC0_initCubePropActorProp(cube);
|
||||
|
||||
// @recomp Get the cube's prop handle list.
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
u32 prop_index = cube->prop2Cnt - 1;
|
||||
// TODO prop subtypes.
|
||||
cube_handle->prop_handles[prop_index] = recomp_create_object_data(EXTENSION_TYPE_PROP, 0);
|
||||
|
||||
return sp1C;
|
||||
}
|
||||
|
||||
// @recomp Patched to initialize prop handles after a cube has been loaded.
|
||||
RECOMP_PATCH void __code7AF80_initCubeFromFile(Cube *cube, File* file_ptr) {
|
||||
s32 pad[3];
|
||||
|
||||
// @recomp Get the cube's prop handle list.
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
|
||||
// @recomp Free any prop handles that the cube may already have, as this initialization resets the cube's prop list.
|
||||
for (u32 i = 0; i < cube->prop2Cnt; i++) {
|
||||
recomp_destroy_object_data(EXTENSION_TYPE_PROP, cube_handle->prop_handles[i]);
|
||||
cube_handle->prop_handles[i] = 0;
|
||||
}
|
||||
|
||||
while(!file_isNextByteExpected(file_ptr, 1)) {
|
||||
if (file_getNWords_ifExpected(file_ptr, 0, pad, 3)) {
|
||||
file_getNWords(file_ptr, pad, 3);
|
||||
} else if (!file_getNWords_ifExpected(file_ptr, 2, pad, 3) && file_isNextByteExpected(file_ptr, 3)
|
||||
) {
|
||||
code7AF80_initCubeFromFile(file_ptr, cube);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Initialize prop handles after loading the cube and handle note saving.
|
||||
for (u32 i = 0; i < cube->prop2Cnt; i++) {
|
||||
// TODO prop subtypes.
|
||||
cube_handle->prop_handles[i] = recomp_create_object_data(EXTENSION_TYPE_PROP, 0);
|
||||
|
||||
// Check if this prop is a sprite prop.
|
||||
Prop *prop = &cube->prop2Ptr[i];
|
||||
if (!prop->is_3d && !prop->is_actor) {
|
||||
// Check if this sprite prop is a musical note.
|
||||
|
||||
// Get the asset ID for this sprite prop.
|
||||
enum asset_e sprite_prop_asset_id;
|
||||
func_8032DE78(&prop->spriteProp, &sprite_prop_asset_id);
|
||||
|
||||
if (sprite_prop_asset_id == ASSET_6D6_MODEL_MUSIC_NOTE) {
|
||||
note_saving_handle_static_note(cube, prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to delete the handle for the deleted prop and shift the remaining prop handles.
|
||||
RECOMP_PATCH s32 func_8032D9C0(Cube *cube, Prop* prop){
|
||||
s32 sp24;
|
||||
s32 tmp;
|
||||
|
||||
// @recomp Get the cube's prop handle list.
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
|
||||
sp24 = 0;
|
||||
if(cube->prop2Cnt != 0){
|
||||
// @recomp Delete the handle for the deleted prop.
|
||||
u32 prop_index = prop - cube->prop2Ptr;
|
||||
|
||||
sp24 = prop->is_3d;
|
||||
if(func_80305D14()){
|
||||
func_80305CD8(func_803058C0(prop->unk4[1]), -1);
|
||||
}
|
||||
|
||||
// @recomp Destroy the prop's extension data.
|
||||
recomp_destroy_object_data(EXTENSION_TYPE_PROP, cube_handle->prop_handles[prop_index]);
|
||||
|
||||
if((prop - cube->prop2Ptr) < (cube->prop2Cnt - 1)){
|
||||
memcpy(prop, prop + 1, (s32)(&cube->prop2Ptr[cube->prop2Cnt-1]) - (s32)(prop));
|
||||
// @recomp Shift the prop handles back by 1 to remove the gap.
|
||||
for (u32 cur_prop_index = prop_index; cur_prop_index < cube->prop2Cnt - 1; cur_prop_index++) {
|
||||
cube_handle->prop_handles[cur_prop_index] = cube_handle->prop_handles[cur_prop_index + 1];
|
||||
}
|
||||
// @recomp Clear the handle at the end of the list to account for the list decreasing in size.
|
||||
cube_handle->prop_handles[cube->prop2Cnt - 1] = 0;
|
||||
}
|
||||
cube->prop2Cnt--;
|
||||
if(cube->prop2Cnt){
|
||||
cube->prop2Ptr = realloc(cube->prop2Ptr, cube->prop2Cnt*sizeof(Prop));
|
||||
code_A5BC0_initCubePropActorProp(cube);
|
||||
}else{
|
||||
free(cube->prop2Ptr);
|
||||
cube->prop2Ptr = NULL;
|
||||
}
|
||||
return sp24;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to clear all prop handles for a cube when freeing a cube.
|
||||
RECOMP_PATCH void cube_free(Cube *cube){
|
||||
Prop *iProp;
|
||||
|
||||
// @recomp Get the cube's prop handle list.
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
|
||||
// @recomp Delete and clear the cube's prop handles.
|
||||
for (u32 prop_index = 0; prop_index < cube->prop2Cnt; prop_index++) {
|
||||
recomp_destroy_object_data(EXTENSION_TYPE_PROP, cube_handle->prop_handles[prop_index]);
|
||||
cube_handle->prop_handles[prop_index] = 0;
|
||||
}
|
||||
|
||||
if(cube->prop2Ptr){
|
||||
for(iProp = cube->prop2Ptr; iProp < cube->prop2Ptr +cube->prop2Cnt; iProp++){
|
||||
if(iProp->is_actor){
|
||||
func_80332B2C(iProp->actorProp.marker);
|
||||
}
|
||||
}
|
||||
free(cube->prop2Ptr);
|
||||
cube->prop2Ptr = NULL;
|
||||
}
|
||||
if(cube->prop1Ptr){
|
||||
free(cube->prop1Ptr);
|
||||
cube->prop1Ptr = NULL;
|
||||
}
|
||||
cube->prop2Cnt = 0;
|
||||
cube->prop1Cnt = 0;
|
||||
cube->unk0_4 = 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to swap prop handles when sorting a cube's props.
|
||||
RECOMP_PATCH void __cube_sort(Cube *cube, bool global) {
|
||||
s32 ref_position[3];
|
||||
Prop *var_v1;
|
||||
Prop *start_prop;
|
||||
s32 temp_a2;
|
||||
Prop *var_t1;
|
||||
Prop * var_a3;
|
||||
Prop * var_t0;
|
||||
s32 i;
|
||||
Prop *new_var;
|
||||
|
||||
// @recomp Get the cube's prop handle list.
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
|
||||
if (cube->prop2Cnt >= 2) {
|
||||
if (global == 0) {
|
||||
viewport_getPosition_vec3w(ref_position); //distance from viewport
|
||||
} else {
|
||||
ref_position[0] = 0;
|
||||
ref_position[1] = 0;
|
||||
ref_position[2] = 0;
|
||||
}
|
||||
|
||||
//calculate prop distances
|
||||
new_var = var_v1 = cube->prop2Ptr;
|
||||
for(i = 0; i < cube->prop2Cnt; var_v1++, i++){
|
||||
D_80383450[i] = (var_v1->actorProp.x - ref_position[0])*(var_v1->actorProp.x - ref_position[0])
|
||||
+ (var_v1->actorProp.y - ref_position[1])* (var_v1->actorProp.y - ref_position[1])
|
||||
+ (var_v1->actorProp.z - ref_position[2])* (var_v1->actorProp.z - ref_position[2]);
|
||||
}
|
||||
|
||||
//sort prop list
|
||||
start_prop = cube->prop2Ptr;
|
||||
var_t0 = cube->prop2Ptr + (cube->prop2Cnt - 1);
|
||||
do {
|
||||
new_var = start_prop;
|
||||
var_t1 = var_t0;
|
||||
start_prop = NULL;
|
||||
var_v1 = new_var;
|
||||
i = (new_var - cube->prop2Ptr);
|
||||
while(var_v1 < var_t1){
|
||||
if(D_80383450[i] < D_80383450[i + 1]){
|
||||
var_t0 = var_v1 + 1;
|
||||
if (start_prop != 0) {
|
||||
var_t0 = var_v1;
|
||||
} else {
|
||||
start_prop = (var_v1 == cube->prop2Ptr) ? var_v1 : var_v1 - 1;
|
||||
}
|
||||
|
||||
//swap_distances
|
||||
temp_a2 = D_80383450[i];
|
||||
D_80383450[i] = D_80383450[i + 1];
|
||||
D_80383450[i + 1] = temp_a2;
|
||||
|
||||
//swap_props
|
||||
temp_a2 = ((s32*)(&var_v1[0]))[0];
|
||||
((s32*)(&var_v1[0]))[0] = ((s32*)(&var_v1[1]))[0];
|
||||
((s32*)(&var_v1[1]))[0] = temp_a2;
|
||||
|
||||
temp_a2 = ((s32*)(&var_v1[0]))[1];
|
||||
((s32*)(&var_v1[0]))[1] = ((s32*)(&var_v1[1]))[1];
|
||||
((s32*)(&var_v1[1]))[1] = temp_a2;
|
||||
|
||||
temp_a2 = ((s32*)(&var_v1[0]))[2];
|
||||
((s32*)(&var_v1[0]))[2] = ((s32*)(&var_v1[1]))[2];
|
||||
((s32*)(&var_v1[1]))[2] = temp_a2;
|
||||
|
||||
// @recomp Swap prop extension data handles.
|
||||
u32 temp_handle = cube_handle->prop_handles[i];
|
||||
cube_handle->prop_handles[i] = cube_handle->prop_handles[i + 1];
|
||||
cube_handle->prop_handles[i + 1] = temp_handle;
|
||||
}
|
||||
|
||||
var_v1++;
|
||||
i++;
|
||||
}
|
||||
} while (start_prop != NULL);
|
||||
code_A5BC0_initCubePropActorProp(cube);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to reset the prop handle list.
|
||||
RECOMP_PATCH void cubeList_free(){
|
||||
Cube *iCube;
|
||||
|
||||
for(iCube = sCubeList.cubes; iCube < sCubeList.cubes + sCubeList.cubeCnt; iCube++){
|
||||
cube_free(iCube);
|
||||
}
|
||||
free(sCubeList.cubes);
|
||||
|
||||
if(sCubeList.unk3C){
|
||||
cube_free(sCubeList.unk3C);
|
||||
free(sCubeList.unk3C);
|
||||
}
|
||||
|
||||
if(sCubeList.unk40){
|
||||
cube_free(sCubeList.unk40);
|
||||
free(sCubeList.unk40);
|
||||
}
|
||||
bitfield_free(D_8036A9E0);
|
||||
D_8036A9E0 = NULL;
|
||||
|
||||
// @recomp Reset the prop handle list.
|
||||
recomp_clear_all_object_data(EXTENSION_TYPE_PROP);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT PropExtensionId bkrecomp_extend_prop_all(u32 size) {
|
||||
return recomp_register_object_extension_generic(EXTENSION_TYPE_PROP, size);
|
||||
}
|
||||
|
||||
RECOMP_EXPORT void *bkrecomp_get_extended_prop_data(Cube* cube, Prop* prop, PropExtensionId extension_id) {
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
s32 prop_index = prop - cube->prop2Ptr;
|
||||
if (prop_index < 0 || prop_index >= cube->prop2Cnt) {
|
||||
recomp_printf("bkrecomp_get_extended_prop_data: Invalid Cube/Prop pair\n");
|
||||
recomp_abort("Fatal error in mod - Invalid call to bkrecomp_get_extended_prop_data");
|
||||
}
|
||||
|
||||
// TODO prop subtypes.
|
||||
void* data = recomp_get_object_data(EXTENSION_TYPE_PROP, 0, cube_handle->prop_handles[prop_index], extension_id);
|
||||
if (data == NULL) {
|
||||
recomp_printf("bkrecomp_get_extended_prop_data: Invalid extension id 0x%08X\n", extension_id);
|
||||
recomp_abort("Fatal error in mod - Invalid call to bkrecomp_get_extended_prop_data");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
RECOMP_EXPORT u32 bkrecomp_get_prop_spawn_index(Cube* cube, Prop* prop) {
|
||||
CubeHandle* cube_handle = get_cube_handle(cube);
|
||||
s32 prop_index = prop - cube->prop2Ptr;
|
||||
if (prop_index < 0 || prop_index >= cube->prop2Cnt) {
|
||||
recomp_printf("bkrecomp_get_prop_spawn_index: Invalid Cube/Prop pair\n");
|
||||
recomp_abort("Fatal error in mod - Invalid call to bkrecomp_get_prop_spawn_index");
|
||||
}
|
||||
|
||||
u32 spawn_index = recomp_get_object_spawn_index(EXTENSION_TYPE_PROP, cube_handle->prop_handles[prop_index]);
|
||||
if (spawn_index == 0xFFFFFFFF) {
|
||||
recomp_printf("bkrecomp_get_prop_spawn_index: Internal error\n");
|
||||
recomp_abort("Fatal error - Internal error in bkrecomp_get_prop_spawn_index");
|
||||
}
|
||||
|
||||
return spawn_index;
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "bk_api.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
#include "core2/vla.h"
|
||||
|
||||
typedef union{
|
||||
struct{
|
||||
u32 pad31: 27;
|
||||
u32 unk4: 1;
|
||||
u32 pad3: 1;
|
||||
u32 unk2: 1;
|
||||
u32 unk1: 1;
|
||||
u32 unk0: 1;
|
||||
};
|
||||
u32 word;
|
||||
} tmp_bitfield;
|
||||
|
||||
extern vector(ActorMarker *) *D_80383550;
|
||||
extern vector(ActorMarker *) *D_80383554;
|
||||
|
||||
void propModelList_drawSprite(Gfx **, Mtx **, Vtx **, f32[3], f32, s32, Cube*,s32 ,s32, s32, s32, s32);
|
||||
void propModelList_drawModel(Gfx **, Mtx **, Vtx **, f32[3], f32[3], f32, s32, Cube*);
|
||||
void __marker_draw(ActorMarker *this, Gfx **gfx, Mtx **mtx, Vtx **vtx);
|
||||
void __cube_sort(Cube *cube, bool global);
|
||||
void func_8032CD60(Prop *);
|
||||
|
||||
// @recomp Patched to add transform tagging when drawing sprite and model props.
|
||||
RECOMP_PATCH void func_8032D510(Cube *cube, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
Prop *iProp;
|
||||
int i;
|
||||
f32 position[3];
|
||||
f32 rotation[3];
|
||||
tmp_bitfield tmp_v0;
|
||||
int iOffset;
|
||||
ActorMarker **markerPtr;
|
||||
|
||||
if(cube->prop2Cnt == 0 ) return;
|
||||
|
||||
__cube_sort(cube, 0);
|
||||
iOffset = 0;
|
||||
for(i = 0; i < cube->prop2Cnt; i++){//L8032D5A0
|
||||
iOffset = i * 0xC;
|
||||
iProp = (Prop *)((s32)cube->prop2Ptr + iOffset);
|
||||
tmp_v0.word = *(u32 *)((s32)iProp + 0x8);
|
||||
if(!tmp_v0.unk4){
|
||||
|
||||
}else{
|
||||
if(!tmp_v0.unk1){
|
||||
func_8032CD60(iProp);
|
||||
}
|
||||
tmp_v0.word = *(u32 *)((s32)iProp + 0x8);
|
||||
if(tmp_v0.unk0){//actorProp;
|
||||
if(iProp->actorProp.marker->unk40_22){
|
||||
markerPtr = (ActorMarker **)vector_pushBackNew(&D_80383550);
|
||||
*markerPtr = iProp->actorProp.marker;
|
||||
}
|
||||
else if(iProp->actorProp.marker->unk40_19){
|
||||
markerPtr = (ActorMarker **)vector_pushBackNew(&D_80383554);
|
||||
*markerPtr = iProp->actorProp.marker;
|
||||
}
|
||||
else{
|
||||
__marker_draw(iProp->actorProp.marker, gfx, mtx, vtx);
|
||||
}//L8032D62C
|
||||
}
|
||||
else{//L8032D640
|
||||
// @recomp Calculate the base transform ID for the prop.
|
||||
u32 spawn_index = bkrecomp_get_prop_spawn_index(cube, iProp);
|
||||
u32 base_transform_id = spawn_index * PROP_TRANSFORM_ID_COUNT + PROP_TRANSFORM_ID_START;
|
||||
|
||||
position[0] = (f32)iProp->modelProp.position[0];
|
||||
position[1] = (f32)iProp->modelProp.position[1];
|
||||
position[2] = (f32)iProp->modelProp.position[2];
|
||||
if(iProp->is_3d){
|
||||
rotation[0] = 0.0f;
|
||||
rotation[1] = (f32)((s32)iProp->modelProp.yaw*2);
|
||||
rotation[2] = (f32)((s32)iProp->modelProp.roll*2);
|
||||
|
||||
// @recomp Set the model render transform ID before drawing the model.
|
||||
cur_drawn_model_transform_id = base_transform_id;
|
||||
|
||||
propModelList_drawModel(gfx, mtx, vtx,
|
||||
position, rotation, (f32)iProp->modelProp.scale/100.0,
|
||||
iProp->modelProp.model_index, cube
|
||||
);
|
||||
|
||||
|
||||
// @recomp Clear the model render transform ID after drawing the model.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
}
|
||||
else{//L8032D72C
|
||||
// @recomp Set the matrix group before drawing the sprite.
|
||||
// Skip interpolation on vertices to account for vertex lists changing between frames of the sprite.
|
||||
// Also skip interpolation on scale to account for the scale inverting when sprites are mirrored.
|
||||
if (perspective_interpolation_skipped()) {
|
||||
gEXMatrixGroupSkipAll((*gfx)++, base_transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroupDecomposed((*gfx)++, base_transform_id, G_EX_PUSH, G_MTX_MODELVIEW,
|
||||
G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE,
|
||||
G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE,
|
||||
G_EX_ORDER_LINEAR, G_EX_EDIT_NONE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_AUTO);
|
||||
}
|
||||
|
||||
// @recomp Also set the model render transform ID before drawing the sprite. This won't have any effect
|
||||
// in the unmodified game, but will allow transform tagging for mods that draw models in place of sprites.
|
||||
cur_drawn_model_transform_id = base_transform_id;
|
||||
|
||||
propModelList_drawSprite(gfx, mtx, vtx,
|
||||
position, (f32)iProp->spriteProp.scale/100.0, iProp->spriteProp.sprite_index, cube,
|
||||
iProp->spriteProp.r, iProp->spriteProp.b, iProp->spriteProp.g,
|
||||
iProp->spriteProp.mirrored, iProp->spriteProp.frame
|
||||
);
|
||||
|
||||
// @recomp Pop the sprite's matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Clear the model render transform ID after drawing the sprite.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
}
|
||||
}//L8032D7C4
|
||||
}
|
||||
iOffset+=0xC;
|
||||
}//L8032D7D4
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "functions.h"
|
||||
|
||||
extern vector(struct21s) *D_80383CE0[2];
|
||||
|
||||
#define PRINT_DEFRAG_CHANGES 0
|
||||
|
||||
// @recomp Patched to just use a normal DMA.
|
||||
RECOMP_PATCH s32 boot_osPiRawStartDma(s32 direction, u32 devAddr, void *dramAddr, u32 size) {
|
||||
OSMesgQueue mq;
|
||||
OSMesg buffer;
|
||||
OSIoMesg io;
|
||||
osCreateMesgQueue(&mq, &buffer, 1);
|
||||
|
||||
// Complete the DMA synchronously (the game immediately waits until it's done anyways)
|
||||
osPiStartDma(&io, OS_MESG_PRI_HIGH, direction, devAddr, dramAddr, size, &mq);
|
||||
osRecvMesg(&mq, NULL, OS_MESG_BLOCK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to not read hardware registers.
|
||||
RECOMP_PATCH s32 boot_osPiGetStatus() {
|
||||
// PI not busy
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to fix a bug where defrag was used instead of vector_defrag, which would break these vectors
|
||||
// if the defrag call moved the vector's memory.
|
||||
RECOMP_PATCH void func_8033B268(void) {
|
||||
#if PRINT_DEFRAG_CHANGES
|
||||
vector(struct21s) *old_0 = D_80383CE0[0];
|
||||
vector(struct21s) *old_1 = D_80383CE0[1];
|
||||
#endif
|
||||
|
||||
D_80383CE0[0] = (vector(struct21s) *)vector_defrag(D_80383CE0[0]);
|
||||
D_80383CE0[1] = (vector(struct21s) *)vector_defrag(D_80383CE0[1]);
|
||||
|
||||
#if PRINT_DEFRAG_CHANGES
|
||||
if (D_80383CE0[0] != old_0) {
|
||||
recomp_printf("vector_defrag() moved D_80383CE0[0] from 0x%08X to 0x%08X.\n", old_0, D_80383CE0[0]);
|
||||
}
|
||||
|
||||
if (D_80383CE0[1] != old_1) {
|
||||
recomp_printf("vector_defrag() moved D_80383CE0[1] from 0x%08X to 0x%08X.\n", old_1, D_80383CE0[1]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#ifndef __SAVE_EXTENSION_H__
|
||||
#define __SAVE_EXTENSION_H__
|
||||
|
||||
typedef struct {
|
||||
u8 bytes[32]; // 32*8 = 256 bits per level, enough to account for mods with unused vanilla rooms.
|
||||
} LevelNotes;
|
||||
|
||||
// This struct must be 256 bytes to add up to 1536 bytes, which adds to the original 512 bytes of save data to equal exactly 2048 bytes.
|
||||
typedef struct {
|
||||
LevelNotes level_notes[9];
|
||||
u8 padding[32]; // Reserved for future use.
|
||||
} SaveFileExtensionData;
|
||||
|
||||
_Static_assert(sizeof(SaveFileExtensionData) == 320, "SaveExtensionData must be 256 bytes");
|
||||
|
||||
typedef struct {
|
||||
u8 padding[256];
|
||||
} SaveGlobalExtensionData;
|
||||
|
||||
_Static_assert(sizeof(SaveGlobalExtensionData) == 256, "save_global_extension_data must be 512 bytes");
|
||||
|
||||
extern SaveFileExtensionData loaded_file_extension_data;
|
||||
|
||||
#endif
|
||||
@@ -1,169 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "save.h"
|
||||
#include "core1/eeprom.h"
|
||||
#include "save_extension.h"
|
||||
|
||||
// Vanilla declarations.
|
||||
extern SaveData gameFile_saveData[4]; //save_data
|
||||
extern s8 gameFile_GameIdToFileIdMap[4]; //gamenum to filenum
|
||||
extern s32 D_80383F04;
|
||||
|
||||
s32 savedata_8033CA2C(s32 filenum, SaveData *save_data);
|
||||
int savedata_8033CC98(s32 filenum, u8 *buffer);
|
||||
int savedata_8033CCD0(s32 filenum);
|
||||
void __gameFile_8033CE14(s32 gamenum);
|
||||
void savedata_clear(SaveData *savedata);
|
||||
void savedata_update_crc(void *buffer, u32 size);
|
||||
void saveData_load(SaveData *savedata);
|
||||
void saveData_create(SaveData *savedata);
|
||||
|
||||
void bsStoredState_clear(void);
|
||||
void func_8031FFAC(void);
|
||||
void item_setItemsStartCounts(void);
|
||||
void jiggyscore_clearAll(void);
|
||||
void honeycombscore_clear(void);
|
||||
void mumboscore_clear(void);
|
||||
void volatileFlag_clear(void);
|
||||
void func_802D6344(void);
|
||||
|
||||
|
||||
// New declarations.
|
||||
|
||||
// One entry for each file and the backup.
|
||||
SaveFileExtensionData save_file_extension_data[4];
|
||||
SaveFileExtensionData loaded_file_extension_data;
|
||||
|
||||
SaveGlobalExtensionData save_global_extension_data;
|
||||
|
||||
_Static_assert(sizeof(save_file_extension_data) + sizeof(save_global_extension_data) == 1536, "Save extension data must be 1536 bytes");
|
||||
|
||||
// Place save file extensions after the 4K eeprom range.
|
||||
#define SAVE_FILE_EXTENSION_OFFSET (EEPROM_BLOCK_SIZE * EEPROM_MAXBLOCKS)
|
||||
// Number of blocks per save file extension slot.
|
||||
#define SAVE_FILE_EXTENSION_DATA_BLOCK_COUNT (sizeof(SaveFileExtensionData) / EEPROM_BLOCK_SIZE)
|
||||
// Place the global extension data after teh save file extensions
|
||||
#define SAVE_GLOBAL_EXTENSION_OFFSET (SAVE_FILE_EXTENSION_OFFSET + sizeof(save_file_extension_data))
|
||||
|
||||
_Static_assert(sizeof(SaveFileExtensionData) % EEPROM_BLOCK_SIZE == 0, "SaveFileExtensionData size must be a multiple of EEPROM_BLOCK_SIZE");
|
||||
_Static_assert(SAVE_GLOBAL_EXTENSION_OFFSET % EEPROM_BLOCK_SIZE == 0, "SAVE_GLOBAL_EXTENSION_OFFSET must be a multiple of EEPROM_BLOCK_SIZE");
|
||||
|
||||
#define SAVE_FILE_EXTENSION_OFFSET_BLOCKS (SAVE_FILE_EXTENSION_OFFSET / EEPROM_BLOCK_SIZE)
|
||||
#define SAVE_GLOBAL_EXTENSION_OFFSET_BLOCKS (SAVE_GLOBAL_EXTENSION_OFFSET / EEPROM_BLOCK_SIZE)
|
||||
|
||||
// @recomp Patched to load the corresponding file number's extension data.
|
||||
RECOMP_PATCH int __gameFile_8033CD90(s32 filenum){
|
||||
int i;
|
||||
s32 tmp_v1;
|
||||
void *save_data_ptr;
|
||||
save_data_ptr = &gameFile_saveData[filenum];
|
||||
// @recomp Get a pointer to the extension data for this file number.
|
||||
SaveFileExtensionData *extension_ptr = &save_file_extension_data[filenum];
|
||||
i = 3;
|
||||
do{
|
||||
// @recomp Also load the extension data.
|
||||
eeprom_readBlocks(0, SAVE_FILE_EXTENSION_OFFSET_BLOCKS + SAVE_FILE_EXTENSION_DATA_BLOCK_COUNT * filenum, extension_ptr, SAVE_FILE_EXTENSION_DATA_BLOCK_COUNT);
|
||||
|
||||
// Read save data from eeprom for file
|
||||
tmp_v1 = savedata_8033CA2C(filenum, save_data_ptr);
|
||||
|
||||
if(!tmp_v1)
|
||||
break;
|
||||
i--;
|
||||
}while(i != 0);
|
||||
if(tmp_v1) {
|
||||
savedata_clear(save_data_ptr);
|
||||
// @recomp Also clear the extension data.
|
||||
bzero(save_data_ptr, sizeof(*save_data_ptr));
|
||||
}
|
||||
return tmp_v1;
|
||||
}
|
||||
|
||||
// @recomp Patched to save the corresponding file number's extension data.
|
||||
RECOMP_PATCH s32 gameFile_8033CFD4(s32 gamenum){
|
||||
s32 next;
|
||||
s32 filenum;
|
||||
u32 i = 3;
|
||||
s32 eeprom_error;
|
||||
SaveData *save_data;
|
||||
|
||||
|
||||
filenum = D_80383F04;
|
||||
next = gameFile_GameIdToFileIdMap[gamenum];
|
||||
gameFile_GameIdToFileIdMap[gamenum] = D_80383F04;
|
||||
bcopy(&gameFile_saveData[next], &gameFile_saveData[filenum], 0xF*8);
|
||||
// @recomp Also copy the extension data from the next slot.
|
||||
bcopy(&save_file_extension_data[next], &save_file_extension_data[filenum], sizeof(save_file_extension_data[0]));
|
||||
|
||||
save_data = gameFile_saveData + filenum;
|
||||
|
||||
// @recomp Get a pointer to the extension data for this file number.
|
||||
SaveFileExtensionData *extension_ptr = &save_file_extension_data[filenum];
|
||||
|
||||
save_data->slotIndex = gamenum + 1;
|
||||
savedata_update_crc(save_data, sizeof(SaveData));
|
||||
for(eeprom_error = 1; eeprom_error && i > 0; i--){//L8033D070
|
||||
// @recomp Also save the extension data.
|
||||
eeprom_writeBlocks(0, SAVE_FILE_EXTENSION_OFFSET_BLOCKS + SAVE_FILE_EXTENSION_DATA_BLOCK_COUNT * filenum, extension_ptr, SAVE_FILE_EXTENSION_DATA_BLOCK_COUNT);
|
||||
|
||||
eeprom_error = savedata_8033CC98(filenum, save_data);
|
||||
if(!eeprom_error){
|
||||
__gameFile_8033CE14(gamenum);
|
||||
}
|
||||
}
|
||||
if(!eeprom_error){
|
||||
for(i = 3; i > 0; i--){//L8033D070
|
||||
eeprom_error = savedata_8033CCD0(next);
|
||||
if(!eeprom_error)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(eeprom_error){
|
||||
gameFile_GameIdToFileIdMap[gamenum] = next;
|
||||
}
|
||||
else{
|
||||
D_80383F04 = next;
|
||||
}
|
||||
return eeprom_error;
|
||||
}
|
||||
|
||||
// @recomp Patched to clear extended file data.
|
||||
RECOMP_PATCH void gameFile_clear(s32 gamenum){
|
||||
s32 filenum = gameFile_GameIdToFileIdMap[gamenum];
|
||||
savedata_clear(&gameFile_saveData[filenum]);
|
||||
|
||||
// @recomp Clear the extended file data for this file number.
|
||||
bzero(&save_file_extension_data[filenum], sizeof(SaveFileExtensionData));
|
||||
}
|
||||
|
||||
// @recomp Patched to load extended file data.
|
||||
RECOMP_PATCH void gameFile_load(s32 gamenum){
|
||||
s32 filenum = gameFile_GameIdToFileIdMap[gamenum];
|
||||
saveData_load(&gameFile_saveData[filenum]);
|
||||
|
||||
// @recomp Load the extended file data for this file number.
|
||||
memcpy(&loaded_file_extension_data, &save_file_extension_data[filenum], sizeof(SaveFileExtensionData));
|
||||
}
|
||||
|
||||
// @recomp Patched to save extended file data.
|
||||
RECOMP_PATCH void gameFile_save(s32 gamenum){
|
||||
s32 filenum = gameFile_GameIdToFileIdMap[gamenum];
|
||||
saveData_create(&gameFile_saveData[filenum]);
|
||||
|
||||
// @recomp Save the extended file data for this file number.
|
||||
memcpy(&save_file_extension_data[filenum], &loaded_file_extension_data, sizeof(SaveFileExtensionData));
|
||||
}
|
||||
|
||||
// @recomp Patched to clear the current loaded extended file data.
|
||||
RECOMP_PATCH void clearScoreStates(void) {
|
||||
bsStoredState_clear();
|
||||
func_8031FFAC();
|
||||
item_setItemsStartCounts();
|
||||
jiggyscore_clearAll();
|
||||
honeycombscore_clear();
|
||||
mumboscore_clear();
|
||||
volatileFlag_clear();
|
||||
func_802D6344();
|
||||
|
||||
// @recomp Clear the current loaded extended file data.
|
||||
bzero(&loaded_file_extension_data, sizeof(loaded_file_extension_data));
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "core1/core1.h"
|
||||
|
||||
typedef struct {
|
||||
s16 model_id;
|
||||
// u8 pad2[0x2];
|
||||
f32 scale;
|
||||
f32 rotation_speed;
|
||||
}SkyInfo;
|
||||
|
||||
typedef struct {
|
||||
s16 map;
|
||||
// u8 pad2[2];
|
||||
SkyInfo sky_list[3];
|
||||
}MapSkyInfo;
|
||||
|
||||
extern struct
|
||||
{
|
||||
MapSkyInfo *sky_info;
|
||||
BKModel *model[3];
|
||||
BKModelBin *model_bins[3];
|
||||
f32 timer;
|
||||
} gcSky;
|
||||
|
||||
typedef struct {
|
||||
f32 unk0;
|
||||
s32 unk4[4];
|
||||
f32 unk14;
|
||||
}Struct_core2_C97F0_2;
|
||||
|
||||
typedef struct {
|
||||
u8 unk0;
|
||||
// u8 pad1[3];
|
||||
Struct_core2_C97F0_2 unk4[15];
|
||||
}Struct_core2_C97F0_1;
|
||||
|
||||
typedef struct {
|
||||
s16 unk0;
|
||||
f32 unk4[3];
|
||||
u8 unk10;
|
||||
}Struct_core2_C97F0_0;
|
||||
|
||||
extern struct {
|
||||
Struct_core2_C97F0_1 *unk0;
|
||||
Struct_core2_C97F0_0 *unk4;
|
||||
void *unk8;
|
||||
} D_80386170;
|
||||
|
||||
extern struct {
|
||||
u8 unk0;
|
||||
u8 unk1;
|
||||
}D_8038617C;
|
||||
|
||||
extern s32 D_803725A8[4];
|
||||
|
||||
// @recomp Patched to tag the skybox projection and skybox models.
|
||||
RECOMP_PATCH void sky_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
||||
int i;
|
||||
f32 position[3];
|
||||
f32 rotation[3];
|
||||
BKModelBin *iAsset;
|
||||
|
||||
viewport_setNearAndFar(5.0f, 15000.0f);
|
||||
if(gcSky.model_bins[0]){
|
||||
drawRectangle2D(gfx, 0, 0, (s32)(f32) gFramebufferWidth, (s32)(f32)gFramebufferHeight,0, 0, 0); //fill screen with black
|
||||
// @recomp Set the skybox projection matrix group.
|
||||
s32 prev_perspective_projection_transform = cur_perspective_projection_transform_id;
|
||||
cur_perspective_projection_transform_id = PROJECTION_SKYBOX_TRANSFORM_ID;
|
||||
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
viewport_getPosition_vec3f(position);
|
||||
for(i = 0; i < 3; i++){
|
||||
iAsset = gcSky.model_bins[i];
|
||||
if(iAsset){
|
||||
rotation[0] = 0.0f;
|
||||
rotation[1] = gcSky.sky_info->sky_list[i].rotation_speed * gcSky.timer;
|
||||
rotation[2] = 0.0f;
|
||||
|
||||
// @recomp Set the model transform ID before drawing the skybox.
|
||||
cur_drawn_model_transform_id = SKYBOX_TRANSFORM_ID_START + SKYBOX_MODEL_TRANSFORM_ID_COUNT * i;
|
||||
|
||||
modelRender_draw(gfx, mtx, position, rotation, gcSky.sky_info->sky_list[i].scale, NULL, iAsset);
|
||||
|
||||
// @recomp Clear the model transform ID after drawing the skybox.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Restore the previous perpsective projection transform ID.
|
||||
cur_perspective_projection_transform_id = prev_perspective_projection_transform;
|
||||
}
|
||||
else{//L8030B200
|
||||
drawRectangle2D(gfx, 0, 0, (s32)(f32) gFramebufferWidth, (s32)(f32)gFramebufferHeight, 0, 0, 0);
|
||||
}//L8030B254
|
||||
}
|
||||
|
||||
// @recomp Patched to tag the lens flare from the sun.
|
||||
RECOMP_PATCH void func_80350818(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
f32 spDC[3];
|
||||
f32 spD0[3];
|
||||
f32 spC4[3];
|
||||
f32 spB8[3];
|
||||
Struct_core2_C97F0_0 *temp_s1;
|
||||
Struct_core2_C97F0_1 *temp_s2;
|
||||
f32 var_f22;
|
||||
s32 i;
|
||||
f32 sp9C[3];
|
||||
f32 sp90[3];
|
||||
s32 sp80[4];
|
||||
|
||||
temp_s2 = D_80386170.unk0;
|
||||
if (temp_s2 != NULL) {
|
||||
|
||||
}
|
||||
|
||||
temp_s1 = D_80386170.unk4;
|
||||
if ((temp_s1 != NULL) && D_8038617C.unk0) {
|
||||
viewport_getPosition_vec3f(spDC);
|
||||
viewport_getRotation_vec3f(spD0);
|
||||
sp9C[0] = temp_s1->unk4[0];
|
||||
sp9C[1] = temp_s1->unk4[1];
|
||||
sp9C[2] = temp_s1->unk4[2];
|
||||
ml_vec3f_yaw_rotate_copy(sp9C, sp9C, -spD0[1]);
|
||||
ml_vec3f_pitch_rotate_copy(sp9C, sp9C, -spD0[0]);
|
||||
if (!(((1.2 * (f32)gFramebufferWidth) / 2) < sp9C[0]) && !(sp9C[0] < ((-1.2 * (f32)gFramebufferWidth) / 2))) {
|
||||
if (!(((1.2 * (f32)gFramebufferHeight) / 2) < sp9C[1]) && !(sp9C[1] < ((-1.2 * (f32)gFramebufferHeight) / 2))) {
|
||||
sp90[0] = -sp9C[0];
|
||||
sp90[1] = -sp9C[1];
|
||||
sp90[2] = sp9C[2];
|
||||
ml_vec3f_pitch_rotate_copy(sp90, sp90, spD0[0]);
|
||||
ml_vec3f_yaw_rotate_copy(sp90, sp90, spD0[1]);
|
||||
var_f22 = 1.0f - (((sp9C[0] * sp9C[0]) + (sp9C[1] * sp9C[1])) / ((f32)gFramebufferHeight * (f32)gFramebufferHeight));
|
||||
if (var_f22 < 0.0f) {
|
||||
var_f22 = 0.0f;
|
||||
}
|
||||
if (var_f22 > 1.0f) {
|
||||
var_f22 = 1.0f;
|
||||
}
|
||||
spC4[0] = sp90[0] - temp_s1->unk4[0];
|
||||
spC4[1] = sp90[1] - temp_s1->unk4[1];
|
||||
spC4[2] = sp90[2] - temp_s1->unk4[2];
|
||||
for (i = 0; temp_s2->unk4[i].unk0 != 0.0f; i++) {
|
||||
spB8[0] = (spDC[0] + temp_s1->unk4[0]) + (temp_s2->unk4[i].unk0 * spC4[0]);
|
||||
spB8[1] = (spDC[1] + temp_s1->unk4[1]) + (temp_s2->unk4[i].unk0 * spC4[1]);
|
||||
spB8[2] = (spDC[2] + temp_s1->unk4[2]) + (temp_s2->unk4[i].unk0 * spC4[2]);
|
||||
sp80[0] = temp_s2->unk4[i].unk4[0];
|
||||
sp80[1] = temp_s2->unk4[i].unk4[1];
|
||||
sp80[2] = temp_s2->unk4[i].unk4[2];
|
||||
sp80[3] = temp_s2->unk4[i].unk4[3];
|
||||
sp80[3] *= var_f22;
|
||||
modelRender_setPrimAndEnvColors(sp80, D_803725A8);
|
||||
|
||||
// @recomp Set the model transform ID before drawing the lens flare.
|
||||
cur_drawn_model_transform_id = LENS_FLARE_TRANSFORM_ID_START + LENS_FLARE_TRANSFORM_ID_COUNT * i;
|
||||
|
||||
modelRender_draw(gfx, mtx, spB8, spD0, temp_s2->unk4[i].unk14 * 0.25, NULL, D_80386170.unk8);
|
||||
|
||||
// @recomp Clear the model transform ID after drawing the lens flare.
|
||||
cur_drawn_model_transform_id = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
|
||||
typedef struct {
|
||||
u8 pad0[0xC];
|
||||
f32 unkC[3];
|
||||
}Struct_core2_72060_0;
|
||||
|
||||
extern s32 D_80369284;
|
||||
extern s32 D_8036928C;
|
||||
extern f32 D_80381040[3];
|
||||
extern f32 D_8038104C;
|
||||
extern f32 D_80381050[3];
|
||||
extern f32 D_80381060[3];
|
||||
extern f32 D_80381070[3];
|
||||
extern f32 D_80381080[3];
|
||||
extern f32 D_8038108C;
|
||||
extern struct4Cs *D_80369280;
|
||||
extern Struct_core2_72060_0 *D_80381094;
|
||||
extern Gfx *D_80381090;
|
||||
extern BKModelBin *D_80369288;
|
||||
|
||||
extern bool func_802BEF64(void);
|
||||
extern void func_802F8FFC(void);
|
||||
extern void func_8033BD20(BKModelBin **arg0);
|
||||
extern s32 globalTimer_getTime(void);
|
||||
|
||||
#define SNOW_PARTICLE_COUNT_ORIGINAL 100
|
||||
#define SNOW_PARTICLE_COUNT_EXPANDED 256
|
||||
#define SNOW_SKIP_INTERPOLATION_MASK 0x8000
|
||||
|
||||
u16 snowIDArray[SNOW_PARTICLE_COUNT_EXPANDED];
|
||||
u16 snowIDQueue[SNOW_PARTICLE_COUNT_EXPANDED];
|
||||
u16 snowIDQueueCount = 0;
|
||||
struct4Ds snowData[SNOW_PARTICLE_COUNT_EXPANDED];
|
||||
|
||||
extern bool recomp_in_demo_playback_game_mode();
|
||||
|
||||
// @recomp Patched to initialize the ID queue for snow particles.
|
||||
RECOMP_PATCH void func_802F9054(void) {
|
||||
func_802F8FFC();
|
||||
D_80369280 = (struct4Cs *)malloc(sizeof(struct4Cs));
|
||||
D_80369280->unk0[0] = D_80369280->unk0[1] = D_80369280->unk0[2] = 0.0f;
|
||||
D_80369280->unkC[0] = D_80369280->unkC[1] = D_80369280->unkC[2] = 0.0f;
|
||||
D_8036928C = 0;
|
||||
D_80369280->unk1C = snowData;
|
||||
D_80369280->unk18 = 0;
|
||||
D_80369288 = assetcache_get(0x8a1); //2D_light
|
||||
|
||||
// @recomp Initialize the snow ID queue.
|
||||
snowIDQueueCount = 0;
|
||||
while (snowIDQueueCount < SNOW_PARTICLE_COUNT_EXPANDED) {
|
||||
snowIDQueue[snowIDQueueCount] = snowIDQueueCount;
|
||||
snowIDQueueCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to not free the vector.
|
||||
RECOMP_PATCH void func_802F8FFC(void) {
|
||||
if (D_80369280) {
|
||||
// @recomp Don't free the vector.
|
||||
// free(D_80369280->unk1C);
|
||||
|
||||
func_8033BD20(&D_80369288);
|
||||
free(D_80369280);
|
||||
D_80369280 = NULL;
|
||||
D_80369284 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to copy the ID when the snow particle is removed.
|
||||
RECOMP_PATCH void func_802F9134(s32 gfx) {
|
||||
// @recomp Put the deleted ID back on the queue.
|
||||
snowIDQueue[snowIDQueueCount++] = snowIDArray[gfx];
|
||||
|
||||
D_80369284 = D_80369284 - 1;
|
||||
if (gfx < D_80369284) {
|
||||
// @recomp Modified to just be a regular memcpy.
|
||||
memcpy(D_80369280->unk1C + gfx, D_80369280->unk1C + D_80369284, sizeof(struct4Ds));
|
||||
|
||||
// @recomp Replicates the copy on the ID array.
|
||||
snowIDArray[gfx] = snowIDArray[D_80369284];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @recomp Patched to clear the array using the free function instead.
|
||||
RECOMP_PATCH void func_802F8FF0(void) {
|
||||
// @recomp Don't just clear the count, use the free function to do it.
|
||||
// D_80369284 = 0;
|
||||
while (D_80369284 > 0) {
|
||||
func_802F9134(D_80369284 - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to increase the amount of snow particles, the spawn area and assign transform IDs to them.
|
||||
RECOMP_PATCH void func_802F919C(void) {
|
||||
f32 temp_f20;
|
||||
s32 sp68;
|
||||
s32 var_v1;
|
||||
s32 sp60;
|
||||
struct4Ds *sp5C;
|
||||
f32 sp58;
|
||||
f32 sp4C[3];
|
||||
f32 var_f20;
|
||||
s32 sp44;
|
||||
struct4Ds *sp40;
|
||||
|
||||
|
||||
if (D_80369280 != NULL) {
|
||||
if (func_802BEF64() != 0) {
|
||||
// @recomp Don't just clear the count, use the free function to do it.
|
||||
// D_80369284 = 0;
|
||||
while (D_80369284 > 0) {
|
||||
func_802F9134(D_80369284 - 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
temp_f20 = time_getDelta();
|
||||
sp60 = (globalTimer_getTime() & 1) * 2;
|
||||
player_getPosition(D_80381040);
|
||||
|
||||
D_80369280->unkC[0] = D_80381040[0] - D_80369280->unk0[0];
|
||||
D_80369280->unkC[1] = D_80381040[1] - D_80369280->unk0[1];
|
||||
D_80369280->unkC[2] = D_80381040[2] - D_80369280->unk0[2];
|
||||
D_80369280->unk0[0] = D_80381040[0];
|
||||
D_80369280->unk0[1] = D_80381040[1];
|
||||
D_80369280->unk0[2] = D_80381040[2];
|
||||
D_8038104C = D_80381040[1] - 300.0f;
|
||||
|
||||
for (sp68 = 0; sp68 < D_80369284; sp68++) {
|
||||
sp5C = D_80369280->unk1C + sp68;
|
||||
for (var_v1 = 0; var_v1 < 3; var_v1++) {
|
||||
sp5C->unk0[var_v1] += sp5C->unkC[var_v1] * temp_f20;
|
||||
}
|
||||
|
||||
sp5C->unkC[sp60] += ((randf() * 30.0) - 15.0);
|
||||
}
|
||||
|
||||
D_8036928C++;
|
||||
if (D_8036928C < D_80369284) {
|
||||
sp5C = &D_80369280[0].unk1C[D_8036928C];
|
||||
if (ml_vec3f_distance((*sp5C).unk0, D_80381040) > 1300.0f) {
|
||||
func_802F9134(D_8036928C);
|
||||
}
|
||||
}
|
||||
else {
|
||||
D_8036928C = 0;
|
||||
}
|
||||
if (D_80369280->unk18 == 1) {
|
||||
// @recomp Patched to use the count from the macro instead and spawn multiple snow particles at once.
|
||||
// This behavior must be ignored while in demo mode to not alter the RNG, as it'll affect the demo's result.
|
||||
u32 snowParticleLimit = recomp_in_demo_playback_game_mode() ? SNOW_PARTICLE_COUNT_ORIGINAL : SNOW_PARTICLE_COUNT_EXPANDED;
|
||||
u32 particlesToSpawn = recomp_in_demo_playback_game_mode() ? 1 : 2;
|
||||
while (D_80369284 < snowParticleLimit && particlesToSpawn > 0) {
|
||||
sp40 = D_80369280->unk1C + D_80369284;
|
||||
|
||||
// @recomp Assign a new ID to this particle. Also mark it to skip interpolation.
|
||||
snowIDArray[D_80369284] = snowIDQueue[--snowIDQueueCount] | SNOW_SKIP_INTERPOLATION_MASK;
|
||||
particlesToSpawn--;
|
||||
|
||||
D_80369284++;
|
||||
sp58 = randf2(100.0f, 1300.0f);
|
||||
sp4C[0] = 0.0f;
|
||||
sp4C[1] = randf() * 200.0f + 200.0f;
|
||||
sp4C[2] = -sp58;
|
||||
if ((D_80369280->unkC[0] * D_80369280->unkC[0] + D_80369280->unkC[1] * D_80369280->unkC[1] + D_80369280->unkC[2] * D_80369280->unkC[2]) < 25.0f) {
|
||||
var_f20 = 100.0f;
|
||||
}
|
||||
else {
|
||||
var_f20 = 70.0f;
|
||||
}
|
||||
|
||||
// @recomp Use the full 360 degrees instead.
|
||||
// This behavior must be ignored while in demo mode to not alter the RNG, as it'll affect the demo's result.
|
||||
if (!recomp_in_demo_playback_game_mode()) {
|
||||
var_f20 = 180.0f;
|
||||
}
|
||||
|
||||
ml_vec3f_yaw_rotate_copy(sp4C, sp4C, viewport_getYaw() + randf2(-var_f20, var_f20));
|
||||
sp4C[0] += D_80381040[0];
|
||||
sp4C[1] += D_80381040[1];
|
||||
sp4C[2] += D_80381040[2];
|
||||
if (sp58 < 650.0) {
|
||||
for (sp44 = 0; sp44 < 5 && viewport_isPointPlane_3f(sp4C[0], sp4C[1] - 10.0f, sp4C[2]); sp44++) {
|
||||
sp4C[1] += 200.0f;
|
||||
}
|
||||
}
|
||||
sp40->unk0[0] = sp4C[0];
|
||||
sp40->unk0[1] = sp4C[1];
|
||||
sp40->unk0[2] = sp4C[2];
|
||||
sp40->unkC[0] = 0.0f;
|
||||
sp40->unkC[1] = randf2(-150.0f, -50.0f);
|
||||
sp40->unkC[2] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to remove the frustum check and tag the snow particle with its assigned transform ID.
|
||||
RECOMP_PATCH bool func_802F989C(Gfx **gfx, Mtx **mtx, f32 arg2[3]) {
|
||||
D_80381070[0] = arg2[0] - D_80381050[0]; \
|
||||
D_80381070[1] = arg2[1] - D_80381050[1]; \
|
||||
D_80381070[2] = arg2[2] - D_80381050[2];
|
||||
if (((-17000.0f < D_80381070[0]) && (D_80381070[0] < 17000.0f))
|
||||
&& (arg2[1] > -200.0f)
|
||||
&& ((-17000.0f < D_80381070[2]) && (D_80381070[2] < 17000.0f))
|
||||
// @recomp Remove frustum check.
|
||||
// This behavior must be ignored while in demo mode to not alter the RNG, as it'll affect the demo's result.
|
||||
//&& viewport_func_8024DB50(arg2, D_8038108C)
|
||||
&& (!recomp_in_demo_playback_game_mode() || viewport_func_8024DB50(arg2, D_8038108C))
|
||||
) {
|
||||
func_80251B5C(D_80381070[0], D_80381070[1], D_80381070[2]);
|
||||
mlMtxApply(*mtx);
|
||||
mlMtx_apply_vec3f_restricted(&D_80381080, D_80381094->unkC);
|
||||
func_80251B5C(D_80381080[0], D_80381080[1], D_80381080[2]);
|
||||
mlMtx_rotate_yaw_deg(D_80381060[1]);
|
||||
mlMtx_rotate_pitch_deg(D_80381060[0]);
|
||||
func_80252A38(-(D_80381094->unkC[0]), -(D_80381094->unkC[1]), -(D_80381094->unkC[2]));
|
||||
mlMtxApply(*mtx);
|
||||
|
||||
// @recomp Set a matrix group before drawing the snow particle. If the interpolation skip bit is enabled as the snow particle was just
|
||||
// created, do not interpolate and clear the bit instead.
|
||||
s32 snowIndex = (struct struct_4D_s *)(arg2)-D_80369280->unk1C;
|
||||
u32 snowId = SNOW_TRANSFORM_ID_START + snowIDArray[snowIndex];
|
||||
if (snowIDArray[snowIndex] & SNOW_SKIP_INTERPOLATION_MASK) {
|
||||
gEXMatrixGroupSkipAll((*gfx)++, snowId, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
snowIDArray[snowIndex] ^= SNOW_SKIP_INTERPOLATION_MASK;
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroupSimpleNormal((*gfx)++, snowId, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
}
|
||||
|
||||
gSPMatrix((*gfx)++, (*mtx)++, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
// @recomp Remove unnecessary usage of osVirtualToPhysical to allow extended addresses.
|
||||
gSPDisplayList((*gfx)++, /*osVirtualToPhysical*/(D_80381090));
|
||||
gSPPopMatrix((*gfx)++, G_MTX_MODELVIEW);
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1,245 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "music.h"
|
||||
#include "time.h"
|
||||
#include "core1/ml.h"
|
||||
#include "../lib/bk-decomp/src/core1/musicplayer.h"
|
||||
#include "sound.h"
|
||||
|
||||
// @recomp The music player is often used to play sound effects. Therefore, check if track_id is actually music.
|
||||
bool isMusic(s16 trackId) {
|
||||
switch (trackId) {
|
||||
case COMUSIC_2_MM:
|
||||
case COMUSIC_3_FP_TWINKLIES_TALKING:
|
||||
case COMUSIC_4_MMM_CLOCK_VERSION:
|
||||
case COMUSIC_5_TTC_VACATION_VERSION:
|
||||
case COMUSIC_6_BGS:
|
||||
case COMUSIC_7_CC_MUTANT_CRABS:
|
||||
case COMUSIC_8_STARTUP_MUSICAL:
|
||||
case COMUSIC_F_MMM_ALTERNATIVE:
|
||||
case COMUSIC_10_SM:
|
||||
case COMUSIC_12_TTC_NIPPER:
|
||||
case COMUSIC_13_INSIDE_SANDCASTLE:
|
||||
case COMUSIC_1B_MYSTERIOUS_INDOORS:
|
||||
case COMUSIC_1C_CC_ALTERNATIVE:
|
||||
case COMUSIC_1E_GL_MM_VERSION:
|
||||
case COMUSIC_1F_CC_INSIDE_CLANKER:
|
||||
case COMUSIC_20_GV_ALTERNATIVE:
|
||||
case COMUSIC_21_MMM_INSIDE_MMM_MANSION:
|
||||
case COMUSIC_22_MMM:
|
||||
case COMUSIC_23_MMM_INSIDE_CHURCH:
|
||||
case COMUSIC_24_GV_INSIDE_PYRAMID:
|
||||
case COMUSIC_25_USING_GOLD_FEATHERS:
|
||||
case COMUSIC_26_GV_SANDYBUTT_DANGER:
|
||||
case COMUSIC_27_GV_RUBEES_SONG:
|
||||
case COMUSIC_28_SOMETHING_AQUATIC:
|
||||
case COMUSIC_29_CCW_SUMMER:
|
||||
case COMUSIC_2A_CCW_WINTER:
|
||||
case COMUSIC_2E_CCW_FALL_AQUATIC:
|
||||
case COMUSIC_2F_CCW_HUBROOM:
|
||||
case COMUSIC_32_STARTUP_LOGO_SCENE:
|
||||
case COMUSIC_33_RBB_ALTERNATIVE:
|
||||
case COMUSIC_34_SNACKER_DANGER:
|
||||
case COMUSIC_35_RBB_MASCHINE_ROOM_AQUATIC:
|
||||
case COMUSIC_39_DK64_FUNGI_FOREST:
|
||||
case COMUSIC_3A_FP_BOGGY_RACE:
|
||||
case COMUSIC_41_MUMBOS_HUT:
|
||||
case COMUSIC_44_CCW_NABNUT:
|
||||
case COMUSIC_45_CCW_NABNUT_ATTIC_A:
|
||||
case COMUSIC_46_CCW_SPRING:
|
||||
case COMUSIC_47_BGS_INSIDE_TANKTUP:
|
||||
case COMUSIC_48_CCW_ALTERNATIVE_A:
|
||||
case COMUSIC_49_CCW_ALTERNATIVE_QUICK:
|
||||
case COMUSIC_4A_RBB_INSIDE_CONTAINER:
|
||||
case COMUSIC_4B_CCW_ZUBBA_FIGHT:
|
||||
case COMUSIC_4C_RBB_CREWMATE_CABIN:
|
||||
case COMUSIC_50_GL_TTC_VERSION:
|
||||
case COMUSIC_51_GL_CCW_VERSION:
|
||||
case COMUSIC_52_GL_BGS_RBB_VERSION:
|
||||
case COMUSIC_53_GL_FP_VERSION_A:
|
||||
case COMUSIC_54_GL_GV_VERSION:
|
||||
case COMUSIC_55_BGS_MR_VILE:
|
||||
case COMUSIC_56_SM_HANGBRIDGE:
|
||||
case COMUSIC_57_TURBO_TRAINERS:
|
||||
case COMUSIC_58_WADING_BOOTS:
|
||||
case COMUSIC_59_GL_FP_VERSION_B:
|
||||
case COMUSIC_5A_FP_IGLOO_SAD:
|
||||
case COMUSIC_5B_FP_IGLOO_HAPPY:
|
||||
case COMUSIC_5D_GL_MMM_VERSION:
|
||||
case COMUSIC_5E_GL_MMM_RBB_VERSION:
|
||||
case COMUSIC_5F_CCW_ALTERNATIVE_B:
|
||||
case COMUSIC_60_NABNUT_ATTIC_B:
|
||||
case COMUSIC_62_RBB_BOOMBOX:
|
||||
case COMUSIC_63_GL_FF_VERSION:
|
||||
case COMUSIC_64_WORLD_OPENING_A:
|
||||
case COMUSIC_65_WORLD_OPENING_B:
|
||||
case COMUSIC_66_FP_INSIDE_WOZZAS_CAVE:
|
||||
case COMUSIC_68_TWINKLY_MINIGAME:
|
||||
case COMUSIC_6A_MMM_TUMBLARS_SHED:
|
||||
case COMUSIC_6B_FP_ALTERNATIVE:
|
||||
case COMUSIC_6C_INTRO_TOWER_SCENE:
|
||||
case COMUSIC_6D_CCW_GNAWTYS_HOUSE:
|
||||
case COMUSIC_6E_GAME_SELECT:
|
||||
case COMUSIC_6F_PAUSE_SCREEN:
|
||||
case COMUSIC_70_MMM_INSIDE_LOGGO:
|
||||
case COMUSIC_71_FF:
|
||||
case MUSIC_BGS_FLIBBIT_FIGHT:
|
||||
case COMUSIC_74_GL_FINAL_SECTION:
|
||||
case COMUSIC_7A_BRENTILDA:
|
||||
case COMUSIC_83_GV_SNS:
|
||||
case COMUSIC_84_TTC_SNS:
|
||||
case COMUSIC_85_FP_SNS:
|
||||
case COMUSIC_86_MMM_SNS:
|
||||
case COMUSIC_87_MMM_SNS_HAPPIER:
|
||||
case COMUSIC_88_BIG_SNS_FANFARE:
|
||||
case COMUSIC_8E_CREDITS:
|
||||
case COMUSIC_94_BBONUS:
|
||||
case COMUSIC_95_BBONUS_A:
|
||||
case COMUSIC_AC_GOOD_ENDING:
|
||||
case MUSIC_MUMBO_BBQ:
|
||||
case COMUSIC_A8_KLUNGO_BY_FALLEN_GRUNTY:
|
||||
case COMUSIC_AA_BEACH:
|
||||
case COMUSIC_91_GRUNTY_FALLING:
|
||||
case COMUSIC_80_GAME_OVER_CUTSCENE:
|
||||
case COMUSIC_1_FINAL_BATTLE:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
extern MusicTrack D_80281720[6];
|
||||
extern CoMusic *musicTracks;
|
||||
extern int D_80276E34;
|
||||
|
||||
void func_8024FCE0(u8 arg0, s16 arg1);
|
||||
bool func_80250074(u8);
|
||||
void func_8024FC6C(u8 arg0);
|
||||
void func_8025A7DC(enum comusic_e);
|
||||
void func_8024FF34(void);
|
||||
void func_802599B4(CoMusic *this);
|
||||
|
||||
// @recomp Patched to incorporate the bgm player volume in the setvol command for music tracks.
|
||||
RECOMP_PATCH void musicTrack_setVolume(u8 arg0, s16 arg1) {
|
||||
D_80281720[arg0].unk0 = arg1;
|
||||
|
||||
if (isMusic(musicTracks[arg0].track_id)) {
|
||||
alCSPSetVol(&D_80281720[arg0].cseqp, (s16)(arg1 * recomp_get_bgm_volume()));
|
||||
} else {
|
||||
alCSPSetVol(&D_80281720[arg0].cseqp, arg1);
|
||||
}
|
||||
if (D_80281720[arg0].unk3 && arg1) {
|
||||
func_8024FCE0(arg0, arg1);
|
||||
} else if (!D_80281720[arg0].unk3 && arg1 == 0) {
|
||||
if (func_80250074(arg0) == 0) {
|
||||
func_8024FC6C(arg0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to always set the volume of every music track in each update loop.
|
||||
RECOMP_PATCH void coMusicPlayer_update(void) {
|
||||
s32 temp_lo;
|
||||
CoMusic *var_s0;
|
||||
f32 dt;
|
||||
|
||||
dt = time_getDelta();
|
||||
|
||||
for (var_s0 = musicTracks; var_s0 < &musicTracks[MAX_MUSIC_STRUCT_COUNT]; var_s0++) {
|
||||
if (var_s0->track_id >= 0) {
|
||||
temp_lo = var_s0 - musicTracks;
|
||||
var_s0->unk4 = ml_min_f(var_s0->unk4 + dt, 600.0f);
|
||||
|
||||
if ((var_s0->unk4 > 1.0f) && func_80250074(temp_lo)) {
|
||||
func_8025A7DC(var_s0->track_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func_8024FF34();
|
||||
|
||||
if (!D_80276E34) {
|
||||
// @recomp If there are no pending track updates, send a volume command for each track to incorporate the BGM volume.
|
||||
for (var_s0 = musicTracks; var_s0 < &musicTracks[6]; var_s0++) {
|
||||
if (isMusic(var_s0->track_id)) {
|
||||
temp_lo = var_s0 - musicTracks;
|
||||
alCSPSetVol(&D_80281720[temp_lo].cseqp, (s16)(var_s0->volume * recomp_get_bgm_volume()));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
D_80276E34 = FALSE;
|
||||
|
||||
for (var_s0 = musicTracks; var_s0 < &musicTracks[6]; var_s0++) {
|
||||
if (var_s0->track_id < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (var_s0->unk12 != 0) {
|
||||
temp_lo = var_s0 - musicTracks;
|
||||
|
||||
if (var_s0->unk0 > 0.0f) {
|
||||
var_s0->unk0 -= time_getDelta();
|
||||
D_80276E34 = TRUE;
|
||||
|
||||
// @recomp Send a volume command to incorporate the current BGM volume if the track's volume wasn't changed.
|
||||
if (isMusic(var_s0->track_id)) {
|
||||
alCSPSetVol(&D_80281720[temp_lo].cseqp, (s16)(var_s0->volume * recomp_get_bgm_volume()));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (var_s0->unk12 < 0) {
|
||||
var_s0->volume += var_s0->unk12;
|
||||
|
||||
if (var_s0->unk15 && (var_s0->unkC == 0) && (var_s0->volume <= 0)) {
|
||||
func_802599B4(var_s0);
|
||||
continue;
|
||||
} else {
|
||||
if (var_s0->unkC >= var_s0->volume) {
|
||||
var_s0->volume = var_s0->unkC;
|
||||
var_s0->unk12 = 0;
|
||||
} else {
|
||||
D_80276E34 = TRUE;
|
||||
}
|
||||
musicTrack_setVolume(temp_lo, (s16)var_s0->volume);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (var_s0->volume < var_s0->unkC) {
|
||||
if (var_s0->volume == 0) {
|
||||
var_s0->unk4 = 0.0f;
|
||||
}
|
||||
var_s0->volume += var_s0->unk12;
|
||||
if (var_s0->volume >= var_s0->unkC) {
|
||||
var_s0->volume = var_s0->unkC;
|
||||
var_s0->unk12 = 0;
|
||||
} else {
|
||||
D_80276E34 = TRUE;
|
||||
}
|
||||
musicTrack_setVolume(temp_lo, (s16)var_s0->volume);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// @recomp Send a volume command to incorporate the current BGM volume if the track's volume wasn't changed.
|
||||
if (isMusic(var_s0->track_id)) {
|
||||
alCSPSetVol(&D_80281720[temp_lo].cseqp, (s16)(var_s0->volume * recomp_get_bgm_volume()));
|
||||
}
|
||||
|
||||
|
||||
var_s0->unk12 = 0;
|
||||
}
|
||||
// @recomp Always set the volume of every music track in each update loop.
|
||||
else {
|
||||
temp_lo = var_s0 - musicTracks;
|
||||
// @recomp Send a volume command to incorporate the current BGM volume if the track's volume wasn't changed.
|
||||
if (isMusic(var_s0->track_id)) {
|
||||
alCSPSetVol(&D_80281720[temp_lo].cseqp, (s16)(var_s0->volume * recomp_get_bgm_volume()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "functions.h"
|
||||
#include "transform_ids.h"
|
||||
#include "bk_api.h"
|
||||
|
||||
#define IDS_PER_BEE 8
|
||||
|
||||
typedef struct {
|
||||
f32 unk0[3];
|
||||
f32 unkC[3];
|
||||
f32 unk18[3];
|
||||
f32 unk24[3];
|
||||
}Struct_core2_47BD0_0;
|
||||
|
||||
typedef struct {
|
||||
s32 unk0;
|
||||
u8 unk4;
|
||||
u8 unk5;
|
||||
u8 unk6;
|
||||
u8 unk7;
|
||||
Struct_core2_47BD0_0 *unk8;
|
||||
f32 unkC[3];
|
||||
f32 unk18;
|
||||
f32 unk1C;
|
||||
BKModelBin *unk20;
|
||||
s32 unk24;
|
||||
}ActorLocal_core2_47BD0;
|
||||
|
||||
extern struct0* D_8037C200;
|
||||
|
||||
extern f32 func_8028E82C(void);
|
||||
extern void func_8028E84C(f32 arg0[3]);
|
||||
extern bool func_8028F070(void);
|
||||
extern bool func_8028F150(void);
|
||||
extern bool func_8028F2DC(void);
|
||||
extern void func_802CA790(Actor* this);
|
||||
extern s32 func_8033A170(void);
|
||||
extern enum map_e map_get(void);
|
||||
extern enum bswatergroup_e player_getWaterState(void);
|
||||
|
||||
extern u32 get_cutscene_counter(void);
|
||||
|
||||
// @recomp Patched to give the bees in the bee swarm individual IDs. The bees can show interpolation glitches otherwise, as they all share one matrix
|
||||
// group and can get culled individually based on distance. This is easily reproduceable by walking into a beehive with bees from a far away distance.
|
||||
RECOMP_PATCH Actor *chBeeSwarm_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
Actor *this;
|
||||
ActorLocal_core2_47BD0 *local;
|
||||
BKModelBin *phi_fp;
|
||||
s32 phi_s2;
|
||||
f32 sp8C[3];
|
||||
f32 sp80[3];
|
||||
Struct_core2_47BD0_0 *phi_s0;
|
||||
|
||||
this = marker_getActor(marker);
|
||||
local = (ActorLocal_core2_47BD0 *)&this->local;
|
||||
phi_fp = marker_loadModelBin(marker);
|
||||
for (phi_s2 = 0, phi_s0 = local->unk8; phi_s2 < local->unk0; phi_s2++) {
|
||||
sp80[0] = 0.0f;
|
||||
sp80[1] = phi_s0->unk24[1] - 90.0f;
|
||||
sp80[2] = 0.0f;
|
||||
|
||||
sp8C[0] = this->position[0] + phi_s0->unk0[0];
|
||||
sp8C[1] = this->position[1] + phi_s0->unk0[1];
|
||||
sp8C[2] = this->position[2] + phi_s0->unk0[2];
|
||||
|
||||
// @recomp Set the model transform ID.
|
||||
s32 cur_drawn_marker_spawn_index = bkrecomp_get_marker_spawn_index(marker);
|
||||
u32 transform_id = MARKER_TRANSFORM_ID_START + cur_drawn_marker_spawn_index * MARKER_TRANSFORM_ID_COUNT + phi_s2 * IDS_PER_BEE;
|
||||
u32 prev_transform_id = cur_drawn_model_transform_id;
|
||||
cur_drawn_model_transform_id = transform_id;
|
||||
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE);
|
||||
modelRender_setAlpha(0xFF);
|
||||
modelRender_draw(gfx, mtx, sp8C, sp80, 0.25f, NULL, phi_fp);
|
||||
|
||||
local->unk5 |= func_8033A170();
|
||||
if (phi_s2 < 10) {
|
||||
sp8C[1] = local->unk18 + 6.0f;
|
||||
modelRender_setAlpha(0xC0);
|
||||
modelRender_setDepthMode(MODEL_RENDER_DEPTH_COMPARE);
|
||||
modelRender_draw(gfx, mtx, sp8C, sp80, 0.1f, NULL, local->unk20);
|
||||
local->unk5 |= func_8033A170();
|
||||
}
|
||||
phi_s0++;
|
||||
|
||||
// @recomp Reset the model transform ID.
|
||||
cur_drawn_model_transform_id = prev_transform_id;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
extern f32 D_8036E580[3];
|
||||
extern void actor_postdrawMethod(ActorMarker *);
|
||||
extern void actor_predrawMethod(Actor *);
|
||||
extern BKModelBin *func_803257B4(ActorMarker *marker);
|
||||
|
||||
// @recomp Patch to skip interpolation on the Christmas tree while the lights
|
||||
// turn on to prevent visual glitches.
|
||||
RECOMP_PATCH Actor *actor_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
f32 sp3C[3];
|
||||
Actor *this;
|
||||
|
||||
this = marker_getActorAndRotation(marker, sp3C);
|
||||
|
||||
// @recomp Check for the xmas tree model
|
||||
if (marker->modelId == ASSET_488_MODEL_XMAS_TREE) {
|
||||
// @recomp Check that the lights are currently turning on / flickering
|
||||
if (this->state == 2 || this->state == 3) {
|
||||
// @recomp Skip interpolation
|
||||
cur_drawn_model_skip_interpolation = TRUE;
|
||||
}
|
||||
}
|
||||
// @recomp Check for the hut model.
|
||||
else if (marker->modelId == ASSET_7D7_MODEL_MM_HUT) {
|
||||
// @recomp Check if the hut is destroyed (HUT_STATE_2_DESTROYED).
|
||||
if (this->state == 2) {
|
||||
cur_drawn_model_skip_interpolation = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
modelRender_preDraw((GenFunction_1)actor_predrawMethod, (s32)this);
|
||||
modelRender_postDraw((GenFunction_1)actor_postdrawMethod, (s32)marker);
|
||||
modelRender_draw(gfx, mtx, this->position, sp3C, this->scale, (this->unk104 != NULL) ? D_8036E580 : NULL, func_803257B4(marker));
|
||||
// @recomp Re-enable interpolation
|
||||
cur_drawn_model_skip_interpolation = FALSE;
|
||||
return this;
|
||||
}
|
||||
|
||||
extern void func_802E0710(Actor *this);
|
||||
|
||||
// @recomp Make sure the model being skipped are the bulls during the intro cutscene, and only during the
|
||||
// first few seconds of the cutscene while the camera is panning.
|
||||
bool skip_drawing_intro_bulls(u32 model_id) {
|
||||
return
|
||||
(map_get() == MAP_1E_CS_START_NINTENDO) &&
|
||||
(model_id == ASSET_353_MODEL_BIGBUTT || model_id == ASSET_354_MODEL_BULL_INTRO) &&
|
||||
get_cutscene_counter() < 180;
|
||||
}
|
||||
|
||||
// @recomp Patched to skip drawing the bull actors on the intro cutscene's start.
|
||||
RECOMP_PATCH Actor *func_802E0738(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
f32 sp34[3];
|
||||
Actor *this;
|
||||
|
||||
this = marker_getActorAndRotation(marker, &sp34);
|
||||
|
||||
// @recomp Check the condition for not drawing this actor if it's one of the bulls during the intro.
|
||||
if (skip_drawing_intro_bulls(marker->modelId)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (marker->modelId == 0x355) {
|
||||
// @recomp Greenscreen for recording concert Banjo.
|
||||
const u32 green = 0x07C107C1;
|
||||
gDPSetCycleType((*gfx)++, G_CYC_FILL);
|
||||
gDPSetRenderMode((*gfx)++, G_RM_NOOP, G_RM_NOOP2);
|
||||
gDPSetFillColor((*gfx)++, green);
|
||||
gDPScisFillRectangle((*gfx)++, 0, 0, DEFAULT_FRAMEBUFFER_WIDTH - 1, DEFAULT_FRAMEBUFFER_HEIGHT - 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
modelRender_preDraw((GenFunction_1)func_802E0710, (s32)this);
|
||||
modelRender_postDraw((GenFunction_1)actor_postdrawMethod, (s32)marker);
|
||||
modelRender_draw(gfx, mtx, this->position, sp34, this->scale, NULL, marker_loadModelBin(marker));
|
||||
return this;
|
||||
}
|
||||
|
||||
// @recomp Patched to skip interpolating the player shadow on large surface changes.
|
||||
RECOMP_PATCH Actor* func_802CA7BC(ActorMarker* marker, Gfx** gfx, Mtx** mtx, Vtx** vtx) {
|
||||
Actor* this;
|
||||
f32 sp60;
|
||||
f32 sp54[3];
|
||||
f32 rotation[3];
|
||||
f32 sp44;
|
||||
f32 sp40;
|
||||
f32 sp34[3];
|
||||
|
||||
sp60 = (player_getWaterState() == BSWATERGROUP_2_UNDERWATER) ? 8.0f : 4.0f;
|
||||
this = marker_getActor(marker);
|
||||
if (!func_8028F070()
|
||||
|| !func_8028F150()
|
||||
|| !func_8028F2DC()
|
||||
) {
|
||||
return this;
|
||||
}
|
||||
|
||||
player_getPosition(sp54);
|
||||
sp40 = func_8028E82C();
|
||||
func_8028E84C(sp34);
|
||||
this->position_x = sp54[0];
|
||||
this->position_y = sp40 + sp60;
|
||||
this->position_z = sp54[2];
|
||||
|
||||
func_80258108(sp34, &this->yaw, &this->pitch);
|
||||
|
||||
rotation[0] = this->pitch;
|
||||
rotation[1] = this->yaw;
|
||||
rotation[2] = this->roll;
|
||||
sp44 = ml_map_f(sp54[1] - sp40, 0.0f, 300.0f, 0.43f, 0.28f);
|
||||
|
||||
// @recomp Check for the player shadow model.
|
||||
if (marker->modelId == ASSET_3BF_MODEL_PLAYER_SHADOW) {
|
||||
// @recomp Skip interpolation if the player's projected position on the floor has changed too quickly. Only do this check when the triangle has changed.
|
||||
static f32 previousPosY = 0.0f;
|
||||
static f32 previousNormY = 1.0f;
|
||||
static s16 previousTri[3] = { 0, 0, 0 };
|
||||
s16* currentTri = &D_8037C200->unk4.unk0[0];
|
||||
if (currentTri[0] != previousTri[0] || currentTri[1] != previousTri[1] || currentTri[2] != previousTri[2]) {
|
||||
f32 projectedHeightDistance = previousNormY * mlAbsF(this->position_y - previousPosY);
|
||||
const f32 skipHeightThreshold = 20.0f;
|
||||
cur_drawn_model_skip_interpolation = projectedHeightDistance >= skipHeightThreshold;
|
||||
|
||||
previousNormY = D_8037C200->normY;
|
||||
previousTri[0] = currentTri[0];
|
||||
previousTri[1] = currentTri[1];
|
||||
previousTri[2] = currentTri[2];
|
||||
}
|
||||
|
||||
previousPosY = this->position_y;
|
||||
}
|
||||
|
||||
modelRender_preDraw((GenFunction_1)func_802CA790, (s32)this);
|
||||
modelRender_draw(gfx, mtx, this->position, rotation, sp44, NULL, marker_loadModelBin(marker));
|
||||
|
||||
// @recomp Re-enable interpolation
|
||||
cur_drawn_model_skip_interpolation = FALSE;
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -18,13 +18,13 @@ osDpSetStatus_recomp = 0x8F000034;
|
||||
malloc_recomp = 0x8F000038;
|
||||
free_recomp = 0x8F00003C;
|
||||
realloc_recomp = 0x8F000040;
|
||||
recomp_register_object_extension = 0x8F000044;
|
||||
recomp_register_object_extension_generic = 0x8F000048;
|
||||
recomp_clear_all_object_data = 0x8F00004C;
|
||||
recomp_create_object_data = 0x8F000050;
|
||||
recomp_destroy_object_data = 0x8F000054;
|
||||
recomp_get_object_data = 0x8F000058;
|
||||
recomp_get_object_spawn_index = 0x8F00005C;
|
||||
recomp_register_actor_extension = 0x8F000044;
|
||||
recomp_register_actor_extension_generic = 0x8F000048;
|
||||
recomp_clear_all_actor_data = 0x8F00004C;
|
||||
recomp_create_actor_data = 0x8F000050;
|
||||
recomp_destroy_actor_data = 0x8F000054;
|
||||
recomp_get_actor_data = 0x8F000058;
|
||||
recomp_get_actor_spawn_index = 0x8F00005C;
|
||||
recomp_error = 0x8F000060;
|
||||
memcpy_recomp = 0x8F000064;
|
||||
__divdi3_recomp = 0x8F000068;
|
||||
@@ -32,22 +32,3 @@ __udivdi3_recomp = 0x8F00006C;
|
||||
__umoddi3_recomp = 0x8F000070;
|
||||
strlen_recomp = 0x8F000074;
|
||||
osVirtualToPhysical_recomp = 0x8F000078;
|
||||
osPiStartDma_recomp = 0x8F00007C;
|
||||
recomp_abort = 0x8F000080;
|
||||
recomp_get_target_aspect_ratio = 0x8F000084;
|
||||
osExQueueDisplaylistEvent_recomp = 0x8F000088;
|
||||
recomp_xxh3 = 0x8F00008C;
|
||||
recomp_get_bgm_volume = 0x8F000090;
|
||||
sinf_recomp = 0x8F000094;
|
||||
__cosf_recomp = 0x8F000098;
|
||||
recomp_get_right_analog_inputs = 0x8F00009C;
|
||||
recomp_get_analog_cam_enabled = 0x8F0000A0;
|
||||
recomp_get_analog_inverted_axes = 0x8F0000A4;
|
||||
recomp_set_right_analog_suppressed = 0x8F0000A8;
|
||||
osContGetReadData_recomp = 0x8F0000AC;
|
||||
bcopy_recomp = 0x8F0000B0;
|
||||
recomp_get_note_saving_enabled = 0x8F0000B4;
|
||||
recomp_get_cutscene_aspect_ratio = 0x8F0000B8;
|
||||
recomp_get_flying_and_swimming_inverted_axes = 0x8F0000BC;
|
||||
recomp_get_first_person_inverted_axes = 0x8F0000C0;
|
||||
recomp_get_analog_cam_sensitivity = 0x8F0000C4;
|
||||
@@ -1,498 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "functions.h"
|
||||
|
||||
typedef struct {
|
||||
u8 unk0;
|
||||
u8 unk1;
|
||||
s8 unk2;
|
||||
s8 unk3;
|
||||
}Struct_6DA30_0_s;
|
||||
|
||||
typedef struct {
|
||||
s16 x;
|
||||
s16 y;
|
||||
s16 unk4;
|
||||
s16 unk6;
|
||||
u8 fmtString[8];
|
||||
f32 unk10;
|
||||
u8 *string;
|
||||
u8 rgba[4];
|
||||
} PrintBuffer;
|
||||
|
||||
extern char D_80380AB0;
|
||||
extern s8 D_80380F20[0x80];
|
||||
extern u16 gScissorBoxLeft;
|
||||
extern u16 gScissorBoxRight;
|
||||
extern u16 gScissorBoxTop;
|
||||
extern u16 gScissorBoxBottom;
|
||||
extern s32 D_80369068[];
|
||||
extern s32 D_80380B04;
|
||||
extern s32 D_80380AE8;
|
||||
extern s32 D_80380AEC;
|
||||
extern s32 D_80380AF0;
|
||||
extern s32 D_80380AF4;
|
||||
extern s32 D_80380AF8;
|
||||
extern s32 D_80380AFC;
|
||||
extern s32 D_80380B00;
|
||||
extern s32 D_80380B0C;
|
||||
extern s32 D_80380B10;
|
||||
extern s32 D_80380B14;
|
||||
extern s8 D_80380B20[0x400];
|
||||
extern bool print_sInFontFormatMode;
|
||||
extern Struct_6DA30_0_s D_80369000[];
|
||||
extern PrintBuffer *print_sPrintBuffer;
|
||||
extern PrintBuffer *print_sCurrentPtr;
|
||||
extern Gfx D_80369238[];
|
||||
|
||||
extern BKSpriteTextureBlock *func_802F5494(s32 letterId, s32 *fontType);
|
||||
extern void *func_802F55A8(u8 arg0);
|
||||
extern f32 func_802F6C90(u8 letter, f32 *xPtr, f32 *yPtr, f32 arg3);
|
||||
|
||||
extern struct {
|
||||
u8 unk0;
|
||||
u8 unk1;
|
||||
u8 unk2;
|
||||
u8 unk3;
|
||||
} D_80369078;
|
||||
|
||||
// @recomp This ID plus the index of the character in the string will be used to tag each letter if it's assigned before printing text.
|
||||
u32 cur_pushed_text_transform_id = 0;
|
||||
u32 cur_pushed_text_transform_origin = G_EX_ORIGIN_NONE;
|
||||
u32 cur_pushed_text_transform_skip_interpolation = FALSE;
|
||||
u32 cur_drawn_text_transform_id = 0;
|
||||
u32 cur_drawn_text_transform_skip_interpolation = 0;
|
||||
Mtx *cur_drawn_text_mtx = NULL;
|
||||
u32 print_sPrintBufferIDs[0x20];
|
||||
u32 print_sPrintBufferOrigins[0x20];
|
||||
u32 print_sPrintBufferSkipInterpolationFlags[0x20];
|
||||
|
||||
// @recomp Patched to assign the current ID and origin from the global variables to the print buffer array.
|
||||
RECOMP_PATCH void _printbuffer_push_new(s32 x, s32 y, u8 *string) {
|
||||
for (print_sCurrentPtr = print_sPrintBuffer; print_sCurrentPtr < print_sPrintBuffer + 0x20 && print_sCurrentPtr->string; print_sCurrentPtr++) {
|
||||
}
|
||||
if (print_sCurrentPtr == print_sPrintBuffer + 0x20) {
|
||||
print_sCurrentPtr = NULL;
|
||||
return;
|
||||
}
|
||||
print_sCurrentPtr->x = x;
|
||||
print_sCurrentPtr->y = y;
|
||||
print_sCurrentPtr->fmtString[0] = (u8)0;
|
||||
print_sCurrentPtr->string = string;
|
||||
print_sCurrentPtr->unk10 = 1.0f;
|
||||
print_sCurrentPtr->rgba[0] = (u8)D_80369078.unk0;
|
||||
print_sCurrentPtr->rgba[1] = (u8)D_80369078.unk1;
|
||||
print_sCurrentPtr->rgba[2] = (u8)D_80369078.unk2;
|
||||
print_sCurrentPtr->rgba[3] = (u8)D_80369078.unk3;
|
||||
|
||||
// @recomp Store the current ID and origin in the arrays that run parallel to the print buffer.
|
||||
u32 bufferIndex = print_sCurrentPtr - print_sPrintBuffer;
|
||||
print_sPrintBufferIDs[bufferIndex] = cur_pushed_text_transform_id;
|
||||
print_sPrintBufferOrigins[bufferIndex] = cur_pushed_text_transform_origin;
|
||||
print_sPrintBufferSkipInterpolationFlags[bufferIndex] = cur_pushed_text_transform_skip_interpolation;
|
||||
}
|
||||
|
||||
// @recomp Patched to force orthographic projections to be used for all letters.
|
||||
RECOMP_PATCH void _printbuffer_draw_letter(char letter, f32 *xPtr, f32 *yPtr, f32 arg3, Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
static f32 D_80380FA0;
|
||||
|
||||
// u8 letter = arg0;
|
||||
BKSpriteTextureBlock *sp214;
|
||||
s32 sp210;
|
||||
s32 sp20C;
|
||||
s32 t0;
|
||||
s8 t1;
|
||||
f32 sp200;
|
||||
f32 f28;
|
||||
f32 sp1F8;
|
||||
s32 sp1F4; //font_type;
|
||||
|
||||
int i;
|
||||
|
||||
|
||||
|
||||
t0 = 0;
|
||||
sp200 = *xPtr;
|
||||
f28 = *yPtr;
|
||||
t1 = 0;
|
||||
|
||||
if (!D_80380B04 && !letter) {
|
||||
D_80380FA0 = 0.0f;
|
||||
}//L802F563C
|
||||
|
||||
switch (D_80380AE8) {
|
||||
case 0: //L802F5678
|
||||
if (letter >= '\x21' && letter < '\x5f') {
|
||||
sp20C = letter - '\x21';
|
||||
t0 = 1;
|
||||
}
|
||||
break;
|
||||
case 1: //L802F56A0
|
||||
if (letter < '\x80' && D_80380F20[letter] >= 0) {
|
||||
for (i = 0; D_80369000[i].unk0 != 0; i++) {
|
||||
if (letter == D_80369000[i].unk1 && D_80380AB0 == D_80369000[i].unk0) {
|
||||
t1 = D_80369000[i].unk3;
|
||||
break;
|
||||
}
|
||||
}//L802F5710
|
||||
sp20C = D_80380F20[letter];
|
||||
t0 = 1;
|
||||
D_80380AB0 = letter;
|
||||
f28 += (f32)t1 * arg3;
|
||||
}//L802F5738
|
||||
break;
|
||||
case 2: //L802F5740
|
||||
sp20C = letter;
|
||||
if (D_80380B04) {
|
||||
t0 = 1;
|
||||
sp20C += (D_80380B04 << 8) - 0x100;
|
||||
D_80380B04 = 0;
|
||||
}
|
||||
else {//L802F5764
|
||||
if (sp20C > 0 && sp20C < 0xfD)
|
||||
t0 = 1;
|
||||
}
|
||||
break;
|
||||
}//L802F5778
|
||||
|
||||
if (!t0 || print_sInFontFormatMode) {
|
||||
print_sInFontFormatMode = FALSE;
|
||||
switch (letter) {
|
||||
case ' '://802F5818
|
||||
*xPtr += ((D_80380AF0) ? D_80369068[D_80380AE8] : D_80369068[D_80380AE8] * 0.8) * arg3;
|
||||
break;
|
||||
|
||||
case 'b': //L802F5890
|
||||
//toggle background
|
||||
D_80380B00 = D_80380B00 ^ 1;
|
||||
break;
|
||||
|
||||
case 'f': //L802F58A8
|
||||
D_80380AEC = D_80380AE8 = D_80380AE8 ^ 1;
|
||||
break;
|
||||
|
||||
case 'l': //L802F58BC
|
||||
D_80380B10 = 0;
|
||||
break;
|
||||
|
||||
case 'h': //L802F58C8
|
||||
D_80380B10 = 1;
|
||||
break;
|
||||
|
||||
case 'j': //L802F58D4
|
||||
if (D_80380AFC == 0) {
|
||||
D_80380AFC = 1;
|
||||
D_80380AEC = D_80380AE8;
|
||||
D_80380AE8 = 2;
|
||||
// D_80380AE8 = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'e': //L802F58FC
|
||||
if (D_80380AFC) {
|
||||
D_80380AFC = 0;
|
||||
D_80380AE8 = D_80380AEC;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p': //L802F5924
|
||||
D_80380AF0 = D_80380AF0 ^ 1;
|
||||
break;
|
||||
|
||||
case 'q': //L802F593C
|
||||
D_80380B14 = D_80380B14 ^ 1;
|
||||
if (D_80380B14) {
|
||||
gDPSetTextureFilter((*gfx)++, G_TF_POINT);
|
||||
}
|
||||
else {//L802F5978
|
||||
gDPSetTextureFilter((*gfx)++, G_TF_BILERP);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v': //L802F59A0
|
||||
//toggle letter gradient
|
||||
D_80380AF4 ^= 1;
|
||||
if (D_80380AF4) {
|
||||
// @recomp Comment these lines out, as the viewport is now set in the parent function.
|
||||
//viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
//gDPPipeSync((*gfx)++);
|
||||
//gDPSetTexturePersp((*gfx)++, G_TP_PERSP);
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0x00, 0x00, 0x00, 0xFF);
|
||||
gDPSetCombineLERP((*gfx)++, 0, 0, 0, TEXEL0, TEXEL0, 0, SHADE, 0, 0, 0, 0, TEXEL0, TEXEL0, 0, SHADE, 0);
|
||||
}
|
||||
else {//L802F5A44
|
||||
gDPSetCombineMode((*gfx)++, G_CC_DECALRGBA, G_CC_DECALRGBA);
|
||||
// @recomp Comment this line out, as texture rectangle letters are no longer possible.
|
||||
//gDPSetTexturePersp((*gfx)++, G_TP_NONE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd': //L802F5A8C
|
||||
D_80380AF8 ^= 1;
|
||||
if (D_80380AF8) {
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetCycleType((*gfx)++, G_CYC_2CYCLE);
|
||||
gDPSetRenderMode((*gfx)++, G_RM_PASS, G_RM_XLU_SURF2);
|
||||
gDPSetTextureLOD((*gfx)++, G_TL_TILE);
|
||||
gDPSetCombineLERP((*gfx)++, 0, 0, 0, TEXEL0, TEXEL0, 0, TEXEL1, 0, 0, 0, 0, COMBINED, 0, 0, 0, COMBINED);
|
||||
}
|
||||
else {//L802F5B48
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetCombineMode((*gfx)++, G_CC_DECALRGBA, G_CC_DECALRGBA);
|
||||
gDPSetCycleType((*gfx)++, G_CYC_1CYCLE);
|
||||
gDPSetTextureLOD((*gfx)++, G_TL_LOD);
|
||||
gDPSetRenderMode((*gfx)++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xfd: //L802F5BEC
|
||||
print_sInFontFormatMode = TRUE;
|
||||
break;
|
||||
|
||||
case 0xfe://L802F5BF4
|
||||
D_80380B04 = 1;
|
||||
break;
|
||||
|
||||
case 0xff://L802F5BFC
|
||||
D_80380B04 = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {//L802F5C08
|
||||
sp214 = func_802F5494(sp20C, &sp1F4);
|
||||
if (D_80380B10 != 0) {
|
||||
sp200 += randf2(-2.0f, 2.0f);
|
||||
f28 += randf2(-2.0f, 2.0f);
|
||||
}
|
||||
sp1F8 = (D_80380AF0 != 0) ? D_80369068[D_80380AE8] : sp214->x;
|
||||
|
||||
// temp_f2 = D_80380FA0;
|
||||
// phi_f2 = temp_f2;
|
||||
if (D_80380FA0 == 0.0f) {
|
||||
D_80380FA0 = -sp1F8 * 0.5;
|
||||
}
|
||||
|
||||
sp200 += (D_80380FA0 + (sp1F8 - sp214->x) * 0.5);
|
||||
f28 -= sp214->h * 0.5;
|
||||
sp210 = (s32)(sp214 + 1);
|
||||
while (sp210 % 8) {
|
||||
sp210++;
|
||||
}
|
||||
if (sp1F4 == SPRITE_TYPE_RGBA32) {
|
||||
gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_RGBA, G_IM_SIZ_32b, sp214->w, sp214->h, 0, 0, sp214->x - 1, sp214->y - 1, NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
}
|
||||
else if (sp1F4 == SPRITE_TYPE_IA8) {
|
||||
gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_IA, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x - 1, sp214->y - 1, NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
}
|
||||
else if (sp1F4 == SPRITE_TYPE_I8) {
|
||||
gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_I, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x - 1, sp214->y - 1, NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
}
|
||||
else if (sp1F4 == SPRITE_TYPE_I4) {
|
||||
gDPLoadTextureTile_4b((*gfx)++, sp210, G_IM_FMT_I, sp214->w, sp214->h, 0, 0, sp214->x - 1, sp214->y - 1, NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
}
|
||||
else if (sp1F4 == SPRITE_TYPE_CI8) {
|
||||
void *pal = func_802F55A8(sp20C);
|
||||
gDPLoadTLUT_pal256((*gfx)++, pal);
|
||||
gDPLoadTextureTile((*gfx)++, sp210, G_IM_FMT_CI, G_IM_SIZ_8b, sp214->w, sp214->h, 0, 0, sp214->x - 1, sp214->y - 1, NULL, G_TX_CLAMP, G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
gDPSetTextureLUT((*gfx)++, G_TT_RGBA16);
|
||||
}//L802F6570
|
||||
if (D_80380AF8 != 0) {
|
||||
s32 temp_t1;
|
||||
s32 phi_a0;
|
||||
temp_t1 = ((print_sCurrentPtr->unk4 - print_sCurrentPtr->y) - D_80380B0C) + 1;
|
||||
phi_a0 = -MAX(1 - D_80380B0C, MIN(0, temp_t1));
|
||||
|
||||
gDPSetTextureImage((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, 32, &D_80380B20);
|
||||
gDPSetTile((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, (sp214->x + 8) >> 3, 0x0100, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD);
|
||||
gDPLoadSync((*gfx)++);
|
||||
gDPLoadTile((*gfx)++, G_TX_LOADTILE, 0 << G_TEXTURE_IMAGE_FRAC, (phi_a0) << G_TEXTURE_IMAGE_FRAC, (sp214->x) << G_TEXTURE_IMAGE_FRAC, (D_80380B0C - 1) << G_TEXTURE_IMAGE_FRAC);
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetTile((*gfx)++, G_IM_FMT_I, G_IM_SIZ_8b, ((sp214->x - 0 + 1) * G_IM_SIZ_8b_LINE_BYTES + 7) >> 3, 0x0100, 1, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOLOD);
|
||||
gDPSetTileSize((*gfx)++, 1, 0 << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) + phi_a0) << G_TEXTURE_IMAGE_FRAC, (sp214->x) << G_TEXTURE_IMAGE_FRAC, (MAX(0, temp_t1) - (1 - D_80380B0C)) << G_TEXTURE_IMAGE_FRAC);
|
||||
|
||||
// gDPLoadMultiTile((*gfx)++, &D_80380B20,)
|
||||
|
||||
}//L802F677C
|
||||
|
||||
// @recomp Force orthographic projection rectangles to be used for all letters as it allows them to be interpolated.
|
||||
//if (D_80380AF4 != 0) {
|
||||
if (TRUE) {
|
||||
f32 temp_f24;
|
||||
f32 spD0;
|
||||
f32 ix;
|
||||
f32 iy;
|
||||
f32 temp_f26;
|
||||
f32 spC0;
|
||||
|
||||
temp_f24 = (sp214->x - 1.0);
|
||||
spD0 = sp214->y - 1.0;
|
||||
temp_f26 = (f64)sp200 - (f32)gFramebufferWidth * 0.5;
|
||||
|
||||
// @recomp Remove the incorrect half pixel offset that was applied.
|
||||
//spC0 = (f64)f28 - (f32)gFramebufferHeight * 0.5 - 0.5f;
|
||||
spC0 = (f64)f28 - (f32)gFramebufferHeight * 0.5;
|
||||
|
||||
// @recomp Assign a unique matrix and group to each letter drawn if an ID is currently assigned.
|
||||
if (cur_drawn_text_transform_id != 0) {
|
||||
gSPMatrix((*gfx)++, OS_K0_TO_PHYSICAL(cur_drawn_text_mtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
|
||||
if (cur_drawn_text_transform_skip_interpolation) {
|
||||
gEXMatrixGroupSkipAll((*gfx)++, cur_drawn_text_transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroupSimpleVerts((*gfx)++, cur_drawn_text_transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
}
|
||||
|
||||
cur_drawn_text_transform_id++;
|
||||
}
|
||||
|
||||
gSPVertex((*gfx)++, *vtx, 4, 0);
|
||||
for (iy = 0.0f; iy < 2.0; iy += 1.0) {
|
||||
for (ix = 0.0f; ix < 2.0; ix += 1.0) {
|
||||
s32 s = (ix * temp_f24 * 64.0f);
|
||||
// @recomp Add one pixel to the right of the rectangle.
|
||||
//(*vtx)->v.ob[0] = (s16)(s32)((f64)(temp_f26 + (temp_f24 * arg3 * ix)) * 4.0);
|
||||
s32 x = (s32)((f64)(temp_f26 + (temp_f24 * arg3 * ix)) * 4.0) + (ix * 4);
|
||||
(*vtx)->v.ob[0] = (s16)(x);
|
||||
|
||||
{
|
||||
s32 t = (iy * spD0 * 64.0f);
|
||||
// @recomp Add one pixel to the bottom of the rectangle.
|
||||
//(*vtx)->v.ob[1] = (s16)(s32)((f64)(spC0 + (spD0 * arg3 * iy)) * -4.0);
|
||||
s32 y = (s32)((f64)(spC0 + (spD0 * arg3 * iy)) * -4.0) - iy * 4;
|
||||
(*vtx)->v.ob[1] = (s16)(y);
|
||||
(*vtx)->v.ob[2] = -0x14;
|
||||
|
||||
// @recomp Add one pixel to the texture coordinates.
|
||||
//(*vtx)->v.tc[0] = s;
|
||||
//(*vtx)->v.tc[1] = t;
|
||||
(*vtx)->v.tc[0] = s + ix * 64;
|
||||
(*vtx)->v.tc[1] = t + iy * 64;
|
||||
}
|
||||
(*vtx)->v.cn[3] = (iy != 0.0f) ? print_sCurrentPtr->unk6 : print_sCurrentPtr->unk4;
|
||||
|
||||
(*vtx)++;
|
||||
}
|
||||
}
|
||||
|
||||
gSP1Quadrangle((*gfx)++, 0, 1, 3, 2, 0);
|
||||
|
||||
// @recomp Clear the matrix group.
|
||||
if (cur_drawn_text_transform_id != 0) {
|
||||
gEXPopMatrixGroup((*gfx)++, G_MTX_MODELVIEW);
|
||||
}
|
||||
}
|
||||
else {
|
||||
gSPScisTextureRectangle((*gfx)++, (s32)(sp200 * 4.0f), (s32)(f28 * 4.0f), (s32)((sp200 + sp214->x * arg3) * 4.0f), (s32)((f28 + sp214->y * arg3) * 4.0f), 0, 0, 0, (s32)(1024.0f / arg3), (s32)(1024.0f / arg3));
|
||||
}
|
||||
*xPtr += sp1F8 * arg3;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Patched to set up an orthographic projection for each print and align them to their corresponding side on the screen.
|
||||
RECOMP_PATCH void printbuffer_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx) {
|
||||
static f32 D_80380FA8[0x20];
|
||||
|
||||
s32 j;
|
||||
f32 _x;
|
||||
f32 _y;
|
||||
f32 width;
|
||||
|
||||
gSPDisplayList((*gfx)++, D_80369238);
|
||||
|
||||
// @recomp Set up a scissor that covers the entire screen.
|
||||
gEXPushScissor((*gfx)++);
|
||||
gEXSetScissor((*gfx)++, G_SC_NON_INTERLACE, G_EX_ORIGIN_LEFT, G_EX_ORIGIN_RIGHT, 0, gScissorBoxRight, 0, gScissorBoxBottom);
|
||||
|
||||
// @recomp Set up an orthographic projection that will be used for all letters by default.
|
||||
u32 curOrigin = G_EX_ORIGIN_NONE;
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_NONE, 0, 0);
|
||||
gEXSetRectAlign((*gfx)++, G_EX_ORIGIN_NONE, G_EX_ORIGIN_NONE, 0, 0, 0, 0);
|
||||
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
cur_drawn_text_mtx = (*mtx - 1);
|
||||
|
||||
// @recomp Set up some drawing parameters that were set up when changing between rectangle and orthographic mode.
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetTexturePersp((*gfx)++, G_TP_PERSP);
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0x00, 0x00, 0x00, 0xFF);
|
||||
gDPSetCombineLERP((*gfx)++, 0, 0, 0, TEXEL0, TEXEL0, 0, SHADE, 0, 0, 0, 0, TEXEL0, TEXEL0, 0, SHADE, 0);
|
||||
|
||||
for (print_sCurrentPtr = print_sPrintBuffer; print_sCurrentPtr < print_sPrintBuffer + 0x20; print_sCurrentPtr++) {
|
||||
if (print_sCurrentPtr->string != 0) {
|
||||
// @recomp When the origin changes, set up a new viewport with the alignment specified for the print buffer.
|
||||
u32 bufferIndex = print_sCurrentPtr - print_sPrintBuffer;
|
||||
cur_drawn_text_transform_id = print_sPrintBufferIDs[bufferIndex];
|
||||
cur_drawn_text_transform_skip_interpolation = print_sPrintBufferSkipInterpolationFlags[bufferIndex];
|
||||
if (curOrigin != print_sPrintBufferOrigins[bufferIndex]) {
|
||||
curOrigin = print_sPrintBufferOrigins[bufferIndex];
|
||||
s32 viewportOffset = curOrigin < G_EX_ORIGIN_NONE ? (gScissorBoxTop * curOrigin * -4) / G_EX_ORIGIN_RIGHT : 0;
|
||||
gEXSetViewportAlign((*gfx)++, curOrigin, viewportOffset, 0);
|
||||
gEXSetRectAlign((*gfx)++, curOrigin, curOrigin, viewportOffset, 0, viewportOffset, 0);
|
||||
viewport_setRenderViewportAndOrthoMatrix(gfx, mtx);
|
||||
}
|
||||
|
||||
_x = (f32)print_sCurrentPtr->x;
|
||||
_y = (f32)print_sCurrentPtr->y;
|
||||
//toggle on string format modifiers
|
||||
for (j = 0; print_sCurrentPtr->fmtString[j] != 0; j++) {
|
||||
_printbuffer_draw_letter(0xFD, &_x, &_y, 1.0f, gfx, mtx, vtx);
|
||||
_printbuffer_draw_letter(print_sCurrentPtr->fmtString[j], &_x, &_y, 1.0f, gfx, mtx, vtx);
|
||||
}
|
||||
if (D_80380B00 != 0) {
|
||||
width = (strlen(print_sCurrentPtr->string) - 1) * D_80369068[D_80380AE8];
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0x00, 0x00, 0x00, 0x64);
|
||||
gDPSetCombineMode((*gfx)++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
|
||||
gDPScisFillRectangle((*gfx)++, _x - D_80369068[D_80380AE8] / 2 - 1.0f, _y - D_80369068[D_80380AE8] / 2 - 1.0f, _x + width + D_80369068[D_80380AE8] / 2, _y + D_80369068[D_80380AE8] / 2 + 1.0f);
|
||||
gDPPipeSync((*gfx)++);
|
||||
|
||||
}//L802F73E8
|
||||
// @recomp Ignore the condition for not setting up these parameters while on orthographic mode.
|
||||
if (D_80380AF8 == 0) { //if ((D_80380AF8 == 0) && (D_80380AF4 == 0)) {
|
||||
if (D_80380AE8 != 0) {
|
||||
gDPSetCombineMode((*gfx)++, G_CC_DECALRGBA, G_CC_DECALRGBA);
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
}
|
||||
else {
|
||||
gDPSetCombineMode((*gfx)++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
||||
gDPSetPrimColor((*gfx)++, 0, 0, print_sCurrentPtr->rgba[0], print_sCurrentPtr->rgba[1], print_sCurrentPtr->rgba[2], print_sCurrentPtr->rgba[3]);
|
||||
}
|
||||
}
|
||||
if ((D_80380AE8 == 1) && ((f64)print_sCurrentPtr->unk10 < 0.0)) {
|
||||
for (j = 0; print_sCurrentPtr->string[j]; j++) {
|
||||
D_80380FA8[j] = func_802F6C90(print_sCurrentPtr->string[j], &_x, &_y, -print_sCurrentPtr->unk10);
|
||||
}
|
||||
while (j >= 0) {
|
||||
_x = D_80380FA8[j];
|
||||
_printbuffer_draw_letter(print_sCurrentPtr->string[j], &_x, &_y, -print_sCurrentPtr->unk10, gfx, mtx, vtx);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (j = 0; (print_sCurrentPtr->string[j] != 0) || (D_80380B04 != 0); j++) {
|
||||
_printbuffer_draw_letter(print_sCurrentPtr->string[j], &_x, &_y, print_sCurrentPtr->unk10, gfx, mtx, vtx);
|
||||
}
|
||||
}
|
||||
//toggle off string format modifiers
|
||||
for (j = 0; print_sCurrentPtr->fmtString[j] != 0; j++) {
|
||||
_printbuffer_draw_letter(0xFD, &_x, &_y, 1.0f, gfx, mtx, vtx);
|
||||
_printbuffer_draw_letter(print_sCurrentPtr->fmtString[j], &_x, &_y, 1.0f, gfx, mtx, vtx);
|
||||
}
|
||||
_printbuffer_draw_letter(0, &_x, &_y, 1.0f, gfx, mtx, vtx);
|
||||
print_sCurrentPtr->string = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Clear the alignment and the scissor. Also clear the assigned transform group for the letters.
|
||||
gEXSetViewportAlign((*gfx)++, G_EX_ORIGIN_NONE, 0, 0);
|
||||
gEXSetRectAlign((*gfx)++, G_EX_ORIGIN_NONE, G_EX_ORIGIN_NONE, 0, 0, 0, 0);
|
||||
gEXPopScissor((*gfx)++);
|
||||
cur_drawn_text_transform_id = 0;
|
||||
|
||||
gDPPipeSync((*gfx)++);
|
||||
gDPSetTexturePersp((*gfx)++, G_TP_PERSP);
|
||||
gDPSetTextureFilter((*gfx)++, G_TF_BILERP);
|
||||
viewport_setRenderViewportAndPerspectiveMatrix(gfx, mtx);
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
#include "patches.h"
|
||||
#include "prop.h"
|
||||
|
||||
typedef struct demo_input{
|
||||
u8 unk0;
|
||||
u8 unk1;
|
||||
u16 unk2;
|
||||
u8 unk4;
|
||||
u8 unk5;
|
||||
}DemoInput;
|
||||
|
||||
typedef struct demo_file_header{
|
||||
u8 pad0[0x4];
|
||||
DemoInput inputs[];
|
||||
} DemoFileHeader;
|
||||
|
||||
extern DemoInput *D_803860D0; //demo_input_ptr
|
||||
extern DemoFileHeader * D_803860D4; //demo_file_ptr
|
||||
extern s32 D_803860D8;//current_input
|
||||
extern s32 D_803860DC;//total_inputs
|
||||
|
||||
extern DemoInput D_80371EF0;
|
||||
|
||||
enum extra_actors_e {
|
||||
ACTOR_19_FRAMERATE_60 = 0x19,
|
||||
ACTOR_1A_FRAMERATE_30,
|
||||
ACTOR_1B_FRAMERATE_20,
|
||||
ACTOR_1C_FRAMERATE_15,
|
||||
ACTOR_1D_FRAMERATE_12,
|
||||
};
|
||||
|
||||
typedef struct struct_core2_9B180_s{
|
||||
s16 unk0;
|
||||
// u8 pad2[0x2];
|
||||
NodeProp *unk4;
|
||||
void (*unk8)(struct struct_core2_9B180_s *);
|
||||
void (*unkC)(struct struct_core2_9B180_s *);
|
||||
void (*unk10)(struct struct_core2_9B180_s *);
|
||||
}Struct_core2_9B180_0;
|
||||
|
||||
extern Struct_core2_9B180_0 D_8036DE00[6];
|
||||
|
||||
extern volatile s32 D_802808D8;
|
||||
extern s32 D_802808DC;
|
||||
extern s32 D_80280E90;
|
||||
|
||||
void func_80244A98(s32 arg0);
|
||||
NodeProp *cubeList_findNodePropByActorIdAndPosition_s32(enum actor_e actor_id, s32 arg1[3]);
|
||||
void func_8032236C(s32 arg0, s32 arg1, s32 *arg2);
|
||||
void viMgr_func_8024BF94(s32 arg0);
|
||||
void viMgr_func_8024BFD8(s32 arg0);
|
||||
void dummy_func_8025AFB8(void);
|
||||
s32 getGameMode(void);
|
||||
f32 time_getDelta(void);
|
||||
s32 item_adjustByDiffWithHud(enum item_e item, s32 diff);
|
||||
void func_802FACA4(enum item_e item_id);
|
||||
bool func_802FAFE8(enum item_e item_id);
|
||||
enum map_e map_get(void);
|
||||
|
||||
s32 demo_frame_divisor = -1;
|
||||
|
||||
// @recomp Patched to set a variable to use as the frame divisor when processing demo inputs.
|
||||
RECOMP_PATCH int demo_readInput(OSContPad* arg0, s32* arg1){
|
||||
DemoInput *input_ptr = &D_803860D0[D_803860D8++];
|
||||
int not_eof = D_803860D8 < D_803860DC;
|
||||
|
||||
if(!not_eof)
|
||||
input_ptr = &D_80371EF0;
|
||||
|
||||
arg0->stick_x = input_ptr->unk0;
|
||||
arg0->stick_y = input_ptr->unk1;
|
||||
arg0->button = input_ptr->unk2;
|
||||
*arg1 = input_ptr->unk4;
|
||||
|
||||
// @recomp Track the frame divisor for later.
|
||||
demo_frame_divisor = input_ptr->unk4;
|
||||
|
||||
// @recomp Lock the frame divisor to 3 (20 FPS) in Bottles' Bonus.
|
||||
// The game generally runs at 20 FPS during Bottles' Bonus on original hardware, which means the minigame timer should last a similar amount of time.
|
||||
// Return 2 (30 FPS) into arg1 so that the game doesn't compensate by making the timer run faster.
|
||||
s32 game_mode = getGameMode();
|
||||
if (game_mode == GAME_MODE_8_BOTTLES_BONUS) {
|
||||
// *arg1 = 2;
|
||||
demo_frame_divisor = 3;
|
||||
}
|
||||
// @recomp Lock the frame divisor in the Mumbo SNS pictures based on the loaded map.
|
||||
// This makes sure that the dialog doesn't get cut off because the scene runs too quickly.
|
||||
if (game_mode == GAME_MODE_A_SNS_PICTURE) {
|
||||
s32 cur_map = map_get();
|
||||
|
||||
switch (cur_map) {
|
||||
// 20 FPS maps.
|
||||
case MAP_7F_FP_WOZZAS_CAVE:
|
||||
case MAP_92_GV_SNS_CHAMBER:
|
||||
demo_frame_divisor = 3;
|
||||
break;
|
||||
// Remaining maps run at 30 FPS.
|
||||
default:
|
||||
demo_frame_divisor = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return not_eof;
|
||||
}
|
||||
|
||||
int extraVis = 0;
|
||||
|
||||
// @recomp Patched to override the VI frame divisor when the demo frame divisor has been set.
|
||||
// Also overrides it if a cutscene needs timing compensation.
|
||||
RECOMP_PATCH s32 viMgr_func_8024BFA0() {
|
||||
if (demo_frame_divisor != -1) {
|
||||
return demo_frame_divisor;
|
||||
}
|
||||
return D_802808DC + extraVis;
|
||||
}
|
||||
|
||||
// @recomp Patched to clear lag overrides after viMgr_func_8024BFD8.
|
||||
RECOMP_PATCH void viMgr_func_8024C1B4(void){
|
||||
viMgr_func_8024BFD8(0);
|
||||
// @recomp Clear the demo frame divisor.
|
||||
demo_frame_divisor = -1;
|
||||
dummy_func_8025AFB8();
|
||||
// @recomp Clear the lag override for cutscenes.
|
||||
extraVis = 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to clear lag overrides after viMgr_func_8024BFD8.
|
||||
RECOMP_PATCH void viMgr_func_8024C1DC(void){
|
||||
viMgr_func_8024BFD8(1);
|
||||
// @recomp Clear the demo frame divisor.
|
||||
demo_frame_divisor = -1;
|
||||
// @recomp Clear the lag override for cutscenes.
|
||||
extraVis = 0;
|
||||
}
|
||||
|
||||
// @recomp Patched to use a fixed time delta of 30 FPS when decrementing the hourglass timer during Bottles' Bonus.
|
||||
// Because the game is running at 20 FPS, this will result in the timer running slightly slower, which is accurate
|
||||
// to how fast it runs on original hardware.
|
||||
RECOMP_PATCH void func_80345EB0(enum item_e item){
|
||||
if(func_802FAFE8(item)){
|
||||
// @recomp Get the time delta and override it if this is the hourglass timer and the gamemode is Bottles' Bonus.
|
||||
f32 time_delta = time_getDelta();
|
||||
if (item == ITEM_0_HOURGLASS_TIMER && getGameMode() == GAME_MODE_8_BOTTLES_BONUS) {
|
||||
time_delta = 1.0f / 30.0f;
|
||||
}
|
||||
item_adjustByDiffWithHud(item, (s32)(-time_delta*60.0f * 1.1));
|
||||
}else{
|
||||
func_802FACA4(item);
|
||||
}
|
||||
}
|
||||
|
||||
// The concert intro cutscene stutters on console, but it does not stutter in recomp.
|
||||
// The cutscene is timed with the stutters in mind so this causes desyncs with the music and sound effects.
|
||||
// We have manually analyzed the cutscene and taken note of the exact frames during which it stutters,
|
||||
// and we lag the game to 15 FPS internally (this cutscene targets 20 FPS) for a few frames when it would
|
||||
// have stuttered on console in order to keep the cutscene in sync.
|
||||
|
||||
// What frames of the cutscene to lag on, and for how many frames.
|
||||
int concertStuttersStartFrames[] = { 269, 521, 583, 663, 769, 959, 1155, 1182, 1214 };
|
||||
int concertStutterDurations[] = { 4, 4, 4, 4, 4, 4, 4, 4, 4 };
|
||||
|
||||
// What frames of the cutscene to lag on, and for how many frames.
|
||||
int lairDingpotStuttersStartFrames[] = { 258, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000 };
|
||||
int lairDingpotStutterDurations[] = { 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
|
||||
|
||||
// These are reset on map load, so that the cutscene can be replayed (such as when saving and exiting)
|
||||
// See func_803329AC in load_patches.c
|
||||
int cutsceneCounter = 0;
|
||||
int cutsceneNextStutter = 0;
|
||||
int cutsceneLagIndex = 0;
|
||||
|
||||
bool should_lag_cutscene(int *stuttersStartFrames, int *stutterDurations, int stuttersStartFramesCount) {
|
||||
// No stutters left to compensate for. Exit the function early.
|
||||
if (cutsceneNextStutter == -1) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//recomp_printf("cutsceneCounter %d\n", cutsceneCounter);
|
||||
|
||||
// First frame of the cutscene. Set the first stutter frame.
|
||||
if (cutsceneNextStutter < stuttersStartFrames[0]) {
|
||||
cutsceneNextStutter = stuttersStartFrames[0];
|
||||
//recomp_printf("Start cutscene with timing corrections. First stutter frame: %d\n", cutsceneNextStutter);
|
||||
}
|
||||
|
||||
if (cutsceneCounter >= (cutsceneNextStutter) && cutsceneCounter < (cutsceneNextStutter + stutterDurations[cutsceneLagIndex])) {
|
||||
// A stutter would have occured on console now. Lag the game for a given amount of frames.
|
||||
//recomp_printf("LAGGING. Stutter number %d. Frame number %d\n", cutsceneLagIndex, cutsceneCounter);
|
||||
return TRUE;
|
||||
} else if (cutsceneCounter > (cutsceneNextStutter)) {
|
||||
cutsceneLagIndex++;
|
||||
if (cutsceneLagIndex >= stuttersStartFramesCount) {
|
||||
// That was the last stutter. We're done.
|
||||
cutsceneNextStutter = -1;
|
||||
//recomp_printf("End cutscene. %d\n", cutsceneNextStutter);
|
||||
} else {
|
||||
// Set the next stutter frame.
|
||||
cutsceneNextStutter = stuttersStartFrames[cutsceneLagIndex];
|
||||
//recomp_printf("Next stutter: %d\n", cutsceneNextStutter);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
// Reset the custom cutscene frame counter and the stutter frame index used to
|
||||
// correct the timings of the cutscene.
|
||||
void reset_cutscene_timings_state(void) {
|
||||
cutsceneCounter = 0;
|
||||
cutsceneNextStutter = 0;
|
||||
cutsceneLagIndex = 0;
|
||||
}
|
||||
|
||||
// Return the current cutscene counter.
|
||||
u32 get_cutscene_counter(void) {
|
||||
return cutsceneCounter;
|
||||
}
|
||||
|
||||
// Check the current map to see if it's a cutscene map that requires timing fixes,
|
||||
// and run the relevant function if so.
|
||||
void handle_cutscene_timings(void) {
|
||||
switch (map_get()) {
|
||||
case MAP_1E_CS_START_NINTENDO:
|
||||
if (should_lag_cutscene(concertStuttersStartFrames, concertStutterDurations, (int)sizeof(concertStuttersStartFrames) / (int)sizeof(concertStuttersStartFrames[0]))) {
|
||||
extraVis = 1;
|
||||
}
|
||||
cutsceneCounter++;
|
||||
break;
|
||||
case MAP_7B_CS_INTRO_GL_DINGPOT_1:
|
||||
if (should_lag_cutscene(lairDingpotStuttersStartFrames, lairDingpotStutterDurations, (int)sizeof(lairDingpotStuttersStartFrames) / (int)sizeof(lairDingpotStuttersStartFrames[0]))) {
|
||||
extraVis = 1;
|
||||
}
|
||||
cutsceneCounter++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||