diff --git a/DataSpec/DNAMP1/CMakeLists.txt b/DataSpec/DNAMP1/CMakeLists.txt index 2e7633982..0ecc0cf9e 100644 --- a/DataSpec/DNAMP1/CMakeLists.txt +++ b/DataSpec/DNAMP1/CMakeLists.txt @@ -12,6 +12,7 @@ make_dnalist(liblist MREA DeafBabe SCAN + FRME Tweaks/CTweakGame Tweaks/CTweakParticle Tweaks/CTweakPlayer @@ -30,6 +31,7 @@ add_library(DNAMP1 MAPA.hpp MREA.cpp SCLY.hpp SCLY.cpp + FRME.cpp DeafBabe.cpp) target_link_libraries(DNAMP1 ScriptObjectsMP1) diff --git a/DataSpec/DNAMP1/DNAMP1.cpp b/DataSpec/DNAMP1/DNAMP1.cpp index 63190d933..90dce3df1 100644 --- a/DataSpec/DNAMP1/DNAMP1.cpp +++ b/DataSpec/DNAMP1/DNAMP1.cpp @@ -10,6 +10,7 @@ #include "ANCS.hpp" #include "MREA.hpp" #include "MAPA.hpp" +#include "FRME.hpp" namespace Retro { @@ -268,6 +269,8 @@ ResExtractor PAKBridge::LookupExtractor(const PAK::Entry& entry) return {SCAN::Extract, nullptr, {_S(".yaml")}, 0, SCAN::Name}; case SBIG('TXTR'): return {TXTR::Extract, nullptr, {_S(".png")}}; + case SBIG('FRME'): + return {nullptr, FRME::Extract, {_S(".blend")}, 2}; case SBIG('CMDL'): return {nullptr, CMDL::Extract, {_S(".blend")}, 1, CMDL::Name}; case SBIG('ANCS'): diff --git a/DataSpec/DNAMP1/EVNT.cpp b/DataSpec/DNAMP1/EVNT.cpp index 9c0afdd17..92c42117c 100644 --- a/DataSpec/DNAMP1/EVNT.cpp +++ b/DataSpec/DNAMP1/EVNT.cpp @@ -13,17 +13,17 @@ void EVNT::read(Athena::io::IStreamReader& reader) reader.enumerate(loopEvents, loopCount); uevtEvents.clear(); - if (version == 2) - { - atUint32 uevtCount = reader.readUint32Big(); - reader.enumerate(uevtEvents, uevtCount); - } + atUint32 uevtCount = reader.readUint32Big(); + reader.enumerate(uevtEvents, uevtCount); atUint32 effectCount = reader.readUint32Big(); reader.enumerate(effectEvents, effectCount); - atUint32 sfxCount = reader.readUint32Big(); - reader.enumerate(sfxEvents, sfxCount); + if (version == 2) + { + atUint32 sfxCount = reader.readUint32Big(); + reader.enumerate(sfxEvents, sfxCount); + } } void EVNT::write(Athena::io::IStreamWriter& writer) const @@ -33,17 +33,17 @@ void EVNT::write(Athena::io::IStreamWriter& writer) const writer.writeUint32Big(loopEvents.size()); writer.enumerate(loopEvents); - if (version == 2) - { - writer.writeUint32Big(uevtEvents.size()); - writer.enumerate(uevtEvents); - } + writer.writeUint32Big(uevtEvents.size()); + writer.enumerate(uevtEvents); writer.writeUint32Big(effectEvents.size()); writer.enumerate(effectEvents); - writer.writeUint32Big(sfxEvents.size()); - writer.enumerate(sfxEvents); + if (version == 2) + { + writer.writeUint32Big(sfxEvents.size()); + writer.enumerate(sfxEvents); + } } void EVNT::read(Athena::io::YAMLDocReader& reader) @@ -54,17 +54,17 @@ void EVNT::read(Athena::io::YAMLDocReader& reader) reader.enumerate("loopEvents", loopEvents, loopCount); uevtEvents.clear(); - if (version == 2) - { - atUint32 uevtCount = reader.readUint32("uevtCount"); - reader.enumerate("uevtEvents", uevtEvents, uevtCount); - } + atUint32 uevtCount = reader.readUint32("uevtCount"); + reader.enumerate("uevtEvents", uevtEvents, uevtCount); atUint32 effectCount = reader.readUint32("effectCount"); reader.enumerate("effectEvents", effectEvents, effectCount); - atUint32 sfxCount = reader.readUint32("sfxCount"); - reader.enumerate("sfxEvents", sfxEvents, sfxCount); + if (version == 2) + { + atUint32 sfxCount = reader.readUint32("sfxCount"); + reader.enumerate("sfxEvents", sfxEvents, sfxCount); + } } void EVNT::write(Athena::io::YAMLDocWriter& writer) const @@ -74,17 +74,33 @@ void EVNT::write(Athena::io::YAMLDocWriter& writer) const writer.writeUint32("loopCount", loopEvents.size()); writer.enumerate("loopEvents", loopEvents); - if (version == 2) - { - writer.writeUint32("uevtCount", uevtEvents.size()); - writer.enumerate("uevtEvents", uevtEvents); - } + writer.writeUint32("uevtCount", uevtEvents.size()); + writer.enumerate("uevtEvents", uevtEvents); writer.writeUint32("effectCount", effectEvents.size()); writer.enumerate("effectEvents", effectEvents); - writer.writeUint32("sfxCount", sfxEvents.size()); - writer.enumerate("sfxEvents", sfxEvents); + if (version == 2) + { + writer.writeUint32("sfxCount", sfxEvents.size()); + writer.enumerate("sfxEvents", sfxEvents); + } +} + +const char* EVNT::DNAType() +{ + return "Retro::DNAMP1::EVNT"; +} + +size_t EVNT::binarySize(size_t __isz) const +{ + __isz = __EnumerateSize(__isz, loopEvents); + __isz = __EnumerateSize(__isz, uevtEvents); + __isz = __EnumerateSize(__isz, effectEvents); + if (version == 2) + __isz = __EnumerateSize(__isz, sfxEvents); + + return __isz + (version == 2 ? 20 : 16); } } diff --git a/DataSpec/DNAMP1/EVNT.hpp b/DataSpec/DNAMP1/EVNT.hpp index 8823e3670..ec63b091b 100644 --- a/DataSpec/DNAMP1/EVNT.hpp +++ b/DataSpec/DNAMP1/EVNT.hpp @@ -2,6 +2,7 @@ #define __DNAMP1_EVNT_HPP__ #include "../DNACommon/DNACommon.hpp" +#include "DNAMP1.hpp" namespace Retro { @@ -25,7 +26,7 @@ struct EVNT : BigYAML Value idx; Value unk2; Value unk3; - Value unk4; + Value unk4; Value unk5; }; @@ -64,6 +65,16 @@ struct EVNT : BigYAML Value bigNum; }; std::vector sfxEvents; + + static bool Extract(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath) + { + EVNT evnt; + evnt.read(rs); + FILE* fp = HECL::Fopen(outPath.getAbsolutePath().c_str(), _S("wb")); + evnt.toYAMLFile(fp); + fclose(fp); + return true; + } }; } diff --git a/DataSpec/DNAMP1/FRME.cpp b/DataSpec/DNAMP1/FRME.cpp new file mode 100644 index 000000000..2cacc5ca7 --- /dev/null +++ b/DataSpec/DNAMP1/FRME.cpp @@ -0,0 +1,262 @@ +#include "FRME.hpp" + +namespace Retro +{ +namespace DNAMP1 +{ +void FRME::read(Athena::io::IStreamReader& __dna_reader) +{ + /* version */ + version = __dna_reader.readUint32Big(); + /* unk1 */ + unk1 = __dna_reader.readUint32Big(); + /* modelCount */ + modelCount = __dna_reader.readUint32Big(); + /* unk3 */ + unk3 = __dna_reader.readUint32Big(); + /* widgetCount */ + widgetCount = __dna_reader.readUint32Big(); + /* widgets */ + __dna_reader.enumerate(widgets, widgetCount, [this](Athena::io::IStreamReader& reader, Widget& w) { + w.owner = this; + w.read(reader); + }); +} + +void FRME::write(Athena::io::IStreamWriter& __dna_writer) const +{ + /* version */ + __dna_writer.writeUint32Big(version); + /* unk1 */ + __dna_writer.writeUint32Big(unk1); + /* modelCount */ + __dna_writer.writeUint32Big(modelCount); + /* unk3 */ + __dna_writer.writeUint32Big(unk3); + /* widgetCount */ + __dna_writer.writeUint32Big(widgetCount); + /* widgets */ + __dna_writer.enumerate(widgets); +} + +size_t FRME::binarySize(size_t __isz) const +{ + __isz = __EnumerateSize(__isz, widgets); + return __isz + 20; +} + +void FRME::Widget::read(Athena::io::IStreamReader& __dna_reader) +{ + /* type */ + type.read(__dna_reader); + /* header */ + header.read(__dna_reader); + switch(type) + { + case SBIG('BWIG'): widgetInfo.reset(new BWIGInfo); break; + case SBIG('HWIG'): widgetInfo.reset(new HWIGInfo); break; + case SBIG('CAMR'): widgetInfo.reset(new CAMRInfo); break; + case SBIG('MODL'): widgetInfo.reset(new MODLInfo); break; + case SBIG('LITE'): widgetInfo.reset(new LITEInfo); break; + case SBIG('TXPN'): widgetInfo.reset(new TXPNInfo(owner->version)); break; + case SBIG('IMGP'): widgetInfo.reset(new IMGPInfo); break; + case SBIG('GRUP'): widgetInfo.reset(new GRUPInfo); break; + case SBIG('TBGP'): widgetInfo.reset(new TBGPInfo); break; + case SBIG('ENRG'): widgetInfo.reset(new ENRGInfo); break; + case SBIG('METR'): widgetInfo.reset(new METRInfo); break; + case SBIG('SLGP'): widgetInfo.reset(new SLGPInfo); break; + default: + Log.report(LogVisor::FatalError, _S("Unsupported FRME widget type %s"), type.toString().c_str()); + } + + /* widgetInfo */ + widgetInfo->read(__dna_reader); + + /* hasGroup */ + hasGroup = __dna_reader.readBool(); + if (hasGroup) + { + /* group */ + group = __dna_reader.readUint16Big(); + } + /* origin */ + origin = __dna_reader.readVec3fBig(); + /* basis[0] */ + basis[0] = __dna_reader.readVec3fBig(); + /* basis[1] */ + basis[1] = __dna_reader.readVec3fBig(); + /* basis[2] */ + basis[2] = __dna_reader.readVec3fBig(); + /* unk1 */ + unk1 = __dna_reader.readVec3fBig(); + /* unk2 */ + unk2 = __dna_reader.readUint32Big(); + /* unk3 */ + unk3 = __dna_reader.readBool(); + /* unk4 */ + unk4 = __dna_reader.readBool(); +} + +void FRME::Widget::write(Athena::io::IStreamWriter& __dna_writer) const +{ + /* type */ + type.write(__dna_writer); + /* header */ + header.write(__dna_writer); + + /* widgetInfo */ + widgetInfo->write(__dna_writer); + + /* hasGroup */ + __dna_writer.writeBool(hasGroup); + if (hasGroup) + { + /* group */ + __dna_writer.writeUint16Big(group); + } + /* origin */ + __dna_writer.writeVec3fBig(origin); + /* basis[0] */ + __dna_writer.writeVec3fBig(basis[0]); + /* basis[1] */ + __dna_writer.writeVec3fBig(basis[1]); + /* basis[2] */ + __dna_writer.writeVec3fBig(basis[2]); + /* unk1 */ + __dna_writer.writeVec3fBig(unk1); + /* unk2 */ + __dna_writer.writeUint32Big(unk2); + /* unk3 */ + __dna_writer.writeBool(unk3); + /* unk4 */ + __dna_writer.writeBool(unk4); +} + +size_t FRME::Widget::binarySize(size_t __isz) const +{ + __isz = type.binarySize(__isz); + __isz = header.binarySize(__isz); + __isz = widgetInfo->binarySize(__isz); + if (hasGroup) + __isz += 4; + return __isz + 67; +} + +void FRME::Widget::CAMRInfo::read(Athena::io::IStreamReader& __dna_reader) +{ + projectionType = ProjectionType(__dna_reader.readUint32Big()); + if (projectionType == ProjectionType::Perspective) + projection.reset(new PerspectiveProjection); + else if (projectionType == ProjectionType::Orthographic) + projection.reset(new OrthographicProjection); + else + Log.report(LogVisor::FatalError, _S("Invalid CAMR projection mode! %i"), int(projectionType)); + + projection->read(__dna_reader); +} + +void FRME::Widget::CAMRInfo::write(Athena::io::IStreamWriter& __dna_writer) const +{ + if (!projection) + Log.report(LogVisor::FatalError, _S("Invalid CAMR projection object!")); + if (projection->type != projectionType) + Log.report(LogVisor::FatalError, _S("CAMR projection type does not match actual projection type!")); + + __dna_writer.writeUint32Big(atUint32(projectionType)); + projection->write(__dna_writer); +} + +size_t FRME::Widget::CAMRInfo::binarySize(size_t __isz) const +{ + __isz = projection->binarySize(__isz); + return __isz + 4; +} + +void FRME::Widget::TXPNInfo::read(Athena::io::IStreamReader& __dna_reader) +{ + IWidgetInfo::read(__dna_reader); + /* frameVals[0] */ + frameVals[0] = __dna_reader.readFloatBig(); + /* frameVals[1] */ + frameVals[1] = __dna_reader.readFloatBig(); + /* frameVals[2] */ + frameVals[2] = __dna_reader.readFloatBig(); + /* frameVals[3] */ + frameVals[3] = __dna_reader.readFloatBig(); + /* frameVals[4] */ + frameVals[4] = __dna_reader.readFloatBig(); + /* font */ + font.read(__dna_reader); + /* unk1 */ + unk1 = __dna_reader.readBool(); + /* unk2 */ + unk2 = __dna_reader.readBool(); + /* unk3 */ + unk3 = __dna_reader.readUint32Big(); + /* unk4 */ + unk4 = __dna_reader.readUint32Big(); + /* fillColor */ + fillColor = __dna_reader.readVec4fBig(); + /* outlineColor */ + outlineColor = __dna_reader.readVec4fBig(); + /* pointScale */ + pointScale = __dna_reader.readVec2fBig(); + if (version == 1) + { + /* jpnFont */ + jpnFont.read(__dna_reader); + /* jpnPointScale */ + jpnPointScale = __dna_reader.readInt32Big(); + } +} + +void FRME::Widget::TXPNInfo::write(Athena::io::IStreamWriter& __dna_writer) const +{ + IWidgetInfo::write(__dna_writer); + /* frameVals[0] */ + __dna_writer.writeFloatBig(frameVals[0]); + /* frameVals[1] */ + __dna_writer.writeFloatBig(frameVals[1]); + /* frameVals[2] */ + __dna_writer.writeFloatBig(frameVals[2]); + /* frameVals[3] */ + __dna_writer.writeFloatBig(frameVals[3]); + /* frameVals[4] */ + __dna_writer.writeFloatBig(frameVals[4]); + /* font */ + font.write(__dna_writer); + /* unk1 */ + __dna_writer.writeBool(unk1); + /* unk2 */ + __dna_writer.writeBool(unk2); + /* unk3 */ + __dna_writer.writeUint32Big(unk3); + /* unk4 */ + __dna_writer.writeUint32Big(unk4); + /* fillColor */ + __dna_writer.writeVec4fBig(fillColor); + /* outlineColor */ + __dna_writer.writeVec4fBig(outlineColor); + /* pointScale */ + __dna_writer.writeVec2fBig(pointScale); + if (version == 1) + { + /* jpnFont */ + jpnFont.write(__dna_writer); + /* jpnPointScale */ + __dna_writer.writeInt32Big(jpnPointScale); + } +} + +size_t FRME::Widget::TXPNInfo::binarySize(size_t __isz) const +{ + __isz = IWidgetInfo::binarySize(__isz); + __isz = font.binarySize(__isz); + if (version == 1) + __isz = jpnFont.binarySize(__isz); + + return __isz + (version == 1 ? 74 : 66); +} + +} +} diff --git a/DataSpec/DNAMP1/FRME.hpp b/DataSpec/DNAMP1/FRME.hpp new file mode 100644 index 000000000..65c155b6b --- /dev/null +++ b/DataSpec/DNAMP1/FRME.hpp @@ -0,0 +1,229 @@ +#ifndef _DNAMP1_FRME_HPP_ +#define _DNAMP1_FRME_HPP_ + +#include "../DNACommon/DNACommon.hpp" +#include "DNAMP1.hpp" +#include + +namespace Retro +{ +namespace DNAMP1 +{ +struct FRME : BigDNA +{ + DECL_EXPLICIT_DNA + Value version; + Value unk1; + Value modelCount; // Matches MODL widgets + Value unk3; + Value widgetCount; + + struct Widget : BigDNA + { + DECL_EXPLICIT_DNA + FRME* owner; + DNAFourCC type; + struct WidgetHeader : BigDNA + { + DECL_DNA + String<-1> name; + String<-1> parent; + Value unk1; + Value unk2; + Value unk3; + Value unk4; + Value color; + Value modelDrawFlags; + } header; + + struct IWidgetInfo : BigDNA + { + Delete _d; + virtual void read(Athena::io::IStreamReader&) {} + void write(Athena::io::IStreamWriter&) const {} + size_t binarySize(size_t __isz) const { return __isz; } + }; + + std::unique_ptr widgetInfo; + Value hasGroup; + Value group; + Value origin; + Value basis[3]; + Value unk1; + Value unk2; + Value unk3; + Value unk4; + + struct BWIGInfo : IWidgetInfo + { Delete _d; }; + + struct HWIGInfo : IWidgetInfo + { Delete _d; }; + + struct CAMRInfo : IWidgetInfo + { + DECL_EXPLICIT_DNA + enum class ProjectionType + { + Perspective, + Orthographic + }; + + Value projectionType; + struct IProjection : BigDNA + { + Delete _d; + const ProjectionType type; + IProjection(ProjectionType t) : type(t) {} + }; + + struct PerspectiveProjection : IProjection + { + DECL_DNA + PerspectiveProjection() : IProjection(ProjectionType::Perspective) {} + Value fov; + Value aspect; + Value near; + Value far; + }; + + struct OrthographicProjection : IProjection + { + DECL_DNA + OrthographicProjection() : IProjection(ProjectionType::Orthographic) {} + Value left; + Value right; + Value top; + Value bottom; + Value near; + Value far; + }; + std::unique_ptr projection; + }; + + struct MODLInfo : IWidgetInfo + { + DECL_DNA + UniqueID32 model; + Value blendMode; + Value lightMode; + }; + + struct LITEInfo : IWidgetInfo + { + DECL_DNA + Value unk1; + Value unk2; + Value unk3; + Value unk4; + Value unk5; + Value unk6; + Value unk7; + Value unk8; + }; + + struct ENRGInfo : IWidgetInfo + { + DECL_DNA + UniqueID32 texture; + }; + + struct METRInfo : IWidgetInfo + { + DECL_DNA + Value unk1; + Value value1; + Value value2; + }; + + struct GRUPInfo : IWidgetInfo + { + DECL_DNA + Value unk1; + Value unk2; + Value unk3; + }; + + struct TBGPInfo : IWidgetInfo + { + DECL_DNA + Value unk1; + Value unk2; + Value unkEnum; + Value unk3; + Value un4; + Value unk5; + Value unk6; + Value unkFloat1; + Value unkFloat2; + Value unk7; + Value unkFloat3; + Value unk8; + Value unk9; + Value unk10; + Value unk11; + }; + + struct SLGPInfo : IWidgetInfo + { + DECL_DNA + Value min; + Value max; + Value unk1; + Value unk2; + }; + + struct TXPNInfo : IWidgetInfo + { + DECL_EXPLICIT_DNA + atUint32 version = 0; + TXPNInfo() {} + TXPNInfo(atUint32 version) + : version(version) + {} + Value frameVals[5]; + UniqueID32 font; + Value unk1; + Value unk2; + Value unk3; + Value unk4; + Value fillColor; + Value outlineColor; + Value pointScale; + /* The following is only found in V1 */ + UniqueID32 jpnFont; + Value jpnPointScale; + }; + + struct IMGPInfo : IWidgetInfo + { + DECL_DNA + UniqueID32 texture; + Value unk1; + Value unk2; + Value quadCoordCount; + Vector quadCoords; + Value uvCoordCount; + Vector uvCoords; + }; + }; + + Vector widgets; + static bool Extract(const SpecBase& dataSpec, + PAKEntryReadStream& rs, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const PAK::Entry& entry, + bool force, + std::function fileChanged) + { + FRME frme; + frme.read(rs); + return true; + } +}; + +} +} + +#endif // _DNAMP1_FRME_HPP_ diff --git a/DataSpec/DNAMP3/MLVL.hpp b/DataSpec/DNAMP3/MLVL.hpp index 4110c3c54..94165fb95 100644 --- a/DataSpec/DNAMP3/MLVL.hpp +++ b/DataSpec/DNAMP3/MLVL.hpp @@ -88,7 +88,7 @@ struct MLVL : BigYAML { MLVL mlvl; mlvl.read(rs); - FILE* fp = HECL::Fopen(outPath.getAbsolutePath().c_str(), _S("wb")); + FILE* fp = HECL::Fopen(outPath.getWithExtension(_S(".yaml")).getAbsolutePath().c_str(), _S("wb")); mlvl.toYAMLFile(fp); fclose(fp); HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();