diff --git a/DataSpec/DNACommon/ANCS.hpp b/DataSpec/DNACommon/ANCS.hpp index 81313155d..4f0c742f5 100644 --- a/DataSpec/DNACommon/ANCS.hpp +++ b/DataSpec/DNACommon/ANCS.hpp @@ -41,7 +41,7 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn, const SpecBase& dataspec, std::function fileChanged, bool force=false) -{ +{ /* Extract character CMDL/CSKR first */ std::vector> chResInfo; ancs.getCharacterResInfo(chResInfo); diff --git a/DataSpec/DNACommon/CMDL.cpp b/DataSpec/DNACommon/CMDL.cpp index 813e24743..81137275b 100644 --- a/DataSpec/DNACommon/CMDL.cpp +++ b/DataSpec/DNACommon/CMDL.cpp @@ -1,10 +1,415 @@ #include "CMDL.hpp" +#include "../DNAMP1/CMDLMaterials.hpp" +#include "../DNAMP1/CSKR.hpp" +#include "../DNAMP2/CMDLMaterials.hpp" +#include "../DNAMP2/CSKR.hpp" +#include "../DNAMP3/CMDLMaterials.hpp" +#include "../DNAMP3/CSKR.hpp" namespace DataSpec { namespace DNACMDL { +template +void GetVertexAttributes(const MaterialSet& matSet, + std::vector& attributesOut) +{ + attributesOut.clear(); + attributesOut.reserve(matSet.materials.size()); + + for (const typename MaterialSet::Material& mat : matSet.materials) + { + const typename MaterialSet::Material::VAFlags& vaFlags = mat.getVAFlags(); + attributesOut.emplace_back(); + VertexAttributes& va = attributesOut.back(); + + va.pos = vaFlags.position(); + va.norm = vaFlags.normal(); + va.color0 = vaFlags.color0(); + va.color1 = vaFlags.color1(); + + if ((va.uvs[0] = vaFlags.tex0())) + ++va.uvCount; + if ((va.uvs[1] = vaFlags.tex1())) + ++va.uvCount; + if ((va.uvs[2] = vaFlags.tex2())) + ++va.uvCount; + if ((va.uvs[3] = vaFlags.tex3())) + ++va.uvCount; + if ((va.uvs[4] = vaFlags.tex4())) + ++va.uvCount; + if ((va.uvs[5] = vaFlags.tex5())) + ++va.uvCount; + if ((va.uvs[6] = vaFlags.tex6())) + ++va.uvCount; + + va.pnMtxIdx = vaFlags.pnMatIdx(); + + if ((va.texMtxIdx[0] = vaFlags.tex0MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[1] = vaFlags.tex1MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[2] = vaFlags.tex2MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[3] = vaFlags.tex3MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[4] = vaFlags.tex4MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[5] = vaFlags.tex5MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[6] = vaFlags.tex6MatIdx())) + ++va.texMtxIdxCount; + + va.shortUVs = mat.getFlags().lightmapUVArray(); + } +} + +template +void ReadMaterialSetToBlender_1_2(HECL::BlenderConnection::PyOutStream& os, + const MaterialSet& matSet, + const PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + unsigned setIdx) +{ + /* Texmaps */ + os << "texmap_list = []\n"; + for (const UniqueID32& tex : matSet.head.textureIDs) + { + std::string texName = pakRouter.getBestEntryName(tex); + const NOD::Node* node; + const typename PAKRouter::EntryType* texEntry = pakRouter.lookupEntry(tex, &node); + HECL::ProjectPath txtrPath = pakRouter.getWorking(texEntry); + if (txtrPath.getPathType() == HECL::ProjectPath::Type::None) + { + PAKEntryReadStream rs = texEntry->beginReadStream(*node); + TXTR::Extract(rs, txtrPath); + } + HECL::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex); + HECL::SystemUTF8View resPathView(resPath); + os.format("if '%s' in bpy.data.textures:\n" + " image = bpy.data.images['%s']\n" + " texture = bpy.data.textures[image.name]\n" + "else:\n" + " image = bpy.data.images.load('''//%s''')\n" + " image.name = '%s'\n" + " texture = bpy.data.textures.new(image.name, 'IMAGE')\n" + " texture.image = image\n" + "texmap_list.append(texture)\n" + "\n", texName.c_str(), texName.c_str(), + resPathView.str().c_str(), texName.c_str()); + } + + unsigned m=0; + for (const typename MaterialSet::Material& mat : matSet.materials) + { + MaterialSet::ConstructMaterial(os, mat, setIdx, m++); + os << "materials.append(new_material)\n"; + } +} + +template +void ReadMaterialSetToBlender_3(HECL::BlenderConnection::PyOutStream& os, + const MaterialSet& matSet, + const PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + unsigned setIdx) +{ + unsigned m=0; + for (const typename MaterialSet::Material& mat : matSet.materials) + { + MaterialSet::ConstructMaterial(os, pakRouter, entry, mat, setIdx, m++); + os << "materials.append(new_material)\n"; + } +} + +class DLReader +{ +public: + /* Class used for splitting verts with shared positions but different skinning matrices */ + class ExtraVertTracker + { + std::map>> m_extraVerts; + atUint16 m_maxBasePos = 0; + atUint16 m_nextOverPos = 1; + public: + atInt16 addPosSkinPair(atUint16 pos, atInt16 skin) + { + m_maxBasePos = std::max(m_maxBasePos, pos); + auto search = m_extraVerts.find(pos); + if (search == m_extraVerts.end()) + { + m_extraVerts[pos] = {std::make_pair(skin, 0)}; + return skin; + } + std::vector>& vertTrack = search->second; + for (const std::pair& s : vertTrack) + if (s.first == skin) + return vertTrack.front().first; + vertTrack.push_back(std::make_pair(skin, m_nextOverPos++)); + return vertTrack.front().first; + } + + template + void sendAdditionalVertsToBlender(HECL::BlenderConnection::PyOutStream& os, + const RigPair& rp) const + { + atUint32 nextVert = 1; + while (nextVert < m_nextOverPos) + { + for (const std::pair>>& ev : m_extraVerts) + { + for (const std::pair& se : ev.second) + { + if (se.second == nextVert) + { + os.format("bm.verts.ensure_lookup_table()\n" + "orig_vert = bm.verts[%u]\n" + "vert = bm.verts.new(orig_vert.co)\n", + ev.first); + rp.first->weightVertex(os, *rp.second, se.first); + ++nextVert; + } + } + } + } + } + + atUint16 lookupVertIdx(atUint16 pos, atInt16 skin) const + { + auto search = m_extraVerts.find(pos); + if (search == m_extraVerts.end()) + return -1; + const std::vector>& vertTrack = search->second; + if (vertTrack.front().first == skin) + return pos; + for (auto it=vertTrack.begin()+1 ; it!=vertTrack.end() ; ++it) + if (it->first == skin) + return m_maxBasePos + it->second; + return -1; + } + }; + +private: + const VertexAttributes& m_va; + std::unique_ptr m_dl; + size_t m_dlSize; + ExtraVertTracker& m_evt; + const atInt16* m_bankIn; + atUint8* m_cur; + atUint16 readVal(GX::AttrType type) + { + atUint16 retval = 0; + switch (type) + { + case GX::DIRECT: + case GX::INDEX8: + if ((m_cur - m_dl.get()) >= intptr_t(m_dlSize)) + return 0; + retval = *m_cur; + ++m_cur; + break; + case GX::INDEX16: + if ((m_cur - m_dl.get() + 1) >= intptr_t(m_dlSize)) + return 0; + retval = HECL::SBig(*(atUint16*)m_cur); + m_cur += 2; + break; + default: break; + } + return retval; + } +public: + DLReader(const VertexAttributes& va, std::unique_ptr&& dl, + size_t dlSize, ExtraVertTracker& evt, const atInt16* bankIn=nullptr) + : m_va(va), m_dl(std::move(dl)), m_dlSize(dlSize), m_evt(evt), m_bankIn(bankIn) + { + m_cur = m_dl.get(); + } + + operator bool() + { + return ((m_cur - m_dl.get()) < intptr_t(m_dlSize)) && *m_cur; + } + + GX::Primitive readPrimitive() + { + return GX::Primitive(*m_cur++ & 0xf8); + } + + GX::Primitive readPrimitiveAndVat(unsigned& vatOut) + { + atUint8 val = *m_cur++; + vatOut = val & 0x7; + return GX::Primitive(val & 0xf8); + } + + atUint16 readVertCount() + { + atUint16 retval = HECL::SBig(*(atUint16*)m_cur); + m_cur += 2; + return retval; + } + + struct DLPrimVert + { + atUint16 pos = 0; + atUint16 norm = 0; + atUint16 color[2] = {0}; + atUint16 uvs[7] = {0}; + atUint8 pnMtxIdx = 0; + atUint8 texMtxIdx[7] = {0}; + }; + + DLPrimVert readVert(bool peek=false) + { + atUint8* bakCur = m_cur; + DLPrimVert retval; + retval.pnMtxIdx = readVal(m_va.pnMtxIdx); + retval.texMtxIdx[0] = readVal(m_va.texMtxIdx[0]); + retval.texMtxIdx[1] = readVal(m_va.texMtxIdx[1]); + retval.texMtxIdx[2] = readVal(m_va.texMtxIdx[2]); + retval.texMtxIdx[3] = readVal(m_va.texMtxIdx[3]); + retval.texMtxIdx[4] = readVal(m_va.texMtxIdx[4]); + retval.texMtxIdx[5] = readVal(m_va.texMtxIdx[5]); + retval.texMtxIdx[6] = readVal(m_va.texMtxIdx[6]); + if (m_bankIn) + { + atUint16 posIdx = readVal(m_va.pos); + atUint8 mtxIdx = retval.pnMtxIdx / 3; + atInt16 skinIdx = -1; + if (mtxIdx < 10) + skinIdx = m_bankIn[mtxIdx]; + retval.pos = m_evt.lookupVertIdx(posIdx, skinIdx); + } + else + retval.pos = readVal(m_va.pos); + retval.norm = readVal(m_va.norm); + retval.color[0] = readVal(m_va.color0); + retval.color[1] = readVal(m_va.color1); + retval.uvs[0] = readVal(m_va.uvs[0]); + retval.uvs[1] = readVal(m_va.uvs[1]); + retval.uvs[2] = readVal(m_va.uvs[2]); + retval.uvs[3] = readVal(m_va.uvs[3]); + retval.uvs[4] = readVal(m_va.uvs[4]); + retval.uvs[5] = readVal(m_va.uvs[5]); + retval.uvs[6] = readVal(m_va.uvs[6]); + if (peek) + m_cur = bakCur; + return retval; + } + + void preReadMaxIdxs(DLPrimVert& out) + { + atUint8* bakCur = m_cur; + while (*this) + { + readPrimitive(); + atUint16 vc = readVertCount(); + for (atUint16 v=0 ; v& skinOut) + { + atUint8* bakCur = m_cur; + while (*this) + { + readPrimitive(); + atUint16 vc = readVertCount(); + for (atUint16 v=0 ; v +atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os, + Athena::io::IStreamReader& reader, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + const RigPair& rp, + bool shortNormals, + bool shortUVs, + std::vector& vertAttribs, + int meshIdx, + atUint32 secCount, + atUint32 matSetCount, + const atUint32* secSizes, + atUint32 surfaceCount) +{ + os << "# Begin bmesh\n" + "bm = bmesh.new()\n" + "\n" + "# Overdraw-tracking\n" + "od_list = []\n" + "\n" + "orig_pidx_lay = bm.verts.layers.int.new('CMDLOriginalPosIdxs')\n" + "orig_nidx_lay = bm.loops.layers.int.new('CMDLOriginalNormIdxs')\n"; + + if (rp.first) + os << "dvert_lay = bm.verts.layers.deform.verify()\n"; + + /* Pre-read pass to determine maximum used vert indices */ + atUint32 matSecCount = 0; + if (matSetCount) + matSecCount = MaterialSet::OneSection() ? 1 : matSetCount; + bool visitedDLOffsets = false; + atUint32 lastDlSec = secCount; + atUint64 afterHeaderPos = reader.position(); + DLReader::DLPrimVert maxIdxs; + std::vector skinIndices; + DLReader::ExtraVertTracker extraTracker; + for (size_t s=0 ; sgetMatrixBank(sHead.skinMatrixBankIdx()); + + /* Do max index pre-read */ + atUint32 realDlSize = secSizes[s] - (reader.position() - secStart); + DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), + realDlSize, extraTracker, bankIn); + if (SurfaceHeader::UseMatrixSkinning() && rp.first) + dl.preReadMaxIdxs(maxIdxs, skinIndices); + else + dl.preReadMaxIdxs(maxIdxs); + + } + } + } + + if (s < secCount - 1) + reader.seek(secStart + secSizes[s], Athena::Begin); + } + + reader.seek(afterHeaderPos, Athena::Begin); + + visitedDLOffsets = false; + unsigned createdUVLayers = 0; + unsigned surfIdx = 0; + + for (size_t s=0 ; sweightVertex(os, *rp.second, skinIndices[i]); + else if (!SurfaceHeader::UseMatrixSkinning()) + rp.first->weightVertex(os, *rp.second, i); + } + } + if (rp.first && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) + extraTracker.sendAdditionalVertsToBlender(os, rp); + break; + } + case 1: + { + /* Normals */ + os << "norm_list = []\n"; + if (shortNormals) + { + size_t normCount = secSizes[s] / 6; + for (size_t i=0 ; igetMatrixBank(sHead.skinMatrixBankIdx()); + + os.format("materials[%u].pass_index = %u\n", sHead.matIdx, surfIdx++); + if (matUVCount > createdUVLayers) + { + for (unsigned l=createdUVLayers ; l= vertCount - 3); + + /* Advance one prim vert */ + primVerts[c%3] = dl.readVert(peek); + ++c; + } + } + else if (ptype == GX::TRIANGLES) + { + for (int v=0 ; v= vertCount) + break; + + /* Advance 3 Prim Verts */ + for (int pv=0 ; pv<3 ; ++pv) + primVerts[pv] = dl.readVert(); + } + } + else if (ptype == GX::TRIANGLEFAN) + { + ++c; + for (int v=0 ; v= vertCount) + break; + + /* Advance one prim vert */ + primVerts[(c+2)%3] = dl.readVert(); + ++c; + } + } + os << "\n"; + } + } + } + } + + if (s < secCount - 1) + reader.seek(secStart + secSizes[s], Athena::Begin); + } + + /* Finish Mesh */ + FinishBlenderMesh(os, matSetCount, meshIdx); + + if (rp.first) + rp.second->sendVertexGroupsToBlender(os); + + return lastDlSec; +} + +template +bool ReadCMDLToBlender(HECL::BlenderConnection& conn, + Athena::io::IStreamReader& reader, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + const SpecBase& dataspec, + const RigPair& rp) +{ + Header head; + head.read(reader); + + if (head.magic != 0xDEADBABE) + { + LogDNACommon.report(LogVisor::Error, "invalid CMDL magic"); + return false; + } + + if (head.version != Version) + { + LogDNACommon.report(LogVisor::Error, "invalid CMDL version"); + return false; + } + + /* Open Py Stream and read sections */ + HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true); + os.format("import bpy\n" + "import bmesh\n" + "\n" + "bpy.context.scene.name = '%s'\n" + "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n", + pakRouter.getBestEntryName(entry).c_str()); + InitGeomBlenderContext(os, dataspec.getMasterShaderPath()); + MaterialSet::RegisterMaterialProps(os); + + os << "# Materials\n" + "materials = []\n" + "\n"; + + std::vector vertAttribs; + ReadGeomSectionsToBlender + (os, reader, pakRouter, entry, rp, head.flags.shortNormals(), + head.flags.shortUVs(), vertAttribs, -1, + head.secCount, head.matSetCount, head.secSizes.data()); + + return true; +} + +template bool ReadCMDLToBlender, DNAMP1::MaterialSet, + std::pair, DNACMDL::SurfaceHeader_1, 2> +(HECL::BlenderConnection& conn, + Athena::io::IStreamReader& reader, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + const SpecBase& dataspec, + const std::pair& rp); + +template bool ReadCMDLToBlender, DNAMP2::MaterialSet, + std::pair, DNACMDL::SurfaceHeader_2, 4> +(HECL::BlenderConnection& conn, + Athena::io::IStreamReader& reader, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + const SpecBase& dataspec, + const std::pair& rp); + +template bool ReadCMDLToBlender, DNAMP3::MaterialSet, + std::pair, DNACMDL::SurfaceHeader_3, 4> +(HECL::BlenderConnection& conn, + Athena::io::IStreamReader& reader, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + const SpecBase& dataspec, + const std::pair& rp); + +template bool ReadCMDLToBlender, DNAMP3::MaterialSet, + std::pair, DNACMDL::SurfaceHeader_3, 5> +(HECL::BlenderConnection& conn, + Athena::io::IStreamReader& reader, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + const SpecBase& dataspec, + const std::pair& rp); + +template +void NameCMDL(Athena::io::IStreamReader& reader, + PAKRouter& pakRouter, + typename PAKRouter::EntryType& entry, + const SpecBase& dataspec) +{ + Header head; + head.read(reader); + std::string bestName = HECL::Format("CMDL_%s", entry.id.toString().c_str()); + + /* Pre-read pass to determine maximum used vert indices */ + atUint32 matSecCount = 0; + if (head.matSetCount) + matSecCount = MaterialSet::OneSection() ? 1 : head.matSetCount; + atUint32 lastDlSec = head.secCount; + for (size_t s=0 ; s, DNAMP1::MaterialSet> +(Athena::io::IStreamReader& reader, + PAKRouter& pakRouter, + typename PAKRouter::EntryType& entry, + const SpecBase& dataspec); + +static void WriteDLVal(Athena::io::FileWriter& writer, GX::AttrType type, atUint32 val) +{ + switch (type) + { + case GX::DIRECT: + case GX::INDEX8: + writer.writeUByte(atUint8(val)); + break; + case GX::INDEX16: + writer.writeUint16Big(atUint16(val)); + break; + default: break; + } +} + +template +bool WriteCMDL(const HECL::ProjectPath& outPath, const HECL::ProjectPath& inPath, const Mesh& mesh) +{ + Header head; + head.magic = 0xDEADBABE; + head.version = Version; + head.aabbMin = mesh.aabbMin.val; + head.aabbMax = mesh.aabbMax.val; + head.matSetCount = mesh.materialSets.size(); + head.secCount = head.matSetCount + 5 + mesh.surfaces.size(); + head.secSizes.reserve(head.secCount); + + /* Lengths of padding to insert while writing */ + std::vector paddingSizes; + paddingSizes.reserve(head.secCount); + + /* Build material sets */ + std::vector matSets; + matSets.reserve(mesh.materialSets.size()); + { + HECL::Frontend::Frontend FE; + for (const std::vector& mset : mesh.materialSets) + { + matSets.emplace_back(); + MaterialSet& targetMSet = matSets.back(); + std::vector texPaths; + std::vector setBackends; + setBackends.reserve(mset.size()); + + size_t endOff = 0; + atUint32 nextGroupIdx = 0; + for (const Mesh::Material& mat : mset) + { + std::string diagName = HECL::Format("%s:%s", inPath.getLastComponentUTF8(), mat.name.c_str()); + HECL::Frontend::IR matIR = FE.compileSource(mat.source, diagName); + setBackends.emplace_back(); + HECL::Backend::GX& matGX = setBackends.back(); + matGX.reset(matIR, FE.getDiagnostics()); + + atUint32 groupIdx = -1; + if (matSets.size() == 1) + { + for (size_t i=0 ; i surfEndOffs; + surfEndOffs.reserve(mesh.surfaces.size()); + secSz = mesh.surfaces.size() * 4 + 4; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + + /* Surfaces */ + size_t endOff = 0; + for (const Mesh::Surface& surf : mesh.surfaces) + { + size_t vertSz = matSets.at(0).materials.at(surf.materialIdx).getVAFlags().vertDLSize(); + if (surf.verts.size() > 65536) + LogDNACommon.report(LogVisor::FatalError, "GX DisplayList overflow"); + size_t secSz = 67 + surf.verts.size() * vertSz; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + endOff += secSz32; + surfEndOffs.push_back(endOff); + } + + /* Write sections */ + Athena::io::FileWriter writer(outPath.getAbsolutePath()); + head.write(writer); + std::vector::const_iterator padIt = paddingSizes.cbegin(); + + /* Material Sets */ + for (const MaterialSet& mset : matSets) + { + mset.write(writer); + writer.fill(atUint8(0), *padIt); + ++padIt; + } + + /* Vertex Positions */ + for (const atVec3f& pos : mesh.pos) + writer.writeVec3fBig(pos); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Vertex Normals */ + for (const atVec3f& norm : mesh.norm) + writer.writeVec3fBig(norm); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Vertex Colors */ + for (const atVec3f& col : mesh.color) + { + GX::Color qCol(col); + qCol.write(writer); + } + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* UV coords */ + for (const atVec2f& uv : mesh.uv) + writer.writeVec2fBig(uv); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Surface index */ + writer.writeUint32Big(surfEndOffs.size()); + for (size_t off : surfEndOffs) + writer.writeUint32Big(off); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Surfaces */ + GX::Primitive prim; + if (mesh.topology == HECL::HMDLTopology::Triangles) + prim = GX::TRIANGLES; + else if (mesh.topology == HECL::HMDLTopology::TriStrips) + prim = GX::TRIANGLESTRIP; + else + LogDNACommon.report(LogVisor::FatalError, "unrecognized mesh output mode"); + for (const Mesh::Surface& surf : mesh.surfaces) + { + const typename MaterialSet::Material::VAFlags& vaFlags = + matSets.at(0).materials.at(surf.materialIdx).getVAFlags(); + size_t vertSz = vaFlags.vertDLSize(); + + SurfaceHeader header; + header.centroid = surf.centroid; + header.matIdx = surf.materialIdx; + header.dlSize = 3 + surf.verts.size() * vertSz; + header.reflectionNormal = surf.reflectionNormal; + header.write(writer); + + writer.writeUByte(prim); + writer.writeUint16Big(surf.verts.size()); + + for (const Mesh::Surface::Vert& vert : surf.verts) + { + atUint32 skinIdx = vert.iBankSkin * 3; + WriteDLVal(writer, vaFlags.pnMatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex0MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex1MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex2MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex3MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex4MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex5MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex6MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.position(), vert.iPos); + WriteDLVal(writer, vaFlags.normal(), vert.iNorm); + WriteDLVal(writer, vaFlags.color0(), vert.iColor[0]); + WriteDLVal(writer, vaFlags.color1(), vert.iColor[1]); + WriteDLVal(writer, vaFlags.tex0(), vert.iUv[0]); + WriteDLVal(writer, vaFlags.tex1(), vert.iUv[1]); + WriteDLVal(writer, vaFlags.tex2(), vert.iUv[2]); + WriteDLVal(writer, vaFlags.tex3(), vert.iUv[3]); + WriteDLVal(writer, vaFlags.tex4(), vert.iUv[4]); + WriteDLVal(writer, vaFlags.tex5(), vert.iUv[5]); + WriteDLVal(writer, vaFlags.tex6(), vert.iUv[6]); + } + + writer.fill(atUint8(0), *padIt); + ++padIt; + } + + writer.close(); + return true; +} + +template bool WriteCMDL +(const HECL::ProjectPath& outPath, const HECL::ProjectPath& inPath, const Mesh& mesh); + +template +bool WriteHMDLCMDL(const HECL::ProjectPath& outPath, const HECL::ProjectPath& inPath, const Mesh& mesh) +{ + Header head; + head.magic = 0xDEADBABE; + head.version = 0x10000 | Version; + head.aabbMin = mesh.aabbMin.val; + head.aabbMax = mesh.aabbMax.val; + head.matSetCount = mesh.materialSets.size(); + head.secCount = head.matSetCount + 4 + mesh.surfaces.size(); + head.secSizes.reserve(head.secCount); + + /* Lengths of padding to insert while writing */ + std::vector paddingSizes; + paddingSizes.reserve(head.secCount); + + /* Build material sets */ + std::vector matSets; + matSets.reserve(mesh.materialSets.size()); + { + HECL::Frontend::Frontend FE; + for (const std::vector& mset : mesh.materialSets) + { + matSets.emplace_back(); + MaterialSet& targetMSet = matSets.back(); + std::vector texPaths; + texPaths.reserve(mset.size()*4); + for (const Mesh::Material& mat : mset) + { + for (const HECL::ProjectPath& path : mat.texs) + { + bool found = false; + for (const HECL::ProjectPath& ePath : texPaths) + { + if (path == ePath) + { + found = true; + break; + } + } + if (!found) + texPaths.push_back(path); + } + } + + size_t endOff = 0; + for (const Mesh::Material& mat : mset) + { + std::string diagName = HECL::Format("%s:%s", inPath.getLastComponentUTF8(), mat.name.c_str()); + targetMSet.materials.emplace_back(FE, diagName, mat, mat.iprops, texPaths); + endOff = targetMSet.materials.back().binarySize(endOff); + targetMSet.head.addMaterialEndOff(endOff); + } + + for (const HECL::ProjectPath& path : texPaths) + { + const HECL::SystemString& relPath = path.getRelativePath(); + + /* TODO: incorporate hecl hashes */ + size_t search = relPath.find(_S("TXTR_")); + if (search != HECL::SystemString::npos) + targetMSet.head.addTexture(relPath.c_str() + search + 5); + else + LogDNACommon.report(LogVisor::FatalError, "unable to get hash from path"); + } + + size_t secSz = targetMSet.binarySize(0); + size_t secSz32 = ROUND_UP_32(secSz); + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + } + } + + HECL::HMDLBuffers bufs = mesh.getHMDLBuffers(); + + /* Metadata */ + size_t secSz = bufs.m_meta.binarySize(0); + size_t secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + + /* VBO */ + secSz = bufs.m_vboSz; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + + /* IBO */ + secSz = bufs.m_iboSz; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + + /* Surface index */ + std::vector surfEndOffs; + surfEndOffs.reserve(bufs.m_surfaces.size()); + secSz = bufs.m_surfaces.size() * 4 + 4; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + + /* Surfaces */ + size_t endOff = 0; + for (const HECL::HMDLBuffers::Surface& surf : bufs.m_surfaces) + { + head.secSizes.push_back(64); + paddingSizes.push_back(0); + endOff += 64; + surfEndOffs.push_back(endOff); + } + + /* Write sections */ + Athena::io::FileWriter writer(outPath.getAbsolutePath()); + head.write(writer); + std::vector::const_iterator padIt = paddingSizes.cbegin(); + + /* Material Sets */ + for (const MaterialSet& mset : matSets) + { + mset.write(writer); + writer.fill(atUint8(0), *padIt); + ++padIt; + } + + /* Metadata */ + bufs.m_meta.write(writer); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* VBO */ + writer.writeUBytes(bufs.m_vboData.get(), bufs.m_vboSz); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* IBO */ + writer.writeUBytes(bufs.m_iboData.get(), bufs.m_iboSz); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Surface index */ + writer.writeUint32Big(surfEndOffs.size()); + for (size_t off : surfEndOffs) + writer.writeUint32Big(off); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Surfaces */ + for (const HECL::HMDLBuffers::Surface& surf : bufs.m_surfaces) + { + const Mesh::Surface& osurf = surf.m_origSurf; + + SurfaceHeader header; + header.centroid = osurf.centroid; + header.matIdx = osurf.materialIdx; + header.reflectionNormal = osurf.reflectionNormal; + header.unk1 = surf.m_start; + header.unk2 = surf.m_count; + header.write(writer); + + writer.fill(atUint8(0), *padIt); + ++padIt; + } + + /* Ensure final surface's alignment writes zeros */ + writer.seek(-1, Athena::Current); + writer.writeUByte(0); + writer.close(); + return true; +} + } } diff --git a/DataSpec/DNACommon/CMDL.hpp b/DataSpec/DNACommon/CMDL.hpp index ea2061e3d..72d8ee6a4 100644 --- a/DataSpec/DNACommon/CMDL.hpp +++ b/DataSpec/DNACommon/CMDL.hpp @@ -113,402 +113,21 @@ struct VertexAttributes template void GetVertexAttributes(const MaterialSet& matSet, - std::vector& attributesOut) -{ - attributesOut.clear(); - attributesOut.reserve(matSet.materials.size()); - - for (const typename MaterialSet::Material& mat : matSet.materials) - { - const typename MaterialSet::Material::VAFlags& vaFlags = mat.getVAFlags(); - attributesOut.emplace_back(); - VertexAttributes& va = attributesOut.back(); - - va.pos = vaFlags.position(); - va.norm = vaFlags.normal(); - va.color0 = vaFlags.color0(); - va.color1 = vaFlags.color1(); - - if ((va.uvs[0] = vaFlags.tex0())) - ++va.uvCount; - if ((va.uvs[1] = vaFlags.tex1())) - ++va.uvCount; - if ((va.uvs[2] = vaFlags.tex2())) - ++va.uvCount; - if ((va.uvs[3] = vaFlags.tex3())) - ++va.uvCount; - if ((va.uvs[4] = vaFlags.tex4())) - ++va.uvCount; - if ((va.uvs[5] = vaFlags.tex5())) - ++va.uvCount; - if ((va.uvs[6] = vaFlags.tex6())) - ++va.uvCount; - - va.pnMtxIdx = vaFlags.pnMatIdx(); - - if ((va.texMtxIdx[0] = vaFlags.tex0MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[1] = vaFlags.tex1MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[2] = vaFlags.tex2MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[3] = vaFlags.tex3MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[4] = vaFlags.tex4MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[5] = vaFlags.tex5MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[6] = vaFlags.tex6MatIdx())) - ++va.texMtxIdxCount; - - va.shortUVs = mat.getFlags().lightmapUVArray(); - } -} + std::vector& attributesOut); template void ReadMaterialSetToBlender_1_2(HECL::BlenderConnection::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, - unsigned setIdx) -{ - /* Texmaps */ - os << "texmap_list = []\n"; - for (const UniqueID32& tex : matSet.head.textureIDs) - { - std::string texName = pakRouter.getBestEntryName(tex); - const NOD::Node* node; - const typename PAKRouter::EntryType* texEntry = pakRouter.lookupEntry(tex, &node); - HECL::ProjectPath txtrPath = pakRouter.getWorking(texEntry); - if (txtrPath.getPathType() == HECL::ProjectPath::Type::None) - { - PAKEntryReadStream rs = texEntry->beginReadStream(*node); - TXTR::Extract(rs, txtrPath); - } - HECL::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex); - HECL::SystemUTF8View resPathView(resPath); - os.format("if '%s' in bpy.data.textures:\n" - " image = bpy.data.images['%s']\n" - " texture = bpy.data.textures[image.name]\n" - "else:\n" - " image = bpy.data.images.load('''//%s''')\n" - " image.name = '%s'\n" - " texture = bpy.data.textures.new(image.name, 'IMAGE')\n" - " texture.image = image\n" - "texmap_list.append(texture)\n" - "\n", texName.c_str(), texName.c_str(), - resPathView.str().c_str(), texName.c_str()); - } - - unsigned m=0; - for (const typename MaterialSet::Material& mat : matSet.materials) - { - MaterialSet::ConstructMaterial(os, mat, setIdx, m++); - os << "materials.append(new_material)\n"; - } -} + unsigned setIdx); template void ReadMaterialSetToBlender_3(HECL::BlenderConnection::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, - unsigned setIdx) -{ - unsigned m=0; - for (const typename MaterialSet::Material& mat : matSet.materials) - { - MaterialSet::ConstructMaterial(os, pakRouter, entry, mat, setIdx, m++); - os << "materials.append(new_material)\n"; - } -} - -class DLReader -{ -public: - /* Class used for splitting verts with shared positions but different skinning matrices */ - class ExtraVertTracker - { - std::map>> m_extraVerts; - atUint16 m_maxBasePos = 0; - atUint16 m_nextOverPos = 1; - public: - atInt16 addPosSkinPair(atUint16 pos, atInt16 skin) - { - m_maxBasePos = std::max(m_maxBasePos, pos); - auto search = m_extraVerts.find(pos); - if (search == m_extraVerts.end()) - { - m_extraVerts[pos] = {std::make_pair(skin, 0)}; - return skin; - } - std::vector>& vertTrack = search->second; - for (const std::pair& s : vertTrack) - if (s.first == skin) - return vertTrack.front().first; - vertTrack.push_back(std::make_pair(skin, m_nextOverPos++)); - return vertTrack.front().first; - } - - template - void sendAdditionalVertsToBlender(HECL::BlenderConnection::PyOutStream& os, - const RigPair& rp) const - { - atUint32 nextVert = 1; - while (nextVert < m_nextOverPos) - { - for (const std::pair>>& ev : m_extraVerts) - { - for (const std::pair& se : ev.second) - { - if (se.second == nextVert) - { - os.format("bm.verts.ensure_lookup_table()\n" - "orig_vert = bm.verts[%u]\n" - "vert = bm.verts.new(orig_vert.co)\n", - ev.first); - rp.first->weightVertex(os, *rp.second, se.first); - ++nextVert; - } - } - } - } - } - - atUint16 lookupVertIdx(atUint16 pos, atInt16 skin) const - { - auto search = m_extraVerts.find(pos); - if (search == m_extraVerts.end()) - return -1; - const std::vector>& vertTrack = search->second; - if (vertTrack.front().first == skin) - return pos; - for (auto it=vertTrack.begin()+1 ; it!=vertTrack.end() ; ++it) - if (it->first == skin) - return m_maxBasePos + it->second; - return -1; - } - }; - -private: - const VertexAttributes& m_va; - std::unique_ptr m_dl; - size_t m_dlSize; - ExtraVertTracker& m_evt; - const atInt16* m_bankIn; - atUint8* m_cur; - atUint16 readVal(GX::AttrType type) - { - atUint16 retval = 0; - switch (type) - { - case GX::DIRECT: - case GX::INDEX8: - if ((m_cur - m_dl.get()) >= intptr_t(m_dlSize)) - return 0; - retval = *m_cur; - ++m_cur; - break; - case GX::INDEX16: - if ((m_cur - m_dl.get() + 1) >= intptr_t(m_dlSize)) - return 0; - retval = HECL::SBig(*(atUint16*)m_cur); - m_cur += 2; - break; - default: break; - } - return retval; - } -public: - DLReader(const VertexAttributes& va, std::unique_ptr&& dl, - size_t dlSize, ExtraVertTracker& evt, const atInt16* bankIn=nullptr) - : m_va(va), m_dl(std::move(dl)), m_dlSize(dlSize), m_evt(evt), m_bankIn(bankIn) - { - m_cur = m_dl.get(); - } - - operator bool() - { - return ((m_cur - m_dl.get()) < intptr_t(m_dlSize)) && *m_cur; - } - - GX::Primitive readPrimitive() - { - return GX::Primitive(*m_cur++ & 0xf8); - } - - GX::Primitive readPrimitiveAndVat(unsigned& vatOut) - { - atUint8 val = *m_cur++; - vatOut = val & 0x7; - return GX::Primitive(val & 0xf8); - } - - atUint16 readVertCount() - { - atUint16 retval = HECL::SBig(*(atUint16*)m_cur); - m_cur += 2; - return retval; - } - - struct DLPrimVert - { - atUint16 pos = 0; - atUint16 norm = 0; - atUint16 color[2] = {0}; - atUint16 uvs[7] = {0}; - atUint8 pnMtxIdx = 0; - atUint8 texMtxIdx[7] = {0}; - }; - - DLPrimVert readVert(bool peek=false) - { - atUint8* bakCur = m_cur; - DLPrimVert retval; - retval.pnMtxIdx = readVal(m_va.pnMtxIdx); - retval.texMtxIdx[0] = readVal(m_va.texMtxIdx[0]); - retval.texMtxIdx[1] = readVal(m_va.texMtxIdx[1]); - retval.texMtxIdx[2] = readVal(m_va.texMtxIdx[2]); - retval.texMtxIdx[3] = readVal(m_va.texMtxIdx[3]); - retval.texMtxIdx[4] = readVal(m_va.texMtxIdx[4]); - retval.texMtxIdx[5] = readVal(m_va.texMtxIdx[5]); - retval.texMtxIdx[6] = readVal(m_va.texMtxIdx[6]); - if (m_bankIn) - { - atUint16 posIdx = readVal(m_va.pos); - atUint8 mtxIdx = retval.pnMtxIdx / 3; - atInt16 skinIdx = -1; - if (mtxIdx < 10) - skinIdx = m_bankIn[mtxIdx]; - retval.pos = m_evt.lookupVertIdx(posIdx, skinIdx); - } - else - retval.pos = readVal(m_va.pos); - retval.norm = readVal(m_va.norm); - retval.color[0] = readVal(m_va.color0); - retval.color[1] = readVal(m_va.color1); - retval.uvs[0] = readVal(m_va.uvs[0]); - retval.uvs[1] = readVal(m_va.uvs[1]); - retval.uvs[2] = readVal(m_va.uvs[2]); - retval.uvs[3] = readVal(m_va.uvs[3]); - retval.uvs[4] = readVal(m_va.uvs[4]); - retval.uvs[5] = readVal(m_va.uvs[5]); - retval.uvs[6] = readVal(m_va.uvs[6]); - if (peek) - m_cur = bakCur; - return retval; - } - - void preReadMaxIdxs(DLPrimVert& out) - { - atUint8* bakCur = m_cur; - while (*this) - { - readPrimitive(); - atUint16 vc = readVertCount(); - for (atUint16 v=0 ; v& skinOut) - { - atUint8* bakCur = m_cur; - while (*this) - { - readPrimitive(); - atUint16 vc = readVertCount(); - for (atUint16 v=0 ; v skinIndices; - DLReader::ExtraVertTracker extraTracker; - for (size_t s=0 ; sgetMatrixBank(sHead.skinMatrixBankIdx()); - - /* Do max index pre-read */ - atUint32 realDlSize = secSizes[s] - (reader.position() - secStart); - DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), - realDlSize, extraTracker, bankIn); - if (SurfaceHeader::UseMatrixSkinning() && rp.first) - dl.preReadMaxIdxs(maxIdxs, skinIndices); - else - dl.preReadMaxIdxs(maxIdxs); - - } - } - } - - if (s < secCount - 1) - reader.seek(secStart + secSizes[s], Athena::Begin); - } - - reader.seek(afterHeaderPos, Athena::Begin); - - visitedDLOffsets = false; - unsigned createdUVLayers = 0; - unsigned surfIdx = 0; - - for (size_t s=0 ; sweightVertex(os, *rp.second, skinIndices[i]); - else if (!SurfaceHeader::UseMatrixSkinning()) - rp.first->weightVertex(os, *rp.second, i); - } - } - if (rp.first && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) - extraTracker.sendAdditionalVertsToBlender(os, rp); - break; - } - case 1: - { - /* Normals */ - os << "norm_list = []\n"; - if (shortNormals) - { - size_t normCount = secSizes[s] / 6; - for (size_t i=0 ; igetMatrixBank(sHead.skinMatrixBankIdx()); - - os.format("materials[%u].pass_index = %u\n", sHead.matIdx, surfIdx++); - if (matUVCount > createdUVLayers) - { - for (unsigned l=createdUVLayers ; l= vertCount - 3); - - /* Advance one prim vert */ - primVerts[c%3] = dl.readVert(peek); - ++c; - } - } - else if (ptype == GX::TRIANGLES) - { - for (int v=0 ; v= vertCount) - break; - - /* Advance 3 Prim Verts */ - for (int pv=0 ; pv<3 ; ++pv) - primVerts[pv] = dl.readVert(); - } - } - else if (ptype == GX::TRIANGLEFAN) - { - ++c; - for (int v=0 ; v= vertCount) - break; - - /* Advance one prim vert */ - primVerts[(c+2)%3] = dl.readVert(); - ++c; - } - } - os << "\n"; - } - } - } - } - - if (s < secCount - 1) - reader.seek(secStart + secSizes[s], Athena::Begin); - } - - /* Finish Mesh */ - FinishBlenderMesh(os, matSetCount, meshIdx); - - if (rp.first) - rp.second->sendVertexGroupsToBlender(os); - - return lastDlSec; -} + atUint32 surfaceCount=0); template bool ReadCMDLToBlender(HECL::BlenderConnection& conn, @@ -1004,513 +155,19 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn, PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec, - const RigPair& rp) -{ - Header head; - head.read(reader); - - if (head.magic != 0xDEADBABE) - { - LogDNACommon.report(LogVisor::Error, "invalid CMDL magic"); - return false; - } - - if (head.version != Version) - { - LogDNACommon.report(LogVisor::Error, "invalid CMDL version"); - return false; - } - - /* Open Py Stream and read sections */ - HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true); - os.format("import bpy\n" - "import bmesh\n" - "\n" - "bpy.context.scene.name = '%s'\n" - "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n", - pakRouter.getBestEntryName(entry).c_str()); - InitGeomBlenderContext(os, dataspec.getMasterShaderPath()); - MaterialSet::RegisterMaterialProps(os); - - os << "# Materials\n" - "materials = []\n" - "\n"; - - std::vector vertAttribs; - ReadGeomSectionsToBlender - (os, reader, pakRouter, entry, rp, head.flags.shortNormals(), - head.flags.shortUVs(), vertAttribs, -1, - head.secCount, head.matSetCount, head.secSizes.data()); - - return true; -} + const RigPair& rp); template void NameCMDL(Athena::io::IStreamReader& reader, PAKRouter& pakRouter, typename PAKRouter::EntryType& entry, - const SpecBase& dataspec) -{ - Header head; - head.read(reader); - std::string bestName = HECL::Format("CMDL_%s", entry.id.toString().c_str()); - - /* Pre-read pass to determine maximum used vert indices */ - atUint32 matSecCount = 0; - if (head.matSetCount) - matSecCount = MaterialSet::OneSection() ? 1 : head.matSetCount; - atUint32 lastDlSec = head.secCount; - for (size_t s=0 ; s -bool WriteCMDL(const HECL::ProjectPath& outPath, const HECL::ProjectPath& inPath, const Mesh& mesh) -{ - Header head; - head.magic = 0xDEADBABE; - head.version = Version; - head.aabbMin = mesh.aabbMin.val; - head.aabbMax = mesh.aabbMax.val; - head.matSetCount = mesh.materialSets.size(); - head.secCount = head.matSetCount + 5 + mesh.surfaces.size(); - head.secSizes.reserve(head.secCount); - - /* Lengths of padding to insert while writing */ - std::vector paddingSizes; - paddingSizes.reserve(head.secCount); - - /* Build material sets */ - std::vector matSets; - matSets.reserve(mesh.materialSets.size()); - { - HECL::Frontend::Frontend FE; - for (const std::vector& mset : mesh.materialSets) - { - matSets.emplace_back(); - MaterialSet& targetMSet = matSets.back(); - std::vector texPaths; - std::vector setBackends; - setBackends.reserve(mset.size()); - - size_t endOff = 0; - atUint32 nextGroupIdx = 0; - for (const Mesh::Material& mat : mset) - { - std::string diagName = HECL::Format("%s:%s", inPath.getLastComponentUTF8(), mat.name.c_str()); - HECL::Frontend::IR matIR = FE.compileSource(mat.source, diagName); - setBackends.emplace_back(); - HECL::Backend::GX& matGX = setBackends.back(); - matGX.reset(matIR, FE.getDiagnostics()); - - atUint32 groupIdx = -1; - if (matSets.size() == 1) - { - for (size_t i=0 ; i surfEndOffs; - surfEndOffs.reserve(mesh.surfaces.size()); - secSz = mesh.surfaces.size() * 4 + 4; - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); - - /* Surfaces */ - size_t endOff = 0; - for (const Mesh::Surface& surf : mesh.surfaces) - { - size_t vertSz = matSets.at(0).materials.at(surf.materialIdx).getVAFlags().vertDLSize(); - if (surf.verts.size() > 65536) - LogDNACommon.report(LogVisor::FatalError, "GX DisplayList overflow"); - size_t secSz = 67 + surf.verts.size() * vertSz; - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); - endOff += secSz32; - surfEndOffs.push_back(endOff); - } - - /* Write sections */ - Athena::io::FileWriter writer(outPath.getAbsolutePath()); - head.write(writer); - std::vector::const_iterator padIt = paddingSizes.cbegin(); - - /* Material Sets */ - for (const MaterialSet& mset : matSets) - { - mset.write(writer); - writer.fill(atUint8(0), *padIt); - ++padIt; - } - - /* Vertex Positions */ - for (const atVec3f& pos : mesh.pos) - writer.writeVec3fBig(pos); - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* Vertex Normals */ - for (const atVec3f& norm : mesh.norm) - writer.writeVec3fBig(norm); - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* Vertex Colors */ - for (const atVec3f& col : mesh.color) - { - GX::Color qCol(col); - qCol.write(writer); - } - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* UV coords */ - for (const atVec2f& uv : mesh.uv) - writer.writeVec2fBig(uv); - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* Surface index */ - writer.writeUint32Big(surfEndOffs.size()); - for (size_t off : surfEndOffs) - writer.writeUint32Big(off); - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* Surfaces */ - GX::Primitive prim; - if (mesh.topology == HECL::HMDLTopology::Triangles) - prim = GX::TRIANGLES; - else if (mesh.topology == HECL::HMDLTopology::TriStrips) - prim = GX::TRIANGLESTRIP; - else - LogDNACommon.report(LogVisor::FatalError, "unrecognized mesh output mode"); - for (const Mesh::Surface& surf : mesh.surfaces) - { - const typename MaterialSet::Material::VAFlags& vaFlags = - matSets.at(0).materials.at(surf.materialIdx).getVAFlags(); - size_t vertSz = vaFlags.vertDLSize(); - - SurfaceHeader header; - header.centroid = surf.centroid; - header.matIdx = surf.materialIdx; - header.dlSize = 3 + surf.verts.size() * vertSz; - header.reflectionNormal = surf.reflectionNormal; - header.write(writer); - - writer.writeUByte(prim); - writer.writeUint16Big(surf.verts.size()); - - for (const Mesh::Surface::Vert& vert : surf.verts) - { - atUint32 skinIdx = vert.iBankSkin * 3; - WriteDLVal(writer, vaFlags.pnMatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex0MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex1MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex2MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex3MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex4MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex5MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex6MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.position(), vert.iPos); - WriteDLVal(writer, vaFlags.normal(), vert.iNorm); - WriteDLVal(writer, vaFlags.color0(), vert.iColor[0]); - WriteDLVal(writer, vaFlags.color1(), vert.iColor[1]); - WriteDLVal(writer, vaFlags.tex0(), vert.iUv[0]); - WriteDLVal(writer, vaFlags.tex1(), vert.iUv[1]); - WriteDLVal(writer, vaFlags.tex2(), vert.iUv[2]); - WriteDLVal(writer, vaFlags.tex3(), vert.iUv[3]); - WriteDLVal(writer, vaFlags.tex4(), vert.iUv[4]); - WriteDLVal(writer, vaFlags.tex5(), vert.iUv[5]); - WriteDLVal(writer, vaFlags.tex6(), vert.iUv[6]); - } - - writer.fill(atUint8(0), *padIt); - ++padIt; - } - - writer.close(); - return true; -} +bool WriteCMDL(const HECL::ProjectPath& outPath, const HECL::ProjectPath& inPath, const Mesh& mesh); template -bool WriteHMDLCMDL(const HECL::ProjectPath& outPath, const HECL::ProjectPath& inPath, const Mesh& mesh) -{ - Header head; - head.magic = 0xDEADBABE; - head.version = 0x10000 | Version; - head.aabbMin = mesh.aabbMin.val; - head.aabbMax = mesh.aabbMax.val; - head.matSetCount = mesh.materialSets.size(); - head.secCount = head.matSetCount + 4 + mesh.surfaces.size(); - head.secSizes.reserve(head.secCount); - - /* Lengths of padding to insert while writing */ - std::vector paddingSizes; - paddingSizes.reserve(head.secCount); - - /* Build material sets */ - std::vector matSets; - matSets.reserve(mesh.materialSets.size()); - { - HECL::Frontend::Frontend FE; - for (const std::vector& mset : mesh.materialSets) - { - matSets.emplace_back(); - MaterialSet& targetMSet = matSets.back(); - std::vector texPaths; - texPaths.reserve(mset.size()*4); - for (const Mesh::Material& mat : mset) - { - for (const HECL::ProjectPath& path : mat.texs) - { - bool found = false; - for (const HECL::ProjectPath& ePath : texPaths) - { - if (path == ePath) - { - found = true; - break; - } - } - if (!found) - texPaths.push_back(path); - } - } - - size_t endOff = 0; - for (const Mesh::Material& mat : mset) - { - std::string diagName = HECL::Format("%s:%s", inPath.getLastComponentUTF8(), mat.name.c_str()); - targetMSet.materials.emplace_back(FE, diagName, mat, mat.iprops, texPaths); - endOff = targetMSet.materials.back().binarySize(endOff); - targetMSet.head.addMaterialEndOff(endOff); - } - - for (const HECL::ProjectPath& path : texPaths) - { - const HECL::SystemString& relPath = path.getRelativePath(); - - /* TODO: incorporate hecl hashes */ - size_t search = relPath.find(_S("TXTR_")); - if (search != HECL::SystemString::npos) - targetMSet.head.addTexture(relPath.c_str() + search + 5); - else - LogDNACommon.report(LogVisor::FatalError, "unable to get hash from path"); - } - - size_t secSz = targetMSet.binarySize(0); - size_t secSz32 = ROUND_UP_32(secSz); - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); - } - } - - HECL::HMDLBuffers bufs = mesh.getHMDLBuffers(); - - /* Metadata */ - size_t secSz = bufs.m_meta.binarySize(0); - size_t secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); - - /* VBO */ - secSz = bufs.m_vboSz; - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); - - /* IBO */ - secSz = bufs.m_iboSz; - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); - - /* Surface index */ - std::vector surfEndOffs; - surfEndOffs.reserve(bufs.m_surfaces.size()); - secSz = bufs.m_surfaces.size() * 4 + 4; - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); - - /* Surfaces */ - size_t endOff = 0; - for (const HECL::HMDLBuffers::Surface& surf : bufs.m_surfaces) - { - head.secSizes.push_back(64); - paddingSizes.push_back(0); - endOff += 64; - surfEndOffs.push_back(endOff); - } - - /* Write sections */ - Athena::io::FileWriter writer(outPath.getAbsolutePath()); - head.write(writer); - std::vector::const_iterator padIt = paddingSizes.cbegin(); - - /* Material Sets */ - for (const MaterialSet& mset : matSets) - { - mset.write(writer); - writer.fill(atUint8(0), *padIt); - ++padIt; - } - - /* Metadata */ - bufs.m_meta.write(writer); - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* VBO */ - writer.writeUBytes(bufs.m_vboData.get(), bufs.m_vboSz); - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* IBO */ - writer.writeUBytes(bufs.m_iboData.get(), bufs.m_iboSz); - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* Surface index */ - writer.writeUint32Big(surfEndOffs.size()); - for (size_t off : surfEndOffs) - writer.writeUint32Big(off); - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* Surfaces */ - for (const HECL::HMDLBuffers::Surface& surf : bufs.m_surfaces) - { - const Mesh::Surface& osurf = surf.m_origSurf; - - SurfaceHeader header; - header.centroid = osurf.centroid; - header.matIdx = osurf.materialIdx; - header.reflectionNormal = osurf.reflectionNormal; - header.unk1 = surf.m_start; - header.unk2 = surf.m_count; - header.write(writer); - - writer.fill(atUint8(0), *padIt); - ++padIt; - } - - /* Ensure final surface's alignment writes zeros */ - writer.seek(-1, Athena::Current); - writer.writeUByte(0); - writer.close(); - return true; -} +bool WriteHMDLCMDL(const HECL::ProjectPath& outPath, const HECL::ProjectPath& inPath, const Mesh& mesh); } } diff --git a/DataSpec/DNACommon/CMakeLists.txt b/DataSpec/DNACommon/CMakeLists.txt index 6ca52ff02..ab0c7f022 100644 --- a/DataSpec/DNACommon/CMakeLists.txt +++ b/DataSpec/DNACommon/CMakeLists.txt @@ -7,15 +7,16 @@ make_dnalist(liblist add_library(DNACommon DNACommon.hpp DNACommon.cpp ${liblist} - PAK.hpp + PAK.hpp PAK.cpp GX.hpp - MLVL.hpp + MLVL.hpp MLVL.cpp CMDL.cpp + MAPA.cpp STRG.hpp STRG.cpp TXTR.hpp TXTR.cpp ANCS.hpp ANIM.hpp ANIM.cpp - PART.hpp + PART.hpp PART.cpp SWHC.hpp ELSC.hpp ParticleCommon.cpp diff --git a/DataSpec/DNACommon/DNACommon.hpp b/DataSpec/DNACommon/DNACommon.hpp index a0252c4e6..e2ec519c7 100644 --- a/DataSpec/DNACommon/DNACommon.hpp +++ b/DataSpec/DNACommon/DNACommon.hpp @@ -59,17 +59,20 @@ public: HECL::Database::Project& getProject() const {return m_dataSpec.getProject();} virtual HECL::ProjectPath getWorking(const UniqueID32&) const { - LogDNACommon.report(LogVisor::FatalError, "PAKRouter IDType mismatch; expected UniqueID32 specialization"); + LogDNACommon.report(LogVisor::FatalError, + "PAKRouter IDType mismatch; expected UniqueID32 specialization"); return HECL::ProjectPath(); } virtual HECL::ProjectPath getWorking(const UniqueID64&) const { - LogDNACommon.report(LogVisor::FatalError, "PAKRouter IDType mismatch; expected UniqueID64 specialization"); + LogDNACommon.report(LogVisor::FatalError, + "PAKRouter IDType mismatch; expected UniqueID64 specialization"); return HECL::ProjectPath(); } virtual HECL::ProjectPath getWorking(const UniqueID128&) const { - LogDNACommon.report(LogVisor::FatalError, "PAKRouter IDType mismatch; expected UniqueID128 specialization"); + LogDNACommon.report(LogVisor::FatalError, + "PAKRouter IDType mismatch; expected UniqueID128 specialization"); return HECL::ProjectPath(); } }; diff --git a/DataSpec/DNACommon/MAPA.cpp b/DataSpec/DNACommon/MAPA.cpp new file mode 100644 index 000000000..0da1e25b7 --- /dev/null +++ b/DataSpec/DNACommon/MAPA.cpp @@ -0,0 +1,321 @@ +#include "MAPA.hpp" +#include "../DNAMP1/DNAMP1.hpp" +#include "../DNAMP2/DNAMP2.hpp" +#include "../DNAMP3/DNAMP3.hpp" + +namespace DataSpec +{ +namespace DNAMAPA +{ + +void MAPA::read(Athena::io::IStreamReader& __dna_reader) +{ + /* magic */ + magic = __dna_reader.readUint32Big(); + if (magic != 0xDEADD00D) + { + LogDNACommon.report(LogVisor::Error, "invalid MAPA magic"); + return; + } + /* version */ + version = __dna_reader.readUint32Big(); + if (version == 2) + header.reset(new HeaderMP1); + else if (version == 3) + header.reset(new HeaderMP2); + else if (version == 5) + header.reset(new HeaderMP3); + else + { + LogDNACommon.report(LogVisor::Error, "invalid MAPA version"); + return; + } + + header->read(__dna_reader); + + for (atUint32 i = 0; i < header->mappableObjectCount(); i++) + { + std::unique_ptr mo = nullptr; + if (version != 5) + mo.reset(new MappableObjectMP1_2); + else + mo.reset(new MappableObjectMP3); + mo->read(__dna_reader); + mappableObjects.push_back(std::move(mo)); + } + + /* vertices */ + __dna_reader.enumerateBig(vertices, header->vertexCount()); + /* surfaceHeaders */ + __dna_reader.enumerate(surfaceHeaders, header->surfaceCount()); + /* surfaces */ + __dna_reader.enumerate(surfaces, header->surfaceCount()); +} + +void MAPA::write(Athena::io::IStreamWriter& __dna_writer) const +{ + /* magic */ + __dna_writer.writeUint32Big(magic); + /* version */ + __dna_writer.writeUint32Big(version); + header->write(__dna_writer); + + /* mappableObjects */ + for (const std::unique_ptr& mo : mappableObjects) + mo->write(__dna_writer); + /* vertices */ + __dna_writer.enumerateBig(vertices); + /* surfaceHeaders */ + __dna_writer.enumerate(surfaceHeaders); + /* surfaces */ + __dna_writer.enumerate(surfaces); +} + +size_t MAPA::binarySize(size_t __isz) const +{ + __isz = header->binarySize(__isz); + + for (const std::unique_ptr& mo : mappableObjects) + __isz = mo->binarySize(__isz); + + __isz += vertices.size() * 12; + __isz = __EnumerateSize(__isz, surfaceHeaders); + __isz = __EnumerateSize(__isz, surfaces); + return __isz + 8; +} + +template +bool ReadMAPAToBlender(HECL::BlenderConnection& conn, + const MAPA& mapa, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + bool force) +{ + /* Rename MAPA for consistency */ + HECL::ProjectPath mapaPath(outPath.getParentPath(), _S("!map.blend")); + if (!force && mapaPath.getPathType() == HECL::ProjectPath::Type::File) + return true; + + if (!conn.createBlend(mapaPath, HECL::BlenderConnection::BlendType::MapArea)) + return false; + HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true); + + os << "import bpy, bmesh\n" + "from mathutils import Matrix\n" + "\n" + "bpy.types.Object.retro_mappable_type = bpy.props.IntProperty(name='Retro: MAPA object type', default=-1)\n" + "bpy.types.Object.retro_mappable_unk = bpy.props.IntProperty(name='Retro: MAPA object unk')\n" + "bpy.types.Object.retro_mappable_sclyid = bpy.props.StringProperty(name='Retro: MAPA object SCLY ID')\n" + "\n" + "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n" + "\n" + "def add_triangle(bm, verts):\n" + " verts = [bm.verts[vi] for vi in verts]\n" + " face = bm.faces.get(verts)\n" + " if face:\n" + " face = face.copy()\n" + " bm.verts.ensure_lookup_table()\n" + " face.normal_flip()\n" + " else:\n" + " bm.faces.new(verts)\n" + "\n" + "def add_border(bm, verts):\n" + " verts = [bm.verts[vi] for vi in verts]\n" + " edge = bm.edges.get(verts)\n" + " if not edge:\n" + " edge = bm.edges.new(verts)\n" + " edge.seam = True\n" + "\n"; + + os.format("bpy.context.scene.name = 'MAPA_%s'\n", + entry.id.toString().c_str()); + + /* Add empties representing MappableObjects */ + int moIdx = 0; + for (const std::unique_ptr& mo : mapa.mappableObjects) + { + const MAPA::MappableObjectMP1_2* moMP12 = dynamic_cast(mo.get()); + if (moMP12) + { + os.format("obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" + "bpy.context.scene.objects.link(obj)\n" + "obj.retro_mappable_type = %d\n" + "obj.retro_mappable_unk = %d\n" + "obj.retro_mappable_sclyid = '%08X'\n" + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "obj.rotation_mode = 'QUATERNION'\n" + "obj.location = mtxd[0]\n" + "obj.rotation_quaternion = mtxd[1]\n" + "obj.scale = mtxd[2]\n", + moIdx, moMP12->type, moMP12->unknown1, moMP12->sclyId, + moMP12->transformMtx[0].vec[0], moMP12->transformMtx[0].vec[1], moMP12->transformMtx[0].vec[2], moMP12->transformMtx[0].vec[3], + moMP12->transformMtx[1].vec[0], moMP12->transformMtx[1].vec[1], moMP12->transformMtx[1].vec[2], moMP12->transformMtx[1].vec[3], + moMP12->transformMtx[2].vec[0], moMP12->transformMtx[2].vec[1], moMP12->transformMtx[2].vec[2], moMP12->transformMtx[2].vec[3]); + ++moIdx; + continue; + } + const MAPA::MappableObjectMP3* moMP3 = dynamic_cast(mo.get()); + if (moMP3) + { + os.format("obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" + "bpy.context.scene.objects.link(obj)\n" + "obj.retro_mappable_type = %d\n" + "obj.retro_mappable_unk = %d\n" + "obj.retro_mappable_sclyid = '%08X'\n" + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "obj.rotation_mode = 'QUATERNION'\n" + "obj.location = mtxd[0]\n" + "obj.rotation_quaternion = mtxd[1]\n" + "obj.scale = mtxd[2]\n", + moIdx, moMP3->type, moMP3->unknown1, moMP3->sclyId, + moMP3->transformMtx[0].vec[0], moMP3->transformMtx[0].vec[1], moMP3->transformMtx[0].vec[2], moMP3->transformMtx[0].vec[3], + moMP3->transformMtx[1].vec[0], moMP3->transformMtx[1].vec[1], moMP3->transformMtx[1].vec[2], moMP3->transformMtx[1].vec[3], + moMP3->transformMtx[2].vec[0], moMP3->transformMtx[2].vec[1], moMP3->transformMtx[2].vec[2], moMP3->transformMtx[2].vec[3]); + ++moIdx; + continue; + } + } + + os << "# Begin bmesh\n" + "bm = bmesh.new()\n" + "\n"; + + /* Read in verts */ + for (const atVec3f& vert : mapa.vertices) + os.format("bm.verts.new((%f,%f,%f))\n", + vert.vec[0], vert.vec[1], vert.vec[2]); + os << "bm.verts.ensure_lookup_table()\n"; + + /* Read in surfaces */ + for (const typename MAPA::Surface& surf : mapa.surfaces) + { + for (const typename MAPA::Surface::Primitive& prim : surf.primitives) + { + auto iit = prim.indices.cbegin(); + + /* 3 Prim Verts to start */ + int c = 0; + unsigned int primVerts[3] = + { + *iit++, + *iit++, + *iit++ + }; + + if (GX::Primitive(prim.type) == GX::TRIANGLESTRIP) + { + atUint8 flip = 0; + for (size_t v=0 ; v= prim.indexCount - 3); + + /* Advance one prim vert */ + if (peek) + primVerts[c%3] = *iit; + else + primVerts[c%3] = *iit++; + ++c; + } + } + else if (GX::Primitive(prim.type) == GX::TRIANGLES) + { + for (size_t v=0 ; v= prim.indexCount) + break; + + /* Advance 3 Prim Verts */ + for (int pv=0 ; pv<3 ; ++pv) + primVerts[pv] = *iit++; + } + } + } + + for (const typename MAPA::Surface::Border& border : surf.borders) + { + auto iit = border.indices.cbegin(); + for (size_t i=0 ; i> +(HECL::BlenderConnection& conn, + const MAPA& mapa, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + bool force); + +template bool ReadMAPAToBlender> +(HECL::BlenderConnection& conn, + const MAPA& mapa, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + bool force); + +template bool ReadMAPAToBlender> +(HECL::BlenderConnection& conn, + const MAPA& mapa, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + bool force); + +} +} diff --git a/DataSpec/DNACommon/MAPA.hpp b/DataSpec/DNACommon/MAPA.hpp index 9e751321b..0adc38b85 100644 --- a/DataSpec/DNACommon/MAPA.hpp +++ b/DataSpec/DNACommon/MAPA.hpp @@ -74,81 +74,9 @@ struct MAPA : BigDNA }; - void read(Athena::io::IStreamReader& __dna_reader) - { - /* magic */ - magic = __dna_reader.readUint32Big(); - if (magic != 0xDEADD00D) - { - LogDNACommon.report(LogVisor::Error, "invalid MAPA magic"); - return; - } - /* version */ - version = __dna_reader.readUint32Big(); - if (version == 2) - header.reset(new HeaderMP1); - else if (version == 3) - header.reset(new HeaderMP2); - else if (version == 5) - header.reset(new HeaderMP3); - else - { - LogDNACommon.report(LogVisor::Error, "invalid MAPA version"); - return; - } - - header->read(__dna_reader); - - for (atUint32 i = 0; i < header->mappableObjectCount(); i++) - { - std::unique_ptr mo = nullptr; - if (version != 5) - mo.reset(new MappableObjectMP1_2); - else - mo.reset(new MappableObjectMP3); - mo->read(__dna_reader); - mappableObjects.push_back(std::move(mo)); - } - - /* vertices */ - __dna_reader.enumerateBig(vertices, header->vertexCount()); - /* surfaceHeaders */ - __dna_reader.enumerate(surfaceHeaders, header->surfaceCount()); - /* surfaces */ - __dna_reader.enumerate(surfaces, header->surfaceCount()); - } - - void write(Athena::io::IStreamWriter& __dna_writer) const - { - /* magic */ - __dna_writer.writeUint32Big(magic); - /* version */ - __dna_writer.writeUint32Big(version); - header->write(__dna_writer); - - /* mappableObjects */ - for (const std::unique_ptr& mo : mappableObjects) - mo->write(__dna_writer); - /* vertices */ - __dna_writer.enumerateBig(vertices); - /* surfaceHeaders */ - __dna_writer.enumerate(surfaceHeaders); - /* surfaces */ - __dna_writer.enumerate(surfaces); - } - - size_t binarySize(size_t __isz) const - { - __isz = header->binarySize(__isz); - - for (const std::unique_ptr& mo : mappableObjects) - __isz = mo->binarySize(__isz); - - __isz += vertices.size() * 12; - __isz = __EnumerateSize(__isz, surfaceHeaders); - __isz = __EnumerateSize(__isz, surfaces); - return __isz + 8; - } + void read(Athena::io::IStreamReader& __dna_reader); + void write(Athena::io::IStreamWriter& __dna_writer) const; + size_t binarySize(size_t __isz) const; std::unique_ptr header; @@ -257,208 +185,7 @@ bool ReadMAPAToBlender(HECL::BlenderConnection& conn, const HECL::ProjectPath& outPath, PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, - bool force) -{ - /* Rename MAPA for consistency */ - HECL::ProjectPath mapaPath(outPath.getParentPath(), _S("!map.blend")); - if (!force && mapaPath.getPathType() == HECL::ProjectPath::Type::File) - return true; - - if (!conn.createBlend(mapaPath, HECL::BlenderConnection::BlendType::MapArea)) - return false; - HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true); - - os << "import bpy, bmesh\n" - "from mathutils import Matrix\n" - "\n" - "bpy.types.Object.retro_mappable_type = bpy.props.IntProperty(name='Retro: MAPA object type', default=-1)\n" - "bpy.types.Object.retro_mappable_unk = bpy.props.IntProperty(name='Retro: MAPA object unk')\n" - "bpy.types.Object.retro_mappable_sclyid = bpy.props.StringProperty(name='Retro: MAPA object SCLY ID')\n" - "\n" - "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "\n" - "def add_triangle(bm, verts):\n" - " verts = [bm.verts[vi] for vi in verts]\n" - " face = bm.faces.get(verts)\n" - " if face:\n" - " face = face.copy()\n" - " bm.verts.ensure_lookup_table()\n" - " face.normal_flip()\n" - " else:\n" - " bm.faces.new(verts)\n" - "\n" - "def add_border(bm, verts):\n" - " verts = [bm.verts[vi] for vi in verts]\n" - " edge = bm.edges.get(verts)\n" - " if not edge:\n" - " edge = bm.edges.new(verts)\n" - " edge.seam = True\n" - "\n"; - - os.format("bpy.context.scene.name = 'MAPA_%s'\n", - entry.id.toString().c_str()); - - /* Add empties representing MappableObjects */ - int moIdx = 0; - for (const std::unique_ptr& mo : mapa.mappableObjects) - { - const MAPA::MappableObjectMP1_2* moMP12 = dynamic_cast(mo.get()); - if (moMP12) - { - os.format("obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" - "bpy.context.scene.objects.link(obj)\n" - "obj.retro_mappable_type = %d\n" - "obj.retro_mappable_unk = %d\n" - "obj.retro_mappable_sclyid = '%08X'\n" - "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "obj.rotation_mode = 'QUATERNION'\n" - "obj.location = mtxd[0]\n" - "obj.rotation_quaternion = mtxd[1]\n" - "obj.scale = mtxd[2]\n", - moIdx, moMP12->type, moMP12->unknown1, moMP12->sclyId, - moMP12->transformMtx[0].vec[0], moMP12->transformMtx[0].vec[1], moMP12->transformMtx[0].vec[2], moMP12->transformMtx[0].vec[3], - moMP12->transformMtx[1].vec[0], moMP12->transformMtx[1].vec[1], moMP12->transformMtx[1].vec[2], moMP12->transformMtx[1].vec[3], - moMP12->transformMtx[2].vec[0], moMP12->transformMtx[2].vec[1], moMP12->transformMtx[2].vec[2], moMP12->transformMtx[2].vec[3]); - ++moIdx; - continue; - } - const MAPA::MappableObjectMP3* moMP3 = dynamic_cast(mo.get()); - if (moMP3) - { - os.format("obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" - "bpy.context.scene.objects.link(obj)\n" - "obj.retro_mappable_type = %d\n" - "obj.retro_mappable_unk = %d\n" - "obj.retro_mappable_sclyid = '%08X'\n" - "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "obj.rotation_mode = 'QUATERNION'\n" - "obj.location = mtxd[0]\n" - "obj.rotation_quaternion = mtxd[1]\n" - "obj.scale = mtxd[2]\n", - moIdx, moMP3->type, moMP3->unknown1, moMP3->sclyId, - moMP3->transformMtx[0].vec[0], moMP3->transformMtx[0].vec[1], moMP3->transformMtx[0].vec[2], moMP3->transformMtx[0].vec[3], - moMP3->transformMtx[1].vec[0], moMP3->transformMtx[1].vec[1], moMP3->transformMtx[1].vec[2], moMP3->transformMtx[1].vec[3], - moMP3->transformMtx[2].vec[0], moMP3->transformMtx[2].vec[1], moMP3->transformMtx[2].vec[2], moMP3->transformMtx[2].vec[3]); - ++moIdx; - continue; - } - } - - os << "# Begin bmesh\n" - "bm = bmesh.new()\n" - "\n"; - - /* Read in verts */ - for (const atVec3f& vert : mapa.vertices) - os.format("bm.verts.new((%f,%f,%f))\n", - vert.vec[0], vert.vec[1], vert.vec[2]); - os << "bm.verts.ensure_lookup_table()\n"; - - /* Read in surfaces */ - for (const typename MAPA::Surface& surf : mapa.surfaces) - { - for (const typename MAPA::Surface::Primitive& prim : surf.primitives) - { - auto iit = prim.indices.cbegin(); - - /* 3 Prim Verts to start */ - int c = 0; - unsigned int primVerts[3] = - { - *iit++, - *iit++, - *iit++ - }; - - if (GX::Primitive(prim.type) == GX::TRIANGLESTRIP) - { - atUint8 flip = 0; - for (size_t v=0 ; v= prim.indexCount - 3); - - /* Advance one prim vert */ - if (peek) - primVerts[c%3] = *iit; - else - primVerts[c%3] = *iit++; - ++c; - } - } - else if (GX::Primitive(prim.type) == GX::TRIANGLES) - { - for (size_t v=0 ; v= prim.indexCount) - break; - - /* Advance 3 Prim Verts */ - for (int pv=0 ; pv<3 ; ++pv) - primVerts[pv] = *iit++; - } - } - } - - for (const typename MAPA::Surface::Border& border : surf.borders) - { - auto iit = border.indices.cbegin(); - for (size_t i=0 ; i +bool ReadMLVLToBlender(HECL::BlenderConnection& conn, + const MLVL& mlvl, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + bool force, + std::function fileChanged) +{ + /* Rename MLVL for consistency */ + HECL::ProjectPath mlvlPath(outPath.getParentPath(), _S("!world.blend")); + if (!force && mlvlPath.getPathType() == HECL::ProjectPath::Type::File) + return true; + + /* Create World Blend */ + if (!conn.createBlend(mlvlPath, HECL::BlenderConnection::BlendType::World)) + return false; + HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true); + os.format("import bpy\n" + "import bmesh\n" + "from mathutils import Matrix\n" + "\n" + "bpy.context.scene.name = 'World'\n" + "\n" + "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n"); + + /* Insert area empties */ + int areaIdx = 0; + for (const auto& area : mlvl.areas) + { + const typename PAKRouter::EntryType* mreaEntry = pakRouter.lookupEntry(area.areaMREAId); + HECL::SystemUTF8View areaDirName(*mreaEntry->unique.m_areaName); + + os.AABBToBMesh(area.aabb[0], area.aabb[1]); + os.format("box_mesh = bpy.data.meshes.new('''%s''')\n" + "bm.to_mesh(box_mesh)\n" + "bm.free()\n" + "box = bpy.data.objects.new(box_mesh.name, box_mesh)\n" + "bpy.context.scene.objects.link(box)\n" + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "box.rotation_mode = 'QUATERNION'\n" + "box.location = mtxd[0]\n" + "box.rotation_quaternion = mtxd[1]\n" + "box.scale = mtxd[2]\n", + areaDirName.str().c_str(), + area.transformMtx[0].vec[0], area.transformMtx[0].vec[1], area.transformMtx[0].vec[2], area.transformMtx[0].vec[3], + area.transformMtx[1].vec[0], area.transformMtx[1].vec[1], area.transformMtx[1].vec[2], area.transformMtx[1].vec[3], + area.transformMtx[2].vec[0], area.transformMtx[2].vec[1], area.transformMtx[2].vec[2], area.transformMtx[2].vec[3]); + + /* Insert dock planes */ + int dockIdx = 0; + for (const auto& dock : area.docks) + { + os << "bm = bmesh.new()\n"; + Zeus::CVector3f pvAvg; + for (const atVec3f& pv : dock.planeVerts) + pvAvg += pv; + pvAvg /= dock.planeVerts.size(); + int idx = 0; + for (const atVec3f& pv : dock.planeVerts) + { + Zeus::CVector3f pvRel = Zeus::CVector3f(pv) - pvAvg; + os.format("bm.verts.new((%f,%f,%f))\n" + "bm.verts.ensure_lookup_table()\n", + pvRel[0], pvRel[1], pvRel[2]); + if (idx) + os << "bm.edges.new((bm.verts[-2], bm.verts[-1]))\n"; + ++idx; + } + os << "bm.edges.new((bm.verts[-1], bm.verts[0]))\n"; + os.format("dockMesh = bpy.data.meshes.new('DOCK_%02d_%02d')\n", areaIdx, dockIdx); + os << "dockObj = bpy.data.objects.new(dockMesh.name, dockMesh)\n" + "bpy.context.scene.objects.link(dockObj)\n" + "bm.to_mesh(dockMesh)\n" + "bm.free()\n" + "dockObj.parent = box\n"; + os.format("dockObj.location = (%f,%f,%f)\n", + pvAvg[0], pvAvg[1], pvAvg[2]); + ++dockIdx; + } + ++areaIdx; + } + + os.centerView(); + os.close(); + conn.saveBlend(); + return true; +} + +template bool ReadMLVLToBlender, DNAMP1::MLVL> +(HECL::BlenderConnection& conn, + const DNAMP1::MLVL& mlvl, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + bool force, + std::function fileChanged); + +template bool ReadMLVLToBlender, DNAMP2::MLVL> +(HECL::BlenderConnection& conn, + const DNAMP2::MLVL& mlvl, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + bool force, + std::function fileChanged); + +template bool ReadMLVLToBlender, DNAMP3::MLVL> +(HECL::BlenderConnection& conn, + const DNAMP3::MLVL& mlvl, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + bool force, + std::function fileChanged); + +} +} diff --git a/DataSpec/DNACommon/MLVL.hpp b/DataSpec/DNACommon/MLVL.hpp index af6d5715d..9ffcf2492 100644 --- a/DataSpec/DNACommon/MLVL.hpp +++ b/DataSpec/DNACommon/MLVL.hpp @@ -17,91 +17,7 @@ bool ReadMLVLToBlender(HECL::BlenderConnection& conn, PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force, - std::function fileChanged) -{ - /* Rename MLVL for consistency */ - HECL::ProjectPath mlvlPath(outPath.getParentPath(), _S("!world.blend")); - if (!force && mlvlPath.getPathType() == HECL::ProjectPath::Type::File) - return true; - - /* Create World Blend */ - if (!conn.createBlend(mlvlPath, HECL::BlenderConnection::BlendType::World)) - return false; - HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true); - os.format("import bpy\n" - "import bmesh\n" - "from mathutils import Matrix\n" - "\n" - "bpy.context.scene.name = 'World'\n" - "\n" - "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n"); - - /* Insert area empties */ - int areaIdx = 0; - for (const auto& area : mlvl.areas) - { - const typename PAKRouter::EntryType* mreaEntry = pakRouter.lookupEntry(area.areaMREAId); - HECL::SystemUTF8View areaDirName(*mreaEntry->unique.m_areaName); - - os.AABBToBMesh(area.aabb[0], area.aabb[1]); - os.format("box_mesh = bpy.data.meshes.new('''%s''')\n" - "bm.to_mesh(box_mesh)\n" - "bm.free()\n" - "box = bpy.data.objects.new(box_mesh.name, box_mesh)\n" - "bpy.context.scene.objects.link(box)\n" - "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "box.rotation_mode = 'QUATERNION'\n" - "box.location = mtxd[0]\n" - "box.rotation_quaternion = mtxd[1]\n" - "box.scale = mtxd[2]\n", - areaDirName.str().c_str(), - area.transformMtx[0].vec[0], area.transformMtx[0].vec[1], area.transformMtx[0].vec[2], area.transformMtx[0].vec[3], - area.transformMtx[1].vec[0], area.transformMtx[1].vec[1], area.transformMtx[1].vec[2], area.transformMtx[1].vec[3], - area.transformMtx[2].vec[0], area.transformMtx[2].vec[1], area.transformMtx[2].vec[2], area.transformMtx[2].vec[3]); - - /* Insert dock planes */ - int dockIdx = 0; - for (const auto& dock : area.docks) - { - os << "bm = bmesh.new()\n"; - Zeus::CVector3f pvAvg; - for (const atVec3f& pv : dock.planeVerts) - pvAvg += pv; - pvAvg /= dock.planeVerts.size(); - int idx = 0; - for (const atVec3f& pv : dock.planeVerts) - { - Zeus::CVector3f pvRel = Zeus::CVector3f(pv) - pvAvg; - os.format("bm.verts.new((%f,%f,%f))\n" - "bm.verts.ensure_lookup_table()\n", - pvRel[0], pvRel[1], pvRel[2]); - if (idx) - os << "bm.edges.new((bm.verts[-2], bm.verts[-1]))\n"; - ++idx; - } - os << "bm.edges.new((bm.verts[-1], bm.verts[0]))\n"; - os.format("dockMesh = bpy.data.meshes.new('DOCK_%02d_%02d')\n", areaIdx, dockIdx); - os << "dockObj = bpy.data.objects.new(dockMesh.name, dockMesh)\n" - "bpy.context.scene.objects.link(dockObj)\n" - "bm.to_mesh(dockMesh)\n" - "bm.free()\n" - "dockObj.parent = box\n"; - os.format("dockObj.location = (%f,%f,%f)\n", - pvAvg[0], pvAvg[1], pvAvg[2]); - ++dockIdx; - } - ++areaIdx; - } - - os.centerView(); - os.close(); - conn.saveBlend(); - return true; -} + std::function fileChanged); } } diff --git a/DataSpec/DNACommon/PAK.cpp b/DataSpec/DNACommon/PAK.cpp new file mode 100644 index 000000000..66a2f21c5 --- /dev/null +++ b/DataSpec/DNACommon/PAK.cpp @@ -0,0 +1,588 @@ +#include "PAK.hpp" +#include "../DNAMP1/DNAMP1.hpp" +#include "../DNAMP2/DNAMP2.hpp" +#include "../DNAMP3/DNAMP3.hpp" + +namespace DataSpec +{ + +template +void UniqueResult::checkEntry(const PAKBRIDGE& pakBridge, const typename PAKBRIDGE::PAKType::Entry& entry) +{ + UniqueResult::Type resultType = UniqueResult::Type::NotFound; + bool foundOneLayer = false; + const HECL::SystemString* levelName = nullptr; + typename PAKBRIDGE::PAKType::IDType levelId; + typename PAKBRIDGE::PAKType::IDType areaId; + unsigned layerIdx; + for (const auto& lpair : pakBridge.m_levelDeps) + { + if (entry.id == lpair.first) + { + levelName = &lpair.second.name; + resultType = UniqueResult::Type::Level; + break; + } + + for (const auto& pair : lpair.second.areas) + { + unsigned l=0; + for (const auto& layer : pair.second.layers) + { + if (layer.resources.find(entry.id) != layer.resources.end()) + { + if (foundOneLayer) + { + if (areaId == pair.first) + { + resultType = UniqueResult::Type::Area; + } + else if (levelId == lpair.first) + { + resultType = UniqueResult::Type::Level; + break; + } + else + { + m_type = UniqueResult::Type::Pak; + return; + } + continue; + } + else + resultType = UniqueResult::Type::Layer; + levelName = &lpair.second.name; + levelId = lpair.first; + areaId = pair.first; + layerIdx = l; + foundOneLayer = true; + } + ++l; + } + if (pair.second.resources.find(entry.id) != pair.second.resources.end()) + { + if (foundOneLayer) + { + if (areaId == pair.first) + { + resultType = UniqueResult::Type::Area; + } + else if (levelId == lpair.first) + { + resultType = UniqueResult::Type::Level; + break; + } + else + { + m_type = UniqueResult::Type::Pak; + return; + } + continue; + } + else + resultType = UniqueResult::Type::Area; + levelName = &lpair.second.name; + levelId = lpair.first; + areaId = pair.first; + foundOneLayer = true; + } + } + } + m_type = resultType; + m_levelName = levelName; + if (resultType == UniqueResult::Type::Layer || resultType == UniqueResult::Type::Area) + { + const typename PAKBRIDGE::Level::Area& area = pakBridge.m_levelDeps.at(levelId).areas.at(areaId); + m_areaName = &area.name; + if (resultType == UniqueResult::Type::Layer) + { + const typename PAKBRIDGE::Level::Area::Layer& layer = area.layers[layerIdx]; + m_layerName = &layer.name; + } + } +} + +template void UniqueResult::checkEntry(const DNAMP1::PAKBridge& pakBridge, + const DNAMP1::PAKBridge::PAKType::Entry& entry); +template void UniqueResult::checkEntry(const DNAMP2::PAKBridge& pakBridge, + const DNAMP2::PAKBridge::PAKType::Entry& entry); +template void UniqueResult::checkEntry(const DNAMP3::PAKBridge& pakBridge, + const DNAMP3::PAKBridge::PAKType::Entry& entry); + +HECL::ProjectPath UniqueResult::uniquePath(const HECL::ProjectPath& pakPath) const +{ + if (m_type == Type::Pak) + return pakPath; + + HECL::ProjectPath levelDir; + if (m_levelName) + levelDir.assign(pakPath, *m_levelName); + else + levelDir = pakPath; + levelDir.makeDir(); + + if (m_type == Type::Area) + { + HECL::ProjectPath areaDir(levelDir, *m_areaName); + areaDir.makeDir(); + return areaDir; + } + else if (m_type == Type::Layer) + { + HECL::ProjectPath areaDir(levelDir, *m_areaName); + areaDir.makeDir(); + HECL::ProjectPath layerDir(areaDir, *m_layerName); + layerDir.makeDir(); + return layerDir; + } + + return levelDir; +} + +template +void PAKRouter::build(std::vector& bridges, std::function progress) +{ + m_bridges = &bridges; + m_bridgePaths.clear(); + + m_uniqueEntries.clear(); + m_sharedEntries.clear(); + m_cmdlRigs.clear(); + size_t count = 0; + float bridgesSz = bridges.size(); + + /* Route entries unique/shared per-pak */ + size_t bridgeIdx = 0; + for (BRIDGETYPE& bridge : bridges) + { + const std::string& name = bridge.getName(); + HECL::SystemStringView sysName(name); + + HECL::SystemString::const_iterator extit = sysName.sys_str().end() - 4; + HECL::SystemString baseName(sysName.sys_str().begin(), extit); + + m_bridgePaths.emplace_back(std::make_pair(HECL::ProjectPath(m_gameWorking, baseName), + HECL::ProjectPath(m_gameCooked, baseName))); + + /* Index this PAK */ + bridge.build(); + + /* Add to global entry lookup */ + const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); + for (const auto& entry : pak.m_idMap) + { + if (!pak.m_noShare) + { + auto sSearch = m_sharedEntries.find(entry.first); + if (sSearch != m_sharedEntries.end()) + continue; + auto uSearch = m_uniqueEntries.find(entry.first); + if (uSearch != m_uniqueEntries.end()) + { + m_uniqueEntries.erase(uSearch); + m_sharedEntries[entry.first] = std::make_pair(bridgeIdx, entry.second); + } + else + m_uniqueEntries[entry.first] = std::make_pair(bridgeIdx, entry.second); + } + else + m_uniqueEntries[entry.first] = std::make_pair(bridgeIdx, entry.second); + } + + /* Add RigPairs to global map */ + bridge.addCMDLRigPairs(*this, m_cmdlRigs); + + progress(++count / bridgesSz); + ++bridgeIdx; + } + + /* Add named resources to catalog YAML files */ + for (BRIDGETYPE& bridge : bridges) + { + Athena::io::YAMLDocWriter catalogWriter(nullptr); + + enterPAKBridge(bridge); + const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); + for (const auto& namedEntry : pak.m_nameEntries) + { + catalogWriter.enterSubRecord(namedEntry.name.c_str()); + catalogWriter.writeString(nullptr, getWorking(namedEntry.id).getRelativePathUTF8().c_str()); + catalogWriter.leaveSubRecord(); + } + + /* Write catalog */ + const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].first; + HECL::SystemString catalogPath = HECL::ProjectPath(pakPath, "catalog.yaml").getAbsolutePath(); + FILE* catalog = HECL::Fopen(catalogPath.c_str(), _S("w")); + yaml_emitter_set_output_file(catalogWriter.getEmitter(), catalog); + catalogWriter.finish(); + fclose(catalog); + } +} + +template +void PAKRouter::enterPAKBridge(const BRIDGETYPE& pakBridge) +{ + g_PakRouter = this; + auto pit = m_bridgePaths.begin(); + size_t bridgeIdx = 0; + for (const BRIDGETYPE& bridge : *m_bridges) + { + if (&bridge == &pakBridge) + { + pit->first.makeDir(); + pit->second.makeDir(); + m_pak = &pakBridge.getPAK(); + m_node = &pakBridge.getNode(); + m_curBridgeIdx = bridgeIdx; + return; + } + ++pit; + ++bridgeIdx; + } + LogDNACommon.report(LogVisor::FatalError, + "PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()"); +} + +template +HECL::ProjectPath PAKRouter::getWorking(const EntryType* entry, + const ResExtractor& extractor) const +{ + if (!entry) + return HECL::ProjectPath(); + if (!m_pak) + LogDNACommon.report(LogVisor::FatalError, + "PAKRouter::enterPAKBridge() must be called before PAKRouter::getWorkingPath()"); + if (m_pak->m_noShare) + { + const EntryType* singleSearch = m_pak->lookupEntry(entry->id); + if (singleSearch) + { + const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].first; + pakPath.makeDir(); +#if HECL_UCS2 + HECL::SystemString entName = HECL::UTF8ToWide(getBestEntryName(*entry)); +#else + HECL::SystemString entName = getBestEntryName(*entry); +#endif + if (extractor.fileExts[0] && !extractor.fileExts[1]) + entName += extractor.fileExts[0]; + return HECL::ProjectPath(pakPath, entName); + } + } + + auto uniqueSearch = m_uniqueEntries.find(entry->id); + if (uniqueSearch != m_uniqueEntries.end()) + { + const HECL::ProjectPath& pakPath = m_bridgePaths[uniqueSearch->second.first].first; + pakPath.makeDir(); + HECL::ProjectPath uniquePath = entry->unique.uniquePath(pakPath); +#if HECL_UCS2 + HECL::SystemString entName = HECL::UTF8ToWide(getBestEntryName(*entry)); +#else + HECL::SystemString entName = getBestEntryName(*entry); +#endif + if (extractor.fileExts[0] && !extractor.fileExts[1]) + entName += extractor.fileExts[0]; + return HECL::ProjectPath(uniquePath, entName); + } + + auto sharedSearch = m_sharedEntries.find(entry->id); + if (sharedSearch != m_sharedEntries.end()) + { +#if HECL_UCS2 + HECL::SystemString entBase = HECL::UTF8ToWide(getBestEntryName(*entry)); +#else + HECL::SystemString entBase = getBestEntryName(*entry); +#endif + HECL::SystemString entName = entBase; + if (extractor.fileExts[0] && !extractor.fileExts[1]) + entName += extractor.fileExts[0]; + HECL::ProjectPath sharedPath(m_sharedWorking, entName); + m_sharedWorking.makeDir(); + return sharedPath; + } + + LogDNACommon.report(LogVisor::FatalError, "Unable to find entry %s", entry->id.toString().c_str()); + return HECL::ProjectPath(); +} + +template +HECL::ProjectPath PAKRouter::getWorking(const EntryType* entry) const +{ + if (!entry) + return HECL::ProjectPath(); + return getWorking(entry, BRIDGETYPE::LookupExtractor(*entry)); +} + +template +HECL::ProjectPath PAKRouter::getWorking(const IDType& id) const +{ + return getWorking(lookupEntry(id)); +} + +template +HECL::ProjectPath PAKRouter::getCooked(const EntryType* entry) const +{ + if (!entry) + return HECL::ProjectPath(); + if (!m_pak) + LogDNACommon.report(LogVisor::FatalError, + "PAKRouter::enterPAKBridge() must be called before PAKRouter::getCookedPath()"); + if (m_pak->m_noShare) + { + const EntryType* singleSearch = m_pak->lookupEntry(entry->id); + if (singleSearch) + { + const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].second; + pakPath.makeDir(); + return HECL::ProjectPath(pakPath, getBestEntryName(*entry)); + } + } + auto uniqueSearch = m_uniqueEntries.find(entry->id); + if (uniqueSearch != m_uniqueEntries.end()) + { + const HECL::ProjectPath& pakPath = m_bridgePaths[uniqueSearch->second.first].second; + pakPath.makeDir(); + HECL::ProjectPath uniquePath = entry->unique.uniquePath(pakPath); + return HECL::ProjectPath(uniquePath, getBestEntryName(*entry)); + } + auto sharedSearch = m_sharedEntries.find(entry->id); + if (sharedSearch != m_sharedEntries.end()) + { + m_sharedCooked.makeDir(); + return HECL::ProjectPath(m_sharedCooked, getBestEntryName(*entry)); + } + LogDNACommon.report(LogVisor::FatalError, "Unable to find entry %s", entry->id.toString().c_str()); + return HECL::ProjectPath(); +} + +template +HECL::ProjectPath PAKRouter::getCooked(const IDType& id) const +{ + return getCooked(lookupEntry(id)); +} + +template +HECL::SystemString PAKRouter::getResourceRelativePath(const EntryType& a, const IDType& b) const +{ + if (!m_pak) + LogDNACommon.report(LogVisor::FatalError, + "PAKRouter::enterPAKBridge() must be called before PAKRouter::getResourceRelativePath()"); + const typename BRIDGETYPE::PAKType::Entry* be = lookupEntry(b); + if (!be) + return HECL::SystemString(); + HECL::ProjectPath aPath = getWorking(&a, BRIDGETYPE::LookupExtractor(a)); + HECL::SystemString ret; + for (int i=0 ; i +std::string PAKRouter::getBestEntryName(const EntryType& entry) const +{ + std::string name; + for (const BRIDGETYPE& bridge : *m_bridges) + { + const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); + bool named; + name = pak.bestEntryName(entry, named); + if (named) + return name; + } + return name; +} + +template +std::string PAKRouter::getBestEntryName(const IDType& entry) const +{ + std::string name; + for (const BRIDGETYPE& bridge : *m_bridges) + { + const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); + const typename BRIDGETYPE::PAKType::Entry* e = pak.lookupEntry(entry); + if (!e) + continue; + bool named; + name = pak.bestEntryName(*e, named); + if (named) + return name; + } + return name; +} + +template +bool PAKRouter::extractResources(const BRIDGETYPE& pakBridge, bool force, + std::function progress) +{ + enterPAKBridge(pakBridge); + size_t count = 0; + size_t sz = m_pak->m_idMap.size(); + float fsz = sz; + for (unsigned w=0 ; countm_firstEntries) + { + ResExtractor extractor = BRIDGETYPE::LookupExtractor(*item); + if (extractor.weight != w) + continue; + + std::string bestName = getBestEntryName(*item); + HECL::SystemStringView bestNameView(bestName); + float thisFac = ++count / fsz; + progress(bestNameView.sys_str().c_str(), thisFac); + + /* Extract first, so they start out invalid */ + HECL::ProjectPath cooked = getCooked(item); + if (force || cooked.getPathType() == HECL::ProjectPath::Type::None) + { + PAKEntryReadStream s = item->beginReadStream(*m_node); + FILE* fout = HECL::Fopen(cooked.getAbsolutePath().c_str(), _S("wb")); + fwrite(s.data(), 1, s.length(), fout); + fclose(fout); + } + + HECL::ProjectPath working = getWorking(item, extractor); + if (extractor.func_a) /* Doesn't need PAKRouter access */ + { + if (force || working.getPathType() == HECL::ProjectPath::Type::None) + { + PAKEntryReadStream s = item->beginReadStream(*m_node); + extractor.func_a(s, working); + } + } + else if (extractor.func_b) /* Needs PAKRouter access */ + { + if (force || working.getPathType() == HECL::ProjectPath::Type::None) + { + PAKEntryReadStream s = item->beginReadStream(*m_node); + extractor.func_b(m_dataSpec, s, working, *this, *item, force, + [&progress, thisFac](const HECL::SystemChar* update) + { + progress(update, thisFac); + }); + } + } + } + } + + return true; +} + +template +const typename BRIDGETYPE::PAKType::Entry* PAKRouter::lookupEntry(const IDType& entry, + const NOD::Node** nodeOut, + bool silenceWarnings, + bool currentPAK) const +{ + if (!entry) + return nullptr; + + if (!m_bridges) + LogDNACommon.report(LogVisor::FatalError, + "PAKRouter::build() must be called before PAKRouter::lookupEntry()"); + + if (m_pak) + { + const EntryType* ent = m_pak->lookupEntry(entry); + if (ent) + { + if (nodeOut) + *nodeOut = m_node; + return ent; + } + } + + if (currentPAK) + { + if (!silenceWarnings) + LogDNACommon.report(LogVisor::Warning, + "unable to find PAK entry %s in current PAK", entry.toString().c_str()); + return nullptr; + } + + for (const BRIDGETYPE& bridge : *m_bridges) + { + const PAKType& pak = bridge.getPAK(); + const EntryType* ent = pak.lookupEntry(entry); + if (ent) + { + if (nodeOut) + *nodeOut = &bridge.getNode(); + return ent; + } + } + + if (!silenceWarnings) + LogDNACommon.report(LogVisor::Warning, + "unable to find PAK entry %s", entry.toString().c_str()); + if (nodeOut) + *nodeOut = nullptr; + return nullptr; +} + +template +const typename PAKRouter::RigPair* PAKRouter::lookupCMDLRigPair(const IDType& id) const +{ + auto search = m_cmdlRigs.find(id); + if (search == m_cmdlRigs.end()) + return nullptr; + return &search->second; +} + +template +HECL::ProjectPath PAKRouter::getAreaLayerWorking(const IDType& areaId, int layerIdx) const +{ + if (!m_bridges) + LogDNACommon.report(LogVisor::FatalError, + "PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()"); + auto bridgePathIt = m_bridgePaths.cbegin(); + for (const BRIDGETYPE& bridge : *m_bridges) + { + for (const auto& level : bridge.m_levelDeps) + for (const auto& area : level.second.areas) + if (area.first == areaId) + { + HECL::ProjectPath levelPath(bridgePathIt->first, level.second.name); + HECL::ProjectPath areaPath(levelPath, area.second.name); + if (layerIdx < 0) + return areaPath; + return HECL::ProjectPath(areaPath, area.second.layers.at(layerIdx).name); + } + ++bridgePathIt; + } + return HECL::ProjectPath(); +} + +template +HECL::ProjectPath PAKRouter::getAreaLayerCooked(const IDType& areaId, int layerIdx) const +{ + if (!m_bridges) + LogDNACommon.report(LogVisor::FatalError, + "PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()"); + auto bridgePathIt = m_bridgePaths.cbegin(); + for (const BRIDGETYPE& bridge : *m_bridges) + { + for (const auto& level : bridge.m_levelDeps) + for (const auto& area : level.second.areas) + if (area.first == areaId) + { + HECL::ProjectPath levelPath(bridgePathIt->second, level.second.name); + HECL::ProjectPath areaPath(levelPath, area.second.name); + if (layerIdx < 0) + return areaPath; + return HECL::ProjectPath(areaPath, area.second.layers.at(layerIdx).name); + } + ++bridgePathIt; + } + return HECL::ProjectPath(); +} + +template class PAKRouter; +template class PAKRouter; +template class PAKRouter; + +} diff --git a/DataSpec/DNACommon/PAK.hpp b/DataSpec/DNACommon/PAK.hpp index 7e3e8155d..96f336da4 100644 --- a/DataSpec/DNACommon/PAK.hpp +++ b/DataSpec/DNACommon/PAK.hpp @@ -66,131 +66,10 @@ struct UniqueResult UniqueResult() = default; UniqueResult(Type tp) : m_type(tp) {} - template - void checkEntry(const PAKBRIDGE& pakBridge, const typename PAKBRIDGE::PAKType::Entry& entry) - { - UniqueResult::Type resultType = UniqueResult::Type::NotFound; - bool foundOneLayer = false; - const HECL::SystemString* levelName = nullptr; - typename PAKBRIDGE::PAKType::IDType levelId; - typename PAKBRIDGE::PAKType::IDType areaId; - unsigned layerIdx; - for (const auto& lpair : pakBridge.m_levelDeps) - { - if (entry.id == lpair.first) - { - levelName = &lpair.second.name; - resultType = UniqueResult::Type::Level; - break; - } + template + void checkEntry(const PAKBRIDGE& pakBridge, const typename PAKBRIDGE::PAKType::Entry& entry); - for (const auto& pair : lpair.second.areas) - { - unsigned l=0; - for (const auto& layer : pair.second.layers) - { - if (layer.resources.find(entry.id) != layer.resources.end()) - { - if (foundOneLayer) - { - if (areaId == pair.first) - { - resultType = UniqueResult::Type::Area; - } - else if (levelId == lpair.first) - { - resultType = UniqueResult::Type::Level; - break; - } - else - { - m_type = UniqueResult::Type::Pak; - return; - } - continue; - } - else - resultType = UniqueResult::Type::Layer; - levelName = &lpair.second.name; - levelId = lpair.first; - areaId = pair.first; - layerIdx = l; - foundOneLayer = true; - } - ++l; - } - if (pair.second.resources.find(entry.id) != pair.second.resources.end()) - { - if (foundOneLayer) - { - if (areaId == pair.first) - { - resultType = UniqueResult::Type::Area; - } - else if (levelId == lpair.first) - { - resultType = UniqueResult::Type::Level; - break; - } - else - { - m_type = UniqueResult::Type::Pak; - return; - } - continue; - } - else - resultType = UniqueResult::Type::Area; - levelName = &lpair.second.name; - levelId = lpair.first; - areaId = pair.first; - foundOneLayer = true; - } - } - } - m_type = resultType; - m_levelName = levelName; - if (resultType == UniqueResult::Type::Layer || resultType == UniqueResult::Type::Area) - { - const typename PAKBRIDGE::Level::Area& area = pakBridge.m_levelDeps.at(levelId).areas.at(areaId); - m_areaName = &area.name; - if (resultType == UniqueResult::Type::Layer) - { - const typename PAKBRIDGE::Level::Area::Layer& layer = area.layers[layerIdx]; - m_layerName = &layer.name; - } - } - } - - HECL::ProjectPath uniquePath(const HECL::ProjectPath& pakPath) const - { - if (m_type == Type::Pak) - return pakPath; - - HECL::ProjectPath levelDir; - if (m_levelName) - levelDir.assign(pakPath, *m_levelName); - else - levelDir = pakPath; - levelDir.makeDir(); - - if (m_type == Type::Area) - { - HECL::ProjectPath areaDir(levelDir, *m_areaName); - areaDir.makeDir(); - return areaDir; - } - else if (m_type == Type::Layer) - { - HECL::ProjectPath areaDir(levelDir, *m_areaName); - areaDir.makeDir(); - HECL::ProjectPath layerDir(areaDir, *m_layerName); - layerDir.makeDir(); - return layerDir; - } - - return levelDir; - } + HECL::ProjectPath uniquePath(const HECL::ProjectPath& pakPath) const; }; template @@ -258,375 +137,29 @@ public: m_gameWorking(working), m_gameCooked(cooked), m_sharedWorking(working, "Shared"), m_sharedCooked(cooked, "Shared") {} - void build(std::vector& bridges, std::function progress) - { - m_bridges = &bridges; - m_bridgePaths.clear(); + void build(std::vector& bridges, std::function progress); - m_uniqueEntries.clear(); - m_sharedEntries.clear(); - m_cmdlRigs.clear(); - size_t count = 0; - float bridgesSz = bridges.size(); - - /* Route entries unique/shared per-pak */ - size_t bridgeIdx = 0; - for (BRIDGETYPE& bridge : bridges) - { - const std::string& name = bridge.getName(); - HECL::SystemStringView sysName(name); - - HECL::SystemString::const_iterator extit = sysName.sys_str().end() - 4; - HECL::SystemString baseName(sysName.sys_str().begin(), extit); - - m_bridgePaths.emplace_back(std::make_pair(HECL::ProjectPath(m_gameWorking, baseName), - HECL::ProjectPath(m_gameCooked, baseName))); - - /* Index this PAK */ - bridge.build(); - - /* Add to global entry lookup */ - const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); - for (const auto& entry : pak.m_idMap) - { - if (!pak.m_noShare) - { - auto sSearch = m_sharedEntries.find(entry.first); - if (sSearch != m_sharedEntries.end()) - continue; - auto uSearch = m_uniqueEntries.find(entry.first); - if (uSearch != m_uniqueEntries.end()) - { - m_uniqueEntries.erase(uSearch); - m_sharedEntries[entry.first] = std::make_pair(bridgeIdx, entry.second); - } - else - m_uniqueEntries[entry.first] = std::make_pair(bridgeIdx, entry.second); - } - else - m_uniqueEntries[entry.first] = std::make_pair(bridgeIdx, entry.second); - } - - /* Add RigPairs to global map */ - bridge.addCMDLRigPairs(*this, m_cmdlRigs); - - progress(++count / bridgesSz); - ++bridgeIdx; - } - - /* Add named resources to catalog YAML files */ - for (BRIDGETYPE& bridge : bridges) - { - Athena::io::YAMLDocWriter catalogWriter(nullptr); - - enterPAKBridge(bridge); - const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); - for (const auto& namedEntry : pak.m_nameEntries) - { - catalogWriter.enterSubRecord(namedEntry.name.c_str()); - catalogWriter.writeString(nullptr, getWorking(namedEntry.id).getRelativePathUTF8().c_str()); - catalogWriter.leaveSubRecord(); - } - - /* Write catalog */ - const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].first; - HECL::SystemString catalogPath = HECL::ProjectPath(pakPath, "catalog.yaml").getAbsolutePath(); - FILE* catalog = HECL::Fopen(catalogPath.c_str(), _S("w")); - yaml_emitter_set_output_file(catalogWriter.getEmitter(), catalog); - catalogWriter.finish(); - fclose(catalog); - } - } - - void enterPAKBridge(const BRIDGETYPE& pakBridge) - { - g_PakRouter = this; - auto pit = m_bridgePaths.begin(); - size_t bridgeIdx = 0; - for (const BRIDGETYPE& bridge : *m_bridges) - { - if (&bridge == &pakBridge) - { - pit->first.makeDir(); - pit->second.makeDir(); - m_pak = &pakBridge.getPAK(); - m_node = &pakBridge.getNode(); - m_curBridgeIdx = bridgeIdx; - return; - } - ++pit; - ++bridgeIdx; - } - LogDNACommon.report(LogVisor::FatalError, "PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()"); - } + void enterPAKBridge(const BRIDGETYPE& pakBridge); HECL::ProjectPath getWorking(const EntryType* entry, - const ResExtractor& extractor) const - { - if (!entry) - return HECL::ProjectPath(); - if (!m_pak) - LogDNACommon.report(LogVisor::FatalError, - "PAKRouter::enterPAKBridge() must be called before PAKRouter::getWorkingPath()"); - if (m_pak->m_noShare) - { - const EntryType* singleSearch = m_pak->lookupEntry(entry->id); - if (singleSearch) - { - const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].first; - pakPath.makeDir(); -#if HECL_UCS2 - HECL::SystemString entName = HECL::UTF8ToWide(getBestEntryName(*entry)); -#else - HECL::SystemString entName = getBestEntryName(*entry); -#endif - if (extractor.fileExts[0] && !extractor.fileExts[1]) - entName += extractor.fileExts[0]; - return HECL::ProjectPath(pakPath, entName); - } - } + const ResExtractor& extractor) const; + HECL::ProjectPath getWorking(const EntryType* entry) const; + HECL::ProjectPath getWorking(const IDType& id) const; + HECL::ProjectPath getCooked(const EntryType* entry) const; + HECL::ProjectPath getCooked(const IDType& id) const; - auto uniqueSearch = m_uniqueEntries.find(entry->id); - if (uniqueSearch != m_uniqueEntries.end()) - { - const HECL::ProjectPath& pakPath = m_bridgePaths[uniqueSearch->second.first].first; - pakPath.makeDir(); - HECL::ProjectPath uniquePath = entry->unique.uniquePath(pakPath); -#if HECL_UCS2 - HECL::SystemString entName = HECL::UTF8ToWide(getBestEntryName(*entry)); -#else - HECL::SystemString entName = getBestEntryName(*entry); -#endif - if (extractor.fileExts[0] && !extractor.fileExts[1]) - entName += extractor.fileExts[0]; - return HECL::ProjectPath(uniquePath, entName); - } + HECL::SystemString getResourceRelativePath(const EntryType& a, const IDType& b) const; - auto sharedSearch = m_sharedEntries.find(entry->id); - if (sharedSearch != m_sharedEntries.end()) - { -#if HECL_UCS2 - HECL::SystemString entBase = HECL::UTF8ToWide(getBestEntryName(*entry)); -#else - HECL::SystemString entBase = getBestEntryName(*entry); -#endif - HECL::SystemString entName = entBase; - if (extractor.fileExts[0] && !extractor.fileExts[1]) - entName += extractor.fileExts[0]; - HECL::ProjectPath sharedPath(m_sharedWorking, entName); - m_sharedWorking.makeDir(); - return sharedPath; - } - - LogDNACommon.report(LogVisor::FatalError, "Unable to find entry %s", entry->id.toString().c_str()); - return HECL::ProjectPath(); - } - - HECL::ProjectPath getWorking(const EntryType* entry) const - { - if (!entry) - return HECL::ProjectPath(); - return getWorking(entry, BRIDGETYPE::LookupExtractor(*entry)); - } - - HECL::ProjectPath getWorking(const IDType& id) const - { - return getWorking(lookupEntry(id)); - } - - HECL::ProjectPath getCooked(const EntryType* entry) const - { - if (!entry) - return HECL::ProjectPath(); - if (!m_pak) - LogDNACommon.report(LogVisor::FatalError, - "PAKRouter::enterPAKBridge() must be called before PAKRouter::getCookedPath()"); - if (m_pak->m_noShare) - { - const EntryType* singleSearch = m_pak->lookupEntry(entry->id); - if (singleSearch) - { - const HECL::ProjectPath& pakPath = m_bridgePaths[m_curBridgeIdx].second; - pakPath.makeDir(); - return HECL::ProjectPath(pakPath, getBestEntryName(*entry)); - } - } - auto uniqueSearch = m_uniqueEntries.find(entry->id); - if (uniqueSearch != m_uniqueEntries.end()) - { - const HECL::ProjectPath& pakPath = m_bridgePaths[uniqueSearch->second.first].second; - pakPath.makeDir(); - HECL::ProjectPath uniquePath = entry->unique.uniquePath(pakPath); - return HECL::ProjectPath(uniquePath, getBestEntryName(*entry)); - } - auto sharedSearch = m_sharedEntries.find(entry->id); - if (sharedSearch != m_sharedEntries.end()) - { - m_sharedCooked.makeDir(); - return HECL::ProjectPath(m_sharedCooked, getBestEntryName(*entry)); - } - LogDNACommon.report(LogVisor::FatalError, "Unable to find entry %s", entry->id.toString().c_str()); - return HECL::ProjectPath(); - } - - HECL::ProjectPath getCooked(const IDType& id) const - { - return getCooked(lookupEntry(id)); - } - - HECL::SystemString getResourceRelativePath(const EntryType& a, const IDType& b) const - { - if (!m_pak) - LogDNACommon.report(LogVisor::FatalError, - "PAKRouter::enterPAKBridge() must be called before PAKRouter::getResourceRelativePath()"); - const typename BRIDGETYPE::PAKType::Entry* be = lookupEntry(b); - if (!be) - return HECL::SystemString(); - HECL::ProjectPath aPath = getWorking(&a, BRIDGETYPE::LookupExtractor(a)); - HECL::SystemString ret; - for (int i=0 ; i progress) - { - enterPAKBridge(pakBridge); - size_t count = 0; - size_t sz = m_pak->m_idMap.size(); - float fsz = sz; - for (unsigned w=0 ; countm_firstEntries) - { - ResExtractor extractor = BRIDGETYPE::LookupExtractor(*item); - if (extractor.weight != w) - continue; - - std::string bestName = getBestEntryName(*item); - HECL::SystemStringView bestNameView(bestName); - float thisFac = ++count / fsz; - progress(bestNameView.sys_str().c_str(), thisFac); - - /* Extract first, so they start out invalid */ - HECL::ProjectPath cooked = getCooked(item); - if (force || cooked.getPathType() == HECL::ProjectPath::Type::None) - { - PAKEntryReadStream s = item->beginReadStream(*m_node); - FILE* fout = HECL::Fopen(cooked.getAbsolutePath().c_str(), _S("wb")); - fwrite(s.data(), 1, s.length(), fout); - fclose(fout); - } - - HECL::ProjectPath working = getWorking(item, extractor); - if (extractor.func_a) /* Doesn't need PAKRouter access */ - { - if (force || working.getPathType() == HECL::ProjectPath::Type::None) - { - PAKEntryReadStream s = item->beginReadStream(*m_node); - extractor.func_a(s, working); - } - } - else if (extractor.func_b) /* Needs PAKRouter access */ - { - if (force || working.getPathType() == HECL::ProjectPath::Type::None) - { - PAKEntryReadStream s = item->beginReadStream(*m_node); - extractor.func_b(m_dataSpec, s, working, *this, *item, force, - [&progress, thisFac](const HECL::SystemChar* update) - { - progress(update, thisFac); - }); - } - } - } - } - - return true; - } + std::function progress); const typename BRIDGETYPE::PAKType::Entry* lookupEntry(const IDType& entry, const NOD::Node** nodeOut=nullptr, bool silenceWarnings=false, - bool currentPAK=false) const - { - if (!entry) - return nullptr; - - if (!m_bridges) - LogDNACommon.report(LogVisor::FatalError, - "PAKRouter::build() must be called before PAKRouter::lookupEntry()"); - - if (m_pak) - { - const EntryType* ent = m_pak->lookupEntry(entry); - if (ent) - { - if (nodeOut) - *nodeOut = m_node; - return ent; - } - } - - if (currentPAK) - { - if (!silenceWarnings) - LogDNACommon.report(LogVisor::Warning, "unable to find PAK entry %s in current PAK", entry.toString().c_str()); - return nullptr; - } - - for (const BRIDGETYPE& bridge : *m_bridges) - { - const PAKType& pak = bridge.getPAK(); - const EntryType* ent = pak.lookupEntry(entry); - if (ent) - { - if (nodeOut) - *nodeOut = &bridge.getNode(); - return ent; - } - } - - if (!silenceWarnings) - LogDNACommon.report(LogVisor::Warning, "unable to find PAK entry %s", entry.toString().c_str()); - if (nodeOut) - *nodeOut = nullptr; - return nullptr; - } + bool currentPAK=false) const; template bool lookupAndReadDNA(const IDType& id, DNA& out, bool silenceWarnings=false) @@ -640,59 +173,10 @@ public: return true; } - const RigPair* lookupCMDLRigPair(const IDType& id) const - { - auto search = m_cmdlRigs.find(id); - if (search == m_cmdlRigs.end()) - return nullptr; - return &search->second; - } + const RigPair* lookupCMDLRigPair(const IDType& id) const; - HECL::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx) const - { - if (!m_bridges) - LogDNACommon.report(LogVisor::FatalError, - "PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()"); - auto bridgePathIt = m_bridgePaths.cbegin(); - for (const BRIDGETYPE& bridge : *m_bridges) - { - for (const auto& level : bridge.m_levelDeps) - for (const auto& area : level.second.areas) - if (area.first == areaId) - { - HECL::ProjectPath levelPath(bridgePathIt->first, level.second.name); - HECL::ProjectPath areaPath(levelPath, area.second.name); - if (layerIdx < 0) - return areaPath; - return HECL::ProjectPath(areaPath, area.second.layers.at(layerIdx).name); - } - ++bridgePathIt; - } - return HECL::ProjectPath(); - } - - HECL::ProjectPath getAreaLayerCooked(const IDType& areaId, int layerIdx) const - { - if (!m_bridges) - LogDNACommon.report(LogVisor::FatalError, - "PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()"); - auto bridgePathIt = m_bridgePaths.cbegin(); - for (const BRIDGETYPE& bridge : *m_bridges) - { - for (const auto& level : bridge.m_levelDeps) - for (const auto& area : level.second.areas) - if (area.first == areaId) - { - HECL::ProjectPath levelPath(bridgePathIt->second, level.second.name); - HECL::ProjectPath areaPath(levelPath, area.second.name); - if (layerIdx < 0) - return areaPath; - return HECL::ProjectPath(areaPath, area.second.layers.at(layerIdx).name); - } - ++bridgePathIt; - } - return HECL::ProjectPath(); - } + HECL::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx) const; + HECL::ProjectPath getAreaLayerCooked(const IDType& areaId, int layerIdx) const; }; } diff --git a/DataSpec/DNACommon/PART.cpp b/DataSpec/DNACommon/PART.cpp new file mode 100644 index 000000000..97633bb8d --- /dev/null +++ b/DataSpec/DNACommon/PART.cpp @@ -0,0 +1,1571 @@ +#include "PART.hpp" + +namespace DataSpec +{ +namespace DNAParticle +{ + +template +void GPSM::read(Athena::io::YAMLDocReader& r) +{ + for (const auto& elem : r.getCurNode()->m_mapChildren) + { + if (elem.first.size() < 4) + { + LogModule.report(LogVisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); + continue; + } + + r.enterSubRecord(elem.first.c_str()); + switch (*reinterpret_cast(elem.first.data())) + { + case SBIG('PMCL'): + x78_PMCL.read(r); + break; + case SBIG('LFOR'): + x118_LFOR.read(r); + break; + case SBIG('IDTS'): + xa4_IDTS.read(r); + break; + case SBIG('EMTR'): + x40_EMTR.read(r); + break; + case SBIG('COLR'): + x30_COLR.read(r); + break; + case SBIG('CIND'): + x45_30_CIND = r.readBool(nullptr); + break; + case SBIG('AAPH'): + x44_26_AAPH = r.readBool(nullptr); + break; + case SBIG('CSSD'): + xa0_CSSD.read(r); + break; + case SBIG('GRTE'): + x2c_GRTE.read(r); + break; + case SBIG('FXLL'): + x44_25_FXLL = r.readBool(nullptr); + break; + case SBIG('ICTS'): + x8c_ICTS.read(r); + break; + case SBIG('KSSM'): + xd0_KSSM.read(r); + break; + case SBIG('ILOC'): + x38_ILOC.read(r); + break; + case SBIG('IITS'): + xb8_IITS.read(r); + break; + case SBIG('IVEC'): + x3c_IVEC.read(r); + break; + case SBIG('LDIR'): + x110_LDIR.read(r); + break; + case SBIG('LCLR'): + x104_LCLR.read(r); + break; + case SBIG('LENG'): + x20_LENG.read(r); + break; + case SBIG('MAXP'): + x28_MAXP.read(r); + break; + case SBIG('LOFF'): + x10c_LOFF.read(r); + break; + case SBIG('LINT'): + x108_LINT.read(r); + break; + case SBIG('LINE'): + x44_24_LINE = r.readBool(nullptr); + break; + case SBIG('LFOT'): + x114_LFOT.read(r); + break; + case SBIG('LIT_'): + x44_29_LIT_ = r.readBool(nullptr); + break; + case SBIG('LTME'): + x34_LTME.read(r); + break; + case SBIG('LSLA'): + x11c_LSLA.read(r); + break; + case SBIG('LTYP'): + x100_LTYP.read(r); + break; + case SBIG('NDSY'): + xb4_NDSY.read(r); + break; + case SBIG('MBSP'): + x48_MBSP.read(r); + break; + case SBIG('MBLR'): + x44_30_MBLR = r.readBool(nullptr); + break; + case SBIG('NCSY'): + x9c_NCSY.read(r); + break; + case SBIG('PISY'): + xc8_PISY.read(r); + break; + case SBIG('OPTS'): + x45_31_OPTS = r.readBool(nullptr); + break; + case SBIG('PMAB'): + x44_31_PMAB = r.readBool(nullptr); + break; + case SBIG('SESD'): + xf8_SESD.read(r); + break; + case SBIG('SEPO'): + xfc_SEPO.read(r); + break; + case SBIG('PSLT'): + xc_PSLT.read(r); + break; + case SBIG('PMSC'): + x74_PMSC.read(r); + break; + case SBIG('PMOP'): + x6c_PMOP.read(r); + break; + case SBIG('PMDL'): + x5c_PMDL.read(r); + break; + case SBIG('PMRT'): + x70_PMRT.read(r); + break; + case SBIG('POFS'): + x18_POFS.read(r); + break; + case SBIG('PMUS'): + x45_24_PMUS = r.readBool(nullptr); + break; + case SBIG('PSIV'): + x0_PSIV.read(r); + break; + case SBIG('ROTA'): + x50_ROTA.read(r); + break; + case SBIG('PSVM'): + x4_PSVM.read(r); + break; + case SBIG('PSTS'): + x14_PSTS.read(r); + break; + case SBIG('PSOV'): + x8_PSOV.read(r); + break; + case SBIG('PSWT'): + x10_PSWT.read(r); + break; + case SBIG('PMLC'): + xec_PMLC.read(r); + break; + case SBIG('SEED'): + x1c_SEED.read(r); + break; + case SBIG('PMOO'): + x45_25_PMOO = r.readBool(nullptr); + break; + case SBIG('SSSD'): + xe4_SSSD.read(r); + break; + case SBIG('SORT'): + x44_28_SORT = r.readBool(nullptr); + break; + case SBIG('SIZE'): + x4c_SIZE.read(r); + break; + case SBIG('SISY'): + xcc_SISY.read(r); + break; + case SBIG('SSPO'): + xe8_SSPO.read(r); + break; + case SBIG('TEXR'): + x54_TEXR.read(r); + break; + case SBIG('SSWH'): + xd4_SSWH.read(r); + break; + case SBIG('TIND'): + x58_TIND.read(r); + break; + case SBIG('VMD4'): + x45_29_VMD4 = r.readBool(nullptr); + break; + case SBIG('VMD3'): + x45_28_VMD3 = r.readBool(nullptr); + break; + case SBIG('VMD2'): + x45_27_VMD2 = r.readBool(nullptr); + break; + case SBIG('VMD1'): + x45_26_VMD1 = r.readBool(nullptr); + break; + case SBIG('VEL4'): + x88_VEL4.read(r); + break; + case SBIG('VEL3'): + x84_VEL3.read(r); + break; + case SBIG('VEL2'): + x80_VEL2.read(r); + break; + case SBIG('VEL1'): + x7c_VEL1.read(r); + break; + case SBIG('ZBUF'): + x44_27_ZBUF = r.readBool(nullptr); + break; + case SBIG('WIDT'): + x24_WIDT.read(r); + break; + case SBIG('ORNT'): + x30_30_ORNT = r.readBool(nullptr); + break; + case SBIG('RSOP'): + x30_31_RSOP = r.readBool(nullptr); + break; + case SBIG('ADV1'): + x10c_ADV1.read(r); + break; + case SBIG('ADV2'): + x110_ADV2.read(r); + break; + case SBIG('ADV3'): + x114_ADV3.read(r); + break; + case SBIG('ADV4'): + x118_ADV4.read(r); + break; + case SBIG('ADV5'): + x11c_ADV5.read(r); + break; + case SBIG('ADV6'): + x120_ADV6.read(r); + break; + case SBIG('ADV7'): + x124_ADV7.read(r); + break; + case SBIG('SELC'): + xd8_SELC.read(r); + break; + default: + break; + } + r.leaveSubRecord(); + } +} + +template +void GPSM::write(Athena::io::YAMLDocWriter& w) const +{ + if (x0_PSIV) + { + w.enterSubRecord("PSIV"); + x0_PSIV.write(w); + w.leaveSubRecord(); + } + if (x4_PSVM) + { + w.enterSubRecord("PSVM"); + x4_PSVM.write(w); + w.leaveSubRecord(); + } + if (x8_PSOV) + { + w.enterSubRecord("PSOV"); + x8_PSOV.write(w); + w.leaveSubRecord(); + } + if (xc_PSLT) + { + w.enterSubRecord("PSLT"); + xc_PSLT.write(w); + w.leaveSubRecord(); + } + if (x10_PSWT) + { + w.enterSubRecord("PSWT"); + x10_PSWT.write(w); + w.leaveSubRecord(); + } + if (x14_PSTS) + { + w.enterSubRecord("PSTS"); + x14_PSTS.write(w); + w.leaveSubRecord(); + } + if (x18_POFS) + { + w.enterSubRecord("POFS"); + x18_POFS.write(w); + w.leaveSubRecord(); + } + if (x1c_SEED) + { + w.enterSubRecord("SEED"); + x1c_SEED.write(w); + w.leaveSubRecord(); + } + if (x20_LENG) + { + w.enterSubRecord("LENG"); + x20_LENG.write(w); + w.leaveSubRecord(); + } + if (x24_WIDT) + { + w.enterSubRecord("WIDT"); + x24_WIDT.write(w); + w.leaveSubRecord(); + } + if (x28_MAXP) + { + w.enterSubRecord("MAXP"); + x28_MAXP.write(w); + w.leaveSubRecord(); + } + if (x2c_GRTE) + { + w.enterSubRecord("GRTE"); + x2c_GRTE.write(w); + w.leaveSubRecord(); + } + if (x30_COLR) + { + w.enterSubRecord("COLR"); + x30_COLR.write(w); + w.leaveSubRecord(); + } + if (x34_LTME) + { + w.enterSubRecord("LTME"); + x34_LTME.write(w); + w.leaveSubRecord(); + } + if (x38_ILOC) + { + w.enterSubRecord("ILOC"); + x38_ILOC.write(w); + w.leaveSubRecord(); + } + if (x3c_IVEC) + { + w.enterSubRecord("IVEC"); + x3c_IVEC.write(w); + w.leaveSubRecord(); + } + if (x40_EMTR) + { + w.enterSubRecord("EMTR"); + x40_EMTR.write(w); + w.leaveSubRecord(); + } + if (x44_24_LINE) + w.writeBool("LINE", true); + if (x44_25_FXLL) + w.writeBool("FXLL", true); + if (x44_26_AAPH) + w.writeBool("AAPH", true); + if (x44_27_ZBUF) + w.writeBool("ZBUF", true); + if (x44_28_SORT) + w.writeBool("SORT", true); + if (x44_29_LIT_) + w.writeBool("LIT_", true); + if (x44_30_MBLR) + w.writeBool("MBLR", true); + if (x44_31_PMAB) + w.writeBool("PMAB", true); + if (x45_24_PMUS) + w.writeBool("PMUS", true); + if (!x45_25_PMOO) + w.writeBool("PMOO", false); + if (x45_26_VMD1) + w.writeBool("VMD1", true); + if (x45_27_VMD2) + w.writeBool("VMD2", true); + if (x45_28_VMD3) + w.writeBool("VMD3", true); + if (x45_29_VMD4) + w.writeBool("VMD4", true); + if (x45_30_CIND) + w.writeBool("CIND", true); + if (x45_31_OPTS) + w.writeBool("OPTS", true); + if (x30_30_ORNT) + w.writeBool("ORNT", true); + if (x30_31_RSOP) + w.writeBool("RSOP", true); + if (x48_MBSP) + { + w.enterSubRecord("MPSB"); + x48_MBSP.write(w); + w.leaveSubRecord(); + } + if (x4c_SIZE) + { + w.enterSubRecord("SIZE"); + x4c_SIZE.write(w); + w.leaveSubRecord(); + } + if (x50_ROTA) + { + w.enterSubRecord("ROTA"); + x50_ROTA.write(w); + w.leaveSubRecord(); + } + if (x54_TEXR) + { + w.enterSubRecord("TEXR"); + x54_TEXR.write(w); + w.leaveSubRecord(); + } + if (x58_TIND) + { + w.enterSubRecord("TIND"); + x58_TIND.write(w); + w.leaveSubRecord(); + } + if (x5c_PMDL) + { + w.enterSubRecord("PMDL"); + x5c_PMDL.write(w); + w.leaveSubRecord(); + } + if (x6c_PMOP) + { + w.enterSubRecord("PMOP"); + x6c_PMOP.write(w); + w.leaveSubRecord(); + } + if (x70_PMRT) + { + w.enterSubRecord("PMRT"); + x70_PMRT.write(w); + w.leaveSubRecord(); + } + if (x74_PMSC) + { + w.enterSubRecord("PMSC"); + x74_PMSC.write(w); + w.leaveSubRecord(); + } + if (x78_PMCL) + { + w.enterSubRecord("PMCL"); + x78_PMCL.write(w); + w.leaveSubRecord(); + } + if (x7c_VEL1) + { + w.enterSubRecord("VEL1"); + x7c_VEL1.write(w); + w.leaveSubRecord(); + } + if (x80_VEL2) + { + w.enterSubRecord("VEL2"); + x80_VEL2.write(w); + w.leaveSubRecord(); + } + if (x84_VEL3) + { + w.enterSubRecord("VEL3"); + x84_VEL3.write(w); + w.leaveSubRecord(); + } + if (x88_VEL4) + { + w.enterSubRecord("VEL4"); + x88_VEL4.write(w); + w.leaveSubRecord(); + } + if (x8c_ICTS) + { + w.enterSubRecord("ICTS"); + x8c_ICTS.write(w); + w.leaveSubRecord(); + } + if (x9c_NCSY) + { + w.enterSubRecord("NCSY"); + x9c_NCSY.write(w); + w.leaveSubRecord(); + } + if (xa0_CSSD) + { + w.enterSubRecord("CSSD"); + xa0_CSSD.write(w); + w.leaveSubRecord(); + } + if (xa4_IDTS) + { + w.enterSubRecord("IDTS"); + xa4_IDTS.write(w); + w.leaveSubRecord(); + } + if (xb4_NDSY) + { + w.enterSubRecord("NDSY"); + xb4_NDSY.write(w); + w.leaveSubRecord(); + } + if (xb8_IITS) + { + w.enterSubRecord("IITS"); + xb8_IITS.write(w); + w.leaveSubRecord(); + } + if (xc8_PISY) + { + w.enterSubRecord("PISY"); + xc8_PISY.write(w); + w.leaveSubRecord(); + } + if (xcc_SISY) + { + w.enterSubRecord("SISY"); + xcc_SISY.write(w); + w.leaveSubRecord(); + } + if (xd0_KSSM) + { + w.enterSubRecord("KSSM"); + xd0_KSSM.write(w); + w.leaveSubRecord(); + } + if (xd4_SSWH) + { + w.enterSubRecord("SSWH"); + xd4_SSWH.write(w); + w.leaveSubRecord(); + } + if (xd8_SELC) + { + w.enterSubRecord("SELC"); + xd8_SELC.write(w); + w.leaveSubRecord(); + } + if (xe4_SSSD) + { + w.enterSubRecord("SSSD"); + xe4_SSSD.write(w); + w.leaveSubRecord(); + } + if (xe8_SSPO) + { + w.enterSubRecord("SSPO"); + xe8_SSPO.write(w); + w.leaveSubRecord(); + } + if (xf8_SESD) + { + w.enterSubRecord("SESD"); + xf8_SESD.write(w); + w.leaveSubRecord(); + } + if (xfc_SEPO) + { + w.enterSubRecord("SEPO"); + xfc_SEPO.write(w); + w.leaveSubRecord(); + } + if (xec_PMLC) + { + w.enterSubRecord("PMLC"); + xec_PMLC.write(w); + w.leaveSubRecord(); + } + if (x100_LTYP) + { + w.enterSubRecord("LTYP"); + x100_LTYP.write(w); + w.leaveSubRecord(); + } + if (x104_LCLR) + { + w.enterSubRecord("LCLR"); + x104_LCLR.write(w); + w.leaveSubRecord(); + } + if (x108_LINT) + { + w.enterSubRecord("LINT"); + x108_LINT.write(w); + w.leaveSubRecord(); + } + if (x10c_LOFF) + { + w.enterSubRecord("LOFF"); + x10c_LOFF.write(w); + w.leaveSubRecord(); + } + if (x110_LDIR) + { + w.enterSubRecord("LDIR"); + x110_LDIR.write(w); + w.leaveSubRecord(); + } + if (x114_LFOT) + { + w.enterSubRecord("LFOT"); + x114_LFOT.write(w); + w.leaveSubRecord(); + } + if (x118_LFOR) + { + w.enterSubRecord("LFOR"); + x118_LFOR.write(w); + w.leaveSubRecord(); + } + if (x11c_LSLA) + { + w.enterSubRecord("LSLA"); + x11c_LSLA.write(w); + w.leaveSubRecord(); + } + if (x10c_ADV1) + { + w.enterSubRecord("ADV1"); + x10c_ADV1.write(w); + w.leaveSubRecord(); + } + if (x110_ADV2) + { + w.enterSubRecord("ADV2"); + x110_ADV2.write(w); + w.leaveSubRecord(); + } + if (x114_ADV3) + { + w.enterSubRecord("ADV3"); + x114_ADV3.write(w); + w.leaveSubRecord(); + } + if (x118_ADV4) + { + w.enterSubRecord("ADV4"); + x118_ADV4.write(w); + w.leaveSubRecord(); + } + if (x11c_ADV5) + { + w.enterSubRecord("ADV5"); + x11c_ADV5.write(w); + w.leaveSubRecord(); + } + if (x120_ADV6) + { + w.enterSubRecord("ADV6"); + x120_ADV6.write(w); + w.leaveSubRecord(); + } + if (x124_ADV7) + { + w.enterSubRecord("ADV7"); + x124_ADV7.write(w); + w.leaveSubRecord(); + } + if (x128_ADV8) + { + w.enterSubRecord("ADV8"); + x128_ADV8.write(w); + w.leaveSubRecord(); + } +} + +template +size_t GPSM::binarySize(size_t __isz) const +{ + __isz += 4; + if (x0_PSIV) + __isz = x0_PSIV.binarySize(__isz + 4); + if (x4_PSVM) + __isz = x4_PSVM.binarySize(__isz + 4); + if (x8_PSOV) + __isz = x8_PSOV.binarySize(__isz + 4); + if (xc_PSLT) + __isz = xc_PSLT.binarySize(__isz + 4); + if (x10_PSWT) + __isz = x10_PSWT.binarySize(__isz + 4); + if (x14_PSTS) + __isz = x14_PSTS.binarySize(__isz + 4); + if (x18_POFS) + __isz = x18_POFS.binarySize(__isz + 4); + if (x1c_SEED) + __isz = x1c_SEED.binarySize(__isz + 4); + if (x20_LENG) + __isz = x20_LENG.binarySize(__isz + 4); + if (x24_WIDT) + __isz = x24_WIDT.binarySize(__isz + 4); + if (x28_MAXP) + __isz = x28_MAXP.binarySize(__isz + 4); + if (x2c_GRTE) + __isz = x2c_GRTE.binarySize(__isz + 4); + if (x30_COLR) + __isz = x30_COLR.binarySize(__isz + 4); + if (x34_LTME) + __isz = x34_LTME.binarySize(__isz + 4); + if (x38_ILOC) + __isz = x38_ILOC.binarySize(__isz + 4); + if (x3c_IVEC) + __isz = x3c_IVEC.binarySize(__isz + 4); + if (x40_EMTR) + __isz = x40_EMTR.binarySize(__isz + 4); + if (x44_24_LINE) + __isz += 9; + if (x44_25_FXLL) + __isz += 9; + if (x44_26_AAPH) + __isz += 9; + if (x44_27_ZBUF) + __isz += 9; + if (x44_28_SORT) + __isz += 9; + if (x44_29_LIT_) + __isz += 9; + if (x44_30_MBLR) + __isz += 9; + if (x44_31_PMAB) + __isz += 9; + if (x45_24_PMUS) + __isz += 9; + if (!x45_25_PMOO) + __isz += 9; + if (x45_26_VMD1) + __isz += 9; + if (x45_27_VMD2) + __isz += 9; + if (x45_28_VMD3) + __isz += 9; + if (x45_29_VMD4) + __isz += 9; + if (x45_30_CIND) + __isz += 9; + if (x45_31_OPTS) + __isz += 9; + if (x30_30_ORNT) + __isz += 9; + if (x30_31_RSOP) + __isz += 9; + if (x48_MBSP) + __isz = x48_MBSP.binarySize(__isz + 4); + if (x4c_SIZE) + __isz = x4c_SIZE.binarySize(__isz + 4); + if (x50_ROTA) + __isz = x50_ROTA.binarySize(__isz + 4); + if (x54_TEXR) + __isz = x54_TEXR.binarySize(__isz + 4); + if (x58_TIND) + __isz = x58_TIND.binarySize(__isz + 4); + if (x5c_PMDL) + __isz = x5c_PMDL.binarySize(__isz + 4); + if (x6c_PMOP) + __isz = x6c_PMOP.binarySize(__isz + 4); + if (x70_PMRT) + __isz = x70_PMRT.binarySize(__isz + 4); + if (x74_PMSC) + __isz = x74_PMSC.binarySize(__isz + 4); + if (x78_PMCL) + __isz = x78_PMCL.binarySize(__isz + 4); + if (x7c_VEL1) + __isz = x7c_VEL1.binarySize(__isz + 4); + if (x80_VEL2) + __isz = x80_VEL2.binarySize(__isz + 4); + if (x84_VEL3) + __isz = x84_VEL3.binarySize(__isz + 4); + if (x88_VEL4) + __isz = x88_VEL4.binarySize(__isz + 4); + if (x8c_ICTS) + __isz = x8c_ICTS.binarySize(__isz + 4); + if (x9c_NCSY) + __isz = x9c_NCSY.binarySize(__isz + 4); + if (xa0_CSSD) + __isz = xa0_CSSD.binarySize(__isz + 4); + if (xa4_IDTS) + __isz = xa4_IDTS.binarySize(__isz + 4); + if (xb4_NDSY) + __isz = xb4_NDSY.binarySize(__isz + 4); + if (xb8_IITS) + __isz = xb8_IITS.binarySize(__isz + 4); + if (xc8_PISY) + __isz = xc8_PISY.binarySize(__isz + 4); + if (xcc_SISY) + __isz = xcc_SISY.binarySize(__isz + 4); + if (xd0_KSSM) + __isz = xd0_KSSM.binarySize(__isz + 4); + if (xd4_SSWH) + __isz = xd4_SSWH.binarySize(__isz + 4); + if (xd8_SELC) + __isz = xd8_SELC.binarySize(__isz + 4); + if (xe4_SSSD) + __isz = xe4_SSSD.binarySize(__isz + 4); + if (xe8_SSPO) + __isz = xe8_SSPO.binarySize(__isz + 4); + if (xf8_SESD) + __isz = xf8_SESD.binarySize(__isz + 4); + if (xfc_SEPO) + __isz = xfc_SEPO.binarySize(__isz + 4); + if (xec_PMLC) + __isz = xec_PMLC.binarySize(__isz + 4); + if (x100_LTYP) + __isz = x100_LTYP.binarySize(__isz + 4); + if (x104_LCLR) + __isz = x104_LCLR.binarySize(__isz + 4); + if (x108_LINT) + __isz = x108_LINT.binarySize(__isz + 4); + if (x10c_LOFF) + __isz = x10c_LOFF.binarySize(__isz + 4); + if (x110_LDIR) + __isz = x110_LDIR.binarySize(__isz + 4); + if (x114_LFOT) + __isz = x114_LFOT.binarySize(__isz + 4); + if (x118_LFOR) + __isz = x118_LFOR.binarySize(__isz + 4); + if (x11c_LSLA) + __isz = x11c_LSLA.binarySize(__isz + 4); + if (x10c_ADV1) + __isz = x10c_ADV1.binarySize(__isz + 4); + if (x110_ADV2) + __isz = x110_ADV2.binarySize(__isz + 4); + if (x114_ADV3) + __isz = x114_ADV3.binarySize(__isz + 4); + if (x118_ADV4) + __isz = x118_ADV4.binarySize(__isz + 4); + if (x11c_ADV5) + __isz = x11c_ADV5.binarySize(__isz + 4); + if (x120_ADV6) + __isz = x120_ADV6.binarySize(__isz + 4); + if (x124_ADV7) + __isz = x124_ADV7.binarySize(__isz + 4); + if (x128_ADV8) + __isz = x128_ADV8.binarySize(__isz + 4); + return __isz; +} + +template +void GPSM::read(Athena::io::IStreamReader& r) +{ + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId != SBIG('GPSM')) + { + LogModule.report(LogVisor::Warning, "non GPSM provided to GPSM parser"); + return; + } + r.readBytesToBuf(&clsId, 4); + while (clsId != SBIG('_END')) + { + switch (clsId) + { + case SBIG('PMCL'): + x78_PMCL.read(r); + break; + case SBIG('LFOR'): + x118_LFOR.read(r); + break; + case SBIG('IDTS'): + xa4_IDTS.read(r); + break; + case SBIG('EMTR'): + x40_EMTR.read(r); + break; + case SBIG('COLR'): + x30_COLR.read(r); + break; + case SBIG('CIND'): + r.readUint32Big(); + x45_30_CIND = r.readBool(); + break; + case SBIG('AAPH'): + r.readUint32Big(); + x44_26_AAPH = r.readBool(); + break; + case SBIG('CSSD'): + xa0_CSSD.read(r); + break; + case SBIG('GRTE'): + x2c_GRTE.read(r); + break; + case SBIG('FXLL'): + r.readUint32Big(); + x44_25_FXLL = r.readBool(); + break; + case SBIG('ICTS'): + x8c_ICTS.read(r); + break; + case SBIG('KSSM'): + xd0_KSSM.read(r); + break; + case SBIG('ILOC'): + x38_ILOC.read(r); + break; + case SBIG('IITS'): + xb8_IITS.read(r); + break; + case SBIG('IVEC'): + x3c_IVEC.read(r); + break; + case SBIG('LDIR'): + x110_LDIR.read(r); + break; + case SBIG('LCLR'): + x104_LCLR.read(r); + break; + case SBIG('LENG'): + x20_LENG.read(r); + break; + case SBIG('MAXP'): + x28_MAXP.read(r); + break; + case SBIG('LOFF'): + x10c_LOFF.read(r); + break; + case SBIG('LINT'): + x108_LINT.read(r); + break; + case SBIG('LINE'): + r.readUint32Big(); + x44_24_LINE = r.readBool(); + break; + case SBIG('LFOT'): + x114_LFOT.read(r); + break; + case SBIG('LIT_'): + r.readUint32Big(); + x44_29_LIT_ = r.readBool(); + break; + case SBIG('LTME'): + x34_LTME.read(r); + break; + case SBIG('LSLA'): + x11c_LSLA.read(r); + break; + case SBIG('LTYP'): + x100_LTYP.read(r); + break; + case SBIG('NDSY'): + xb4_NDSY.read(r); + break; + case SBIG('MBSP'): + x48_MBSP.read(r); + break; + case SBIG('MBLR'): + r.readUint32Big(); + x44_30_MBLR = r.readBool(); + break; + case SBIG('NCSY'): + x9c_NCSY.read(r); + break; + case SBIG('PISY'): + xc8_PISY.read(r); + break; + case SBIG('OPTS'): + r.readUint32Big(); + x45_31_OPTS = r.readBool(); + break; + case SBIG('PMAB'): + r.readUint32Big(); + x44_31_PMAB = r.readBool(); + break; + case SBIG('SESD'): + xf8_SESD.read(r); + break; + case SBIG('SEPO'): + xfc_SEPO.read(r); + break; + case SBIG('PSLT'): + xc_PSLT.read(r); + break; + case SBIG('PMSC'): + x74_PMSC.read(r); + break; + case SBIG('PMOP'): + x6c_PMOP.read(r); + break; + case SBIG('PMDL'): + x5c_PMDL.read(r); + break; + case SBIG('PMRT'): + x70_PMRT.read(r); + break; + case SBIG('POFS'): + x18_POFS.read(r); + break; + case SBIG('PMUS'): + r.readUint32Big(); + x45_24_PMUS = r.readBool(); + break; + case SBIG('PSIV'): + x0_PSIV.read(r); + break; + case SBIG('ROTA'): + x50_ROTA.read(r); + break; + case SBIG('PSVM'): + x4_PSVM.read(r); + break; + case SBIG('PSTS'): + x14_PSTS.read(r); + break; + case SBIG('PSOV'): + x8_PSOV.read(r); + break; + case SBIG('PSWT'): + x10_PSWT.read(r); + break; + case SBIG('PMLC'): + xec_PMLC.read(r); + break; + case SBIG('SEED'): + x1c_SEED.read(r); + break; + case SBIG('PMOO'): + r.readUint32Big(); + x45_25_PMOO = r.readBool(); + break; + case SBIG('SSSD'): + xe4_SSSD.read(r); + break; + case SBIG('SORT'): + r.readUint32Big(); + x44_28_SORT = r.readBool(); + break; + case SBIG('SIZE'): + x4c_SIZE.read(r); + break; + case SBIG('SISY'): + xcc_SISY.read(r); + break; + case SBIG('SSPO'): + xe8_SSPO.read(r); + break; + case SBIG('TEXR'): + x54_TEXR.read(r); + break; + case SBIG('SSWH'): + xd4_SSWH.read(r); + break; + case SBIG('TIND'): + x58_TIND.read(r); + break; + case SBIG('VMD4'): + r.readUint32Big(); + x45_29_VMD4 = r.readBool(); + break; + case SBIG('VMD3'): + r.readUint32Big(); + x45_28_VMD3 = r.readBool(); + break; + case SBIG('VMD2'): + r.readUint32Big(); + x45_27_VMD2 = r.readBool(); + break; + case SBIG('VMD1'): + r.readUint32Big(); + x45_26_VMD1 = r.readBool(); + break; + case SBIG('VEL4'): + x88_VEL4.read(r); + break; + case SBIG('VEL3'): + x84_VEL3.read(r); + break; + case SBIG('VEL2'): + x80_VEL2.read(r); + break; + case SBIG('VEL1'): + x7c_VEL1.read(r); + break; + case SBIG('ZBUF'): + r.readUint32Big(); + x44_27_ZBUF = r.readBool(); + break; + case SBIG('WIDT'): + x24_WIDT.read(r); + break; + case SBIG('ORNT'): + r.readUint32Big(); + x30_30_ORNT = r.readBool(); + break; + case SBIG('RSOP'): + r.readUint32Big(); + x30_31_RSOP = r.readBool(); + break; + case SBIG('ADV1'): + x10c_ADV1.read(r); + break; + case SBIG('ADV2'): + x110_ADV2.read(r); + break; + case SBIG('ADV3'): + x114_ADV3.read(r); + break; + case SBIG('ADV4'): + x118_ADV4.read(r); + break; + case SBIG('ADV5'): + x11c_ADV5.read(r); + break; + case SBIG('ADV6'): + x120_ADV6.read(r); + break; + case SBIG('ADV7'): + x124_ADV7.read(r); + break; + case SBIG('ADV8'): + x128_ADV8.read(r); + break; + case SBIG('SELC'): + xd8_SELC.read(r); + break; + default: + LogModule.report(LogVisor::FatalError, "Unknown GPSM class %.4s @%" PRIi64, &clsId, r.position()); + break; + } + r.readBytesToBuf(&clsId, 4); + } +} + +template +void GPSM::write(Athena::io::IStreamWriter& w) const +{ + w.writeBytes((atInt8*)"GPSM", 4); + if (x0_PSIV) + { + w.writeBytes((atInt8*)"PSIV", 4); + x0_PSIV.write(w); + } + if (x4_PSVM) + { + w.writeBytes((atInt8*)"PSVM", 4); + x4_PSVM.write(w); + } + if (x8_PSOV) + { + w.writeBytes((atInt8*)"PSOV", 4); + x8_PSOV.write(w); + } + if (xc_PSLT) + { + w.writeBytes((atInt8*)"PSLT", 4); + xc_PSLT.write(w); + } + if (x10_PSWT) + { + w.writeBytes((atInt8*)"PSWT", 4); + x10_PSWT.write(w); + } + if (x14_PSTS) + { + w.writeBytes((atInt8*)"PSTS", 4); + x14_PSTS.write(w); + } + if (x18_POFS) + { + w.writeBytes((atInt8*)"POFS", 4); + x18_POFS.write(w); + } + if (x1c_SEED) + { + w.writeBytes((atInt8*)"SEED", 4); + x1c_SEED.write(w); + } + if (x20_LENG) + { + w.writeBytes((atInt8*)"LENG", 4); + x20_LENG.write(w); + } + if (x24_WIDT) + { + w.writeBytes((atInt8*)"WIDT", 4); + x24_WIDT.write(w); + } + if (x28_MAXP) + { + w.writeBytes((atInt8*)"MAXP", 4); + x28_MAXP.write(w); + } + if (x2c_GRTE) + { + w.writeBytes((atInt8*)"GRTE", 4); + x2c_GRTE.write(w); + } + if (x30_COLR) + { + w.writeBytes((atInt8*)"COLR", 4); + x30_COLR.write(w); + } + if (x34_LTME) + { + w.writeBytes((atInt8*)"LTME", 4); + x34_LTME.write(w); + } + if (x38_ILOC) + { + w.writeBytes((atInt8*)"ILOC", 4); + x38_ILOC.write(w); + } + if (x3c_IVEC) + { + w.writeBytes((atInt8*)"IVEC", 4); + x3c_IVEC.write(w); + } + if (x40_EMTR) + { + w.writeBytes((atInt8*)"EMTR", 4); + x40_EMTR.write(w); + } + if (x44_24_LINE) + { + w.writeBytes((atInt8*)"LINECNST\x01", 9); + } + if (x44_25_FXLL) + { + w.writeBytes((atInt8*)"FXLLCNST\x01", 9); + } + if (x44_26_AAPH) + { + w.writeBytes((atInt8*)"AAPHCNST\x01", 9); + } + if (x44_27_ZBUF) + { + w.writeBytes((atInt8*)"ZBUFCNST\x01", 9); + } + if (x44_28_SORT) + { + w.writeBytes((atInt8*)"SORTCNST\x01", 9); + } + if (x44_29_LIT_) + { + w.writeBytes((atInt8*)"LIT_CNST\x01", 9); + } + if (x44_30_MBLR) + { + w.writeBytes((atInt8*)"MBLRCNST\x01", 9); + } + if (x44_31_PMAB) + { + w.writeBytes((atInt8*)"PMABCNST\x01", 9); + } + if (x45_24_PMUS) + { + w.writeBytes((atInt8*)"PMUSCNST\x01", 9); + } + if (!x45_25_PMOO) + { + w.writeBytes((atInt8*)"PMOOCNST\x00", 9); + } + if (x45_26_VMD1) + { + w.writeBytes((atInt8*)"VMD1CNST\x01", 9); + } + if (x45_27_VMD2) + { + w.writeBytes((atInt8*)"VMD2CNST\x01", 9); + } + if (x45_28_VMD3) + { + w.writeBytes((atInt8*)"VMD3CNST\x01", 9); + } + if (x45_29_VMD4) + { + w.writeBytes((atInt8*)"VMD4CNST\x01", 9); + } + if (x45_30_CIND) + { + w.writeBytes((atInt8*)"CINDCNST\x01", 9); + } + if (x45_31_OPTS) + { + w.writeBytes((atInt8*)"OPTSCNST\x01", 9); + } + if (x30_30_ORNT) + { + w.writeBytes((atInt8*)"ORNTCNST\x01", 9); + } + if (x30_31_RSOP) + { + w.writeBytes((atInt8*)"RSOPCNST\x01", 9); + } + if (x48_MBSP) + { + w.writeBytes((atInt8*)"MBSP", 4); + x48_MBSP.write(w); + } + if (x4c_SIZE) + { + w.writeBytes((atInt8*)"SIZE", 4); + x4c_SIZE.write(w); + } + if (x50_ROTA) + { + w.writeBytes((atInt8*)"ROTA", 4); + x50_ROTA.write(w); + } + if (x54_TEXR) + { + w.writeBytes((atInt8*)"TEXR", 4); + x54_TEXR.write(w); + } + if (x58_TIND) + { + w.writeBytes((atInt8*)"TIND", 4); + x58_TIND.write(w); + } + if (x5c_PMDL) + { + w.writeBytes((atInt8*)"PMDL", 4); + x5c_PMDL.write(w); + } + if (x6c_PMOP) + { + w.writeBytes((atInt8*)"PMOP", 4); + x6c_PMOP.write(w); + } + if (x70_PMRT) + { + w.writeBytes((atInt8*)"PMRT", 4); + x70_PMRT.write(w); + } + if (x74_PMSC) + { + w.writeBytes((atInt8*)"PMSC", 4); + x74_PMSC.write(w); + } + if (x78_PMCL) + { + w.writeBytes((atInt8*)"PMCL", 4); + x78_PMCL.write(w); + } + if (x7c_VEL1) + { + w.writeBytes((atInt8*)"VEL1", 4); + x7c_VEL1.write(w); + } + if (x80_VEL2) + { + w.writeBytes((atInt8*)"VEL2", 4); + x80_VEL2.write(w); + } + if (x84_VEL3) + { + w.writeBytes((atInt8*)"VEL3", 4); + x84_VEL3.write(w); + } + if (x88_VEL4) + { + w.writeBytes((atInt8*)"VEL4", 4); + x88_VEL4.write(w); + } + if (x8c_ICTS) + { + w.writeBytes((atInt8*)"ICTS", 4); + x8c_ICTS.write(w); + } + if (x9c_NCSY) + { + w.writeBytes((atInt8*)"NCSY", 4); + x9c_NCSY.write(w); + } + if (xa0_CSSD) + { + w.writeBytes((atInt8*)"CSSD", 4); + xa0_CSSD.write(w); + } + if (xa4_IDTS) + { + w.writeBytes((atInt8*)"IDTS", 4); + xa4_IDTS.write(w); + } + if (xb4_NDSY) + { + w.writeBytes((atInt8*)"NDSY", 4); + xb4_NDSY.write(w); + } + if (xb8_IITS) + { + w.writeBytes((atInt8*)"IITS", 4); + xb8_IITS.write(w); + } + if (xc8_PISY) + { + w.writeBytes((atInt8*)"PISY", 4); + xc8_PISY.write(w); + } + if (xcc_SISY) + { + w.writeBytes((atInt8*)"SISY", 4); + xcc_SISY.write(w); + } + if (xd0_KSSM) + { + w.writeBytes((atInt8*)"KSSM", 4); + xd0_KSSM.write(w); + } + if (xd4_SSWH) + { + w.writeBytes((atInt8*)"SSWH", 4); + xd4_SSWH.write(w); + } + if (xd8_SELC) + { + w.writeBytes((atInt8*)"SELC", 4); + xd8_SELC.write(w); + } + if (xe4_SSSD) + { + w.writeBytes((atInt8*)"SSSD", 4); + xe4_SSSD.write(w); + } + if (xe8_SSPO) + { + w.writeBytes((atInt8*)"SSPO", 4); + xe8_SSPO.write(w); + } + if (xf8_SESD) + { + w.writeBytes((atInt8*)"SESD", 4); + xf8_SESD.write(w); + } + if (xfc_SEPO) + { + w.writeBytes((atInt8*)"SEPO", 4); + xfc_SEPO.write(w); + } + if (xec_PMLC) + { + w.writeBytes((atInt8*)"PMLC", 4); + xec_PMLC.write(w); + } + if (x100_LTYP) + { + w.writeBytes((atInt8*)"LTYP", 4); + x100_LTYP.write(w); + } + if (x104_LCLR) + { + w.writeBytes((atInt8*)"LCLR", 4); + x104_LCLR.write(w); + } + if (x108_LINT) + { + w.writeBytes((atInt8*)"LINT", 4); + x108_LINT.write(w); + } + if (x10c_LOFF) + { + w.writeBytes((atInt8*)"LOFF", 4); + x10c_LOFF.write(w); + } + if (x110_LDIR) + { + w.writeBytes((atInt8*)"LDIR", 4); + x110_LDIR.write(w); + } + if (x114_LFOT) + { + w.writeBytes((atInt8*)"LFOT", 4); + x114_LFOT.write(w); + } + if (x118_LFOR) + { + w.writeBytes((atInt8*)"LFOR", 4); + x118_LFOR.write(w); + } + if (x11c_LSLA) + { + w.writeBytes((atInt8*)"LSLA", 4); + x11c_LSLA.write(w); + } + if (x10c_ADV1) + { + w.writeBytes((atInt8*)"ADV1", 4); + x10c_ADV1.write(w); + } + if (x110_ADV2) + { + w.writeBytes((atInt8*)"ADV2", 4); + x110_ADV2.write(w); + } + if (x114_ADV3) + { + w.writeBytes((atInt8*)"ADV3", 4); + x114_ADV3.write(w); + } + if (x118_ADV4) + { + w.writeBytes((atInt8*)"ADV4", 4); + x118_ADV4.write(w); + } + if (x11c_ADV5) + { + w.writeBytes((atInt8*)"ADV5", 4); + x11c_ADV5.write(w); + } + if (x120_ADV6) + { + w.writeBytes((atInt8*)"ADV6", 4); + x120_ADV6.write(w); + } + if (x124_ADV7) + { + w.writeBytes((atInt8*)"ADV7", 4); + x124_ADV7.write(w); + } + if (x128_ADV8) + { + w.writeBytes((atInt8*)"ADV8", 4); + x128_ADV8.write(w); + } +} + +template struct GPSM; +template struct GPSM; + +template +bool ExtractGPSM(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath) +{ + FILE* fp = HECL::Fopen(outPath.getAbsolutePath().c_str(), _S("w")); + if (fp) + { + GPSM gpsm; + gpsm.read(rs); + gpsm.toYAMLFile(fp); + fclose(fp); + return true; + } + return false; +} +template bool ExtractGPSM(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath); +template bool ExtractGPSM(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath); + +template +bool WriteGPSM(const GPSM& gpsm, const HECL::ProjectPath& outPath) +{ + Athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) + return false; + gpsm.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i=0 ; i<32-rem ; ++i) + w.writeBytes((atInt8*)"\xff", 1); + return true; +} +template bool WriteGPSM(const GPSM& gpsm, const HECL::ProjectPath& outPath); +template bool WriteGPSM(const GPSM& gpsm, const HECL::ProjectPath& outPath); + +} +} diff --git a/DataSpec/DNACommon/PART.hpp b/DataSpec/DNACommon/PART.hpp index 1f0abf3ce..3b968349a 100644 --- a/DataSpec/DNACommon/PART.hpp +++ b/DataSpec/DNACommon/PART.hpp @@ -107,1552 +107,18 @@ struct GPSM : BigYAML x45_25_PMOO = true; } - void read(Athena::io::YAMLDocReader& r) - { - for (const auto& elem : r.getCurNode()->m_mapChildren) - { - if (elem.first.size() < 4) - { - LogModule.report(LogVisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); - continue; - } - - r.enterSubRecord(elem.first.c_str()); - switch (*reinterpret_cast(elem.first.data())) - { - case SBIG('PMCL'): - x78_PMCL.read(r); - break; - case SBIG('LFOR'): - x118_LFOR.read(r); - break; - case SBIG('IDTS'): - xa4_IDTS.read(r); - break; - case SBIG('EMTR'): - x40_EMTR.read(r); - break; - case SBIG('COLR'): - x30_COLR.read(r); - break; - case SBIG('CIND'): - x45_30_CIND = r.readBool(nullptr); - break; - case SBIG('AAPH'): - x44_26_AAPH = r.readBool(nullptr); - break; - case SBIG('CSSD'): - xa0_CSSD.read(r); - break; - case SBIG('GRTE'): - x2c_GRTE.read(r); - break; - case SBIG('FXLL'): - x44_25_FXLL = r.readBool(nullptr); - break; - case SBIG('ICTS'): - x8c_ICTS.read(r); - break; - case SBIG('KSSM'): - xd0_KSSM.read(r); - break; - case SBIG('ILOC'): - x38_ILOC.read(r); - break; - case SBIG('IITS'): - xb8_IITS.read(r); - break; - case SBIG('IVEC'): - x3c_IVEC.read(r); - break; - case SBIG('LDIR'): - x110_LDIR.read(r); - break; - case SBIG('LCLR'): - x104_LCLR.read(r); - break; - case SBIG('LENG'): - x20_LENG.read(r); - break; - case SBIG('MAXP'): - x28_MAXP.read(r); - break; - case SBIG('LOFF'): - x10c_LOFF.read(r); - break; - case SBIG('LINT'): - x108_LINT.read(r); - break; - case SBIG('LINE'): - x44_24_LINE = r.readBool(nullptr); - break; - case SBIG('LFOT'): - x114_LFOT.read(r); - break; - case SBIG('LIT_'): - x44_29_LIT_ = r.readBool(nullptr); - break; - case SBIG('LTME'): - x34_LTME.read(r); - break; - case SBIG('LSLA'): - x11c_LSLA.read(r); - break; - case SBIG('LTYP'): - x100_LTYP.read(r); - break; - case SBIG('NDSY'): - xb4_NDSY.read(r); - break; - case SBIG('MBSP'): - x48_MBSP.read(r); - break; - case SBIG('MBLR'): - x44_30_MBLR = r.readBool(nullptr); - break; - case SBIG('NCSY'): - x9c_NCSY.read(r); - break; - case SBIG('PISY'): - xc8_PISY.read(r); - break; - case SBIG('OPTS'): - x45_31_OPTS = r.readBool(nullptr); - break; - case SBIG('PMAB'): - x44_31_PMAB = r.readBool(nullptr); - break; - case SBIG('SESD'): - xf8_SESD.read(r); - break; - case SBIG('SEPO'): - xfc_SEPO.read(r); - break; - case SBIG('PSLT'): - xc_PSLT.read(r); - break; - case SBIG('PMSC'): - x74_PMSC.read(r); - break; - case SBIG('PMOP'): - x6c_PMOP.read(r); - break; - case SBIG('PMDL'): - x5c_PMDL.read(r); - break; - case SBIG('PMRT'): - x70_PMRT.read(r); - break; - case SBIG('POFS'): - x18_POFS.read(r); - break; - case SBIG('PMUS'): - x45_24_PMUS = r.readBool(nullptr); - break; - case SBIG('PSIV'): - x0_PSIV.read(r); - break; - case SBIG('ROTA'): - x50_ROTA.read(r); - break; - case SBIG('PSVM'): - x4_PSVM.read(r); - break; - case SBIG('PSTS'): - x14_PSTS.read(r); - break; - case SBIG('PSOV'): - x8_PSOV.read(r); - break; - case SBIG('PSWT'): - x10_PSWT.read(r); - break; - case SBIG('PMLC'): - xec_PMLC.read(r); - break; - case SBIG('SEED'): - x1c_SEED.read(r); - break; - case SBIG('PMOO'): - x45_25_PMOO = r.readBool(nullptr); - break; - case SBIG('SSSD'): - xe4_SSSD.read(r); - break; - case SBIG('SORT'): - x44_28_SORT = r.readBool(nullptr); - break; - case SBIG('SIZE'): - x4c_SIZE.read(r); - break; - case SBIG('SISY'): - xcc_SISY.read(r); - break; - case SBIG('SSPO'): - xe8_SSPO.read(r); - break; - case SBIG('TEXR'): - x54_TEXR.read(r); - break; - case SBIG('SSWH'): - xd4_SSWH.read(r); - break; - case SBIG('TIND'): - x58_TIND.read(r); - break; - case SBIG('VMD4'): - x45_29_VMD4 = r.readBool(nullptr); - break; - case SBIG('VMD3'): - x45_28_VMD3 = r.readBool(nullptr); - break; - case SBIG('VMD2'): - x45_27_VMD2 = r.readBool(nullptr); - break; - case SBIG('VMD1'): - x45_26_VMD1 = r.readBool(nullptr); - break; - case SBIG('VEL4'): - x88_VEL4.read(r); - break; - case SBIG('VEL3'): - x84_VEL3.read(r); - break; - case SBIG('VEL2'): - x80_VEL2.read(r); - break; - case SBIG('VEL1'): - x7c_VEL1.read(r); - break; - case SBIG('ZBUF'): - x44_27_ZBUF = r.readBool(nullptr); - break; - case SBIG('WIDT'): - x24_WIDT.read(r); - break; - case SBIG('ORNT'): - x30_30_ORNT = r.readBool(nullptr); - break; - case SBIG('RSOP'): - x30_31_RSOP = r.readBool(nullptr); - break; - case SBIG('ADV1'): - x10c_ADV1.read(r); - break; - case SBIG('ADV2'): - x110_ADV2.read(r); - break; - case SBIG('ADV3'): - x114_ADV3.read(r); - break; - case SBIG('ADV4'): - x118_ADV4.read(r); - break; - case SBIG('ADV5'): - x11c_ADV5.read(r); - break; - case SBIG('ADV6'): - x120_ADV6.read(r); - break; - case SBIG('ADV7'): - x124_ADV7.read(r); - break; - case SBIG('SELC'): - xd8_SELC.read(r); - break; - default: - break; - } - r.leaveSubRecord(); - } - } - void write(Athena::io::YAMLDocWriter& w) const - { - if (x0_PSIV) - { - w.enterSubRecord("PSIV"); - x0_PSIV.write(w); - w.leaveSubRecord(); - } - if (x4_PSVM) - { - w.enterSubRecord("PSVM"); - x4_PSVM.write(w); - w.leaveSubRecord(); - } - if (x8_PSOV) - { - w.enterSubRecord("PSOV"); - x8_PSOV.write(w); - w.leaveSubRecord(); - } - if (xc_PSLT) - { - w.enterSubRecord("PSLT"); - xc_PSLT.write(w); - w.leaveSubRecord(); - } - if (x10_PSWT) - { - w.enterSubRecord("PSWT"); - x10_PSWT.write(w); - w.leaveSubRecord(); - } - if (x14_PSTS) - { - w.enterSubRecord("PSTS"); - x14_PSTS.write(w); - w.leaveSubRecord(); - } - if (x18_POFS) - { - w.enterSubRecord("POFS"); - x18_POFS.write(w); - w.leaveSubRecord(); - } - if (x1c_SEED) - { - w.enterSubRecord("SEED"); - x1c_SEED.write(w); - w.leaveSubRecord(); - } - if (x20_LENG) - { - w.enterSubRecord("LENG"); - x20_LENG.write(w); - w.leaveSubRecord(); - } - if (x24_WIDT) - { - w.enterSubRecord("WIDT"); - x24_WIDT.write(w); - w.leaveSubRecord(); - } - if (x28_MAXP) - { - w.enterSubRecord("MAXP"); - x28_MAXP.write(w); - w.leaveSubRecord(); - } - if (x2c_GRTE) - { - w.enterSubRecord("GRTE"); - x2c_GRTE.write(w); - w.leaveSubRecord(); - } - if (x30_COLR) - { - w.enterSubRecord("COLR"); - x30_COLR.write(w); - w.leaveSubRecord(); - } - if (x34_LTME) - { - w.enterSubRecord("LTME"); - x34_LTME.write(w); - w.leaveSubRecord(); - } - if (x38_ILOC) - { - w.enterSubRecord("ILOC"); - x38_ILOC.write(w); - w.leaveSubRecord(); - } - if (x3c_IVEC) - { - w.enterSubRecord("IVEC"); - x3c_IVEC.write(w); - w.leaveSubRecord(); - } - if (x40_EMTR) - { - w.enterSubRecord("EMTR"); - x40_EMTR.write(w); - w.leaveSubRecord(); - } - if (x44_24_LINE) - w.writeBool("LINE", true); - if (x44_25_FXLL) - w.writeBool("FXLL", true); - if (x44_26_AAPH) - w.writeBool("AAPH", true); - if (x44_27_ZBUF) - w.writeBool("ZBUF", true); - if (x44_28_SORT) - w.writeBool("SORT", true); - if (x44_29_LIT_) - w.writeBool("LIT_", true); - if (x44_30_MBLR) - w.writeBool("MBLR", true); - if (x44_31_PMAB) - w.writeBool("PMAB", true); - if (x45_24_PMUS) - w.writeBool("PMUS", true); - if (!x45_25_PMOO) - w.writeBool("PMOO", false); - if (x45_26_VMD1) - w.writeBool("VMD1", true); - if (x45_27_VMD2) - w.writeBool("VMD2", true); - if (x45_28_VMD3) - w.writeBool("VMD3", true); - if (x45_29_VMD4) - w.writeBool("VMD4", true); - if (x45_30_CIND) - w.writeBool("CIND", true); - if (x45_31_OPTS) - w.writeBool("OPTS", true); - if (x30_30_ORNT) - w.writeBool("ORNT", true); - if (x30_31_RSOP) - w.writeBool("RSOP", true); - if (x48_MBSP) - { - w.enterSubRecord("MPSB"); - x48_MBSP.write(w); - w.leaveSubRecord(); - } - if (x4c_SIZE) - { - w.enterSubRecord("SIZE"); - x4c_SIZE.write(w); - w.leaveSubRecord(); - } - if (x50_ROTA) - { - w.enterSubRecord("ROTA"); - x50_ROTA.write(w); - w.leaveSubRecord(); - } - if (x54_TEXR) - { - w.enterSubRecord("TEXR"); - x54_TEXR.write(w); - w.leaveSubRecord(); - } - if (x58_TIND) - { - w.enterSubRecord("TIND"); - x58_TIND.write(w); - w.leaveSubRecord(); - } - if (x5c_PMDL) - { - w.enterSubRecord("PMDL"); - x5c_PMDL.write(w); - w.leaveSubRecord(); - } - if (x6c_PMOP) - { - w.enterSubRecord("PMOP"); - x6c_PMOP.write(w); - w.leaveSubRecord(); - } - if (x70_PMRT) - { - w.enterSubRecord("PMRT"); - x70_PMRT.write(w); - w.leaveSubRecord(); - } - if (x74_PMSC) - { - w.enterSubRecord("PMSC"); - x74_PMSC.write(w); - w.leaveSubRecord(); - } - if (x78_PMCL) - { - w.enterSubRecord("PMCL"); - x78_PMCL.write(w); - w.leaveSubRecord(); - } - if (x7c_VEL1) - { - w.enterSubRecord("VEL1"); - x7c_VEL1.write(w); - w.leaveSubRecord(); - } - if (x80_VEL2) - { - w.enterSubRecord("VEL2"); - x80_VEL2.write(w); - w.leaveSubRecord(); - } - if (x84_VEL3) - { - w.enterSubRecord("VEL3"); - x84_VEL3.write(w); - w.leaveSubRecord(); - } - if (x88_VEL4) - { - w.enterSubRecord("VEL4"); - x88_VEL4.write(w); - w.leaveSubRecord(); - } - if (x8c_ICTS) - { - w.enterSubRecord("ICTS"); - x8c_ICTS.write(w); - w.leaveSubRecord(); - } - if (x9c_NCSY) - { - w.enterSubRecord("NCSY"); - x9c_NCSY.write(w); - w.leaveSubRecord(); - } - if (xa0_CSSD) - { - w.enterSubRecord("CSSD"); - xa0_CSSD.write(w); - w.leaveSubRecord(); - } - if (xa4_IDTS) - { - w.enterSubRecord("IDTS"); - xa4_IDTS.write(w); - w.leaveSubRecord(); - } - if (xb4_NDSY) - { - w.enterSubRecord("NDSY"); - xb4_NDSY.write(w); - w.leaveSubRecord(); - } - if (xb8_IITS) - { - w.enterSubRecord("IITS"); - xb8_IITS.write(w); - w.leaveSubRecord(); - } - if (xc8_PISY) - { - w.enterSubRecord("PISY"); - xc8_PISY.write(w); - w.leaveSubRecord(); - } - if (xcc_SISY) - { - w.enterSubRecord("SISY"); - xcc_SISY.write(w); - w.leaveSubRecord(); - } - if (xd0_KSSM) - { - w.enterSubRecord("KSSM"); - xd0_KSSM.write(w); - w.leaveSubRecord(); - } - if (xd4_SSWH) - { - w.enterSubRecord("SSWH"); - xd4_SSWH.write(w); - w.leaveSubRecord(); - } - if (xd8_SELC) - { - w.enterSubRecord("SELC"); - xd8_SELC.write(w); - w.leaveSubRecord(); - } - if (xe4_SSSD) - { - w.enterSubRecord("SSSD"); - xe4_SSSD.write(w); - w.leaveSubRecord(); - } - if (xe8_SSPO) - { - w.enterSubRecord("SSPO"); - xe8_SSPO.write(w); - w.leaveSubRecord(); - } - if (xf8_SESD) - { - w.enterSubRecord("SESD"); - xf8_SESD.write(w); - w.leaveSubRecord(); - } - if (xfc_SEPO) - { - w.enterSubRecord("SEPO"); - xfc_SEPO.write(w); - w.leaveSubRecord(); - } - if (xec_PMLC) - { - w.enterSubRecord("PMLC"); - xec_PMLC.write(w); - w.leaveSubRecord(); - } - if (x100_LTYP) - { - w.enterSubRecord("LTYP"); - x100_LTYP.write(w); - w.leaveSubRecord(); - } - if (x104_LCLR) - { - w.enterSubRecord("LCLR"); - x104_LCLR.write(w); - w.leaveSubRecord(); - } - if (x108_LINT) - { - w.enterSubRecord("LINT"); - x108_LINT.write(w); - w.leaveSubRecord(); - } - if (x10c_LOFF) - { - w.enterSubRecord("LOFF"); - x10c_LOFF.write(w); - w.leaveSubRecord(); - } - if (x110_LDIR) - { - w.enterSubRecord("LDIR"); - x110_LDIR.write(w); - w.leaveSubRecord(); - } - if (x114_LFOT) - { - w.enterSubRecord("LFOT"); - x114_LFOT.write(w); - w.leaveSubRecord(); - } - if (x118_LFOR) - { - w.enterSubRecord("LFOR"); - x118_LFOR.write(w); - w.leaveSubRecord(); - } - if (x11c_LSLA) - { - w.enterSubRecord("LSLA"); - x11c_LSLA.write(w); - w.leaveSubRecord(); - } - if (x10c_ADV1) - { - w.enterSubRecord("ADV1"); - x10c_ADV1.write(w); - w.leaveSubRecord(); - } - if (x110_ADV2) - { - w.enterSubRecord("ADV2"); - x110_ADV2.write(w); - w.leaveSubRecord(); - } - if (x114_ADV3) - { - w.enterSubRecord("ADV3"); - x114_ADV3.write(w); - w.leaveSubRecord(); - } - if (x118_ADV4) - { - w.enterSubRecord("ADV4"); - x118_ADV4.write(w); - w.leaveSubRecord(); - } - if (x11c_ADV5) - { - w.enterSubRecord("ADV5"); - x11c_ADV5.write(w); - w.leaveSubRecord(); - } - if (x120_ADV6) - { - w.enterSubRecord("ADV6"); - x120_ADV6.write(w); - w.leaveSubRecord(); - } - if (x124_ADV7) - { - w.enterSubRecord("ADV7"); - x124_ADV7.write(w); - w.leaveSubRecord(); - } - if (x128_ADV8) - { - w.enterSubRecord("ADV8"); - x128_ADV8.write(w); - w.leaveSubRecord(); - } - } - size_t binarySize(size_t __isz) const - { - __isz += 4; - if (x0_PSIV) - __isz = x0_PSIV.binarySize(__isz + 4); - if (x4_PSVM) - __isz = x4_PSVM.binarySize(__isz + 4); - if (x8_PSOV) - __isz = x8_PSOV.binarySize(__isz + 4); - if (xc_PSLT) - __isz = xc_PSLT.binarySize(__isz + 4); - if (x10_PSWT) - __isz = x10_PSWT.binarySize(__isz + 4); - if (x14_PSTS) - __isz = x14_PSTS.binarySize(__isz + 4); - if (x18_POFS) - __isz = x18_POFS.binarySize(__isz + 4); - if (x1c_SEED) - __isz = x1c_SEED.binarySize(__isz + 4); - if (x20_LENG) - __isz = x20_LENG.binarySize(__isz + 4); - if (x24_WIDT) - __isz = x24_WIDT.binarySize(__isz + 4); - if (x28_MAXP) - __isz = x28_MAXP.binarySize(__isz + 4); - if (x2c_GRTE) - __isz = x2c_GRTE.binarySize(__isz + 4); - if (x30_COLR) - __isz = x30_COLR.binarySize(__isz + 4); - if (x34_LTME) - __isz = x34_LTME.binarySize(__isz + 4); - if (x38_ILOC) - __isz = x38_ILOC.binarySize(__isz + 4); - if (x3c_IVEC) - __isz = x3c_IVEC.binarySize(__isz + 4); - if (x40_EMTR) - __isz = x40_EMTR.binarySize(__isz + 4); - if (x44_24_LINE) - __isz += 9; - if (x44_25_FXLL) - __isz += 9; - if (x44_26_AAPH) - __isz += 9; - if (x44_27_ZBUF) - __isz += 9; - if (x44_28_SORT) - __isz += 9; - if (x44_29_LIT_) - __isz += 9; - if (x44_30_MBLR) - __isz += 9; - if (x44_31_PMAB) - __isz += 9; - if (x45_24_PMUS) - __isz += 9; - if (!x45_25_PMOO) - __isz += 9; - if (x45_26_VMD1) - __isz += 9; - if (x45_27_VMD2) - __isz += 9; - if (x45_28_VMD3) - __isz += 9; - if (x45_29_VMD4) - __isz += 9; - if (x45_30_CIND) - __isz += 9; - if (x45_31_OPTS) - __isz += 9; - if (x30_30_ORNT) - __isz += 9; - if (x30_31_RSOP) - __isz += 9; - if (x48_MBSP) - __isz = x48_MBSP.binarySize(__isz + 4); - if (x4c_SIZE) - __isz = x4c_SIZE.binarySize(__isz + 4); - if (x50_ROTA) - __isz = x50_ROTA.binarySize(__isz + 4); - if (x54_TEXR) - __isz = x54_TEXR.binarySize(__isz + 4); - if (x58_TIND) - __isz = x58_TIND.binarySize(__isz + 4); - if (x5c_PMDL) - __isz = x5c_PMDL.binarySize(__isz + 4); - if (x6c_PMOP) - __isz = x6c_PMOP.binarySize(__isz + 4); - if (x70_PMRT) - __isz = x70_PMRT.binarySize(__isz + 4); - if (x74_PMSC) - __isz = x74_PMSC.binarySize(__isz + 4); - if (x78_PMCL) - __isz = x78_PMCL.binarySize(__isz + 4); - if (x7c_VEL1) - __isz = x7c_VEL1.binarySize(__isz + 4); - if (x80_VEL2) - __isz = x80_VEL2.binarySize(__isz + 4); - if (x84_VEL3) - __isz = x84_VEL3.binarySize(__isz + 4); - if (x88_VEL4) - __isz = x88_VEL4.binarySize(__isz + 4); - if (x8c_ICTS) - __isz = x8c_ICTS.binarySize(__isz + 4); - if (x9c_NCSY) - __isz = x9c_NCSY.binarySize(__isz + 4); - if (xa0_CSSD) - __isz = xa0_CSSD.binarySize(__isz + 4); - if (xa4_IDTS) - __isz = xa4_IDTS.binarySize(__isz + 4); - if (xb4_NDSY) - __isz = xb4_NDSY.binarySize(__isz + 4); - if (xb8_IITS) - __isz = xb8_IITS.binarySize(__isz + 4); - if (xc8_PISY) - __isz = xc8_PISY.binarySize(__isz + 4); - if (xcc_SISY) - __isz = xcc_SISY.binarySize(__isz + 4); - if (xd0_KSSM) - __isz = xd0_KSSM.binarySize(__isz + 4); - if (xd4_SSWH) - __isz = xd4_SSWH.binarySize(__isz + 4); - if (xd8_SELC) - __isz = xd8_SELC.binarySize(__isz + 4); - if (xe4_SSSD) - __isz = xe4_SSSD.binarySize(__isz + 4); - if (xe8_SSPO) - __isz = xe8_SSPO.binarySize(__isz + 4); - if (xf8_SESD) - __isz = xf8_SESD.binarySize(__isz + 4); - if (xfc_SEPO) - __isz = xfc_SEPO.binarySize(__isz + 4); - if (xec_PMLC) - __isz = xec_PMLC.binarySize(__isz + 4); - if (x100_LTYP) - __isz = x100_LTYP.binarySize(__isz + 4); - if (x104_LCLR) - __isz = x104_LCLR.binarySize(__isz + 4); - if (x108_LINT) - __isz = x108_LINT.binarySize(__isz + 4); - if (x10c_LOFF) - __isz = x10c_LOFF.binarySize(__isz + 4); - if (x110_LDIR) - __isz = x110_LDIR.binarySize(__isz + 4); - if (x114_LFOT) - __isz = x114_LFOT.binarySize(__isz + 4); - if (x118_LFOR) - __isz = x118_LFOR.binarySize(__isz + 4); - if (x11c_LSLA) - __isz = x11c_LSLA.binarySize(__isz + 4); - if (x10c_ADV1) - __isz = x10c_ADV1.binarySize(__isz + 4); - if (x110_ADV2) - __isz = x110_ADV2.binarySize(__isz + 4); - if (x114_ADV3) - __isz = x114_ADV3.binarySize(__isz + 4); - if (x118_ADV4) - __isz = x118_ADV4.binarySize(__isz + 4); - if (x11c_ADV5) - __isz = x11c_ADV5.binarySize(__isz + 4); - if (x120_ADV6) - __isz = x120_ADV6.binarySize(__isz + 4); - if (x124_ADV7) - __isz = x124_ADV7.binarySize(__isz + 4); - if (x128_ADV8) - __isz = x128_ADV8.binarySize(__isz + 4); - return __isz; - } - void read(Athena::io::IStreamReader& r) - { - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - if (clsId != SBIG('GPSM')) - { - LogModule.report(LogVisor::Warning, "non GPSM provided to GPSM parser"); - return; - } - r.readBytesToBuf(&clsId, 4); - while (clsId != SBIG('_END')) - { - switch (clsId) - { - case SBIG('PMCL'): - x78_PMCL.read(r); - break; - case SBIG('LFOR'): - x118_LFOR.read(r); - break; - case SBIG('IDTS'): - xa4_IDTS.read(r); - break; - case SBIG('EMTR'): - x40_EMTR.read(r); - break; - case SBIG('COLR'): - x30_COLR.read(r); - break; - case SBIG('CIND'): - r.readUint32Big(); - x45_30_CIND = r.readBool(); - break; - case SBIG('AAPH'): - r.readUint32Big(); - x44_26_AAPH = r.readBool(); - break; - case SBIG('CSSD'): - xa0_CSSD.read(r); - break; - case SBIG('GRTE'): - x2c_GRTE.read(r); - break; - case SBIG('FXLL'): - r.readUint32Big(); - x44_25_FXLL = r.readBool(); - break; - case SBIG('ICTS'): - x8c_ICTS.read(r); - break; - case SBIG('KSSM'): - xd0_KSSM.read(r); - break; - case SBIG('ILOC'): - x38_ILOC.read(r); - break; - case SBIG('IITS'): - xb8_IITS.read(r); - break; - case SBIG('IVEC'): - x3c_IVEC.read(r); - break; - case SBIG('LDIR'): - x110_LDIR.read(r); - break; - case SBIG('LCLR'): - x104_LCLR.read(r); - break; - case SBIG('LENG'): - x20_LENG.read(r); - break; - case SBIG('MAXP'): - x28_MAXP.read(r); - break; - case SBIG('LOFF'): - x10c_LOFF.read(r); - break; - case SBIG('LINT'): - x108_LINT.read(r); - break; - case SBIG('LINE'): - r.readUint32Big(); - x44_24_LINE = r.readBool(); - break; - case SBIG('LFOT'): - x114_LFOT.read(r); - break; - case SBIG('LIT_'): - r.readUint32Big(); - x44_29_LIT_ = r.readBool(); - break; - case SBIG('LTME'): - x34_LTME.read(r); - break; - case SBIG('LSLA'): - x11c_LSLA.read(r); - break; - case SBIG('LTYP'): - x100_LTYP.read(r); - break; - case SBIG('NDSY'): - xb4_NDSY.read(r); - break; - case SBIG('MBSP'): - x48_MBSP.read(r); - break; - case SBIG('MBLR'): - r.readUint32Big(); - x44_30_MBLR = r.readBool(); - break; - case SBIG('NCSY'): - x9c_NCSY.read(r); - break; - case SBIG('PISY'): - xc8_PISY.read(r); - break; - case SBIG('OPTS'): - r.readUint32Big(); - x45_31_OPTS = r.readBool(); - break; - case SBIG('PMAB'): - r.readUint32Big(); - x44_31_PMAB = r.readBool(); - break; - case SBIG('SESD'): - xf8_SESD.read(r); - break; - case SBIG('SEPO'): - xfc_SEPO.read(r); - break; - case SBIG('PSLT'): - xc_PSLT.read(r); - break; - case SBIG('PMSC'): - x74_PMSC.read(r); - break; - case SBIG('PMOP'): - x6c_PMOP.read(r); - break; - case SBIG('PMDL'): - x5c_PMDL.read(r); - break; - case SBIG('PMRT'): - x70_PMRT.read(r); - break; - case SBIG('POFS'): - x18_POFS.read(r); - break; - case SBIG('PMUS'): - r.readUint32Big(); - x45_24_PMUS = r.readBool(); - break; - case SBIG('PSIV'): - x0_PSIV.read(r); - break; - case SBIG('ROTA'): - x50_ROTA.read(r); - break; - case SBIG('PSVM'): - x4_PSVM.read(r); - break; - case SBIG('PSTS'): - x14_PSTS.read(r); - break; - case SBIG('PSOV'): - x8_PSOV.read(r); - break; - case SBIG('PSWT'): - x10_PSWT.read(r); - break; - case SBIG('PMLC'): - xec_PMLC.read(r); - break; - case SBIG('SEED'): - x1c_SEED.read(r); - break; - case SBIG('PMOO'): - r.readUint32Big(); - x45_25_PMOO = r.readBool(); - break; - case SBIG('SSSD'): - xe4_SSSD.read(r); - break; - case SBIG('SORT'): - r.readUint32Big(); - x44_28_SORT = r.readBool(); - break; - case SBIG('SIZE'): - x4c_SIZE.read(r); - break; - case SBIG('SISY'): - xcc_SISY.read(r); - break; - case SBIG('SSPO'): - xe8_SSPO.read(r); - break; - case SBIG('TEXR'): - x54_TEXR.read(r); - break; - case SBIG('SSWH'): - xd4_SSWH.read(r); - break; - case SBIG('TIND'): - x58_TIND.read(r); - break; - case SBIG('VMD4'): - r.readUint32Big(); - x45_29_VMD4 = r.readBool(); - break; - case SBIG('VMD3'): - r.readUint32Big(); - x45_28_VMD3 = r.readBool(); - break; - case SBIG('VMD2'): - r.readUint32Big(); - x45_27_VMD2 = r.readBool(); - break; - case SBIG('VMD1'): - r.readUint32Big(); - x45_26_VMD1 = r.readBool(); - break; - case SBIG('VEL4'): - x88_VEL4.read(r); - break; - case SBIG('VEL3'): - x84_VEL3.read(r); - break; - case SBIG('VEL2'): - x80_VEL2.read(r); - break; - case SBIG('VEL1'): - x7c_VEL1.read(r); - break; - case SBIG('ZBUF'): - r.readUint32Big(); - x44_27_ZBUF = r.readBool(); - break; - case SBIG('WIDT'): - x24_WIDT.read(r); - break; - case SBIG('ORNT'): - r.readUint32Big(); - x30_30_ORNT = r.readBool(); - break; - case SBIG('RSOP'): - r.readUint32Big(); - x30_31_RSOP = r.readBool(); - break; - case SBIG('ADV1'): - x10c_ADV1.read(r); - break; - case SBIG('ADV2'): - x110_ADV2.read(r); - break; - case SBIG('ADV3'): - x114_ADV3.read(r); - break; - case SBIG('ADV4'): - x118_ADV4.read(r); - break; - case SBIG('ADV5'): - x11c_ADV5.read(r); - break; - case SBIG('ADV6'): - x120_ADV6.read(r); - break; - case SBIG('ADV7'): - x124_ADV7.read(r); - break; - case SBIG('ADV8'): - x128_ADV8.read(r); - break; - case SBIG('SELC'): - xd8_SELC.read(r); - break; - default: - LogModule.report(LogVisor::FatalError, "Unknown GPSM class %.4s @%" PRIi64, &clsId, r.position()); - break; - } - r.readBytesToBuf(&clsId, 4); - } - } - void write(Athena::io::IStreamWriter& w) const - { - w.writeBytes((atInt8*)"GPSM", 4); - if (x0_PSIV) - { - w.writeBytes((atInt8*)"PSIV", 4); - x0_PSIV.write(w); - } - if (x4_PSVM) - { - w.writeBytes((atInt8*)"PSVM", 4); - x4_PSVM.write(w); - } - if (x8_PSOV) - { - w.writeBytes((atInt8*)"PSOV", 4); - x8_PSOV.write(w); - } - if (xc_PSLT) - { - w.writeBytes((atInt8*)"PSLT", 4); - xc_PSLT.write(w); - } - if (x10_PSWT) - { - w.writeBytes((atInt8*)"PSWT", 4); - x10_PSWT.write(w); - } - if (x14_PSTS) - { - w.writeBytes((atInt8*)"PSTS", 4); - x14_PSTS.write(w); - } - if (x18_POFS) - { - w.writeBytes((atInt8*)"POFS", 4); - x18_POFS.write(w); - } - if (x1c_SEED) - { - w.writeBytes((atInt8*)"SEED", 4); - x1c_SEED.write(w); - } - if (x20_LENG) - { - w.writeBytes((atInt8*)"LENG", 4); - x20_LENG.write(w); - } - if (x24_WIDT) - { - w.writeBytes((atInt8*)"WIDT", 4); - x24_WIDT.write(w); - } - if (x28_MAXP) - { - w.writeBytes((atInt8*)"MAXP", 4); - x28_MAXP.write(w); - } - if (x2c_GRTE) - { - w.writeBytes((atInt8*)"GRTE", 4); - x2c_GRTE.write(w); - } - if (x30_COLR) - { - w.writeBytes((atInt8*)"COLR", 4); - x30_COLR.write(w); - } - if (x34_LTME) - { - w.writeBytes((atInt8*)"LTME", 4); - x34_LTME.write(w); - } - if (x38_ILOC) - { - w.writeBytes((atInt8*)"ILOC", 4); - x38_ILOC.write(w); - } - if (x3c_IVEC) - { - w.writeBytes((atInt8*)"IVEC", 4); - x3c_IVEC.write(w); - } - if (x40_EMTR) - { - w.writeBytes((atInt8*)"EMTR", 4); - x40_EMTR.write(w); - } - if (x44_24_LINE) - { - w.writeBytes((atInt8*)"LINECNST\x01", 9); - } - if (x44_25_FXLL) - { - w.writeBytes((atInt8*)"FXLLCNST\x01", 9); - } - if (x44_26_AAPH) - { - w.writeBytes((atInt8*)"AAPHCNST\x01", 9); - } - if (x44_27_ZBUF) - { - w.writeBytes((atInt8*)"ZBUFCNST\x01", 9); - } - if (x44_28_SORT) - { - w.writeBytes((atInt8*)"SORTCNST\x01", 9); - } - if (x44_29_LIT_) - { - w.writeBytes((atInt8*)"LIT_CNST\x01", 9); - } - if (x44_30_MBLR) - { - w.writeBytes((atInt8*)"MBLRCNST\x01", 9); - } - if (x44_31_PMAB) - { - w.writeBytes((atInt8*)"PMABCNST\x01", 9); - } - if (x45_24_PMUS) - { - w.writeBytes((atInt8*)"PMUSCNST\x01", 9); - } - if (!x45_25_PMOO) - { - w.writeBytes((atInt8*)"PMOOCNST\x00", 9); - } - if (x45_26_VMD1) - { - w.writeBytes((atInt8*)"VMD1CNST\x01", 9); - } - if (x45_27_VMD2) - { - w.writeBytes((atInt8*)"VMD2CNST\x01", 9); - } - if (x45_28_VMD3) - { - w.writeBytes((atInt8*)"VMD3CNST\x01", 9); - } - if (x45_29_VMD4) - { - w.writeBytes((atInt8*)"VMD4CNST\x01", 9); - } - if (x45_30_CIND) - { - w.writeBytes((atInt8*)"CINDCNST\x01", 9); - } - if (x45_31_OPTS) - { - w.writeBytes((atInt8*)"OPTSCNST\x01", 9); - } - if (x30_30_ORNT) - { - w.writeBytes((atInt8*)"ORNTCNST\x01", 9); - } - if (x30_31_RSOP) - { - w.writeBytes((atInt8*)"RSOPCNST\x01", 9); - } - if (x48_MBSP) - { - w.writeBytes((atInt8*)"MBSP", 4); - x48_MBSP.write(w); - } - if (x4c_SIZE) - { - w.writeBytes((atInt8*)"SIZE", 4); - x4c_SIZE.write(w); - } - if (x50_ROTA) - { - w.writeBytes((atInt8*)"ROTA", 4); - x50_ROTA.write(w); - } - if (x54_TEXR) - { - w.writeBytes((atInt8*)"TEXR", 4); - x54_TEXR.write(w); - } - if (x58_TIND) - { - w.writeBytes((atInt8*)"TIND", 4); - x58_TIND.write(w); - } - if (x5c_PMDL) - { - w.writeBytes((atInt8*)"PMDL", 4); - x5c_PMDL.write(w); - } - if (x6c_PMOP) - { - w.writeBytes((atInt8*)"PMOP", 4); - x6c_PMOP.write(w); - } - if (x70_PMRT) - { - w.writeBytes((atInt8*)"PMRT", 4); - x70_PMRT.write(w); - } - if (x74_PMSC) - { - w.writeBytes((atInt8*)"PMSC", 4); - x74_PMSC.write(w); - } - if (x78_PMCL) - { - w.writeBytes((atInt8*)"PMCL", 4); - x78_PMCL.write(w); - } - if (x7c_VEL1) - { - w.writeBytes((atInt8*)"VEL1", 4); - x7c_VEL1.write(w); - } - if (x80_VEL2) - { - w.writeBytes((atInt8*)"VEL2", 4); - x80_VEL2.write(w); - } - if (x84_VEL3) - { - w.writeBytes((atInt8*)"VEL3", 4); - x84_VEL3.write(w); - } - if (x88_VEL4) - { - w.writeBytes((atInt8*)"VEL4", 4); - x88_VEL4.write(w); - } - if (x8c_ICTS) - { - w.writeBytes((atInt8*)"ICTS", 4); - x8c_ICTS.write(w); - } - if (x9c_NCSY) - { - w.writeBytes((atInt8*)"NCSY", 4); - x9c_NCSY.write(w); - } - if (xa0_CSSD) - { - w.writeBytes((atInt8*)"CSSD", 4); - xa0_CSSD.write(w); - } - if (xa4_IDTS) - { - w.writeBytes((atInt8*)"IDTS", 4); - xa4_IDTS.write(w); - } - if (xb4_NDSY) - { - w.writeBytes((atInt8*)"NDSY", 4); - xb4_NDSY.write(w); - } - if (xb8_IITS) - { - w.writeBytes((atInt8*)"IITS", 4); - xb8_IITS.write(w); - } - if (xc8_PISY) - { - w.writeBytes((atInt8*)"PISY", 4); - xc8_PISY.write(w); - } - if (xcc_SISY) - { - w.writeBytes((atInt8*)"SISY", 4); - xcc_SISY.write(w); - } - if (xd0_KSSM) - { - w.writeBytes((atInt8*)"KSSM", 4); - xd0_KSSM.write(w); - } - if (xd4_SSWH) - { - w.writeBytes((atInt8*)"SSWH", 4); - xd4_SSWH.write(w); - } - if (xd8_SELC) - { - w.writeBytes((atInt8*)"SELC", 4); - xd8_SELC.write(w); - } - if (xe4_SSSD) - { - w.writeBytes((atInt8*)"SSSD", 4); - xe4_SSSD.write(w); - } - if (xe8_SSPO) - { - w.writeBytes((atInt8*)"SSPO", 4); - xe8_SSPO.write(w); - } - if (xf8_SESD) - { - w.writeBytes((atInt8*)"SESD", 4); - xf8_SESD.write(w); - } - if (xfc_SEPO) - { - w.writeBytes((atInt8*)"SEPO", 4); - xfc_SEPO.write(w); - } - if (xec_PMLC) - { - w.writeBytes((atInt8*)"PMLC", 4); - xec_PMLC.write(w); - } - if (x100_LTYP) - { - w.writeBytes((atInt8*)"LTYP", 4); - x100_LTYP.write(w); - } - if (x104_LCLR) - { - w.writeBytes((atInt8*)"LCLR", 4); - x104_LCLR.write(w); - } - if (x108_LINT) - { - w.writeBytes((atInt8*)"LINT", 4); - x108_LINT.write(w); - } - if (x10c_LOFF) - { - w.writeBytes((atInt8*)"LOFF", 4); - x10c_LOFF.write(w); - } - if (x110_LDIR) - { - w.writeBytes((atInt8*)"LDIR", 4); - x110_LDIR.write(w); - } - if (x114_LFOT) - { - w.writeBytes((atInt8*)"LFOT", 4); - x114_LFOT.write(w); - } - if (x118_LFOR) - { - w.writeBytes((atInt8*)"LFOR", 4); - x118_LFOR.write(w); - } - if (x11c_LSLA) - { - w.writeBytes((atInt8*)"LSLA", 4); - x11c_LSLA.write(w); - } - if (x10c_ADV1) - { - w.writeBytes((atInt8*)"ADV1", 4); - x10c_ADV1.write(w); - } - if (x110_ADV2) - { - w.writeBytes((atInt8*)"ADV2", 4); - x110_ADV2.write(w); - } - if (x114_ADV3) - { - w.writeBytes((atInt8*)"ADV3", 4); - x114_ADV3.write(w); - } - if (x118_ADV4) - { - w.writeBytes((atInt8*)"ADV4", 4); - x118_ADV4.write(w); - } - if (x11c_ADV5) - { - w.writeBytes((atInt8*)"ADV5", 4); - x11c_ADV5.write(w); - } - if (x120_ADV6) - { - w.writeBytes((atInt8*)"ADV6", 4); - x120_ADV6.write(w); - } - if (x124_ADV7) - { - w.writeBytes((atInt8*)"ADV7", 4); - x124_ADV7.write(w); - } - if (x128_ADV8) - { - w.writeBytes((atInt8*)"ADV8", 4); - x128_ADV8.write(w); - } - } + void read(Athena::io::YAMLDocReader& r); + void write(Athena::io::YAMLDocWriter& w) const; + size_t binarySize(size_t __isz) const; + void read(Athena::io::IStreamReader& r); + void write(Athena::io::IStreamWriter& w) const; }; template -bool ExtractGPSM(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath) -{ - FILE* fp = HECL::Fopen(outPath.getAbsolutePath().c_str(), _S("w")); - if (fp) - { - GPSM gpsm; - gpsm.read(rs); - gpsm.toYAMLFile(fp); - fclose(fp); - return true; - } - return false; -} +bool ExtractGPSM(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath); template -bool WriteGPSM(const GPSM& gpsm, const HECL::ProjectPath& outPath) -{ - Athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); - if (w.hasError()) - return false; - gpsm.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeBytes((atInt8*)"\xff", 1); - return true; -} +bool WriteGPSM(const GPSM& gpsm, const HECL::ProjectPath& outPath); } }