5.4 KiB
Platform -- Sony PSP
DUSK_TARGET_SYSTEM: psp
Source layer: src/duskpsp/
Renderer: OpenGL ES (legacy, via PSPGL/SDL2)
Overview
The PSP is a 32 MB MIPS-based handheld console running at up to 333 MHz.
It uses SDL2 (ported to PSP) for windowing and OpenGL in legacy/fixed-
function mode. The game binary and all assets are packaged together inside
a .pbp file -- the PSP's native executable format.
Hardware
| Attribute | Value |
|---|---|
| CPU | MIPS R4000 (Allegrex), up to 333 MHz |
| RAM | 32 MB (4 MB reserved for OS) |
| Display | 480x272, 16/32-bit colour |
| Storage | Memory Stick (UMD for retail; MS for homebrew) |
| Endian | Little-endian |
Compile-time macros
| Macro | Set |
|---|---|
DUSK_PSP |
yes |
DUSK_SDL2 |
yes |
DUSK_OPENGL |
yes |
DUSK_OPENGL_LEGACY |
yes |
DUSK_INPUT_GAMEPAD |
yes |
DUSK_PLATFORM_ENDIAN_LITTLE |
yes |
DUSK_DISPLAY_WIDTH |
480 |
DUSK_DISPLAY_HEIGHT |
272 |
DUSK_THREAD_PTHREAD |
yes |
No DUSK_DISPLAY_SIZE_DYNAMIC -- the resolution is fixed.
No DUSK_INPUT_KEYBOARD, no DUSK_INPUT_POINTER.
Display
- Fixed 480x272 resolution.
- OpenGL legacy (fixed-function pipeline,
DUSK_OPENGL_LEGACY). - Texture dimensions must be powers of two (use
mathNextPowTwo). - VFPU (4-wide float SIMD) is available -- use it for matrix/vector hot
paths under
#ifdef DUSK_PSP.
Asset loading
Assets are packed into the PSAR section of the .pbp file by the
post-build create_pbp_file() CMake command. At runtime,
assetInitPBP() locates and opens the PSAR from the running executable's
path.
The PBP format header:
typedef struct {
char_t signature[4]; // "\0PBP"
uint32_t version;
uint32_t sfoOffset;
uint32_t icon0Offset;
uint32_t icon1Offset;
uint32_t pic0Offset;
uint32_t pic1Offset;
uint32_t snd0Offset;
uint32_t pspOffset;
uint32_t psarOffset; // dusk.dsk starts here
} assetpbpheader_t;
assetpbp_t holds the open file handle and parsed header. Asset paths
inside the PSAR are ZIP paths within dusk.dsk.
Input
Layered on SDL2. inputInitPSP() maps PSP physical buttons to SDL2
SDL_CONTROLLER_BUTTON_* constants:
| PSP button | Action |
|---|---|
| Cross | Accept |
| Circle | Cancel |
| Triangle | - |
| Square | - |
| L / R | Shoulder buttons |
| D-pad | Directional |
| L-Stick | Analog axes |
No keyboard or pointer input available. Attempting to use
INPUT_BUTTON_TYPE_KEYBOARD on PSP is undefined behaviour.
The PSP system setting PSP_UTILITY_ACCEPT_CROSS / ACCEPT_CIRCLE
swaps the Cross and Circle button roles in OS dialogs -- read this via
systemPSPGetCrossButtonSetting() if you need to match the system
convention.
Save system
- Path:
ms0:/PSP/SAVEDATA/<TITLE_ID><slot>/save.dat(default title IDDUSK00001, configurable viaSAVE_PSP_TITLE_ID). - Uses
sceIofor file I/O -- no extra dialog required for raw reads. - PSP OS-level save/load dialogs (via
sceUtility) are separate and block the main loop when open (systemGetActiveDialogType()returnsSYSTEM_DIALOG_TYPE_TICK_BLOCKING). - Do not call save functions directly from game code during a dialog.
Network
Connection requires an explicit user Wi-Fi selection step via the PSP
system network dialog (sceUtilityNetconfInitStart).
networkRequestConnection(onConnected, onFailed, onDisconnect, user);
// -> shows PSP Wi-Fi selection dialog (blocking dialog type)
// -> calls onConnected or onFailed when the dialog closes
HTTP and SSL modules (psphttp, pspssl, pspnet_resolver) are
linked in psp.cmake but the HTTP implementation code is commented out.
The infrastructure exists for future use.
Time
- Tick source:
SDL_GetTicks64(). - Real time:
sceRtcGetCurrentTick()(returns microseconds). - Dynamic timestep is not enabled (
DUSK_TIME_DYNAMICnot set). Every tick is a fixed 16 ms step.
System dialogs
PSP shows OS-level dialogs for:
- Wi-Fi configuration (
networkRequestConnection) - Save management (if using
sceUtilitysave dialogs)
Check systemGetActiveDialogTypePSP() to know whether the main loop
should skip rendering or ticking.
Build and toolchain
Requires the PSPDEV toolchain.
Set PSPDEV in your environment before configuring.
cmake -B build \
-DDUSK_TARGET_SYSTEM=psp \
-DCMAKE_TOOLCHAIN_FILE=${PSPDEV}/lib/cmake/psp.cmake \
-DCMAKE_BUILD_TYPE=Release
cmake --build build
Post-build output: Dusk.pbp (executable + assets combined).
Dependencies: SDL2-PSP, OpenGL-PSP, pspgu, pspctrl, pspdisplay, pspaudio, pspaudiolib, psputility, pspvfpu, pspvram, pspnet, pspnet_inet, pspnet_apctl, psphttp, pspssl, pspdebug, psphprm, mbedtls, mbedcrypto, lzma, zip, bz2, z.
Endianness
Little-endian. DUSK_PLATFORM_ENDIAN_LITTLE is set at compile time.
No runtime endian check is needed.
Gotchas
- The PSP has only 28 MB of usable RAM after the OS. Keep asset budgets
tight -- see
.claude/optimization.md. - VFPU instructions are not valid on threads other than the main thread
on some firmware versions. Use
assertIsMainThreadon any code that calls VFPU intrinsics. - OpenGL legacy mode means no vertex/fragment shaders; rendering uses
the fixed-function pipeline via
pspgl. DUSK_TIME_DYNAMICis absent -- physics always runs at exactly the fixed step rate.