From adbe1db7e1b80d627dd71f66f368fa2c53deeded Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Sat, 7 Nov 2026 17:22:36 +0000 Subject: [PATCH] Decompile 3 functions in Source/Resource/Models/ModelResourceV2.cpp, Source/Resource/Models/ModelResource.h, ... Batch #14636 by secret: 0 byte-identical, 3 confirmed by peer review. - fn_08020 C3dModelResV2::ReadVersion1: logic confirmed by peer review - fn_08021 C3dModelResV2::ReadVersion2: logic confirmed by peer review - fn_08022 C3dModelResV2::ReadVersion3: logic confirmed by peer review Peer-reviewed-by: Tanke, Toshiro, codeplay Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- .../Contents/Models/ModelTextureAnimation.cpp | 20 ------ Source/Resource/Models/ModelResource.cpp | 3 - Source/Resource/Models/ModelResource.h | 31 ++++++++- Source/Resource/Models/ModelResourceV2.cpp | 64 +++++-------------- 4 files changed, 45 insertions(+), 73 deletions(-) diff --git a/Source/Contents/Models/ModelTextureAnimation.cpp b/Source/Contents/Models/ModelTextureAnimation.cpp index d25a58df2..54cc6d758 100644 --- a/Source/Contents/Models/ModelTextureAnimation.cpp +++ b/Source/Contents/Models/ModelTextureAnimation.cpp @@ -34,10 +34,6 @@ void SampleModelTexture(const ModelTextureChannels& channels, float frame, Model } } -struct ModelKeyList1 : std::vector { - void Read(CFile& file); -}; - // OFFSET: 0x00541160 // FUNCTION: fn_01728 void ModelKeyList1::Read(CFile& file) { @@ -50,10 +46,6 @@ void ModelKeyList1::Read(CFile& file) { } } -struct ModelKeyList2 : std::vector { - void Read(CFile& file); -}; - // OFFSET: 0x005411E0 // FUNCTION: fn_01729 void ModelKeyList2::Read(CFile& file) { @@ -66,10 +58,6 @@ void ModelKeyList2::Read(CFile& file) { } } -struct ModelKeyList3 : std::vector { - void Read(CFile& file); -}; - // OFFSET: 0x00541250 // FUNCTION: fn_01730 void ModelKeyList3::Read(CFile& file) { @@ -82,10 +70,6 @@ void ModelKeyList3::Read(CFile& file) { } } -struct ModelKeyList4 : std::vector { - void Read(CFile& file); -}; - // OFFSET: 0x00541350 // FUNCTION: fn_01731 void ModelKeyList4::Read(CFile& file) { @@ -98,10 +82,6 @@ void ModelKeyList4::Read(CFile& file) { } } -struct ModelTextureChannelMap : ModelTextureChannels { - void Read(CFile& file); -}; - // OFFSET: 0x005413D0 // FUNCTION: fn_01732 void ModelTextureChannelMap::Read(CFile& file) { diff --git a/Source/Resource/Models/ModelResource.cpp b/Source/Resource/Models/ModelResource.cpp index 5ccc6c197..1feabb183 100644 --- a/Source/Resource/Models/ModelResource.cpp +++ b/Source/Resource/Models/ModelResource.cpp @@ -72,9 +72,6 @@ __forceinline ModelNodeV1::ModelNodeV1() = default; // INLINED ModelNodeV1::~ModelNodeV1() = default; -// INLINED -ModelNodeV2::ModelNodeV2() = default; - // INLINED ModelNodeV2::~ModelNodeV2() = default; diff --git a/Source/Resource/Models/ModelResource.h b/Source/Resource/Models/ModelResource.h index 0f7318edc..51c1a7b5a 100644 --- a/Source/Resource/Models/ModelResource.h +++ b/Source/Resource/Models/ModelResource.h @@ -40,6 +40,28 @@ struct ModelTextureKey { using ModelTextureChannels = std::map>; +class CFile; + +struct ModelKeyList1 : std::vector { + void Read(CFile& file); +}; + +struct ModelKeyList2 : std::vector { + void Read(CFile& file); +}; + +struct ModelKeyList3 : std::vector { + void Read(CFile& file); +}; + +struct ModelKeyList4 : std::vector { + void Read(CFile& file); +}; + +struct ModelTextureChannelMap : ModelTextureChannels { + void Read(CFile& file); +}; + static_assert(sizeof(ModelTextureKey) == 8); struct ModelVolume { @@ -88,12 +110,15 @@ public: ~ModelNodeV2() override; /* 0058 */ float transform[12]; - /* 0088 */ std::vector scaleKeys; - /* 0094 */ std::vector rotationKeys; - /* 00A0 */ std::vector positionKeys; + /* 0088 */ ModelKeyList4 scaleKeys; + /* 0094 */ ModelKeyList3 rotationKeys; + /* 00A0 */ ModelKeyList1 positionKeys; /* 00AC */ std::map textureKeys; }; +// INLINED +inline ModelNodeV2::ModelNodeV2() = default; + class C3dModelRes : public CRes { friend class ModelNode; public: diff --git a/Source/Resource/Models/ModelResourceV2.cpp b/Source/Resource/Models/ModelResourceV2.cpp index b122f5a6f..ef92d5063 100644 --- a/Source/Resource/Models/ModelResourceV2.cpp +++ b/Source/Resource/Models/ModelResourceV2.cpp @@ -10,25 +10,6 @@ #include #include -namespace { - // INLINED - void ReadKeys(CFile& input, std::vector& keys, bool scale) { - int count = 0; - input.Read(&count, 4); - - for (int index = 0; index < count; ++index) { - ModelRotationKey key; - - if (scale) { - key = {0, {0, 0, 0, 1}}; - } - - input.Read(&key, sizeof(key)); - keys.push_back(key); - } - } -} - // OFFSET: 0x007555C0 // FUNCTION: fn_07984 C3dModelResV2::C3dModelResV2() : framesPerSecond(0.0f), animationLength(0) { @@ -175,10 +156,13 @@ void C3dModelResV2::ReadVersion1(CFile& input) { /* 0014 */ std::uint32_t smoothing; } record; input.Read(&record, sizeof(record)); - std::memcpy(target.vertices, record.vertices, sizeof(target.vertices)); - std::memcpy(target.textureVertices, record.textureVertices, sizeof(target.textureVertices)); + for (int corner = 0; corner < 3; ++corner) { + target.vertices[corner] = record.vertices[corner]; + } + for (int corner = 0; corner < 3; ++corner) { + target.textureVertices[corner] = record.textureVertices[corner]; + } target.texture = record.texture; - target.unknown_000E = record.unknown_000E; target.twoSided = record.twoSided; if (target.smoothing.empty()) { @@ -188,9 +172,9 @@ void C3dModelResV2::ReadVersion1(CFile& input) { std::sort(mesh.faces, mesh.faces + mesh.faceCount, [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; }); mesh.CalculateNormals(); - ReadKeys(input, node->scaleKeys, false); - ReadKeys(input, node->rotationKeys, true); - ReadKeys(input, node->positionKeys, false); + node->scaleKeys.Read(input); + node->rotationKeys.Read(input); + node->positionKeys.Read(input); this->nodes.push_back(node); this->meshes[node->name] = node->mesh.get(); } @@ -307,9 +291,9 @@ void C3dModelResV2::ReadVersion2(CFile& input) { std::sort(mesh.faces, mesh.faces + mesh.faceCount, [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; }); mesh.CalculateNormals(); - ReadKeys(input, node->scaleKeys, false); - ReadKeys(input, node->rotationKeys, true); - ReadKeys(input, node->positionKeys, false); + node->scaleKeys.Read(input); + node->rotationKeys.Read(input); + node->positionKeys.Read(input); this->nodes.push_back(node); this->meshes[node->name] = node->mesh.get(); } @@ -416,31 +400,17 @@ void C3dModelResV2::ReadVersion3(CFile& input) { std::sort(mesh.faces, mesh.faces + mesh.faceCount, [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; }); mesh.CalculateNormals(); - ReadKeys(input, node->scaleKeys, false); - ReadKeys(input, node->rotationKeys, true); - ReadKeys(input, node->positionKeys, false); + node->scaleKeys.Read(input); + node->rotationKeys.Read(input); + node->positionKeys.Read(input); int textureAnimations = 0; input.Read(&textureAnimations, 4); for (int animation = 0; animation < textureAnimations; ++animation) { int texture = 0; input.Read(&texture, 4); - ModelTextureChannels channels; - int channelCount = 0; - input.Read(&channelCount, 4); - - for (int channel = 0; channel < channelCount; ++channel) { - int id = 0; - int keyCount = 0; - input.Read(&id, 4); - input.Read(&keyCount, 4); - - for (int key = 0; key < keyCount; ++key) { - ModelTextureKey value; - input.Read(&value, sizeof(value)); - channels[id].push_back(value); - } - } + ModelTextureChannelMap channels; + channels.Read(input); node->textureKeys[texture] = std::move(channels); }