diff --git a/UnleashedRecomp/patches/video_patches.cpp b/UnleashedRecomp/patches/video_patches.cpp index e7083196..68e96b52 100644 --- a/UnleashedRecomp/patches/video_patches.cpp +++ b/UnleashedRecomp/patches/video_patches.cpp @@ -66,3 +66,139 @@ bool MotionBlurMidAsmHook() { return Config::MotionBlur != EMotionBlur::Off; } + +// These are here for now to not recompile basically all of the project. +namespace Chao::CSD +{ + struct Cast + { + SWA_INSERT_PADDING(0x144); + }; + + struct CastLink + { + be ChildCastIndex; + be SiblingCastIndex; + }; + + struct CastNode + { + be CastCount; + xpointer pCasts; + be RootCastIndex; + xpointer pCastLinks; + }; + + struct CastIndex + { + xpointer pCastName; + be CastNodeIndex; + be CastIndex; + }; + + struct Scene + { + SWA_INSERT_PADDING(0x24); + be CastNodeCount; + xpointer pCastNodes; + be CastCount; + xpointer pCastIndices; + }; + + struct SceneIndex + { + xpointer pSceneName; + be SceneIndex; + }; + + struct SceneNodeIndex + { + xpointer pSceneNodeName; + be SceneNodeIndex; + }; + + struct SceneNode + { + be SceneCount; + xpointer> pScenes; + xpointer pSceneIndices; + be SceneNodeCount; + xpointer pSceneNodes; + xpointer pSceneNodeIndices; + }; + + struct Project + { + xpointer pRootNode; + }; +} + +static std::map g_paths; + +static void EmplacePath(const void* key, const std::string_view& value) +{ + g_paths.emplace(key, XXH3_64bits(value.data(), value.size())); +} + +static void TraverseCast(Chao::CSD::Scene* scene, uint32_t castNodeIndex, Chao::CSD::CastNode* castNode, uint32_t castIndex, const std::string& parentPath) +{ + if (castIndex == ~0) + return; + + TraverseCast(scene, castNodeIndex, castNode, castNode->pCastLinks[castIndex].SiblingCastIndex, parentPath); + + std::string path = parentPath; + + for (size_t i = 0; i < scene->CastCount; i++) + { + auto& index = scene->pCastIndices[i]; + if (index.CastNodeIndex == castNodeIndex && index.CastIndex == castIndex) + { + path += index.pCastName; + break; + } + } + + EmplacePath(&castNode->pCasts[castIndex], path); + path += "/"; + + TraverseCast(scene, castNodeIndex, castNode, castNode->pCastLinks[castIndex].ChildCastIndex, path); +} + +static void TraverseScene(Chao::CSD::Scene* scene, std::string path) +{ + EmplacePath(scene, path); + path += "/"; + + for (size_t i = 0; i < scene->CastNodeCount; i++) + { + auto& castNode = scene->pCastNodes[i]; + TraverseCast(scene, i, &castNode, castNode.RootCastIndex, path); + } +} + +static void TraverseSceneNode(Chao::CSD::SceneNode* sceneNode, std::string path) +{ + EmplacePath(sceneNode, path); + path += "/"; + + for (size_t i = 0; i < sceneNode->SceneCount; i++) + { + auto& sceneIndex = sceneNode->pSceneIndices[i]; + TraverseScene(sceneNode->pScenes[sceneIndex.SceneIndex], path + sceneIndex.pSceneName.get()); + } + + for (size_t i = 0; i < sceneNode->SceneNodeCount; i++) + { + auto& sceneNodeIndex = sceneNode->pSceneNodeIndices[i]; + TraverseSceneNode(&sceneNode->pSceneNodes[sceneNodeIndex.SceneNodeIndex], path + sceneNodeIndex.pSceneNodeName.get()); + } +} + +void MakeCsdProjectMidAsmHook(PPCRegister& r3, PPCRegister& r29) +{ + uint8_t* base = g_memory.base; + auto csdProject = reinterpret_cast(base + PPC_LOAD_U32(PPC_LOAD_U32(r3.u32 + 16) + 4)); + auto name = reinterpret_cast(base + PPC_LOAD_U32(r29.u32)); + TraverseSceneNode(csdProject->m_pResource->pRootNode, name); +} diff --git a/UnleashedRecompLib/config/SWA.toml b/UnleashedRecompLib/config/SWA.toml index 61616295..c327635f 100644 --- a/UnleashedRecompLib/config/SWA.toml +++ b/UnleashedRecompLib/config/SWA.toml @@ -590,3 +590,8 @@ jump_address = 0x82B723BC name = "DisableDLCIconMidAsmHook" address = 0x825756B0 jump_address_on_true = 0x825756E0 + +[[midasm_hook]] +name = "MakeCsdProjectMidAsmHook" +address = 0x825E4120 +registers = ["r3", "r29"]