diff --git a/DataSpec/DNACommon/CMakeLists.txt b/DataSpec/DNACommon/CMakeLists.txt index ac32507de..e316add8e 100644 --- a/DataSpec/DNACommon/CMakeLists.txt +++ b/DataSpec/DNACommon/CMakeLists.txt @@ -17,7 +17,8 @@ add_library(DNACommon ANCS.hpp ANIM.hpp ANIM.cpp PART.hpp PART.cpp - SWHC.hpp + SWHC.hpp SWHC.cpp + CRSC.hpp CRSC.cpp ELSC.hpp ELSC.cpp ParticleCommon.cpp FONT.hpp FONT.cpp diff --git a/DataSpec/DNACommon/CRSC.cpp b/DataSpec/DNACommon/CRSC.cpp new file mode 100644 index 000000000..b0e077448 --- /dev/null +++ b/DataSpec/DNACommon/CRSC.cpp @@ -0,0 +1,338 @@ +#include "CRSC.hpp" + +namespace DataSpec +{ +namespace DNAParticle +{ +static const std::vector GeneratorTypes = +{ + 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('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 +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; + } + + 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); + r.leaveSubRecord(); + 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()); + r.leaveSubRecord(); + 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); + r.leaveSubRecord(); + continue; + } + if (clsId == SBIG('RNGE')) + x30_RNGE = r.readFloat(nullptr); + else if (clsId == SBIG('FOFF')) + x34_FOFF = r.readFloat(nullptr); + + r.leaveSubRecord(); + } +} + +template +void CRSM::write(athena::io::YAMLDocWriter& w) const +{ + for (const auto& pair : x0_generators) + { + if (pair.second) + { + w.enterSubRecord(pair.first.toString().c_str()); + pair.second.write(w); + w.leaveSubRecord(); + } + } + + 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) + { + w.enterSubRecord(pair.first.toString().c_str()); + pair.second.write(w); + w.leaveSubRecord(); + } + } + + if (x30_RNGE != 50.f) + w.writeFloat("RNGE", x30_RNGE); + if (x34_FOFF != 0.2f) + w.writeFloat("FOFF", x34_FOFF); +} + +template +size_t CRSM::binarySize(size_t __isz) const +{ + __isz += 4; + for (const auto& pair : x0_generators) + { + if (pair.second) + __isz = pair.second.binarySize(__isz + 4); + } + for (const auto& pair : x10_sfx) + { + if (pair.second != ~0) + __isz += 12; + } + + for (const auto& pair : x20_decals) + { + if (pair.second) + __isz = pair.second.binarySize(__isz + 4); + } + + if (x30_RNGE != 50.f) + __isz += 12; + if (x34_FOFF != 0.2f) + __isz += 12; + return __isz; +} + +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) + { + if (pair.second) + { + w.writeBytes(pair.first.toString().c_str(), 4); + pair.second.write(w); + } + } + + for (const auto& pair : x10_sfx) + { + if (pair.second != ~0) + { + w.writeBytes(pair.first.toString().c_str(), 4); + w.writeUint32Big(pair.second); + } + } + + for (const auto& pair : x20_decals) + { + if (pair.second) + { + w.writeBytes(pair.first.toString().c_str(), 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); +} + +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) +{ + FILE* fp = hecl::Fopen(outPath.getAbsolutePath().c_str(), _S("w")); + if (fp) + { + CRSM crsm; + crsm.read(rs); + crsm.toYAMLFile(fp); + fclose(fp); + 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.writeBytes((atInt8*)"\xff", 1); + return true; +} +template bool WriteCRSM(const CRSM& crsm, const hecl::ProjectPath& outPath); +template bool WriteCRSM(const CRSM& crsm, const hecl::ProjectPath& outPath); +} +} + diff --git a/DataSpec/DNACommon/CRSC.hpp b/DataSpec/DNACommon/CRSC.hpp new file mode 100644 index 000000000..3d8156d2b --- /dev/null +++ b/DataSpec/DNACommon/CRSC.hpp @@ -0,0 +1,40 @@ +#ifndef CRSC_HPP +#define CRSC_HPP + +#include "ParticleCommon.hpp" +#include "PAK.hpp" +#include "athena/FileWriter.hpp" +#include "optional.hpp" + +namespace DataSpec +{ +namespace DNAParticle +{ +template +struct CRSM : BigYAML +{ + static const char* DNAType() { return "CRSM"; } + const char* DNATypeV() const { return DNAType(); } + + std::unordered_map> x0_generators; + std::unordered_map x10_sfx; + std::unordered_map> x20_decals; + float x30_RNGE; + float x34_FOFF; + + 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; + + CRSM(); +}; +template +bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); + +template +bool WriteCRSM(const CRSM& crsm, const hecl::ProjectPath& outPath); +} +} +#endif // CRSC_HPP diff --git a/DataSpec/DNACommon/ELSC.cpp b/DataSpec/DNACommon/ELSC.cpp index d8c8c4e74..26c69cb20 100644 --- a/DataSpec/DNACommon/ELSC.cpp +++ b/DataSpec/DNACommon/ELSC.cpp @@ -441,6 +441,7 @@ void ELSM::write(athena::io::IStreamWriter& w) const w.writeBytes((atInt8*)"ZERY", 4); x70_ZERY.write(w); } + w.writeBytes("_END", 4); } template struct ELSM; diff --git a/DataSpec/DNACommon/PART.cpp b/DataSpec/DNACommon/PART.cpp index 9368414b9..945168d64 100644 --- a/DataSpec/DNACommon/PART.cpp +++ b/DataSpec/DNACommon/PART.cpp @@ -21,246 +21,246 @@ void GPSM::read(athena::io::YAMLDocReader& r) { case SBIG('PMCL'): x78_PMCL.read(r); - break; + break; case SBIG('LFOR'): x118_LFOR.read(r); - break; + break; case SBIG('IDTS'): xa4_IDTS.read(r); - break; + break; case SBIG('EMTR'): x40_EMTR.read(r); - break; + break; case SBIG('COLR'): x30_COLR.read(r); - break; + break; case SBIG('CIND'): x45_30_CIND = r.readBool(nullptr); - break; + break; case SBIG('AAPH'): x44_26_AAPH = r.readBool(nullptr); - break; + break; case SBIG('CSSD'): xa0_CSSD.read(r); - break; + break; case SBIG('GRTE'): x2c_GRTE.read(r); - break; + break; case SBIG('FXLL'): x44_25_FXLL = r.readBool(nullptr); - break; + break; case SBIG('ICTS'): x8c_ICTS.read(r); - break; + break; case SBIG('KSSM'): xd0_KSSM.read(r); - break; + break; case SBIG('ILOC'): x38_ILOC.read(r); - break; + break; case SBIG('IITS'): xb8_IITS.read(r); - break; + break; case SBIG('IVEC'): x3c_IVEC.read(r); - break; + break; case SBIG('LDIR'): x110_LDIR.read(r); - break; + break; case SBIG('LCLR'): x104_LCLR.read(r); - break; + break; case SBIG('LENG'): x20_LENG.read(r); - break; + break; case SBIG('MAXP'): x28_MAXP.read(r); - break; + break; case SBIG('LOFF'): x10c_LOFF.read(r); - break; + break; case SBIG('LINT'): x108_LINT.read(r); - break; + break; case SBIG('LINE'): x44_24_LINE = r.readBool(nullptr); - break; + break; case SBIG('LFOT'): x114_LFOT.read(r); - break; + break; case SBIG('LIT_'): x44_29_LIT_ = r.readBool(nullptr); - break; + break; case SBIG('LTME'): x34_LTME.read(r); - break; + break; case SBIG('LSLA'): x11c_LSLA.read(r); - break; + break; case SBIG('LTYP'): x100_LTYP.read(r); - break; + break; case SBIG('NDSY'): xb4_NDSY.read(r); - break; + break; case SBIG('MBSP'): x48_MBSP.read(r); - break; + break; case SBIG('MBLR'): x44_30_MBLR = r.readBool(nullptr); - break; + break; case SBIG('NCSY'): x9c_NCSY.read(r); - break; + break; case SBIG('PISY'): xc8_PISY.read(r); - break; + break; case SBIG('OPTS'): x45_31_OPTS = r.readBool(nullptr); - break; + break; case SBIG('PMAB'): x44_31_PMAB = r.readBool(nullptr); - break; + break; case SBIG('SESD'): xf8_SESD.read(r); - break; + break; case SBIG('SEPO'): xfc_SEPO.read(r); - break; + break; case SBIG('PSLT'): xc_PSLT.read(r); - break; + break; case SBIG('PMSC'): x74_PMSC.read(r); - break; + break; case SBIG('PMOP'): x6c_PMOP.read(r); - break; + break; case SBIG('PMDL'): x5c_PMDL.read(r); - break; + break; case SBIG('PMRT'): x70_PMRT.read(r); - break; + break; case SBIG('POFS'): x18_POFS.read(r); - break; + break; case SBIG('PMUS'): x45_24_PMUS = r.readBool(nullptr); - break; + break; case SBIG('PSIV'): x0_PSIV.read(r); - break; + break; case SBIG('ROTA'): x50_ROTA.read(r); - break; + break; case SBIG('PSVM'): x4_PSVM.read(r); - break; + break; case SBIG('PSTS'): x14_PSTS.read(r); - break; + break; case SBIG('PSOV'): x8_PSOV.read(r); - break; + break; case SBIG('PSWT'): x10_PSWT.read(r); - break; + break; case SBIG('PMLC'): xec_PMLC.read(r); - break; + break; case SBIG('SEED'): x1c_SEED.read(r); - break; + break; case SBIG('PMOO'): x45_25_PMOO = r.readBool(nullptr); - break; + break; case SBIG('SSSD'): xe4_SSSD.read(r); - break; + break; case SBIG('SORT'): x44_28_SORT = r.readBool(nullptr); - break; + break; case SBIG('SIZE'): x4c_SIZE.read(r); - break; + break; case SBIG('SISY'): xcc_SISY.read(r); - break; + break; case SBIG('SSPO'): xe8_SSPO.read(r); - break; + break; case SBIG('TEXR'): x54_TEXR.read(r); - break; + break; case SBIG('SSWH'): xd4_SSWH.read(r); - break; + break; case SBIG('TIND'): x58_TIND.read(r); - break; + break; case SBIG('VMD4'): x45_29_VMD4 = r.readBool(nullptr); - break; + break; case SBIG('VMD3'): x45_28_VMD3 = r.readBool(nullptr); - break; + break; case SBIG('VMD2'): x45_27_VMD2 = r.readBool(nullptr); - break; + break; case SBIG('VMD1'): x45_26_VMD1 = r.readBool(nullptr); - break; + break; case SBIG('VEL4'): x88_VEL4.read(r); - break; + break; case SBIG('VEL3'): x84_VEL3.read(r); - break; + break; case SBIG('VEL2'): x80_VEL2.read(r); - break; + break; case SBIG('VEL1'): x7c_VEL1.read(r); - break; + break; case SBIG('ZBUF'): x44_27_ZBUF = r.readBool(nullptr); - break; + break; case SBIG('WIDT'): x24_WIDT.read(r); - break; + break; case SBIG('ORNT'): x30_30_ORNT = r.readBool(nullptr); - break; + break; case SBIG('RSOP'): x30_31_RSOP = r.readBool(nullptr); - break; + break; case SBIG('ADV1'): x10c_ADV1.read(r); - break; + break; case SBIG('ADV2'): x110_ADV2.read(r); - break; + break; case SBIG('ADV3'): x114_ADV3.read(r); - break; + break; case SBIG('ADV4'): x118_ADV4.read(r); - break; + break; case SBIG('ADV5'): x11c_ADV5.read(r); - break; + break; case SBIG('ADV6'): x120_ADV6.read(r); - break; + break; case SBIG('ADV7'): x124_ADV7.read(r); - break; + break; case SBIG('SELC'): xd8_SELC.read(r); - break; + break; default: - break; + break; } r.leaveSubRecord(); } @@ -871,268 +871,268 @@ void GPSM::read(athena::io::IStreamReader& r) { case SBIG('PMCL'): x78_PMCL.read(r); - break; + break; case SBIG('LFOR'): x118_LFOR.read(r); - break; + break; case SBIG('IDTS'): xa4_IDTS.read(r); - break; + break; case SBIG('EMTR'): x40_EMTR.read(r); - break; + break; case SBIG('COLR'): x30_COLR.read(r); - break; + break; case SBIG('CIND'): r.readUint32Big(); x45_30_CIND = r.readBool(); - break; + break; case SBIG('AAPH'): r.readUint32Big(); x44_26_AAPH = r.readBool(); - break; + break; case SBIG('CSSD'): xa0_CSSD.read(r); - break; + break; case SBIG('GRTE'): x2c_GRTE.read(r); - break; + break; case SBIG('FXLL'): r.readUint32Big(); x44_25_FXLL = r.readBool(); - break; + break; case SBIG('ICTS'): x8c_ICTS.read(r); - break; + break; case SBIG('KSSM'): xd0_KSSM.read(r); - break; + break; case SBIG('ILOC'): x38_ILOC.read(r); - break; + break; case SBIG('IITS'): xb8_IITS.read(r); - break; + break; case SBIG('IVEC'): x3c_IVEC.read(r); - break; + break; case SBIG('LDIR'): x110_LDIR.read(r); - break; + break; case SBIG('LCLR'): x104_LCLR.read(r); - break; + break; case SBIG('LENG'): x20_LENG.read(r); - break; + break; case SBIG('MAXP'): x28_MAXP.read(r); - break; + break; case SBIG('LOFF'): x10c_LOFF.read(r); - break; + break; case SBIG('LINT'): x108_LINT.read(r); - break; + break; case SBIG('LINE'): r.readUint32Big(); x44_24_LINE = r.readBool(); - break; + break; case SBIG('LFOT'): x114_LFOT.read(r); - break; + break; case SBIG('LIT_'): r.readUint32Big(); x44_29_LIT_ = r.readBool(); - break; + break; case SBIG('LTME'): x34_LTME.read(r); - break; + break; case SBIG('LSLA'): x11c_LSLA.read(r); - break; + break; case SBIG('LTYP'): x100_LTYP.read(r); - break; + break; case SBIG('NDSY'): xb4_NDSY.read(r); - break; + break; case SBIG('MBSP'): x48_MBSP.read(r); - break; + break; case SBIG('MBLR'): r.readUint32Big(); x44_30_MBLR = r.readBool(); - break; + break; case SBIG('NCSY'): x9c_NCSY.read(r); - break; + break; case SBIG('PISY'): xc8_PISY.read(r); - break; + break; case SBIG('OPTS'): r.readUint32Big(); x45_31_OPTS = r.readBool(); - break; + break; case SBIG('PMAB'): r.readUint32Big(); x44_31_PMAB = r.readBool(); - break; + break; case SBIG('SESD'): xf8_SESD.read(r); - break; + break; case SBIG('SEPO'): xfc_SEPO.read(r); - break; + break; case SBIG('PSLT'): xc_PSLT.read(r); - break; + break; case SBIG('PMSC'): x74_PMSC.read(r); - break; + break; case SBIG('PMOP'): x6c_PMOP.read(r); - break; + break; case SBIG('PMDL'): x5c_PMDL.read(r); - break; + break; case SBIG('PMRT'): x70_PMRT.read(r); - break; + break; case SBIG('POFS'): x18_POFS.read(r); - break; + break; case SBIG('PMUS'): r.readUint32Big(); x45_24_PMUS = r.readBool(); - break; + break; case SBIG('PSIV'): x0_PSIV.read(r); - break; + break; case SBIG('ROTA'): x50_ROTA.read(r); - break; + break; case SBIG('PSVM'): x4_PSVM.read(r); - break; + break; case SBIG('PSTS'): x14_PSTS.read(r); - break; + break; case SBIG('PSOV'): x8_PSOV.read(r); - break; + break; case SBIG('PSWT'): x10_PSWT.read(r); - break; + break; case SBIG('PMLC'): xec_PMLC.read(r); - break; + break; case SBIG('SEED'): x1c_SEED.read(r); - break; + break; case SBIG('PMOO'): r.readUint32Big(); x45_25_PMOO = r.readBool(); - break; + break; case SBIG('SSSD'): xe4_SSSD.read(r); - break; + break; case SBIG('SORT'): r.readUint32Big(); x44_28_SORT = r.readBool(); - break; + break; case SBIG('SIZE'): x4c_SIZE.read(r); - break; + break; case SBIG('SISY'): xcc_SISY.read(r); - break; + break; case SBIG('SSPO'): xe8_SSPO.read(r); - break; + break; case SBIG('TEXR'): x54_TEXR.read(r); - break; + break; case SBIG('SSWH'): xd4_SSWH.read(r); - break; + break; case SBIG('TIND'): x58_TIND.read(r); - break; + break; case SBIG('VMD4'): r.readUint32Big(); x45_29_VMD4 = r.readBool(); - break; + break; case SBIG('VMD3'): r.readUint32Big(); x45_28_VMD3 = r.readBool(); - break; + break; case SBIG('VMD2'): r.readUint32Big(); x45_27_VMD2 = r.readBool(); - break; + break; case SBIG('VMD1'): r.readUint32Big(); x45_26_VMD1 = r.readBool(); - break; + break; case SBIG('VEL4'): x88_VEL4.read(r); - break; + break; case SBIG('VEL3'): x84_VEL3.read(r); - break; + break; case SBIG('VEL2'): x80_VEL2.read(r); - break; + break; case SBIG('VEL1'): x7c_VEL1.read(r); - break; + break; case SBIG('ZBUF'): r.readUint32Big(); x44_27_ZBUF = r.readBool(); - break; + break; case SBIG('WIDT'): x24_WIDT.read(r); - break; + break; case SBIG('ORNT'): r.readUint32Big(); x30_30_ORNT = r.readBool(); - break; + break; case SBIG('RSOP'): r.readUint32Big(); x30_31_RSOP = r.readBool(); - break; + break; case SBIG('ADV1'): x10c_ADV1.read(r); - break; + break; case SBIG('ADV2'): x110_ADV2.read(r); - break; + break; case SBIG('ADV3'): x114_ADV3.read(r); - break; + break; case SBIG('ADV4'): x118_ADV4.read(r); - break; + break; case SBIG('ADV5'): x11c_ADV5.read(r); - break; + break; case SBIG('ADV6'): x120_ADV6.read(r); - break; + break; case SBIG('ADV7'): x124_ADV7.read(r); - break; + break; case SBIG('ADV8'): x128_ADV8.read(r); - break; + break; case SBIG('SELC'): xd8_SELC.read(r); - break; + break; default: LogModule.report(logvisor::Fatal, "Unknown GPSM class %.4s @%" PRIi64, &clsId, r.position()); - break; + break; } r.readBytesToBuf(&clsId, 4); } @@ -1529,6 +1529,7 @@ void GPSM::write(athena::io::IStreamWriter& w) const w.writeBytes((atInt8*)"ADV8", 4); x128_ADV8.write(w); } + w.writeBytes("_END", 4); } template struct GPSM; diff --git a/DataSpec/DNACommon/SWHC.cpp b/DataSpec/DNACommon/SWHC.cpp new file mode 100644 index 000000000..9e550653a --- /dev/null +++ b/DataSpec/DNACommon/SWHC.cpp @@ -0,0 +1,578 @@ +#include "SWHC.hpp" + +namespace DataSpec +{ +namespace DNAParticle +{ + +template +void SWSH::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('PSLT'): + x0_PSLT.read(r); + break; + case SBIG('TIME'): + x4_TIME.read(r); + break; + case SBIG('LRAD'): + x8_LRAD.read(r); + break; + case SBIG('RRAD'): + xc_RRAD.read(r); + break; + case SBIG('LENG'): + x10_LENG.read(r); + break; + case SBIG('COLR'): + x14_COLR.read(r); + break; + case SBIG('SIDE'): + x18_SIDE.read(r); + break; + case SBIG('IROT'): + x1c_IROT.read(r); + break; + case SBIG('ROTM'): + x20_ROTM.read(r); + break; + case SBIG('POFS'): + x24_POFS.read(r); + break; + case SBIG('IVEL'): + x28_IVEL.read(r); + break; + case SBIG('NPOS'): + x2c_NPOS.read(r); + break; + case SBIG('VELM'): + x30_VELM.read(r); + break; + case SBIG('VLM2'): + x34_VLM2.read(r); + break; + case SBIG('SPLN'): + x38_SPLN.read(r); + break; + case SBIG('TEXR'): + x3c_TEXR.read(r); + break; + case SBIG('TSPN'): + x40_TSPN.read(r); + break; + case SBIG('LLRD'): + x44_24_LLRD = r.readBool(nullptr); + break; + case SBIG('CROS'): + x44_25_CROS = r.readBool(nullptr); + break; + case SBIG('VLS1'): + x44_26_VLS1 = r.readBool(nullptr); + break; + case SBIG('VLS2'): + x44_27_VLS2 = r.readBool(nullptr); + break; + case SBIG('SROT'): + x44_28_SROT = r.readBool(nullptr); + break; + case SBIG('WIRE'): + x44_29_WIRE = r.readBool(nullptr); + break; + case SBIG('TEXW'): + x44_30_TEXW = r.readBool(nullptr); + break; + case SBIG('AALP'): + x44_31_AALP = r.readBool(nullptr); + break; + case SBIG('ZBUF'): + x45_24_ZBUF = r.readBool(nullptr); + break; + case SBIG('ORNT'): + x45_25_ORNT = r.readBool(nullptr); + break; + case SBIG('CRND'): + x45_26_CRND = r.readBool(nullptr); + break; + } + + r.leaveSubRecord(); + } +} + +template +void SWSH::write(athena::io::YAMLDocWriter& w) const +{ + if (x0_PSLT) + { + w.enterSubRecord("PSLT"); + x0_PSLT.write(w); + w.leaveSubRecord(); + } + if (x4_TIME) + { + w.enterSubRecord("TIME"); + x4_TIME.write(w); + w.leaveSubRecord(); + } + if (x8_LRAD) + { + w.enterSubRecord("LRAD"); + x8_LRAD.write(w); + w.leaveSubRecord(); + } + if (xc_RRAD) + { + w.enterSubRecord("RRAD"); + xc_RRAD.write(w); + w.leaveSubRecord(); + } + if (x10_LENG) + { + w.enterSubRecord("LENG"); + x10_LENG.write(w); + w.leaveSubRecord(); + } + if (x14_COLR) + { + w.enterSubRecord("COLR"); + x14_COLR.write(w); + w.leaveSubRecord(); + } + if (x18_SIDE) + { + w.enterSubRecord("SIDE"); + x18_SIDE.write(w); + w.leaveSubRecord(); + } + if (x1c_IROT) + { + w.enterSubRecord("IROT"); + x1c_IROT.write(w); + w.leaveSubRecord(); + } + if (x20_ROTM) + { + w.enterSubRecord("ROTM"); + x20_ROTM.write(w); + w.leaveSubRecord(); + } + if (x24_POFS) + { + w.enterSubRecord("POFS"); + x24_POFS.write(w); + w.leaveSubRecord(); + } + if (x28_IVEL) + { + w.enterSubRecord("IVEL"); + x28_IVEL.write(w); + w.leaveSubRecord(); + } + if (x2c_NPOS) + { + w.enterSubRecord("NPOS"); + x2c_NPOS.write(w); + w.leaveSubRecord(); + } + if (x30_VELM) + { + w.enterSubRecord("VELM"); + x30_VELM.write(w); + w.leaveSubRecord(); + } + if (x34_VLM2) + { + w.enterSubRecord("VLM2"); + x34_VLM2.write(w); + w.leaveSubRecord(); + } + if (x38_SPLN) + { + w.enterSubRecord("SPLN"); + x38_SPLN.write(w); + w.leaveSubRecord(); + } + if (x3c_TEXR) + { + w.enterSubRecord("TEXR"); + x3c_TEXR.write(w); + w.leaveSubRecord(); + } + if (x40_TSPN) + { + w.enterSubRecord("TSPN"); + x40_TSPN.write(w); + w.leaveSubRecord(); + } + + if (x44_24_LLRD) + w.writeBool("LLRD", true); + if (!x44_25_CROS) + w.writeBool("CROS", false); + if (x44_26_VLS1) + w.writeBool("VLS1", true); + if (x44_27_VLS2) + w.writeBool("VLS2", true); + if (x44_28_SROT) + w.writeBool("SROT", true); + if (x44_29_WIRE) + w.writeBool("WIRE", true); + if (x44_30_TEXW) + w.writeBool("TEXW", true); + if (x44_31_AALP) + w.writeBool("AALP", true); + if (x45_24_ZBUF) + w.writeBool("ZBUF", true); + if (x45_25_ORNT) + w.writeBool("ORNT", true); + if (x45_26_CRND) + w.writeBool("CRND", true); +} + + +template +size_t SWSH::binarySize(size_t __isz) const +{ + __isz += 4; + if (x0_PSLT) + __isz = x0_PSLT.binarySize(__isz + 4); + if (x4_TIME) + __isz = x4_TIME.binarySize(__isz + 4); + if (x8_LRAD) + __isz = x8_LRAD.binarySize(__isz + 4); + if (xc_RRAD) + __isz = xc_RRAD.binarySize(__isz + 4); + if (x10_LENG) + __isz = x10_LENG.binarySize(__isz + 4); + if (x14_COLR) + __isz = x14_COLR.binarySize(__isz + 4); + if (x18_SIDE) + __isz = x18_SIDE.binarySize(__isz + 4); + if (x1c_IROT) + __isz = x1c_IROT.binarySize(__isz + 4); + if (x20_ROTM) + __isz = x20_ROTM.binarySize(__isz + 4); + if (x24_POFS) + __isz = x24_POFS.binarySize(__isz + 4); + if (x28_IVEL) + __isz = x28_IVEL.binarySize(__isz + 4); + if (x2c_NPOS) + __isz = x2c_NPOS.binarySize(__isz + 4); + if (x30_VELM) + __isz = x30_VELM.binarySize(__isz + 4); + if (x34_VLM2) + __isz = x34_VLM2.binarySize(__isz + 4); + if (x38_SPLN) + __isz = x38_SPLN.binarySize(__isz + 4); + if (x3c_TEXR) + __isz = x3c_TEXR.binarySize(__isz + 4); + if (x40_TSPN) + __isz = x40_TSPN.binarySize(__isz + 4); + if (x44_24_LLRD) + __isz += 9; + if (!x44_25_CROS) + __isz += 9; + if (x44_26_VLS1) + __isz += 9; + if (x44_27_VLS2) + __isz += 9; + if (x44_28_SROT) + __isz += 9; + if (x44_29_WIRE) + __isz += 9; + if (x44_30_TEXW) + __isz += 9; + if (x44_31_AALP) + __isz += 9; + if (x45_24_ZBUF) + __isz += 9; + if (x45_25_ORNT) + __isz += 9; + if (x45_26_CRND) + __isz += 9; + + return __isz; +} + +template +void SWSH::read(athena::io::IStreamReader& r) +{ + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId != SBIG('SWSH')) + { + LogModule.report(logvisor::Warning, "non SWSH provided to SWSH parser"); + return; + } + + r.readBytesToBuf(&clsId, 4); + while (clsId != SBIG('_END')) + { + switch(clsId) + { + case SBIG('PSLT'): + x0_PSLT.read(r); + break; + case SBIG('TIME'): + x4_TIME.read(r); + break; + case SBIG('LRAD'): + x8_LRAD.read(r); + break; + case SBIG('RRAD'): + xc_RRAD.read(r); + break; + case SBIG('LENG'): + x10_LENG.read(r); + break; + case SBIG('COLR'): + x14_COLR.read(r); + break; + case SBIG('SIDE'): + x18_SIDE.read(r); + break; + case SBIG('IROT'): + x1c_IROT.read(r); + break; + case SBIG('ROTM'): + x20_ROTM.read(r); + break; + case SBIG('POFS'): + x24_POFS.read(r); + break; + case SBIG('IVEL'): + x28_IVEL.read(r); + break; + case SBIG('NPOS'): + x2c_NPOS.read(r); + break; + case SBIG('VELM'): + x30_VELM.read(r); + break; + case SBIG('VLM2'): + x34_VLM2.read(r); + break; + case SBIG('SPLN'): + x38_SPLN.read(r); + break; + case SBIG('TEXR'): + x3c_TEXR.read(r); + break; + case SBIG('TSPN'): + x40_TSPN.read(r); + break; + case SBIG('LLRD'): + r.readUint32Big(); + x44_24_LLRD = r.readBool(); + break; + case SBIG('CROS'): + r.readUint32Big(); + x44_25_CROS = r.readBool(); + break; + case SBIG('VLS1'): + r.readUint32Big(); + x44_26_VLS1 = r.readBool(); + break; + case SBIG('VLS2'): + r.readUint32Big(); + x44_27_VLS2 = r.readBool(); + break; + case SBIG('SROT'): + r.readUint32Big(); + x44_28_SROT = r.readBool(); + break; + case SBIG('WIRE'): + r.readUint32Big(); + x44_29_WIRE = r.readBool(); + break; + case SBIG('TEXW'): + r.readUint32Big(); + x44_30_TEXW = r.readBool(); + break; + case SBIG('AALP'): + r.readUint32Big(); + x44_31_AALP = r.readBool(); + break; + case SBIG('ZBUF'): + r.readUint32Big(); + x45_24_ZBUF = r.readBool(); + break; + case SBIG('ORNT'): + r.readUint32Big(); + x45_25_ORNT = r.readBool(); + break; + case SBIG('CRND'): + r.readUint32Big(); + x45_26_CRND = r.readBool(); + break; + default: + LogModule.report(logvisor::Fatal, "Unknown SWSH class %.4s @%" PRIi64, &clsId, r.position()); + break; + } + r.readBytesToBuf(&clsId, 4); + } +} + +template +void SWSH::write(athena::io::IStreamWriter& w) const +{ + w.writeBytes((atInt8*)"SWSH", 4); + if (x0_PSLT) + { + w.writeBytes((atInt8*)"PSLT", 4); + x0_PSLT.write(w); + } + if (x4_TIME) + { + w.writeBytes((atInt8*)"TIME", 4); + x4_TIME.write(w); + } + if (x8_LRAD) + { + w.writeBytes((atInt8*)"LRAD", 4); + x8_LRAD.write(w); + } + if (xc_RRAD) + { + w.writeBytes((atInt8*)"RRAD", 4); + xc_RRAD.write(w); + } + if (x10_LENG) + { + w.writeBytes((atInt8*)"LENG", 4); + x10_LENG.write(w); + } + if (x14_COLR) + { + w.writeBytes((atInt8*)"COLR", 4); + x14_COLR.write(w); + } + if (x18_SIDE) + { + w.writeBytes((atInt8*)"SIDE", 4); + x18_SIDE.write(w); + } + if (x1c_IROT) + { + w.writeBytes((atInt8*)"IROT", 4); + x1c_IROT.write(w); + } + if (x20_ROTM) + { + w.writeBytes((atInt8*)"ROTM", 4); + x20_ROTM.write(w); + } + if (x24_POFS) + { + w.writeBytes((atInt8*)"POFS", 4); + x24_POFS.write(w); + } + if (x28_IVEL) + { + w.writeBytes((atInt8*)"IVEL", 4); + x28_IVEL.write(w); + } + if (x2c_NPOS) + { + w.writeBytes((atInt8*)"NPOS", 4); + x2c_NPOS.write(w); + } + if (x30_VELM) + { + w.writeBytes((atInt8*)"VELM", 4); + x30_VELM.write(w); + } + if (x34_VLM2) + { + w.writeBytes((atInt8*)"VLM2", 4); + x34_VLM2.write(w); + } + if (x38_SPLN) + { + w.writeBytes((atInt8*)"SPLN", 4); + x38_SPLN.write(w); + } + if (x3c_TEXR) + { + w.writeBytes((atInt8*)"TEXR", 4); + x3c_TEXR.write(w); + } + if (x40_TSPN) + { + w.writeBytes((atInt8*)"TSPN", 4); + x40_TSPN.write(w); + } + + if (x44_24_LLRD) + w.writeBytes("LLRDCNST\x01", 9); + if (!x44_25_CROS) + w.writeBytes("CROSCNST\x00", 9); + if (x44_26_VLS1) + w.writeBytes("VLS1CNST\x01", 9); + if (x44_27_VLS2) + w.writeBytes("VLS2CNST\x01", 9); + if (x44_28_SROT) + w.writeBytes("SROTCNST\x01", 9); + if (x44_29_WIRE) + w.writeBytes("WIRECNST\x01", 9); + if (x44_30_TEXW) + w.writeBytes("TEXWCNST\x01", 9); + if (x44_31_AALP) + w.writeBytes("AALPCNST\x01", 9); + if (x45_24_ZBUF) + w.writeBytes("ZBUFCNST\x01", 9); + if (x45_25_ORNT) + w.writeBytes("ORNTCNST\x01", 9); + if (x45_26_CRND) + w.writeBytes("CRNDCNST\x01", 9); + w.writeBytes("_END", 4); +} + +template struct SWSH; +template struct SWSH; + +template +bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) +{ + FILE* fp = hecl::Fopen(outPath.getAbsolutePath().c_str(), _S("w")); + if (fp) + { + SWSH swsh; + swsh.read(rs); + swsh.toYAMLFile(fp); + fclose(fp); + return true; + } + return false; +} +template bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); +template bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); + +template +bool WriteSWSH(const SWSH& swsh, const hecl::ProjectPath& outPath) +{ + athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) + return false; + swsh.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 WriteSWSH(const SWSH& swsh, const hecl::ProjectPath& outPath); +template bool WriteSWSH(const SWSH& swsh, const hecl::ProjectPath& outPath); + +} +} diff --git a/DataSpec/DNACommon/SWHC.hpp b/DataSpec/DNACommon/SWHC.hpp index fc487a095..880c371f3 100644 --- a/DataSpec/DNACommon/SWHC.hpp +++ b/DataSpec/DNACommon/SWHC.hpp @@ -1,4 +1,67 @@ #ifndef __COMMON_SWHC_HPP__ #define __COMMON_SWHC_HPP__ +#include "ParticleCommon.hpp" +#include "PAK.hpp" +#include "athena/FileWriter.hpp" + +namespace DataSpec +{ +namespace DNAParticle +{ + +template +struct SWSH : public BigYAML +{ + static const char* DNAType() { return "SWSH"; } + const char* DNATypeV() const { return DNAType(); } + + IntElementFactory x0_PSLT; + RealElementFactory x4_TIME; + RealElementFactory x8_LRAD; + RealElementFactory xc_RRAD; + IntElementFactory x10_LENG; + ColorElementFactory x14_COLR; + IntElementFactory x18_SIDE; + RealElementFactory x1c_IROT; + RealElementFactory x20_ROTM; + VectorElementFactory x24_POFS; + VectorElementFactory x28_IVEL; + VectorElementFactory x2c_NPOS; + ModVectorElementFactory x30_VELM; + ModVectorElementFactory x34_VLM2; + IntElementFactory x38_SPLN; + UVElementFactory x3c_TEXR; + IntElementFactory x40_TSPN; + union + { + struct + { + bool x44_24_LLRD : 1; bool x44_25_CROS : 1; bool x44_26_VLS1 : 1; bool x44_27_VLS2 : 1; + bool x44_28_SROT : 1; bool x44_29_WIRE : 1; bool x44_30_TEXW : 1; bool x44_31_AALP : 1; + bool x45_24_ZBUF : 1; bool x45_25_ORNT : 1; bool x45_26_CRND : 1; + }; + uint16_t dummy = 0; + }; + + + 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; + + SWSH() + { + x44_25_CROS = true; + } +}; + +template +bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); + +template +bool WriteSWSH(const SWSH& gpsm, const hecl::ProjectPath& outPath); +} +} #endif // __COMMON_SWHC_HPP__ diff --git a/DataSpec/DNAMP1/DNAMP1.cpp b/DataSpec/DNAMP1/DNAMP1.cpp index a6e923110..fb08efab9 100644 --- a/DataSpec/DNAMP1/DNAMP1.cpp +++ b/DataSpec/DNAMP1/DNAMP1.cpp @@ -8,6 +8,8 @@ #include "../DNACommon/TXTR.hpp" #include "../DNACommon/PART.hpp" #include "../DNACommon/ELSC.hpp" +#include "../DNACommon/SWHC.hpp" +#include "../DNACommon/CRSC.hpp" #include "../DNACommon/FONT.hpp" #include "CMDL.hpp" #include "AFSM.hpp" @@ -292,6 +294,10 @@ ResExtractor PAKBridge::LookupExtractor(const PAK::Entry& entry) return {DNAParticle::ExtractGPSM, nullptr, {_S(".gpsm.yaml")}}; case SBIG('ELSC'): return {DNAParticle::ExtractELSM, nullptr, {_S(".elsm.yaml")}}; + case SBIG('SWHC'): + return {DNAParticle::ExtractSWSH, nullptr, {_S(".swsh.yaml")}}; + case SBIG('CRSC'): + return {DNAParticle::ExtractCRSM, nullptr, {_S(".crsm.yaml")}}; case SBIG('FONT'): return {DNAFont::ExtractFONT, nullptr, {_S(".yaml")}}; } diff --git a/Runtime/CGameState.cpp b/Runtime/CGameState.cpp index f14f545c9..2b8503548 100644 --- a/Runtime/CGameState.cpp +++ b/Runtime/CGameState.cpp @@ -1,5 +1,6 @@ #include "CGameState.hpp" #include "IOStreams.hpp" +#include "zeus/Math.hpp" namespace urde { @@ -12,4 +13,9 @@ void CGameState::SetCurrentWorldId(unsigned int id, const std::string& name) { } +void CGameState::SetTotalPlayTime(float time) +{ + xa0_playTime = zeus::clamp(0.0, time, 359999.0); +} + } diff --git a/Runtime/CGameState.hpp b/Runtime/CGameState.hpp index f996dd816..5ab5103bf 100644 --- a/Runtime/CGameState.hpp +++ b/Runtime/CGameState.hpp @@ -17,11 +17,13 @@ class CGameState CWorldTransManager m_transManager; float m_gameTime = 0.0; CGameOptions m_gameOpts; + double xa0_playTime; public: CGameState() {} CGameState(CBitStreamReader& stream); void SetCurrentWorldId(unsigned int id, const std::string& name); CWorldTransManager& WorldTransitionManager() {return m_transManager;} + void SetTotalPlayTime(float time); }; } diff --git a/Runtime/CPlayerState.cpp b/Runtime/CPlayerState.cpp index 324796153..4deabb310 100644 --- a/Runtime/CPlayerState.cpp +++ b/Runtime/CPlayerState.cpp @@ -4,12 +4,6 @@ namespace urde { -/* TODO: Implement this properly */ -/* NOTE: This is only to be used as a reference, - * and is not indicative of how the actual format is structured - * a proper RE is still required! - */ - const u32 CPlayerState::PowerUpMaxValues[41] = { 1, 1, 1, 1, 250, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 @@ -60,126 +54,81 @@ const char* PowerUpNames[41]= "Artifact of Newborn", }; -CPlayerState::CPlayerState(CBitStreamReader& in) - : x188_staticIntf(5) +CPlayerState::CPlayerState(CBitStreamReader& stream) + : CPlayerState() { - x0_24_ = true; - u32 bitCount = 0; - std::for_each(std::cbegin(CPlayerState::PowerUpMaxValues), std::cend(CPlayerState::PowerUpMaxValues), [&bitCount](const u32& max){ - bitCount += CBitStreamReader::GetBitCount(max); - }); - -#if 1 - in.readUint32Big(); - in.readBool(); - in.readBool(); - in.readBool(); - - atInt8 data[0xAE]; - in.readBytesToBuf(data, 0xAE); - for (u32 k = 0; k < 3; k++) + x4_ = stream.ReadEncoded(0x20); + u32 tmp = stream.ReadEncoded(0x20); + xc_currentHealth = *reinterpret_cast(&tmp); + x8_currentBeam = EBeamId(stream.ReadEncoded(CBitStreamReader::GetBitCount(5))); + x20_currentSuit = EPlayerSuit(stream.ReadEncoded(CBitStreamReader::GetBitCount(4))); + x24_powerups.resize(41); + for (u32 i = 0; i < x24_powerups.size(); ++i) { - atInt8 save[0x3AC]; - in.readBytesToBuf(save, 0x3AC); - { - CBitStreamReader stream(save, 0x1000); - std::string filename = athena::utility::sprintf("Game%i.dat", k + 1); - std::string logFilename = athena::utility::sprintf("Game%i.txt", k + 1); - FILE * f = fopen(logFilename.c_str(), "w"); - CBitStreamWriter w{filename}; + if (PowerUpMaxValues[i] == 0) + continue; - fprintf(f, "Game State\n"); - for (u32 i = 0; i < 0x80; i++) - { - u32 tmp = stream.ReadEncoded(8); - if (!(i % 16)) - fprintf(f, "\n"); - fprintf(f, "%.2i ", tmp); - w.WriteEncoded(tmp, 8); - } - fprintf(f, "\n\n"); - - s32 tmp = stream.ReadEncoded(32); - w.WriteEncoded(tmp, 0x20); - fprintf(f, "%i\n", tmp); - tmp = stream.ReadEncoded(1); - w.WriteEncoded(tmp, 1); - fprintf(f, "%i\n", tmp); - tmp = stream.ReadEncoded(1); - w.WriteEncoded(tmp, 1); - fprintf(f, "%i\n", tmp); - tmp = stream.ReadEncoded(32); - w.WriteEncoded(tmp, 0x20); - fprintf(f, "%f\n", *reinterpret_cast(&tmp)); - tmp = stream.ReadEncoded(32); - w.WriteEncoded(tmp, 0x20); - fprintf(f, "%f\n", *reinterpret_cast(&tmp)); - tmp = stream.ReadEncoded(32); - fprintf(f, "%x\n", tmp); - w.WriteEncoded(tmp, 0x20); - - fprintf(f, "PlayerState\n"); - x4_ = stream.ReadEncoded(0x20); - w.WriteEncoded(x4_, 0x20); - fprintf(f, "%x\n", x4_); - tmp = stream.ReadEncoded(0x20); - fprintf(f, "Base health %f\n", *reinterpret_cast(&tmp)); - xc_currentHealth = *reinterpret_cast(&tmp); - w.WriteEncoded(tmp, 0x20); - x8_currentBeam = stream.ReadEncoded(CBitStreamReader::GetBitCount(5)); - fprintf(f, "%i\n", x8_currentBeam); - w.WriteEncoded(x8_currentBeam, CBitStreamReader::GetBitCount(5)); - x20_currentSuit = EPlayerSuit(stream.ReadEncoded(CBitStreamReader::GetBitCount(4))); - fprintf(f, "%i\n", x20_currentSuit); - w.WriteEncoded(u32(x20_currentSuit), CBitStreamReader::GetBitCount(4)); - x24_powerups.resize(41); - fprintf(f, "Powerups\n"); - for (u32 i = 0; i < x24_powerups.size(); ++i) - { - if (PowerUpMaxValues[i] == 0) - continue; - - u32 a = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i])); - u32 b = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i])); - w.WriteEncoded(a, CBitStreamReader::GetBitCount(PowerUpMaxValues[i])); - w.WriteEncoded(b, CBitStreamReader::GetBitCount(PowerUpMaxValues[i])); - x24_powerups[i] = CPowerUp(a, b); - fprintf(f, "%2i(%21s): cur=%3i max=%3i\n", i, PowerUpNames[i], a, b); - } - - for (u32 i = 0; i < 832; i++) - { - u32 tmp = stream.ReadEncoded(1); - if (!(i % 32)) - fprintf(f, "\n"); - - fprintf(f, "%i ", tmp); - w.WriteEncoded(tmp, 1); - } - fprintf(f, "\n\n"); - - tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100)); - w.WriteEncoded(tmp, CBitStreamReader::GetBitCount(0x100)); - fprintf(f, "%i\n", tmp); - tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100)); - w.WriteEncoded(tmp, CBitStreamReader::GetBitCount(0x100)); - fprintf(f, "%i\n", tmp); - - fprintf(f, "Final Offset %.8llx\n", stream.position()); - fprintf(f, "Completion: %.2i%%\n", CalculateItemCollectionRate()); - w.save(); - } + u32 a = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i])); + u32 b = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i])); + x24_powerups[i] = CPowerUp(a, b); } -#endif + + x170_scanTimes.resize(846); + for (u32 i = 0; i < x170_scanTimes.size(); i++) + { + x170_scanTimes[i].first = stream.ReadEncoded(1); + if (x170_scanTimes[i].first) + x170_scanTimes[i].second = 1.f; + else + x170_scanTimes[i].second = 0.f; + } + + x180_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100)); + x184_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100)); } -float CPlayerState::GetBeamSwitchTime() const +void CPlayerState::PutTo(CBitStreamWriter &stream) { - static const float switchTimes[4] { - 0.2, 0.1, 0.2, 0.2 + stream.WriteEncoded(x4_, 32); + u32 tmp = *reinterpret_cast(&xc_currentHealth); + stream.WriteEncoded(tmp, 32); + stream.WriteEncoded((u32)x8_currentBeam, CBitStreamWriter::GetBitCount(5)); + stream.WriteEncoded((u32)x20_currentSuit, CBitStreamWriter::GetBitCount(4)); + for (u32 i = 0; i < x24_powerups.size(); ++i) + { + const CPowerUp& pup = x24_powerups[i]; + stream.WriteEncoded(pup.x0_amount, CBitStreamWriter::GetBitCount(PowerUpMaxValues[i])); + stream.WriteEncoded(pup.x4_capacity, CBitStreamWriter::GetBitCount(PowerUpMaxValues[i])); + } + + for (const auto& scanTime : x170_scanTimes) + { + if (scanTime.second >= 1.f) + stream.WriteEncoded(true, 1); + else + stream.WriteEncoded(false, 1); + } + + stream.WriteEncoded(x180_, CBitStreamWriter::GetBitCount(0x100)); + stream.WriteEncoded(x184_, CBitStreamWriter::GetBitCount(0x100)); +} + +float CPlayerState::sub_80091204() const +{ + static const float unk[] { + 0.2f, 0.1f, 0.2f, 0.2f, 1.f }; - return switchTimes[u32(x8_currentBeam)]; + return unk[u32(x8_currentBeam)]; +} + +u32 CPlayerState::GetMissileCostForAltAttack() const +{ + static const u32 costs[] { + 5, 10, 10, 10, 1 + }; + + return costs[u32(x8_currentBeam)]; } u32 CPlayerState::CalculateItemCollectionRate() const @@ -244,7 +193,7 @@ CPlayerState::EPlayerVisor CPlayerState::GetActiveVisor(const CStateManager& sta #if 0 CFirstPersionCamera* cam = dynamic_cast(stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr)); if (!cam) - return EVisorType::Zero; + return EVisorType::Combat; #endif return x14_currentVisor; } @@ -254,8 +203,9 @@ void CPlayerState::UpdateStaticInterference(CStateManager& stateMgr, const float x188_staticIntf.Update(stateMgr, dt); } -void CPlayerState::NewScanTime(u32 time) +void CPlayerState::IncreaseScanTime(u32 time, float val) { + } bool CPlayerState::GetIsVisorTransitioning() const diff --git a/Runtime/CPlayerState.hpp b/Runtime/CPlayerState.hpp index 3fceabc29..df4835923 100644 --- a/Runtime/CPlayerState.hpp +++ b/Runtime/CPlayerState.hpp @@ -84,6 +84,15 @@ public: FusionPhazon }; + enum class EBeamId : u32 + { + Power, + Ice, + Plasma, + Wave, + Phazon + }; + private: static const u32 PowerUpMaxValues[41]; @@ -101,7 +110,7 @@ private: }; u32 x4_ = 0; - u32 x8_currentBeam = 0; + EBeamId x8_currentBeam = EBeamId::Power; float xc_currentHealth = 99.f; float x10_ = 50.f; EPlayerVisor x14_currentVisor = EPlayerVisor::Combat; @@ -109,14 +118,17 @@ private: float x1c_visorTransitionFactor = 0.2f; EPlayerSuit x20_currentSuit = EPlayerSuit::Power; rstl::reserved_vector x24_powerups; - + rstl::reserved_vector, 846> x170_scanTimes; + u32 x180_ = 0; + u32 x184_ = 0; CStaticInterference x188_staticIntf; public: - float GetBeamSwitchTime() const; + float sub_80091204() const; + u32 GetMissileCostForAltAttack() const; u32 CalculateItemCollectionRate() const; - u32 GetBaseHealthCapacityInt32() { return 99; } + u32 GetPickupTotal() { return 99; } void SetFusion(bool val) { x0_26_fusion = val; } bool GetFusion() const { return x0_26_fusion; } EPlayerSuit GetCurrentSuit() const; @@ -124,7 +136,8 @@ public: EPlayerVisor GetActiveVisor(const CStateManager& stateMgr) const; void UpdateStaticInterference(CStateManager& stateMgr, const float& dt); void IncreaseScanTime(u32 time, float val); - void NewScanTime(u32 time); + void SetScanTime(u32 time, float val); + float GetScanTime(u32 time, float val); bool GetIsVisorTransitioning() const; float GetVisorTransitionFactor() const; void UpdateVisorTransition(float dt); @@ -146,6 +159,7 @@ public: void InitializePowerUp(EItemType type, u32 capacity); CPlayerState() : x188_staticIntf(5) { x0_24_ = true; } CPlayerState(CBitStreamReader& stream); + void PutTo(CBitStreamWriter& stream); }; } diff --git a/Runtime/Particle/CCollisionResponseData.cpp b/Runtime/Particle/CCollisionResponseData.cpp index 4458064db..64b17589a 100644 --- a/Runtime/Particle/CCollisionResponseData.cpp +++ b/Runtime/Particle/CCollisionResponseData.cpp @@ -79,9 +79,7 @@ void CCollisionResponseData::AddParticleSystemToResponse(EWeaponCollisionRespons int i = int(type); std::vector tracker; tracker.resize(8); - x0[i].first = std::move(CPF::GetChildGeneratorDesc(in, resPool, tracker).m_token); - if (x0[i].first) - x0[i].second = true; + x0_generators[i].emplace(std::move(CPF::GetChildGeneratorDesc(in, resPool, tracker).m_token)); } bool CCollisionResponseData::CheckAndAddDecalToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool) @@ -99,10 +97,7 @@ bool CCollisionResponseData::CheckAndAddDecalToResponse(FourCC clsId, CInputStre if (!id) return true; - x20[i].first = std::move(resPool->GetObj({FOURCC('DPSC'), id})); - if (x0[i].first) - x0[i].second = true; - + x20_decals[i].emplace(std::move(resPool->GetObj({FOURCC('DPSC'), id}))); return true; } i++; @@ -121,7 +116,7 @@ bool CCollisionResponseData::CheckAndAddSoundFXToResponse(FourCC clsId, CInputSt if (cls == SBIG('NONE')) return true; - x10[i] = CPF::GetInt(in); + x10_sfx[i] = CPF::GetInt(in); return true; } i++; @@ -140,6 +135,7 @@ bool CCollisionResponseData::CheckAndAddParticleSystemToResponse(FourCC clsId, C AddParticleSystemToResponse(EWeaponCollisionResponseTypes(i), in, resPool); return true; } + i++; } return false; } @@ -159,9 +155,12 @@ bool CCollisionResponseData::CheckAndAddResourceToResponse(FourCC clsId, CInputS CCollisionResponseData::CCollisionResponseData(CInputStream& in, CSimplePool* resPool) : x30_RNGE(50.f), x34_FOFF(0.2f) { - x0.resize(94); - x10.resize(94); - x20.resize(94); + x0_generators.resize(94); + x10_sfx.resize(94); + x20_decals.resize(94); + for (TResId& id : x10_sfx) + id = ~0; + FourCC clsId = CPF::GetClassID(in); if (clsId == SBIG('CRSM')) { diff --git a/Runtime/Particle/CCollisionResponseData.hpp b/Runtime/Particle/CCollisionResponseData.hpp index 7239b3b49..392759458 100644 --- a/Runtime/Particle/CCollisionResponseData.hpp +++ b/Runtime/Particle/CCollisionResponseData.hpp @@ -5,6 +5,7 @@ #include "IObj.hpp" #include "CToken.hpp" #include "IOStreams.hpp" +#include "optional.hpp" namespace urde { @@ -38,9 +39,9 @@ enum class EWeaponCollisionResponseTypes class CCollisionResponseData { - std::vector, bool>> x0; - std::vector x10; - std::vector, bool>> x20; + std::vector>> x0_generators; + std::vector x10_sfx; + std::vector>> x20_decals; float x30_RNGE; float x34_FOFF; diff --git a/Runtime/Particle/CSwooshDescription.hpp b/Runtime/Particle/CSwooshDescription.hpp index eb1479dab..6bb67f369 100644 --- a/Runtime/Particle/CSwooshDescription.hpp +++ b/Runtime/Particle/CSwooshDescription.hpp @@ -41,6 +41,11 @@ public: }; u16 dummy = 0; }; + + CSwooshDescription() + { + x44_25_CROS = true; + } }; }