2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-08 14:24:56 +00:00

Integrate Amuse into hecl cook/extract for MP1/2

This commit is contained in:
Jack Andersen
2018-09-02 14:46:16 -10:00
parent 5a60a0acfc
commit e46ec80b64
150 changed files with 5011 additions and 430 deletions

View File

@@ -1,92 +1,82 @@
#include "AGSC.hpp"
#include "amuse/AudioGroup.hpp"
#include "amuse/AudioGroupData.hpp"
namespace DataSpec::DNAMP2
{
bool AGSC::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
bool AGSC::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& dir)
{
dir.makeDirChain(true);
Header head;
head.read(rs);
auto pool = rs.readUBytes(head.poolSz);
auto proj = rs.readUBytes(head.projSz);
auto sdir = rs.readUBytes(head.sdirSz);
auto samp = rs.readUBytes(head.sampSz);
amuse::AudioGroupData data(proj.get(), head.projSz, pool.get(), head.poolSz,
sdir.get(), head.sdirSz, samp.get(), head.sampSz, amuse::GCNDataTag{});
/* Load into amuse representation */
amuse::ProjectDatabase projDb;
projDb.setIdDatabases();
amuse::AudioGroupDatabase group(data);
group.setGroupPath(dir.getAbsolutePath());
/* Extract samples */
group.getSdir().extractAllCompressed(dir.getAbsolutePath(), data.getSamp());
/* Write out project/pool */
{
hecl::ProjectPath poolPath = outPath.getWithExtension(_S(".pool"), true);
athena::io::FileWriter w(poolPath.getAbsolutePath());
w.writeBytes(rs.readBytes(head.poolSz).get(), head.poolSz);
auto projd = group.getProj().toYAML();
athena::io::FileWriter fo(hecl::ProjectPath(dir, _S("!project.yaml")).getAbsolutePath());
if (fo.hasError())
return false;
fo.writeUBytes(projd.data(), projd.size());
}
{
hecl::ProjectPath projPath = outPath.getWithExtension(_S(".proj"), true);
athena::io::FileWriter w(projPath.getAbsolutePath());
w.writeBytes(rs.readBytes(head.projSz).get(), head.projSz);
}
{
hecl::ProjectPath sdirPath = outPath.getWithExtension(_S(".sdir"), true);
athena::io::FileWriter w(sdirPath.getAbsolutePath());
w.writeBytes(rs.readBytes(head.sdirSz).get(), head.sdirSz);
}
{
hecl::ProjectPath sampPath = outPath.getWithExtension(_S(".samp"), true);
athena::io::FileWriter w(sampPath.getAbsolutePath());
w.writeBytes(rs.readBytes(head.sampSz).get(), head.sampSz);
auto poold = group.getPool().toYAML();
athena::io::FileWriter fo(hecl::ProjectPath(dir, _S("!pool.yaml")).getAbsolutePath());
if (fo.hasError())
return false;
fo.writeUBytes(poold.data(), poold.size());
}
return true;
}
bool AGSC::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath)
bool AGSC::Cook(const hecl::ProjectPath& dir, const hecl::ProjectPath& outPath)
{
athena::io::FileWriter w(outPath.getAbsolutePath());
if (w.hasError())
return false;
hecl::ProjectPath woExt = inPath.getWithExtension(nullptr, true);
std::string lastComp = std::string(woExt.getLastComponentUTF8());
if (hecl::StringUtils::EndsWith(lastComp, "_AGSC"))
lastComp.assign(lastComp.cbegin(), lastComp.cend() - 5);
amuse::ProjectDatabase projDb;
projDb.setIdDatabases();
amuse::AudioGroupDatabase group(dir.getAbsolutePath());
hecl::ProjectPath poolPath = inPath.getWithExtension(_S(".pool"), true);
athena::io::FileReader poolR(poolPath.getAbsolutePath());
if (poolR.hasError())
return false;
uint32_t poolLen = poolR.length();
hecl::ProjectPath projPath = inPath.getWithExtension(_S(".proj"), true);
athena::io::FileReader projR(projPath.getAbsolutePath());
if (projR.hasError())
return false;
uint32_t projLen = projR.length();
hecl::ProjectPath sdirPath = inPath.getWithExtension(_S(".sdir"), true);
athena::io::FileReader sdirR(sdirPath.getAbsolutePath());
if (sdirR.hasError())
return false;
uint32_t sdirLen = sdirR.length();
hecl::ProjectPath sampPath = inPath.getWithExtension(_S(".samp"), true);
athena::io::FileReader sampR(sampPath.getAbsolutePath());
if (sampR.hasError())
return false;
uint32_t sampLen = sampR.length();
projR.seek(4, athena::SeekOrigin::Begin);
uint16_t groupId = projR.readUint16Big();
projR.seek(0, athena::SeekOrigin::Begin);
auto proj = group.getProj().toGCNData(group.getPool(), group.getSdir());
auto pool = group.getPool().toData<athena::Big>();
auto sdirSamp = group.getSdir().toGCNData(group);
Header head;
head.groupName = lastComp;
head.groupId = groupId;
head.poolSz = poolLen;
head.projSz = projLen;
head.sdirSz = sdirLen;
head.sampSz = sampLen;
head.groupName = dir.getLastComponentUTF8();
for (const auto& p : group.getProj().sfxGroups())
head.groupId = p.first.id;
head.poolSz = pool.size();
head.projSz = proj.size();
head.sdirSz = sdirSamp.first.size();
head.sampSz = sdirSamp.second.size();
head.write(w);
w.writeBytes(poolR.readBytes(poolLen).get(), poolLen);
w.writeBytes(projR.readBytes(projLen).get(), projLen);
w.writeBytes(sdirR.readBytes(sdirLen).get(), sdirLen);
w.writeBytes(sampR.readBytes(sampLen).get(), sampLen);
w.writeUBytes(pool.data(), pool.size());
w.writeUBytes(proj.data(), proj.size());
w.writeUBytes(sdirSamp.first.data(), sdirSamp.first.size());
w.writeUBytes(sdirSamp.second.data(), sdirSamp.second.size());
return true;
}

View File

@@ -9,6 +9,7 @@ namespace DataSpec::DNAMP2
class AGSC
{
public:
struct Header : BigDNA
{
AT_DECL_DNA
@@ -20,7 +21,6 @@ class AGSC
Value<atUint32> sdirSz = 0;
Value<atUint32> sampSz = 0;
};
public:
static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
};

View File

@@ -221,7 +221,7 @@ struct ANCS : BigDNA
PAKEntryReadStream& rs,
const hecl::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry,
const DNAMP2::PAK::Entry& entry,
bool force,
hecl::blender::Token& btok,
std::function<void(const hecl::SystemChar*)> fileChanged)

View File

@@ -8,7 +8,7 @@ bool CMDL::Extract(const SpecBase& dataSpec,
PAKEntryReadStream& rs,
const hecl::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry,
const DNAMP2::PAK::Entry& entry,
bool,
hecl::blender::Token& btok,
std::function<void(const hecl::SystemChar*)>)

View File

@@ -17,7 +17,7 @@ struct CMDL
PAKEntryReadStream& rs,
const hecl::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry,
const DNAMP2::PAK::Entry& entry,
bool,
hecl::blender::Token& btok,
std::function<void(const hecl::SystemChar*)>);

View File

@@ -13,6 +13,7 @@ make_dnalist(liblist DNAMP2
set(DNAMP2_SOURCES
DNAMP2.hpp DNAMP2.cpp
DeafBabe.cpp
PAK.cpp
ANIM.cpp
AGSC.cpp
CINF.cpp

View File

@@ -42,13 +42,13 @@ PAKBridge::PAKBridge(const nod::Node& node,
/* Append Level String */
for (const auto& entry : m_pak.m_entries)
{
const DNAMP1::PAK::Entry& e = entry.second;
const DNAMP2::PAK::Entry& e = entry.second;
if (e.type == FOURCC('MLVL'))
{
PAKEntryReadStream rs = e.beginReadStream(m_node);
MLVL mlvl;
mlvl.read(rs);
const DNAMP1::PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId);
const DNAMP2::PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId);
if (nameEnt)
{
PAKEntryReadStream rs = nameEnt->beginReadStream(m_node);
@@ -76,7 +76,7 @@ void PAKBridge::build()
/* First pass: build per-area/per-layer dependency map */
for (const auto& entry : m_pak.m_entries)
{
const DNAMP1::PAK::Entry& e = entry.second;
const DNAMP2::PAK::Entry& e = entry.second;
if (e.type == FOURCC('MLVL'))
{
Level& level = m_levelDeps[e.id];
@@ -87,13 +87,13 @@ void PAKBridge::build()
mlvl.read(rs);
}
bool named;
std::string bestName = m_pak.bestEntryName(e, named);
std::string bestName = m_pak.bestEntryName(m_node, e, named);
level.name = hecl::SystemStringConv(bestName).sys_str();
level.areas.reserve(mlvl.areaCount);
unsigned layerIdx = 0;
/* Make MAPW available to lookup MAPAs */
const DNAMP1::PAK::Entry* worldMapEnt = m_pak.lookupEntry(mlvl.worldMap);
const DNAMP2::PAK::Entry* worldMapEnt = m_pak.lookupEntry(mlvl.worldMap);
std::vector<UniqueID32> mapw;
if (worldMapEnt)
{
@@ -111,7 +111,7 @@ void PAKBridge::build()
{
Level::Area& areaDeps = level.areas[area.areaMREAId];
MLVL::LayerFlags& layerFlags = mlvl.layerFlags[ai];
const DNAMP1::PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
const DNAMP2::PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
if (areaNameEnt)
{
STRG areaName;
@@ -173,7 +173,7 @@ void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter,
std::unordered_map<UniqueID32, std::pair<UniqueID32, UniqueID32>>& addTo,
std::unordered_map<UniqueID32, std::pair<UniqueID32, std::string>>& cskrCinfToAncs) const
{
for (const std::pair<UniqueID32, DNAMP1::PAK::Entry>& entry : m_pak.m_entries)
for (const std::pair<UniqueID32, DNAMP2::PAK::Entry>& entry : m_pak.m_entries)
{
if (entry.second.type == FOURCC('ANCS'))
{
@@ -201,7 +201,7 @@ void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
std::unordered_map<UniqueID32, zeus::CMatrix4f>& addTo,
std::unordered_map<UniqueID32, hecl::ProjectPath>& pathOverrides) const
{
for (const std::pair<UniqueID32, DNAMP1::PAK::Entry>& entry : m_pak.m_entries)
for (const std::pair<UniqueID32, DNAMP2::PAK::Entry>& entry : m_pak.m_entries)
{
if (entry.second.type == FOURCC('MLVL'))
{
@@ -225,7 +225,7 @@ void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
if (mlvl.worldMap)
{
const nod::Node* mapNode;
const DNAMP1::PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode);
const DNAMP2::PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode);
if (mapEntry)
{
PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode);
@@ -252,7 +252,8 @@ void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
}
}
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK& pak, const DNAMP1::PAK::Entry& entry)
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, const DNAMP2::PAK& pak,
const DNAMP2::PAK::Entry& entry)
{
switch (entry.type)
{
@@ -285,7 +286,7 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK& pak, const
case SBIG('DGRP'):
return {DNADGRP::ExtractDGRP<UniqueID32>, {_S(".yaml")}};
case SBIG('AGSC'):
return {AGSC::Extract, {_S(".pool"), _S(".proj"), _S(".samp"), _S(".sdir")}};
return {AGSC::Extract, {}};
case SBIG('CSNG'):
return {DNAMP1::CSNG::Extract, {_S(".mid"), _S(".yaml")}};
case SBIG('ATBL'):

View File

@@ -2,7 +2,7 @@
#define __DNAMP2_HPP__
#include "DataSpec/DNACommon/DNACommon.hpp"
#include "../DNAMP1/PAK.hpp"
#include "PAK.hpp"
namespace DataSpec::DNAMP2
{
@@ -13,7 +13,7 @@ extern logvisor::Module Log;
class PAKBridge
{
const nod::Node& m_node;
DNAMP1::PAK m_pak;
DNAMP2::PAK m_pak;
public:
bool m_doExtract;
using Level = DataSpec::Level<UniqueID32>;
@@ -22,11 +22,12 @@ public:
PAKBridge(const nod::Node& node, bool doExtract=true);
void build();
static ResExtractor<PAKBridge> LookupExtractor(const DNAMP1::PAK& pak, const DNAMP1::PAK::Entry& entry);
static ResExtractor<PAKBridge> LookupExtractor(const nod::Node& pakNode,
const DNAMP2::PAK& pak, const DNAMP2::PAK::Entry& entry);
std::string_view getName() const {return m_node.getName();}
hecl::SystemStringView getLevelString() const {return m_levelString;}
using PAKType = DNAMP1::PAK;
using PAKType = DNAMP2::PAK;
const PAKType& getPAK() const {return m_pak;}
const nod::Node& getNode() const {return m_node;}

View File

@@ -96,7 +96,7 @@ struct DeafBabe : BigDNA
bool surfaceMud() const { return false; }
void setSurfaceMud(bool v) {}
bool surfaceStoneRock() const { return false; }
void setSurfaceStoneRock(bool v) {}
void setSurfaceLavaStone(bool v) {}
bool solid() const { return false; }
void setSolid(bool v) {}
bool noPlatformCollision() const { return false; }

View File

@@ -13,7 +13,7 @@ struct MAPA : DNAMAPA::MAPA
PAKEntryReadStream& rs,
const hecl::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry,
const DNAMP2::PAK::Entry& entry,
bool force,
hecl::blender::Token& btok,
std::function<void(const hecl::SystemChar*)> fileChanged)

View File

@@ -16,7 +16,7 @@ struct MAPU : DNAMAPU::MAPU
PAKEntryReadStream& rs,
const hecl::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry,
const DNAMP2::PAK::Entry& entry,
bool force,
hecl::blender::Token& btok,
std::function<void(const hecl::SystemChar*)> fileChanged)

View File

@@ -96,7 +96,7 @@ struct MLVL : BigDNA
PAKEntryReadStream& rs,
const hecl::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry,
const DNAMP2::PAK::Entry& entry,
bool force,
hecl::blender::Token& btok,
std::function<void(const hecl::SystemChar*)> fileChanged)

View File

@@ -164,7 +164,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
PAKEntryReadStream& rs,
const hecl::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry,
const DNAMP2::PAK::Entry& entry,
bool force,
hecl::blender::Token& btok,
std::function<void(const hecl::SystemChar*)>)

View File

@@ -119,7 +119,7 @@ struct MREA
PAKEntryReadStream& rs,
const hecl::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry,
const DNAMP2::PAK::Entry& entry,
bool,
hecl::blender::Token& btok,
std::function<void(const hecl::SystemChar*)>);

23
DataSpec/DNAMP2/PAK.cpp Normal file
View File

@@ -0,0 +1,23 @@
#include "PAK.hpp"
#include "AGSC.hpp"
namespace DataSpec::DNAMP2
{
std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const
{
std::unordered_map<UniqueID32, Entry>::const_iterator search;
if (entry.type == FOURCC('AGSC') && (search = m_entries.find(entry.id)) != m_entries.cend())
{
/* Use internal AGSC name for entry */
auto rs = search->second.beginReadStream(pakNode);
AGSC::Header header;
header.read(rs);
named = true;
return header.groupName;
}
return DNAMP1::PAK::bestEntryName(pakNode, entry, named);
}
}

View File

@@ -3,11 +3,15 @@
#include "../DNAMP1/PAK.hpp"
namespace urde::DNAMP2
namespace DataSpec::DNAMP2
{
/* Same PAK format as MP1 */
using PAK = DNAMP1::PAK;
struct PAK : DNAMP1::PAK
{
using DNAMP1::PAK::PAK;
std::string bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const;
};
}