#include "CRSC.hpp" namespace DataSpec::DNAParticle { static const std::vector GeneratorTypes = { SBIG('NODP'), SBIG('DEFS'), SBIG('CRTS'), SBIG('MTLS'), SBIG('GRAS'), SBIG('ICEE'), SBIG('GOOO'), SBIG('WODS'), SBIG('WATR'), SBIG('1MUD'), SBIG('1LAV'), SBIG('1SAN'), SBIG('1PRJ'), SBIG('DCHR'), SBIG('DCHS'), SBIG('DCSH'), SBIG('DENM'), SBIG('DESP'), SBIG('DESH'), SBIG('BTLE'), SBIG('WASP'), SBIG('TALP'), SBIG('PTGM'), SBIG('SPIR'), SBIG('FPIR'), SBIG('FFLE'), SBIG('PARA'), SBIG('BMON'), SBIG('BFLR'), SBIG('PBOS'), SBIG('IBOS'), SBIG('1SVA'), SBIG('1RPR'), SBIG('1MTR'), SBIG('1PDS'), SBIG('1FLB'), SBIG('1DRN'), SBIG('1MRE'), SBIG('CHOZ'), SBIG('JZAP'), SBIG('1ISE'), SBIG('1BSE'), SBIG('1ATB'), SBIG('1ATA'), SBIG('BTSP'), SBIG('WWSP'), SBIG('TASP'), SBIG('TGSP'), SBIG('SPSP'), SBIG('FPSP'), SBIG('FFSP'), SBIG('PSSP'), SBIG('BMSP'), SBIG('BFSP'), SBIG('PBSP'), SBIG('IBSP'), SBIG('2SVA'), SBIG('2RPR'), SBIG('2MTR'), SBIG('2PDS'), SBIG('2FLB'), SBIG('2DRN'), SBIG('2MRE'), SBIG('CHSP'), SBIG('JZSP'), SBIG('3ISE'), SBIG('3BSE'), SBIG('3ATB'), SBIG('3ATA'), SBIG('BTSH'), SBIG('WWSH'), SBIG('TASH'), SBIG('TGSH'), SBIG('SPSH'), SBIG('FPSH'), SBIG('FFSH'), SBIG('PSSH'), SBIG('BMSH'), SBIG('BFSH'), SBIG('PBSH'), SBIG('IBSH'), SBIG('3SVA'), SBIG('3RPR'), SBIG('3MTR'), SBIG('3PDS'), SBIG('3FLB'), SBIG('3DRN'), SBIG('3MRE'), SBIG('CHSH'), SBIG('JZSH'), SBIG('5ISE'), SBIG('5BSE'), SBIG('5ATB'), SBIG('5ATA')}; static const std::vector SFXTypes = { SBIG('DSFX'), SBIG('CSFX'), SBIG('MSFX'), SBIG('GRFX'), SBIG('NSFX'), SBIG('DSFX'), SBIG('CSFX'), SBIG('MSFX'), SBIG('GRFX'), SBIG('ICFX'), SBIG('GOFX'), SBIG('WSFX'), SBIG('WTFX'), SBIG('2MUD'), SBIG('2LAV'), SBIG('2SAN'), SBIG('2PRJ'), SBIG('DCFX'), SBIG('DSFX'), SBIG('DSHX'), SBIG('DEFX'), SBIG('ESFX'), SBIG('SHFX'), SBIG('BEFX'), SBIG('WWFX'), SBIG('TAFX'), SBIG('GTFX'), SBIG('SPFX'), SBIG('FPFX'), SBIG('FFFX'), SBIG('PAFX'), SBIG('BMFX'), SBIG('BFFX'), SBIG('PBFX'), SBIG('IBFX'), SBIG('4SVA'), SBIG('4RPR'), SBIG('4MTR'), SBIG('4PDS'), SBIG('4FLB'), SBIG('4DRN'), SBIG('4MRE'), SBIG('CZFX'), SBIG('JZAS'), SBIG('2ISE'), SBIG('2BSE'), SBIG('2ATB'), SBIG('2ATA'), SBIG('BSFX'), SBIG('WSFX'), SBIG('TSFX'), SBIG('GSFX'), SBIG('SSFX'), SBIG('FSFX'), SBIG('SFFX'), SBIG('PSFX'), SBIG('MSFX'), SBIG('SBFX'), SBIG('PBSX'), SBIG('IBSX'), SBIG('5SVA'), SBIG('5RPR'), SBIG('5MTR'), SBIG('5PDS'), SBIG('5FLB'), SBIG('5DRN'), SBIG('5MRE'), SBIG('CSFX'), SBIG('JZPS'), SBIG('4ISE'), SBIG('4BSE'), SBIG('4ATB'), SBIG('4ATA'), SBIG('BHFX'), SBIG('WHFX'), SBIG('THFX'), SBIG('GHFX'), SBIG('SHFX'), SBIG('FHFX'), SBIG('HFFX'), SBIG('PHFX'), SBIG('MHFX'), SBIG('HBFX'), SBIG('PBHX'), SBIG('IBHX'), SBIG('6SVA'), SBIG('6RPR'), SBIG('6MTR'), SBIG('6PDS'), SBIG('6FLB'), SBIG('6DRN'), SBIG('6MRE'), SBIG('CHFX'), SBIG('JZHS'), SBIG('6ISE'), SBIG('6BSE'), SBIG('6ATB'), SBIG('6ATA'), }; static const std::vector DecalTypes = {SBIG('NCDL'), SBIG('DDCL'), SBIG('CODL'), SBIG('MEDL'), SBIG('GRDL'), SBIG('ICDL'), SBIG('GODL'), SBIG('WODL'), SBIG('WTDL'), SBIG('3MUD'), SBIG('3LAV'), SBIG('3SAN'), SBIG('CHDL'), SBIG('ENDL')}; template <> const char* CRSM::DNAType() { return "CRSM"; } template <> const char* CRSM::DNAType() { return "CRSM"; } template void CRSM::_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; } if (auto rec = r.enterSubRecord(elem.first.c_str())) { FourCC clsId(elem.first.c_str()); auto gen = std::find_if(GeneratorTypes.begin(), GeneratorTypes.end(), [&clsId](const FourCC& other) -> bool { return clsId == other; }); if (gen != GeneratorTypes.end()) { x0_generators[clsId].read(r); continue; } auto sfx = std::find_if(SFXTypes.begin(), SFXTypes.end(), [&clsId](const FourCC& other) -> bool { return clsId == other; }); if (sfx != SFXTypes.end()) { x10_sfx[clsId] = r.readInt32(clsId.toString().c_str()); continue; } auto decal = std::find_if(DecalTypes.begin(), DecalTypes.end(), [&clsId](const FourCC& other) -> bool { return clsId == other; }); if (decal != DecalTypes.end()) { x20_decals[clsId].read(r); continue; } if (clsId == SBIG('RNGE')) x30_RNGE = r.readFloat(nullptr); else if (clsId == SBIG('FOFF')) x34_FOFF = r.readFloat(nullptr); } } } template void CRSM::_write(athena::io::YAMLDocWriter& w) const { for (const auto& pair : x0_generators) if (pair.second) if (auto rec = w.enterSubRecord(pair.first.toString().c_str())) pair.second.write(w); for (const auto& pair : x10_sfx) if (pair.second != ~0) w.writeUint32(pair.first.toString().c_str(), pair.second); for (const auto& pair : x20_decals) if (pair.second) if (auto rec = w.enterSubRecord(pair.first.toString().c_str())) pair.second.write(w); if (x30_RNGE != 50.f) w.writeFloat("RNGE", x30_RNGE); if (x34_FOFF != 0.2f) w.writeFloat("FOFF", x34_FOFF); } template void CRSM::_binarySize(size_t& __isz) const { __isz += 4; for (const auto& pair : x0_generators) { if (pair.second) { __isz += 4; pair.second.binarySize(__isz); } } for (const auto& pair : x10_sfx) { if (pair.second != ~0) __isz += 12; } for (const auto& pair : x20_decals) { if (pair.second) { __isz += 4; pair.second.binarySize(__isz); } } if (x30_RNGE != 50.f) __isz += 12; if (x34_FOFF != 0.2f) __isz += 12; } template void CRSM::_read(athena::io::IStreamReader& r) { uint32_t clsId; r.readBytesToBuf(&clsId, 4); if (clsId != SBIG('CRSM')) { LogModule.report(logvisor::Warning, "non CRSM provided to CRSM parser"); return; } while (clsId != SBIG('_END')) { r.readBytesToBuf(&clsId, 4); auto gen = std::find_if(GeneratorTypes.begin(), GeneratorTypes.end(), [&clsId](const FourCC& other) -> bool { return clsId == other; }); if (gen != GeneratorTypes.end()) { x0_generators[clsId].read(r); continue; } auto sfx = std::find_if(SFXTypes.begin(), SFXTypes.end(), [&clsId](const FourCC& other) -> bool { return clsId == other; }); if (sfx != SFXTypes.end()) { uint32_t fcc; r.readBytesToBuf(&fcc, 4); if (fcc != SBIG('NONE')) x10_sfx[clsId] = r.readInt32Big(); else x10_sfx[clsId] = ~0; continue; } auto decal = std::find_if(DecalTypes.begin(), DecalTypes.end(), [&clsId](const FourCC& other) -> bool { return clsId == other; }); if (decal != DecalTypes.end()) { x20_decals[clsId].read(r); continue; } if (clsId == SBIG('RNGE')) { r.readUint32(); x30_RNGE = r.readFloatBig(); continue; } if (clsId == SBIG('FOFF')) { r.readUint32(); x34_FOFF = r.readFloatBig(); continue; } if (clsId != SBIG('_END')) LogModule.report(logvisor::Fatal, "Unknown CRSM class %.4s @%" PRIi64, &clsId, r.position()); } } template void CRSM::_write(athena::io::IStreamWriter& w) const { w.writeBytes("CRSM", 4); for (const auto& pair : x0_generators) { w.writeBytes(pair.first.getChars(), 4); pair.second.write(w); } for (const auto& pair : x10_sfx) { w.writeBytes(pair.first.getChars(), 4); if (pair.second != ~0) { w.writeBytes("CNST", 4); w.writeUint32Big(pair.second); } else { w.writeBytes("NONE", 4); } } for (const auto& pair : x20_decals) { w.writeBytes(pair.first.getChars(), 4); pair.second.write(w); } if (x30_RNGE != 50.f) { w.writeBytes("RNGECNST", 8); w.writeFloatBig(x30_RNGE); } if (x34_FOFF != 0.2f) { w.writeBytes("FOFFCNST", 8); w.writeFloatBig(x34_FOFF); } w.writeBytes("_END", 4); } AT_SUBSPECIALIZE_DNA_YAML(CRSM) AT_SUBSPECIALIZE_DNA_YAML(CRSM) template void CRSM::gatherDependencies(std::vector& pathsOut) const { for (const auto& p : x0_generators) g_curSpec->flattenDependencies(p.second.id, pathsOut); for (const auto& p : x20_decals) g_curSpec->flattenDependencies(p.second.id, pathsOut); } template CRSM::CRSM() : x30_RNGE(50.f), x34_FOFF(0.2f) { for (const auto& sfx : SFXTypes) x10_sfx[sfx] = ~0; } template struct CRSM; template struct CRSM; template bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { athena::io::FileWriter writer(outPath.getAbsolutePath()); if (writer.isOpen()) { CRSM crsm; crsm.read(rs); athena::io::ToYAMLStream(crsm, writer); return true; } return false; } template bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool WriteCRSM(const CRSM& crsm, const hecl::ProjectPath& outPath) { athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); if (w.hasError()) return false; crsm.write(w); int64_t rem = w.position() % 32; if (rem) for (int64_t i = 0; i < 32 - rem; ++i) w.writeUByte(0xff); return true; } template bool WriteCRSM(const CRSM& crsm, const hecl::ProjectPath& outPath); template bool WriteCRSM(const CRSM& crsm, const hecl::ProjectPath& outPath); } // namespace DataSpec::DNAParticle