metaforce/DataSpec/DNAMP1/SCLY.cpp

199 lines
6.6 KiB
C++
Raw Permalink Normal View History

2015-09-10 20:30:35 +00:00
#include "SCLY.hpp"
#include "ScriptObjects/ScriptTypes.hpp"
2018-12-08 05:30:43 +00:00
namespace DataSpec::DNAMP1 {
2015-09-10 20:30:35 +00:00
2018-02-22 07:24:51 +00:00
template <>
2018-12-08 05:30:43 +00:00
void SCLY::Enumerate<BigDNA::Read>(athena::io::IStreamReader& rs) {
2019-07-20 04:27:21 +00:00
fourCC.read(rs);
2018-12-08 05:30:43 +00:00
version = rs.readUint32Big();
layerCount = rs.readUint32Big();
rs.enumerateBig(layerSizes, layerCount);
atUint32 i = 0;
rs.enumerate<ScriptLayer>(layers, layerCount, [&i, this](athena::io::IStreamReader& rs, ScriptLayer& layer) {
atUint64 start = rs.position();
layer.read(rs);
rs.seek(start + layerSizes[i++], athena::SeekOrigin::Begin);
2018-12-08 05:30:43 +00:00
});
2015-09-10 20:30:35 +00:00
}
2018-02-22 07:24:51 +00:00
template <>
2018-12-08 05:30:43 +00:00
void SCLY::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& ws) {
2019-07-20 04:27:21 +00:00
fourCC.write(ws);
2018-12-08 05:30:43 +00:00
ws.writeUint32Big(version);
ws.writeUint32Big(layerCount);
ws.enumerateBig(layerSizes);
ws.enumerate(layers);
2015-09-10 20:30:35 +00:00
}
2018-02-22 07:24:51 +00:00
template <>
2018-12-08 05:30:43 +00:00
void SCLY::Enumerate<BigDNA::BinarySize>(size_t& __isz) {
__isz += 12;
__isz += layerSizes.size() * 4;
for (const ScriptLayer& layer : layers)
layer.binarySize(__isz);
}
void SCLY::exportToLayerDirectories(const PAK::Entry& entry, PAKRouter<PAKBridge>& pakRouter, bool force) const {
for (atUint32 i = 0; i < layerCount; i++) {
bool active;
hecl::ProjectPath layerPath = pakRouter.getAreaLayerWorking(entry.id, i, active);
if (layerPath.isNone())
layerPath.makeDirChain(true);
if (active) {
const hecl::ProjectPath activePath(layerPath, "!defaultactive");
[[maybe_unused]] const auto fp = hecl::FopenUnique(activePath.getAbsolutePath().data(), "wb");
2018-12-08 05:30:43 +00:00
}
hecl::ProjectPath yamlFile(layerPath, "!objects.yaml");
2018-12-08 05:30:43 +00:00
if (force || yamlFile.isNone()) {
athena::io::FileWriter writer(yamlFile.getAbsolutePath());
athena::io::ToYAMLStream(layers[i], writer);
2015-09-10 20:30:35 +00:00
}
2018-12-08 05:30:43 +00:00
}
2015-09-10 20:30:35 +00:00
}
2018-12-08 05:30:43 +00:00
void SCLY::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const {
for (const ScriptLayer& layer : layers)
layer.addCMDLRigPairs(pakRouter, charAssoc);
}
2018-12-08 05:30:43 +00:00
void SCLY::ScriptLayer::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
CharacterAssociations<UniqueID32>& charAssoc) const {
for (const std::unique_ptr<IScriptObject>& obj : objects)
obj->addCMDLRigPairs(pakRouter, charAssoc);
}
2018-12-08 05:30:43 +00:00
void SCLY::nameIDs(PAKRouter<PAKBridge>& pakRouter) const {
for (const ScriptLayer& layer : layers)
layer.nameIDs(pakRouter);
}
2018-12-08 05:30:43 +00:00
void SCLY::ScriptLayer::nameIDs(PAKRouter<PAKBridge>& pakRouter) const {
for (const std::unique_ptr<IScriptObject>& obj : objects)
obj->nameIDs(pakRouter);
}
2018-02-22 07:24:51 +00:00
template <>
2018-12-08 05:30:43 +00:00
void SCLY::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& docin) {
2019-08-27 03:02:31 +00:00
Do<BigDNA::ReadYaml>(athena::io::PropId{"fourCC"}, fourCC, docin);
2018-12-08 05:30:43 +00:00
version = docin.readUint32("version");
layerCount = docin.enumerate("layerSizes", layerSizes);
docin.enumerate("layers", layers);
2015-09-10 20:30:35 +00:00
}
2018-02-22 07:24:51 +00:00
template <>
2018-12-08 05:30:43 +00:00
void SCLY::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& docout) {
2019-08-27 03:02:31 +00:00
Do<BigDNA::WriteYaml>(athena::io::PropId{"fourCC"}, fourCC, docout);
2018-12-08 05:30:43 +00:00
docout.writeUint32("version", version);
docout.enumerate("layerSizes", layerSizes);
docout.enumerate("layers", layers);
2015-09-10 20:30:35 +00:00
}
2021-04-10 08:42:06 +00:00
std::string_view SCLY::DNAType() { return "DNAMP1::SCLY"sv; }
2015-10-01 00:46:37 +00:00
2018-02-22 07:24:51 +00:00
template <>
2018-12-08 05:30:43 +00:00
void SCLY::ScriptLayer::Enumerate<BigDNA::Read>(athena::io::IStreamReader& rs) {
unknown = rs.readUByte();
objectCount = rs.readUint32Big();
objects.clear();
objects.reserve(objectCount);
for (atUint32 i = 0; i < objectCount; i++) {
atUint8 type = rs.readUByte();
atUint32 len = rs.readUint32Big();
atUint64 start = rs.position();
auto iter = std::find_if(SCRIPT_OBJECT_DB.begin(), SCRIPT_OBJECT_DB.end(),
[&type](const ScriptObjectSpec* obj) -> bool { return obj->type == type; });
if (iter != SCRIPT_OBJECT_DB.end()) {
2022-01-30 20:07:24 +00:00
std::unique_ptr<IScriptObject> obj((*iter)->loader());
2018-12-08 05:30:43 +00:00
obj->type = type;
obj->read(rs);
objects.push_back(std::move(obj));
size_t actualLen = rs.position() - start;
if (actualLen != len)
Log.report(logvisor::Fatal,
FMT_STRING("Error while reading object of type 0x{:02X}, did not read the expected amount of "
"data, read 0x{:x}, expected 0x{:x}"),
(atUint32)type, actualLen, len);
rs.seek(start + len, athena::SeekOrigin::Begin);
} else {
Log.report(logvisor::Fatal, FMT_STRING("Unable to find type 0x{:X} in object database"),
2021-06-07 19:29:18 +00:00
(atUint32)type);
}
2018-12-08 05:30:43 +00:00
}
2015-09-10 20:30:35 +00:00
}
2018-02-22 07:24:51 +00:00
template <>
2018-12-08 05:30:43 +00:00
void SCLY::ScriptLayer::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& rs) {
unknown = rs.readUByte("unknown");
size_t objCount;
objects.clear();
if (auto v = rs.enterSubVector("objects", objCount)) {
objectCount = objCount;
objects.reserve(objCount);
for (atUint32 i = 0; i < objectCount; i++) {
2019-10-01 07:38:03 +00:00
if (auto rec = rs.enterSubRecord()) {
2018-12-08 05:30:43 +00:00
atUint8 type = rs.readUByte("type");
auto iter = std::find_if(SCRIPT_OBJECT_DB.begin(), SCRIPT_OBJECT_DB.end(),
[&type](const ScriptObjectSpec* obj) -> bool { return obj->type == type; });
if (iter != SCRIPT_OBJECT_DB.end()) {
2022-01-30 20:07:24 +00:00
std::unique_ptr<IScriptObject> obj((*iter)->loader());
2018-12-08 05:30:43 +00:00
obj->read(rs);
obj->type = type;
objects.push_back(std::move(obj));
} else
Log.report(logvisor::Fatal, FMT_STRING("Unable to find type 0x{:X} in object database"),
2021-06-07 19:29:18 +00:00
(atUint32)type);
2018-12-08 05:30:43 +00:00
}
2015-09-10 20:30:35 +00:00
}
2018-12-08 05:30:43 +00:00
} else
objectCount = 0;
2015-09-10 20:30:35 +00:00
}
2018-02-22 07:24:51 +00:00
template <>
2018-12-08 05:30:43 +00:00
void SCLY::ScriptLayer::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& ws) {
ws.writeUByte(unknown);
ws.writeUint32Big(objectCount);
for (const std::unique_ptr<IScriptObject>& obj : objects) {
ws.writeByte(obj->type);
size_t expLen = 0;
obj->binarySize(expLen);
ws.writeUint32Big(expLen);
auto start = ws.position();
obj->write(ws);
auto wrote = ws.position() - start;
if (wrote != expLen)
2020-04-11 22:51:39 +00:00
Log.report(logvisor::Error, FMT_STRING("expected writing {} byte SCLY obj; wrote {}"), expLen, wrote);
2018-12-08 05:30:43 +00:00
}
2015-09-10 20:30:35 +00:00
}
2018-02-22 07:24:51 +00:00
template <>
2018-12-08 05:30:43 +00:00
void SCLY::ScriptLayer::Enumerate<BigDNA::BinarySize>(size_t& __isz) {
__isz += 5;
for (const std::unique_ptr<IScriptObject>& obj : objects) {
__isz += 5;
2018-12-08 05:30:43 +00:00
obj->binarySize(__isz);
}
}
2018-02-22 07:24:51 +00:00
template <>
2018-12-08 05:30:43 +00:00
void SCLY::ScriptLayer::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& ws) {
ws.writeUByte("unknown", unknown);
if (auto v = ws.enterSubVector("objects")) {
for (const std::unique_ptr<IScriptObject>& obj : objects) {
2019-10-01 07:38:03 +00:00
if (auto rec = ws.enterSubRecord()) {
2018-12-08 05:30:43 +00:00
ws.writeUByte("type", obj->type);
obj->write(ws);
}
2017-02-12 23:56:03 +00:00
}
2018-12-08 05:30:43 +00:00
}
2015-09-10 20:30:35 +00:00
}
2021-04-10 08:42:06 +00:00
std::string_view SCLY::ScriptLayer::DNAType() { return "DNAMP1::SCLY::ScriptLayer"sv; }
2015-10-01 00:46:37 +00:00
2018-12-08 05:30:43 +00:00
} // namespace DataSpec::DNAMP1