Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions advanced_techniques.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: Advanced Techniques
layout: home
nav_order: 7
---

# Advanced Techniques
{: .fs-8 .fw-700 .text-center }

Here are links to more in depth explanations of specific more advanced PSP programming topics.

- [Creating PRX Modules](techniques/prx_modules.html)
2 changes: 1 addition & 1 deletion contributing.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Contributing
layout: home
nav_order: 8
nav_order: 9
---

# Contributing
Expand Down
2 changes: 1 addition & 1 deletion downloads.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Downloads
layout: home
nav_order: 7
nav_order: 8
---

# Downloads
Expand Down
193 changes: 193 additions & 0 deletions techniques/prx_modules.md
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to cover the coding limitations for prx modules as well? From what I understand using libraries in a module is difficult.

Copy link
Copy Markdown
Author

@xeonliu xeonliu May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be many restrictions. I haven't figured out the exact restrictions yet, only some suggestions.

It would be better if others in the channel can help verify them

But as for my observation, most problem comes from using standard C lib or libstdc++

Use only PSPSDK functions and writing the code in C without crt0 can avoid most problems.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I would still merge this if this is not yet included here now. It can be added later. Maybe having one sentence about the limitation would be good for now. I'll leave it up to you.

Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
---
title: Creating PRX Modules
layout: home
nav_exclude: true
---
# Creating PRX Modules
{: .fs-8 .fw-700 .text-center }

## Basic Concepts
{: .fs-6 .fw-700 }

Multiple modules can be loaded at the same time on the PSP. The main module is the one which is launched when starting a homebrew, but additional modules can be loaded and unloaded at runtime. These additional modules are called PRX modules and have the `.prx` file extension. They are similar to DLLs on Windows or shared objects on Linux.

### Stub Library
{: .fs-4 .fw-700 }

To load a PRX module, the main module needs to know which functions it can call within that module. This is done by creating a stub library, a static library containing the signatures of the functions in the PRX module. The main module links against this stub library and calls the functions in the PRX module just like regular functions.

The stub library only contains the Module Name, the NID (hash of the function name) of the function and a stub implementation of the function.

## Basic Workflow
{: .fs-6 .fw-700 }

> PRX modules can act as a Resident Library, which exposes their own functions inside and export them for other modules to use.

The core steps for creating a PRX module that others can load are as follows:
1. PRX module developers declare which functions are accessible from external modules by writing an **Export Table**.
2. Users can establish a reference to these external functions in their modules by using an **Import Table**, which is generated from the PRX module's export table and can be compiled into a **Stub Library**.

## Writing Code and Export Table
{: .fs-6 .fw-700 }

### Writing Code
{: .fs-4 .fw-700 }

Writing code for a PRX module is largely identical to writing code for a regular module. The primary difference is the entry point.

Instead of writing a standard `main` function, you write a `module_start` function (called when the module is loaded) and a `module_stop` function (called when unloaded). These functions should return 0 on success and a negative value on failure.

> Make sure to use at least one function from other modules (for example, `sceIoOpen`), otherwise `psp-fixup-imports` will complain `Error, no .lib.stub section found`.

Also it is not recommended to use any Standard C Library functions in your code. The `newlib` implementation in the PSPSDK often causes issues when used in PRX modules, and it is generally better to avoid it altogether. Instead, you can use the PSPSDK's own functions with `sce` prefix for memory management, string manipulation, etc.

Due to similar reasons, C++ is also not recommended for PRX modules.

```c
#include <pspuser.h>

// Module Name, Attributes, Major Version, Minor Version
// This module is a user module
PSP_MODULE_INFO("SamplePlugin", PSP_MODULE_USER, 1, 0);
PSP_NO_CREATE_MAIN_THREAD();

int module_start() {
SceUID fd = sceIoOpen("log.txt", PSP_O_WRONLY | PSP_O_CREAT | PSP_O_APPEND, 0777);
if (fd >= 0) {
sceIoWrite(fd, "Hello World!", 12);
sceIoClose(fd);
}
return 0;
}

int module_stop() {
SceUID fd = sceIoOpen("log.txt", PSP_O_WRONLY | PSP_O_CREAT | PSP_O_APPEND, 0777);
if (fd >= 0) {
sceIoWrite(fd, "Goodbye World!", 14);
sceIoClose(fd);
}
return 0;
}

// This function will be exported and can be called from other modules
int sum(int a, int b) {
return a + b;
}
```

### Write the Export Table
{: .fs-4 .fw-700 }

Create a file with an `.exp` extension. It is used to declare which functions are accessible from external modules. The format is as follows:

> Guidelines
> 1. `syslib` is an essential keyword that must be included in the export table.
> 2. It is generally not recommended to export global variables.

Here is an example export table:

```
# Define the exports for the prx
PSP_BEGIN_EXPORTS

# These lines are mandatory
PSP_EXPORT_START(syslib, 0, 0x8000)
PSP_EXPORT_FUNC(module_start)
PSP_EXPORT_FUNC(module_stop)
PSP_EXPORT_VAR(module_info)
PSP_EXPORT_END

# Export our function
# 'MyLib' is the name of the library, it doesn't have to match the module name
PSP_EXPORT_START(MyLib, 0, 0x0001)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would be good to specify where MyLib comes from.

PSP_EXPORT_FUNC_HASH(sum)
PSP_EXPORT_END

PSP_END_EXPORTS
```

Comment thread
sharkwouter marked this conversation as resolved.
### Compile the PRX Module
{: .fs-4 .fw-700 }

If you are using Makefiles, you can add the following lines to your Makefile to compile the PRX module:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to also add instructions for CMake? We have an example here: https://psp-re.github.io/blog/nid-cracking/

Since we mostly use CMake in our examples on the website.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure yes. CMake can do that.

I choose Makefile because most existing projects still use them.

I think I will provide 2 versions if possible.


```makefile
# Define to build this as a prx
BUILD_PRX=1
# Define the name of our custom exports
PRX_EXPORTS=exports.exp
```

When `PRX_EXPORTS` is defined, the build system calls `psp-build-exports -b` and automatically generates the code to compile into the PRX module.

> The `.rodata.sceResident` segment contains the exported NIDs and function addresses.
>
> The `.lib.ent` segment contains the module name and export table metadata, including a pointer to the export table in the `.rodata.sceResident` segment.
>
> You can inspect the generated code by running `psp-build-exports -b exports.exp` in your terminal.

Also, when building a PRX module, you should add the `-nostartfiles` flag to your `LDFLAGS` to prevent the linker from including the startup files, which are not needed and can cause issues in PRX modules.

```makefile
LDFLAGS = -nostartfiles
```

The whole Makefile looks like this:

```makefile
TARGET = SamplePlugin

OBJS = main.o

CFLAGS = -O2 -Wall
LDFLAGS = -nostartfiles

BUILD_PRX = 1
PRX_EXPORTS = exports.exp

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
```

### Generate the Stub Library
{: .fs-4 .fw-700 }

To generate the stub library, first run the following command in the terminal:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be good to specify in this section how this relates to the Makefile/CMake and building more.


```sh
psp-build-exports -k exports.exp
```

This generates a stub file in `.S` assembly format. It's name is `MyLib.S` as the library name in the export table is `MyLib`.

```c
.set noreorder

#include "pspimport.s"

// Build files
// MyLib_0000.o MyLib_0001.o

#ifdef F_MyLib_0000
IMPORT_START "MyLib",0x00090000
#endif
#ifdef F_MyLib_0001
IMPORT_FUNC "MyLib",0x55F3DFE9,sum
#endif
```

This file can be compiled into a static library using `psp-gcc` followed by `psp-ar`, or distributed directly. When others want to use your PRX module, they can simply include this `.S` file as a source file.

## Dynamically Loading PRX Modules
{: .fs-6 .fw-700 }

To dynamically load a PRX module, you can use the `sceKernelLoadModule` and `sceKernelStartModule` functions.

When building your programs, include the generated `.S` stub file (or the `.a` stub library) in your `OBJS` or `LIBS` for linking.

The generated `.S` file uses several macros along with the post-processing tool `psp-fixup-imports` to construct the import table.

## Further Reading
{: .fs-6 .fw-700 }

- [PSP Modules, Exports, Imports and Patches](https://uofw.github.io/upspd/docs/software/ModuleTutorialv1.pdf): A short tutorial released in 2007 describing modules used in Sony’s PSP by Anissian.