- C 94.1%
- Lua 1.8%
- Python 1.5%
- Assembly 1%
- C++ 0.8%
- Other 0.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| browser | ||
| docs | ||
| homebrew | ||
| Luac0re | ||
| .gitignore | ||
| LICENSE | ||
| README.md | ||
Homebrew Browser
An on-screen, gamepad-driven homebrew launcher for the PS5, baked into the Luac0re savedata. Trigger the exploit (OPTIONS → HALL OF FAME in Star Wars Racer Revenge) and the menu is simply there — pick a title, press Cross, play. No PC, no network, no payload sender at runtime.
No kernel exploit required. Everything runs in userland inside the ps2emu sandbox.
Bundled titles:
Controls
| DualSense | Action |
|---|---|
| D-Pad | navigate |
| Cross | launch / select |
| Circle | back to the Homebrew Browser (from any emulator's picker) |
| R1 (hold) | quit the browser to the Luac0re remote Lua loader (TCP 9026) |
Requirements
- A PS5 running Luac0re from the Star Wars Racer Revenge (CUSA03474 /
CUSA03492) savedata — see
Luac0re/README.md - Build host:
gcc,binutils,make,python3 - garlic-savemgr on the console for the one-time save install and updates
Build and install
browser/tools/stage.sh
This builds the browser and every emulator under homebrew/, then assembles
browser/saveimage/ — the exact tree that goes into the savedata image
(--skip-emulators skips the emulator builds while iterating on the menu):
lua/auto.lua the orchestrator Luac0re boots into
browser/menu.bin the on-screen menu payload
homebrew/<Title>/payload.bin one per emulator
homebrew/<Title>/manifest launch metadata (see docs/DEVELOPING.md)
Then, with garlic-savemgr running on the console:
browser/tools/install_save.py <savemgr-ip> <save-index>
It mounts the save, uploads the staged tree, prints the used/free space
against the 42.25 MB image budget, and always unmounts afterwards. Game
assets are your own: GB/GBC/N64 ROMs go in roms/, the PS1 BIOS
(scph7002.bin) in bios/. Do the install with the game closed.
To update later, re-run both commands.
Repository layout
browser/— the launcher itself: Lua orchestrator (lua/auto.lua), the native menu payload (src/), staging/install tooling (tools/), and a JIT capability probe (tools/jitprobe.lua)homebrew/— the bundled emulators, each with adisttarget producing thepayload.bin+manifestpair the browser installsLuac0re/— the delivery substrate (vendored from Gezine/Luac0re)docs/DEVELOPING.md— how to write your own homebrew for this launcher
Writing your own homebrew
See docs/DEVELOPING.md. Short version: a title is a
directory homebrew/<Title>/ in the save containing a freestanding
static-PIE x86_64 payload.bin and a four-line manifest. The browser
loads it into JIT memory and calls it; when it returns, the menu comes back.
Limitations
- LuaPSX discs do not fit in the save — they live in
/temp0(uploaded with LuaPSX's own flow) and do not survive a reboot. - The touch web controller (port 9030) is not available for browser-launched titles; use the DualSense.
- The screen goes black for a moment between menu and game — the menu payload is reloaded each time. Normal.
- The JIT pool is three 256 KB chunks per session, shared by menu and games; a title can reserve at most 768 KB. Payloads that allocate must release, or the Nth launch fails.
Troubleshooting
- Run
browser/tools/jitprobe.luaonce viaLuac0re/payload_sender.pybefore installing on a new firmware — it validates the JIT assumptions and logs to UDP 9027 (nc -u -l -p 9027). It spends the JIT pool, so relaunch the game afterwards. - The browser and every payload log to UDP 9027 (subnet broadcast). When something hangs, the last log line names the stage.
Credits
- Luac0re — Gezine (MIT) — exploit chain and Lua runtime
- LuaGB / LuaPSX / PSN64 — soniciso1 — the bundled emulators
- Emulation cores: fixGB (FIX94), PCSX-ReARMed, mupen64plus / parallel-n64 / cen64 (angrylion)
- PS5 runtime pattern: EmuC0re by egycnq / EgyDevTeam
- remote_lua_loader by shahrilnet — the pattern Luac0re's Lua side derives from
No copyrighted content (BIOS, ROMs) is included in this repository.
This project was made with Kimi K3.