PSAR: don't decrypt entries a filter is going to reject

Decrypting an entry's contents is by far the most expensive part of
walking an archive, and it happened for every entry before the filter
was even consulted. Now it waits until entryData()/entryCompression()
asks, so pulling just the fonts out of an updater no longer costs a
full firmware decrypt. Records are decrypted independently of each
other, so deferring one is safe.

Unpacking fonts from a 3.11 updater goes 0.365s -> 0.133s; a full
unpack is unchanged and produces identical output. The compression
counts now describe the entries we actually decoded rather than
everything in the archive.

Also adds --unpack-updater-filter to headless, which is how the above
was measured.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
This commit is contained in:
Henrik RydgårdandClaude Opus 5 committed 2026-09-04 18:35:07 -06:00
1 parent a641305c75
commit 111f01481c
4 files changed
+56 -22

No files matched your search

+5 -2
View File
@@ -630,6 +630,9 @@ int main(int argc, const char* argv[]) {
PSARUnpackOptions unpackOptions;
unpackOptions.verbose = testOptions.verbose;
if (cmdLineOptions.unpackUpdaterFilter.has_value()) {
unpackOptions.prefixFilter = cmdLineOptions.unpackUpdaterFilter.value();
}
if (cmdLineOptions.unpackUpdaterModel.has_value() &&
!PSPModelGenerationFromString(cmdLineOptions.unpackUpdaterModel.value(), &unpackOptions.model)) {
fprintf(stderr, "Unknown PSP model '%s' - expected 01g..12g or any\n", cmdLineOptions.unpackUpdaterModel.value().c_str());
@@ -641,9 +644,9 @@ int main(int argc, const char* argv[]) {
if (!ok) {
fprintf(stderr, "Unpacking failed: %s\n", unpackError.c_str());
}
printf("Firmware %s (model %s): %d entries, %d files written, %d directories, %d unresolved names, %d for other models, %d failed\n",
printf("Firmware %s (model %s): %d entries, %d files written, %d directories, %d skipped by filter, %d unresolved names, %d for other models, %d failed\n",
stats.firmwareVersion.c_str(), PSPModelGenerationToString(unpackOptions.model), stats.entries, stats.written,
stats.directories, stats.unnamed, stats.otherModel, stats.failed);
stats.directories, stats.skippedByFilter, stats.unnamed, stats.otherModel, stats.failed);
printf("Compression: none=%d zlib=%d KL4E=%d KL3E=%d LZR=%d unknown=%d\n",
stats.compressionCounts[(int)PSARCompression::None],
stats.compressionCounts[(int)PSARCompression::Zlib],