Skip to main content

Create Your First Application

This guide will walk you through creating a simple “Hello World” application for PS3.
1

Create project directory

mkdir ~/ps3-hello-world
cd ~/ps3-hello-world
mkdir source
2

Create the source file

Create source/main.c with the following content:
source/main.c
#include <stdio.h>

int main()
{
    printf("hello, ps3\n");
    return 0;
}
By default, PSL1GHT redirects stdout and stderr to the lv2 TTY interface. You can use Kammy’s ethdebug module to view this output over the network.
3

Create the Makefile

Create a Makefile in the project root:
Makefile
# Name of your project, binary and package
# Default - guessed from current directory name
TARGET = hello-world

# Object files to link into your binary
OFILES = source/main.o

# Compiler flags
CFLAGS = -I$(PS3DEV)/ppu/include -std=gnu99

# Linker flags
LDFLAGS =

# Build directory for .pkg output
BUILDDIR = build

# Package metadata
TITLE = Hello World - PSL1GHT
APPID = HELLO0001

# Include PSL1GHT build rules
include $(PSL1GHT)/ppu_rules

# Build targets
pkg: $(TARGET).pkg

run:
    ps3load $(TARGET).self

clean:
    rm -rf $(TARGET)*.pkg $(TARGET)*.self $(BUILDDIR) source/*.o
Make sure $PSL1GHT is set in your environment. The build will fail with an error if this variable is not defined.
4

Build the application

Build the SELF executable:
make
This will:
  1. Compile source/main.c to source/main.o
  2. Link object files into hello-world.elf
  3. Strip and process the ELF to create hello-world.self
The .self file can be loaded directly on a jailbroken PS3.
5

Package for installation

Create a .pkg installer package:
make pkg
This creates:
  • hello-world.pkg - Standard package
  • hello-world.gnpdrm.pkg - Signed package for CFW
The package can be installed via the PS3’s Package Manager.

Understanding the Build Process

The PSL1GHT build system follows this workflow:

Build Stages

Source files are compiled to object files using ppu-gcc:
ppu-gcc -I$(PSL1GHT)/ppu/include -c source/main.c -o source/main.o
The PPU rules automatically include:
  • -mhard-float - Hardware floating point
  • -fmodulo-sched - Optimized scheduling
  • -ffunction-sections -fdata-sections - For dead code elimination
Object files are linked into an ELF executable:
ppu-gcc source/main.o -L$(PSL1GHT)/ppu/lib -llv2 -o hello-world.elf
Common libraries:
  • -llv2 - LV2 system calls
  • -lrt - Runtime support
  • -lio - I/O (pad, keyboard, mouse)
  • -lrsx - RSX graphics
  • -lgcm_sys - Graphics memory management
  • -lsysutil - System utilities
The ELF is processed into a SELF (signed executable):
ppu-strip hello-world.elf -o build/hello-world.elf
sprxlinker build/hello-world.elf
make_self build/hello-world.elf hello-world.self
  • Strip - Removes debug symbols
  • SPRX Linker - Resolves dynamic library references
  • make_self - Creates signed executable for CFW
The SELF is packaged for installation:
mkdir -p build/pkg/USRDIR
make_self_npdrm hello-world.elf build/pkg/USRDIR/EBOOT.BIN <CONTENTID>
sfo.py --title "Hello World" --appid "HELLO0001" build/pkg/PARAM.SFO
pkg.py --contentid <CONTENTID> build/pkg/ hello-world.pkg
package_finalize hello-world.gnpdrm.pkg
Package structure:
pkg/
├── PARAM.SFO    # Package metadata
├── ICON0.PNG    # XMB icon
└── USRDIR/
    └── EBOOT.BIN # Your application

A More Complex Example

Here’s a graphics example that displays colored rectangles using RSX:
#include <stdio.h>
#include <rsx/rsx.h>
#include <sysutil/video.h>
#include <io/pad.h>

int main()
{
    // Initialize video
    videoState state;
    videoConfiguration vconfig;
    
    videoGetState(0, 0, &state);
    videoGetResolution(state.displayMode.resolution, &vconfig);
    
    // Initialize RSX
    gcmContextData *context;
    void *host_addr = memalign(1024*1024, HOST_SIZE);
    rsxInit(&context, CB_SIZE, HOST_SIZE, host_addr);
    
    // Initialize controller
    ioPadInit(7);
    
    printf("PS3 Graphics Demo\n");
    printf("Resolution: %dx%d\n", vconfig.width, vconfig.height);
    printf("Press START to exit\n");
    
    // Main loop
    padData paddata;
    int running = 1;
    
    while(running) {
        ioPadGetData(0, &paddata);
        
        if(paddata.BTN_START) {
            running = 0;
        }
        
        // Draw frame
        rsxSetClearColor(context, 0x00406080);
        rsxClearSurface(context, GCM_CLEAR_R | GCM_CLEAR_G | 
                        GCM_CLEAR_B | GCM_CLEAR_A);
        
        flip(context);
    }
    
    ioPadEnd();
    return 0;
}

Package Metadata

Customize your application’s appearance in the XMB:
TITLE     = My Awesome Game
APPID     = GAME00042
CONTENTID = UP0001-$(APPID)_00-0000000000000000
The PKGFILES directory contents are copied to /dev_hdd0/game/$APPID/ on the PS3.

Running Your Application

Option 1: ps3load (Network Loading)

For rapid testing without creating packages:
make run
Requires ps3load homebrew running on your PS3.

Option 2: Install Package

  1. Copy the .gnpdrm.pkg file to a USB drive
  2. Insert the USB drive into your PS3
  3. Navigate to Package ManagerInstall Package Files
  4. Select your package and install
  5. Find your app under Game in the XMB

Common Build Issues

The $PSL1GHT environment variable is not set. Add to your shell profile:
export PSL1GHT=/usr/local/ps3dev/psl1ght
Then reload: source ~/.bashrc
You’re missing required libraries in the LIBS variable. Common libraries:
LIBS = -lrt -llv2 -lm                    # Basic runtime
LIBS = -lio -lsysutil -lrt -llv2         # I/O and system
LIBS = -lrsx -lgcm_sys -lsysutil -lrt -llv2  # Graphics
LIBS = -laudio -lrt -llv2                # Audio
Common causes:
  • Not calling ioPadInit() before using controller functions
  • Not initializing video/RSX before graphics calls
  • Stack overflow (try increasing stack size in linker flags)
  • Not registering exit callback for XMB quit events

Next Steps

Project Structure

Learn about the SDK layout and build system

API Reference

Explore available libraries and functions

Graphics Programming

Learn RSX graphics programming

Sample Code

Browse complete example applications

Build docs developers (and LLMs) love