An All-in-One "Swiss Army Knife" & Micro-Engine for Homebrew Developers • Streamlined CLI • Asset Cooker • Designed for 60 FPS Workloads
Get Started • Documentation • Tutorials • Demos • Architecture • Thanks
- Overview
- ✨ 100% Vibe-Coded Origins
- Up and Running (Quickstart)
- Architecture & Key Features
- Repository Structure
- Requirements
- Installation & Setup
- Showcase Demos
- Tutorials & Guides
- Real Hardware Deployment
- Open to Contributions
- Thanks & Acknowledgments
- SEO, Discovery & LLM Metadata
- License
Important
Built on top of PSPSDK, not a replacement!
PSP-Forge does not aim to replace the official PSPSDK / PSPDEV toolchain—we build directly on top of it!
Rather, PSP-Forge serves as an all-in-one "Swiss Army knife" (coltellino svizzero) for game developers: creators working on other engines (such as Raylib, Godot, LÖVE2D, SDL) or beginners who want pre-built templates, automated asset processing, and a high-level micro-engine without having to reinvent low-level hardware wheels (display lists, texture swizzling, memory layouts, and audio threads).
PSP-Forge bridges the gap between modern game development developer experiences (DX) and classic bare-metal embedded consoles. Built specifically for the Sony PlayStation Portable (PSP-1000/2000/3000/Go/Street), PSP-Forge unifies:
- An intuitive CLI tool (
init,cook,build,run,clean) that abstracts away arcane toolchain incantations, sets up IDE include paths, and packages EBOOTs. - A deterministic Asset Pipeline ("The Cooker") that automatically optimizes textures (GPU swizzling, power-of-two padding, CLUT palettization), 3D Wavefront OBJ models, and 44.1 kHz PCM audio, complete with hardware budget warning checks.
- A clean C99 Micro-Engine (
libpspforge.a) built on PSPSDK, providing zero per-frame runtime allocations, pre-baked 2D sprite rendering, 3D perspective pipelines with hierarchical transforms, collision detection, sprite flipbook animations, multi-scene management, and dedicated asynchronous audio playback out of the box.
Note
PSP-Forge is completely and unapologetically vibe-coded.
The entire architecture—the Python CLI, the automated asset swizzlers and compilers, the C99 micro-engine, the collision solvers, the multi-scene state machines, the documentation, and the showcase demos—was authored and iterated through collaborative AI pair-programming (human intent + advanced LLM agentic engineering).
This project stands as proof that vibe coding is not limited to high-level JavaScript web toys: when guided by solid architectural principles, it can conquer 20-year-old bare-metal embedded MIPS architectures, reverse-engineered hardware registers, display list geometry, cache line flushes, and strict
Get a complete PSP game project initialized, cooked, built, and running in less than 60 seconds:
# 1. Initialize a new 2D or 3D project skeleton
psp-forge init my_game --template 2d
cd my_game
# 2. Cook assets (PNG, OBJ, WAV -> hardware formats with budget checks)
psp-forge cook
# 3. Build native MIPS EBOOT.PBP via CMake & psp-gcc
psp-forge build
# 4. Run immediately in the PPSSPP emulator
psp-forge runpsp-forge init <name> [--template 2d|3d]: Scaffolds a complete project with CMakeLists.txt,psp.tomlmanifest, assets, and VS Code C/C++ include paths.psp-forge cook: Incremental build system for game assets with timestamp caching.psp-forge build [--clean] [--release|--debug]: Automates asset cooking, wrapspsp-cmakeandcmake --buildto compile MIPS binaries and generate relocatableEBOOT.PBP(PRX mode).psp-forge run: Auto-detects local PPSSPP installations (Flatpak, native binary, AppImage) and boots the game in one click.psp-forge clean: Cleans the build directory and compiled assets.
The PSP hardware imposes strict memory and rasterizer constraints. The Asset Cooker automatically converts assets and guides developers around hardware bottlenecks:
-
Texture Swizzling: Interleaves pixel data into
$16 \times 8$ byte tiles to eliminate GPU cache misses during texture sampling. -
Power-of-Two (POT) Padding & Auto-Resizing: Expands textures to
$2^n$ dimensions up to$512 \times 512$ . Source textures exceeding$512 \times 512$ are automatically downsampled to$512 \times 512$ via Lanczos filtering with a warning. -
Format Conversion & CLUT Quantization: Supports
RGBA8888,RGBA5551,RGBA4444, and indexed CLUT8 (256 colors) / CLUT4 (16 colors via Octree quantization). -
Material Atlas Fusion & Heuristic Chroma Keying: Fuses multi-material glTF models into a single
$512 \times 512$ texture atlas with UV remapping, with heuristic matte background keying for facial and accessory layers. -
Dual Export (.p3d & .p3dx): Exports engine-optimized
.p3dmodels or format-agnostic.p3dxcontainers preserving original material topologies. -
glTF / GLB to Skeletal Mesh & Animations: Decomposes rigs into sub-mesh chunks referencing
$\le 8$ local bones for hardware vertex skinning, generating.p3dgeometry and 30 FPS.panmanimation tracks. -
Audio Transcoder & Streamer: Resamples audio to signed 16-bit PCM at 44.1 kHz, with streaming support (
forge_music_*) from Memory Stick to save RAM. -
Hardware Budget Warnings & Policies:
⚠️ Warns if 3D models exceed 3,000 triangles or 256 KB.⚠️ Warns if input textures exceed$512 \times 512$ (auto-downsampling applied).⚠️ Warns if texture VRAM footprint exceeds the recommended 512 KB budget (physical eDRAM scratchpad is 688 KB; 512 KB leaves safety headroom in the bump allocator).⚠️ Warns if uncompressed audio clips exceed 2 MB RAM.
-
Zero Per-Frame Dynamic Allocation (In-Game Loop): The 60 FPS gameplay simulation has zero allocations. Dynamic memory (
malloc,calloc,memalign) is strictly restricted to asset loading/unloading during scene transitions. The 2 MB on-chip eDRAM is deterministically partitioned: Draw buffer ($544\text{ KiB}$ ), Display buffer ($544\text{ KiB}$ ), 16-bit Depth buffer ($272\text{ KiB}$ ), and a fast bump-allocated Texture scratchpad ($688\text{ KiB}$ ). -
Display List & Memory Management: Safe 16-byte aligned GU Display Lists with D-Cache writeback (
sceKernelDcacheWritebackRange) for uploaded textures, vertices, and audio DMA buffers. -
2D & 3D Pipelines: Fast 2D sprite batching (
GU_SPRITES), perspective projection, camera view matrix, articulated hierarchical node transforms (forge_draw_mesh_node), hardware alpha test control (forge_set_alpha_test), and distance-based virtual light culling. -
3D Skeletal Animation: Native hardware vertex skinning (
GU_WEIGHTS,sceGuBoneMatrix), sub-mesh chunking ($\le 8$ local bones per chunk), and.panmanimation playback with shortest-arc quaternion SLERP. Architectural capacity supports rigs up to 96 bones, with 24–32 bones recommended per rig for guaranteed 60 FPS on the 333 MHz Allegrex CPU. -
Collision Engine: Lightweight, allocation-free 2D primitives (
ForgeRect,ForgeCircle) and 3D bounding volumes (ForgeAABB,ForgeSphere) with analytical intersection tests. -
2D Flipbook Animation: Grid-based spritesheet player (
ForgeSpriteAnim) with frame timing, UV coordinate computation, and playback loops. -
Scene Manager (
ForgeScene): Lifecycle state machine (on_init,on_update,on_draw,on_destroy) enabling clean memory recycling between Title Menus and Gameplay levels in$24\text{ MB}$ RAM. -
Multithreaded Audio: Dedicated high-priority audio thread (
0x12) feeding 512-sample stereo PCM chunks from RAM buffers or streaming streams directly from disk via DMA.
psp-forge/
├── bin/
│ └── psp-forge # Portable CLI executable wrapper
├── cli/
│ ├── psp_forge.py # Core CLI orchestrator
│ ├── config.py # psp.toml manifest parser
│ ├── cookers/ # Hardware-aware asset compilers
│ │ ├── texture.py # Swizzling, POT padding, CLUT quantization
│ │ ├── mesh.py # OBJ to binary .p3d parser + AABB bounds
│ │ ├── gltf.py # glTF/GLB parser, .panm clips, sub-mesh chunker
│ │ └── audio.py # WAV to PCM 44.1kHz transcoder
│ └── templates/ # Project starter templates (2D & 3D)
├── runtime/ # libpspforge (C99 Micro-Engine source)
│ ├── include/
│ │ └── psp_forge.h # Unified public header
│ ├── src/
│ │ ├── core.c # GU initialization & DisplayList loop
│ │ ├── vram.c # 2MB VRAM deterministic layout
│ │ ├── video2d.c # 2D Sprites & swizzled texture rendering
│ │ ├── video3d.c # 3D Meshes, matrices & 4 HW lights
│ │ ├── anim3d.c # Skeletal animation, SLERP & multi-chunk renderer
│ │ ├── input.c # Differential button & analog polling
│ │ ├── physics.c # 2D & 3D collision detection
│ │ ├── anim.c # 2D flipbook sprite animation
│ │ ├── scene.c # Multi-scene state machine
│ │ └── audio.c # Dedicated high-priority PCM audio thread
│ └── CMakeLists.txt
├── demos/ # Complete, ready-to-run showcase games
│ ├── demo_anim_2d/ # 2D animated knight with flipbook spritesheet
│ ├── demo_anim_3d/ # Floating rotating 3D gem with lighting
│ ├── demo_anim_3d_v2/ # 3D articulated humanoid rig with walk/jump/slash
│ ├── demo_anim_skeletal/ # 3D smooth skinned glTF character with 11 animation clips
│ ├── demo_scenes/ # Title Menu <-> Game state transitions
│ └── demo_collisions/ # AABB and Circle collision detection & audio
├── docs/ # Full documentation, tutorials, and API reference
└── tests/ # Python unit test suite
To build and use PSP-Forge, you need:
- Linux (x86_64 or ARM64) or macOS.
- PSPDEV Toolchain (
psp-gcc,psp-cmake,pspsdk, etc.) installed at/usr/local/pspdev. - Python 3.11+ with
Pillowinstalled (pip install Pillow). - CMake (v3.15+) and Make.
- PPSSPP (optional, recommended for instantaneous testing).
Add these lines to your shell profile (~/.bashrc or ~/.zshrc):
export PSPDEV=/usr/local/pspdev
export PATH=$PATH:$PSPDEV/binVerify your toolchain:
psp-config --pspsdk-pathCompile and install the C99 micro-engine directly into your PSPDEV system includes:
cd runtime
psp-cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
sudo cmake --install buildThis installs libpspforge.a in $PSPDEV/psp/lib/ and psp_forge.h in $PSPDEV/psp/include/.
Add bin/ to your PATH, or symlink the launcher:
sudo ln -sf $(pwd)/bin/psp-forge /usr/local/bin/psp-forgeSee docs/INSTALLATION.md for complete from-scratch toolchain installation steps.
Six complete, standalone showcase demos are provided in demos/. All demos feature 100% copyright-free procedural assets and run at a rock-solid 60 FPS on real PSP hardware and PPSSPP:
2D Animation (demo_anim_2d) |
3D Animation (demo_anim_3d) |
3D Humanoid V2 (demo_anim_3d_v2) |
|---|---|---|
![]() |
![]() |
![]() |
Scene Manager (demo_scenes) |
Collisions (demo_collisions) |
3D Skeletal Animation (demo_anim_skeletal) |
![]() |
![]() |
![]() |
| Demo | Directory | Key Techniques Demonstrated | Assets Included |
|---|---|---|---|
| 2D Animation | demos/demo_anim_2d/ |
60 FPS flipbook sprite animation via ForgeSpriteAnim, dynamic state switching (Walk/Idle) |
walker_sheet.png (4-frame |
| 3D Animation | demos/demo_anim_3d/ |
Floating crystal with sinusoidal bobbing ( |
gem.obj, gem.png, pedestal.obj, pedestal.png
|
| 3D Humanoid V2 | demos/demo_anim_3d_v2/ |
Articulated humanoid rig with pspgum matrix cascade, walk/run cycle, jump physics, sword slash, 360° orbiting camera |
knight_bot.png, arena.png, shadow.png, modular OBJ body parts |
| 3D Skeletal Anim | demos/demo_anim_skeletal/ |
Continuous vertex skinning, 11 .panm animation clips with crossfading, multi-chunk sub-mesh rendering ( |
character.glb, 11 cooked .panm clips, extracted texture |
| Scene Manager | demos/demo_scenes/ |
Clean Title Menu |
menu_banner.png, player.png, synthesized click.wav
|
| Collisions | demos/demo_collisions/ |
Solid AABB obstacles (rect_rect) and collectible coins (rect_circle) with audio chime |
box_player.png, coin_item.png, synthesized collect.wav
|
Run any demo in seconds:
cd demos/demo_anim_3d_v2
psp-forge build
psp-forge run- ⚙️ Installation & Environment Setup: Setting up PSPDEV, building the runtime, and configuring PPSSPP.
- 🛡️ 2D Game Tutorial: "Hero Starter": Complete guide to 2D sprites, controller edge detection, screen clamping, and audio.
- 🏎️ 3D Game Tutorial: "Track Runner": 3D meshes, UV texturing, perspective projection, camera physics, and gravity.
- 🏃 Tutorial: 2D Animation & Spritesheets: Using
ForgeSpriteAnimfor flipbook animations. - 💎 Tutorial: 3D Animation & Hierarchical Rigs: Mathematical transforms, floating oscillations, rotations, and articulated humanoid skeletons.
- 🎬 Tutorial: Scene Management (
ForgeScene): Designing multi-screen games while preventing RAM leaks. - 💥 Tutorial: Bounding Boxes & Collisions: Implementing 2D and 3D collision detection.
- 🎨 Asset Pipeline & Format Specification: Deep dive into swizzling, POT scaling,
.p3d,.snd, and hardware budgets. - 🕹️ C99 API Reference (
psp_forge.h): Comprehensive reference for all functions, structures, and callbacks.
Every PSP-Forge project compiles with the BUILD_PRX directive enabled, ensuring seamless operation on both PPSSPP and physical PSP hardware (tested and verified on Sony PSP-3004 running 6.61 PRO-C Custom Firmware):
- Pure User-Mode Linking: Links only against user-mode stubs (
libpspuser.a), avoiding*ForKernelreferences that trigger8002013Cor boot freezes on CFW. - Safe HOME/PS Button Teardown: Asynchronous exit callback sets
s_running = 0, allowing the main thread loop to cleanly shut down display lists, audio DMA, and release VRAM before callingsceKernelExitGame(). - FPU Trap Masking: Calls
pspFpuSetEnable(0)on startup to prevent Allegrex floating-point exceptions from crashing the hardware. - Dynamic RAM Sizing: Relies on Newlib's
_sbrk.cdynamic heap allocation, avoiding hardcodedPSP_HEAP_SIZE_KBallocation failures. - 16-Byte DMA Alignment: 16-byte alignment for display lists (
__attribute__((aligned(16)))), textures (memalign(16, size)), and mesh vertices to prevent GPU bus error lockups. - Non-Blocking Input: Uses
sceCtrlPeekBufferPositiveto guarantee zero frame-loop hitching.
Developing for real silicon requires respecting embedded hardware boundaries that high-end PC emulators mask:
-
Avoid Synchronous In-Game Disk Reads: The PSP Memory Stick PRO Duo bus throughput is
$3\text{--}7\text{ MB/s}$ with high seek latency. Loading or freeing heavy 3D assets/textures on button-presses (e.g. during rapid character selection) stalls the main thread. Always cache UI previews or preload models asynchronously during scene transitions. -
Skeletal Animation CPU Budget: The C99 runtime calculates forward kinematics (FK), quaternion SLERP, and matrix transforms on the MIPS R4000 CPU before dispatching bones to the GE hardware. While rigs up to 96 bones are structurally supported,
$24\text{--}32$ bones per rig is the recommended upper bound for steady 60 FPS gameplay with multiple active entities. -
Anime & Cel-Shaded Unlit Rendering: The GE applies Gouraud vertex lighting via
GU_TFX_MODULATE. For stylized or anime-style models without normal maps, disabling lights (sceGuDisable(GU_LIGHTING)withGU_TFX_REPLACE) avoids muddy dark shadows and preserves the 100% vibrant, original hand-painted texture colors at zero GPU arithmetic overhead. -
Texture Storage: Favor indexed textures (
clut8/clut4) or 16-bit textures (5551,5650) over heavy 32-bitRGBA8888for game assets to reduce bus bandwidth consumption and prevent VRAM allocation overflows.
- Connect your PSP via USB or insert your Memory Stick Duo into your computer.
- Copy the project folder containing
EBOOT.PBPand itsassets/directory to:ms0:/PSP/GAME/my_game/ ├── EBOOT.PBP └── assets/ ├── icon0.png ├── pic1.png └── [cooked .tex, .p3d, .snd files...] - Disconnect USB and launch your game from the PSP XMB under Game → Memory Stick!
Contributions from the homebrew community are welcome and encouraged! Whether you are an experienced embedded C hacker, a tool developer, an artist, or a game designer, there are many ways to get involved:
- New Asset Cookers: Add support for font atlas generation (
.fnt/TrueType), compressed tracker music (MOD, XM, IT vialibmodplug), or compressed textures. - Engine Capabilities: Implement particle systems, tilemap rendering engines, or VFPU-accelerated matrix transforms.
- Showcase Games & Templates: Submit new gameplay templates (e.g., Shmup, Platformer, RPG) or complete open-source demo games.
- Hardware Compatibility Testing: Test and report performance across different PSP models (PSP-1000, 2000, 3000, PSP Go, and PSP Street / E1000).
- Bug Reports & Improvements: Open an issue or submit a pull request on GitHub!
PSP-Forge stands on the shoulders of giants. We express our deepest appreciation to:
- The PSPDEV Organization & pspdev.github.io: For maintaining and preserving the modern open-source PSP development ecosystem, including
psptoolchain,psptoolchain-allegrex,pspsdk, andpsp-packages. - nem: For pioneering PSP homebrew with the original Hello World and reverse-engineering the foundational system call imports.
- The PSP Homebrew Community: Everyone on the PSP Homebrew Discord (
#psp-toolchain) whose passion keeps the PSP scene thriving decades after the console's release. - Henrik Rydgård & the PPSSPP Team: For creating the gold standard in PSP emulation, enabling rapid iteration and debugging.
- The Authors of Unofficial Hardware Documentation: Including the authors of Yet Another PSP Documentation (YAPSPD), the uofw team, and the Allegrex VFPU documentation maintainers.
psppspdevpspsdksony-pspplaystation-portablehomebrewgame-enginevibe-codingvibe-codedai-codingmipsallegrexc99retro-gaminggamedevasset-pipelinetexture-swizzlingedramppssppembedded-systemscmake
project: psp-forge
type: homebrew-game-development-suite-and-c99-micro-engine
target_hardware: Sony PlayStation Portable (MIPS Allegrex R4000 @ 333MHz, 24MB RAM, 2MB eDRAM)
programming_languages: [C99, Python 3.11, CMake]
architecture_features:
- Zero per-frame allocations with static 2MB VRAM layout (544K Draw, 544K Disp, 272K Depth, 688K Scratchpad)
- 16x8 block texture swizzling to prevent GE cache line stalls
- Power-of-two texture padding up to 512x512 with CLUT4/CLUT8 quantization
- Compact .p3d vertex streaming with precomputed AABB bounds
- High-priority 44.1kHz PCM audio thread with 512-sample stereo buffer
- Lightweight AABB, Sphere, Rect, and Circle collision detection
- Multi-scene lifecycle architecture (ForgeScene on_init, on_update, on_draw, on_destroy)
- 100% vibe-coded via human-directed AI pair programming
toolchain_dependencies: [pspdev, psp-gcc, psp-cmake, pspsdk, pspgu, pspgum]
license: MITPSP-Forge is distributed under the MIT License. Sony, PlayStation Portable, and PSP are registered trademarks of Sony Interactive Entertainment Inc. This project is an independent open-source tool and is not affiliated with or endorsed by Sony.





