- Shell 82.8%
- Python 17.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
The previous commit fixed the icon step but could only verify the icon logic in isolation — it was written on macOS, which can't run ldd bundling, appimagetool, or a Linux PPSSPPSDL. That gap is now closed. Ran on Ubuntu 24.04 x86_64 (16 cores): build-ppsspp-sdl.sh links PPSSPPSDL clean at 1059/1059, and build-appimage.sh completes with exit 0 — the run that previously died at the missing-icon cp. Output is a 1.4 GB PSP2i-x86_64.AppImage. The ImageMagick 6 `convert` branch is what actually ran there (that box has convert but not magick), so all three icon paths have now been exercised on a platform that has them: magick and ffmpeg on macOS, convert on Linux. Each produces the same correct 256x256 padded icon. Launched headless under xvfb-run, the AppImage self-mounts, boots the bundled game data from inside the mount, survives a 60s run without crashing, isolates its memstick under the test HOME, seeds NPJH50332.ini, and logs zero occurrences of the extracted-ISO warning. No download happened: appimagetool was already cached at /tmp/appimagetool, so the script's wget fallback never fired. Co-Authored-By: Claude <noreply@anthropic.com> |
||
| gamedata/psp2i-en | ||
| packaging | ||
| ppsspp@4309d222c9 | ||
| scripts | ||
| tools | ||
| .gitignore | ||
| .gitmodules | ||
| README.md | ||
psp2i-standalone — Phantasy Star Portable 2 Infinity, natively
Turning Phantasy Star Portable 2 Infinity (PSP, 2011) into a native executable that runs without an ISO or an emulator — and, along the way, building enough understanding of the engine to retool it.
Objectives (in priority order)
The point of this repo is a standalone PSP2i — the game running on its own, with no ISO and no emulator to launch. Everything else is in service of that.
- Android APK that boots straight into PSP2i. The highest-value output: a single installable that opens directly to the game, nothing else in front of it.
- Desktop builds — Windows, Linux, and macOS. Also genuinely valuable. Same native runtime, different shells around it.
- Decompilation — a later aspiration, not a prerequisite. Once the game runs standalone, the goal is to start decompiling it to learn how it works, get some form of source into version control, and from there make changes and recompile. This is a follow-on to a working standalone build, not a blocker for it (see "static recompilation" below for why that ordering is cheap).
Honest framing: this one is for love, not leverage
The other two repos (psz-re, psz-melonmix) exist to unblock psz-godot. This one does not. It contributes nothing to the Phantasy Star Zero remake and should not be prioritised as if it did.
What it is: the best-isolated project of the three. Self-contained C/C++, no dependency on anyone's taste, and an unusually strong automated oracle (see below). It is well suited to running unattended in the background while attention is elsewhere.
Prioritise accordingly. Nothing here is urgent.
Approach: static recompilation, not decompilation
The original plan was "decompile PSP2i, then slowly work back and retool it." There is a much cheaper path.
sal063/PSP-recompilation-project demonstrates static recompilation of PSP titles: rather than recovering human-readable C that a person maintains, it mechanically translates the game's MIPS machine code into C, then links that against a native runtime. Its pipeline is:
- Relocate the PRX/ELF to its target virtual base address
- Map library imports to HLE (high-level emulation) functions
- Generate C from MIPS instructions
- Compile against a native runtime — custom scheduler, HLE kernel, audio/video decoders, and an SDL3 + Vulkan renderer written from scratch
The difference in cost is enormous. Decompilation requires a human to understand every function before it can be rewritten. Static recompilation requires understanding only the boundaries — the syscall/library surface — and gets a running native binary immediately, with fidelity improving as HLE coverage improves.
That inverts the schedule. You get a native, playable, hackable binary early, and decompile selectively afterwards, only where you actually want to change behaviour. Retooling the game — the actual goal — never required a complete decomp.
Note the licensing consequence: that project is GPL-2.0-or-later because it reuses PPSSPP code (sceMpeg runtime, system fonts). Any fork or derivation inherits that. Plan for it rather than discovering it late.
Existing work — do not duplicate
Several repos already exist in this space. Read this table before starting anything.
| Repo / path | What it is | State |
|---|---|---|
kion/psp2i-android (Forgejo, private) |
Umbrella: PSP2i English Android recompile — PPSSPP fork, unpacker, tools, 6.7 GB game data via LFS | The most advanced artefact |
| kion-dgl/psp2i-decomp | Decompilation project scaffold; has a ppsspp/ dir and an "APK with bundled gamedata" commit |
2 commits, early |
| dashgl/psp2i | Browser model/animation viewer (JS) — bones, skinning, weapons | Working, unrelated to the native goal |
~/projects/psp-decompile/from-231/ |
Local working tree: ISOs, extracted/, fpb-extracted/, ppsspp-src/, Ghidra projects |
Where the data actually is |
| Agrathejagged/tenora-works | PSU-family format library — FPB extractor, NBL/AFS/XNR/GIM/UVR parsers, MissionBuilder | Reference implementation; check before writing any parser |
Asset extraction is already done. FPB contents are extracted for all seven
game versions (PSP1 JP/US, PSP2 JP/US, PSP2i JP/JP-demo/EN) — 2,523 to 4,941
files each. extract_fpb.py is a working Python port of the FPB extractor.
XNJ → glTF conversion works end-to-end (NblDump → RebaseFile(0) →
XnjToGlb; the rebase step is mandatory and its omission was a previous
blocker).
This repo's job is the native runtime, not re-extracting assets.
How an agent verifies its own work
The strongest oracle of the three repos, because PPSSPP ships a headless mode built for exactly this.
ppsspp-headless supports --graphics=software, --timeout, --compare,
--screenshot, and --bench. That gives a genuine reference implementation to
diff against:
- Reference capture. Run PPSSPP headless on the original ISO with a fixed input script; capture screenshots at fixed frames. This is ground truth.
- Differential testing. Run the same script against our native build. Compare frames. Divergence localises the bug to a specific frame, and usually to a specific unimplemented syscall.
- Boot progression. Track how far the native build gets before it diverges or crashes — a single monotonic number that measures real progress and cannot be argued with.
- HLE coverage. Count implemented vs. referenced library imports. Also monotonic, also machine-checkable.
- It builds and runs. CI, every commit.
Both (3) and (4) make good README badges and good agent objectives: "raise the boot-progression frame count" is unambiguous work.
Work breakdown
Phase 0 — consolidate
- Inventory
psp2i-android,psp2i-decomp, andfrom-231/and writedocs/inventory.md— what exists, what works, what is dead - Decide the base: fork
PSP-recompilation-project, or build the recompiler fresh using it as reference. Record the decision and why. - Confirm the GPL position given PPSSPP-derived code
- Stand up CI: build + headless smoke test
Phase 1 — reference harness
- Scripted input playback against PPSSPP headless on the original ISO
- Capture reference screenshots at fixed frames; commit hashes, not images
- Frame-comparison harness reusable by the native build
Phase 2 — recompiler
- Load and relocate PSP2i's
EBOOT.BINto its virtual base - Enumerate library imports; emit the HLE surface that must be implemented
- MIPS → C translation for the main executable
- Minimal native runtime: scheduler, memory map, HLE kernel stubs
- First boot attempt; record the boot-progression number
- Iterate HLE coverage, raising boot progression each time
Phase 3 — presentation
- Renderer (SDL3 + Vulkan, per the reference project's approach)
- Audio
- Input / gamepad
- Android target — the existing
psp2i-androidwork is the head start here
Phase 4 — retooling (the actual goal)
- Selectively decompile systems worth changing
- Asset replacement pipeline
- Network protocol reimplementation for multiplayer
Status
Not started as a native-recompilation effort. Substantial prerequisite work (asset extraction, format parsing, Android packaging) already exists in the repos listed above.
Why this lives on Forgejo (and why assets go in-tree)
This repo is hosted on the local Forgejo server, not GitHub, on purpose: so the game assets can be committed directly into the repo. Keeping the ISO, EBOOT, and extracted data in-tree makes the project trivial to clone and build with no side-channel asset fetch — ease of use, on a private server, over legal caution. That convenience is the whole reason for not using GitHub.
A public GitHub mirror can be published later, using .gitignore to strip
the copyrighted game data. Treat the committed .gitignore as the
GitHub-publish filter — the rules for what a public mirror omits — not as the
policy for this Forgejo repo, where committing assets is the intent. (Note: as
written, .gitignore still ignores extracted/, EBOOT.BIN, and ISOs, so
adding assets here will need an explicit git add -f or a loosened ignore
list.)
Legal
This is a private Forgejo repo and may contain committed game data
(ISO / EBOOT / extracted assets) for convenience; it is not published. Any
public mirror must strip that data via .gitignore, and contributors to a
public fork supply their own legally obtained copy. Expect GPL-2.0-or-later if
PPSSPP-derived code is used.