From e69af98c775ee45c2ae721f2da51ceccba4d76e0 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Mon, 9 Nov 2026 20:50:58 +0000 Subject: [PATCH] Decompile 2 functions in Source/Resource/Models/ModelResourceV2.cpp Batch #15309 by Yommy: 0 byte-identical, 2 confirmed by peer review. - fn_08020 C3dModelResV2::ReadVersion1: logic confirmed by peer review - fn_08022 C3dModelResV2::ReadVersion3: logic confirmed by peer review Peer-reviewed-by: ragnarok-clanker, eAthena Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/Resource/Models/ModelResourceV2.cpp | 154 +++++++++++++-------- 1 file changed, 93 insertions(+), 61 deletions(-) diff --git a/Source/Resource/Models/ModelResourceV2.cpp b/Source/Resource/Models/ModelResourceV2.cpp index ef92d5063..d974c301b 100644 --- a/Source/Resource/Models/ModelResourceV2.cpp +++ b/Source/Resource/Models/ModelResourceV2.cpp @@ -10,6 +10,15 @@ #include #include +struct ModelFaceRecord { + /* 0000 */ std::uint16_t vertices[3]; + /* 0006 */ std::uint16_t textureVertices[3]; + /* 000C */ std::uint16_t texture; + /* 000E */ std::uint16_t unknown_000E; + /* 0010 */ std::uint32_t twoSided; + /* 0014 */ std::uint32_t smoothing; +}; + // OFFSET: 0x007555C0 // FUNCTION: fn_07984 C3dModelResV2::C3dModelResV2() : framesPerSecond(0.0f), animationLength(0) { @@ -106,7 +115,7 @@ void C3dModelResV2::ReadVersion1(CFile& input) { auto* node = new ModelNodeV2; node->model = this; node->mesh.reset(new ModelMesh); - unsigned bytes = 0; + int bytes = 0; input.Read(&bytes, 4); char name[40]{}; input.Read(name, bytes); @@ -114,7 +123,7 @@ void C3dModelResV2::ReadVersion1(CFile& input) { bytes = 0; input.Read(&bytes, 4); - if (static_cast(bytes) > 0) { + if (bytes > 0) { char parentName[40]{}; input.Read(parentName, bytes); node->parentName = parentName; @@ -135,26 +144,26 @@ void C3dModelResV2::ReadVersion1(CFile& input) { } input.Read(node->transform, sizeof(node->transform)); - ModelMesh& mesh = *node->mesh; - input.Read(&mesh.vertexCount, 4); - mesh.vertices = new std::array[mesh.vertexCount]{}; - input.Read(mesh.vertices, static_cast(mesh.vertexCount) * 12u); - input.Read(&mesh.textureVertexCount, 4); - mesh.textureVertices = new ModelTextureVertex[mesh.textureVertexCount]; - input.Read(mesh.textureVertices, static_cast(mesh.textureVertexCount) * 12u); - input.Read(&mesh.faceCount, 4); - mesh.faces = new ModelFace[mesh.faceCount]; + int vertexCount = 0; + input.Read(&vertexCount, 4); + node->mesh->vertexCount = vertexCount; + auto* vertices = new std::array[vertexCount]{}; + input.Read(vertices, static_cast(vertexCount) * 12u); + node->mesh->vertices = vertices; + int textureVertexCount = 0; + input.Read(&textureVertexCount, 4); + node->mesh->textureVertexCount = textureVertexCount; + ModelTextureVertex* textureVertices = new ModelTextureVertex[textureVertexCount]; + input.Read(textureVertices, static_cast(textureVertexCount) * 12u); + node->mesh->textureVertices = textureVertices; + int faceCount = 0; + input.Read(&faceCount, 4); + node->mesh->faceCount = faceCount; + ModelFace* faces = new ModelFace[faceCount]; - for (int face = 0; face < mesh.faceCount; ++face) { - ModelFace& target = mesh.faces[face]; - struct { - /* 0000 */ std::uint16_t vertices[3]; - /* 0006 */ std::uint16_t textureVertices[3]; - /* 000C */ std::uint16_t texture; - /* 000E */ std::uint16_t unknown_000E; - /* 0010 */ std::uint32_t twoSided; - /* 0014 */ std::uint32_t smoothing; - } record; + for (int face = 0; face < faceCount; ++face) { + ModelFace& target = faces[face]; + ModelFaceRecord record; input.Read(&record, sizeof(record)); for (int corner = 0; corner < 3; ++corner) { target.vertices[corner] = record.vertices[corner]; @@ -170,8 +179,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(); + node->mesh->faces = faces; + std::sort(node->mesh->faces, node->mesh->faces + node->mesh->faceCount, [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; }); + node->mesh->CalculateNormals(); node->scaleKeys.Read(input); node->rotationKeys.Read(input); node->positionKeys.Read(input); @@ -190,14 +200,16 @@ void C3dModelResV2::ReadVersion1(CFile& input) { } } - int volumeCount = 0; - input.Read(&volumeCount, 4); + { + int volumeCount = 0; + input.Read(&volumeCount, 4); - for (int index = 0; index < volumeCount; ++index) { - auto* volume = new ModelVolume; - std::memset(volume, 0, 132); - input.Read(volume, sizeof(ModelVolume)); - this->volumes.push_back(volume); + for (int index = 0; index < volumeCount; ++index) { + auto* volume = new ModelVolume; + std::memset(volume, 0, 132); + input.Read(volume, sizeof(ModelVolume)); + this->volumes.push_back(volume); + } } } @@ -335,7 +347,7 @@ void C3dModelResV2::ReadVersion3(CFile& input) { input.Read(&bytes, 4); char name[40]{}; input.Read(name, bytes); - this->rootNames.emplace_back(name); + this->rootNames.push_back(name); } int nodeCount = 0; @@ -345,18 +357,20 @@ void C3dModelResV2::ReadVersion3(CFile& input) { auto* node = new ModelNodeV2; node->model = this; node->mesh.reset(new ModelMesh); - unsigned bytes = 0; - input.Read(&bytes, 4); - char name[40]{}; - input.Read(name, bytes); - node->name = name; - bytes = 0; - input.Read(&bytes, 4); + { + int bytes = 0; + input.Read(&bytes, 4); + char name[40]{}; + input.Read(name, bytes); + node->name = name; + bytes = 0; + input.Read(&bytes, 4); - if (static_cast(bytes) > 0) { - char parentName[40]{}; - input.Read(parentName, bytes); - node->parentName = parentName; + if (bytes > 0) { + char parentName[40]{}; + input.Read(parentName, bytes); + node->parentName = parentName; + } } int nodeTextureCount = 0; @@ -376,30 +390,48 @@ void C3dModelResV2::ReadVersion3(CFile& input) { } input.Read(node->transform, sizeof(node->transform)); - ModelMesh& mesh = *node->mesh; - input.Read(&mesh.vertexCount, 4); - mesh.vertices = new std::array[mesh.vertexCount]{}; - input.Read(mesh.vertices, static_cast(mesh.vertexCount) * 12u); - input.Read(&mesh.textureVertexCount, 4); - mesh.textureVertices = new ModelTextureVertex[mesh.textureVertexCount]; - input.Read(mesh.textureVertices, static_cast(mesh.textureVertexCount) * 12u); - input.Read(&mesh.faceCount, 4); - mesh.faces = new ModelFace[mesh.faceCount]; + int vertexCount = 0; + input.Read(&vertexCount, 4); + node->mesh->vertexCount = vertexCount; + auto* vertices = new std::array[vertexCount]{}; + input.Read(vertices, static_cast(vertexCount) * 12u); + node->mesh->vertices = vertices; + int textureVertexCount = 0; + input.Read(&textureVertexCount, 4); + node->mesh->textureVertexCount = textureVertexCount; + ModelTextureVertex* textureVertices = new ModelTextureVertex[textureVertexCount]; + input.Read(textureVertices, static_cast(textureVertexCount) * 12u); + node->mesh->textureVertices = textureVertices; + int faceCount = 0; + input.Read(&faceCount, 4); + node->mesh->faceCount = faceCount; + ModelFace* faces = new ModelFace[faceCount]; - for (int face = 0; face < mesh.faceCount; ++face) { - ModelFace& target = mesh.faces[face]; + for (int face = 0; face < faceCount; ++face) { + ModelFace& target = faces[face]; unsigned size = 0; input.Read(&size, 4); - std::vector record(size); - input.Read(record.data(), size); - std::memcpy(&target, record.data(), 20); - const unsigned groups = (size - 20u) / 4u; + std::vector buffer; + buffer.resize(size); + input.Read(buffer.data(), size); + ModelFaceRecord record; + std::memcpy(&record, buffer.data(), 20); + 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.twoSided = record.twoSided; + const unsigned groups = (buffer.size() - 20u) / 4u; target.smoothing.resize(groups); - std::memcpy(target.smoothing.data(), record.data() + 20, groups * 4u); + std::memcpy(target.smoothing.data(), buffer.data() + 20, groups * 4u); } - std::sort(mesh.faces, mesh.faces + mesh.faceCount, [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; }); - mesh.CalculateNormals(); + node->mesh->faces = faces; + std::sort(node->mesh->faces, node->mesh->faces + node->mesh->faceCount, [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; }); + node->mesh->CalculateNormals(); node->scaleKeys.Read(input); node->rotationKeys.Read(input); node->positionKeys.Read(input); @@ -412,7 +444,7 @@ void C3dModelResV2::ReadVersion3(CFile& input) { ModelTextureChannelMap channels; channels.Read(input); - node->textureKeys[texture] = std::move(channels); + node->textureKeys[texture] = channels; } this->nodes.push_back(node);