Added support for tracking AGSC dependencies
This commit is contained in:
parent
2e1add84be
commit
10c87779b3
|
@ -1,4 +1,5 @@
|
|||
#include "CDependencyTree.h"
|
||||
#include "Core/GameProject/CGameProject.h"
|
||||
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||
#include "Core/Resource/Script/CScriptLayer.h"
|
||||
#include "Core/Resource/Script/CScriptObject.h"
|
||||
|
@ -120,6 +121,22 @@ void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependenc
|
|||
if (Type == eStructProperty || Type == eArrayProperty)
|
||||
ParseStructDependencies(pInst, static_cast<CPropertyStruct*>(pProp));
|
||||
|
||||
else if (Type == eSoundProperty)
|
||||
{
|
||||
u32 SoundID = static_cast<TSoundProperty*>(pProp)->Get();
|
||||
|
||||
if (SoundID != -1)
|
||||
{
|
||||
SSoundInfo Info = CGameProject::ActiveProject()->AudioManager()->GetSoundInfo(SoundID);
|
||||
|
||||
if (Info.pAudioGroup)
|
||||
{
|
||||
CPropertyDependency *pDep = new CPropertyDependency(pProp->IDString(true), Info.pAudioGroup->ID());
|
||||
pInst->mChildren.push_back(pDep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (Type == eAssetProperty)
|
||||
{
|
||||
CAssetID ID = static_cast<TAssetProperty*>(pProp)->Get();
|
||||
|
|
|
@ -19,11 +19,12 @@
|
|||
|
||||
CGameExporter::CGameExporter(const TString& rkInputDir, const TString& rkOutputDir)
|
||||
{
|
||||
mGame = eUnknownGame;
|
||||
mGameDir = FileUtil::MakeAbsolute(rkInputDir);
|
||||
mExportDir = FileUtil::MakeAbsolute(rkOutputDir);
|
||||
|
||||
mpProject = new CGameProject(mExportDir);
|
||||
mDiscDir = mpProject->DiscDir(true);
|
||||
mDiscDir = L"Disc\\";
|
||||
mWorldsDirName = L"Worlds\\";
|
||||
}
|
||||
|
||||
|
@ -38,12 +39,18 @@ bool CGameExporter::Export()
|
|||
FileUtil::CreateDirectory(mExportDir);
|
||||
FileUtil::ClearDirectory(mExportDir);
|
||||
|
||||
// Initial analyze/copy of disc data
|
||||
CopyDiscData();
|
||||
mpStore = new CResourceStore(this, L"Content\\", L"Cooked\\", mpProject->Game());
|
||||
mpStore->SetProject(mpProject);
|
||||
|
||||
// Create project
|
||||
mpProject = new CGameProject(this, mExportDir, mGame);
|
||||
mpProject->SetProjectName(CMasterTemplate::FindGameName(mGame));
|
||||
mpProject->SetActive();
|
||||
mpStore = mpProject->ResourceStore();
|
||||
mContentDir = mpStore->RawDir(false);
|
||||
mCookedDir = mpStore->CookedDir(false);
|
||||
|
||||
// Export game data
|
||||
CResourceStore *pOldStore = gpResourceStore;
|
||||
gpResourceStore = mpStore;
|
||||
|
||||
|
@ -51,10 +58,12 @@ bool CGameExporter::Export()
|
|||
LoadPaks();
|
||||
ExportWorlds();
|
||||
ExportCookedResources();
|
||||
mpProject->AudioManager()->LoadAssets();
|
||||
ExportResourceEditorData();
|
||||
|
||||
// Export finished!
|
||||
delete mpProject;
|
||||
gpResourceStore = pOldStore;
|
||||
delete mpStore;
|
||||
mpStore = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -89,16 +98,16 @@ void CGameExporter::CopyDiscData()
|
|||
continue;
|
||||
|
||||
// Hack to determine game
|
||||
if (Game() == eUnknownGame)
|
||||
if (mGame == eUnknownGame)
|
||||
{
|
||||
TWideString Name = FullPath.GetFileName(false);
|
||||
if (Name == L"MetroidCWP") SetGame(ePrimeDemo);
|
||||
else if (Name == L"NESemu") SetGame(ePrime);
|
||||
else if (Name == L"PirateGun") SetGame(eEchoesDemo);
|
||||
else if (Name == L"AtomicBeta") SetGame(eEchoes);
|
||||
else if (Name == L"InGameAudio") SetGame(eCorruptionProto);
|
||||
else if (Name == L"GuiDVD") SetGame(eCorruption);
|
||||
else if (Name == L"PreloadData") SetGame(eReturns);
|
||||
if (Name == L"MetroidCWP") mGame = ePrimeDemo;
|
||||
else if (Name == L"NESemu") mGame = ePrime;
|
||||
else if (Name == L"PirateGun") mGame = eEchoesDemo;
|
||||
else if (Name == L"AtomicBeta") mGame = eEchoes;
|
||||
else if (Name == L"InGameAudio") mGame = eCorruptionProto;
|
||||
else if (Name == L"GuiDVD") mGame = eCorruption;
|
||||
else if (Name == L"PreloadData") mGame = eReturns;
|
||||
}
|
||||
|
||||
// Detect paks
|
||||
|
@ -116,9 +125,7 @@ void CGameExporter::CopyDiscData()
|
|||
#endif
|
||||
}
|
||||
|
||||
ASSERT(Game() != eUnknownGame);
|
||||
mpProject->SetGame(Game());
|
||||
mpProject->SetProjectName(CMasterTemplate::FindGameName(Game()));
|
||||
ASSERT(mGame != eUnknownGame);
|
||||
}
|
||||
|
||||
void CGameExporter::LoadAssetList()
|
||||
|
@ -128,7 +135,7 @@ void CGameExporter::LoadAssetList()
|
|||
// Determine the asset list to use
|
||||
TString ListFile = "../resources/list/AssetList";
|
||||
|
||||
switch (Game())
|
||||
switch (mGame)
|
||||
{
|
||||
case ePrimeDemo: ListFile += "MP1Demo"; break;
|
||||
case ePrime: ListFile += "MP1"; break;
|
||||
|
@ -177,7 +184,6 @@ void CGameExporter::LoadPaks()
|
|||
{
|
||||
#if LOAD_PAKS
|
||||
SCOPED_TIMER(LoadPaks);
|
||||
EIDLength IDLength = (Game() < eCorruptionProto ? e32Bit : e64Bit);
|
||||
|
||||
for (auto It = mPaks.begin(); It != mPaks.end(); It++)
|
||||
{
|
||||
|
@ -196,7 +202,7 @@ void CGameExporter::LoadPaks()
|
|||
CResourceCollection *pCollection = pPackage->AddCollection("Default");
|
||||
|
||||
// MP1-MP3Proto
|
||||
if (Game() < eCorruption)
|
||||
if (mGame < eCorruption)
|
||||
{
|
||||
u32 PakVersion = Pak.ReadLong();
|
||||
Pak.Seek(0x4, SEEK_CUR);
|
||||
|
@ -211,7 +217,7 @@ void CGameExporter::LoadPaks()
|
|||
for (u32 iName = 0; iName < NumNamedResources; iName++)
|
||||
{
|
||||
CFourCC ResType = Pak.ReadLong();
|
||||
CAssetID ResID(Pak, IDLength);
|
||||
CAssetID ResID(Pak, mGame);
|
||||
u32 NameLen = Pak.ReadLong();
|
||||
TString Name = Pak.ReadString(NameLen);
|
||||
pCollection->AddResource(Name, ResID, ResType);
|
||||
|
@ -228,7 +234,7 @@ void CGameExporter::LoadPaks()
|
|||
{
|
||||
bool Compressed = (Pak.ReadLong() == 1);
|
||||
CFourCC ResType = Pak.ReadLong();
|
||||
CAssetID ResID(Pak, IDLength);
|
||||
CAssetID ResID(Pak, mGame);
|
||||
u32 ResSize = Pak.ReadLong();
|
||||
u32 ResOffset = Pak.ReadLong();
|
||||
|
||||
|
@ -288,7 +294,7 @@ void CGameExporter::LoadPaks()
|
|||
{
|
||||
TString Name = Pak.ReadString();
|
||||
CFourCC ResType = Pak.ReadLong();
|
||||
CAssetID ResID(Pak, IDLength);
|
||||
CAssetID ResID(Pak, mGame);
|
||||
pCollection->AddResource(Name, ResID, ResType);
|
||||
SetResourcePath(ResID, PakName + L"\\", Name.ToUTF16());
|
||||
}
|
||||
|
@ -308,7 +314,7 @@ void CGameExporter::LoadPaks()
|
|||
{
|
||||
bool Compressed = (Pak.ReadLong() == 1);
|
||||
CFourCC Type = Pak.ReadLong();
|
||||
CAssetID ResID(Pak, IDLength);
|
||||
CAssetID ResID(Pak, mGame);
|
||||
u32 Size = Pak.ReadLong();
|
||||
u32 Offset = DataStart + Pak.ReadLong();
|
||||
|
||||
|
@ -316,7 +322,7 @@ void CGameExporter::LoadPaks()
|
|||
mResourceMap[ResID] = SResourceInstance { PakPath, ResID, Type, Offset, Size, Compressed, false };
|
||||
|
||||
// Check for duplicate resources (unnecessary for DKCR)
|
||||
if (Game() != eReturns)
|
||||
if (mGame != eReturns)
|
||||
{
|
||||
if (Type == "MREA")
|
||||
{
|
||||
|
@ -357,9 +363,9 @@ void CGameExporter::LoadResource(const SResourceInstance& rkResource, std::vecto
|
|||
// Handle compression
|
||||
if (rkResource.Compressed)
|
||||
{
|
||||
bool ZlibCompressed = (Game() <= eEchoesDemo || Game() == eReturns);
|
||||
bool ZlibCompressed = (mGame <= eEchoesDemo || mGame == eReturns);
|
||||
|
||||
if (Game() <= eCorruptionProto)
|
||||
if (mGame <= eCorruptionProto)
|
||||
{
|
||||
std::vector<u8> CompressedData(rkResource.PakSize);
|
||||
|
||||
|
@ -539,6 +545,10 @@ void CGameExporter::ExportCookedResources()
|
|||
#endif
|
||||
mpProject->Save();
|
||||
}
|
||||
}
|
||||
|
||||
void CGameExporter::ExportResourceEditorData()
|
||||
{
|
||||
{
|
||||
// Save raw versions of resources + resource cache data files
|
||||
// Note this has to be done after all cooked resources are exported
|
||||
|
|
|
@ -14,6 +14,7 @@ class CGameExporter
|
|||
// Project
|
||||
CGameProject *mpProject;
|
||||
CResourceStore *mpStore;
|
||||
EGame mGame;
|
||||
|
||||
// Directories
|
||||
TWideString mGameDir;
|
||||
|
@ -59,6 +60,7 @@ protected:
|
|||
void LoadResource(const SResourceInstance& rkResource, std::vector<u8>& rBuffer);
|
||||
void ExportWorlds();
|
||||
void ExportCookedResources();
|
||||
void ExportResourceEditorData();
|
||||
void ExportResource(SResourceInstance& rRes);
|
||||
|
||||
// Convenience Functions
|
||||
|
@ -80,9 +82,6 @@ protected:
|
|||
{
|
||||
mResourcePaths[rkID] = SResourcePath { rkDir, rkName };
|
||||
}
|
||||
|
||||
inline EGame Game() const { return mpProject->Game(); }
|
||||
inline void SetGame(EGame Game) { mpProject->SetGame(Game); }
|
||||
};
|
||||
|
||||
#endif // CGAMEEXPORTER_H
|
||||
|
|
|
@ -8,6 +8,9 @@ CGameProject::~CGameProject()
|
|||
{
|
||||
if (IsActive())
|
||||
mspActiveProject = nullptr;
|
||||
|
||||
delete mpAudioManager;
|
||||
delete mpResourceStore;
|
||||
}
|
||||
|
||||
bool CGameProject::Load(const TWideString& rkPath)
|
||||
|
@ -20,7 +23,7 @@ bool CGameProject::Load(const TWideString& rkPath)
|
|||
Serialize(Reader);
|
||||
|
||||
mpResourceStore->LoadResourceDatabase();
|
||||
mAudioManager.LoadAssets();
|
||||
mpAudioManager->LoadAssets();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "CPackage.h"
|
||||
#include "CResourceStore.h"
|
||||
#include "Core/CAudioManager.h"
|
||||
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||
#include <Common/CAssetID.h>
|
||||
#include <Common/EGame.h>
|
||||
#include <Common/FileUtil.h>
|
||||
|
@ -18,7 +19,7 @@ class CGameProject
|
|||
TWideString mResourceDBPath;
|
||||
std::vector<CPackage*> mPackages;
|
||||
CResourceStore *mpResourceStore;
|
||||
CAudioManager mAudioManager;
|
||||
CAudioManager *mpAudioManager;
|
||||
|
||||
enum EProjectVersion
|
||||
{
|
||||
|
@ -34,9 +35,10 @@ public:
|
|||
CGameProject()
|
||||
: mGame(eUnknownGame)
|
||||
, mProjectName("Unnamed Project")
|
||||
, mAudioManager(this)
|
||||
, mResourceDBPath(L"ResourceDB.rdb")
|
||||
{
|
||||
mpResourceStore = new CResourceStore(this);
|
||||
mpAudioManager = new CAudioManager(this);
|
||||
}
|
||||
|
||||
CGameProject(const TWideString& rkProjRootDir)
|
||||
|
@ -44,9 +46,20 @@ public:
|
|||
, mProjectName("Unnamed Project")
|
||||
, mProjectRoot(rkProjRootDir)
|
||||
, mResourceDBPath(L"ResourceDB.rdb")
|
||||
, mAudioManager(this)
|
||||
{
|
||||
mpResourceStore = new CResourceStore(this);
|
||||
mpAudioManager = new CAudioManager(this);
|
||||
mProjectRoot.Replace(L"/", L"\\");
|
||||
}
|
||||
|
||||
CGameProject(CGameExporter *pExporter, const TWideString& rkProjRootDir, EGame Game)
|
||||
: mGame(Game)
|
||||
, mProjectName(CMasterTemplate::FindGameName(Game))
|
||||
, mProjectRoot(rkProjRootDir)
|
||||
, mResourceDBPath(L"ResourceDB.rdb")
|
||||
{
|
||||
mpResourceStore = new CResourceStore(this, pExporter, L"Content\\", L"Cooked\\", Game);
|
||||
mpAudioManager = new CAudioManager(this);
|
||||
mProjectRoot.Replace(L"/", L"\\");
|
||||
}
|
||||
|
||||
|
@ -69,14 +82,13 @@ public:
|
|||
inline TWideString ResourceCachePath(bool Relative) const { return ResourceDBPath(Relative).GetFileDirectory() + L"ResourceCacheData.rcd"; }
|
||||
|
||||
// Accessors
|
||||
inline void SetGame(EGame Game) { mGame = Game; }
|
||||
inline void SetProjectName(const TString& rkName) { mProjectName = rkName; }
|
||||
|
||||
inline u32 NumPackages() const { return mPackages.size(); }
|
||||
inline CPackage* PackageByIndex(u32 Index) const { return mPackages[Index]; }
|
||||
inline void AddPackage(CPackage *pPackage) { mPackages.push_back(pPackage); }
|
||||
inline CResourceStore* ResourceStore() const { return mpResourceStore; }
|
||||
inline CAudioManager* AudioManager() { return &mAudioManager; }
|
||||
inline CAudioManager* AudioManager() const { return mpAudioManager; }
|
||||
inline EGame Game() const { return mGame; }
|
||||
inline bool IsActive() const { return mspActiveProject == this; }
|
||||
|
||||
|
|
|
@ -16,8 +16,9 @@ CResourceEntry::CResourceEntry(CResourceStore *pStore, const CAssetID& rkID,
|
|||
, mpStore(pStore)
|
||||
, mpDependencies(nullptr)
|
||||
, mID(rkID)
|
||||
, mName(rkFilename)
|
||||
, mType(Type)
|
||||
, mpDirectory(nullptr)
|
||||
, mName(rkFilename)
|
||||
, mCachedSize(-1)
|
||||
, mCachedUppercaseName(rkFilename.ToUpper())
|
||||
{
|
||||
|
|
|
@ -24,13 +24,14 @@ CResourceStore::CResourceStore(const TWideString& rkDatabasePath)
|
|||
mDatabaseName = rkDatabasePath.GetFileName();
|
||||
}
|
||||
|
||||
CResourceStore::CResourceStore(CGameExporter *pExporter, const TWideString& rkRawDir, const TWideString& rkCookedDir, EGame Game)
|
||||
CResourceStore::CResourceStore(CGameProject *pProject, CGameExporter *pExporter, const TWideString& rkRawDir, const TWideString& rkCookedDir, EGame Game)
|
||||
: mpProj(nullptr)
|
||||
, mGame(Game)
|
||||
, mRawDir(rkRawDir)
|
||||
, mCookedDir(rkCookedDir)
|
||||
, mpExporter(pExporter)
|
||||
{
|
||||
SetProject(pProject);
|
||||
}
|
||||
|
||||
CResourceStore::CResourceStore(CGameProject *pProject)
|
||||
|
|
|
@ -46,7 +46,7 @@ class CResourceStore
|
|||
|
||||
public:
|
||||
CResourceStore(const TWideString& rkDatabasePath);
|
||||
CResourceStore(CGameExporter *pExporter, const TWideString& rkRawDir, const TWideString& rkCookedDir, EGame Game);
|
||||
CResourceStore(CGameProject *pProject, CGameExporter *pExporter, const TWideString& rkRawDir, const TWideString& rkCookedDir, EGame Game);
|
||||
CResourceStore(CGameProject *pProject);
|
||||
~CResourceStore();
|
||||
void SerializeResourceDatabase(IArchive& rArc);
|
||||
|
|
|
@ -273,14 +273,13 @@ void CPackageDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurE
|
|||
for (u32 iChild = 0; iChild < pNode->NumChildren(); iChild++)
|
||||
EvaluateDependencyNode(pCurEntry, pNode->ChildByIndex(iChild), rOut);
|
||||
|
||||
|
||||
if (Type == eDNT_ScriptInstance)
|
||||
mIsPlayerActor = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ************ CAreaDependencyListBuilder ************
|
||||
void CAreaDependencyListBuilder::BuildDependencyList(std::list<CAssetID>& rAssetsOut, std::list<u32>& rLayerOffsetsOut)
|
||||
void CAreaDependencyListBuilder::BuildDependencyList(std::list<CAssetID>& rAssetsOut, std::list<u32>& rLayerOffsetsOut, std::set<CAssetID> *pAudioGroupsOut)
|
||||
{
|
||||
CAreaDependencyTree *pTree = static_cast<CAreaDependencyTree*>(mpAreaEntry->Dependencies());
|
||||
|
||||
|
@ -331,7 +330,7 @@ void CAreaDependencyListBuilder::BuildDependencyList(std::list<CAssetID>& rAsset
|
|||
continue;
|
||||
}
|
||||
|
||||
AddDependency(pDep->ID(), rAssetsOut);
|
||||
AddDependency(pDep->ID(), rAssetsOut, pAudioGroupsOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -344,24 +343,27 @@ void CAreaDependencyListBuilder::BuildDependencyList(std::list<CAssetID>& rAsset
|
|||
for (u32 iDep = 0; iDep < BaseEndIndex; iDep++)
|
||||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pTree->ChildByIndex(iDep));
|
||||
AddDependency(pDep->ID(), rAssetsOut);
|
||||
AddDependency(pDep->ID(), rAssetsOut, pAudioGroupsOut);
|
||||
}
|
||||
}
|
||||
|
||||
void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<CAssetID>& rOut)
|
||||
void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<CAssetID>& rOut, std::set<CAssetID> *pAudioGroupsOut)
|
||||
{
|
||||
CResourceEntry *pEntry = gpResourceStore->FindEntry(rkID);
|
||||
if (!pEntry) return;
|
||||
|
||||
EResType ResType = pEntry->ResourceType();
|
||||
|
||||
// Check if this is a valid dependency
|
||||
bool IsValid = ResType != eMidi &&
|
||||
ResType != eWorld &&
|
||||
ResType != eArea &&
|
||||
(ResType != eAudioGroup || mGame >= eEchoesDemo);
|
||||
// If this is an audio group, for MP1, save it in the output set. For MP2, treat audio groups as a normal dependency.
|
||||
if (mGame <= ePrime && ResType == eAudioGroup)
|
||||
{
|
||||
if (pAudioGroupsOut) pAudioGroupsOut->insert(rkID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValid) return;
|
||||
// Check to ensure this is a valid/new dependency
|
||||
if (ResType == eWorld || ResType == eArea)
|
||||
return;
|
||||
|
||||
if (mBaseUsedAssets.find(rkID) != mBaseUsedAssets.end() || mLayerUsedAssets.find(rkID) != mLayerUsedAssets.end())
|
||||
return;
|
||||
|
@ -378,7 +380,7 @@ void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<C
|
|||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pTree->ChildByIndex(iDep));
|
||||
ASSERT(pDep->Type() == eDNT_ResourceDependency);
|
||||
AddDependency(pDep->ID(), rOut);
|
||||
AddDependency(pDep->ID(), rOut, pAudioGroupsOut);
|
||||
}
|
||||
|
||||
for (u32 iChar = 0; iChar < pTree->NumCharacters(); iChar++)
|
||||
|
@ -395,7 +397,7 @@ void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<C
|
|||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pTree->ChildByIndex(iDep));
|
||||
ASSERT(pDep->Type() == eDNT_ResourceDependency);
|
||||
AddDependency(pDep->ID(), rOut);
|
||||
AddDependency(pDep->ID(), rOut, pAudioGroupsOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -409,9 +411,11 @@ void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<C
|
|||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pTree->ChildByIndex(iDep));
|
||||
ASSERT(pDep->Type() == eDNT_ResourceDependency);
|
||||
AddDependency(pDep->ID(), rOut);
|
||||
AddDependency(pDep->ID(), rOut, pAudioGroupsOut);
|
||||
}
|
||||
}
|
||||
|
||||
rOut.push_back(rkID);
|
||||
// Don't add CSNGs to the output dependency list (we parse them because we need their AGSC dependencies in the output AudioGroup set)
|
||||
if (ResType != eMidi)
|
||||
rOut.push_back(rkID);
|
||||
}
|
||||
|
|
|
@ -72,8 +72,8 @@ public:
|
|||
ASSERT(mpAreaEntry->ResourceType() == eArea);
|
||||
}
|
||||
|
||||
void BuildDependencyList(std::list<CAssetID>& rAssetsOut, std::list<u32>& rLayerOffsetsOut);
|
||||
void AddDependency(const CAssetID& rkID, std::list<CAssetID>& rOut);
|
||||
void BuildDependencyList(std::list<CAssetID>& rAssetsOut, std::list<u32>& rLayerOffsetsOut, std::set<CAssetID> *pAudioGroupsOut = nullptr);
|
||||
void AddDependency(const CAssetID& rkID, std::list<CAssetID>& rOut, std::set<CAssetID> *pAudioGroupsOut);
|
||||
};
|
||||
|
||||
#endif // DEPENDENCYLISTBUILDERS
|
||||
|
|
|
@ -49,6 +49,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
|
|||
// Areas
|
||||
rMLVL.WriteLong(pWorld->mAreas.size());
|
||||
if (Game <= ePrime) rMLVL.WriteLong(1); // Unknown
|
||||
std::set<CAssetID> AudioGroups;
|
||||
|
||||
for (u32 iArea = 0; iArea < pWorld->mAreas.size(); iArea++)
|
||||
{
|
||||
|
@ -79,7 +80,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
|
|||
std::list<CAssetID> Dependencies;
|
||||
std::list<u32> LayerDependsOffsets;
|
||||
CAreaDependencyListBuilder Builder(pAreaEntry);
|
||||
Builder.BuildDependencyList(Dependencies, LayerDependsOffsets);
|
||||
Builder.BuildDependencyList(Dependencies, LayerDependsOffsets, &AudioGroups);
|
||||
|
||||
rMLVL.WriteLong(0);
|
||||
rMLVL.WriteLong( Dependencies.size() );
|
||||
|
@ -156,6 +157,59 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
|
|||
// Audio Groups
|
||||
if (Game <= ePrime)
|
||||
{
|
||||
#if 0
|
||||
// Debug: make sure our generated list matches the original, no missing or extra audio groups
|
||||
std::set<CAssetID> OriginalGroups;
|
||||
|
||||
for (u32 iGrp = 0; iGrp < pWorld->mAudioGrps.size(); iGrp++)
|
||||
{
|
||||
CWorld::SAudioGrp& rAudioGroup = pWorld->mAudioGrps[iGrp];
|
||||
OriginalGroups.insert(rAudioGroup.ResID);
|
||||
|
||||
if (AudioGroups.find(rAudioGroup.ResID) == AudioGroups.end())
|
||||
{
|
||||
CResourceEntry *pEntry = gpResourceStore->FindEntry(rAudioGroup.ResID);
|
||||
Log::Error("Missing audio group: " + pEntry->Name().ToUTF8());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto It = AudioGroups.begin(); It != AudioGroups.end(); It++)
|
||||
{
|
||||
if (OriginalGroups.find(*It) == OriginalGroups.end())
|
||||
{
|
||||
CResourceEntry *pEntry = gpResourceStore->FindEntry(*It);
|
||||
Log::Error("Extra audio group: " + pEntry->Name().ToUTF8());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Create sorted list of audio groups (sort by group ID)
|
||||
std::vector<CAudioGroup*> SortedAudioGroups;
|
||||
|
||||
for (auto It = AudioGroups.begin(); It != AudioGroups.end(); It++)
|
||||
{
|
||||
CAudioGroup *pGroup = (CAudioGroup*) gpResourceStore->LoadResource(*It, "AGSC");
|
||||
ASSERT(pGroup);
|
||||
SortedAudioGroups.push_back(pGroup);
|
||||
}
|
||||
|
||||
std::sort(SortedAudioGroups.begin(), SortedAudioGroups.end(), [](CAudioGroup *pLeft, CAudioGroup *pRight) -> bool {
|
||||
return pLeft->GroupID() < pRight->GroupID();
|
||||
});
|
||||
|
||||
// Write sorted audio group list to file
|
||||
rMLVL.WriteLong(SortedAudioGroups.size());
|
||||
|
||||
for (u32 iGrp = 0; iGrp < pWorld->mAudioGrps.size(); iGrp++)
|
||||
{
|
||||
CAudioGroup *pGroup = SortedAudioGroups[iGroup];
|
||||
rMLVL.WriteLong(pGroup->GroupID());
|
||||
pGroup->ID().Write(rMLVL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
rMLVL.WriteLong(pWorld->mAudioGrps.size());
|
||||
|
||||
for (u32 iGrp = 0; iGrp < pWorld->mAudioGrps.size(); iGrp++)
|
||||
|
@ -164,6 +218,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
|
|||
rMLVL.WriteLong(rAudioGroup.GroupID);
|
||||
rAudioGroup.ResID.Write(rMLVL);
|
||||
}
|
||||
#endif
|
||||
|
||||
rMLVL.WriteByte(0);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "CUnsupportedFormatLoader.h"
|
||||
#include "Core/GameProject/CGameProject.h"
|
||||
#include "Core/Resource/ParticleParameters.h"
|
||||
|
||||
CDependencyGroup* CUnsupportedFormatLoader::LoadCSNG(IInputStream& rCSNG, CResourceEntry *pEntry)
|
||||
|
@ -67,8 +68,16 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadEVNT(IInputStream& rEVNT, CResou
|
|||
{
|
||||
rEVNT.Seek(0x2, SEEK_CUR);
|
||||
rEVNT.ReadString();
|
||||
rEVNT.Seek(0x27, SEEK_CUR);
|
||||
rEVNT.Seek(0x1B, SEEK_CUR);
|
||||
u32 SoundID = rEVNT.ReadLong() & 0xFFFF;
|
||||
rEVNT.Seek(0x8, SEEK_CUR);
|
||||
if (IsEchoes) rEVNT.Seek(0xC, SEEK_CUR);
|
||||
|
||||
if (SoundID != 0xFFFF)
|
||||
{
|
||||
SSoundInfo SoundInfo = CGameProject::ActiveProject()->AudioManager()->GetSoundInfo(SoundID);
|
||||
pGroup->AddDependency(SoundInfo.pAudioGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "CUnsupportedParticleLoader.h"
|
||||
#include <Core/GameProject/CGameProject.h>
|
||||
|
||||
// ************ PARAMETER LOADING ************
|
||||
bool CUnsupportedParticleLoader::ParseParticleParameter(IInputStream& rPART)
|
||||
|
@ -462,8 +463,7 @@ bool CUnsupportedParticleLoader::ParseWeaponParameter(IInputStream& rWPSC)
|
|||
case kWeaponVMD2:
|
||||
ParseBoolFunction(rWPSC);
|
||||
break;
|
||||
|
||||
case kWeaponPJFX:
|
||||
|
||||
case kWeaponPSLT:
|
||||
ParseIntFunction(rWPSC);
|
||||
break;
|
||||
|
@ -509,6 +509,10 @@ bool CUnsupportedParticleLoader::ParseWeaponParameter(IInputStream& rWPSC)
|
|||
case kWeaponTTEX:
|
||||
ParseUVFunction(rWPSC);
|
||||
break;
|
||||
|
||||
case kWeaponPJFX:
|
||||
ParseSoundFunction(rWPSC);
|
||||
break;
|
||||
|
||||
case kWeaponAPSM:
|
||||
case kWeaponAPS1:
|
||||
|
@ -570,26 +574,12 @@ bool CUnsupportedParticleLoader::ParseCollisionResponseParameter(IInputStream& r
|
|||
case kColi6GRN:
|
||||
case kColi2MUD:
|
||||
case kColi2SAN:
|
||||
case kColiBHFX:
|
||||
case kColiCHFX:
|
||||
case kColiCSFX:
|
||||
case kColiCZFX:
|
||||
case kColiDCSH:
|
||||
case kColiDSFX:
|
||||
case kColiDSHX:
|
||||
case kColiGOFX:
|
||||
case kColiGRFX:
|
||||
case kColiHBFX:
|
||||
case kColiICFX:
|
||||
case kColiMSFX:
|
||||
case kColiPBHX:
|
||||
case kColiPBOS:
|
||||
case kColiPBSX:
|
||||
case kColiSHFX:
|
||||
case kColiTAFX:
|
||||
case kColiTASP:
|
||||
case kColiWSFX:
|
||||
case kColiWTFX:
|
||||
ParseIntFunction(rCRSC);
|
||||
break;
|
||||
|
||||
|
@ -597,7 +587,24 @@ bool CUnsupportedParticleLoader::ParseCollisionResponseParameter(IInputStream& r
|
|||
case kColiRNGE:
|
||||
ParseFloatFunction(rCRSC);
|
||||
break;
|
||||
|
||||
|
||||
case kColiBHFX:
|
||||
case kColiCHFX:
|
||||
case kColiCSFX:
|
||||
case kColiCZFX:
|
||||
case kColiDSFX:
|
||||
case kColiGOFX:
|
||||
case kColiGRFX:
|
||||
case kColiHBFX:
|
||||
case kColiICFX:
|
||||
case kColiMSFX:
|
||||
case kColiSHFX:
|
||||
case kColiTAFX:
|
||||
case kColiWSFX:
|
||||
case kColiWTFX:
|
||||
ParseSoundFunction(rCRSC);
|
||||
break;
|
||||
|
||||
case kColi1LAV:
|
||||
case kColi3LAV:
|
||||
case kColi1MUD:
|
||||
|
@ -1275,6 +1282,35 @@ void CUnsupportedParticleLoader::ParseEmitterFunction(IInputStream& rFile)
|
|||
}
|
||||
}
|
||||
|
||||
void CUnsupportedParticleLoader::ParseSoundFunction(IInputStream& rFile)
|
||||
{
|
||||
u32 FuncOffset = rFile.Tell();
|
||||
CFourCC Func = rFile.ReadLong();
|
||||
|
||||
switch (Func.ToLong())
|
||||
{
|
||||
case kFuncNONE:
|
||||
break;
|
||||
|
||||
case kSoundCNST:
|
||||
{
|
||||
u32 SoundID = rFile.ReadLong() & 0xFFFF;
|
||||
|
||||
if (SoundID != 0xFFFF)
|
||||
{
|
||||
SSoundInfo SoundInfo = CGameProject::ActiveProject()->AudioManager()->GetSoundInfo(SoundID);
|
||||
mpGroup->AddDependency(SoundInfo.pAudioGroup);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Log::FileError(rFile.GetSourceString(), FuncOffset, "Unknown sound function: " + Func.ToString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CUnsupportedParticleLoader::ParseAssetFunction(IInputStream& rFile)
|
||||
{
|
||||
u32 FuncOffset = rFile.Tell();
|
||||
|
|
|
@ -31,6 +31,7 @@ class CUnsupportedParticleLoader
|
|||
void ParseColorFunction(IInputStream& rFile);
|
||||
void ParseUVFunction(IInputStream& rFile);
|
||||
void ParseEmitterFunction(IInputStream& rFile);
|
||||
void ParseSoundFunction(IInputStream& rFile);
|
||||
void ParseAssetFunction(IInputStream& rFile);
|
||||
void ParseSpawnSystemKeyframeData(IInputStream& rFile);
|
||||
void ParseKeyframeEmitterData(IInputStream& rFile, const CFourCC& rkFunc, u32 ElemSize);
|
||||
|
|
|
@ -515,6 +515,8 @@ FUNC(Color, VRTC, 'V', 'R', 'T', 'C') // Vector, Float
|
|||
// UV Functions
|
||||
FUNC(UV, CNST, 'C', 'N', 'S', 'T') // Asset (TXTR)
|
||||
FUNC(UV, ATEX, 'A', 'T', 'E', 'X') // Asset (TXTR), Int, Int, Int, Int, Int, Bool
|
||||
// Sound Functions
|
||||
FUNC(Sound, CNST, 'C', 'N', 'S', 'T') // Sound ID
|
||||
// Asset Functions
|
||||
FUNC(Asset, CNST, 'C', 'N', 'S', 'T') // Asset ID
|
||||
// Emitter Functions
|
||||
|
|
Loading…
Reference in New Issue