Deficuet.APFS
0.0.1-alpha.4
dotnet add package Deficuet.APFS --version 0.0.1-alpha.4
NuGet\Install-Package Deficuet.APFS -Version 0.0.1-alpha.4
<PackageReference Include="Deficuet.APFS" Version="0.0.1-alpha.4" />
<PackageVersion Include="Deficuet.APFS" Version="0.0.1-alpha.4" />
<PackageReference Include="Deficuet.APFS" />
paket add Deficuet.APFS --version 0.0.1-alpha.4
#r "nuget: Deficuet.APFS, 0.0.1-alpha.4"
#:package Deficuet.APFS@0.0.1-alpha.4
#addin nuget:?package=Deficuet.APFS&version=0.0.1-alpha.4&prerelease
#tool nuget:?package=Deficuet.APFS&version=0.0.1-alpha.4&prerelease
APFS — AzurPromilia Package File System
A read-only virtual file system for game asset packages, built on ROVFS (and therefore WinFsp). APFS is the data manager implementation: it maps a JSON-describable asset tree onto two flat, case-insensitive dictionaries and serves reads from segmented package files.
Concepts
| Type | Role |
|---|---|
SegmentedFileEntry |
One virtual file: PackageName, ResSubPath, PathType, plus Offset/Size of the segment inside its backing package file. |
DirectoryData |
Population-phase (intermediate) directory node holding child files and directories in case-insensitive dictionaries. |
DirectoryView |
Static (final) directory: natural-sort-ordered EntryInfo<string>[] plus a case-insensitive name→index map for O(1) marker lookup; Win32 wildcard matching is built in. |
AzurPromiliaFileDataManager |
The ROVFS data manager: path resolution, directory contexts, backing file handles, and FileInfo assembly. |
Population workflow
The manager follows a populate first, mount once, never modify lifecycle. Entry and directory objects are created outside this project; after population they are handed to the manager, and the tree can be serialized to / deserialized from JSON (also outside this project) for persistence.
Create a root
DirectoryDatainstance acting as the volume root.For every file call
root.AddFile(path, entry).pathis the file's full path relative to the node,/-separated, and never starts with a separator; missing intermediate directories are created implicitly (case-insensitively merged). The per-directory key inserts a_{PackResName}-{offset}-{size}suffix between the file name and its extension, so identically named segments from different packages stay unique:root.AddFile("characters/hero/hero.bin", new SegmentedFileEntry { PackageName = "pkg001", ResSubPath = "characters/hero/hero.bin", PackResName = "pkg001", PathType = PathType.Static, Offset = 0, Size = 1048576, }); // dictionary key: "hero_pkg001-0-1048576.bin"Call
manager.AddFileTree(root). This traverses the tree breadth-first, finalizes every node into aDirectoryView, assigns a uniqueIndexNumberto every file and directory (counter starts at 0, also persisted with the intermediate tree), accumulatesTotalSize, and stores every node under its full path. Full paths are rooted at\and use\separators — this is exactly the form WinFsp passes to the file system, regardless of whether the volume is mounted on a drive letter or into an existing empty folder (the mount point prefix never reaches user mode).Mount.
AddFileTreemay be called exactly once; the internal maps must not be modified afterwards.
All lookups (TryResolveFile, TryResolveDirectory, TryCheckNodeExists) use StringComparer.OrdinalIgnoreCase dictionaries, matching the case-insensitive volume flag applied by ROVFS.
Backing files
| PathType | Physical location |
|---|---|
Static |
{RootDirectoryPath}\StreamingAssets\.res\{PackageName}\{ResSubPath} |
Cache |
{RootDirectoryPath}\.res\{PackageName}\BundleFiles\{ResSubPath} |
RootDirectoryPath must not end with a separator. Handles are opened read-only with FILE_FLAG_OVERLAPPED, so multiple segments of the same package can be read concurrently through independent handles. A missing or unreadable backing file is logged and mapped to a Win32-derived NT status.
Mounting example
var manager = new AzurPromiliaFileDataManager(rootDirectoryPath, mountPoint)
{
GlobalTimestamp = volumeCreationFileTime,
};
manager.PackageTimestampMap["pkg001"] = packageFileTime;
manager.AddFileTree(root); // populated tree from the steps above
var fileSystem = new ReadOnlyFileSystem<
SegmentedFileEntry, DirectoryView, SafeFileHandle, string, string>(manager);
var host = new FileSystemHost(fileSystem);
host.Mount("X:"); // or host.Mount(@"C:\Some\Empty\Folder");
Dependencies
- Deficuet.ROVFS
0.0.1-alpha.14 NaturalSort.Extension4.4.1Newtonsoft.Json13.0.4(used by the external serialization code, not by this library)System.Text.Encoding.CodePages8.0.0- WinFsp
2.1must be installed on the machine.
Both libraries target netstandard2.0; Deficuet.ROVFS transitively brings in System.Memory, which Unity consumers must also ship.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Deficuet.ROVFS (>= 0.0.1-alpha.15)
- NaturalSort.Extension (>= 4.4.1)
- Newtonsoft.Json (>= 13.0.4)
- System.Text.Encoding.CodePages (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.1-alpha.4 | 67 | 9/13/2026 |
| 0.0.1-alpha.3 | 69 | 9/13/2026 |
| 0.0.1-alpha.2 | 73 | 9/8/2026 |
| 0.0.1-alpha.1 | 71 | 9/8/2026 |