[Ampr] Fix PakDirectoryTracker to handle multiple directories with the same name
This commit is contained in:
parent
4799a1f82f
commit
ecaf856425
|
|
@ -60,10 +60,19 @@ internal static class PakDirectoryTracker
|
|||
// related assets, and the guest streams them with locality, so disambiguate collisions
|
||||
// by choosing the unconsumed match nearest the running read cursor.
|
||||
DirectoryEntry? best = null;
|
||||
DirectoryEntry? uniqueMatch = null;
|
||||
var matchCount = 0;
|
||||
var bestDistance = ulong.MaxValue;
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
if (entry.Consumed || entry.FileLen != requestedSize)
|
||||
if (entry.FileLen != requestedSize)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uniqueMatch = entry;
|
||||
matchCount++;
|
||||
if (entry.Consumed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -90,6 +99,12 @@ internal static class PakDirectoryTracker
|
|||
|
||||
return best.FilePos;
|
||||
}
|
||||
|
||||
// A unique archive member may be opened again after its first read.
|
||||
if (matchCount == 1)
|
||||
{
|
||||
return uniqueMatch!.FilePos;
|
||||
}
|
||||
}
|
||||
|
||||
return state.NextOffset;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,23 @@ public sealed class PakDirectoryTrackerTests
|
|||
Assert.Equal(0x1000UL + (runLen * 2), third);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResolveSequentialOffset_UniqueEntryCanBeReadAgain()
|
||||
{
|
||||
const uint fileId = 0x5AA5_0003;
|
||||
const uint size = 15903;
|
||||
var memory = new FakeCpuMemory(0x1_0000_0000, 0x1000);
|
||||
var ctx = new CpuContext(memory, Generation.Gen5);
|
||||
LoadDirectory(ctx, fileId, memory, 0x1_0000_0000, dirFileOffset: 0x400, new[]
|
||||
{
|
||||
new PakEntry("bots/characters.txt", FilePos: 0xF81CF, FileLen: size),
|
||||
});
|
||||
|
||||
Assert.Equal(0xF81CFUL, PakDirectoryTracker.ResolveSequentialOffset(fileId, size));
|
||||
PakDirectoryTracker.OnReadCompleted(ctx, fileId, destination: 0x1_0000_0000, fileOffset: 0xF81CF, bytesRead: size);
|
||||
Assert.Equal(0xF81CFUL, PakDirectoryTracker.ResolveSequentialOffset(fileId, size));
|
||||
}
|
||||
|
||||
// Feeds the tracker a synthetic PACK header + directory table exactly as the AMPR read path does:
|
||||
// first the 12-byte header (which arms directory parsing), then the directory records themselves.
|
||||
private static void LoadDirectory(
|
||||
|
|
|
|||
Loading…
Reference in New Issue