Fixed CHAR files failing to load

This commit is contained in:
parax0 2016-06-29 23:23:49 -06:00
parent f967519a77
commit 2f2ec13ced
7 changed files with 66 additions and 34 deletions

View File

@ -96,7 +96,12 @@ CResource* CResourceEntry::Load()
{
// todo: load raw
if (mpResource) return mpResource;
if (!HasCookedVersion()) return nullptr;
if (!HasCookedVersion())
{
Log::Error("Couldn't locate resource: " + CookedAssetPath(true));
return nullptr;
}
CFileInStream File(CookedAssetPath().ToStdString(), IOUtil::eBigEndian);
if (!File.IsValid())
@ -116,27 +121,20 @@ CResource* CResourceEntry::Load(IInputStream& rInput)
switch (mType)
{
case eAnimation: mpResource = CAnimationLoader::LoadANIM(rInput, this); break;
case eArea: mpResource = CAreaLoader::LoadMREA(rInput, this); break;
case eDynamicCollision: mpResource = CCollisionLoader::LoadDCLN(rInput, this); break;
case eFont: mpResource = CFontLoader::LoadFONT(rInput, this); break;
case eModel: mpResource = CModelLoader::LoadCMDL(rInput, this); break;
case eScan: mpResource = CScanLoader::LoadSCAN(rInput, this); break;
case eSkeleton: mpResource = CSkeletonLoader::LoadCINF(rInput, this); break;
case eSkin: mpResource = CSkinLoader::LoadCSKR(rInput, this); break;
case eStaticGeometryMap: mpResource = CPoiToWorldLoader::LoadEGMC(rInput, this); break;
case eStringTable: mpResource = CStringLoader::LoadSTRG(rInput, this); break;
case eTexture: mpResource = CTextureDecoder::LoadTXTR(rInput, this); break;
case eWorld: mpResource = CWorldLoader::LoadMLVL(rInput, this); break;
case eAnimSet:
if (mGame <= eEchoes)
mpResource = CAnimSetLoader::LoadANCS(rInput, this);
else
mpResource = CAnimSetLoader::LoadCHAR(rInput, this);
break;
default: mpResource = new CResource(this); break;
case eAnimation: mpResource = CAnimationLoader::LoadANIM(rInput, this); break;
case eAnimSet: mpResource = CAnimSetLoader::LoadANCSOrCHAR(rInput, this); break;
case eArea: mpResource = CAreaLoader::LoadMREA(rInput, this); break;
case eDynamicCollision: mpResource = CCollisionLoader::LoadDCLN(rInput, this); break;
case eFont: mpResource = CFontLoader::LoadFONT(rInput, this); break;
case eModel: mpResource = CModelLoader::LoadCMDL(rInput, this); break;
case eScan: mpResource = CScanLoader::LoadSCAN(rInput, this); break;
case eSkeleton: mpResource = CSkeletonLoader::LoadCINF(rInput, this); break;
case eSkin: mpResource = CSkinLoader::LoadCSKR(rInput, this); break;
case eStaticGeometryMap: mpResource = CPoiToWorldLoader::LoadEGMC(rInput, this); break;
case eStringTable: mpResource = CStringLoader::LoadSTRG(rInput, this); break;
case eTexture: mpResource = CTextureDecoder::LoadTXTR(rInput, this); break;
case eWorld: mpResource = CWorldLoader::LoadMLVL(rInput, this); break;
default: mpResource = new CResource(this); break;
}
return mpResource;

View File

@ -232,14 +232,14 @@ bool CResourceStore::RegisterResource(const CUniqueID& rkID, EResType Type, cons
}
}
CResourceEntry* CResourceStore::CreateTransientEntry(EResType Type, const TWideString& rkDir /*= L""*/, const TWideString& rkFileName /*= L""*/)
CResourceEntry* CResourceStore::RegisterTransientResource(EResType Type, const TWideString& rkDir /*= L""*/, const TWideString& rkFileName /*= L""*/)
{
CResourceEntry *pEntry = new CResourceEntry(this, CUniqueID::RandomID(), rkDir, rkFileName, Type, true);
mResourceEntries[pEntry->ID()] = pEntry;
return pEntry;
}
CResourceEntry* CResourceStore::CreateTransientEntry(EResType Type, const CUniqueID& rkID, const TWideString& rkDir /*=L ""*/, const TWideString& rkFileName /*= L""*/)
CResourceEntry* CResourceStore::RegisterTransientResource(EResType Type, const CUniqueID& rkID, const TWideString& rkDir /*=L ""*/, const TWideString& rkFileName /*= L""*/)
{
CResourceEntry *pEntry = new CResourceEntry(this, rkID, rkDir, rkFileName, Type, true);
mResourceEntries[rkID] = pEntry;
@ -264,7 +264,7 @@ CResource* CResourceStore::LoadResource(const CUniqueID& rkID, const CFourCC& rk
CMemoryInStream MemStream(DataBuffer.data(), DataBuffer.size(), IOUtil::eBigEndian);
EResType Type = CResource::ResTypeForExtension(rkType);
CResourceEntry *pEntry = CreateTransientEntry(Type, rkID);
CResourceEntry *pEntry = RegisterTransientResource(Type, rkID);
CResource *pRes = pEntry->Load(MemStream);
if (pRes) mLoadedResources[rkID] = pEntry;
return pRes;
@ -282,9 +282,15 @@ CResource* CResourceStore::LoadResource(const CUniqueID& rkID, const CFourCC& rk
if (Type != eInvalidResType)
{
TWideString Name = rkID.ToString().ToUTF16();
CResourceEntry *pEntry = CreateTransientEntry(Type, mTransientLoadDir, Name);
CResource *pRes = pEntry->Load();
// Note the entry may not be able to find the resource on its own (due to not knowing what game
// it is) so we will attempt to open the file stream ourselves and pass it to the entry instead.
TString Name = rkID.ToString();
CResourceEntry *pEntry = RegisterTransientResource(Type, mTransientLoadDir, Name.ToUTF16());
TString Path = mTransientLoadDir.ToUTF8() + Name + "." + rkType.ToString();
CFileInStream File(Path.ToStdString(), IOUtil::eBigEndian);
CResource *pRes = pEntry->Load(File);
if (pRes) mLoadedResources[rkID] = pEntry;
return pRes;
}
@ -318,10 +324,22 @@ CResource* CResourceStore::LoadResource(const TString& rkPath)
return nullptr;
}
// Open file
CFileInStream File(rkPath.ToStdString(), IOUtil::eBigEndian);
if (!File.IsValid())
{
Log::Error("Unable to load resource; couldn't open file: " + rkPath);
return nullptr;
}
// Load resource
TString OldTransientDir = mTransientLoadDir;
mTransientLoadDir = Dir;
CResourceEntry *pEntry = CreateTransientEntry(Type, ID, Dir, Name);
CResource *pRes = pEntry->Load();
CResourceEntry *pEntry = RegisterTransientResource(Type, ID, Dir, Name);
CResource *pRes = pEntry->Load(File);
if (pRes) mLoadedResources[ID] = pEntry;
mTransientLoadDir = OldTransientDir;
@ -375,6 +393,7 @@ void CResourceStore::DestroyUnreferencedResources()
{
It = mLoadedResources.erase(It);
NumDeleted++;
if (It == mLoadedResources.end()) break;
}
}
}

View File

@ -47,8 +47,8 @@ public:
bool RegisterResource(const CUniqueID& rkID, EResType Type, const TWideString& rkDir, const TWideString& rkFileName);
CResourceEntry* FindEntry(const CUniqueID& rkID) const;
CResourceEntry* CreateTransientEntry(EResType Type, const TWideString& rkDir = L"", const TWideString& rkFileName = L"");
CResourceEntry* CreateTransientEntry(EResType Type, const CUniqueID& rkID, const TWideString& rkDir = L"", const TWideString& rkFileName = L"");
CResourceEntry* RegisterTransientResource(EResType Type, const TWideString& rkDir = L"", const TWideString& rkFileName = L"");
CResourceEntry* RegisterTransientResource(EResType Type, const CUniqueID& rkID, const TWideString& rkDir = L"", const TWideString& rkFileName = L"");
CResource* LoadResource(const CUniqueID& rkID, const CFourCC& rkType);
CResource* LoadResource(const TString& rkPath);

View File

@ -165,7 +165,7 @@ REGISTER_RESOURCE_TYPE(ATBL, eAudioLookupTable, ePrimeDemo, eCorruption)
REGISTER_RESOURCE_TYPE(BFRC, eBurstFireData, eCorruptionProto, eCorruption)
REGISTER_RESOURCE_TYPE(CAAD, eUnknown_CAAD, eCorruption, eCorruption)
REGISTER_RESOURCE_TYPE(CAUD, eAudioMacro, eCorruptionProto, eReturns)
REGISTER_RESOURCE_TYPE(CHAR, eCharacter, eCorruptionProto, eReturns)
REGISTER_RESOURCE_TYPE(CHAR, eAnimSet, eCorruptionProto, eReturns)
REGISTER_RESOURCE_TYPE(CINF, eSkeleton, ePrimeDemo, eReturns)
REGISTER_RESOURCE_TYPE(CMDL, eModel, ePrimeDemo, eReturns)
REGISTER_RESOURCE_TYPE(CRSC, eParticleCollisionResponse, ePrimeDemo, eCorruption)

View File

@ -38,7 +38,7 @@ public:
CResource(CResourceEntry *pEntry = 0)
: mpEntry(pEntry), mRefCount(0)
{
if (!mpEntry) mpEntry = gResourceStore.CreateTransientEntry(Type());
if (!mpEntry) mpEntry = gResourceStore.RegisterTransientResource(Type());
}
virtual ~CResource() {}

View File

@ -194,6 +194,20 @@ void CAnimSetLoader::LoadHalfTransition(IInputStream& rANCS)
}
// ************ STATIC ************
CAnimSet* CAnimSetLoader::LoadANCSOrCHAR(IInputStream& rFile, CResourceEntry *pEntry)
{
if (!rFile.IsValid()) return nullptr;
u8 Test = rFile.PeekByte();
if (Test == 0x3 || Test == 0x5 || Test == 0x59)
return LoadCHAR(rFile, pEntry);
else if (Test == 0x0)
return LoadANCS(rFile, pEntry);
Log::Error("Failed to determine animset format for " + rFile.GetSourceString() + "; first byte is " + TString::HexString(Test, 2));
return nullptr;
}
CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
{
if (!rANCS.IsValid()) return nullptr;

View File

@ -42,6 +42,7 @@ class CAnimSetLoader
void LoadHalfTransition(IInputStream& rANCS);
public:
static CAnimSet* LoadANCSOrCHAR(IInputStream& rFile, CResourceEntry *pEntry);
static CAnimSet* LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry);
static CAnimSet* LoadCHAR(IInputStream& rCHAR, CResourceEntry *pEntry);
};