Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
14 changes: 14 additions & 0 deletions advanced_techniques.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: Advanced Techniques
layout: home
nav_order: 7
---

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

When developing for the Playstation Portable (PSP), you may want to dynamically load code at runtime. This page will cover how to do that.
Comment thread
xeonliu marked this conversation as resolved.
Outdated

- [Creating PRX Modules](techniques/prx_modules.html)
<!-- - [Syscall Restrictions](#syscall-restrictions) -->
<!-- - [Kernel Module and User Module](#module-types) -->
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
123 changes: 123 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,123 @@
---
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 (Native ID?) of the function and a stub implementation of the function.
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.

NID stands for name identifier it seems: https://psp-re.github.io/blog/nid-cracking/

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.

"which I believe stands for Name Identifier"

Maybe I should just explain what it is rather than its real name


## 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.

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 for memory management, string manipulation, etc.

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

### 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. (TODO: Reference needed)
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 you can remove the TODO here. This makes sense to me without additional context, as the user cannot know what modifies the exported global variable or what effect modifying it will have on the program.

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.

I believe this restriction is documented in a document which I read before. I couldn't remember where.


Here is an example export table (you can view it in the [SDK source code](https://github.com/pspdev/pspsdk/blob/master/src/samples/prx/testprx/exports.exp)):

```
# Define the exports for the prx
PSP_BEGIN_EXPORTS

# These four lines are mandatory (although you can add other functions like module_stop)
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 would be good to explicitly explain how to export a function below this code example as well.

# syslib is a psynonym for the single mandatory export.
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 is less confusing without this second line.

PSP_EXPORT_START(syslib, 0, 0x8000)
PSP_EXPORT_FUNC_HASH(module_start)
PSP_EXPORT_VAR_HASH(module_info)
PSP_EXPORT_END

# Export our function
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(getModuleInfo)
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 (instead of a static elf)
BUILD_PRX=1
# Define the name of our custom exports (minus the .exp extension)
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
```

### 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 my_lib.exp
```

This generates a stub file in `.S` assembly format. 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.