Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/bsa-inspection.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,23 @@ Limits: 4,294,967,295 input bytes, 64 MiB metadata, 100,000 folders, 500,000 fil
This report is **source evidence only**. It does not change the ZIP/7z/RAR ledger or automatically produce a recipe. To establish an upstream source chain, separately verify the outer download archive, its exact BSA member hash and the desired internal member hash. Compare the installed file's complete size/SHA-256; a similar name or image is insufficient. A reviewed recipe can use the explicit [`extract-bsa104` action](loadstone-format.md#outputs-and-actions) for [bounded nested-BSA reconstruction](native-reconstruction.md#nested-bsa-104-files). Transformed-file reproduction, rights review and real installation acceptance remain separate work. No game or mod data is bundled by this command.

The JavaScript implementation and synthetic fixtures are original. Format semantics were checked against Wabbajack's pinned [104/105 reader](https://github.com/wabbajack-tools/wabbajack/blob/4.2.3.0/Wabbajack.Compression.BSA/TES5Archive/Reader.cs), [folder records](https://github.com/wabbajack-tools/wabbajack/blob/4.2.3.0/Wabbajack.Compression.BSA/TES5Archive/FolderRecord.cs) and [file records](https://github.com/wabbajack-tools/wabbajack/blob/4.2.3.0/Wabbajack.Compression.BSA/TES5Archive/FileRecord.cs). Loadstone deliberately supports a narrower format subset.

## Nested source mapping

The separate creator command extends a private [source ledger](installed-inventory.md) with exact nested matches:

```powershell
node scripts/map-bsa-sources.mjs private-mapping.json new-private-bsa-mapping.json --mod "Example container mod" --7zip C:\Tools\7-Zip\7z.exe
```

Repeat `--mod` for other exact inventoried mod names. The selected mods must contain inventoried `.bsa` files and have original archive candidates in the ledger. Disabled mods can supply containers without being enabled. The optional `--7zip` is required for 7z/RAR candidates; ZIP comparison uses the built-in reader. No tool or original archive is downloaded by this command.

The mapper independently rehashes each selected original archive and validates its complete structure. It hashes candidate BSA members and compares their full size/SHA-256 with the installed BSA inventory. Only then does it inspect the matching local BSA, rechecking the complete container fingerprint and hashing its internal contents. The local file is a read-only witness of the verified original member; nothing is staged or extracted. It compares inner content with all managed mod-file fingerprints in the accepted ledger, including disabled mods, and excludes local `meta.ini`. It does not rehash every loose installed target during this pass, nor map game/root/profile/overwrite records.

Each matched file receives a separate `bsaSourceMatches` array. A reference records `archiveSha256`, `container: { member, bytes, sha256 }`, the inner `member` and the number of byte-equivalent inner members (`equivalentMembers`). The representative is the lexicographically first normalized inner path per container and content fingerprint. The original archive's fingerprint and available provider hints appear in `bsaMapping.sources`; provider hints still require review. These references supply the fields for a reviewed `extract-bsa104` action once a recipe source ID is assigned. They do not generate or approve a recipe.

Existing `sourceMatches`, the direct `mapping` report, mod states and other inventory records remain intact. `bsaMapping` separately reports nested matches, newly matched files and the combined unique file totals. Re-running the command replaces the nested extension from fresh checks without multiplying old references. A fresh direct archive-mapping pass clears the old nested extension, which must then be recomputed. Failed archives or containers produce unresolved issues; no partial matches from a failed inspection are accepted.

Limits: 64 selected containers, 20 GB total container bytes, 20 GB combined successfully inspected logical content, 1,000 candidate archive paths and 500,000 nested match references, in addition to the existing archive/BSA reader limits. ZIP and per-member 7z/RAR comparison retain their 1 GB member limit; eligible 7z archives can use the existing bounded single-pass reader for larger members. Other BSA versions and arbitrary nesting remain unsupported.

The command locks the input ledger, referenced inventory and optional source hints, checks them again before writing, refuses existing report paths and keeps reports outside installation/download roots. Ctrl+C cancels without a final report. Reports contain private paths and installed-content names: keep them outside public source. Matching bytes establish source evidence only; source rights, typed transformations, recipe validation and actual reconstruction/gameplay acceptance remain required.
2 changes: 1 addition & 1 deletion docs/installed-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ For tests, `scripts/prepare-sevenzip.ps1 -Destination <new-private-directory>` d

7-Zip is a separate upstream tool with LGPL, BSD and unRAR terms; a future bundled distribution needs its own notices/source compliance review. See the [official release](https://github.com/ip7z/7zip/releases/tag/26.04) and [license](https://www.7-zip.org/license.txt).

For a separate read-only inventory of files inside a local Fallout 3/New Vegas BSA, see [BSA 104 inspection](bsa-inspection.md). This hashes the internal members without adding nested-container matches to the ledger. Reviewed source chains can be declared explicitly for [native BSA reconstruction](native-reconstruction.md#nested-bsa-104-files).
For a separate read-only inventory of files inside a local Fallout 3/New Vegas BSA, see [BSA 104 inspection](bsa-inspection.md). To connect selected installed BSAs to original archive candidates and compare their contents with the ledger, use [nested BSA source mapping](bsa-inspection.md#nested-source-mapping). Reviewed source chains can then be declared explicitly for [native BSA reconstruction](native-reconstruction.md#nested-bsa-104-files).

## Native `.loadstone` format

Expand Down
9 changes: 8 additions & 1 deletion electron/archive-mapping.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ async function mapArchiveSources(ledger, options = {}) {
throw new Error('Use a supported source ledger.');
const result = structuredClone(ledger),
archiveGroups = new Map();
// A fresh direct pass does not revalidate previously recorded nested chains.
delete result.bsaMapping;
let fileCount = 0;
for (const mod of result.mods) {
if (
Expand All @@ -122,6 +124,7 @@ async function mapArchiveSources(ledger, options = {}) {
)
throw new Error('Invalid installed file fingerprint.');
file.sourceMatches = [];
delete file.bsaSourceMatches;
}
if (mod.separator || !mod.installedFiles.length) continue;
for (const candidate of mod.archiveCandidates) {
Expand Down Expand Up @@ -240,4 +243,8 @@ async function mapArchiveSources(ledger, options = {}) {
];
return result;
}
module.exports = { mapArchiveSources, mapZipSources: mapArchiveSources };
module.exports = {
mapArchiveSources,
mapZipSources: mapArchiveSources,
inspectZipMembers,
};
Loading
Loading