mirror of
https://github.com/phantomptr/ps5upload.git
synced 2026-10-21 19:33:08 -05:00
- A single-file upload that fills the drive keeps <file>.ava-part so Retry resumes it, but nothing said so: the failed row now names it and offers Delete partial file (the next attempt starts fresh). - Stopping a stream install before the engine had its job dropped the row and left the install running unseen; Stop now waits for the job and stops it. - 0x80B21104 explains that the console will not take this package and links its FAQ entry, instead of the generic PlayGo text. - The Connection screen's "port not open" step suggests turning a VPN off (reported twice on Discord). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ub1mez9eaVtTF8pMEFXvA9
68 lines
2.8 KiB
TypeScript
68 lines
2.8 KiB
TypeScript
// Maps an install error (raw message and/or Sony code) to the FAQ section that
|
|
// explains it, so an error toast can link straight to the support matrix.
|
|
//
|
|
// The FAQ screen filters its sections by a search string (`/faq?q=…`), so an
|
|
// "anchor" here is a string the target section is guaranteed to contain: the
|
|
// error code itself, or the exact phrase the explainer is titled with. The FAQ
|
|
// sections that carry these strings are "Install routes: what works for what"
|
|
// and "My uploaded game won't launch" in FAQ.md; installErrorDoc.test.ts reads
|
|
// FAQ.md and fails if an anchor stops resolving.
|
|
|
|
export interface InstallErrorDoc {
|
|
/** The FAQ search string that lands on the explanation. */
|
|
query: string;
|
|
}
|
|
|
|
/** Anchor strings. Each must appear (case-insensitively) in FAQ.md. */
|
|
export const DOC_ANCHORS = {
|
|
stagedRefused: "0x80b2116f",
|
|
streamUnreachable: "PS5UPLOAD_PKG_HOST_IP",
|
|
proxy: "0x80431084",
|
|
entitlement: "missing base entitlement",
|
|
viewProduct: "View product",
|
|
ps4OnPs5: "isn't playable on PS5",
|
|
e2: "E2-80B22410",
|
|
ce: "CE-108255-1",
|
|
wontLaunch: "won't launch",
|
|
matrix: "support matrix",
|
|
declined1104: "0x80B21104",
|
|
} as const;
|
|
|
|
const RULES: Array<[RegExp, string]> = [
|
|
[/0x80b21104/i, DOC_ANCHORS.declined1104],
|
|
[/0x80b2116f|0x80b2150f|staged route|refused this package from its own storage/i, DOC_ANCHORS.stagedRefused],
|
|
[/0x80431084|proxy server|proxy setting/i, DOC_ANCHORS.proxy],
|
|
[
|
|
/0x80431064|0x80431068|0x8041013d|never reached (this computer|the engine)|cannot connect to this computer|could not reach/i,
|
|
DOC_ANCHORS.streamUnreachable,
|
|
],
|
|
[/e2-?80b22410/i, DOC_ANCHORS.e2],
|
|
[/ce-?108255-?1/i, DOC_ANCHORS.ce],
|
|
[/base entitlement|missing base/i, DOC_ANCHORS.entitlement],
|
|
[/view product/i, DOC_ANCHORS.viewProduct],
|
|
[/ps4 game.*(not|n't) playable on ps5|isn't playable on ps5/i, DOC_ANCHORS.ps4OnPs5],
|
|
];
|
|
|
|
/** The explanation for an install error, or null when there is none to link.
|
|
* `code` is Sony's numeric code when the caller has it. */
|
|
export function installErrorDoc(raw: string | null | undefined, code?: number): InstallErrorDoc | null {
|
|
const hex = code && code > 0 ? ` 0x${(code >>> 0).toString(16).padStart(8, "0")}` : "";
|
|
const text = `${raw ?? ""}${hex}`;
|
|
if (!text.trim()) return null;
|
|
for (const [re, query] of RULES) {
|
|
if (re.test(text)) return { query };
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/** The in-app route for a FAQ search. */
|
|
export function faqLink(query: string): string {
|
|
return `/faq?q=${encodeURIComponent(query)}`;
|
|
}
|
|
|
|
/** The route an install-error toast links to: its explanation when it has
|
|
* one, else the install-routes matrix (the page users should read first). */
|
|
export function installErrorLink(raw: string | null | undefined, code?: number): string {
|
|
return faqLink(installErrorDoc(raw, code)?.query ?? DOC_ANCHORS.matrix);
|
|
}
|