metaforce/DataSpec/DNAMP1/SCLY.cpp

225 lines
6.6 KiB
C++
Raw Normal View History

2015-09-10 20:30:35 +00:00
#include "SCLY.hpp"
#include "ScriptObjects/ScriptTypes.hpp"
2016-02-13 09:02:47 +00:00
namespace DataSpec
2015-09-10 20:30:35 +00:00
{
namespace DNAMP1
{
2016-03-04 23:04:53 +00:00
void SCLY::read(athena::io::IStreamReader& rs)
2015-09-10 20:30:35 +00:00
{
fourCC = rs.readUint32Little();
version = rs.readUint32Big();
layerCount = rs.readUint32Big();
rs.enumerateBig(layerSizes, layerCount);
atUint32 i = 0;
2016-03-04 23:04:53 +00:00
rs.enumerate<ScriptLayer>(layers, layerCount, [&i,this](athena::io::IStreamReader& rs, ScriptLayer& layer) {
2015-09-10 20:30:35 +00:00
atUint64 start = rs.position();
layer.read(rs);
2016-03-04 23:04:53 +00:00
rs.seek(start + layerSizes[i++], athena::Begin);
2015-09-10 20:30:35 +00:00
});
}
2016-03-04 23:04:53 +00:00
void SCLY::write(athena::io::IStreamWriter& ws) const
2015-09-10 20:30:35 +00:00
{
ws.writeUint32Big(fourCC);
ws.writeUint32Big(version);
ws.writeUint32Big(layerCount);
ws.enumerateBig(layerSizes);
ws.enumerate(layers);
}
size_t SCLY::binarySize(size_t __isz) const
{
__isz += 12;
__isz += layerSizes.size() * 4;
return __EnumerateSize(__isz, layers);
}
2016-08-10 02:52:00 +00:00
void SCLY::exportToLayerDirectories(const PAK::Entry& entry, PAKRouter<PAKBridge>& pakRouter, bool force) const
2015-09-10 20:30:35 +00:00
{
for (atUint32 i = 0; i < layerCount; i++)
{
2016-08-10 02:52:00 +00:00
bool active;
hecl::ProjectPath layerPath = pakRouter.getAreaLayerWorking(entry.id, i, active);
2016-09-18 23:47:48 +00:00
if (layerPath.isNone())
layerPath.makeDirChain(true);
2015-09-10 20:30:35 +00:00
2016-08-10 02:52:00 +00:00
if (active)
{
hecl::ProjectPath activePath(layerPath, "!defaultactive");
2017-11-13 06:19:18 +00:00
fclose(hecl::Fopen(activePath.getAbsolutePath().data(), _S("wb")));
2016-08-10 02:52:00 +00:00
}
2016-10-01 23:20:20 +00:00
hecl::ProjectPath yamlFile(layerPath, _S("!objects.yaml"));
2016-09-18 23:47:48 +00:00
if (force || yamlFile.isNone())
2015-09-10 20:30:35 +00:00
{
2016-08-22 03:47:48 +00:00
athena::io::FileWriter writer(yamlFile.getAbsolutePath());
layers[i].toYAMLStream(writer);
2015-09-10 20:30:35 +00:00
}
}
}
void SCLY::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
std::unordered_map<UniqueID32, std::pair<UniqueID32, UniqueID32>>& addTo) const
{
for (const ScriptLayer& layer : layers)
layer.addCMDLRigPairs(pakRouter, addTo);
}
void SCLY::ScriptLayer::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
std::unordered_map<UniqueID32, std::pair<UniqueID32, UniqueID32>>& addTo) const
{
2015-11-29 05:59:34 +00:00
for (const std::unique_ptr<IScriptObject>& obj : objects)
obj->addCMDLRigPairs(pakRouter, addTo);
}
void SCLY::nameIDs(PAKRouter<PAKBridge>& pakRouter) const
{
for (const ScriptLayer& layer : layers)
layer.nameIDs(pakRouter);
}
void SCLY::ScriptLayer::nameIDs(PAKRouter<PAKBridge>& pakRouter) const
{
2015-11-29 05:59:34 +00:00
for (const std::unique_ptr<IScriptObject>& obj : objects)
obj->nameIDs(pakRouter);
}
2016-03-04 23:04:53 +00:00
void SCLY::read(athena::io::YAMLDocReader& docin)
2015-09-10 20:30:35 +00:00
{
fourCC = docin.readUint32("fourCC");
version = docin.readUint32("version");
2016-03-04 01:01:37 +00:00
layerCount = docin.enumerate("layerSizes", layerSizes);
docin.enumerate("layers", layers);
2015-09-10 20:30:35 +00:00
}
2016-03-04 23:04:53 +00:00
void SCLY::write(athena::io::YAMLDocWriter& docout) const
2015-09-10 20:30:35 +00:00
{
docout.writeUint32("fourCC", fourCC);
docout.writeUint32("version", version);
docout.enumerate("layerSizes", layerSizes);
docout.enumerate("layers", layers);
}
2015-10-01 00:46:37 +00:00
const char* SCLY::DNAType()
{
2016-03-04 23:04:53 +00:00
return "urde::DNAMP1::SCLY";
2015-10-01 00:46:37 +00:00
}
2016-03-04 23:04:53 +00:00
void SCLY::ScriptLayer::read(athena::io::IStreamReader& rs)
2015-09-10 20:30:35 +00:00
{
unknown = rs.readUByte();
objectCount = rs.readUint32Big();
2016-03-04 23:04:53 +00:00
objects.clear();
2015-09-10 20:30:35 +00:00
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())
{
2015-11-29 05:59:34 +00:00
std::unique_ptr<IScriptObject> obj((*iter)->a());
2015-09-10 20:30:35 +00:00
obj->type = type;
obj->read(rs);
2015-11-29 05:59:34 +00:00
objects.push_back(std::move(obj));
size_t actualLen = rs.position() - start;
if (actualLen != len)
2016-03-04 23:04:53 +00:00
Log.report(logvisor::Fatal, _S("Error while reading object of type 0x%.2X, did not read the expected amount of data, read 0x%x, expected 0x%x"), (atUint32)type, actualLen, len);
rs.seek(start + len, athena::Begin);
2015-09-10 20:30:35 +00:00
}
else
2016-03-04 23:04:53 +00:00
Log.report(logvisor::Fatal, _S("Unable to find type 0x%X in object database"), (atUint32)type);
2015-09-10 20:30:35 +00:00
}
}
2016-03-04 23:04:53 +00:00
void SCLY::ScriptLayer::read(athena::io::YAMLDocReader& rs)
2015-09-10 20:30:35 +00:00
{
unknown = rs.readUByte("unknown");
2016-03-04 01:01:37 +00:00
size_t objCount;
objects.clear();
2017-02-12 23:56:03 +00:00
if (auto v = rs.enterSubVector("objects", objCount))
2015-09-10 20:30:35 +00:00
{
2016-03-04 01:01:37 +00:00
objectCount = objCount;
objects.reserve(objCount);
for (atUint32 i = 0; i < objectCount; i++)
2015-09-10 20:30:35 +00:00
{
2017-02-12 23:56:03 +00:00
if (auto rec = rs.enterSubRecord(nullptr))
2016-03-04 01:01:37 +00:00
{
2017-02-12 23:56:03 +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())
{
std::unique_ptr<IScriptObject> obj((*iter)->a());
obj->read(rs);
obj->type = type;
objects.push_back(std::move(obj));
}
else
Log.report(logvisor::Fatal, _S("Unable to find type 0x%X in object database"), (atUint32)type);
2016-03-04 01:01:37 +00:00
}
2015-09-10 20:30:35 +00:00
}
}
2016-03-04 01:01:37 +00:00
else
objectCount = 0;
2015-09-10 20:30:35 +00:00
}
2016-03-04 23:04:53 +00:00
void SCLY::ScriptLayer::write(athena::io::IStreamWriter& ws) const
2015-09-10 20:30:35 +00:00
{
ws.writeUByte(unknown);
ws.writeUint32Big(objectCount);
2015-11-29 05:59:34 +00:00
for (const std::unique_ptr<IScriptObject>& obj : objects)
2015-09-10 20:30:35 +00:00
{
ws.writeByte(obj->type);
2016-08-13 01:23:27 +00:00
atUint32 expLen = obj->binarySize(0);
ws.writeUint32Big(expLen);
auto start = ws.position();
2015-09-10 20:30:35 +00:00
obj->write(ws);
2016-08-13 01:23:27 +00:00
auto wrote = ws.position() - start;
if (wrote != expLen)
Log.report(logvisor::Error, "expected writing %lu byte SCLY obj; wrote %llu", expLen, wrote);
2015-09-10 20:30:35 +00:00
}
}
size_t SCLY::ScriptLayer::binarySize(size_t __isz) const
{
__isz += 5;
2015-11-29 05:59:34 +00:00
for (const std::unique_ptr<IScriptObject>& obj : objects)
{
2016-08-13 01:23:27 +00:00
__isz += 5;
__isz = obj->binarySize(__isz);
}
return __isz;
}
2016-03-04 23:04:53 +00:00
void SCLY::ScriptLayer::write(athena::io::YAMLDocWriter& ws) const
2015-09-10 20:30:35 +00:00
{
ws.writeUByte("unknown", unknown);
2017-02-12 23:56:03 +00:00
if (auto v = ws.enterSubVector("objects"))
2015-09-10 20:30:35 +00:00
{
2017-02-12 23:56:03 +00:00
for (const std::unique_ptr<IScriptObject>& obj : objects)
{
if (auto rec = ws.enterSubRecord(nullptr))
{
ws.writeUByte("type", obj->type);
obj->write(ws);
}
}
}
2015-09-10 20:30:35 +00:00
}
2015-10-01 00:46:37 +00:00
const char* SCLY::ScriptLayer::DNAType()
{
2016-03-04 23:04:53 +00:00
return "urde::DNAMP1::SCLY::ScriptLayer";
2015-10-01 00:46:37 +00:00
}
2015-09-10 20:30:35 +00:00
}
}