Added support for loading all dependencies of MP2 ANCS, FRME, and SCAN
This commit is contained in:
parent
bc35e15a6a
commit
881bb28d84
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue