CPackage: Make use of unsigned stream helpers where applicable

This commit is contained in:
Lioncash 2020-06-19 03:13:41 -04:00
parent 9a2580ad03
commit df29cc2109
1 changed files with 71 additions and 80 deletions

View File

@ -12,7 +12,7 @@ using namespace tinyxml2;
bool CPackage::Load() bool CPackage::Load()
{ {
TString DefPath = DefinitionPath(false); const TString DefPath = DefinitionPath(false);
CXMLReader Reader(DefPath); CXMLReader Reader(DefPath);
if (Reader.IsValid()) if (Reader.IsValid())
@ -21,12 +21,13 @@ bool CPackage::Load()
mCacheDirty = true; mCacheDirty = true;
return true; return true;
} }
else return false;
return false;
} }
bool CPackage::Save() bool CPackage::Save()
{ {
TString DefPath = DefinitionPath(false); const TString DefPath = DefinitionPath(false);
FileUtil::MakeDirectory(DefPath.GetFileDirectory()); FileUtil::MakeDirectory(DefPath.GetFileDirectory());
CXMLWriter Writer(DefPath, "PackageDefinition", 0, mpProject ? mpProject->Game() : EGame::Invalid); CXMLWriter Writer(DefPath, "PackageDefinition", 0, mpProject ? mpProject->Game() : EGame::Invalid);
@ -53,8 +54,8 @@ void CPackage::UpdateDependencyCache() const
Builder.BuildDependencyList(false, AssetList); Builder.BuildDependencyList(false, AssetList);
mCachedDependencies.clear(); mCachedDependencies.clear();
for (auto Iter = AssetList.begin(); Iter != AssetList.end(); Iter++) for (const auto& asset : AssetList)
mCachedDependencies.insert(*Iter); mCachedDependencies.insert(asset);
mCacheDirty = false; mCacheDirty = false;
} }
@ -82,7 +83,7 @@ void CPackage::Cook(IProgressNotifier *pProgress)
debugf("%d assets in %s.pak", AssetList.size(), *Name()); debugf("%d assets in %s.pak", AssetList.size(), *Name());
// Write new pak // Write new pak
TString PakPath = CookedPackagePath(false); const TString PakPath = CookedPackagePath(false);
CFileOutStream Pak(PakPath, EEndian::BigEndian); CFileOutStream Pak(PakPath, EEndian::BigEndian);
if (!Pak.IsValid()) if (!Pak.IsValid())
@ -91,9 +92,9 @@ void CPackage::Cook(IProgressNotifier *pProgress)
return; return;
} }
EGame Game = mpProject->Game(); const EGame Game = mpProject->Game();
uint32 Alignment = (Game <= EGame::CorruptionProto ? 0x20 : 0x40); const uint32 Alignment = (Game <= EGame::CorruptionProto ? 0x20 : 0x40);
uint32 AlignmentMinusOne = Alignment - 1; const uint32 AlignmentMinusOne = Alignment - 1;
uint32 TocOffset = 0; uint32 TocOffset = 0;
uint32 NamesSize = 0; uint32 NamesSize = 0;
@ -110,17 +111,14 @@ void CPackage::Cook(IProgressNotifier *pProgress)
// Named Resources // Named Resources
Pak.WriteLong(mResources.size()); Pak.WriteLong(mResources.size());
for (auto Iter = mResources.begin(); Iter != mResources.end(); Iter++) for (const auto& res : mResources)
{ {
const SNamedResource& rkRes = *Iter; res.Type.Write(Pak);
rkRes.Type.Write(Pak); res.ID.Write(Pak);
rkRes.ID.Write(Pak); Pak.WriteSizedString(res.Name);
Pak.WriteSizedString(rkRes.Name);
} }
} }
else // Write MP3 pak header
// Write MP3 pak header
else
{ {
// Header // Header
Pak.WriteLong(2); // Version Pak.WriteLong(2); // Version
@ -133,15 +131,14 @@ void CPackage::Cook(IProgressNotifier *pProgress)
Pak.WriteToBoundary(0x40, 0); Pak.WriteToBoundary(0x40, 0);
// Named Resources // Named Resources
uint32 NamesStart = Pak.Tell(); const uint32 NamesStart = Pak.Tell();
Pak.WriteLong(mResources.size()); Pak.WriteULong(static_cast<uint32>(mResources.size()));
for (auto Iter = mResources.begin(); Iter != mResources.end(); Iter++) for (const auto& res : mResources)
{ {
const SNamedResource& rkRes = *Iter; Pak.WriteString(res.Name);
Pak.WriteString(rkRes.Name); res.Type.Write(Pak);
rkRes.Type.Write(Pak); res.ID.Write(Pak);
rkRes.ID.Write(Pak);
} }
Pak.WriteToBoundary(0x40, 0); Pak.WriteToBoundary(0x40, 0);
@ -151,9 +148,9 @@ void CPackage::Cook(IProgressNotifier *pProgress)
// Fill in resource table with junk, write later // Fill in resource table with junk, write later
ResTableOffset = Pak.Tell(); ResTableOffset = Pak.Tell();
Pak.WriteLong(AssetList.size()); Pak.WriteLong(AssetList.size());
CAssetID Dummy = CAssetID::InvalidID(Game); const CAssetID Dummy = CAssetID::InvalidID(Game);
for (uint32 iRes = 0; iRes < AssetList.size(); iRes++) for (size_t iRes = 0; iRes < AssetList.size(); iRes++)
{ {
Pak.WriteLongLong(0); Pak.WriteLongLong(0);
Dummy.Write(Pak); Dummy.Write(Pak);
@ -173,13 +170,13 @@ void CPackage::Cook(IProgressNotifier *pProgress)
}; };
std::vector<SResourceTableInfo> ResourceTableData(AssetList.size()); std::vector<SResourceTableInfo> ResourceTableData(AssetList.size());
uint32 ResIdx = 0; uint32 ResIdx = 0;
uint32 ResDataOffset = Pak.Tell(); const uint32 ResDataOffset = Pak.Tell();
for (auto Iter = AssetList.begin(); Iter != AssetList.end() && !pProgress->ShouldCancel(); Iter++, ResIdx++) for (auto Iter = AssetList.begin(); Iter != AssetList.end() && !pProgress->ShouldCancel(); Iter++, ResIdx++)
{ {
// Initialize entry, recook assets if needed // Initialize entry, recook assets if needed
uint32 AssetOffset = Pak.Tell(); const uint32 AssetOffset = Pak.Tell();
CAssetID ID = *Iter; const CAssetID ID = *Iter;
CResourceEntry *pEntry = gpResourceStore->FindEntry(ID); CResourceEntry *pEntry = gpResourceStore->FindEntry(ID);
ASSERT(pEntry != nullptr); ASSERT(pEntry != nullptr);
@ -190,7 +187,7 @@ void CPackage::Cook(IProgressNotifier *pProgress)
} }
// Update progress bar // Update progress bar
if (ResIdx & 0x1 || ResIdx == AssetList.size() - 1) if ((ResIdx & 1) != 0 || ResIdx == AssetList.size() - 1)
{ {
pProgress->Report(ResIdx, AssetList.size(), TString::Format("Writing asset %d/%d: %s", ResIdx+1, AssetList.size(), *(pEntry->Name() + "." + pEntry->CookedExtension()))); pProgress->Report(ResIdx, AssetList.size(), TString::Format("Writing asset %d/%d: %s", ResIdx+1, AssetList.size(), *(pEntry->Name() + "." + pEntry->CookedExtension())));
} }
@ -203,15 +200,15 @@ void CPackage::Cook(IProgressNotifier *pProgress)
// Load resource data // Load resource data
CFileInStream CookedAsset(pEntry->CookedAssetPath(), EEndian::BigEndian); CFileInStream CookedAsset(pEntry->CookedAssetPath(), EEndian::BigEndian);
ASSERT(CookedAsset.IsValid()); ASSERT(CookedAsset.IsValid());
uint32 ResourceSize = CookedAsset.Size(); const uint32 ResourceSize = CookedAsset.Size();
std::vector<uint8> ResourceData(ResourceSize); std::vector<uint8> ResourceData(ResourceSize);
CookedAsset.ReadBytes(ResourceData.data(), ResourceData.size()); CookedAsset.ReadBytes(ResourceData.data(), ResourceData.size());
// Check if this asset should be compressed; there are a few resource types that are // Check if this asset should be compressed; there are a few resource types that are
// always compressed, and some types that are compressed if they're over a certain size // always compressed, and some types that are compressed if they're over a certain size
EResourceType Type = pEntry->ResourceType(); const EResourceType Type = pEntry->ResourceType();
uint32 CompressThreshold = (Game <= EGame::CorruptionProto ? 0x400 : 0x80); const uint32 CompressThreshold = (Game <= EGame::CorruptionProto ? 0x400 : 0x80);
bool ShouldAlwaysCompress = (Type == EResourceType::Texture || Type == EResourceType::Model || bool ShouldAlwaysCompress = (Type == EResourceType::Texture || Type == EResourceType::Model ||
Type == EResourceType::Skin || Type == EResourceType::AnimSet || Type == EResourceType::Skin || Type == EResourceType::AnimSet ||
@ -226,14 +223,14 @@ void CPackage::Cook(IProgressNotifier *pProgress)
Type == EResourceType::DynamicCollision); Type == EResourceType::DynamicCollision);
} }
bool ShouldCompressConditional = !ShouldAlwaysCompress && const bool ShouldCompressConditional = !ShouldAlwaysCompress &&
(Type == EResourceType::Particle || Type == EResourceType::ParticleElectric || (Type == EResourceType::Particle || Type == EResourceType::ParticleElectric ||
Type == EResourceType::ParticleSwoosh || Type == EResourceType::ParticleWeapon || Type == EResourceType::ParticleSwoosh || Type == EResourceType::ParticleWeapon ||
Type == EResourceType::ParticleDecal || Type == EResourceType::ParticleCollisionResponse || Type == EResourceType::ParticleDecal || Type == EResourceType::ParticleCollisionResponse ||
Type == EResourceType::ParticleSpawn || Type == EResourceType::ParticleSorted || Type == EResourceType::ParticleSpawn || Type == EResourceType::ParticleSorted ||
Type == EResourceType::BurstFireData); Type == EResourceType::BurstFireData);
bool ShouldCompress = ShouldAlwaysCompress || (ShouldCompressConditional && ResourceSize >= CompressThreshold); const bool ShouldCompress = ShouldAlwaysCompress || (ShouldCompressConditional && ResourceSize >= CompressThreshold);
// Write resource data to pak // Write resource data to pak
if (!ShouldCompress) if (!ShouldCompress)
@ -241,7 +238,6 @@ void CPackage::Cook(IProgressNotifier *pProgress)
Pak.WriteBytes(ResourceData.data(), ResourceSize); Pak.WriteBytes(ResourceData.data(), ResourceSize);
rTableInfo.Compressed = false; rTableInfo.Compressed = false;
} }
else else
{ {
uint32 CompressedSize; uint32 CompressedSize;
@ -256,9 +252,9 @@ void CPackage::Cook(IProgressNotifier *pProgress)
// Make sure that the compressed data is actually smaller, accounting for padding + uncompressed size value // Make sure that the compressed data is actually smaller, accounting for padding + uncompressed size value
if (Success) if (Success)
{ {
uint32 CompressionHeaderSize = (Game <= EGame::CorruptionProto ? 4 : 0x10); const uint32 CompressionHeaderSize = (Game <= EGame::CorruptionProto ? 4 : 0x10);
uint32 PaddedUncompressedSize = (ResourceSize + AlignmentMinusOne) & ~AlignmentMinusOne; const uint32 PaddedUncompressedSize = (ResourceSize + AlignmentMinusOne) & ~AlignmentMinusOne;
uint32 PaddedCompressedSize = (CompressedSize + CompressionHeaderSize + AlignmentMinusOne) & ~AlignmentMinusOne; const uint32 PaddedCompressedSize = (CompressedSize + CompressionHeaderSize + AlignmentMinusOne) & ~AlignmentMinusOne;
Success = (PaddedCompressedSize < PaddedUncompressedSize); Success = (PaddedCompressedSize < PaddedUncompressedSize);
} }
@ -268,7 +264,7 @@ void CPackage::Cook(IProgressNotifier *pProgress)
// Write MP1/2 compressed asset // Write MP1/2 compressed asset
if (Game <= EGame::CorruptionProto) if (Game <= EGame::CorruptionProto)
{ {
Pak.WriteLong(ResourceSize); Pak.WriteULong(ResourceSize);
} }
// Write MP3/DKCR compressed asset // Write MP3/DKCR compressed asset
else else
@ -279,13 +275,15 @@ void CPackage::Cook(IProgressNotifier *pProgress)
// multiple blocks or not, so for the sake of simplicity we compress everything to one block. // multiple blocks or not, so for the sake of simplicity we compress everything to one block.
Pak.WriteFourCC( FOURCC('CMPD') ); Pak.WriteFourCC( FOURCC('CMPD') );
Pak.WriteLong(1); Pak.WriteLong(1);
Pak.WriteLong(0xA0000000 | CompressedSize); Pak.WriteULong(0xA0000000 | CompressedSize);
Pak.WriteLong(ResourceSize); Pak.WriteULong(ResourceSize);
} }
Pak.WriteBytes(CompressedData.data(), CompressedSize); Pak.WriteBytes(CompressedData.data(), CompressedSize);
} }
else else
{
Pak.WriteBytes(ResourceData.data(), ResourceSize); Pak.WriteBytes(ResourceData.data(), ResourceSize);
}
rTableInfo.Compressed = Success; rTableInfo.Compressed = Success;
} }
@ -302,7 +300,6 @@ void CPackage::Cook(IProgressNotifier *pProgress)
FileUtil::DeleteFile(PakPath); FileUtil::DeleteFile(PakPath);
mNeedsRecook = true; mNeedsRecook = true;
} }
else else
{ {
// Write table of contents for real // Write table of contents for real
@ -311,26 +308,26 @@ void CPackage::Cook(IProgressNotifier *pProgress)
Pak.Seek(TocOffset, SEEK_SET); Pak.Seek(TocOffset, SEEK_SET);
Pak.WriteLong(3); // Always 3 pak sections Pak.WriteLong(3); // Always 3 pak sections
Pak.WriteFourCC( FOURCC('STRG') ); Pak.WriteFourCC( FOURCC('STRG') );
Pak.WriteLong(NamesSize); Pak.WriteULong(NamesSize);
Pak.WriteFourCC( FOURCC('RSHD') ); Pak.WriteFourCC( FOURCC('RSHD') );
Pak.WriteLong(ResTableSize); Pak.WriteULong(ResTableSize);
Pak.WriteFourCC( FOURCC('DATA') ); Pak.WriteFourCC( FOURCC('DATA') );
Pak.WriteLong(ResDataSize); Pak.WriteULong(ResDataSize);
} }
// Write resource table for real // Write resource table for real
Pak.Seek(ResTableOffset+4, SEEK_SET); Pak.Seek(ResTableOffset+4, SEEK_SET);
for (uint32 iRes = 0; iRes < AssetList.size(); iRes++) for (size_t iRes = 0; iRes < AssetList.size(); iRes++)
{ {
const SResourceTableInfo& rkInfo = ResourceTableData[iRes]; const SResourceTableInfo& rkInfo = ResourceTableData[iRes];
CResourceEntry *pEntry = rkInfo.pEntry; CResourceEntry *pEntry = rkInfo.pEntry;
Pak.WriteLong( rkInfo.Compressed ? 1 : 0 ); Pak.WriteLong(rkInfo.Compressed ? 1 : 0);
pEntry->CookedExtension().Write(Pak); pEntry->CookedExtension().Write(Pak);
pEntry->ID().Write(Pak); pEntry->ID().Write(Pak);
Pak.WriteLong(rkInfo.Size); Pak.WriteULong(rkInfo.Size);
Pak.WriteLong(rkInfo.Offset); Pak.WriteULong(rkInfo.Offset);
} }
// Clear recook flag // Clear recook flag
@ -351,11 +348,11 @@ void CPackage::CompareOriginalAssetList(const std::list<CAssetID>& rkNewList)
// Build a set out of the generated list // Build a set out of the generated list
std::set<CAssetID> NewListSet; std::set<CAssetID> NewListSet;
for (auto Iter = rkNewList.begin(); Iter != rkNewList.end(); Iter++) for (const auto& id : rkNewList)
NewListSet.insert(*Iter); NewListSet.insert(id);
// Read the original pak // Read the original pak
TString CookedPath = CookedPackagePath(false); const TString CookedPath = CookedPackagePath(false);
CFileInStream Pak(CookedPath, EEndian::BigEndian); CFileInStream Pak(CookedPath, EEndian::BigEndian);
if (!Pak.IsValid() || Pak.Size() == 0) if (!Pak.IsValid() || Pak.Size() == 0)
@ -365,24 +362,24 @@ void CPackage::CompareOriginalAssetList(const std::list<CAssetID>& rkNewList)
} }
// Determine pak version // Determine pak version
uint32 PakVersion = Pak.ReadLong(); const uint32 PakVersion = Pak.ReadULong();
std::set<CAssetID> OldListSet; std::set<CAssetID> OldListSet;
// Read MP1/2 pak // Read MP1/2 pak
if (PakVersion == 0x00030005) if (PakVersion == 0x00030005)
{ {
Pak.Seek(0x4, SEEK_CUR); Pak.Seek(0x4, SEEK_CUR);
uint32 NumNamedResources = Pak.ReadLong(); const uint32 NumNamedResources = Pak.ReadULong();
for (uint32 iName = 0; iName < NumNamedResources; iName++) for (uint32 iName = 0; iName < NumNamedResources; iName++)
{ {
Pak.Seek(0x8, SEEK_CUR); Pak.Seek(0x8, SEEK_CUR);
uint32 NameLen = Pak.ReadLong(); const uint32 NameLen = Pak.ReadULong();
Pak.Seek(NameLen, SEEK_CUR); Pak.Seek(NameLen, SEEK_CUR);
} }
// Build a set out of the original pak resource list // Build a set out of the original pak resource list
uint32 NumResources = Pak.ReadLong(); const uint32 NumResources = Pak.ReadULong();
for (uint32 iRes = 0; iRes < NumResources; iRes++) for (uint32 iRes = 0; iRes < NumResources; iRes++)
{ {
@ -391,22 +388,20 @@ void CPackage::CompareOriginalAssetList(const std::list<CAssetID>& rkNewList)
Pak.Seek(0x8, SEEK_CUR); Pak.Seek(0x8, SEEK_CUR);
} }
} }
else // Read MP3/DKCR pak
// Read MP3/DKCR pak
else
{ {
ASSERT(PakVersion == 0x2); ASSERT(PakVersion == 0x2);
// Skip named resources // Skip named resources
Pak.Seek(0x44, SEEK_SET); Pak.Seek(0x44, SEEK_SET);
CFourCC StringSecType = Pak.ReadLong(); [[maybe_unused]] const CFourCC StringSecType = Pak.ReadULong();
uint32 StringSecSize = Pak.ReadLong(); const uint32 StringSecSize = Pak.ReadULong();
ASSERT(StringSecType == "STRG"); ASSERT(StringSecType == "STRG");
Pak.Seek(0x80 + StringSecSize, SEEK_SET); Pak.Seek(0x80 + StringSecSize, SEEK_SET);
// Read resource table // Read resource table
uint32 NumResources = Pak.ReadLong(); const uint32 NumResources = Pak.ReadULong();
for (uint32 iRes = 0; iRes < NumResources; iRes++) for (uint32 iRes = 0; iRes < NumResources; iRes++)
{ {
@ -417,27 +412,23 @@ void CPackage::CompareOriginalAssetList(const std::list<CAssetID>& rkNewList)
} }
// Check for missing resources in the new list // Check for missing resources in the new list
for (auto Iter = OldListSet.begin(); Iter != OldListSet.end(); Iter++) for (const auto& ID : OldListSet)
{ {
CAssetID ID = *Iter;
if (NewListSet.find(ID) == NewListSet.end()) if (NewListSet.find(ID) == NewListSet.end())
{ {
CResourceEntry *pEntry = gpResourceStore->FindEntry(ID); const CResourceEntry *pEntry = gpResourceStore->FindEntry(ID);
TString Extension = (pEntry ? "." + pEntry->CookedExtension() : ""); const TString Extension = (pEntry != nullptr ? "." + pEntry->CookedExtension() : "");
warnf("Missing resource: %s%s", *ID.ToString(), *Extension); warnf("Missing resource: %s%s", *ID.ToString(), *Extension);
} }
} }
// Check for extra resources in the new list // Check for extra resources in the new list
for (auto Iter = NewListSet.begin(); Iter != NewListSet.end(); Iter++) for (const auto& ID : NewListSet)
{ {
CAssetID ID = *Iter;
if (OldListSet.find(ID) == OldListSet.end()) if (OldListSet.find(ID) == OldListSet.end())
{ {
CResourceEntry *pEntry = gpResourceStore->FindEntry(ID); const CResourceEntry *pEntry = gpResourceStore->FindEntry(ID);
TString Extension = (pEntry ? "." + pEntry->CookedExtension() : ""); const TString Extension = (pEntry != nullptr ? "." + pEntry->CookedExtension() : "");
warnf("Extra resource: %s%s", *ID.ToString(), *Extension); warnf("Extra resource: %s%s", *ID.ToString(), *Extension);
} }
} }
@ -453,12 +444,12 @@ bool CPackage::ContainsAsset(const CAssetID& rkID) const
TString CPackage::DefinitionPath(bool Relative) const TString CPackage::DefinitionPath(bool Relative) const
{ {
TString RelPath = mPakPath + mPakName + ".pkd"; const TString RelPath = mPakPath + mPakName + ".pkd";
return Relative ? RelPath : mpProject->PackagesDir(false) + RelPath; return Relative ? RelPath : mpProject->PackagesDir(false) + RelPath;
} }
TString CPackage::CookedPackagePath(bool Relative) const TString CPackage::CookedPackagePath(bool Relative) const
{ {
TString RelPath = mPakPath + mPakName + ".pak"; const TString RelPath = mPakPath + mPakName + ".pak";
return Relative ? RelPath : mpProject->DiscFilesystemRoot(false) + RelPath; return Relative ? RelPath : mpProject->DiscFilesystemRoot(false) + RelPath;
} }