201 lines
5.4 KiB
Markdown
201 lines
5.4 KiB
Markdown
# 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:
|
|
```c
|
|
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 ID `DUSK00001`, configurable via `SAVE_PSP_TITLE_ID`).
|
|
- Uses `sceIo` for 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()` returns
|
|
`SYSTEM_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_DYNAMIC` not 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 `sceUtility` save dialogs)
|
|
|
|
Check `systemGetActiveDialogTypePSP()` to know whether the main loop
|
|
should skip rendering or ticking.
|
|
|
|
---
|
|
|
|
## Build and toolchain
|
|
|
|
Requires the [PSPDEV toolchain](https://github.com/pspdev/pspdev).
|
|
Set `PSPDEV` in your environment before configuring.
|
|
|
|
```sh
|
|
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 `assertIsMainThread` on any code that
|
|
calls VFPU intrinsics.
|
|
- OpenGL legacy mode means no vertex/fragment shaders; rendering uses
|
|
the fixed-function pipeline via `pspgl`.
|
|
- `DUSK_TIME_DYNAMIC` is absent -- physics always runs at exactly the
|
|
fixed step rate.
|