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). -
Indexed 3D Mesh Optimization: OBJ cooker deduplicates shared vertices and generates 16-bit index buffers (
GU_INDEX_16BIT) for hardware vertex cache re-use and reduced vertex bus bandwidth. -
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. -
Tilemap Cooker (.ptm): Compiles Tiled
.tmxand.jsonmaps into binary.ptm(PSP Tilemap) format for rapid tile layer streaming. -
Bitmap Font Cooker (.fnt + .tex): Converts TrueType/OpenType (
.ttf/.otf) fonts into BMFont glyph descriptors and swizzled texture atlases. -
Audio Transcoder & Dual Streaming: Transcodes WAV/MP3 audio to signed 16-bit PCM at 44.1 kHz (
.snd), and supports streaming both raw PCM and compressed hardware MP3 via the PSP Media Engine processor. -
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.⚠️ Warns if cumulative active scene cooked assets exceed the safe 16 MB user RAM budget (24 MB total system 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 Multi-Quad Sprite Batching: Aggregates up to 256 textured quads per draw call (
forge_sprite_batch_begin,forge_sprite_batch_add,forge_sprite_batch_end) usingGU_SPRITESto dramatically minimize GPU display list dispatch overhead. -
2D Tilemap Subsystem: Direct rendering of orthogonal tile layers (
ForgeTilemap,forge_tilemap_load,forge_tilemap_draw) with hardware frustum clipping against the camera viewport. -
2D Particle System: High-efficiency, allocation-free particle simulation (
ForgeParticleSystem) supporting position, velocity, acceleration, size/alpha lerping, and lifetime management. -
Render-to-Texture (RTT): Hardware offscreen rendering into texture memory (
forge_rtt_begin,forge_rtt_end) for mini-maps, mirrors, dynamic impostors, and post-processing passes. -
3D Pipelines & Frustum Culling: Indexed vertex rendering (
GU_INDEX_16BIT), hierarchical node transforms, hardware alpha test control, 4 hardware directional/point lights, and CPU-side camera view frustum culling (forge_frustum_extract,forge_frustum_test_sphere) that automatically discards out-of-view meshes. -
VFPU SIMD Acceleration: Hardware vector matrix multiplication (
vmmul.q) on the Allegrex VFPU coprocessor accelerating bone hierarchy transforms, with automatic alignment checking. -
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 & Resource Tracker: Lifecycle state machine (
on_init,on_update,on_draw,on_destroy) featuring automatic VRAM scratchpad reset on scene transitions and a built-in resource tracker (forge_scene_register_*) for guaranteed leak-free garbage recycling. -
Dual Audio Engine (Raw PCM & Hardware MP3): Dedicated high-priority audio thread (
0x12) feeding 512-sample stereo PCM chunks from RAM buffers or streaming raw PCM / compressed MP3 directly through the Media Engine (sceMp3).
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 indexed .p3d parser + vertex deduplication
│ │ ├── gltf.py # glTF/GLB parser, .panm clips, sub-mesh chunker
│ │ ├── tilemap.py # Tiled .tmx/.json to binary .ptm tilemap cooker
│ │ ├── font.py # TrueType/BMFont to .fnt + .tex atlas cooker
│ │ └── audio.py # WAV/MP3 to PCM 44.1kHz transcoder (.snd)
│ └── 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 & RTT
│ │ ├── video2d.c # 2D Sprites, Sprite Batching, Particles & Tilemaps
│ │ ├── video3d.c # 3D Indexed Meshes, Frustum Culling & HW lights
│ │ ├── anim3d.c # Skeletal animation, VFPU SIMD transforms & SLERP
│ │ ├── input.c # Differential button & analog polling
│ │ ├── physics.c # 2D & 3D collision detection
│ │ ├── anim.c # 2D flipbook sprite animation
│ │ ├── scene.c # Multi-scene state machine & resource tracker
│ │ ├── font.c # Bitmap font glyph rendering
│ │ └── audio.c # Dedicated audio thread, PCM mixer & MP3 ME streaming
│ └── 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 & indexed mesh
│ ├── 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 & audio streaming
│ └── demo_collisions/ # AABB and Circle collision detection & audio
├── docs/ # Full documentation, tutorials, and API reference
└── tests/ # Test suites (Python unit tests & C ABI header harness)
├── c_tests/ # C header compilation & struct layout validation
├── test_cli.py # CLI project creation and workflow test suite
├── test_mesh_cooker.py # 3D mesh cooker and indexing tests
└── test_tilemap_cooker.py # Tilemap cooker tests
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 Hardware Acceleration: The C99 runtime calculates forward kinematics (FK) and bone matrix transforms hardware-accelerated by the Allegrex VFPU coprocessor (
vmmul.q), with normalized quaternion SLERP before dispatching skinning matrices 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 when multiple active skeletal entities share the scene. -
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, .mp3, .ptm 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 compressed tracker music (MOD, XM, IT via
libmodplug), compressed texture formats, or custom collision mesh generators. - Engine Capabilities: Implement 3D ragdoll physics, hierarchical scene graph nodes, or dynamic light maps.
- Showcase Games & Templates: Submit new gameplay templates (e.g., Shmup, Top-down RPG, Beat-'em-up, Platformer) 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-codingmipsallegrexvfpuc99retro-gaminggamedevasset-pipelinetexture-swizzlingtilemapparticle-systemmedia-engineedramppssppembedded-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
- Indexed 16-bit .p3d vertex streaming with precomputed AABB bounds and CPU frustum culling
- VFPU SIMD hardware-accelerated matrix multiplication (vmmul.q) for skeletal animation
- 2D multi-quad sprite batching (up to 256 quads per call) and orthogonal tilemap engine (.ptm)
- Allocation-free 2D particle simulation system with lifetime and alpha/scale lerping
- Offscreen Render-to-Texture (RTT) pipeline for mini-maps and dynamic impostors
- Dual audio engine: 44.1kHz raw PCM thread and hardware-decoded MP3 streaming via Media Engine
- Lightweight AABB, Sphere, Rect, and Circle collision detection
- Multi-scene lifecycle architecture (ForgeScene on_init, on_update, on_draw, on_destroy) with automatic VRAM reset & resource tracking
- 100% vibe-coded via human-directed AI pair programming
toolchain_dependencies: [pspdev, psp-gcc, psp-cmake, pspsdk, pspgu, pspgum, pspmp3, psputility]
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.





