# rust-psp: writing PSP homebrew in Rust instead of C

> rust-psp is a Rust SDK for the PlayStation Portable that reimplements the PSP system libraries from scratch, with no dependency on the original C PSPSDK, plus allocation, panic unwinding and a macro based VFPU assembler. It is a real SDK rather than a binding, and it is still missing std and kernel mode support.

**overdrivenpotato/rust-psp** — Rust on PSP. Panic and allocation support. Access PSP system libraries.

- Repository: https://github.com/overdrivenpotato/rust-psp
- Stars: 827 · Forks: 45
- Language: Rust
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/overdrivenpotato-rust-psp

## A reimplementation of the PSP system libraries

rust-psp is a library for building full PSP modules, including both PRX plugins and regular homebrew apps. The project description is Rust on PSP, with panic and allocation support and access to the PSP system libraries.

What makes it more than a binding is stated plainly: this project is a completely new SDK, with no dependency on the original C/C++ PSPSDK. It aims to be a complete replacement, with more efficient implementations of graphics functions and the addition of missing libraries.

That distinction matters for anyone considering it. A binding would map Rust functions onto an existing C library and inherit that library's build system, its ABI constraints and its bugs. A reimplementation gives the author freedom to design the interfaces as Rust interfaces, and it means the SDK can be built with cargo alone rather than with the PSPToolchain cross compilation setup. The roadmap lists no dependency on PSPSDK or PSPToolchain as a checked item, alongside core support, PSP system library support, alloc support, panic = "unwind" support, the macro based VFPU assembler, full 3D graphics support, reach of full parity with user mode support in PSPSDK, and port definitions to the libc crate.

The remaining unchecked items are the honest part of the story: add support for creating kernel mode modules, add std support, automatically sign EBOOT.PBP files to run on unmodified PSPs, and implement or reverse undiscovered libraries.

The audience is homebrew developers on an unusual target. The topic tags cover eboot, game, game-development, graphics, homebrew, playstation-portable, psp, pspsdk, rust and rust-psp, and the examples directory shows the shape of the work, with clock-speed, cube, embedded-graphics, fontdue-scrolltext, gu-background, gu-debug-print, hello-world, msg-dialog, paint-mode, rainbow, ratatui, rust-std-hello-world, time, vfpu-addition, vfpu-context-switching and wlan.

Two of those example names are worth noting. ratatui means terminal user interface rendering on the PSP, and rust-std-hello-world is there precisely to track the std support work rather than to ship it.

## The module macro is the entry point

The hello world is a Rust program that is not a normal Rust program. There is no main function, because the PSP's module model expects an entry point with a specific name and a specific calling convention, so the crate provides a macro that generates the module metadata and the entry point for you.

```rust
#![no_std]
#![no_main]

psp::module!("sample_module", 1, 1);

fn psp_main() {
    psp::enable_home_button();
    psp::dprintln!("Hello PSP from rust!");
}
```

The two attributes at the top are the standard Rust way of saying that there is no standard library and no default runtime entry point. The module macro takes a module name and a version, and the psp_main function is where the program starts. Inside it you can call into the PSP system libraries, here to enable the HOME button and to print to the debug console.

The Usage section of the README shows the same skeleton with a version of 1, 0, which tells you the third argument is the minor version of the module. The macro is also what distinguishes a PRX plugin from a regular homebrew application, since the README says the library covers both and the module metadata is what the loader reads.

Adding the crate to your own project is described as being like any other dependency, which is the point of the whole design:

```toml
[dependencies]
psp = "x.y.z"
```

The crate is published on crates.io as psp, with API documentation on docs.rs, and the README carries badges for both plus a CI badge pointing at a self-hosted pipeline.

From there you build with cargo psp, and cargo psp --release for a release build. The build produces an EBOOT.PBP file under target/mipsel-sony-psp/debug/, and the path tells you the target triple and the profile in one glance.

## Toolchain setup and the nightly requirement

The dependency requirements are specific, and one of them is unusual for a hobby SDK.

To compile for the PSP you need a Rust nightly version equal to or later than 2026-08-26, plus the rust-src component. The reason for the nightly requirement is inherent in the target: the PSP is a MIPS little endian machine that Rust does not ship stable support for, so the build uses a custom target specification and the nightly toolchain. The README recommends installing Rust through rustup and gives the two commands for people who are new to Rust:

```sh
$ rustup default nightly && rustup component add rust-src
```

You also need cargo-psp installed, which is a separate tool:

```sh
$ cargo install cargo-psp
```

The README notes you can set an override manually per project instead of changing the global default, which is the polite thing to do on a shared machine.

The workspace layout in Cargo.toml shows how the project is arranged. It is a workspace with the psp crate, the examples, and two CI members, ci/std_verification and ci/tests, and the cargo-psp directory is excluded because it is a native target program rather than PSP code. The resolver is set to version 2.

One detail in that file is worth reading closely, because it is the kind of thing that costs an afternoon if you hit it without warning. The unicode-width crate panics on MIPS targets, and the workspace patches it with a fork from a sourcehut repository that disables alignment as a workaround, with the commit link and the issue reference in a comment.

A patch section in a workspace Cargo.toml applies to the whole workspace, so the fork is in effect for every crate in the tree, including the examples and the CI members. It is a pragmatic fix and a slightly unusual dependency, and if you copy the pattern into your own project you are taking on a dependency on a personal fork.

## Getting the build onto the hardware

There are three routes from a built file to a running program, and each solves a different problem.

The simplest assumes a PSP with custom firmware. You copy the EBOOT.PBP file into a new directory under PSP/GAME on the memory stick, and it appears in the XMB menu. The layout the README shows is:

```text
.
└── PSP
    └── GAME
        └── hello-world
            └── EBOOT.PBP
```

If you do not have a PSP, the recommendation is the PPSSPP emulator. The README adds a caveat that matters for anyone writing graphics code: graphics code is very sensitive, so if you are writing graphics code they recommend developing on real hardware, because PPSSPP is more relaxed in some aspects.

That is a real constraint on the workflow. Emulator testing tells you the logic works, but it will not tell you what the frame timing or the geometry pipeline does on the actual MIPS GPU, and a homebrew that runs correctly in PPSSPP can still misbehave on hardware. For anything beyond a simple demo, budget for hardware testing.

The advanced route is for consoles without custom firmware. You sign the PRX manually with PRXEncrypter and then re-package it with pack-pbp.

The third route is the debugging one. If you have the PSPSDK installed and a working copy of PSPLink built manually, you can use psplink and pspsh to run the .prx directly from the target directory. The debugging documentation names the versions to use, psplinkusb v3.1.0 and GNU gdb 11.0.50.20210718-git or later, and states that Rust types are fully supported for a rich debugging experience.

For that to work you need debug symbols in your release binaries, which is a one line addition to Cargo.toml:

```toml
[profile.release]
debug = true
```

And then the instructions in part 6 of the PSPlink manual. The point of the whole setup is that a Rust type printed by gdb looks like a Rust type rather than a struct of integers.

## Branding the EBOOT and a common build error

A homebrew file on a memory stick is not just an executable. It has a name and an icon in the XMB menu, and the README shows how to set those without touching code.

You create a Psp.toml file in the root of your project, and all keys are optional. The available ones are the XMB title, the icon as a 24bit 144x80 png, the background as a 24bit 480x272 png, and the music as an ATRAC3 at3 file:

```toml
title = "XMB title"
xmb_icon_png = "path/to/24bit_144x80_image.png"
xmb_background_png = "path/to/24bit_480x272_background.png"
xmb_music_at3 = "path/to/ATRAC3_audio.at3"
```

The image dimensions are specific, 144x80 for the icon and 480x272 for the background, which are the XMB element sizes. A file of the wrong size will not render as intended, and the README notes that more options are in the schema definition.

The README also documents a common build failure, which is the kind of thing worth knowing before you lose an hour to it. If you see an error like this:

```text
error[E0460]: found possibly newer version of crate `panic_unwind` which `psp` depends on
```

the fix is to clean your target directory:

```sh
$ cargo clean
```

The cause is a stale artifact in the target directory conflicting with the version the psp crate expects, which is a common consequence of switching between toolchains or branches. The error message points at a use of psp::dprintln in your own source, which is misleading, and that is probably why it is in the README.

## What rust-psp cannot do yet

The roadmap is the honest boundary of the project, and it is worth reading line by line before you commit to it.

There is no std support. That is the largest gap, and it is the one that shapes what a program can be. Without the standard library there is no Vec, no String, no HashMap, no file IO, no threads, and the ecosystem crates that assume std are not usable as they are. The examples directory contains rust-std-hello-world, which is the honest way to signal that std is work in progress rather than a shipped feature.

There is no kernel mode module support either. Kernel mode modules are the other half of the PSP module model, and they are a different privilege level with different APIs. The project has reached parity with user mode support in PSPSDK and lists kernel mode as still to do.

Automatic EBOOT.PBP signing is not implemented. This is why the PRXEncrypter and pack-pbp route exists in the documentation. Without signing, the output runs on a console with custom firmware, which is a genuine hardware and legal constraint for anyone distributing homebrew.

And the last item, implement or reverse undiscovered libraries, is a statement that the PSP's undocumented system libraries are not all known yet. Some of the SDK is therefore necessarily incomplete, and there is no way for a user to tell which parts.

The alternatives differ in what they assume. The original PSPSDK is the C and C++ path, and it is what rust-psp is being compared against for parity. Porting a PSPSDK C project to Rust means rewriting the code, not just recompiling, though the libc port definitions mean the familiar C library surface is available. A different language SDK for the same target would face the same two problems rust-psp does, the absence of std and the closed system libraries, and the practical difference is the toolchain rather than the capability. Writing directly against the C SDK and keeping a Rust layer for game logic is a different architecture with a different trade-off, and it keeps the C ABI out of the way at the cost of giving up Rust's ownership model at the boundary.

For anything above homebrew, which means commercial software on licensed hardware, none of this applies and a licensed development environment is the only route.

## Licence, maintenance and what the project is worth

The licence is recorded as a custom one that GitHub cannot classify, with a LICENSE file in the repository. That is a different situation from a well known OSI licence, and for a project you might want to build on, the terms are worth reading directly rather than assuming they are permissive or copyleft.

The maintenance picture is more encouraging. The repository is not archived, and the last push was on 2026-09-27, with a CI badge pointing at a self-hosted pipeline that runs the test suite for the master branch. The recent work is visible in the repository layout as well, with a libunwind directory for the panic unwinding support, a prx.md document, a bindgen.sh script, a cargo-psp directory for the build tool, and a ci directory with a std_verification member and a tests member.

The existence of ci/std_verification is the interesting signal. It means there is an automated check on whether std support has improved, which is how you keep an open roadmap item honest, and it also means the test suite runs on a native target as well as the PSP one.

There are no GitHub releases, so the version reference for the psp crate is the crates.io one, and the README's own dependency example uses a placeholder version. The crate is published on crates.io and documented on docs.rs, and the README links the CI pipeline, the crate page and the docs page in the badge row, so you can check the current state of the build before you install anything.

The real evaluation question is narrower than the feature list suggests. If you want to write a PSP homebrew and you know Rust, this is one of the few ways to do it that does not require a C toolchain, and the support for panic unwinding and the VFPU assembler are the two features you are least likely to find elsewhere. If you need std, or kernel mode, or a signed EBOOT for stock hardware, you are reading a roadmap rather than a manual, and that is the moment to decide.

## Conclusion

Adopt rust-psp if you are writing PSP homebrew and want Rust's type system, cargo and modern tooling on a target that has no other good Rust option. Do not adopt it if you need standard library support, kernel mode modules, or a signed EBOOT that runs on an unmodified console, since all three are still open items on the roadmap. Verify first that you have a nightly Rust at or after 2026-08-26 with the rust-src component, that cargo-psp is installed, and that the example set in the repository builds before you start anything larger.

## FAQ

### What does rust-psp provide for PlayStation Portable development?

It is a Rust SDK for building full PSP modules, both PRX plugins and regular homebrew apps, with a reimplementation of the PSP system libraries that has no dependency on the original C/C++ PSPSDK, plus allocation support, panic = "unwind" support and a macro based VFPU assembler.

### What toolchain do I need to build a PSP program with rust-psp?

A Rust nightly version equal to or later than 2026-08-26 with the rust-src component, installed through rustup, and cargo-psp installed with `cargo install cargo-psp`. The README notes you can set a nightly override per project rather than changing the global default.

### Does rust-psp support the Rust standard library?

Not yet. Add std support is an unchecked item on the project roadmap, and the examples directory contains a rust-std-hello-world example that tracks the work rather than shipping it.

### How do I run a built rust-psp program on a PSP or emulator?

Run cargo psp in an example directory such as examples/hello-world, which creates an EBOOT.PBP under target/mipsel-sony-psp/debug/. With custom firmware you copy it into a new directory under PSP/GAME on the memory stick, and without a PSP the project recommends the PPSSPP emulator, while noting that graphics code is very sensitive and is better developed on real hardware.

### How do I set an icon and title for a rust-psp homebrew?

Create a Psp.toml file in the root of your project with optional keys for title, xmb_icon_png as a 24bit 144x80 image, xmb_background_png as a 24bit 480x272 image, and xmb_music_at3 as ATRAC3 audio.

### What license is rust-psp released under?

A custom license that GitHub cannot classify, with the terms in the LICENSE file at the repository root. The repository is not archived and the last push was on 2026-09-27, with a CI badge for the master branch test pipeline.

## Sources

- [Issues](https://github.com/overdrivenpotato/rust-psp/issues)
- [overdrivenpotato/rust-psp on GitHub](https://github.com/overdrivenpotato/rust-psp)
- [README](https://github.com/overdrivenpotato/rust-psp/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/overdrivenpotato-rust-psp
