Repository navigation
Ampr pack - #1
Merged
Merged
Conversation
Port of ampr_emu ampr_pack.py: LZ4 1.9.4 native shim, AMPRPAK4 formats, TOML config and default preset, builder, verify/unpack/list/inspect, runtime-config, remove-sources, ampr CLI verb, GUI panel, parity tests. Parked: packs only work for titles that read assets through the AMPR API; Unity titles (ordinary file I/O) fail with the default ampr_emu build.
Checked the ampr-pack branch against how ShadowMountPlus and ampr_emu load LZ4 packs on the console: - ampr_emu.index now folds only ASCII letters and hashes UTF-8 bytes with ampr_emu's FNV basis, like build_ampr_index.py and the runtime resolver. Lower-casing every letter and hashing code points (Python MkPFS) left files with non-ASCII names unfindable on the console. The index also skips ampr_commands.bin, apr_emu.log and paths with tabs or line breaks. ASCII-only trees give the same bytes as before. - fakelib2/libSceAmpr.sprx (ShadowMountPlus's exclusive overlay) also triggers the index, the default preset keeps fakelib2/ loose, and --ampr-libs warns when fakelib2/ would hide the copied libraries. - ampr pack warns when a set exceeds the default emulator's limits (2,000,000 files, 16,000,000 chunks, 1,024 volumes), which make the runtime reject the whole manifest, and when --root has no AMPR Emu. - README: APR-only titles, read-only mounts, deploying one build set. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
When the generated AMPR goldens are absent, Fixtures.PathOrSkip skips the case before the work directory exists, and the finally block's Directory.Delete then threw DirectoryNotFoundException, turning 29 skips into failures. Delete the directory only when it exists, as the other parity tests already do. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
New `ampr game` subcommand and default GUI action "Build playable game" on the AMPR Packs page. From an unpacked game folder (only read) it builds a new folder that runs from AMPR packs as is: 1. Libraries: the game's fakelib/ (or fakelib2/, which ShadowMountPlus mounts instead) plus every file of the selected library folder, skipping identical files. libSceAmpr.sprx must be AMPR Emu 0.4.2.1+, detected by its embedded AMPRPAK4 magic; older builds are rejected before anything is written. 2. ampr_emu.index of the final tree (new libraries with their real sizes), written before packing because the manifest addresses files by index row. Byte-identical to upstream build_ampr_index.py run on the reconstructed final folder. 3. Packs, read from the game folder (default preset unless a TOML or preset is given). 4. Loose files and every folder, copied after packing because the packer's sampling decides which large files stay loose. 5. Verification: every chunk decoded, packed files compared with the source, loose files checked against their indexed sizes. A failed step empties the output so a retry starts clean. --exfat (GUI checkbox) then builds a 64 KiB-cluster exFAT image of the folder; a failed image keeps the finished folder. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
The GUI action "Pack game files" ran `ampr pack`, which (like ampr_pack.py) writes only ampr_assets.index, the .pak volumes and the .crc, and users expected a playable folder. Rename it "Pack files only (manifest and .pak volumes)" and show a note pointing to Build playable game. Also correct the docs: the AMPR Emu 0.4.2.1 release is the PackedStdio build, which serves packed files to ordinary open/read/pread and AIO calls as well as AMPR reads, so Unity titles that load libSceAmpr work; only mmap and writable opens must stay loose. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Console test with God of War Sons of Sparta (Unity, IL2CPP) on AMPR Emu 0.4.2.1: packing everything except executables and system files made the game abort at startup (SYSTEM_ABNORMAL_TERMINATION_REQUEST), while packing only Media/StreamingAssets (Addressables bundles, FMOD banks) ran normally. Unity's own data files (level*, sharedassets*, globalgamemanagers, .resS) must stay loose, consistent with Unity reading them through a path AMPR Emu does not intercept. `--preset unity` for `ampr pack` and `ampr game`, and a Rules picker (Default / Unity) on the AMPR Packs page when no TOML is chosen. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Users should not have to know which engine a game uses. New preset `auto` (the default for `ampr game` and the AMPR Packs page, available to `ampr pack`): `unity` when globalgamemanagers, data.unity3d or global-metadata.dat is within four folder levels of the game root, else `default`. The log names the chosen rules and the file that decided them. A TOML file still overrides it. The GUI Rules picker added in the previous commit is removed. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Whether a packed game runs depends on how it reads its files, which only a console test shows, and few games have been tested. Say so: - README: "(experimental)" in the feature list and a notice at the top of the ampr section (keep the original game, report failing titles with the ShadowMountPlus log). - GUI: an amber notice at the top of the AMPR Packs page, in all six languages. - CLI: the ampr help says experimental; `ampr game` prints a warning before it starts. `ampr pack` output is unchanged (ampr_pack.py parity). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
A warning under the intro links to a new explanation at the top of the ampr section: what packing does, what a game needs (ShadowMountPlus, a libSceAmpr title, AMPR Emu 0.4.2.1+, read-only mount), why only a console test shows whether a game runs (reads AMPR Emu does not intercept, such as mmap), how the automatic rules were chosen, the games tested so far, recommended steps, and what to report. The existing reference follows under "How the packs are made" and "Command reference". Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
The CLI log (ampr game, ampr pack --preset) and the AMPR Packs page now
say whether a built-in profile matched the game, which one, the file
that identified it, and whether it has run on a PS5 ("Profile found:
unity (...). Tested: runs on ..." or "No profile found for this game:
generic rules ... Untested"). A TOML file is reported as such. The page
shows the result as soon as the game folder is chosen.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Insomniac Games titles (toc, dag and d/ at the top) now get rules that pack only the d/ archives and keep the boot, movie, sound bank and streamed audio archives loose. PPSA03671 crashed at startup with the default rules and runs with these. --preset auto detects the layout and reports it as a tested profile; the README records the result. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
AMPR Emu's debug build records every APR read into ampr_commands.bin. `mkpfs ampr profile generate` ports ampr_emu's ampr_pack_profile.py 4.1 (the AMPRCMD1 reader, per-file read metrics, block-size scoring, index budget, decoded-cache model and rule emission): the TOML, the Markdown report and the runtime header match the Python tool byte for byte on 33 synthetic trace cases (tools/oracle/check_ampr_profile.py). --metrics JSON and batch are not ported. `ampr game` and `ampr pack` take --traces <folder> (one run per subfolder) and pack from those rules directly; the log says how many runs and files were used. The AMPR Packs page has a matching trace folder field that reports how many runs it found. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
`ampr profile generate --metrics` (and --full-metrics) writes the upstream metrics document, and `ampr profile batch` writes one profile per trace run of a folder or ZIP support bundle (TOML, report, metrics JSON, runtime header and summary.json), with the upstream batch defaults (hybrid patterns, no cache simulation) and --batch-jobs. The JSON writer gains insertion-ordered objects for documents dumped without sort_keys. tools/oracle/check_ampr_profile.py now covers both: 45 cases, every output byte for byte against the Python tool. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
The trace folder search skipped files with the Hidden or System attribute (the .NET default), which copies off the console can carry; Python's rglob counts them, and names now follow the platform's case rules like rglob. The AMPR Packs page also looked at the game and trace folders only when a path was picked, so runs copied in later kept the "No traces in this folder" warning; it now looks again before each run. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
A trace session rarely reaches every level or mode: with two UFC 6 sessions, 111 of its .cas archives (24 GiB) were never read and stayed loose. --pack-untraced-types (ampr game, ampr pack, profile generate) and a checkbox on the AMPR Packs page add every untraced file of the traced games' indexes whose extension a packed traced file has, with the layout, block size and group most traced files of that type got. Files without an extension, executables, modules, sce_sys and fakelib are never added; the rules go before the upstream safety exclusions, and the upstream part of the TOML is unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Images were always exactly full (no free cluster), so nothing could write to a mounted image even read-write: AMPR Emu's debug log stayed empty when a packed game was tested. pack exfat --free-space, ampr game --exfat-free-space and a field on the AMPR Packs page reserve zeroed clusters at the end of the heap; only the used ones are marked in the allocation bitmap. With the default 0 the image is unchanged. fsck.exfat (exfatprogs 1.2.2) reports both kinds of image clean. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
The default, insomniac and unity presets, their auto-detection and --preset are removed. ampr game and the AMPR Packs page now need the game's TOML profile (--config) or a trace folder (--traces); the profiles are published as separate files, one per game. The README describes what the tested profiles learned and adds EA SPORTS UFC 6 to the tested games. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
…mp folder
- AMPR Packs page: the trace folder is searched recursively, and this ran on the
UI thread on every keystroke, so a half-typed path such as a drive root froze
the window. The count now runs in the background after typing pauses.
- profile batch: ZIP member names were split only on '/', so on Windows a part
holding "..\" or a drive ("C:") could write outside the extraction folder.
The resolved target must now stay inside it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
ShadowMountPlus works best with an exFAT image wrapped in FFPFSC, so BUILD now lists Pack exFAT, Pack FFPFSC (formerly Pack File) and AMPR Packs. The Pack Folder and Batch pages are removed from the GUI with their views, view models and strings; `pack folder` and `batch` stay in the CLI. A trace-folder test assertion that raced with the background count is removed. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
…ltips - Runs with several progress phases (pack file with --verify, verify against a source, repair, ampr game with an exFAT image) now fill one bar across all phases, weighted by how much data each moves, and never move it back; the label names the step, for example "verify (2/3)". - CPU Cores is a dropdown: Auto, which uses every core of the computer, then 1 up to the core count. The CLI default is unchanged. - Every Compression Tuning and Advanced option has a tooltip in all six languages. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Environment.ProcessorCount counts logical processors, twice the cores on a CPU with SMT. The picker and its Auto entry now use the physical core count, read from GetLogicalProcessorInformationEx on Windows, the sysfs topology on Linux and hw.physicalcpu on macOS, falling back to the logical count. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
README: a centered header with badges and a screenshot, a contents list, a features table, a quick start with a diagram of the exFAT -> FFPFSC flow, a "which file should I make" table, desktop app screenshots and page table, command and exit-code tables, long option tables folded away, and diagrams for how AMPR packs are read and how a game gets packed. MIGRATION.md gets an at-a-glance table and a table of fixed Python bugs; the oracle README a summary of the three oracles, the profile check and a fixed line-ending note; the native ORIGIN notes a source table. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B4TzvxgYewNT7gc6MCuF5N
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.