Added support for loading all dependencies of MP2 ANCS, FRME, and SCAN

This commit is contained in:
parax0 2016-08-16 03:00:31 -06:00
parent bc35e15a6a
commit 881bb28d84
5 changed files with 210 additions and 92 deletions

View File

@ -3,6 +3,7 @@
#include "TResPtr.h"
#include "CAnimation.h"
#include "CDependencyGroup.h"
#include "CResource.h"
#include "CSkeleton.h"
#include "CSkin.h"
@ -41,10 +42,20 @@ class CAnimSet : public CResource
TResPtr<CAnimation> pAnim;
};
std::vector<SAnimation> mAnims;
std::vector<CDependencyGroup*> mEventDependencies;
public:
CAnimSet(CResourceEntry *pEntry = 0) : CResource(pEntry) {}
~CAnimSet()
{
for (u32 iEvnt = 0; iEvnt < mEventDependencies.size(); iEvnt++)
{
ASSERT(!mEventDependencies[iEvnt]->Entry());
delete mEventDependencies[iEvnt];
}
}
u32 NumNodes() const { return mCharacters.size(); }
TString NodeName(u32 Index) { if (Index >= mCharacters.size()) Index = 0; return mCharacters[Index].Name; }
CModel* NodeModel(u32 Index) { if (Index >= mCharacters.size()) Index = 0; return mCharacters[Index].pModel; }
@ -72,6 +83,18 @@ public:
}
}
for (u32 iEvnt = 0; iEvnt < mEventDependencies.size(); iEvnt++)
{
CDependencyGroup *pGroup = mEventDependencies[iEvnt];
for (u32 iDep = 0; iDep < pGroup->NumDependencies(); iDep++)
{
CAssetID ID = pGroup->DependencyByIndex(iDep);
pTree->AddDependency(iDep);
BaseUsedSet.insert(ID);
}
}
// Character dependencies
for (u32 iNode = 0; iNode < mCharacters.size(); iNode++)
pTree->AddCharacter(&mCharacters[iNode], BaseUsedSet);

View File

@ -30,6 +30,7 @@ private:
bool mIsImportant;
ELogbookCategory mCategory;
CAssetID mScanImageTextures[4];
std::vector<CAssetID> mLogbookAssets;
public:
CScan(CResourceEntry *pEntry = 0)
@ -52,6 +53,9 @@ public:
for (u32 iImg = 0; iImg < 4; iImg++)
pTree->AddDependency(mScanImageTextures[iImg]);
for (u32 iLog = 0; iLog < mLogbookAssets.size(); iLog++)
pTree->AddDependency(mLogbookAssets[iLog]);
return pTree;
}

View File

@ -1,4 +1,5 @@
#include "CAnimSetLoader.h"
#include "CUnsupportedFormatLoader.h"
#include "Core/GameProject/CResourceStore.h"
#include <Common/Log.h>
@ -373,6 +374,18 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
}
}
// Parse anim event data
if (Loader.pSet->Game() >= eEchoesDemo)
{
u32 EventDataCount = rANCS.ReadLong();
for (u32 iEvnt = 0; iEvnt < EventDataCount; iEvnt++)
{
CDependencyGroup *pGrp = CUnsupportedFormatLoader::LoadEVNT(rANCS, nullptr);
Loader.pSet->mEventDependencies.push_back(pGrp);
}
}
return Loader.pSet;
}

View File

@ -105,6 +105,38 @@ void CScanLoader::LoadParamsMP2(IInputStream& rSCAN)
case 0x7B714814:
mpScan->mIsImportant = (rSCAN.ReadByte() != 0);
break;
// Override texture and logbook model/animsets
case 0x53336141:
case 0xB7ADC418:
case 0x15694EE1:
case 0x58F9FE99:
mpScan->mLogbookAssets.push_back( CAssetID(rSCAN, eEchoes) );
break;
// ScanInfoSecondaryModels
case 0x1C5B4A3A:
case 0x8728A0EE:
case 0xF1CD99D3:
case 0x6ABE7307:
case 0x1C07EBA9:
case 0x8774017D:
case 0xF1913840:
case 0x6AE2D294:
case 0x1CE2091C:
u16 NumSubProps = rSCAN.ReadShort();
for (u32 iSub = 0; iSub < NumSubProps; iSub++)
{
u32 SubPropertyID = rSCAN.ReadLong();
u32 Next = rSCAN.Tell() + rSCAN.ReadShort();
if (SubPropertyID == 0x1F7921BC || SubPropertyID == 0xCDD202D1)
mpScan->mLogbookAssets.push_back( CAssetID(rSCAN, eEchoes) );
rSCAN.Seek(Next, SEEK_SET);
}
break;
}
rSCAN.Seek(Next, SEEK_SET);

View File

@ -17,6 +17,8 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadEVNT(IInputStream& rEVNT, CResou
u32 Version = rEVNT.ReadLong();
ASSERT(Version == 1 || Version == 2);
// kinda hack - check if we're reading an Echoes ANCS
bool IsEchoes = (TString(rEVNT.GetSourceString()).GetFileExtension() == "ANCS");
CDependencyGroup *pGroup = new CDependencyGroup(pEntry);
// Loop Events
@ -49,10 +51,26 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadEVNT(IInputStream& rEVNT, CResou
rEVNT.ReadString();
rEVNT.Seek(0x23, SEEK_CUR);
pGroup->AddDependency(rEVNT.ReadLong());
rEVNT.ReadString();
if (IsEchoes)
rEVNT.Seek(0x4, SEEK_CUR);
else
rEVNT.ReadString();
rEVNT.Seek(0x8, SEEK_CUR);
}
// Sound Events
u32 NumSoundEvents = rEVNT.ReadLong();
for (u32 iSound = 0; iSound < NumSoundEvents; iSound++)
{
rEVNT.Seek(0x2, SEEK_CUR);
rEVNT.ReadString();
rEVNT.Seek(0x27, SEEK_CUR);
if (IsEchoes) rEVNT.Seek(0xC, SEEK_CUR);
}
return pGroup;
}
@ -61,112 +79,140 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadFRME(IInputStream& rFRME, CResou
if (pEntry->Game() >= eEchoesDemo) return nullptr;
u32 Version = rFRME.ReadLong();
ASSERT(Version == 0 || Version == 1);
CDependencyGroup *pGroup = new CDependencyGroup(pEntry);
rFRME.Seek(0xC, SEEK_CUR);
u32 NumWidgets = rFRME.ReadLong();
for (u32 iWgt = 0; iWgt < NumWidgets; iWgt++)
// Prime 1
if (Version == 0 || Version == 1)
{
// Widget Header
CFourCC WidgetType = rFRME.ReadLong();
rFRME.ReadString();
rFRME.ReadString();
rFRME.Seek(0x18, SEEK_CUR);
CDependencyGroup *pGroup = new CDependencyGroup(pEntry);
rFRME.Seek(0xC, SEEK_CUR);
u32 NumWidgets = rFRME.ReadLong();
// Head Widget / Base Widget
if (WidgetType == "HWIG" || WidgetType == "BWIG")
{}
// Camera
else if (WidgetType == "CAMR")
for (u32 iWgt = 0; iWgt < NumWidgets; iWgt++)
{
u32 ProjectionType = rFRME.ReadLong();
// Widget Header
CFourCC WidgetType = rFRME.ReadLong();
rFRME.ReadString();
rFRME.ReadString();
rFRME.Seek(0x18, SEEK_CUR);
if (ProjectionType == 0)
rFRME.Seek(0x10, SEEK_CUR);
else
rFRME.Seek(0x18, SEEK_CUR);
}
// Head Widget / Base Widget
if (WidgetType == "HWIG" || WidgetType == "BWIG")
{}
// Light
else if (WidgetType == "LITE")
{
u32 LightType = rFRME.ReadLong();
rFRME.Seek(0x1C, SEEK_CUR);
if (LightType == 0) rFRME.Seek(0x4, SEEK_CUR);
}
// Meter
else if (WidgetType == "METR")
rFRME.Seek(0xA, SEEK_CUR);
// Group
else if (WidgetType == "GRUP")
rFRME.Seek(0x3, SEEK_CUR);
// Table Group
else if (WidgetType == "TBGP")
rFRME.Seek(0x23, SEEK_CUR);
// Model
else if (WidgetType == "MODL")
{
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // CMDL
rFRME.Seek(0x8, SEEK_CUR);
}
// Text Pane
else if (WidgetType == "TXPN")
{
rFRME.Seek(0x14, SEEK_CUR);
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // FONT
rFRME.Seek(0x32, SEEK_CUR);
if (Version == 1)
// Camera
else if (WidgetType == "CAMR")
{
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // FONT
u32 ProjectionType = rFRME.ReadLong();
if (ProjectionType == 0)
rFRME.Seek(0x10, SEEK_CUR);
else
rFRME.Seek(0x18, SEEK_CUR);
}
// Light
else if (WidgetType == "LITE")
{
u32 LightType = rFRME.ReadLong();
rFRME.Seek(0x1C, SEEK_CUR);
if (LightType == 0) rFRME.Seek(0x4, SEEK_CUR);
}
// Meter
else if (WidgetType == "METR")
rFRME.Seek(0xA, SEEK_CUR);
// Group
else if (WidgetType == "GRUP")
rFRME.Seek(0x3, SEEK_CUR);
// Table Group
else if (WidgetType == "TBGP")
rFRME.Seek(0x23, SEEK_CUR);
// Model
else if (WidgetType == "MODL")
{
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // CMDL
rFRME.Seek(0x8, SEEK_CUR);
}
}
// Image Pane
else if (WidgetType == "IMGP")
// Text Pane
else if (WidgetType == "TXPN")
{
rFRME.Seek(0x14, SEEK_CUR);
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // FONT
rFRME.Seek(0x32, SEEK_CUR);
if (Version == 1)
{
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // FONT
rFRME.Seek(0x8, SEEK_CUR);
}
}
// Image Pane
else if (WidgetType == "IMGP")
{
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // TXTR
if (rFRME.ReadLong() != 0xFFFFFFFF) DEBUG_BREAK;
rFRME.Seek(0x4, SEEK_CUR);
u32 NumQuadCoords = rFRME.ReadLong();
rFRME.Seek(NumQuadCoords * 0xC, SEEK_CUR);
u32 NumUVCoords = rFRME.ReadLong();
rFRME.Seek(NumUVCoords * 8, SEEK_CUR);
}
// Energy Bar
else if (WidgetType == "ENRG")
{
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // TXTR
}
// Slider Group
else if (WidgetType == "SLGP")
{
rFRME.Seek(0x10, SEEK_CUR);
}
else
{
Log::Error("Unrecognized FRME widget type: " + WidgetType.ToString());
DEBUG_BREAK;
}
// Widget Footer
if (rFRME.ReadByte() != 0)
rFRME.Seek(0x2, SEEK_CUR);
rFRME.Seek(0x42, SEEK_CUR);
}
}
// MP2/MP3/DKCR are much easier... dependency list right at the beginning of the file
else if (Version == 4 || Version == 5 || Version == 0xD || Version == 0xE || Version == 0x10)
{
EGame Game;
if (Version == 4) Game = eEchoes;
else if (Version == 0x10) Game = eReturns;
else Game = eCorruption;
u32 NumDependencies = rFRME.ReadLong();
for (u32 iDep = 0; iDep < NumDependencies; iDep++)
{
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // TXTR
if (rFRME.ReadLong() != 0xFFFFFFFF) DEBUG_BREAK;
rFRME.Seek(0x4, SEEK_CUR);
u32 NumQuadCoords = rFRME.ReadLong();
rFRME.Seek(NumQuadCoords * 0xC, SEEK_CUR);
u32 NumUVCoords = rFRME.ReadLong();
rFRME.Seek(NumUVCoords * 8, SEEK_CUR);
pGroup->AddDependency( CAssetID(rFRME, Game) );
}
}
// Energy Bar
else if (WidgetType == "ENRG")
{
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // TXTR
}
// Slider Group
else if (WidgetType == "SLGP")
{
rFRME.Seek(0x10, SEEK_CUR);
}
else
{
Log::Error("Unrecognized FRME widget type: " + WidgetType.ToString());
DEBUG_BREAK;
}
// Widget Footer
if (rFRME.ReadByte() != 0)
rFRME.Seek(0x2, SEEK_CUR);
rFRME.Seek(0x42, SEEK_CUR);
else
{
Log::Error("Unrecognized FRME version: " + TString::HexString(Version, 2));
delete pGroup;
return nullptr;
}
return pGroup;