mirror of
https://github.com/quer3q/ps5-dump-forge.git
synced 2026-10-22 05:22:17 -05:00
- PS5 payload (plain .elf): the core runs on the console, built in Docker against the ps5-payload-dev SDK v0.43 (ps5/: target JSON, ps5-ai-cli shims, entry.c, compat.c, linker.sh; FreeBSD 11 ABI via --cfg libc_unstable_freebsd_version="11", struct sizes asserted). - New crate ps5-dump-forge-server and `ps5-dump-forge serve`: the React UI over HTTP on port 8095 (fetch transport, polling, folder/file browser, Show path, Stop), no access control by design. Home-screen tile PDFG00001; the payload saves a copy of itself (two-stage build) so the tile's AppCache'd page can start it through elfldr after a restart. - FreeBSD platform layer in core: destination probe (dest.rs), publish by link or checked rename behind a device guard, bounded dirty data with adaptive fsync cadence (durable.rs), read-ahead (prefetch.rs), drive-removal messages, rest-mode PowerTick. A retried fsync fails the job. - Fast verification is the default on every platform: structure + sampled BLAKE3 slices; "Full verification" switch / --full-verify re-reads every byte; .pkg always full. One hash pass per byte. - vendor patch 0015: UFS2 range reads (cached pointer blocks, contiguous runs, checked offsets). - Tests and tooling: scripts/test-freebsd.sh (FreeBSD VM: UFS, FAT32, nullfs), scripts/release-ps5.sh (ELF, embedded UI, self copy and debug-route checks), CI and release jobs for the .elf. - Hardware (PS5 fw 13.60, /data): .ffpkg/folder sources to .exfat and folder pass their checks; writes ~273 MB/s of the drive's ~288 MB/s; tile launch after a reboot works. Other output formats and USB output are not console-tested yet (TODO.md). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
39 lines
1.5 KiB
JavaScript
39 lines
1.5 KiB
JavaScript
// The http build's AppCache manifest (vite.config.ts writes it after the bundle; the PS5
|
|
// browser keeps the page offline with it, see src/appcache.ts). Plain node, so
|
|
// scripts/check-launcher.mjs runs the same code.
|
|
|
|
import { createHash } from "node:crypto";
|
|
import { readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
|
|
export const MANIFEST = "forge.appcache";
|
|
|
|
/** Every file under `dir` but the manifest, `/`-separated and sorted. */
|
|
export function bundleFiles(dir, prefix = "") {
|
|
const out = [];
|
|
for (const e of readdirSync(join(dir, prefix), { withFileTypes: true })) {
|
|
const rel = prefix + e.name;
|
|
if (e.isDirectory()) out.push(...bundleFiles(dir, `${rel}/`));
|
|
else if (rel !== MANIFEST) out.push(rel);
|
|
}
|
|
return out.sort();
|
|
}
|
|
|
|
/** `CACHE MANIFEST`, a hash over every path and its bytes (any rebuild that changes a byte
|
|
* changes the manifest, so the browser fetches the new page), `/` and every file, then
|
|
* `NETWORK: *` (the API and elfldr). */
|
|
export function manifestText(dir) {
|
|
const files = bundleFiles(dir);
|
|
const hash = createHash("sha256");
|
|
for (const f of files) {
|
|
const bytes = readFileSync(join(dir, f));
|
|
hash.update(`${f}\0${bytes.length}\0`);
|
|
hash.update(bytes);
|
|
}
|
|
return ["CACHE MANIFEST", `# ${hash.digest("hex")}`, "", "CACHE:", "/", ...files.map(encodeURI), "", "NETWORK:", "*", ""].join("\n");
|
|
}
|
|
|
|
export function writeManifest(dir) {
|
|
writeFileSync(join(dir, MANIFEST), manifestText(dir));
|
|
}
|