From f426e60c400f17fbf5ab291ec202c77dd0ef11ba Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Sun, 31 Mar 2024 22:52:01 +0300 Subject: [PATCH] Do not require `_dir` in chunked vpks Fixes #18 --- .../Files/steamdb_test_without_suffix.vpk | Bin 0 -> 202 bytes .../Files/steamdb_test_without_suffix_000.vpk | Bin 0 -> 58101 bytes ValvePak/ValvePak.Test/PackageTest.cs | 23 ++++++------------ ValvePak/ValvePak/Package.Read.cs | 15 ++++++------ 4 files changed, 16 insertions(+), 22 deletions(-) create mode 100644 ValvePak/ValvePak.Test/Files/steamdb_test_without_suffix.vpk create mode 100644 ValvePak/ValvePak.Test/Files/steamdb_test_without_suffix_000.vpk diff --git a/ValvePak/ValvePak.Test/Files/steamdb_test_without_suffix.vpk b/ValvePak/ValvePak.Test/Files/steamdb_test_without_suffix.vpk new file mode 100644 index 0000000000000000000000000000000000000000..7abc3d6253dbf1706bfb1b4275e670f9fa172b13 GIT binary patch literal 202 zcmXpJS{2H~z`#%k#4un0WfTW@iHIb)YN<5EbwklYp7o}2v)n^;~paL#!1!>LZKwoff( QLRg)n)xz_K4J>v60Ay}KSO5S3 literal 0 HcmV?d00001 diff --git a/ValvePak/ValvePak.Test/Files/steamdb_test_without_suffix_000.vpk b/ValvePak/ValvePak.Test/Files/steamdb_test_without_suffix_000.vpk new file mode 100644 index 0000000000000000000000000000000000000000..48d283c4feed8defca5dd306cd512fb0813b032d GIT binary patch literal 58101 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 C_97qv literal 0 HcmV?d00001 diff --git a/ValvePak/ValvePak.Test/PackageTest.cs b/ValvePak/ValvePak.Test/PackageTest.cs index d7bba99..c4e59cb 100644 --- a/ValvePak/ValvePak.Test/PackageTest.cs +++ b/ValvePak/ValvePak.Test/PackageTest.cs @@ -240,21 +240,6 @@ public void ThrowsOnInvalidCRC32() Assert.DoesNotThrow(() => package.ReadEntry(file, out _, false)); } - [Test] - public void ThrowsOnExternalFilesNotInDirVpk() - { - var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "broken_dir.vpk"); - using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - - using var package = new Package(); - package.SetFileName("test.vpk"); - package.Read(fs); - - var file = package.FindEntry("UpperCaseFolder/UpperCaseFile.txt"); - Assert.That(file.CRC32, Is.EqualTo(0x32CFF012)); - Assert.Throws(() => package.ReadEntry(file, out _)); - } - [Test] public void ThrowsOnInvalidEntryTerminator() { @@ -363,6 +348,14 @@ public void ExtractDirVPK() TestVPKExtraction(path); } + [Test] + public void ExtractDirVPKWithoutSuffix() + { + var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "steamdb_test_without_suffix.vpk"); + + TestVPKExtraction(path); + } + [Test] public void ExtractIntoUserProvidedByteArray() { diff --git a/ValvePak/ValvePak/Package.Read.cs b/ValvePak/ValvePak/Package.Read.cs index f5fb927..379a987 100644 --- a/ValvePak/ValvePak/Package.Read.cs +++ b/ValvePak/ValvePak/Package.Read.cs @@ -324,12 +324,7 @@ private Stream GetFileStream(ushort archiveIndex) if (archiveIndex != 0x7FFF) { - if (!IsDirVPK) - { - throw new InvalidOperationException("Given VPK filename does not end in '_dir.vpk', but entry is referencing an external archive."); - } - - var fileName = $"{FileName}_{archiveIndex:D3}.vpk"; + var fileName = GetArchiveIndexFullFilePath(archiveIndex); stream = new FileStream(fileName, FileMode.Open, FileAccess.Read); } @@ -383,7 +378,7 @@ public Stream GetMemoryMappedStreamIfPossible(PackageEntry entry) } else { - path = $"{FileName}_{entry.ArchiveIndex:D3}.vpk"; + path = GetArchiveIndexFullFilePath(entry.ArchiveIndex); } stream = MemoryMappedFile.CreateFromFile(path, FileMode.Open, null, 0, MemoryMappedFileAccess.Read); @@ -400,6 +395,12 @@ public Stream GetMemoryMappedStreamIfPossible(PackageEntry entry) return stream.CreateViewStream(offset, entry.Length, MemoryMappedFileAccess.Read); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private string GetArchiveIndexFullFilePath(ushort archiveIndex) + { + return $"{FileName}_{archiveIndex:D3}.vpk"; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private string ReadNullTermUtf8String(MemoryStream ms) {